• 🏆 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!

[JASS] Again some incredibly simple but apparently invisible fault

Status
Not open for further replies.
Level 5
Joined
May 22, 2006
Messages
150
This is a code to cast an arrow spell automatically on friendly units.

There are two informations about it, which are important...

The good one: It works.

The bad one: There are two preplaced units, who are able to cast the spell...
It works with the first...
It works with the second...
But it does not work with both at once!

If I activate auto-cast for both units, they never cast at the same time, even if they could
(and when my debug messages say they should)!

I would really like to change that.
Any hints are welcome. ~~

JASS:
globals
integer udg_Cast_RecoverTimer_Order = -1
player array udg_Player
timer array udg_Cast_RecoverTime
trigger udg_CastAutomatical
endglobals

header script:
JASS:
//=================
// Filter - dryads
//=================

function Unitfilter_Dryad takes nothing returns boolean
  return GetUnitTypeId(GetFilterUnit()) == 'edry' and GetUnitUserData(GetFilterUnit()) == 0
endfunction

//===========================
// Filter - keeperOfTheGrove
//===========================

function Unitfilter_KeeperOfTheGrove takes nothing returns boolean
  return GetFilterUnit() == gg_unit_Ekee_0040 or GetFilterUnit() == gg_unit_Ekee_0041
endfunction

//==============================
// Trigger - CastAutomatical
//==============================

function Trig_CastAutomatical_Actions takes nothing returns nothing
  local filterfunc dryads
  local group validTargets
  local timer recoverTime
  local unit lastTarget = null
  local unit triggerUnit
  if GetIssuedOrderId() == OrderId("flamingarrows") then
    call BJDebugMsg("Automatical cast activated.")
    set triggerUnit = GetTriggerUnit()
    if triggerUnit == gg_unit_Ekee_0040 then
      call BJDebugMsg("Order to keeper one.")
    else
      call BJDebugMsg("Order to keeper two.")
    endif
    set dryads = Filter(function Unitfilter_Dryad)
    set validTargets = CreateGroup()
    if udg_Cast_RecoverTime[0] == null then
      call BJDebugMsg("Use of timer one.")
      set udg_Cast_RecoverTime[0] = CreateTimer()
      set recoverTime = udg_Cast_RecoverTime[0]
      if triggerUnit == gg_unit_Ekee_0040 then
        set udg_Cast_RecoverTime_Order = 0
      else
        set udg_Cast_RecoverTime_Order = 1
      endif
    else
      call BJDebugMsg("Use of timer two.")
      set udg_Cast_RecoverTime[1] = CreateTimer()
      set recoverTime = udg_Cast_RecoverTime[1]
    endif
    call BJDebugMsg("Aquiring Targets...")
    loop
      exitwhen recoverTime != udg_Cast_RecoverTime[0] and recoverTime != udg_Cast_RecoverTime[1]
      call BJDebugMsg("Target group created.")
      call GroupEnumUnitsInRange(validTargets,GetUnitX(triggerUnit),GetUnitY(triggerUnit),1024,dryads)
      loop
        call ForGroup(validTargets,function GroupPickRandomUnitEnum)
        exitwhen lastTarget != bj_groupRandomCurrentPick
      endloop
      set lastTarget = bj_groupRandomCurrentPick
      if lastTarget != null then
        call BJDebugMsg("Target aquired.")
        call IssueTargetOrder(triggerUnit,"flamingarrowstarg",lastTarget)
        call TimerStart(recoverTime,8,false,null)
        loop
          call TriggerSleepAction(0.01)
          exitwhen TimerGetRemaining(recoverTime) <= 0 or (recoverTime != udg_Paarung_Erholung[0] and recoverTime != udg_Paarung_Erholung[1])
        endloop
      else
        call BJDebugMsg("No Target.")
        call TriggerSleepAction(0.01)
      endif
      call BJDebugMsg("Target group reseted.")
      call GroupClear(validTargets)
      exitwhen recoverTime != udg_Cast_RecoverTime[0] and recoverTime != udg_Cast_RecoverTime[1]
    endloop
    call DestroyFilter(dryads)
    call DestroyGroup(validTargets)
    call BJDebugMsg("Deactivation completed.")
    set dryads = null
    set validTargets = null
    set recoverTime = null
    set lastTarget = null
    set triggerUnit = null
  elseif GetIssuedOrderId() == OrderId("unflamingarrows") then
    call BJDebugMsg("Automatical cast deactivated.")
    if (udg_Cast_RecoverTime[0] != null and udg_Cast_RecoverTime[1] == null) or (udg_Cast_RecoverTime_Order == 0 and GetTriggerUnit() == gg_unit_Ekee_0040) or (udg_Cast_RecoverTime_Order == 1 and GetTriggerUnit() == gg_unit_Ekee_0041) then
      call DestroyTimer(udg_Cast_RecoverTime[0])
      set udg_Cast_RecoverTime[0] = null
    else
      call DestroyTimer(udg_Cast_RecoverTime[1])
      set udg_Cast_RecoverTime[1] = null
    endif
    set udg_Cast_RecoverTime_Order = -1
  endif
endfunction

Trigger "Initialisation":
JASS:
function Trig_Initialisation_Actions takes nothing returns nothing

//===========
// Variables
//===========

  local filterfunc keeperOfTheGrove = Filter(function Unitfilter_KeeperOfTheGrove)
  call DestroyTimer(udg_Cast_RecoverTime[0])
  call DestroyTimer(udg_Cast_RecoverTime[1])
  set udg_Cast_RecoverTime[0] = null
  set udg_Cast_RecoverTime[1] = null
  set udg_Player[0] = Player(0)
  set udg_Player[1] = Player(1)
  set udg_Player[2] = Player(10)
  set udg_Player[3] = Player(12)
  set udg_Player[4] = Player(15)

//==========
// Auslöser
//==========

  set udg_CastAutomatical = CreateTrigger()

  call TriggerRegisterPlayerUnitEvent(udg_CastAutomatical,udg_Player[2],EVENT_PLAYER_UNIT_ISSUED_ORDER,keeperOfTheGrove)
  call TriggerAddAction(udg_CastAutomatical,function Trig_CastAutomatical_Actions)

  set keeperOfTheGrove = null
  call DestroyTrigger(gg_trg_Initialisation)
endfunction

function InitTrig_Initialisation takes nothing returns nothing
  set gg_trg_Initialisation = CreateTrigger()
  call TriggerAddAction(gg_trg_Initialisation,function Trig_Initialisation_Actions)
endfunction
 
Level 5
Joined
Feb 16, 2006
Messages
151
Do you hate GameCache that much, for you to be using a global timer array o_o;...?
There are rumours arround saying that GameCache is bugged, but no one ever proved it.
So, of course it does not work, you only have the one and only global timer from the array...after automatic-firing twice, the second one simply overwrote the global variable, thus, disabled the first "cast".
 
Level 5
Joined
May 22, 2006
Messages
150
Öh... udg_Cast_Recover[0] and udg_Cast_Recover[1] are totally different variables except for their name.

And yes, debug messages say, that not one of them is used twice.

Also I can see two separate loops (by periodic activation of messages). It seems not to be this fault.

...

But it seems to have something to do with the timers, that's right...

This line is separately executed (as it should be)
JASS:
call BJDebugMsg("Target aquired.")
The next line is only executed if
- the other timer is not yet started,
- the other timer has expired.
JASS:
call IssueTargetOrder(triggerUnit,"flamingarrowstarg",lastTarget)

As one line is next to the other with no conditionals between, that is quite irritating...
 
Level 5
Joined
May 22, 2006
Messages
150
Your hint was right. ~~

"ForGroup" is buggy.
The next action will be done before the function called this way.
So "bj_groupRandomCurrentPick" will allways be the same for the first and second keeper. ~~
I eliminated this locally by using a loop but forgot that "lastTarget" whould be different for both keepers.
Replacing it with a global solves the problem.

And as the loop still aquires time to be executed, the problem of one keeper aiming the same target more than one time is still solved. ^^
 
Status
Not open for further replies.
Top