mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-19 23:03:56 -07:00
162 lines
5.8 KiB
JavaScript
162 lines
5.8 KiB
JavaScript
function Promotion() {}
|
|
|
|
Promotion.prototype.Schema =
|
|
"<element name='Entity'>" +
|
|
"<text/>" +
|
|
"</element>" +
|
|
"<element name='RequiredXp'>" +
|
|
"<data type='positiveInteger'/>" +
|
|
"</element>";
|
|
|
|
Promotion.prototype.Init = function()
|
|
{
|
|
this.currentXp = 0;
|
|
};
|
|
|
|
Promotion.prototype.GetRequiredXp = function()
|
|
{
|
|
return ApplyValueModificationsToEntity("Promotion/RequiredXp", +this.template.RequiredXp, this.entity);
|
|
};
|
|
|
|
Promotion.prototype.GetCurrentXp = function()
|
|
{
|
|
return this.currentXp;
|
|
};
|
|
|
|
Promotion.prototype.GetPromotedTemplateName = function()
|
|
{
|
|
return this.template.Entity;
|
|
};
|
|
|
|
Promotion.prototype.Promote = function(promotedTemplateName)
|
|
{
|
|
// Create promoted unit entity
|
|
var promotedUnitEntity = Engine.AddEntity(promotedTemplateName);
|
|
|
|
// Copy parameters from current entity to promoted one
|
|
var cmpCurrentUnitPosition = Engine.QueryInterface(this.entity, IID_Position);
|
|
var cmpPromotedUnitPosition = Engine.QueryInterface(promotedUnitEntity, IID_Position);
|
|
if (cmpCurrentUnitPosition.IsInWorld())
|
|
{
|
|
var pos = cmpCurrentUnitPosition.GetPosition2D();
|
|
cmpPromotedUnitPosition.JumpTo(pos.x, pos.y);
|
|
}
|
|
var rot = cmpCurrentUnitPosition.GetRotation();
|
|
cmpPromotedUnitPosition.SetYRotation(rot.y);
|
|
cmpPromotedUnitPosition.SetXZRotation(rot.x, rot.z);
|
|
var heightOffset = cmpCurrentUnitPosition.GetHeightOffset();
|
|
cmpPromotedUnitPosition.SetHeightOffset(heightOffset);
|
|
|
|
var cmpCurrentUnitOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
|
|
var cmpPromotedUnitOwnership = Engine.QueryInterface(promotedUnitEntity, IID_Ownership);
|
|
cmpPromotedUnitOwnership.SetOwner(cmpCurrentUnitOwnership.GetOwner());
|
|
|
|
// change promoted unit health to the same percent of hitpoints as unit had before promotion
|
|
var cmpCurrentUnitHealth = Engine.QueryInterface(this.entity, IID_Health);
|
|
var cmpPromotedUnitHealth = Engine.QueryInterface(promotedUnitEntity, IID_Health);
|
|
var healthFraction = Math.max(0, Math.min(1, cmpCurrentUnitHealth.GetHitpoints() / cmpCurrentUnitHealth.GetMaxHitpoints()));
|
|
var promotedUnitHitpoints = Math.round(cmpPromotedUnitHealth.GetMaxHitpoints() * healthFraction);
|
|
cmpPromotedUnitHealth.SetHitpoints(promotedUnitHitpoints);
|
|
|
|
var cmpPromotedUnitPromotion = Engine.QueryInterface(promotedUnitEntity, IID_Promotion);
|
|
if (cmpPromotedUnitPromotion)
|
|
cmpPromotedUnitPromotion.IncreaseXp(this.currentXp);
|
|
|
|
var cmpCurrentUnitResourceGatherer = Engine.QueryInterface(this.entity, IID_ResourceGatherer);
|
|
var cmpPromotedUnitResourceGatherer = Engine.QueryInterface(promotedUnitEntity, IID_ResourceGatherer);
|
|
if (cmpCurrentUnitResourceGatherer && cmpPromotedUnitResourceGatherer)
|
|
{
|
|
var carriedResorces = cmpCurrentUnitResourceGatherer.GetCarryingStatus();
|
|
cmpPromotedUnitResourceGatherer.GiveResources(carriedResorces);
|
|
}
|
|
|
|
var cmpCurrentUnitAI = Engine.QueryInterface(this.entity, IID_UnitAI);
|
|
var cmpPromotedUnitAI = Engine.QueryInterface(promotedUnitEntity, IID_UnitAI);
|
|
var pos = cmpCurrentUnitAI.GetHeldPosition();
|
|
if (pos)
|
|
cmpPromotedUnitAI.SetHeldPosition(pos.x, pos.z);
|
|
if (cmpCurrentUnitAI.GetStanceName())
|
|
cmpPromotedUnitAI.SwitchToStance(cmpCurrentUnitAI.GetStanceName());
|
|
|
|
var orders = cmpCurrentUnitAI.GetOrders();
|
|
if (cmpCurrentUnitAI.IsGarrisoned())
|
|
{
|
|
if (orders.length > 0 && (orders[0].type == "Garrison" || orders[0].type == "Autogarrison"))
|
|
{
|
|
// Replace the garrison order by an autogarrison order,
|
|
// as we are already garrisoned and do not need to do
|
|
// any further checks (or else we should do them here).
|
|
var garrisonHolder = orders[0].data.target;
|
|
orders.shift();
|
|
cmpPromotedUnitAI.Autogarrison(garrisonHolder);
|
|
}
|
|
else
|
|
warn("Promoted garrisoned entity with empty order queue.");
|
|
}
|
|
else
|
|
cmpPromotedUnitAI.Cheer();
|
|
|
|
cmpPromotedUnitAI.AddOrders(orders);
|
|
|
|
var workOrders = cmpCurrentUnitAI.GetWorkOrders();
|
|
cmpPromotedUnitAI.SetWorkOrders(workOrders);
|
|
cmpPromotedUnitAI.SetGuardOf(cmpCurrentUnitAI.IsGuardOf());
|
|
|
|
var cmpCurrentUnitGuard = Engine.QueryInterface(this.entity, IID_Guard);
|
|
var cmpPromotedUnitGuard = Engine.QueryInterface(promotedUnitEntity, IID_Guard);
|
|
if (cmpCurrentUnitGuard && cmpPromotedUnitGuard)
|
|
cmpPromotedUnitGuard.SetEntities(cmpCurrentUnitGuard.GetEntities());
|
|
|
|
Engine.BroadcastMessage(MT_EntityRenamed, { entity: this.entity, newentity: promotedUnitEntity });
|
|
|
|
// Destroy current entity
|
|
Engine.DestroyEntity(this.entity);
|
|
// save the entity id
|
|
this.promotedUnitEntity = promotedUnitEntity;
|
|
};
|
|
|
|
Promotion.prototype.IncreaseXp = function(amount)
|
|
{
|
|
// if the unit was already promoted, but is waiting for the engine to be destroyed
|
|
// transfer the gained xp to the promoted unit if applicable
|
|
if (this.promotedUnitEntity)
|
|
{
|
|
var cmpPromotion = Engine.QueryInterface(this.promotedUnitEntity, IID_Promotion);
|
|
if (cmpPromotion)
|
|
cmpPromotion.IncreaseXp(amount);
|
|
return;
|
|
}
|
|
|
|
this.currentXp += +(amount);
|
|
var requiredXp = this.GetRequiredXp();
|
|
|
|
if (this.currentXp >= requiredXp)
|
|
{
|
|
var cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
|
|
var playerID = QueryOwnerInterface(this.entity, IID_Player).GetPlayerID();
|
|
this.currentXp -= requiredXp;
|
|
var promotedTemplateName = this.GetPromotedTemplateName();
|
|
// check if we can upgrade a second time (or even more)
|
|
while (true)
|
|
{
|
|
var template = cmpTemplateManager.GetTemplate(promotedTemplateName);
|
|
if (!template.Promotion)
|
|
break;
|
|
requiredXp = ApplyValueModificationsToTemplate("Promotion/RequiredXp", +template.Promotion.RequiredXp, playerID, template);
|
|
// compare the current xp to the required xp of the promoted entity
|
|
if (this.currentXp < requiredXp)
|
|
break;
|
|
this.currentXp -= requiredXp;
|
|
promotedTemplateName = template.Promotion.Entity;
|
|
}
|
|
this.Promote(promotedTemplateName);
|
|
}
|
|
};
|
|
|
|
Promotion.prototype.OnValueModification = function(msg)
|
|
{
|
|
if (msg.component == "Promotion")
|
|
this.IncreaseXp(0);
|
|
};
|
|
|
|
Engine.RegisterComponentType(IID_Promotion, "Promotion", Promotion);
|