- Joined
- Feb 27, 2019
- Messages
- 404
Hello,
You may know the following abilities:
- Orb of Slow
- Orb of Lightning
- Attack black arrow bonus
- Melee Lightning Damage Bonus
They are similar, and allow you to make normal attacks have a chance of casting any ability with a target. However they have a known weird issue in which, you didn't ordered the owner of the ability to do something, and even if you have put the chance to do the ability to 100%, it will never fire.
So I have been working on a "work-around" fix for this matter. After hours and hours of experimenting and programming, I got a detailed analysis and a custom fix that works !! It is MUI and I tested it OK with all the cases I thought of (patrol, hold position, attack, smart, move, guard-position consistence...)
Detailed analysis:
How to use:
When you create a unit with the bugged ability, or when a unit learns the bugged ability, just call RegisterUnitForOosFix(<unit>). My code handles the rest (target aquisition, improper orders handle, unit death...).
Triggers:
OosFix RegisterUnit (JASS API function)
OosFix UnitIssuedOrder (GUI)
OosFix UnitTargetAcquisition (GUI)
OosFix HoldPositionResume (GUI)
You may know the following abilities:
- Orb of Slow
- Orb of Lightning
- Attack black arrow bonus
- Melee Lightning Damage Bonus
They are similar, and allow you to make normal attacks have a chance of casting any ability with a target. However they have a known weird issue in which, you didn't ordered the owner of the ability to do something, and even if you have put the chance to do the ability to 100%, it will never fire.
So I have been working on a "work-around" fix for this matter. After hours and hours of experimenting and programming, I got a detailed analysis and a custom fix that works !! It is MUI and I tested it OK with all the cases I thought of (patrol, hold position, attack, smart, move, guard-position consistence...)
Detailed analysis:
First impressions
The ability only casts when players manually gave one of the following orders:
- Order targeting an object (unit): smart (right-click), attack
- Order targeting a point (any point, but order must not be over): attack ground, attack-move, patrol
Test cases (logging last order issued & current order)
OK - Unit is on patrol, and engages a target: lastevent=patrol, currentorder=_
OK - Unit is still doing an attack position order: lastevent=attack, currentorder=attack
OK - Unit is attacking an unit because of an attack or smart order: lastevent=attack/smart, currentorder=attacks/mart (both are identical)
KO - Unit is holding position: lastevent=holdposition, currentorder=_
KO - Unit aquires a new target, and was stopped before: lastevent=stop, current=_
KO - Unit aquires a new target, and last order was irrelevant (learn skill, use skill, etc...): lastevent=****, current=_
KO - Unit finished an attack position, smart or move order; then aquires a target: lastevent=attack/smart/move, currentorder=_
KO - Unit finished an attack or smart order (the unit died or became invisible/invincible), and aquires a new one: lastevent=smart/attack, currentorder = _
The ability only casts when players manually gave one of the following orders:
- Order targeting an object (unit): smart (right-click), attack
- Order targeting a point (any point, but order must not be over): attack ground, attack-move, patrol
Test cases (logging last order issued & current order)
OK - Unit is on patrol, and engages a target: lastevent=patrol, currentorder=_
OK - Unit is still doing an attack position order: lastevent=attack, currentorder=attack
OK - Unit is attacking an unit because of an attack or smart order: lastevent=attack/smart, currentorder=attacks/mart (both are identical)
KO - Unit is holding position: lastevent=holdposition, currentorder=_
KO - Unit aquires a new target, and was stopped before: lastevent=stop, current=_
KO - Unit aquires a new target, and last order was irrelevant (learn skill, use skill, etc...): lastevent=****, current=_
KO - Unit finished an attack position, smart or move order; then aquires a target: lastevent=attack/smart/move, currentorder=_
KO - Unit finished an attack or smart order (the unit died or became invisible/invincible), and aquires a new one: lastevent=smart/attack, currentorder = _
How to use:
When you create a unit with the bugged ability, or when a unit learns the bugged ability, just call RegisterUnitForOosFix(<unit>). My code handles the rest (target aquisition, improper orders handle, unit death...).
Triggers:
OosFix RegisterUnit (JASS API function)
JASS:
function RegisterUnitForOosFix takes unit u returns nothing
// Unit issued order events
if ( IsTriggerEnabled( gg_trg_OosFix_UnitIssuedOrder ) == false ) then
call EnableTrigger( gg_trg_OosFix_UnitIssuedOrder )
endif
call TriggerRegisterUnitEvent( gg_trg_OosFix_UnitIssuedOrder, u, EVENT_UNIT_ISSUED_TARGET_ORDER )
call TriggerRegisterUnitEvent( gg_trg_OosFix_UnitIssuedOrder, u, EVENT_UNIT_ISSUED_POINT_ORDER )
call TriggerRegisterUnitEvent( gg_trg_OosFix_UnitIssuedOrder, u, EVENT_UNIT_ISSUED_ORDER )
// Unit acquires target event
if ( IsTriggerEnabled( gg_trg_OosFix_UnitTargetAcquisition ) == false ) then
call EnableTrigger( gg_trg_OosFix_UnitTargetAcquisition )
endif
call TriggerRegisterUnitEvent( gg_trg_OosFix_UnitTargetAcquisition, u, EVENT_UNIT_ACQUIRED_TARGET )
endfunction
OosFix UnitIssuedOrder (GUI)
-
OosFix UnitIssuedOrder
-

Events
-

Conditions
-

Actions
-


Set TempBoolean = True
-


-------- Patrol order is ignored if distance is too short, because no action was taken by the unit --------
-


If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-



If - Conditions
-




(String((Issued order))) Equal to patrol
-
-



Then - Actions
-




Set TempPoint = (Position of (Ordered unit))
-




If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-





If - Conditions
-






(Distance between TempPoint and (Target point of issued order)) Less than 100.00
-
-





Then - Actions
-






Set TempBoolean = False
-
-





Else - Actions
-






Do nothing
-
-
-




Custom script: call RemoveLocation(udg_TempPoint)
-
-



Else - Actions
-




Do nothing
-
-
-


If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-



If - Conditions
-




TempBoolean Equal to True
-
-



Then - Actions
-




Hashtable - Save (String((Issued order))) as (Key UnitIssuedOrder) of (Key (Ordered unit)) in GameCache
-
-



Else - Actions
-




Do nothing
-
-
-
-
OosFix UnitTargetAcquisition (GUI)
-
OosFix UnitTargetAcquisition
-

Events
-

Conditions
-

Actions
-


-------- Retrieve unit issued order --------
-


Set TempString1 = <Empty String>
-


Set TempString1 = (Load (Key UnitIssuedOrder) of (Key (Triggering unit)) from GameCache)
-


-------- Case A: unit was forced back to holdposition, but re-acquires a target --------
-


If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-



If - Conditions
-




TempString1 Equal to holdpositionforced
-
-



Then - Actions
-




Trigger - Turn off OosFix UnitIssuedOrder <gen>
-




-------- Attack-move in place: preserves guard position. --------
-




Set TempPoint = (Position of (Triggering unit))
-




Unit - Order (Triggering unit) to Attack-Move To TempPoint
-




Custom script: call RemoveLocation(udg_TempPoint)
-




Trigger - Turn on OosFix UnitIssuedOrder <gen>
-




Unit Group - Add (Triggering unit) to BugFixHoldPositionResumeGroup
-




Trigger - Turn on OosFix HoldPositionResume <gen>
-




Hashtable - Save holdposition as (Key UnitIssuedOrder) of (Key (Triggering unit)) in GameCache
-
-



Else - Actions
-




Do nothing
-
-
-


-------- Case B: hold position order is under execution --------
-


If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-



If - Conditions
-




TempString1 Equal to holdposition
-
-



Then - Actions
-




-------- Wait for the end of this acquisition, then reload variable to ensure MUI --------
-




Wait 0.01 seconds
-




Set TempString1 = <Empty String>
-




Set TempString1 = (Load (Key UnitIssuedOrder) of (Key (Triggering unit)) from GameCache)
-




Trigger - Turn off OosFix UnitIssuedOrder <gen>
-




-------- Force back to hold position. Cancels previous acquisition. --------
-




Unit - Order (Triggering unit) to Hold Position
-




Trigger - Turn on OosFix UnitIssuedOrder <gen>
-




Hashtable - Save holdpositionforced as (Key UnitIssuedOrder) of (Key (Triggering unit)) in GameCache
-
-



Else - Actions
-




Do nothing
-
-
-


-------- Case C: no order under execution for the moment --------
-


If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-



If - Conditions
-




TempString1 Not equal to patrol
-




TempString1 Not equal to holdposition
-




TempString1 Not equal to holdpositionforced
-




(String((Current order of (Triggering unit)))) Equal to <Empty String>
-
-



Then - Actions
-




Trigger - Turn off OosFix UnitIssuedOrder <gen>
-




-------- Attack-move in place: preserves guard position. Do not change acquisition. --------
-




Set TempPoint = (Position of (Triggering unit))
-




Unit - Order (Triggering unit) to Attack-Move To TempPoint
-




Custom script: call RemoveLocation(udg_TempPoint)
-




Trigger - Turn on OosFix UnitIssuedOrder <gen>
-
-



Else - Actions
-
-


-------- Case DEFAULT: no change, preserves orders under-execution. --------
-


-------- Else: string(UnitIssuedOrder) == "patrol" or (string(UnitIssuedOrder) != "holdposition" string(current order) != <string vide>) --------
-
-
OosFix HoldPositionResume (GUI)
-
OosFix HoldPositionResume
-

Events
-


Time - Every 0.01 seconds of game time
-
-

Conditions
-

Actions
-


Unit Group - Pick every unit in BugFixHoldPositionResumeGroup and do (Actions)
-



Loop - Actions
-




If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-





If - Conditions
-






((Picked unit) is dead) Equal to True
-
-





Then - Actions
-






Unit Group - Remove (Picked unit) from BugFixHoldPositionResumeGroup
-
-





Else - Actions
-






Set TempString1 = <Empty String>
-






Set TempString1 = (Load (Key UnitCurrentOrder) of (Key (Picked unit)) from GameCache)
-






Set TempString2 = <Empty String>
-






Set TempString2 = (Load (Key UnitIssuedOrder) of (Key (Picked unit)) from GameCache)
-






If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-







If - Conditions
-








TempString1 Equal to (String((Current order of (Picked unit))))
-
-







Then - Actions
-








Do nothing
-
-







Else - Actions
-








Hashtable - Save (String((Current order of (Picked unit)))) as (Key UnitCurrentOrder) of (Key (Picked unit)) in GameCache
-








-------- Case A: last issued order is hold position (normal or forced), and changes from something to idle --------
-








If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-









If - Conditions
-










TempString1 Not equal to holdposition
-










Or - Any (Conditions) are true
-











Conditions
-












TempString2 Equal to holdposition
-












TempString2 Equal to holdpositionforced
-
-
-










(String((Current order of (Picked unit)))) Equal to <Empty String>
-
-









Then - Actions
-










Trigger - Turn off OosFix UnitIssuedOrder <gen>
-










-------- Force back to hold position. --------
-










Unit - Order (Picked unit) to Hold Position
-










Trigger - Turn on OosFix UnitIssuedOrder <gen>
-










Unit Group - Remove (Picked unit) from BugFixHoldPositionResumeGroup
-
-









Else - Actions
-










Do nothing
-
-
-
-
-
-
-
-
-


If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-



If - Conditions
-




(BugFixHoldPositionResumeGroup is empty) Equal to True
-
-



Then - Actions
-




Trigger - Turn off (This trigger)
-
-



Else - Actions
-




Do nothing
-
-
-
-
Last edited: