mirror of
https://gitea.wildfiregames.com/0ad/0ad.git
synced 2026-06-21 12:44:09 +00:00
Fix formation merging issues.
The motion parameters were calculated even without members, which caused us to try set a undefined passclass. Also were members added to previously merged twin-formations. Once merged (i.e. disbanded), they are moved out of world now. Some cleanups/deduplication whilst at it. Reported by: @andy5995 at the forums (https://wildfiregames.com/forum/topic/71578-feedbacks-from-a26-svn-tests/page/8/#comment-505078) Differential revision: https://code.wildfiregames.com/D4727 Comments by: @Langbart, @marder Tested by: @Langbart Fixes #6580 This was SVN commit r26993.
This commit is contained in:
@@ -380,33 +380,38 @@ Formation.prototype.SetMembers = function(ents)
|
||||
Formation.prototype.RemoveMembers = function(ents, renamed = false)
|
||||
{
|
||||
this.offsets = undefined;
|
||||
this.members = this.members.filter(ent => ents.indexOf(ent) === -1);
|
||||
this.members = this.members.filter(ent => !ents.includes(ent));
|
||||
|
||||
for (let ent of ents)
|
||||
for (const ent of ents)
|
||||
{
|
||||
this.finishedEntities.delete(ent);
|
||||
let cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
|
||||
const cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
|
||||
cmpUnitAI.UpdateWorkOrders();
|
||||
cmpUnitAI.SetFormationController(INVALID_ENTITY);
|
||||
cmpUnitAI.UnsetFormationController();
|
||||
}
|
||||
|
||||
for (let ent of this.formationMembersWithAura)
|
||||
{
|
||||
let cmpAuras = Engine.QueryInterface(ent, IID_Auras);
|
||||
const cmpAuras = Engine.QueryInterface(ent, IID_Auras);
|
||||
cmpAuras.RemoveFormationAura(ents);
|
||||
|
||||
// The unit with the aura is also removed from the formation.
|
||||
if (ents.indexOf(ent) !== -1)
|
||||
if (ents.includes(ent))
|
||||
cmpAuras.RemoveFormationAura(this.members);
|
||||
}
|
||||
|
||||
this.formationMembersWithAura = this.formationMembersWithAura.filter(function(e) { return ents.indexOf(e) == -1; });
|
||||
this.formationMembersWithAura = this.formationMembersWithAura.filter(ent => !ents.includes(ent));
|
||||
|
||||
// If there's nobody left, destroy the formation
|
||||
// unless this is a rename where we can have 0 members temporarily.
|
||||
if (this.members.length < +this.template.RequiredMemberCount && !renamed)
|
||||
if (!renamed && this.members.length < +this.template.RequiredMemberCount)
|
||||
{
|
||||
this.Disband();
|
||||
// Hack: switch to a clean state to stop timers.
|
||||
const cmpUnitAI = Engine.QueryInterface(this.entity, IID_UnitAI);
|
||||
cmpUnitAI.UnitFsm.SwitchToNextState(cmpUnitAI, "");
|
||||
Engine.QueryInterface(this.entity, IID_Position).MoveOutOfWorld();
|
||||
this.DeleteTwinFormations();
|
||||
Engine.DestroyEntity(this.entity);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -459,27 +464,7 @@ Formation.prototype.AddMembers = function(ents)
|
||||
*/
|
||||
Formation.prototype.Disband = function()
|
||||
{
|
||||
for (let ent of this.members)
|
||||
{
|
||||
let cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
|
||||
cmpUnitAI.SetFormationController(INVALID_ENTITY);
|
||||
}
|
||||
|
||||
for (let ent of this.formationMembersWithAura)
|
||||
{
|
||||
let cmpAuras = Engine.QueryInterface(ent, IID_Auras);
|
||||
cmpAuras.RemoveFormationAura(this.members);
|
||||
}
|
||||
|
||||
this.members = [];
|
||||
this.finishedEntities.clear();
|
||||
this.formationMembersWithAura = [];
|
||||
this.offsets = undefined;
|
||||
|
||||
let cmpUnitAI = Engine.QueryInterface(this.entity, IID_UnitAI);
|
||||
// Hack: switch to a clean state to stop timers.
|
||||
cmpUnitAI.UnitFsm.SwitchToNextState(cmpUnitAI, "");
|
||||
Engine.DestroyEntity(this.entity);
|
||||
this.RemoveMembers(this.members);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -901,10 +886,13 @@ Formation.prototype.DoesAngleDifferenceAllowTurning = function(a1, a2)
|
||||
*/
|
||||
Formation.prototype.ComputeMotionParameters = function()
|
||||
{
|
||||
if (!this.members.length)
|
||||
return;
|
||||
|
||||
let minSpeed = Infinity;
|
||||
let minAcceleration = Infinity;
|
||||
let maxClearance = 0;
|
||||
let maxPassClass;
|
||||
let maxPassClass = "default";
|
||||
|
||||
const cmpPathfinder = Engine.QueryInterface(SYSTEM_ENTITY, IID_Pathfinder);
|
||||
for (let ent of this.members)
|
||||
@@ -968,11 +956,9 @@ Formation.prototype.ShapeUpdate = function()
|
||||
|
||||
// Merge the members from the twin formation into this one
|
||||
// twin formations should always have exactly the same orders.
|
||||
let otherMembers = cmpOtherFormation.members;
|
||||
const otherMembers = cmpOtherFormation.members;
|
||||
cmpOtherFormation.RemoveMembers(otherMembers);
|
||||
this.AddMembers(otherMembers);
|
||||
Engine.DestroyEntity(this.twinFormations[i]);
|
||||
this.twinFormations.splice(i, 1);
|
||||
}
|
||||
// Switch between column and box if necessary.
|
||||
let cmpUnitAI = Engine.QueryInterface(this.entity, IID_UnitAI);
|
||||
|
||||
@@ -5181,24 +5181,17 @@ UnitAI.prototype.SetFormationController = function(ent)
|
||||
{
|
||||
this.formationController = ent;
|
||||
|
||||
// Set obstruction group, so we can walk through members
|
||||
// of our own formation (or ourself if not in formation)
|
||||
const cmpObstruction = Engine.QueryInterface(this.entity, IID_Obstruction);
|
||||
if (cmpObstruction)
|
||||
{
|
||||
if (ent == INVALID_ENTITY)
|
||||
cmpObstruction.SetControlGroup(this.entity);
|
||||
else
|
||||
cmpObstruction.SetControlGroup(ent);
|
||||
}
|
||||
// Set obstruction group, so we can walk through members of our own formation.
|
||||
Engine.QueryInterface(this.entity, IID_Obstruction)?.SetControlGroup(ent);
|
||||
Engine.QueryInterface(this.entity, IID_UnitMotion)?.SetMemberOfFormation(ent);
|
||||
};
|
||||
|
||||
const cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion);
|
||||
if (cmpUnitMotion)
|
||||
cmpUnitMotion.SetMemberOfFormation(ent);
|
||||
|
||||
// If we were removed from a formation, let the FSM switch back to INDIVIDUAL
|
||||
if (ent == INVALID_ENTITY)
|
||||
this.UnitFsm.ProcessMessage(this, { "type": "FormationLeave" });
|
||||
UnitAI.prototype.UnsetFormationController = function()
|
||||
{
|
||||
this.formationController = INVALID_ENTITY;
|
||||
Engine.QueryInterface(this.entity, IID_Obstruction)?.SetControlGroup(this.entity);
|
||||
Engine.QueryInterface(this.entity, IID_UnitMotion)?.SetMemberOfFormation(this.formationController);
|
||||
this.UnitFsm.ProcessMessage(this, { "type": "FormationLeave" });
|
||||
};
|
||||
|
||||
UnitAI.prototype.GetFormationController = function()
|
||||
|
||||
Reference in New Issue
Block a user