Okay, so. I figured I'd make a new thread for this since the other one wasn't quite about this system but was more for trying to figure out how SC2 triggers work which I think I got it down now. (Maybe xD!)
So, the problem I'm having is that using this system I made you cannot queue orders via Shift Click. This is the trigger:
MagixBoxTriggerEventsUnit-AnyUnitisissuedanordertoAnyAbilityCommandLocalVariablesP_Center=NoPoint<Point>P_Target=NoPoint<Point>P_UnitPoint=NoPoint<Point>P_OrderAngle=0.0<Real>P_Distance=0.0<Real>P_XofUnit=0.0<Real>P_XResult=0.0<Real>P_YofUnit=0.0<Real>P_YResult=0.0<Real>P_Count=0<Integer>P_Int=0<Integer>P_UnitsOrdered=0<Integer>P_InitialOrder=NoAbilityCommand<AbilityCommand>P_OrderUnit=NoUnit<Unit>P_Group=(Emptyunitgroup)<UnitGroup>Conditions(Targettypefor(Triggeringorder))==PointActionsGeneral-ForeachintegerP_Intfrom1to16withincrement1,do(Actions)ActionsVariable-SetP_Target=(Targetpointfor(Triggeringorder))General-If(Conditions)thendo(Actions)elsedo(Actions)IfOrConditions(Triggeringorder)==(((Move,0))targetingP_Target)(Triggeringorder)==(((Move,1))targetingP_Target)(Triggeringorder)==(((Move,3))targetingP_Target)ThenVariable-SetP_InitialOrder=(Abilitycommandfor(Triggeringorder))ElseGeneral-If(Conditions)thendo(Actions)elsedo(Actions)If((Triggeringunit)isinP_Group[P_Int]) == True
Then
Unit Group - Pick each unit in P_Group[P_Int] and do (Actions)
Actions
Variable - Set P_XofUnit = (X of (Position of (Picked unit)))
Variable - Set P_YofUnit = (Y of (Position of (Picked unit)))
Variable - Set P_XResult = (P_XResult + P_XofUnit)
Variable - Set P_YResult = (P_YResult + P_YofUnit)
Variable - Set P_Count = (P_Count + 1)
Variable - Set P_Center = (Point((P_XResult / P_Count), (P_YResult / P_Count)))
Variable - Set P_OrderAngle = (Angle from P_Center to P_Target)
Variable - Set P_Distance = (Distance between P_Center and P_Target)
Variable - Set P_XofUnit = 0.0
Variable - Set P_YofUnit = 0.0
Variable - Set P_XResult = 0.0
Variable - Set P_YResult = 0.0
Variable - Set P_Count = 0
Unit Group - Pick each unit in P_Group[P_Int] and do (Actions)
Actions
Variable - Set P_OrderUnit = (Picked unit)
Variable - Set P_UnitPoint = (Position of (Picked unit))
Trigger - Turn (Current trigger) Off
General - If (Conditions) then do (Actions) else do (Actions)
If
(Distance between P_UnitPoint and P_Center) > 10.0
Then
Unit - Order (Picked unit) to (P_InitialOrder targeting P_Target) (Replace Existing Orders)
Else
General - If (Conditions) then do (Actions) else do (Actions)
If
(Distance between P_Target and P_Center) < 1.0ThenUnit-Order(Pickedunit)to(P_InitialOrdertargetingP_Target)(ReplaceExistingOrders)ElseUnit-Order(Pickedunit)to(P_InitialOrdertargeting((Positionof(Pickedunit))offsetbyP_DistancetowardsP_OrderAngledegrees))(ReplaceExistingOrders)Trigger-Turn(Currenttrigger)OnElse
I have tried setting the (Replace Existing Orders) with (Before/After Existing Orders) but that does not remove the initial order, which is crucial for this to work. The actual order via the normal order buttons (Move/Patrol/Etc) needs to be removed entirely, but the orders via trigger still need to be queueable. Any ideas?
An idea that popped into my head was that you could read all queued orders on the unit into an array (you can query queued orders in SC2). You then issue the first order you want to keep replacing all orders. Then you append the following orders you want to keep to the unit. Performance may or may not be a concern but it will work. The order queue in SC2 is only like 64 or 128 orders so do not worry about overflowing a reasonably sized array. Only 1 array for orders is required, and it could even be made locally on demand.
Here is a rough example how you can keep order queues intact. The marines can be shift ordered to move all over the map and it will still displace the order correctly. The only issue seems to be patrol, however players seldom use that and I am sure there would be some solution to it.
Of note is that the process is very resource intensive. Even queuing maximum orders for 10 marines can cause frames to drop. A possible optimization could be to use a statically allocated stack for orders instead of a local array since that would reduce the stack frame and function initialization complexity. Another approach would be if you could stop the order from ever being issues (dummy ability) then you could only add the correct orders to the stack preventing the need to rebuild the entire order stack.
Sorry I know this thread is a little old, but I'm working on queue manipulation myself and noticed this..
So I've modified this example so that it watches for an attack on a unit (focused on one unit for control) and moved the variables to be global instead of local.
The problem I am running into here is when I actually target the Ghost (this ghost - Ghost [19.94, 59.93]) - it doesn't really 'replace' the order. When I target other units, it issues the move order to the correct unit just fine.. only when I target the unit I actually want to move to, then it has a problem. Any ideas?
OrderQueueManipulationEventsUnit-Ghost[4.06,60.00]isissuedanordertoAttackLocalVariablesConditions(Targettypefor(Triggeringorder))==UnitActions------- The trigger must be turned off to stop it self-firing.Trigger-Turn(Currenttrigger)Off------- First get all unit orders.------- Skip last order as that is the triggering order.Variable-Setend=((CountofordersonGhost[4.06,60.00])-2)General-Foreachintegerifrom0toendwithincrement1,do(Actions)ActionsVariable-Setunitorders[0]=(Ghost[4.06,60.00]orderatindexi)------- Clear all unit orders with the corrected order.------- In this case I offest the order by 2,2 just for demonstration purposes.Variable-Setorder=(MovetargetingGhost[19.94,59.93])Unit-OrderGhost[4.06,60.00]toorder(ReplaceExistingOrders)------- Now refill the orders from top to bottom.General-Foreachintegerifromendto0withincrement-1,do(Actions)ActionsUnit-OrderGhost[4.06,60.00]tounitorders[0](BeforeExistingOrders)------- The trigger must be turned on again to pickup new orders.Trigger-TurnMoveQueueOn
Unit - Order Ghost [4.06, 60.00] to unit orders[0] (Before Existing Orders)
This could be the cause you set the movement order first and then you put the stored orders in front of it. Instead why not start from the start, and work your way to the end using "after existing orders" instead of "before existing orders"
The reason why it goes 'before existing orders' is because it is a queued action.
Let say this is your order queue:
0 - Move to point
1 - Move to point
2 - Attack to point
3 - Move to point
Then, with my current script - it takes an attack on a unit, and changes it to move to unit, it would do this:
0 - Attack to unit -> 0 - Move to unit
THEN
0 - Move to point
1 - Move to point
2 - Attack to point
3 - Move to point
4 - Move to unit
This would keep the current queue intact, and modify the most recent queued up command and have it stay at the end. When I initially target the unit I really want to move to, it doesn't actually move to it (this is a queued order, which after the order at position 3 is executed, the unit is no longer in range or in vision for order 4, and the unit stops). If I target a different unit, it redirects it to the target and ends up moving to the unit just fine, out of range and out of vision as well.
Not sure if I'm explaining the issue well at all.. I could try to get a video of it for an example if that would help.
hmm, if it doesn't work when moving to the (target( unit), why not try switching it to move to (target( position of unit) as a point instead of the unit itself and see if that works. Also there is pathing to the unit and it's not completely blocked right?
Move to position of unit does work, but the purpose is to be able to target the unit directly. It is only set to move as a test, my ultimate goal is to have it issue the attack order instead.. and the path isn't completely blocked.
I'll post some videos in a little bit showing what it does.
With this suggestion, I thought about it a little, and instead of having the current queued order replace and have the rest of the orders before that get placed before the existing queue, I would just save the order for later (after rebuilding the queue) and place the recent order to the end. I get much better results with the queuing.. but I'm still having an issue with getting the attack order to stick on that unit. Videos to follow.
OrderQueueManipulation-UnitEventsUnit-Ghost[4.06,60.00] is issued an order to Attack
Local Variables
order = (Triggering order) <Order>
unit = (Triggering unit) <Unit>
end = 0 <Integer>
i = 0 <Integer>
unit orders = (Triggering order) <Order[64]>
Conditions
(Target type for order) == Unit
Actions
------- The trigger must be turned off to stop it self-firing.
Trigger - Turn Order Queue Manipulation - Unit Off
------- First get all unit orders.
------- Skip last order as that is the triggering order.
Variable - Set end = ((Count of orders on unit) - 2)
General - For each integer i from 0 to end with increment 1, do (Actions)
Actions
Variable - Set unit orders[i] = (unit order at index i)
------- Clear all unit orders with the corrected order.
Variable - Set order = ((Ability command for order) targeting Ghost [19.94,59.93])
Unit - Order unit to ( Stop) (Replace Existing Orders)
------- Now refill the orders from top to bottom.
General - For each integer i from 0 to end with increment 1, do (Actions)
Actions
Unit - Order unit to unit orders[i] (After Existing Orders)
Unit - Order unit to order (After Existing Orders)
------- The trigger must be turned on again to pickup new orders.
Trigger - Turn Order Queue Manipulation - Unit On
Your trigger looks good to me. I believe the lack of unit vision is a concern here. Though it's indeed interesting that it worked without it on your first video.
Does the example from second video works good if you queue those orders while maintaining unit's vision?
Or.. as a wild guess, i'd try to modify this part:
It works when I retain vision, but when I replaced the order with a manually set order like you suggested, it still doesn't work.
I'm not sure if it has something to do with the position of the order where it doesn't want to take it, or what? I will try having the unit move back and forth to see if that works.
The attack 'ends' if my target that I've queued up is no longer in vision, that would explain why it worked when I targeted one of my own units.
This is a problem though, because the mechanic I'm working on is going to end up as a 'tracking' mechanic. If you queue up an attack on a unit that no longer has vision, it will make a best attempt to find that unit based on when the target unit was last visible (aka chase the unit into fog for X number of seconds).
Why not make an if then else statement depending on whether the unit is visible. If it's not visible have the unit move to the position of that unit, if it is have him move to the unit.
Problem with that is I want to attack it, not just move the position - my previous example of 'move' was just for testing and I left it. Moving to the position of a unit (not to the unit itself) does work though.
Rollback Post to RevisionRollBack
To post a comment, please login or register a new account.
Okay, so. I figured I'd make a new thread for this since the other one wasn't quite about this system but was more for trying to figure out how SC2 triggers work which I think I got it down now. (Maybe xD!)
So, the problem I'm having is that using this system I made you cannot queue orders via Shift Click. This is the trigger:
I have tried setting the (Replace Existing Orders) with (Before/After Existing Orders) but that does not remove the initial order, which is crucial for this to work. The actual order via the normal order buttons (Move/Patrol/Etc) needs to be removed entirely, but the orders via trigger still need to be queueable. Any ideas?
SC2Mapster Unofficial Discord! - https://discord.gg/DXENztk
An idea that popped into my head was that you could read all queued orders on the unit into an array (you can query queued orders in SC2). You then issue the first order you want to keep replacing all orders. Then you append the following orders you want to keep to the unit. Performance may or may not be a concern but it will work. The order queue in SC2 is only like 64 or 128 orders so do not worry about overflowing a reasonably sized array. Only 1 array for orders is required, and it could even be made locally on demand.
Okay, I'm not quite sure what you're talking about there. =p
Can you provide an example?
SC2Mapster Unofficial Discord! - https://discord.gg/DXENztk
Here is a rough example how you can keep order queues intact. The marines can be shift ordered to move all over the map and it will still displace the order correctly. The only issue seems to be patrol, however players seldom use that and I am sure there would be some solution to it.
Of note is that the process is very resource intensive. Even queuing maximum orders for 10 marines can cause frames to drop. A possible optimization could be to use a statically allocated stack for orders instead of a local array since that would reduce the stack frame and function initialization complexity. Another approach would be if you could stop the order from ever being issues (dummy ability) then you could only add the correct orders to the stack preventing the need to rebuild the entire order stack.
Sorry I know this thread is a little old, but I'm working on queue manipulation myself and noticed this..
So I've modified this example so that it watches for an attack on a unit (focused on one unit for control) and moved the variables to be global instead of local.
The problem I am running into here is when I actually target the Ghost (this ghost - Ghost [19.94, 59.93]) - it doesn't really 'replace' the order. When I target other units, it issues the move order to the correct unit just fine.. only when I target the unit I actually want to move to, then it has a problem. Any ideas?
Unit - Order Ghost [4.06, 60.00] to unit orders[0] (Before Existing Orders)
This could be the cause you set the movement order first and then you put the stored orders in front of it. Instead why not start from the start, and work your way to the end using "after existing orders" instead of "before existing orders"
Still alive and kicking, just busy.
My guide to the trigger editor (still a work in progress)
Thanks for your response on this.
The reason why it goes 'before existing orders' is because it is a queued action.
Let say this is your order queue:
0 - Move to point
1 - Move to point
2 - Attack to point
3 - Move to point
Then, with my current script - it takes an attack on a unit, and changes it to move to unit, it would do this:
0 - Attack to unit -> 0 - Move to unit
THEN
0 - Move to point
1 - Move to point
2 - Attack to point
3 - Move to point
4 - Move to unit
This would keep the current queue intact, and modify the most recent queued up command and have it stay at the end. When I initially target the unit I really want to move to, it doesn't actually move to it (this is a queued order, which after the order at position 3 is executed, the unit is no longer in range or in vision for order 4, and the unit stops). If I target a different unit, it redirects it to the target and ends up moving to the unit just fine, out of range and out of vision as well.
Not sure if I'm explaining the issue well at all.. I could try to get a video of it for an example if that would help.
hmm, if it doesn't work when moving to the (target( unit), why not try switching it to move to (target( position of unit) as a point instead of the unit itself and see if that works. Also there is pathing to the unit and it's not completely blocked right?
Still alive and kicking, just busy.
My guide to the trigger editor (still a work in progress)
Move to position of unit does work, but the purpose is to be able to target the unit directly. It is only set to move as a test, my ultimate goal is to have it issue the attack order instead.. and the path isn't completely blocked.
I'll post some videos in a little bit showing what it does.
@willuwontu:
With this suggestion, I thought about it a little, and instead of having the current queued order replace and have the rest of the orders before that get placed before the existing queue, I would just save the order for later (after rebuilding the queue) and place the recent order to the end. I get much better results with the queuing.. but I'm still having an issue with getting the attack order to stick on that unit. Videos to follow.
Works on different unit
Does not work on intended unit
Your trigger looks good to me. I believe the lack of unit vision is a concern here. Though it's indeed interesting that it worked without it on your first video.
Does the example from second video works good if you queue those orders while maintaining unit's vision?
Or.. as a wild guess, i'd try to modify this part:
Replacing ((Ability command for order) with manually new created attack command.
@SomeoneTookMyNameTT: Go
It works when I retain vision, but when I replaced the order with a manually set order like you suggested, it still doesn't work.
I'm not sure if it has something to do with the position of the order where it doesn't want to take it, or what? I will try having the unit move back and forth to see if that works.
So I tested it a little bit more.
The attack 'ends' if my target that I've queued up is no longer in vision, that would explain why it worked when I targeted one of my own units.
This is a problem though, because the mechanic I'm working on is going to end up as a 'tracking' mechanic. If you queue up an attack on a unit that no longer has vision, it will make a best attempt to find that unit based on when the target unit was last visible (aka chase the unit into fog for X number of seconds).
Why not make an if then else statement depending on whether the unit is visible. If it's not visible have the unit move to the position of that unit, if it is have him move to the unit.
Still alive and kicking, just busy.
My guide to the trigger editor (still a work in progress)
@willuwontu: Go
Problem with that is I want to attack it, not just move the position - my previous example of 'move' was just for testing and I left it. Moving to the position of a unit (not to the unit itself) does work though.