• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Trigger] Custom Text & native functions

Status
Not open for further replies.
Level 4
Joined
Nov 23, 2007
Messages
113
Is there a way to expose the native functions (such as CreepsOnMap() etc) to be used in Custom Text triggers?

When ever I try to use them, I get an error that a name is expected so I'm assuming it is not accessible from within the trigger (but hoping there is a way to make them available).

Speaking of CreepsOnMap(), I'm just curious if there is a way to check if any live creeps are left on the map through standard triggers. Counting random creeps in group doesn't seem to work.

Regards
 
Level 4
Joined
Nov 23, 2007
Messages
113
Hi GostWolf,

I originally had this as a test trigger, but after the creeps all die no message is displayed. Not sure why that doesn't work.

  • Creeps all dead
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Number of units in (Units owned by Neutral Hostile)) Equal to 0
    • Actions
      • Game - Display to (All players) the text: All creeps dead!
 
Level 1
Joined
Dec 6, 2006
Messages
72
I don't know 100% if this will work

But you can try it..

I just freehanded it

JASS:
function GetCreepsOnMapBoolean takes nothing returns boolean
    return IsUnitOwnedByPlayer(GetFilterUnit(),Player(PLAYER_NEUTRAL_AGGRESSIVE))
endfunction 

function GetCreepsOnMap takes group a returns group
    local group g=CreateGroup()
    local boolexpr b=Condition(function GetCreepsOnMapBoolean)
    call GroupEnumUnitsInRect(g,GetPlayableMapRect(),b)
    set g=a
    call DestroyGroup(g)
    set g=null
    return a
endfunction

Just use GetCreepsOnMap(GROUP HERE)

The only possibility I can see of it not working is that the a will return null because the g is destroyed and nulled...but it shouldn't because I set g equal to a

If it doesn't work tell me i will just make a better one

_____________

@Mannoroth

that is because dead units (ones being decayed) count as units in the map
 
Level 4
Joined
Nov 23, 2007
Messages
113
Thanks Hero,
Perhaps I'm calling it incorrectly or something. Nothing seems to happen when all the creeps die :/

Here's my trigger using your code.

JASS:
function GetCreepsOnMapBoolean takes nothing returns boolean
    return IsUnitOwnedByPlayer(GetFilterUnit(),Player(PLAYER_NEUTRAL_AGGRESSIVE))
endfunction

function GetCreepsOnMap takes group a returns group
    local group g=CreateGroup()
    local boolexpr b=Condition(function GetCreepsOnMapBoolean)
    call GroupEnumUnitsInRect(g,GetPlayableMapRect(),b)
    set g=a
    call DestroyGroup(g)
    set g=null
    return a
endfunction


function Trig_Creeps_all_dead_Conditions takes nothing returns boolean
   if ( GetCreepsOnMap( udg_CreepsGroup ) != null ) then
      return false
   endif

   return true
endfunction

function Trig_Creeps_all_dead_Actions takes nothing returns nothing
    call DisplayTextToForce( GetPlayersAll(), "TRIGSTR_010" )
endfunction

//===========================================================================
function InitTrig_Creeps_all_dead takes nothing returns nothing
    set gg_trg_Creeps_all_dead = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Creeps_all_dead, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddCondition( gg_trg_Creeps_all_dead, Condition( function Trig_Creeps_all_dead_Conditions ) )
    call TriggerAddAction( gg_trg_Creeps_all_dead, function Trig_Creeps_all_dead_Actions )
endfunction
.

Edit: And if I try to use if (udg_CreepsGroup != null ) comparison, it says expecting a 'set'



Edit 2:
I still would like to know how to do the above for knowledge sake but what I'm really trying to do is this: I have created an AI using the AI editor and have unchecked the Melee AI option on the main page because I don't want the AI team helping each other creep.

However, when all the creeps are dead, I want them to come to each other's aid if they are attacked by human players (and with the Malee AI turned off, they don't - no teleport or anything - they just sit there and let their ally die).

So I was hoping to be able to set the Melee AI on after all creeps are dead, and if I can't do that, try to write a trigger that would tell the computer to go help its ally if under attack (prefer the former).
 
Last edited:
Level 1
Joined
Dec 6, 2006
Messages
72
Try this:

Without JASS Tags (The One you copy)

function GetCreepsOnMapBoolean takes nothing returns boolean
return IsUnitOwnedByPlayer(GetFilterUnit(),Player(PLAYER_NEUTRAL_AGGRESSIVE))
endfunction

function GetCreepsOnMap takes group a returns group
local group g=CreateGroup()
local boolexpr b=Condition(function GetCreepsOnMapBoolean)
call GroupEnumUnitsInRect(g,GetPlayableMapRect(),b)
set g=a
call DestroyGroup(g)
set g=null
return a
endfunction

function Trig_Creeps_all_dead_Actions takes nothing returns nothing
local group b=CreateGroup()
set b=GetCreepsOnMap(b)
if CountUnitsInGroup(b)<=0 then
call DisplayTextToForce( GetPlayersAll(), "All Creeps Dead" )
endif
call DestroyGroup(b)
set b=null
endfunction

//===========================================================================
function InitTrig_Creeps_all_dead takes nothing returns nothing
set gg_trg_Creeps_all_dead = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_Creeps_all_dead, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddAction( gg_trg_Creeps_all_dead, function Trig_Creeps_all_dead_Actions )
endfunction

With Jass Tags (Just to see)

JASS:
function GetCreepsOnMapBoolean takes nothing returns boolean  
    return IsUnitOwnedByPlayer(GetFilterUnit(),Player(PLAYER_NEUTRAL_AGGRESSIVE)) 
endfunction 

function GetCreepsOnMap takes group a returns group  
    local group g=CreateGroup()  
    local boolexpr b=Condition(function GetCreepsOnMapBoolean)  
    call GroupEnumUnitsInRect(g,GetPlayableMapRect(),b)  
    set g=a 
    call DestroyGroup(g)  
    set g=null  
    return a 
endfunction 

function Trig_Creeps_all_dead_Actions takes nothing returns nothing  
    local group b=CreateGroup()
    set b=GetCreepsOnMap(b)
if CountUnitsInGroup(b)<=0 then
    call DisplayTextToForce( GetPlayersAll(), "All Creeps Dead" ) 
endif
    call DestroyGroup(b)
    set b=null
endfunction 
    
//=========================================================================== 
function InitTrig_Creeps_all_dead takes nothing returns nothing  
    set gg_trg_Creeps_all_dead = CreateTrigger( ) 
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Creeps_all_dead, EVENT_PLAYER_UNIT_DEATH )   
    call TriggerAddAction( gg_trg_Creeps_all_dead, function Trig_Creeps_all_dead_Actions ) 
endfunction
 
Level 11
Joined
Aug 25, 2006
Messages
971
I'd like to remind you guys of the following.
These are all quotes directly out of the sticky in this section
DO NOT POST ANYTHING NON TRIGGER/SCRIPT RELATED IN THIS SECTION!

JASS policy
Since this section is for GUI triggers only, any discussion involving the coding or how to do anything in JASS is discouraged. The use of "JASS" tags is prohibited: there is no need to use them. As a poster, you can advise people to learn JASS BUT you must give a reason why they should. As a thread creator, you can request that the thread be moved to the JASS section via the use of a post or a PM if the request is not fulfilled in 2 days.​

Custom Script action policy
Since it is a valid GUI action, it is fine to use it as long as. . .
  • Over 50% of the trigger is standard GUI actions.
  • The custom script has no GUI equivalent action.
  • The custom script is described so users know what it does ("why did you need to use it?").
You are not allowed to use it for the following. . .
  • To make new functions in GUI via use of endfunction / function.
  • To make a pure JASS triggers in GUI.
  • To make locals usable in GUI.
  • To make WE crash to spite a person.
  • To call custom functions


I hope you get the point!​
 
Level 4
Joined
Nov 23, 2007
Messages
113
wd40bomber7,
I was going to post this in the JASS scripting section, however, my fear was it would be moved or deleted since this is about triggers using custom text in the GUI, thus I assumed this to be the appropriate (if not safest) forum. JASS is a part of the GUI when using custom text, so I'm not sure if there is a way around that (hence catch 22).

If a mod considers this thread to be unrelated to the aforementioned and wishes to move it, please do.
 
Level 11
Joined
Aug 25, 2006
Messages
971
Just to add something, the function that is used to determine if all creeps are dead has a bug. It just checks that neutral hostile owns no units. It should check that all the units neutral hostile owns are dead. Otherwise it will include decaying units and it'll think neutral hostile still has some units.

About the rules. Your question was a bit iffy. It could have gone either way. However the way it did go is complete and total JASS, but hey, I'm not a mod, its their call.
 
Level 11
Joined
Aug 25, 2006
Messages
971
JASS:
function GetCreepsOnMapBoolean takes nothing returns boolean  
    return IsUnitOwnedByPlayer(GetFilterUnit(),Player(PLAYER_NEUTRAL_AGGRESSIVE)) and not IsUnitType(GetFilterUnit(), UNIT_TYPE_DEAD) 
endfunction 

function GetCreepsOnMap takes group a returns group  
    local group g=CreateGroup()  
    local boolexpr b=Condition(function GetCreepsOnMapBoolean)  
    call GroupEnumUnitsInRect(g,GetPlayableMapRect(),b)  
    set g=a 
    call DestroyGroup(g)  
    set g=null  
    return a 
endfunction 

function Trig_Creeps_all_dead_Actions takes nothing returns nothing  
    local group b=CreateGroup()
    set b=GetCreepsOnMap(b)
if CountUnitsInGroup(b)<=0 then
    call DisplayTextToForce( GetPlayersAll(), "All Creeps Dead" ) 
endif
    call DestroyGroup(b)
    set b=null
endfunction 
    
//=========================================================================== 
function InitTrig_Creeps_all_dead takes nothing returns nothing  
    set gg_trg_Creeps_all_dead = CreateTrigger( ) 
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Creeps_all_dead, EVENT_PLAYER_UNIT_DEATH )   
    call TriggerAddAction( gg_trg_Creeps_all_dead, function Trig_Creeps_all_dead_Actions ) 
endfunction
the modification being in the function 'GetCreepsOnMapBoolean.' (Scroll to the right or you can't see the additional code.)
 
Level 20
Joined
Apr 22, 2007
Messages
1,960
Whoa, this code is flawed. Lemme fix it:
JASS:
function GetCreepsOnMapBoolean takes nothing returns boolean
    return GetWidgetLife(GetFilterUnit())>0.405
endfunction
function Trig_Creeps_all_dead_Actions takes nothing returns nothing
    local group b=CreateGroup()
    call GroupEnumUnitsOfPlayer(b,Player(PLAYER_NEUTRAL_AGGRESSIVE),Filter(function GetCreepsOnMapBoolean))
    if FirstOfGroup(b)==null then
        call DisplayTextToForce( bj_FORCE_ALL_PLAYERS, "All Creeps Dead" )
    endif
    call DestroyGroup(b)
    set b=null
endfunction
//===========================================================================
function InitTrig_Creeps_all_dead takes nothing returns nothing
    set gg_trg_Creeps_all_dead = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Creeps_all_dead, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddAction( gg_trg_Creeps_all_dead, function Trig_Creeps_all_dead_Actions )
endfunction

That should work nicely.
 
Level 4
Joined
Nov 23, 2007
Messages
113
hmm... wd40bomber7, that looked good at first glance but everytime a creep dies, it displays the message "All Creeps Dead".

Too bad that the native function CreepsOnMap can't be accessed in triggers because it works good in ai scripts.

Isn't there some way to import it? Like with some sort of external reference (ie. extern function CreepsOnMap() like in C++) ?
 
Level 11
Joined
Aug 25, 2006
Messages
971
His fix should work, I'm sorry I didn't catch that. When I saw the code I was thinking *isn't there a faster method of getting a players units* but I didn't act on it, sorry about that. He modified it by instead of checking if the unit is dead by checking it has less then .405 hp. I don't know why he did that, but hey it works. He also rearranged parts of the code. I didn't have time to check it over, sorry about that.
 
Level 4
Joined
Nov 23, 2007
Messages
113
HINDYhat,

BINGO! THat's the one :)

All I have to add to that is to turn the trigger off after all the creeps are dead (once a global var is set).

Just out of curiosity, is there any way to accomplish that in pure trigger form? Without custom text?


Another problem I'm having (since I have your experience attention :D ) is there a way to set Melee type AI on (it's initially off since I don't want them helping each other creep) after the creeps have died so that the computer allies will then start going to each other's aid?

Or is there a way in triggers to tell them to teleport/move to the allies base to defend it?


Edit: wd40bomber7, no problem. I appreciate the help. It's all good :^

Edit2: HINDYhat, would you mind elaborating on the GetWidgetLife(GetFilterUnit())>0.405 statement? It seems rather mysterious ;)
 
Level 11
Joined
Aug 25, 2006
Messages
971
A widget is: A unit/destructable/item
GetWidgetLife will tell you what life that widget is at.
That statement returns true for any unit with more then .405 hp. I guess that anything with less than .405 hp is dead. I don't know why he doesn't check whether or not the unit is dead. Maybe its faster to check hp?
 
Level 20
Joined
Apr 22, 2007
Messages
1,960
Well, GetWidgetLife has been proven faster than GetUnitState, and as far as I know, IsUnitType is unstable (in some cases, not sure when). So, I decided to use GetWidgetLife with the life > 0.405, because units actually die at 0.405 life, and then their life is set to 0. So this is the most precise way of detecting all dead units.

You can do this is 'trigger' form. Just paste that code inside a trigger called "Creeps all dead" (case sensitive). If you meant in GUI, yes it's very possible, but alot less efficient and more complicated, when you could use this efficient and simple code :D
 
Level 4
Joined
Nov 23, 2007
Messages
113
Very slick ;)
Thanks for all the info. Very helpful.

Yes, I mean pure GUI trigger form. It was more a curiosity than anything because I had tried for hours to attempt it in pure GUI and couldn't figure it out (so it's still under my skin that a solution must exist in the GUI :D)

Now if I can only get the AI I've done in the AI Editor to help his ally when all the creeps are dead, I'm all set :D


PS - This "reputuation" thing... is unfortunately not on a post-by-post basis. When it's often the same group of people jumping in to give advice, you can't "award" them for it without "spreading rep around to other people first" :/
 
Level 4
Joined
Nov 23, 2007
Messages
113
Well, I'm sure it would be much easier in an ai file (which is what I'm using now to get away from the restrictions (but don't know the appropriate functions yet to accomplish my goal)) but I'm also determined to see what can be accomplished in the interface provided. Just one of those things you look at and think "hmmm... what are the possibilities? What are the limitations? etc" ^_^
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Just from curiosity, couldn't you just do this ?

  • Unknown
    • Events
      • Unit - A unit owned by Neutral Hostile Dies
    • Conditions
    • Actions
      • Set Integar = (Integar - 1)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Integar Equal to 0
        • Then - Actions
          • Actions
        • Else - Actions
 
Level 4
Joined
Nov 23, 2007
Messages
113
Interesting idea GhostWolf, because it does seem superfluous to enumerate each creep every time a unit dies.

However, I would think with creeps that spawn skeletons etc may cause an inaccurate count. In fact, on my test map I've been using Balnazzar as a creep in one center place on the map so I imagine if he spawns 3 infernals (which exist for like 7 mins) that would put the tracking variable count out of whack (unless I also kept track of spawned creep units - ugh!).

Consequently, I think enumerating them on the fly will provide the most accurate count.

My problem with getting the computer to help its computer ally (either TP to his base or move there to his location to help) seems to be exponentially more complex using the GUI triggers than simply writing the code in JASS (although unit references such as Triggering Unit I haven't figured out yet). But even though it seems like a lot more work, I'd like to get it working in GUI triggers just because that is the environment I am trying to evaluate.
 
Level 4
Joined
Nov 23, 2007
Messages
113
Yeah, but like I said above, I'm not sure I really want to start keeping track of all creeps and summoned units using default conditions due to the aforementioned 'bug'. I think given what HINDYhat has said it makes me wonder if the standard function would encounter the same issue with spawned creeps as it does with existing creeps (and thus still have to use his method of detection).

I like the concept of what you're getting at, but given the way the default trigger function returns the number of living units, getting a starting count at map initialization seems the only trusted value I would get. Anything after that might be skewed.

I appreciate the input though :)
 
Level 4
Joined
Nov 23, 2007
Messages
113
I think I may have found an easy way to do this (seems to work in initial testing). I've only used static references to the computer players so at some point I'd have to determine if it's a computer player in general and cross-reference the computer allies.

  • Help Ally
    • Events
      • Unit - A unit owned by Player 3 (Teal) Is attacked
      • Unit - A unit owned by Player 4 (Purple) Is attacked
    • Conditions
      • ((Triggering unit) is A structure) Equal to True
    • Actions
      • Player Group - Make Player Group - Player 4 (Purple) treat Player Group - Player 3 (Teal) as an Ally with shared vision and full shared units
      • Player Group - Make Player Group - Player 3 (Teal) treat Player Group - Player 4 (Purple) as an Ally with shared vision and full shared units
      • Trigger - Turn off (This trigger)

Initially, with Melee AI off, they don't help each other but once the creeps all die I enable this trigger and they (at least once) teleported to assist. If you can think of any negative side effects of doing it this way, please feel free to comment.
 
Status
Not open for further replies.
Top