[JASS] Rematch Trigger

Level 4
Joined
Sep 18, 2007
Messages
104
I haven't touched WC3 in a while but decided to give it a whirl after some friends got back on. I decided to dust off an old project (make it compatible with 1.24+). When I was working on this project I knew a little bit of JASS, but now not so much. I also decided to make a Rematch function because the map is such a short battle and I thought it would be a be a good way to get back into scripting. I also decided to try to make this trigger easily transferrable to other maps.

The type of maps that this trigger is intended for is the basic "Two Armies facing each other; you win by killing their commander type."

This is the first idea I had when I thought of how to go about this, but I realize it probably is quite inefficient and full of leaks.

I used arrays to save information about the unit (position, type, owner) and the code is mostly commented to tell what is supposed to happen (and random comments to myself). Here is the code:

JASS:
library Rematch initializer init requires UnitRecycler
globals
    constant integer LeaderType1 = 'H000' //Unit Type Id for Leader 1 (Cao Cao)
    constant integer LeaderType2 = 'H007' //Unit Type Id for Leader 2 (Ma Chao)
    
    real array UnitX
    real array UnitY
    real array UnitF
    integer array GameId //Type of unit
    integer array UnitOwner
    
    integer loopsave = 0 //used later on for creating units
    integer loopnum = 0 //will become how many intial units there are
    constant integer time = 10 //time between units being created (EX:) Player 1 Units, Wait 10 sec, Player 2 Units
    constant boolean SwitchSides = true //work this in
    group iGroup = CreateGroup() //group that initial units are added to (or maybe just hereos)
endglobals
//---
function HeroIndex takes nothing returns boolean
    return IsUnitType(GetEnumUnit(), UNIT_TYPE_HERO)
endfunction

function RematchIndex takes nothing returns nothing //does not index heroes
    call GroupAddGroup(GetUnitsInRectAll(bj_mapInitialPlayableArea), iGroup)
    loop
    exitwhen loopnum > CountUnitsInGroup(iGroup)
        set UnitX[loopnum] = GetUnitX(GetEnumUnit())
        set UnitY[loopnum] = GetUnitY(GetEnumUnit())
        set UnitF[loopnum] = GetUnitFacing(GetEnumUnit())
        set GameId[loopnum] = S2I(GetUnitName(GetEnumUnit()))
        set UnitOwner[loopnum] = GetPlayerId(GetOwningPlayer(GetEnumUnit()))
        set loopnum = loopnum + 1
    endloop
endfunction

private function init takes nothing returns nothing
    local trigger Rematch = CreateTrigger()
    call TriggerRegisterTimerEvent(Rematch, 0.1, false)
    call TriggerAddAction( Rematch, function RematchIndex)
    set Rematch = null
endfunction
//---

function RematchActions takes nothing returns nothing
    //Create the units
    local integer i = loopsave
    loop
        exitwhen loopsave > loopsave + 30 //only 30 units will be created at one time
        exitwhen loopsave > loopnum
        call CreateUnitEx(Player(UnitOwner[i]), GameId[i], UnitX[i], UnitY[i], UnitF[i])
        set loopsave = loopsave + 1
        set i = i+1
    endloop
    set i = 0
    if (loopsave > loopnum) then //check to see if all units have been created
        set loopsave = 0
    endif
endfunction

function RematchTimeOut takes nothing returns nothing //change so maybe wait is outside loop
    //Wait between players getting their units created
    loop
        exitwhen loopsave > loopnum
        call RematchActions()
        call TriggerSleepAction(time)
    endloop
endfunction

function RecycleActions takes nothing returns nothing
    call RemoveUnitEx(GetEnumUnit())
endfunction

function RecycleSetUp takes nothing returns nothing
    //Recycle All Units in map
    call ForGroupBJ(GetUnitsInRectAll(bj_mapInitialPlayableArea), function RecycleActions)
    call RematchActions()
endfunction

function LeaderCheck takes nothing returns nothing
    local integer uId = GetUnitTypeId(GetDyingUnit())
    if uId == LeaderType1 or uId == LeaderType2 then
        call RecycleSetUp()
    endif
endfunction

//===========================================================================
function InitTrig_Rematch_Lib takes nothing returns nothing
    local trigger Rematch = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( Rematch, EVENT_PLAYER_UNIT_DEATH )
    call TriggerAddAction( Rematch, function LeaderCheck )
    //set Rematch = null
endfunction

endlibrary

I combined 2 trigs into one (I was working on two different ways of trying this, but decided to ditch one of them but wanted some of the code for the one you see now.

Now for the actual problems: I get most of the units "indexed", just not the heroes (as far as I know). When one of the commanders die, the Recycling kicks in and all normal units are "removed from the map" (again, not heroes), but the units don't ever get created. The map has about 320 units (and it is considered small for this type of map) so I didn't want to create all 320 at once for fear of lag. I decided that incrementing in 30 unit groups or so would be the best bet. The "time" variable dictates how much time is elapsed before each interval of unit creation. The boolean variable is whether or not the map maker wants teams to "switch sides", but I haven't written the code for that yet.

As I said earlier I am rusty (and really never good to begin with) and I know this code is inefficient and leaky (I will wory about the leaks after I get it actually working). I am sure there are still some things I forgot to explain so just ask (uses moyack's Unit Recycler Library). Thanks in advance.
 
Level 29
Joined
Oct 24, 2012
Messages
6,549
im new to this so im not the best at this but i do have a few things tht i saw tht might help u if they cant solve ur problem mybe the can make it a little more efficient and hopefully someone can help u umm first major thing i noticed

JASS:
  exitwhen loopsave > loopsave + 30 //only 30 units will be created at one time

i would take tht line out of there it might be crashing the loop because tht condition can never be met (when u do loopsave = loopsave + 1 like at the end of ur loop its changing the variable so say its 1 to start itll be like this (1>1+30)
but when u add like at the end of the loop itll be (2>2+30) so it will never end
i would change it to this

JASS:
  exitwhen loopsave > 30 //only 30 units will be created at one time
and take out the line below it tht says exitwhen

other thing is the call triggersleep action change tht to a polledwait (its faster and i believe less bugged up ( i may be wrong about less bugs tho))

the unit facing variable u have i would just get rid of tht and make them face 0 every time but tht is preference i guess

to set loopsave back to 0 just when u create loopsave do integer loopsave = 0 tht way whenever the trigger fires it will hit 0 so the loop after the unit spawn is not needed

ok for the last ( i believe its the last ) thing i would change

JASS:
function RematchTimeOut takes nothing returns nothing //change so maybe wait is outside loop
    //Wait between players getting their units created
    loop
        exitwhen loopsave > loopnum
        call RematchActions()
        call TriggerSleepAction(time)
    endloop
endfunction

i would get rid of tht and just change the event time for the whole trigger to a periodic time and just create a condition tht says units on map = 330 then set true and let the condition only run the trigger if its true ( this way will let the trigger run as soon as the units on map get below 330 so there will always be over 330 units )

i hope this helped if u need any more debugging u could always try to generate messages for urself in the code so u can see wat is working and wat isnt working and gl
 
Top