Improve behaviour of formations stuck within other units.
Large units risk being stuck between other units. This is true in general, but particularly weird with formations, since individual units may well not be stuck, only the invisible formation controller. This alleviates the issue by ordering units to move individually when the controller appears stuck. It introduces a new "VERY_OBSTRUCTED" unit motion message, which triggers when a unit has failed to move for several turns. Reported By: Angen Reviewed By: Freagarach Fixes #4935 Differential Revision: https://code.wildfiregames.com/D3209 This was SVN commit r24511.
This commit is contained in:
parent
d28a91b83d
commit
f34fb5614c
@ -957,13 +957,30 @@ UnitAI.prototype.UnitFsmSpec = {
|
||||
},
|
||||
|
||||
"leave": function() {
|
||||
this.StopTimer();
|
||||
this.StopMoving();
|
||||
},
|
||||
|
||||
"MovementUpdate": function(msg) {
|
||||
if (msg.veryObstructed && !this.timer)
|
||||
{
|
||||
// It's possible that the controller (with large clearance)
|
||||
// is stuck, but not the individual units.
|
||||
// Ask them to move individually for a little while.
|
||||
this.CallMemberFunction("MoveTo", [this.order.data]);
|
||||
this.StartTimer(3000);
|
||||
return;
|
||||
}
|
||||
else if (this.timer)
|
||||
return;
|
||||
if (msg.likelyFailure || this.CheckRange(this.order.data))
|
||||
this.FinishOrder();
|
||||
},
|
||||
|
||||
"Timer": function() {
|
||||
// Reenter to reset the pathfinder state.
|
||||
this.SetNextState("WALKING");
|
||||
}
|
||||
},
|
||||
|
||||
"WALKINGANDFIGHTING": {
|
||||
@ -1240,8 +1257,8 @@ UnitAI.prototype.UnitFsmSpec = {
|
||||
"MEMBER": {
|
||||
"OrderTargetRenamed": function(msg) {
|
||||
// In general, don't react - we don't want to send spurious messages to members.
|
||||
// This looks odd for hunting hwoever because we wait for all
|
||||
// entities to ahve clumped around the dead resource before proceeding
|
||||
// This looks odd for hunting however because we wait for all
|
||||
// entities to have clumped around the dead resource before proceeding
|
||||
// so explicitly handle this case.
|
||||
if (this.order && this.order.data && this.order.data.hunting &&
|
||||
this.order.data.target == msg.data.newentity &&
|
||||
@ -4222,6 +4239,8 @@ UnitAI.prototype.StopTimer = function()
|
||||
|
||||
UnitAI.prototype.OnMotionUpdate = function(msg)
|
||||
{
|
||||
if (msg.veryObstructed)
|
||||
msg.obstructed = true;
|
||||
this.UnitFsm.ProcessMessage(this, Object.assign({ "type": "MovementUpdate" }, msg));
|
||||
};
|
||||
|
||||
|
@ -327,7 +327,8 @@ public:
|
||||
enum UpdateType {
|
||||
LIKELY_SUCCESS, // UnitMotion considers it is arrived at destination.
|
||||
LIKELY_FAILURE, // UnitMotion says it cannot reach the destination.
|
||||
OBSTRUCTED, // UitMotion was obstructed. This does not mean stuck, but can be a hint to run range checks.
|
||||
OBSTRUCTED, // UnitMotion was obstructed. This does not mean stuck, but can be a hint to run range checks.
|
||||
VERY_OBSTRUCTED, // Sent when obstructed several time in a row.
|
||||
LENGTH
|
||||
};
|
||||
|
||||
|
@ -105,6 +105,12 @@ static const u8 MAX_FAILED_MOVEMENTS = 40;
|
||||
static const u8 ALTERNATE_PATH_TYPE_DELAY = 3;
|
||||
static const u8 ALTERNATE_PATH_TYPE_EVERY = 6;
|
||||
|
||||
/**
|
||||
* After this many failed computations, start sending "VERY_OBSTRUCTED" messages instead.
|
||||
* Should probably be larger than ALTERNATE_PATH_TYPE_DELAY.
|
||||
*/
|
||||
static const u8 VERY_OBSTRUCTED_THRESHOLD = 10;
|
||||
|
||||
static const CColor OVERLAY_COLOR_LONG_PATH(1, 1, 1, 1);
|
||||
static const CColor OVERLAY_COLOR_SHORT_PATH(1, 0, 0, 1);
|
||||
|
||||
@ -557,7 +563,8 @@ private:
|
||||
if (IsFormationMember() && IsFormationControllerMoving())
|
||||
return;
|
||||
|
||||
CMessageMotionUpdate msg(CMessageMotionUpdate::OBSTRUCTED);
|
||||
CMessageMotionUpdate msg(m_FailedMovements >= VERY_OBSTRUCTED_THRESHOLD ?
|
||||
CMessageMotionUpdate::VERY_OBSTRUCTED : CMessageMotionUpdate::OBSTRUCTED);
|
||||
GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg);
|
||||
}
|
||||
|
||||
|
@ -265,7 +265,7 @@ CMessage* CMessageTerritoryPositionChanged::FromJSVal(const ScriptInterface& scr
|
||||
////////////////////////////////
|
||||
|
||||
const std::array<const char*, CMessageMotionUpdate::UpdateType::LENGTH> CMessageMotionUpdate::UpdateTypeStr = { {
|
||||
"likelySuccess", "likelyFailure", "obstructed"
|
||||
"likelySuccess", "likelyFailure", "obstructed", "veryObstructed"
|
||||
} };
|
||||
|
||||
JS::Value CMessageMotionUpdate::ToJSVal(const ScriptInterface& scriptInterface) const
|
||||
@ -290,6 +290,8 @@ CMessage* CMessageMotionUpdate::FromJSVal(const ScriptInterface& scriptInterface
|
||||
return new CMessageMotionUpdate(CMessageMotionUpdate::LIKELY_FAILURE);
|
||||
if (updateString == L"obstructed")
|
||||
return new CMessageMotionUpdate(CMessageMotionUpdate::OBSTRUCTED);
|
||||
if (updateString == L"veryObstructed")
|
||||
return new CMessageMotionUpdate(CMessageMotionUpdate::VERY_OBSTRUCTED);
|
||||
|
||||
LOGWARNING("CMessageMotionUpdate::FromJSVal passed wrong updateString");
|
||||
return NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user