Index: ps/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
+++ ps/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
@@ -772,7 +772,7 @@
return;
}
- this.PushOrderFront("Attack", { "target": msg.data.target, "force": !!msg.data.force, "hunting": true, "allowCapture": false });
+ this.PushOrderFront("Attack", { "target": msg.data.target, "force": !!msg.data.force, "hunting": true, "allowCapture": false, "min": 0, "max": 10 });
return;
}
@@ -1218,10 +1218,7 @@
}
// No orders left, we're an individual now
- if (this.IsAnimal())
- this.SetNextState("ANIMAL.IDLE");
- else
- this.SetNextState("INDIVIDUAL.IDLE");
+ this.SetNextState("INDIVIDUAL.IDLE");
},
// Override the LeaveFoundation order since we're not doing
@@ -1251,6 +1248,15 @@
},
"enter": function() {
+ if (this.IsAnimal())
+ {
+ // Animals can't go in formation.
+ warn("Entity " + this.entity + " was put in FORMATIONMEMBER state but is an animal");
+ this.FinishOrder();
+ this.SetNextState("ANIMAL.IDLE");
+ return true;
+ }
+
let cmpFormation = Engine.QueryInterface(this.formationController, IID_Formation);
if (cmpFormation)
this.SetAnimationVariant(cmpFormation.GetFormationAnimation(this.entity));
@@ -1261,13 +1267,8 @@
},
"IDLE": {
- "enter": function() {
- if (this.IsAnimal())
- this.SetNextState("ANIMAL.IDLE");
- else
- this.SetNextState("INDIVIDUAL.IDLE");
- return true;
- },
+ // Formation members do nothing while Idle, but we need the state
+ // so that they keep the formation variant.
},
"WALKING": {
@@ -1276,11 +1277,22 @@
cmpUnitMotion.MoveToFormationOffset(this.order.data.target, this.order.data.x, this.order.data.z);
},
+ "leave": function() {
+ this.StopMoving();
+ },
+
// Occurs when the unit has reached its destination and the controller
// is done moving. The controller is notified.
"MovementUpdate": function(msg) {
// We can only finish this order if the move was really completed.
- if (!this.CheckRange(this.order.data) || msg.error)
+ let cmpPosition = Engine.QueryInterface(this.formationController, IID_Position);
+ let atDestination = cmpPosition && cmpPosition.IsInWorld();
+ if (!atDestination && cmpPosition)
+ {
+ let pos = cmpPosition.GetPosition2D();
+ atDestination = this.CheckPointRangeExplicit(pos.X + this.order.data.x, pos.Y + this.order.data.z, 0, 0);
+ }
+ if (!atDestination && !msg.error)
return;
if (this.FinishOrder())
@@ -1386,15 +1398,15 @@
"IDLE": {
"enter": function() {
+ if (this.formationController)
+ {
+ this.SetNextState("FORMATIONMEMBER.IDLE");
+ return true;
+ }
+
// Switch back to idle animation to guarantee we won't
// get stuck with an incorrect animation
var animationName = "idle";
- if (this.IsFormationMember())
- {
- var cmpFormation = Engine.QueryInterface(this.formationController, IID_Formation);
- if (cmpFormation)
- animationName = cmpFormation.GetFormationAnimation(this.entity, animationName);
- }
this.SelectAnimation(animationName);
// If we have some orders, it is because we are in an intermediary state
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_formation.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_formation.xml
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_formation.xml
@@ -36,6 +36,17 @@
false
+
+
+ true
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+
0
Index: ps/trunk/source/simulation2/components/CCmpUnitMotion.cpp
===================================================================
--- ps/trunk/source/simulation2/components/CCmpUnitMotion.cpp
+++ ps/trunk/source/simulation2/components/CCmpUnitMotion.cpp
@@ -706,12 +706,6 @@
// This makes sure that units don't clump too much when they are not in a formation and tasked to move.
if (m_LongPath.m_Waypoints.size() > 1)
m_LongPath.m_Waypoints.pop_back();
- else if (IsFormationMember())
- {
- CMessageMotionChanged msg(true);
- GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg);
- return;
- }
CMessageMotionChanged msg(false);
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg);
@@ -818,15 +812,6 @@
if (m_MoveRequest.m_Type == MoveRequest::NONE)
return false;
- if (IsFormationMember())
- {
- // We've reached our assigned position. If the controller
- // is idle, send a notification in case it should disband,
- // otherwise continue following the formation next turn.
- CmpPtr cmpUnitMotion(GetSimContext(), m_MoveRequest.m_Entity);
- return cmpUnitMotion && !cmpUnitMotion->IsMoving();
- }
-
CmpPtr cmpObstructionManager(GetSystemEntity());
ENSURE(cmpObstructionManager);
@@ -836,9 +821,14 @@
return cmpObstructionManager->IsInTargetRange(GetEntityId(), m_MoveRequest.m_Entity, m_MoveRequest.m_MinRange, m_MoveRequest.m_MaxRange, false);
if (m_MoveRequest.m_Type == MoveRequest::OFFSET)
{
+ CmpPtr cmpControllerMotion(GetSimContext(), m_MoveRequest.m_Entity);
+ if (cmpControllerMotion && cmpControllerMotion->IsMoving())
+ return false;
+
CFixedVector2D targetPos;
ComputeTargetPosition(targetPos);
- return cmpObstructionManager->IsInPointRange(GetEntityId(), m_MoveRequest.m_Position.X, m_MoveRequest.m_Position.Y, m_MoveRequest.m_MinRange, m_MoveRequest.m_MaxRange, false);
+ CmpPtr cmpPosition(GetEntityHandle());
+ return cmpObstructionManager->IsInPointRange(GetEntityId(), targetPos.X, targetPos.Y, m_MoveRequest.m_MinRange, m_MoveRequest.m_MaxRange, false);
}
return false;
}