function EntityLimits() {} EntityLimits.prototype.Schema = "Specifies per category limits on number of entities (buildings or units) that can be created for each player" + "" + "" + "25" + "10" + "1" + "1" + "1" + "5" + "" + "" + "" + "2" + "" + "" + "" + "" + "town_phase" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "tokens" + "" + "" + "" + "" + "" + "" + ""; const TRAINING = "training"; const BUILD = "build"; EntityLimits.prototype.Init = function() { this.limit = {}; this.count = {}; // counts entities which change the limit of the given category this.changers = {}; this.removers = {}; this.classCount = {}; // counts entities with the given class, used in the limit removal this.removedLimit = {}; for (var category in this.template.Limits) { this.limit[category] = +this.template.Limits[category]; this.count[category] = 0; if (category in this.template.LimitChangers) { this.changers[category] = {}; for (var c in this.template.LimitChangers[category]) this.changers[category][c] = +this.template.LimitChangers[category][c]; } if (category in this.template.LimitRemovers) { this.removedLimit[category] = this.limit[category]; // keep a copy of removeable limits for possible restoration this.removers[category] = {}; for (var c in this.template.LimitRemovers[category]) { this.removers[category][c] = this.template.LimitRemovers[category][c]._string.split(/\s+/); if (c === "RequiredClasses") for (var cls of this.removers[category][c]) this.classCount[cls] = 0; } } } }; EntityLimits.prototype.ChangeCount = function(category, value) { if (this.count[category] !== undefined) this.count[category] += value; }; EntityLimits.prototype.GetLimits = function() { return this.limit; }; EntityLimits.prototype.GetCounts = function() { return this.count; }; EntityLimits.prototype.GetLimitChangers = function() { return this.changers; }; EntityLimits.prototype.UpdateLimitsFromTech = function(tech) { for (var category in this.removers) if ("RequiredTechs" in this.removers[category] && this.removers[category]["RequiredTechs"].indexOf(tech) !== -1) this.removers[category]["RequiredTechs"].splice(this.removers[category]["RequiredTechs"].indexOf(tech), 1); this.UpdateLimitRemoval(); }; EntityLimits.prototype.UpdateLimitRemoval = function() { for (var category in this.removers) { var nolimit = true; if ("RequiredTechs" in this.removers[category]) nolimit = !this.removers[category]["RequiredTechs"].length; if (nolimit && "RequiredClasses" in this.removers[category]) for (var cls of this.removers[category]["RequiredClasses"]) nolimit = nolimit && this.classCount[cls] > 0; if (nolimit && this.limit[category] !== undefined) this.limit[category] = undefined; else if (!nolimit && this.limit[category] === undefined) this.limit[category] = this.removedLimit[category]; } }; EntityLimits.prototype.AllowedToCreate = function(limitType, category, count) { // Allow unspecified categories and those with no limit if (this.count[category] === undefined || this.limit[category] === undefined) return true; if (this.count[category] + count > this.limit[category]) { var cmpPlayer = Engine.QueryInterface(this.entity, IID_Player); var notification = { "players": [cmpPlayer.GetPlayerID()], "translateMessage": true, "translateParameters": ["category"], "parameters": {"category": category, "limit": this.limit[category]}, }; if (limitType == BUILD) notification.message = markForTranslation("%(category)s build limit of %(limit)s reached"); else if (limitType == TRAINING) notification.message = markForTranslation("%(category)s training limit of %(limit)s reached"); else { warn("EntityLimits.js: Unknown LimitType " + limitType); notification.message = markForTranslation("%(category)s limit of %(limit)s reached"); } var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); cmpGUIInterface.PushNotification(notification); return false; } return true; }; EntityLimits.prototype.AllowedToBuild = function(category) { // We pass count 0 as the creation of the building has already taken place and // the ownership has been set (triggering OnGlobalOwnershipChanged) return this.AllowedToCreate(BUILD, category, 0); }; EntityLimits.prototype.AllowedToTrain = function(category, count) { return this.AllowedToCreate(TRAINING, category, count); }; EntityLimits.prototype.OnGlobalOwnershipChanged = function(msg) { // check if we are adding or removing an entity from this player var cmpPlayer = Engine.QueryInterface(this.entity, IID_Player); if (!cmpPlayer) { error("EntityLimits component is defined on a non-player entity"); return; } if (msg.from == cmpPlayer.GetPlayerID()) var modifier = -1; else if (msg.to == cmpPlayer.GetPlayerID()) var modifier = 1; else return; // Update entity counts var category = null; var cmpBuildRestrictions = Engine.QueryInterface(msg.entity, IID_BuildRestrictions); if (cmpBuildRestrictions) category = cmpBuildRestrictions.GetCategory(); var cmpTrainingRestrictions = Engine.QueryInterface(msg.entity, IID_TrainingRestrictions); if (cmpTrainingRestrictions) category = cmpTrainingRestrictions.GetCategory(); if (category) this.ChangeCount(category, modifier); // Update entity limits var cmpIdentity = Engine.QueryInterface(msg.entity, IID_Identity); if (!cmpIdentity) return; // foundations shouldn't change the entity limits until they're completed var cmpFoundation = Engine.QueryInterface(msg.entity, IID_Foundation); if (cmpFoundation) return; var classes = cmpIdentity.GetClassesList(); for (var category in this.changers) for (var c in this.changers[category]) if (classes.indexOf(c) >= 0) { if (this.limit[category] != undefined) this.limit[category] += modifier * this.changers[category][c]; if (this.removedLimit[category] != undefined) // update removed limits in case we want to restore it this.removedLimit[category] += modifier * this.changers[category][c]; } for (var category in this.removers) if ("RequiredClasses" in this.removers[category]) for (var cls of this.removers[category]["RequiredClasses"]) if (classes.indexOf(cls) !== -1) this.classCount[cls] += modifier; this.UpdateLimitRemoval(); }; Engine.RegisterComponentType(IID_EntityLimits, "EntityLimits", EntityLimits);