forked from mirrors/0ad
Use transform to finish construction.
Decreases duplication. Differential revision: D3804 Comment from: @wraitii (also on IRC) This was SVN commit r25197.
This commit is contained in:
@@ -342,132 +342,24 @@ Foundation.prototype.Build = function(builderEnt, work)
|
||||
|
||||
if (progress >= 1.0)
|
||||
{
|
||||
// Finished construction
|
||||
let cmpPlayerStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker);
|
||||
|
||||
// Create the real entity
|
||||
var building = Engine.AddEntity(this.finalTemplateName);
|
||||
let building = ChangeEntityTemplate(this.entity, this.finalTemplateName);
|
||||
|
||||
// Copy various parameters from the foundation
|
||||
|
||||
var cmpVisual = Engine.QueryInterface(this.entity, IID_Visual);
|
||||
var cmpBuildingVisual = Engine.QueryInterface(building, IID_Visual);
|
||||
if (cmpVisual && cmpBuildingVisual)
|
||||
cmpBuildingVisual.SetActorSeed(cmpVisual.GetActorSeed());
|
||||
|
||||
var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
|
||||
if (!cmpPosition || !cmpPosition.IsInWorld())
|
||||
{
|
||||
error("Foundation " + this.entity + " does not have a position in-world.");
|
||||
Engine.DestroyEntity(building);
|
||||
return;
|
||||
}
|
||||
var cmpBuildingPosition = Engine.QueryInterface(building, IID_Position);
|
||||
if (!cmpBuildingPosition)
|
||||
{
|
||||
error("New building " + building + " has no position component.");
|
||||
Engine.DestroyEntity(building);
|
||||
return;
|
||||
}
|
||||
var pos = cmpPosition.GetPosition2D();
|
||||
cmpBuildingPosition.JumpTo(pos.x, pos.y);
|
||||
var rot = cmpPosition.GetRotation();
|
||||
cmpBuildingPosition.SetYRotation(rot.y);
|
||||
cmpBuildingPosition.SetXZRotation(rot.x, rot.z);
|
||||
// TODO: should add a ICmpPosition::CopyFrom() instead of all this
|
||||
|
||||
var cmpRallyPoint = Engine.QueryInterface(this.entity, IID_RallyPoint);
|
||||
var cmpBuildingRallyPoint = Engine.QueryInterface(building, IID_RallyPoint);
|
||||
if(cmpRallyPoint && cmpBuildingRallyPoint)
|
||||
{
|
||||
var rallyCoords = cmpRallyPoint.GetPositions();
|
||||
var rallyData = cmpRallyPoint.GetData();
|
||||
for (var i = 0; i < rallyCoords.length; ++i)
|
||||
{
|
||||
cmpBuildingRallyPoint.AddPosition(rallyCoords[i].x, rallyCoords[i].z);
|
||||
cmpBuildingRallyPoint.AddData(rallyData[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
var owner;
|
||||
var cmpTerritoryDecay = Engine.QueryInterface(building, IID_TerritoryDecay);
|
||||
if (cmpTerritoryDecay && cmpTerritoryDecay.HasTerritoryOwnership())
|
||||
{
|
||||
let cmpTerritoryManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager);
|
||||
owner = cmpTerritoryManager.GetOwner(pos.x, pos.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
|
||||
if (!cmpOwnership)
|
||||
{
|
||||
error("Foundation " + this.entity + " has no ownership.");
|
||||
Engine.DestroyEntity(building);
|
||||
return;
|
||||
}
|
||||
owner = cmpOwnership.GetOwner();
|
||||
}
|
||||
var cmpBuildingOwnership = Engine.QueryInterface(building, IID_Ownership);
|
||||
if (!cmpBuildingOwnership)
|
||||
{
|
||||
error("New Building " + building + " has no ownership.");
|
||||
Engine.DestroyEntity(building);
|
||||
return;
|
||||
}
|
||||
cmpBuildingOwnership.SetOwner(owner);
|
||||
|
||||
/*
|
||||
Copy over the obstruction control group IDs from the foundation
|
||||
entities. This is needed to ensure that when a foundation is completed
|
||||
and replaced by a new entity, it remains in the same control group(s)
|
||||
as any other foundation entities that may surround it. This is the
|
||||
mechanism that is used to e.g. enable wall pieces to be built closely
|
||||
together, ignoring their mutual obstruction shapes (since they would
|
||||
otherwise be prevented from being built so closely together). If the
|
||||
control groups are not copied over, the new entity will default to a
|
||||
new control group containing only itself, and will hence block
|
||||
construction of any surrounding foundations that it was previously in
|
||||
the same control group with.
|
||||
|
||||
Note that this will result in the completed building entities having
|
||||
control group IDs that equal entity IDs of old (and soon to be deleted)
|
||||
foundation entities. This should not have any consequences, however,
|
||||
since the control group IDs are only meant to be unique identifiers,
|
||||
which is still true when reusing the old ones.
|
||||
*/
|
||||
|
||||
var cmpBuildingObstruction = Engine.QueryInterface(building, IID_Obstruction);
|
||||
if (cmpObstruction && cmpBuildingObstruction)
|
||||
{
|
||||
cmpBuildingObstruction.SetControlGroup(cmpObstruction.GetControlGroup());
|
||||
cmpBuildingObstruction.SetControlGroup2(cmpObstruction.GetControlGroup2());
|
||||
}
|
||||
|
||||
var cmpPlayerStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker);
|
||||
if (cmpPlayerStatisticsTracker)
|
||||
cmpPlayerStatisticsTracker.IncreaseConstructedBuildingsCounter(building);
|
||||
|
||||
var cmpBuildingHealth = Engine.QueryInterface(building, IID_Health);
|
||||
if (cmpBuildingHealth)
|
||||
cmpBuildingHealth.SetHitpoints(progress * cmpBuildingHealth.GetMaxHitpoints());
|
||||
|
||||
PlaySound("constructed", building);
|
||||
|
||||
Engine.PostMessage(this.entity, MT_ConstructionFinished,
|
||||
{ "entity": this.entity, "newentity": building });
|
||||
Engine.PostMessage(this.entity, MT_EntityRenamed, { "entity": this.entity, "newentity": building });
|
||||
|
||||
// Inform the builders that repairing has finished.
|
||||
// This not done by listening to a global message due to performance.
|
||||
for (let builder of this.GetBuilders())
|
||||
{
|
||||
let cmpUnitAIBuilder = Engine.QueryInterface(builder, IID_UnitAI);
|
||||
if (cmpUnitAIBuilder)
|
||||
cmpUnitAIBuilder.ConstructionFinished({ "entity": this.entity, "newentity": building });
|
||||
}
|
||||
|
||||
Engine.DestroyEntity(this.entity);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ RallyPoint.prototype.OrderToRallyPoint = function(entity, ignore = [])
|
||||
|
||||
RallyPoint.prototype.OnGlobalEntityRenamed = function(msg)
|
||||
{
|
||||
for (var data of this.data)
|
||||
for (let data of this.data)
|
||||
{
|
||||
if (!data)
|
||||
continue;
|
||||
@@ -136,6 +136,21 @@ RallyPoint.prototype.OnGlobalEntityRenamed = function(msg)
|
||||
if (data.source && data.source == msg.entity)
|
||||
data.source = msg.newentity;
|
||||
}
|
||||
|
||||
if (msg.entity != this.entity)
|
||||
return;
|
||||
|
||||
let cmpRallyPointNew = Engine.QueryInterface(msg.newentity, IID_RallyPoint);
|
||||
if (cmpRallyPointNew)
|
||||
{
|
||||
let rallyCoords = this.GetPositions();
|
||||
let rallyData = this.GetData();
|
||||
for (let i = 0; i < rallyCoords.length; ++i)
|
||||
{
|
||||
cmpRallyPointNew.AddPosition(rallyCoords[i].x, rallyCoords[i].z);
|
||||
cmpRallyPointNew.AddData(rallyData[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
RallyPoint.prototype.OnOwnershipChanged = function(msg)
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
Engine.LoadHelperScript("Player.js");
|
||||
Engine.LoadHelperScript("Transform.js");
|
||||
Engine.LoadHelperScript("ValueModification.js");
|
||||
Engine.LoadComponentScript("interfaces/AutoBuildable.js");
|
||||
Engine.LoadComponentScript("interfaces/Builder.js");
|
||||
Engine.LoadComponentScript("interfaces/Capturable.js");
|
||||
Engine.LoadComponentScript("interfaces/Cost.js");
|
||||
Engine.LoadComponentScript("interfaces/Foundation.js");
|
||||
Engine.LoadComponentScript("interfaces/Guard.js");
|
||||
Engine.LoadComponentScript("interfaces/Health.js");
|
||||
Engine.LoadComponentScript("interfaces/ModifiersManager.js");
|
||||
Engine.LoadComponentScript("interfaces/Population.js");
|
||||
Engine.LoadComponentScript("interfaces/Promotion.js");
|
||||
Engine.LoadComponentScript("interfaces/Repairable.js");
|
||||
Engine.LoadComponentScript("interfaces/ResourceGatherer.js");
|
||||
Engine.LoadComponentScript("interfaces/StatisticsTracker.js");
|
||||
Engine.LoadComponentScript("interfaces/StatusEffectsReceiver.js");
|
||||
Engine.LoadComponentScript("interfaces/TerritoryDecay.js");
|
||||
Engine.LoadComponentScript("interfaces/Trigger.js");
|
||||
Engine.LoadComponentScript("interfaces/Timer.js");
|
||||
@@ -15,6 +22,7 @@ Engine.LoadComponentScript("interfaces/UnitAI.js");
|
||||
Engine.LoadComponentScript("AutoBuildable.js");
|
||||
Engine.LoadComponentScript("Foundation.js");
|
||||
Engine.LoadComponentScript("Timer.js");
|
||||
|
||||
let player = 1;
|
||||
let playerEnt = 3;
|
||||
let foundationEnt = 20;
|
||||
@@ -84,6 +92,8 @@ function testFoundation(...mocks)
|
||||
"GetRotation": () => rot,
|
||||
"SetConstructionProgress": () => {},
|
||||
"IsInWorld": () => true,
|
||||
"GetHeightOffset": () => {},
|
||||
"MoveOutOfWorld": () => {}
|
||||
});
|
||||
|
||||
AddMock(previewEnt, IID_Ownership, {
|
||||
@@ -108,6 +118,7 @@ function testFoundation(...mocks)
|
||||
});
|
||||
|
||||
AddMock(newEnt, IID_Position, {
|
||||
"GetPosition2D": () => pos,
|
||||
"JumpTo": (x, y) => {
|
||||
TS_ASSERT_EQUALS(x, pos.x);
|
||||
TS_ASSERT_EQUALS(y, pos.y);
|
||||
@@ -117,6 +128,7 @@ function testFoundation(...mocks)
|
||||
TS_ASSERT_EQUALS(rx, rot.x);
|
||||
TS_ASSERT_EQUALS(rz, rot.z);
|
||||
},
|
||||
"SetHeightOffset": () => {}
|
||||
});
|
||||
|
||||
for (let mock of mocks)
|
||||
|
||||
@@ -14,6 +14,7 @@ Engine.LoadComponentScript("interfaces/Promotion.js");
|
||||
Engine.LoadComponentScript("interfaces/Repairable.js");
|
||||
Engine.LoadComponentScript("interfaces/ResourceGatherer.js");
|
||||
Engine.LoadComponentScript("interfaces/StatusEffectsReceiver.js");
|
||||
Engine.LoadComponentScript("interfaces/TerritoryDecay.js");
|
||||
Engine.LoadComponentScript("interfaces/Timer.js");
|
||||
Engine.LoadComponentScript("interfaces/UnitAI.js");
|
||||
Engine.LoadComponentScript("Pack.js");
|
||||
|
||||
@@ -33,12 +33,24 @@ function ChangeEntityTemplate(oldEnt, newTemplate)
|
||||
for (let entity of cmpTurretHolder.GetEntities())
|
||||
cmpNewTurretHolder.SetReservedTurretPoint(cmpTurretHolder.GetOccupiedTurretPointName(entity));
|
||||
|
||||
var cmpOwnership = Engine.QueryInterface(oldEnt, IID_Ownership);
|
||||
var cmpNewOwnership = Engine.QueryInterface(newEnt, IID_Ownership);
|
||||
if (cmpOwnership && cmpNewOwnership)
|
||||
cmpNewOwnership.SetOwner(cmpOwnership.GetOwner());
|
||||
let owner;
|
||||
let cmpTerritoryDecay = Engine.QueryInterface(newEnt, IID_TerritoryDecay);
|
||||
if (cmpTerritoryDecay && cmpTerritoryDecay.HasTerritoryOwnership() && cmpNewPosition)
|
||||
{
|
||||
let pos = cmpNewPosition.GetPosition2D();
|
||||
let cmpTerritoryManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager);
|
||||
owner = cmpTerritoryManager.GetOwner(pos.x, pos.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
let cmpOwnership = Engine.QueryInterface(oldEnt, IID_Ownership);
|
||||
if (cmpOwnership)
|
||||
owner = cmpOwnership.GetOwner();
|
||||
}
|
||||
let cmpNewOwnership = Engine.QueryInterface(newEnt, IID_Ownership);
|
||||
if (cmpNewOwnership)
|
||||
cmpNewOwnership.SetOwner(owner);
|
||||
|
||||
// Copy control groups
|
||||
CopyControlGroups(oldEnt, newEnt);
|
||||
|
||||
// Rescale capture points
|
||||
@@ -143,6 +155,14 @@ function ChangeEntityTemplate(oldEnt, newTemplate)
|
||||
return newEnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy over the obstruction control group IDs.
|
||||
* This is needed to ensure that when a group of structures with the same
|
||||
* control groups is replaced by a new entity, they remains in the same control group(s).
|
||||
* This is the mechanism that is used to e.g. enable wall pieces to be built closely
|
||||
* together, ignoring their mutual obstruction shapes (since they would
|
||||
* otherwise be prevented from being built so closely together).
|
||||
*/
|
||||
function CopyControlGroups(oldEnt, newEnt)
|
||||
{
|
||||
let cmpObstruction = Engine.QueryInterface(oldEnt, IID_Obstruction);
|
||||
|
||||
Reference in New Issue
Block a user