forked from 0ad/0ad
define the limit changing elements together with the limits, so they can be queried by the GUI and the AI. Fixes #2187
This was SVN commit r14408.
This commit is contained in:
parent
040e15ed51
commit
659736301a
@ -1666,14 +1666,16 @@ function getEntityLimitAndCount(playerState, entType)
|
||||
entCategory = template.buildRestrictions.category;
|
||||
var entLimit = undefined;
|
||||
var entCount = undefined;
|
||||
var entLimitChangers = undefined;
|
||||
var canBeAddedCount = undefined;
|
||||
if (entCategory && playerState.entityLimits[entCategory] != null)
|
||||
{
|
||||
entLimit = playerState.entityLimits[entCategory];
|
||||
entCount = playerState.entityCounts[entCategory];
|
||||
entLimitChangers = playerState.entityLimitChangers[entCategory];
|
||||
canBeAddedCount = Math.max(entLimit - entCount, 0);
|
||||
}
|
||||
return [entLimit, entCount, canBeAddedCount];
|
||||
return [entLimit, entCount, canBeAddedCount, entLimitChangers];
|
||||
}
|
||||
|
||||
// Add the unit shown at position to the training queue for all entities in the selection
|
||||
|
@ -139,19 +139,26 @@ function setOverlay(object, value)
|
||||
object.hidden = !value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format entity count/limit message for the tooltip
|
||||
*/
|
||||
function formatLimitString(trainEntLimit, trainEntCount)
|
||||
{
|
||||
if (trainEntLimit == undefined)
|
||||
return "";
|
||||
var text = "\n\nCurrent Count: " + trainEntCount + ", Limit: " + trainEntLimit + ".";
|
||||
if (trainEntCount >= trainEntLimit)
|
||||
text = "[color=\"red\"]" + text + "[/color]";
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format entity count/limit message for the tooltip
|
||||
*/
|
||||
function formatLimitString(trainEntLimit, trainEntCount, trainEntLimitChangers)
|
||||
{
|
||||
if (trainEntLimit == undefined)
|
||||
return "";
|
||||
var text = "\n\nCurrent Count: " + trainEntCount + ", Limit: " + trainEntLimit + ".";
|
||||
if (trainEntCount >= trainEntLimit)
|
||||
text = "[color=\"red\"]" + text + "[/color]";
|
||||
for (var c in trainEntLimitChangers)
|
||||
{
|
||||
if (trainEntLimitChangers[c] > 0)
|
||||
text += "\n" + c + " enlarges the limit with " + trainEntLimitChangers[c] + ".";
|
||||
else if (trainEntLimitChangers[c] < 0)
|
||||
text += "\n" + c + " lessens the limit with " + (-trainEntLimitChangers[c]) + ".";
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format batch training string for the tooltip
|
||||
* Examples:
|
||||
@ -457,15 +464,15 @@ function setupUnitPanel(guiName, usedPanels, unitEntState, playerState, items, c
|
||||
getTrainingBatchStatus(playerState, unitEntState.id, entType, selection);
|
||||
if (Engine.HotkeyIsPressed("session.batchtrain"))
|
||||
trainNum = buildingsCountToTrainFullBatch * fullBatchSize + remainderBatch;
|
||||
|
||||
tooltip += "\n" + getEntityCostTooltip(template, trainNum, unitEntState.id);
|
||||
|
||||
var [trainEntLimit, trainEntCount, canBeAddedCount] =
|
||||
getEntityLimitAndCount(playerState, entType);
|
||||
tooltip += formatLimitString(trainEntLimit, trainEntCount);
|
||||
|
||||
tooltip += "[color=\"255 251 131\"]" + formatBatchTrainingString(buildingsCountToTrainFullBatch, fullBatchSize, remainderBatch) + "[/color]";
|
||||
break;
|
||||
|
||||
tooltip += "\n" + getEntityCostTooltip(template, trainNum, unitEntState.id);
|
||||
|
||||
var [trainEntLimit, trainEntCount, canBeAddedCount, trainEntLimitChangers] =
|
||||
getEntityLimitAndCount(playerState, entType);
|
||||
tooltip += formatLimitString(trainEntLimit, trainEntCount, trainEntLimitChangers);
|
||||
|
||||
tooltip += "[color=\"255 251 131\"]" + formatBatchTrainingString(buildingsCountToTrainFullBatch, fullBatchSize, remainderBatch) + "[/color]";
|
||||
break;
|
||||
|
||||
case RESEARCH:
|
||||
var tooltip = getEntityNamesFormatted(template);
|
||||
@ -492,9 +499,9 @@ function setupUnitPanel(guiName, usedPanels, unitEntState, playerState, items, c
|
||||
tooltip += "\n" + getEntityCostTooltip(template);
|
||||
tooltip += getPopulationBonusTooltip(template);
|
||||
|
||||
var [entLimit, entCount, canBeAddedCount] =
|
||||
var [entLimit, entCount, canBeAddedCount, entLimitChangers] =
|
||||
getEntityLimitAndCount(playerState, entType);
|
||||
tooltip += formatLimitString(entLimit, entCount);
|
||||
tooltip += formatLimitString(entLimit, entCount, entLimitChangers);
|
||||
|
||||
break;
|
||||
|
||||
|
@ -4,18 +4,19 @@ EntityLimits.prototype.Schema =
|
||||
"<a:help>Specifies per category limits on number of entities (buildings or units) that can be created for each player</a:help>" +
|
||||
"<a:example>" +
|
||||
"<Limits>" +
|
||||
"<CivilCentre/>" +
|
||||
"<DefenseTower>25</DefenseTower>" +
|
||||
"<Fortress>10</Fortress>" +
|
||||
"<Wonder>1</Wonder>" +
|
||||
"<Hero>1</Hero>" +
|
||||
"<Apadana>1</Apadana>" +
|
||||
"<Monument>5</Monument>" +
|
||||
"<DefenseTower>25</DefenseTower>" +
|
||||
"<Fortress>10</Fortress>" +
|
||||
"<Wonder>1</Wonder>" +
|
||||
"<Hero>1</Hero>" +
|
||||
"<Apadana>1</Apadana>" +
|
||||
"<Monument>5</Monument>" +
|
||||
"</Limits>" +
|
||||
"<LimitChangers>" +
|
||||
"<Monument>" +
|
||||
"<CivCentre>2</CivCentre>" +
|
||||
"</Monument>" +
|
||||
"</LimitChangers>" +
|
||||
"</a:example>" +
|
||||
"<element name='LimitMultiplier'>" +
|
||||
"<ref name='positiveDecimal'/>" +
|
||||
"</element>" +
|
||||
"<element name='Limits'>" +
|
||||
"<zeroOrMore>" +
|
||||
"<element a:help='Specifies a category of building/unit on which to apply this limit. See BuildRestrictions/TrainingRestrictions for possible categories'>" +
|
||||
@ -23,8 +24,22 @@ EntityLimits.prototype.Schema =
|
||||
"<data type='integer'/>" +
|
||||
"</element>" +
|
||||
"</zeroOrMore>" +
|
||||
"</element>" +
|
||||
"<element name='LimitChangers'>" +
|
||||
"<zeroOrMore>" +
|
||||
"<element a:help='Specifies a category of building/unit on which to apply this limit. See BuildRestrictions/TrainingRestrictions for possible categories'>" +
|
||||
"<anyName />" +
|
||||
"<zeroOrMore>" +
|
||||
"<element a:help='Specifies the class that changes the entity limit'>" +
|
||||
"<anyName />" +
|
||||
"<data type='integer'/>" +
|
||||
"</element>" +
|
||||
"</zeroOrMore>" +
|
||||
"</element>" +
|
||||
"</zeroOrMore>" +
|
||||
"</element>";
|
||||
|
||||
|
||||
/*
|
||||
* TODO: Use an inheriting player_{civ}.xml template for civ-specific limits
|
||||
*/
|
||||
@ -36,50 +51,30 @@ EntityLimits.prototype.Init = function()
|
||||
{
|
||||
this.limit = {};
|
||||
this.count = {};
|
||||
this.changers = {};
|
||||
for (var category in this.template.Limits)
|
||||
{
|
||||
this.limit[category] = +this.template.Limits[category];
|
||||
this.count[category] = 0;
|
||||
if (!(category in this.template.LimitChangers))
|
||||
continue;
|
||||
this.changers[category] = {};
|
||||
for (var c in this.template.LimitChangers[category])
|
||||
this.changers[category][c] = +this.template.LimitChangers[category][c];
|
||||
}
|
||||
};
|
||||
|
||||
EntityLimits.prototype.IncreaseLimit = function(category, value)
|
||||
EntityLimits.prototype.ChangeLimit = function(category, value)
|
||||
{
|
||||
if (!this.limit[category])
|
||||
this.limit[category] = 0;
|
||||
this.limit[category] += value;
|
||||
};
|
||||
|
||||
EntityLimits.prototype.DecreaseLimit = function(category, value)
|
||||
{
|
||||
if (!this.limit[category])
|
||||
this.limit[category] = 0;
|
||||
this.limit[category] -= value;
|
||||
|
||||
};
|
||||
|
||||
EntityLimits.prototype.IncreaseCount = function(category, value)
|
||||
EntityLimits.prototype.ChangeCount = function(category, value)
|
||||
{
|
||||
if (this.count[category] !== undefined)
|
||||
this.count[category] += value;
|
||||
};
|
||||
|
||||
EntityLimits.prototype.DecreaseCount = function(category, value)
|
||||
{
|
||||
if (this.count[category] !== undefined)
|
||||
this.count[category] -= value;
|
||||
};
|
||||
|
||||
EntityLimits.prototype.IncrementCount = function(category)
|
||||
{
|
||||
this.IncreaseCount(category, 1);
|
||||
};
|
||||
|
||||
EntityLimits.prototype.DecrementCount = function(category)
|
||||
{
|
||||
this.DecreaseCount(category, 1);
|
||||
};
|
||||
|
||||
EntityLimits.prototype.GetLimits = function()
|
||||
{
|
||||
return this.limit;
|
||||
@ -90,11 +85,13 @@ EntityLimits.prototype.GetCounts = function()
|
||||
return this.count;
|
||||
};
|
||||
|
||||
EntityLimits.prototype.GetLimitChangers = function()
|
||||
{
|
||||
return this.changers;
|
||||
};
|
||||
|
||||
EntityLimits.prototype.AllowedToCreate = function(limitType, category, count)
|
||||
{
|
||||
// TODO: The UI should reflect this before the user tries to place the building,
|
||||
// since the limits are independent of placement location
|
||||
|
||||
// Allow unspecified categories and those with no limit
|
||||
if (this.count[category] === undefined || this.limit[category] === undefined)
|
||||
return true;
|
||||
@ -116,9 +113,6 @@ EntityLimits.prototype.AllowedToCreate = function(limitType, category, count)
|
||||
|
||||
EntityLimits.prototype.AllowedToBuild = function(category)
|
||||
{
|
||||
// TODO: The UI should reflect this before the user tries to place the building,
|
||||
// since the limits are independent of placement location
|
||||
|
||||
// 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);
|
||||
@ -130,8 +124,22 @@ EntityLimits.prototype.AllowedToTrain = function(category, count)
|
||||
};
|
||||
|
||||
EntityLimits.prototype.OnGlobalOwnershipChanged = function(msg)
|
||||
{
|
||||
// This automatically updates entity counts
|
||||
{
|
||||
// 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)
|
||||
@ -140,13 +148,17 @@ EntityLimits.prototype.OnGlobalOwnershipChanged = function(msg)
|
||||
if (cmpTrainingRestrictions)
|
||||
category = cmpTrainingRestrictions.GetCategory();
|
||||
if (category)
|
||||
{
|
||||
var playerID = (Engine.QueryInterface(this.entity, IID_Player)).GetPlayerID();
|
||||
if (msg.from == playerID)
|
||||
this.DecrementCount(category);
|
||||
if (msg.to == playerID)
|
||||
this.IncrementCount(category);
|
||||
}
|
||||
this.ChangeCount(category,modifier);
|
||||
|
||||
// Update entity limits
|
||||
var cmpIdentity = Engine.QueryInterface(msg.entity, IID_Identity);
|
||||
if (!cmpIdentity)
|
||||
return;
|
||||
var classes = cmpIdentity.GetClassesList();
|
||||
for (var category in this.changers)
|
||||
for (var c in this.changers[category])
|
||||
if (classes.indexOf(c) >= 0)
|
||||
this.ChangeLimit(category, modifier * this.changers[category][c]);
|
||||
};
|
||||
|
||||
Engine.RegisterComponentType(IID_EntityLimits, "EntityLimits", EntityLimits);
|
||||
|
@ -1,58 +0,0 @@
|
||||
function EntityLimitsChanger() {}
|
||||
|
||||
EntityLimitsChanger.prototype.Schema =
|
||||
"<oneOrMore>" +
|
||||
"<element a:help='Take as name the name of the category, and as value the number you want to increase the limit with.'>" +
|
||||
"<anyName/>" +
|
||||
"<data type='integer'/>" +
|
||||
"</element>" +
|
||||
"</oneOrMore>";
|
||||
|
||||
EntityLimitsChanger.prototype.init = function()
|
||||
{
|
||||
};
|
||||
|
||||
EntityLimitsChanger.prototype.OnOwnershipChanged = function(msg)
|
||||
{
|
||||
if (!this.changes)
|
||||
{
|
||||
this.changes = {};
|
||||
for (var cat in this.template)
|
||||
this.changes[cat] = ApplyValueModificationsToEntity("EntityLimitsChanger/Value", +this.template[cat], this.entity);
|
||||
}
|
||||
|
||||
if (msg.from > -1)
|
||||
{
|
||||
var cmpEntityLimits = QueryPlayerIDInterface(msg.from, IID_EntityLimits);
|
||||
if (cmpEntityLimits)
|
||||
for (var cat in this.changes)
|
||||
cmpEntityLimits.DecreaseLimit(cat, this.changes[cat]);
|
||||
}
|
||||
|
||||
if (msg.to > -1)
|
||||
{
|
||||
var cmpEntityLimits = QueryPlayerIDInterface(msg.to, IID_EntityLimits);
|
||||
if (cmpEntityLimits)
|
||||
for (var cat in this.changes)
|
||||
cmpEntityLimits.IncreaseLimit(cat, this.changes[cat]);
|
||||
}
|
||||
}
|
||||
|
||||
EntityLimitsChanger.prototype.OnValueModification = function(msg)
|
||||
{
|
||||
if (msg.component != "EntityLimitsChanger")
|
||||
return;
|
||||
|
||||
var cmpEntityLimits = Engine.QueryOwnerInterface(this.entity, IID_EntityLimits);
|
||||
if (!cmpEntityLimits)
|
||||
return;
|
||||
|
||||
for (var cat in this.changes)
|
||||
{
|
||||
cmpEntityLimits.DecreaseLimit(cat, this.changes[cat]);
|
||||
this.changes[cat] = ApplyValueModificationsToEntity("EntityLimitsChanger/Value", +this.template[cat], this.entity);
|
||||
cmpEntityLimits.IncreaseLimit(cat, this.changes[cat]);
|
||||
}
|
||||
};
|
||||
|
||||
Engine.RegisterComponentType(IID_EntityLimitsChanger, "EntityLimitsChanger", EntityLimitsChanger);
|
@ -94,6 +94,7 @@ GuiInterface.prototype.GetSimulationState = function(player)
|
||||
"isEnemy": enemies,
|
||||
"entityLimits": cmpPlayerEntityLimits.GetLimits(),
|
||||
"entityCounts": cmpPlayerEntityLimits.GetCounts(),
|
||||
"entityLimitChangers": cmpPlayerEntityLimits.GetLimitChangers(),
|
||||
"techModifications": cmpTechnologyManager.GetTechModifications(),
|
||||
"researchQueued": cmpTechnologyManager.GetQueuedResearch(),
|
||||
"researchStarted": cmpTechnologyManager.GetStartedResearch(),
|
||||
|
@ -255,7 +255,7 @@ ProductionQueue.prototype.AddBatch = function(templateName, type, count, metadat
|
||||
{
|
||||
var unitCategory = template.TrainingRestrictions.Category;
|
||||
var cmpPlayerEntityLimits = QueryOwnerInterface(this.entity, IID_EntityLimits);
|
||||
cmpPlayerEntityLimits.IncreaseCount(unitCategory, count);
|
||||
cmpPlayerEntityLimits.ChangeCount(unitCategory, count);
|
||||
}
|
||||
|
||||
this.queue.push({
|
||||
@ -362,7 +362,7 @@ ProductionQueue.prototype.RemoveBatch = function(id)
|
||||
{
|
||||
var unitCategory = template.TrainingRestrictions.Category;
|
||||
var cmpPlayerEntityLimits = QueryPlayerIDInterface(item.player, IID_EntityLimits);
|
||||
cmpPlayerEntityLimits.DecreaseCount(unitCategory, item.count);
|
||||
cmpPlayerEntityLimits.ChangeCount(unitCategory, -item.count);
|
||||
}
|
||||
}
|
||||
|
||||
@ -508,7 +508,7 @@ ProductionQueue.prototype.SpawnUnits = function(templateName, count, metadata)
|
||||
{
|
||||
var unitCategory = cmpTrainingRestrictions.GetCategory();
|
||||
var cmpPlayerEntityLimits = QueryOwnerInterface(this.entity, IID_EntityLimits);
|
||||
cmpPlayerEntityLimits.DecrementCount(unitCategory);
|
||||
cmpPlayerEntityLimits.ChangeCount(unitCategory,-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
Engine.RegisterInterface("EntityLimitsChanger");
|
@ -14,7 +14,6 @@
|
||||
<AlertnessMax>8</AlertnessMax>
|
||||
</BattleDetection>
|
||||
<EntityLimits>
|
||||
<LimitMultiplier>1.0</LimitMultiplier>
|
||||
<Limits>
|
||||
<DefenseTower>30</DefenseTower>
|
||||
<Fortress>10</Fortress>
|
||||
@ -30,6 +29,14 @@
|
||||
<Library>1</Library>
|
||||
<Lighthouse>1</Lighthouse>
|
||||
</Limits>
|
||||
<LimitChangers>
|
||||
<WarDog>
|
||||
<Kennel>10</Kennel>
|
||||
</WarDog>
|
||||
<Pillar>
|
||||
<Ashoka>5</Ashoka>
|
||||
</Pillar>
|
||||
</LimitChangers>
|
||||
</EntityLimits>
|
||||
<Player/>
|
||||
<StatisticsTracker/>
|
||||
|
@ -18,9 +18,6 @@
|
||||
<stone>50</stone>
|
||||
</Resources>
|
||||
</Cost>
|
||||
<EntityLimitsChanger>
|
||||
<WarDog>10</WarDog>
|
||||
</EntityLimitsChanger>
|
||||
<Footprint>
|
||||
<Square width="8.0" depth="7.0"/>
|
||||
<Height>5.0</Height>
|
||||
@ -34,7 +31,8 @@
|
||||
<Civ>brit</Civ>
|
||||
<GenericName>Special Building</GenericName>
|
||||
<SpecificName>Kennel</SpecificName>
|
||||
<Tooltip>Train Celtic war dogs. One kennel can only house 10 dogs.</Tooltip>
|
||||
<Classes>Kennel</Classes>
|
||||
<Tooltip>Train Celtic war dogs.</Tooltip>
|
||||
<Icon>structures/kennel.png</Icon>
|
||||
<RequiredTechnology>phase_town</RequiredTechnology>
|
||||
</Identity>
|
||||
|
@ -18,9 +18,6 @@
|
||||
<stone>50</stone>
|
||||
</Resources>
|
||||
</Cost>
|
||||
<EntityLimitsChanger>
|
||||
<WarDog>10</WarDog>
|
||||
</EntityLimitsChanger>
|
||||
<Footprint>
|
||||
<Square width="8.0" depth="7.0"/>
|
||||
<Height>5.0</Height>
|
||||
@ -34,7 +31,8 @@
|
||||
<Civ>celt</Civ>
|
||||
<GenericName>Special Building</GenericName>
|
||||
<SpecificName>Kennel</SpecificName>
|
||||
<Tooltip>Train Celtic war dogs. One kennel can only house 10 dogs.</Tooltip>
|
||||
<Classes>Kennel</Classes>
|
||||
<Tooltip>Train Celtic war dogs.</Tooltip>
|
||||
<Icon>structures/kennel.png</Icon>
|
||||
<RequiredTechnology>phase_town</RequiredTechnology>
|
||||
</Identity>
|
||||
|
@ -26,7 +26,7 @@
|
||||
<GenericName>Edict Pillar of Ashoka</GenericName>
|
||||
<SpecificName>Śāsana Stambha Aśokā</SpecificName>
|
||||
<Icon>structures/monument.png</Icon>
|
||||
<Tooltip>The famous pillar of Ashoka. Can only be build when the hero Ashoka is alive. Currently a useless structure.</Tooltip>
|
||||
<Tooltip>The famous pillar of Ashoka. Currently a useless structure.</Tooltip>
|
||||
<History>.</History>
|
||||
</Identity>
|
||||
<Obstruction>
|
||||
|
@ -20,9 +20,6 @@
|
||||
<metal>100</metal>
|
||||
</Resources>
|
||||
</Cost>
|
||||
<EntityLimitsChanger>
|
||||
<Pillar>5</Pillar>
|
||||
</EntityLimitsChanger>
|
||||
<Footprint replace="">
|
||||
<Square width="6.0" depth="12.0"/>
|
||||
<Height>5.0</Height>
|
||||
@ -34,6 +31,7 @@
|
||||
<Civ>maur</Civ>
|
||||
<GenericName>Ashoka the Great</GenericName>
|
||||
<SpecificName>Aśoka Devānāmpriya</SpecificName>
|
||||
<Classes>Ashoka</Classes>
|
||||
<Icon>units/maur_hero_ashoka.png</Icon>
|
||||
<Tooltip>Hero Chariot Archer.
|
||||
Hero Aura: TBD.
|
||||
|
Loading…
Reference in New Issue
Block a user