Changeset View
Changeset View
Standalone View
Standalone View
binaries/data/mods/public/simulation/components/Upgrade.js
function Upgrade() {} | function Upgrade() {} | ||||
const UPGRADING_PROGRESS_INTERVAL = 250; | const UPGRADING_PROGRESS_INTERVAL = 250; | ||||
Upgrade.prototype.Schema = | Upgrade.prototype.Schema = | ||||
"<element name='Upgrades'>" + | |||||
"<oneOrMore>" + | "<oneOrMore>" + | ||||
"<element>" + | "<element>" + | ||||
"<anyName />" + | "<anyName/>" + | ||||
"<interleave>" + | "<interleave>" + | ||||
"<element name='Entity' a:help='Entity to upgrade to'>" + | "<element name='Entity' a:help='Entity to upgrade to'>" + | ||||
"<text/>" + | "<text/>" + | ||||
"</element>" + | "</element>" + | ||||
"<optional>" + | "<optional>" + | ||||
"<element name='Icon' a:help='Icon to show in the GUI'>" + | "<element name='Icon' a:help='Icon to show in the GUI'>" + | ||||
"<text/>" + | "<text/>" + | ||||
"</element>" + | "</element>" + | ||||
"</optional>" + | "</optional>" + | ||||
"<optional>" + | "<optional>" + | ||||
"<element name='Variant' a:help='The name of the variant to switch to when upgrading'>" + | "<element name='Variant' a:help='The name of the variant to switch to when upgrading'>" + | ||||
"<text/>" + | "<text/>" + | ||||
"</element>" + | "</element>" + | ||||
"</optional>" + | "</optional>" + | ||||
"<optional>" + | "<optional>" + | ||||
"<element name='Tooltip' a:help='This will be added to the tooltip to help the player choose why to upgrade.'>" + | "<element name='Tooltip' a:help='This will be added to the tooltip to help the player choose why to upgrade.'>" + | ||||
"<text/>" + | "<text/>" + | ||||
"</element>" + | "</element>" + | ||||
"</optional>" + | "</optional>" + | ||||
"<optional>" + | "<optional>" + | ||||
"<element name='Time' a:help='Time required to upgrade this entity, in seconds'>" + | "<element name='Time' a:help='Time required to upgrade this entity, in seconds'>" + | ||||
"<data type='nonNegativeInteger'/>" + | "<data type='nonNegativeInteger'/>" + | ||||
"</element>" + | "</element>" + | ||||
"</optional>" + | "</optional>" + | ||||
"<optional>" + | "<optional>" + | ||||
"<element name='Cost' a:help='Resource cost to upgrade this unit'>" + | "<element name='Cost' a:help='Resource cost to upgrade this unit'>" + | ||||
"<oneOrMore>" + | "<oneOrMore>" + | ||||
"<choice>" + | "<choice>" + | ||||
Resources.BuildSchema("nonNegativeInteger") + | Resources.BuildSchema("nonNegativeInteger") + | ||||
"</choice>" + | "</choice>" + | ||||
"</oneOrMore>" + | "</oneOrMore>" + | ||||
"</element>" + | "</element>" + | ||||
"</optional>" + | "</optional>" + | ||||
"<optional>" + | "<optional>" + | ||||
"<element name='RequiredTechnology' a:help='Define what technology is required for this upgrade'>" + | "<element name='RequiredTechnology' a:help='Define what technology is required for this upgrade'>" + | ||||
"<choice>" + | "<choice>" + | ||||
"<text/>" + | "<text/>" + | ||||
"<empty/>" + | "<empty/>" + | ||||
"</choice>" + | "</choice>" + | ||||
"</element>" + | "</element>" + | ||||
"</optional>" + | "</optional>" + | ||||
"<optional>" + | "<optional>" + | ||||
"<element name='CheckPlacementRestrictions' a:help='Upgrading will check for placement restrictions (nb:GUI only)'><empty/></element>" + | "<element name='CheckPlacementRestrictions' a:help='Upgrading will check for placement restrictions (nb:GUI only)'><empty/></element>" + | ||||
"</optional>" + | "</optional>" + | ||||
"</interleave>" + | "</interleave>" + | ||||
"</element>" + | "</element>" + | ||||
"</oneOrMore>"; | "</oneOrMore>" + | ||||
"</element>" + | |||||
"<optional>" + | |||||
"<element name='AutoUpgrade' a:help='Whether this entity will automatically upgrade itself.'>" + | |||||
"<empty/>" + | |||||
"</element>" + | |||||
"</optional>"; | |||||
Upgrade.prototype.Init = function() | Upgrade.prototype.Init = function() | ||||
{ | { | ||||
this.upgrading = false; | this.upgrading = false; | ||||
this.completed = false; | this.completed = false; | ||||
this.elapsedTime = 0; | this.elapsedTime = 0; | ||||
this.timer = undefined; | this.timer = undefined; | ||||
this.expendedResources = {}; | this.expendedResources = {}; | ||||
this.upgradeTemplates = {}; | this.upgradeTemplates = {}; | ||||
for (let choice in this.template) | for (let choice in this.template.Upgrades) | ||||
{ | { | ||||
let cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity); | let cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity); | ||||
let name = this.template[choice].Entity; | let name = this.template.Upgrades[choice].Entity; | ||||
if (cmpIdentity) | if (cmpIdentity) | ||||
name = name.replace(/\{civ\}/g, cmpIdentity.GetCiv()); | name = name.replace(/\{civ\}/g, cmpIdentity.GetCiv()); | ||||
if (this.upgradeTemplates.name) | if (this.upgradeTemplates.name) | ||||
warn("Upgrade Component: entity " + this.entity + " has two upgrades to the same entity, only the last will be used."); | warn("Upgrade Component: entity " + this.entity + " has two upgrades to the same entity, only the last will be used."); | ||||
this.upgradeTemplates[name] = choice; | this.upgradeTemplates[name] = choice; | ||||
} | } | ||||
this.autoUpgrade = "AutoUpgrade" in this.template; | |||||
}; | }; | ||||
// This will also deal with the "OnDestroy" case. | // This will also deal with the "OnDestroy" case. | ||||
Upgrade.prototype.OnOwnershipChanged = function(msg) | Upgrade.prototype.OnOwnershipChanged = function(msg) | ||||
{ | { | ||||
if (!this.completed) | if (!this.completed) | ||||
this.CancelUpgrade(msg.from); | this.CancelUpgrade(msg.from); | ||||
if (msg.to != INVALID_PLAYER) | if (msg.to == INVALID_PLAYER) | ||||
return; | |||||
Stan: Should you call this if the above is false? | |||||
this.owner = msg.to; | this.owner = msg.to; | ||||
this.CheckAutoUpgrade(); | |||||
}; | }; | ||||
Upgrade.prototype.ChangeUpgradedEntityCount = function(amount) | Upgrade.prototype.ChangeUpgradedEntityCount = function(amount) | ||||
{ | { | ||||
if (!this.IsUpgrading()) | if (!this.IsUpgrading()) | ||||
return; | return; | ||||
let cmpTempMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); | let cmpTempMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); | ||||
Show All 29 Lines | |||||
}; | }; | ||||
Upgrade.prototype.GetUpgrades = function() | Upgrade.prototype.GetUpgrades = function() | ||||
{ | { | ||||
let ret = []; | let ret = []; | ||||
let cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity); | let cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity); | ||||
for (let option in this.template) | for (let option in this.template.Upgrades) | ||||
{ | { | ||||
let choice = this.template[option]; | let choice = this.template.Upgrades[option]; | ||||
let templateName = cmpIdentity ? choice.Entity.replace(/\{civ\}/g, cmpIdentity.GetCiv()) : choice.Entity; | let templateName = cmpIdentity ? choice.Entity.replace(/\{civ\}/g, cmpIdentity.GetCiv()) : choice.Entity; | ||||
let cost = {}; | let cost = {}; | ||||
if (choice.Cost) | if (choice.Cost) | ||||
cost = this.GetResourceCosts(templateName); | cost = this.GetResourceCosts(templateName); | ||||
if (choice.Time) | if (choice.Time) | ||||
cost.time = this.GetUpgradeTime(templateName); | cost.time = this.GetUpgradeTime(templateName); | ||||
Show All 31 Lines | |||||
}; | }; | ||||
Upgrade.prototype.WillCheckPlacementRestrictions = function(template) | Upgrade.prototype.WillCheckPlacementRestrictions = function(template) | ||||
{ | { | ||||
if (!this.upgradeTemplates[template]) | if (!this.upgradeTemplates[template]) | ||||
return undefined; | return undefined; | ||||
// is undefined by default so use X in Y | // is undefined by default so use X in Y | ||||
return "CheckPlacementRestrictions" in this.template[this.upgradeTemplates[template]]; | return "CheckPlacementRestrictions" in this.template.Upgrades[this.upgradeTemplates[template]]; | ||||
}; | }; | ||||
Upgrade.prototype.GetRequiredTechnology = function(templateArg) | Upgrade.prototype.GetRequiredTechnology = function(templateArg) | ||||
{ | { | ||||
let choice = this.upgradeTemplates[templateArg] || templateArg; | let choice = this.upgradeTemplates[templateArg] || templateArg; | ||||
if (this.template[choice].RequiredTechnology) | if (this.template.Upgrades[choice].RequiredTechnology) | ||||
return this.template[choice].RequiredTechnology; | return this.template.Upgrades[choice].RequiredTechnology; | ||||
if (!("RequiredTechnology" in this.template[choice])) | if (!("RequiredTechnology" in this.template.Upgrades[choice])) | ||||
return undefined; | return undefined; | ||||
let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); | let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); | ||||
let cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity); | let cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity); | ||||
let entType = this.template[choice].Entity; | let entType = this.template.Upgrades[choice].Entity; | ||||
if (cmpIdentity) | if (cmpIdentity) | ||||
entType = entType.replace(/\{civ\}/g, cmpIdentity.GetCiv()); | entType = entType.replace(/\{civ\}/g, cmpIdentity.GetCiv()); | ||||
let template = cmpTemplateManager.GetTemplate(entType); | let template = cmpTemplateManager.GetTemplate(entType); | ||||
return template.Identity.RequiredTechnology || undefined; | return template.Identity.RequiredTechnology || undefined; | ||||
}; | }; | ||||
Upgrade.prototype.GetResourceCosts = function(template) | Upgrade.prototype.GetResourceCosts = function(template) | ||||
{ | { | ||||
if (!this.upgradeTemplates[template]) | if (!this.upgradeTemplates[template]) | ||||
return undefined; | return undefined; | ||||
if (this.IsUpgrading() && template == this.GetUpgradingTo()) | if (this.IsUpgrading() && template == this.GetUpgradingTo()) | ||||
return clone(this.expendedResources); | return clone(this.expendedResources); | ||||
let choice = this.upgradeTemplates[template]; | let choice = this.upgradeTemplates[template]; | ||||
if (!this.template[choice].Cost) | if (!this.template.Upgrades[choice].Cost) | ||||
return {}; | return {}; | ||||
let costs = {}; | let costs = {}; | ||||
for (let r in this.template[choice].Cost) | for (let r in this.template.Upgrades[choice].Cost) | ||||
costs[r] = ApplyValueModificationsToEntity("Upgrade/Cost/"+r, +this.template[choice].Cost[r], this.entity); | costs[r] = ApplyValueModificationsToEntity("Upgrade/Cost/"+r, +this.template.Upgrades[choice].Cost[r], this.entity); | ||||
return costs; | return costs; | ||||
}; | }; | ||||
Upgrade.prototype.Upgrade = function(template) | Upgrade.prototype.Upgrade = function(template) | ||||
{ | { | ||||
if (this.IsUpgrading() || !this.upgradeTemplates[template]) | if (this.IsUpgrading() || !this.upgradeTemplates[template]) | ||||
return false; | return false; | ||||
Show All 33 Lines | Upgrade.prototype.CancelUpgrade = function(owner) | ||||
if (cmpPlayer) | if (cmpPlayer) | ||||
cmpPlayer.AddResources(this.expendedResources); | cmpPlayer.AddResources(this.expendedResources); | ||||
this.expendedResources = {}; | this.expendedResources = {}; | ||||
this.ChangeUpgradedEntityCount(-1); | this.ChangeUpgradedEntityCount(-1); | ||||
// Do not update visual actor if the animation didn't change. | // Do not update visual actor if the animation didn't change. | ||||
let choice = this.upgradeTemplates[this.upgrading]; | let choice = this.upgradeTemplates[this.upgrading]; | ||||
if (choice && this.template[choice].Variant) | if (choice && this.template.Upgrades[choice].Variant) | ||||
{ | { | ||||
let cmpVisual = Engine.QueryInterface(this.entity, IID_Visual); | let cmpVisual = Engine.QueryInterface(this.entity, IID_Visual); | ||||
if (cmpVisual) | if (cmpVisual) | ||||
cmpVisual.SelectAnimation("idle", false, 1.0); | cmpVisual.SelectAnimation("idle", false, 1.0); | ||||
} | } | ||||
this.upgrading = false; | this.upgrading = false; | ||||
this.CancelTimer(); | this.CancelTimer(); | ||||
this.SetElapsedTime(0); | this.SetElapsedTime(0); | ||||
}; | }; | ||||
Upgrade.prototype.GetUpgradeTime = function(templateArg) | Upgrade.prototype.GetUpgradeTime = function(templateArg) | ||||
{ | { | ||||
let template = this.upgrading || templateArg; | let template = this.upgrading || templateArg; | ||||
let choice = this.upgradeTemplates[template]; | let choice = this.upgradeTemplates[template]; | ||||
if (!choice) | if (!choice) | ||||
return undefined; | return undefined; | ||||
if (!this.template[choice].Time) | if (!this.template.Upgrades[choice].Time) | ||||
return 0; | return 0; | ||||
return ApplyValueModificationsToEntity("Upgrade/Time", +this.template[choice].Time, this.entity); | return ApplyValueModificationsToEntity("Upgrade/Time", +this.template.Upgrades[choice].Time, this.entity); | ||||
}; | }; | ||||
Upgrade.prototype.GetElapsedTime = function() | Upgrade.prototype.GetElapsedTime = function() | ||||
{ | { | ||||
return this.elapsedTime; | return this.elapsedTime; | ||||
}; | }; | ||||
Upgrade.prototype.GetProgress = function() | Upgrade.prototype.GetProgress = function() | ||||
{ | { | ||||
if (!this.IsUpgrading()) | if (!this.IsUpgrading()) | ||||
return undefined; | return undefined; | ||||
return this.GetUpgradeTime() == 0 ? 1 : Math.min(this.elapsedTime / 1000.0 / this.GetUpgradeTime(), 1.0); | return this.GetUpgradeTime() == 0 ? 1 : Math.min(this.elapsedTime / 1000.0 / this.GetUpgradeTime(), 1.0); | ||||
}; | }; | ||||
Upgrade.prototype.SetElapsedTime = function(time) | Upgrade.prototype.SetElapsedTime = function(time) | ||||
{ | { | ||||
this.elapsedTime = time; | this.elapsedTime = time; | ||||
Engine.PostMessage(this.entity, MT_UpgradeProgressUpdate, null); | Engine.PostMessage(this.entity, MT_UpgradeProgressUpdate, null); | ||||
}; | }; | ||||
Upgrade.prototype.SetUpgradeAnimationVariant = function() | Upgrade.prototype.SetUpgradeAnimationVariant = function() | ||||
{ | { | ||||
let choice = this.upgradeTemplates[this.upgrading]; | let choice = this.upgradeTemplates[this.upgrading]; | ||||
if (!choice || !this.template[choice].Variant) | if (!choice || !this.template.Upgrades[choice].Variant) | ||||
return; | return; | ||||
let cmpVisual = Engine.QueryInterface(this.entity, IID_Visual); | let cmpVisual = Engine.QueryInterface(this.entity, IID_Visual); | ||||
if (!cmpVisual) | if (!cmpVisual) | ||||
return; | return; | ||||
cmpVisual.SelectAnimation(this.template[choice].Variant, false, 1.0); | cmpVisual.SelectAnimation(this.template.Upgrades[choice].Variant, false, 1.0); | ||||
}; | }; | ||||
Upgrade.prototype.UpgradeProgress = function(data, lateness) | Upgrade.prototype.UpgradeProgress = function(data, lateness) | ||||
{ | { | ||||
if (this.elapsedTime/1000.0 < this.GetUpgradeTime()) | if (this.elapsedTime/1000.0 < this.GetUpgradeTime()) | ||||
{ | { | ||||
this.SetElapsedTime(this.GetElapsedTime() + UPGRADING_PROGRESS_INTERVAL + lateness); | this.SetElapsedTime(this.GetElapsedTime() + UPGRADING_PROGRESS_INTERVAL + lateness); | ||||
return; | return; | ||||
} | } | ||||
this.CancelTimer(); | this.CancelTimer(); | ||||
this.completed = true; | this.completed = true; | ||||
this.ChangeUpgradedEntityCount(-1); | this.ChangeUpgradedEntityCount(-1); | ||||
this.expendedResources = {}; | this.expendedResources = {}; | ||||
let newEntity = ChangeEntityTemplate(this.entity, this.upgrading); | let newEntity = ChangeEntityTemplate(this.entity, this.upgrading); | ||||
if (newEntity) | if (newEntity) | ||||
PlaySound("upgraded", newEntity); | PlaySound("upgraded", newEntity); | ||||
}; | }; | ||||
/** | |||||
* Checks for autoupgrade. And upgrades if applicable. | |||||
*/ | |||||
Upgrade.prototype.CheckAutoUpgrade = function() | |||||
{ | |||||
if (this.autoUpgrade) | |||||
this.Upgrade(pickRandom(Object.keys(this.upgradeTemplates))); | |||||
}; | |||||
Engine.RegisterComponentType(IID_Upgrade, "Upgrade", Upgrade); | Engine.RegisterComponentType(IID_Upgrade, "Upgrade", Upgrade); |
Wildfire Games · Phabricator
Should you call this if the above is false?