Summary screen. Closes #638.

This was SVN commit r8576.
This commit is contained in:
fcxSanya 2010-11-12 22:24:49 +00:00
parent 6c3368886b
commit 245f29b798
20 changed files with 586 additions and 30 deletions

View File

@ -5,5 +5,6 @@
<include>common/sprite1.xml</include>
<include>common/init.xml</include>
<include>summary/summary.xml</include>
<include>summary/sprites.xml</include>
<include>common/global.xml</include>
</page>

View File

@ -117,8 +117,11 @@ function leaveGame()
stopMusic();
endGame();
Engine.SwitchGuiPage("page_summary.xml", { "gameResult" : gameResult });
Engine.SwitchGuiPage("page_summary.xml",
{ "gameResult" : gameResult,
"timeElapsed" : simState.timeElapsed,
"playerStates": simState.players
});
}
// Return some data that we'll use when hotloading this file after changes

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<sprites>
<sprite name="bgInfoHeading">
<image backcolor="0 0 0 150" size="0 0 100% 100%" />
</sprite>
<sprite name="bgInfoBox">
<image backcolor="120 70 0 100" size="0 0 100% 100%" />
</sprite>
</sprites>

View File

@ -1,4 +1,176 @@
// Max player slots for any map (should read from config)
const MAX_SLOTS = 8;
var panelNames = [ 'unitsBuildingsPanel', 'resourcesPanel' ];
var panelButtonNames = [ 'unitsBuildingsPanelButton', 'resourcesPanelButton' ];
/**
* @param time Time period in milliseconds (integer)
* @return String representing time period
*/
function timeToString(time)
{
var hours = Math.floor(time / 1000 / 60 / 60);
var minutes = Math.floor(time / 1000 / 60) % 60;
var seconds = Math.floor(time / 1000) % 60;
return hours + ':' + (minutes < 10 ? '0' + minutes : minutes) + ':' + (seconds < 10 ? '0' + seconds : seconds);
}
/**
* Select active panel
* @param panelNumber Number of panel, which should get active state (integer)
*/
function selectPanel(panelNumber)
{
for (var i = 0; i < panelNames.length; i++)
{
if (i != panelNumber)
{
getGUIObjectByName(panelNames[i]).hidden = true;
getGUIObjectByName(panelButtonNames[i]).sprite = "bgInfoHeading";
}
else
{
getGUIObjectByName(panelNames[i]).hidden = false;
getGUIObjectByName(panelButtonNames[i]).sprite = "bgInfoBox";
}
}
}
function init(data)
{
getGUIObjectByName("timeElapsed").caption = "Time elapsed: " + timeToString(data.timeElapsed);
getGUIObjectByName("summaryText").caption = data.gameResult;
//Space player boxes
var boxSpacing = 32;
for (var i = 0; i < panelNames.length; ++i)
for (var j = 0; j < MAX_SLOTS; ++j)
{
var box = getGUIObjectByName("playerBox"+i+"["+j+"]");
var boxSize = box.size;
var h = boxSize.bottom - boxSize.top;
boxSize.top = j * boxSpacing;
boxSize.bottom = j * boxSpacing + h;
box.size = boxSize;
}
// TODO set mapPlayers as playerCounters.length
var maxPlayers = data.playerStates.length - 1;
// align headers
var left = 50;
var width = 100;
getGUIObjectByName("playerNameHeading").size = left + " 26 " + (left + width) + " 100%"; left += width;
getGUIObjectByName("unitsTrainedHeading").size = left + " 16 " + (left + width) + " 100%"; left += width;
getGUIObjectByName("unitsLostHeading").size = left + " 16 " + (left + width) + " 100%"; left += width;
getGUIObjectByName("enemyUnitsKilledHeading").size = left + " 16 " + (left + width) + " 100%"; left += width;
getGUIObjectByName("buildingsConstructedHeading").size = left + " 16 " + (left + width) + " 100%"; left += width;
getGUIObjectByName("buildingsLostHeading").size = left + " 16 " + (left + width) + " 100%"; left += width;
getGUIObjectByName("enemyBuildingsDestroyedHeading").size = left + " 6 " + (left + width) + " 100%"; left += width;
getGUIObjectByName("civCentresBuiltHeading").size = left + " 16 " + (left + width) + " 100%"; left += width;
getGUIObjectByName("enemyCivCentresDestroyedHeading").size = left + " 6 " + (left + width) + " 100%"; left += width;
var left = 50;
getGUIObjectByName("playerName2Heading").size = left + " 26 " + (left + width) + " 100%"; left += width;
getGUIObjectByName("foodGatheredHeading").size = left + " 16 " + (left + width) + " 100%"; left += width;
getGUIObjectByName("vegetarianRatioHeading").size = left + " 16 " + (left + width) + " 100%"; left += width;
getGUIObjectByName("woodGatheredHeading").size = left + " 16 " + (left + width) + " 100%"; left += width;
getGUIObjectByName("metalGatheredHeading").size = left + " 16 " + (left + width) + " 100%"; left += width;
getGUIObjectByName("stoneGatheredHeading").size = left + " 16 " + (left + width) + " 100%"; left += width;
// Show counters
for (var i = 0; i < MAX_SLOTS; ++i)
{
if (i < maxPlayers)
{
var playerState = data.playerStates[i+1];
for (var k = 0; k < panelNames.length; ++k)
{
var playerBox = getGUIObjectByName("playerBox"+k+"["+i+"]");
playerBox.hidden = false;
var colourString = "colour: "
+ Math.floor(playerState.colour.r * 255) + " "
+ Math.floor(playerState.colour.g * 255) + " "
+ Math.floor(playerState.colour.b * 255);
playerBox.sprite = colourString + " 32";
var playerColourBox = getGUIObjectByName("playerColourBox"+k+"["+i+"]");
playerColourBox.sprite = colourString + " 255";
var playerName = getGUIObjectByName("playerName"+k+"["+i+"]");
playerName.caption = playerState.name;
}
var unitsTrained = getGUIObjectByName("unitsTrained["+i+"]");
var unitsLost = getGUIObjectByName("unitsLost["+i+"]");
var enemyUnitsKilled = getGUIObjectByName("enemyUnitsKilled["+i+"]");
var buildingsConstructed = getGUIObjectByName("buildingsConstructed["+i+"]");
var buildingsLost = getGUIObjectByName("buildingsLost["+i+"]");
var enemyBuildingsDestroyed = getGUIObjectByName("enemyBuildingsDestroyed["+i+"]");
var civCentresBuilt = getGUIObjectByName("civCentresBuilt["+i+"]");
var enemyCivCentresDestroyed = getGUIObjectByName("enemyCivCentresDestroyed["+i+"]");
var foodGathered = getGUIObjectByName("foodGathered["+i+"]");
var vegetarianRatio = getGUIObjectByName("vegetarianRatio["+i+"]");
var woodGathered = getGUIObjectByName("woodGathered["+i+"]");
var metalGathered = getGUIObjectByName("metalGathered["+i+"]");
var stoneGathered = getGUIObjectByName("stoneGathered["+i+"]");
// align counters
var left = 140;
var width = 100;
unitsTrained.size = left + " 2 " + (left + width) + " 100%"; left += width;
unitsLost.size = left + " 2 " + (left + width) + " 100%"; left += width;
enemyUnitsKilled.size = left + " 2 " + (left + width) + " 100%"; left += width;
buildingsConstructed.size = left + " 2 " + (left + width) + " 100%"; left += width;
buildingsLost.size = left + " 2 " + (left + width) + " 100%"; left += width;
enemyBuildingsDestroyed.size = left + " 2 " + (left + width) + " 100%"; left += width;
civCentresBuilt.size = left + " 2 " + (left + width) + " 100%"; left += width;
enemyCivCentresDestroyed.size = left + " 2 " + (left + width) + " 100%"; left += width;
var size = getGUIObjectByName("playerBox0["+i+"]").size;
size.right = left + 10;
getGUIObjectByName("playerBox0["+i+"]").size = size;
var left = 140;
foodGathered.size = left + " 2 " + (left + width) + " 100%"; left += width;
vegetarianRatio.size = left + " 2 " + (left + width) + " 100%"; left += width;
woodGathered.size = left + " 2 " + (left + width) + " 100%"; left += width;
metalGathered.size = left + " 2 " + (left + width) + " 100%"; left += width;
stoneGathered.size = left + " 2 " + (left + width) + " 100%"; left += width;
var size = getGUIObjectByName("playerBox1["+i+"]").size;
size.right = left + 10;
getGUIObjectByName("playerBox1["+i+"]").size = size;
// display counters
unitsTrained.caption = playerState.statistics.unitsTrained;
unitsLost.caption = playerState.statistics.unitsLost;
enemyUnitsKilled.caption = playerState.statistics.enemyUnitsKilled;
buildingsConstructed.caption = playerState.statistics.buildingsConstructed;
buildingsLost.caption = playerState.statistics.buildingsLost;
enemyBuildingsDestroyed.caption = playerState.statistics.enemyBuildingsDestroyed;
civCentresBuilt.caption = playerState.statistics.civCentresBuilt;
enemyCivCentresDestroyed.caption = playerState.statistics.enemyCivCentresDestroyed;
foodGathered.caption = playerState.statistics.resourcesGathered.food;
vegetarianRatio.caption = Math.floor(playerState.statistics.resourcesGathered.food > 0 ?
(playerState.statistics.resourcesGathered.vegetarianFood / playerState.statistics.resourcesGathered.food) * 100 : 0) + "%";
woodGathered.caption = playerState.statistics.resourcesGathered.wood;
metalGathered.caption = playerState.statistics.resourcesGathered.metal;
stoneGathered.caption = playerState.statistics.resourcesGathered.stone;
}
else
{
// hide player boxes
for (var k = 0; k < panelNames.length; ++k)
{
var playerBox = getGUIObjectByName("playerBox"+k+"["+i+"]");
playerBox.hidden = true;
}
}
}
}

View File

@ -11,20 +11,132 @@
<object type="image" sprite="bkFillBlack">
<object type="image"
style="wheatWindowGranite"
style="wheatWindow"
size="25 35 100%-25 100%-25"
>
<object type="button" style="wheatWindowTitleBar">
Summary
</object>
<object name="summaryText"
type="text"
size="50 50 100%-50 100%-200"
font="serif-16"
text_align="center"
text_valign="center"
/>
<object type="image" sprite="bgInfoHeading" size="0 10 100% 40">
<object
name="summaryText"
type="text"
size="50 0 100%-50 30"
font="serif-bold-18"
textcolor="255 255 255"
text_align="center"
/>
<object
name="timeElapsed"
type="text"
size="100%-200 0 100%-10 30"
font="serif-16"
textcolor="255 255 255"
text_align="center"
/>
</object>
<object name="unitsBuildingsPanelButton" type="button" sprite="bgInfoBox" text_align="center" size="10 75 160 101">
<action on="Press">selectPanel(0);</action>
Units/buildings
</object>
<object name="resourcesPanelButton" type="button" sprite="bgInfoHeading" text_align="center" size="160 75 310 101">
<action on="Press">selectPanel(1);</action>
Resources
</object>
<object name="unitsBuildingsPanel" type="image" sprite="bgInfoBox" size="10 100 100%-10 100%-50">
<object size="0 0 100% 100%-50">
<object name="playerNameHeading" type="text" text_align="left" font="serif-bold-14" >
Player name
</object>
<object name="unitsTrainedHeading" type="text" text_align="center" font="serif-bold-14" >
Units&#10;trained
</object>
<object name="unitsLostHeading" type="text" text_align="center" font="serif-bold-14" >
Units&#10;lost
</object>
<object name="enemyUnitsKilledHeading" type="text" text_align="center" font="serif-bold-14" >
Enemy units&#10;killed
</object>
<object name="buildingsConstructedHeading" type="text" text_align="center" font="serif-bold-14" >
Buildings&#10;constructed
</object>
<object name="buildingsLostHeading" type="text" text_align="center" font="serif-bold-14" >
Buildings&#10;lost
</object>
<object name="enemyBuildingsDestroyedHeading" type="text" text_align="center" font="serif-bold-14" >
Enemy&#10;buildings&#10;destroyed
</object>
<object name="civCentresBuiltHeading" type="text" text_align="center" font="serif-bold-14" >
Civ centres&#10;built
</object>
<object name="enemyCivCentresDestroyedHeading" type="text" text_align="center" font="serif-bold-14" >
Enemy&#10;civ centres&#10;destroyed
</object>
</object>
<object size="0 65 100% 100%-50">
<repeat count="8">
<object type="image" name="playerBox0[n]" size="10 0 10 30" hidden="true">
<object name="playerColourBox0[n]" type="image" size="10 4 30 24" />
<object name="playerName0[n]" type="text" text_align="left" size="40 2 140 100%" />
<object name="unitsTrained[n]" type="text" text_align="center" />
<object name="unitsLost[n]" type="text" text_align="center" />
<object name="enemyUnitsKilled[n]" type="text" text_align="center" />
<object name="buildingsConstructed[n]" type="text" text_align="center" />
<object name="buildingsLost[n]" type="text" text_align="center" />
<object name="enemyBuildingsDestroyed[n]" type="text" text_align="center" />
<object name="civCentresBuilt[n]" type="text" text_align="center" />
<object name="enemyCivCentresDestroyed[n]" type="text" text_align="center" />
</object>
</repeat>
</object>
</object>
<object name="resourcesPanel" type="image" sprite="bgInfoBox" size="10 100 100%-10 100%-50" hidden="true">
<object size="0 0 100% 100%-50">
<object name="playerName2Heading" type="text" text_align="left" font="serif-bold-14" >
Player name
</object>
<object name="foodGatheredHeading" type="text" text_align="center" font="serif-bold-14" >
Food&#10;gathered
</object>
<object name="vegetarianRatioHeading" type="text" text_align="center" font="serif-bold-14" >
Vegetarian&#10;ratio
</object>
<object name="woodGatheredHeading" type="text" text_align="center" font="serif-bold-14" >
Wood&#10;gathered
</object>
<object name="metalGatheredHeading" type="text" text_align="center" font="serif-bold-14" >
Metal&#10;gathered
</object>
<object name="stoneGatheredHeading" type="text" text_align="center" font="serif-bold-14" >
Stone&#10;gathered
</object>
</object>
<object size="0 65 100% 100%-50">
<repeat count="8">
<object type="image" name="playerBox1[n]" size="10 0 10 30" hidden="true">
<object name="playerColourBox1[n]" type="image" size="10 4 30 24" />
<object name="playerName1[n]" type="text" text_align="left" size="40 2 140 100%" />
<object name="foodGathered[n]" type="text" text_align="center" />
<object name="vegetarianRatio[n]" type="text" text_align="center" />
<object name="woodGathered[n]" type="text" text_align="center" />
<object name="metalGathered[n]" type="text" text_align="center" />
<object name="stoneGathered[n]" type="text" text_align="center" />
</object>
</repeat>
</object>
</object>
<object type="button" style="wheatButton" size="100%-150 100%-40 100% 100%">
Main menu

View File

@ -33,7 +33,7 @@ Armour.prototype.TakeDamage = function(hack, pierce, crush)
// Reduce health
var cmpHealth = Engine.QueryInterface(this.entity, IID_Health);
cmpHealth.Reduce(total);
return cmpHealth.Reduce(total);
};
Armour.prototype.GetArmourStrengths = function()

View File

@ -203,8 +203,21 @@ Attack.prototype.PerformAttack = function(type, target)
// TODO: charge attacks (need to design how they work)
};
/**
* Called when some units kills something (another unit, building, animal etc)
* update player statistics only for now
*/
Attack.prototype.TargetKilled = function(killerEntity, targetEntity)
{
var cmpKillerPlayerStatisticsTracker = QueryOwnerInterface(killerEntity, IID_StatisticsTracker);
if (cmpKillerPlayerStatisticsTracker) cmpKillerPlayerStatisticsTracker.KilledEntity(targetEntity);
var cmpTargetPlayerStatisticsTracker = QueryOwnerInterface(targetEntity, IID_StatisticsTracker);
if (cmpTargetPlayerStatisticsTracker) cmpTargetPlayerStatisticsTracker.LostEntity(targetEntity);
}
// Inflict damage on the target
/**
* Inflict damage on the target
*/
Attack.prototype.CauseDamage = function(data)
{
var strengths = this.GetAttackStrengths(data.type);
@ -212,7 +225,12 @@ Attack.prototype.CauseDamage = function(data)
var cmpDamageReceiver = Engine.QueryInterface(data.target, IID_DamageReceiver);
if (!cmpDamageReceiver)
return;
cmpDamageReceiver.TakeDamage(strengths.hack, strengths.pierce, strengths.crush);
var targetState = cmpDamageReceiver.TakeDamage(strengths.hack, strengths.pierce, strengths.crush);
// if target killed pick up loot and credit experience
if (targetState.killed == true)
{
this.TargetKilled(this.entity, data.target);
}
Engine.PostMessage(data.target, MT_Attacked,
{ "attacker": this.entity, "target": data.target });

View File

@ -107,7 +107,13 @@ Foundation.prototype.Build = function(builderEnt, work)
var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
var cmpBuildingOwnership = Engine.QueryInterface(building, IID_Ownership);
cmpBuildingOwnership.SetOwner(cmpOwnership.GetOwner());
var cmpPlayerStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker);
cmpPlayerStatisticsTracker.IncreaseConstructedBuildingsCounter();
var cmpIdentity = Engine.QueryInterface(building, IID_Identity);
if (cmpIdentity.GetClassesList().indexOf("CivCentre") != -1) cmpPlayerStatisticsTracker.IncreaseBuiltCivCentresCounter();
var cmpHealth = Engine.QueryInterface(this.entity, IID_Health);
var cmpBuildingHealth = Engine.QueryInterface(building, IID_Health);
cmpBuildingHealth.SetHitpoints(cmpHealth.GetHitpoints());

View File

@ -20,15 +20,20 @@ GuiInterface.prototype.Init = function()
GuiInterface.prototype.GetSimulationState = function(player)
{
var ret = {
"players": []
"players": [],
"timeElapsed": 0
};
var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
ret.timeElapsed = cmpTimer.GetTime();
var cmpPlayerMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
var n = cmpPlayerMan.GetNumPlayers();
for (var i = 0; i < n; ++i)
{
var playerEnt = cmpPlayerMan.GetPlayerByID(i);
var cmpPlayer = Engine.QueryInterface(playerEnt, IID_Player);
var cmpPlayerStatisticsTracker = Engine.QueryInterface(playerEnt, IID_StatisticsTracker);
var playerData = {
"name": cmpPlayer.GetName(),
"civ": cmpPlayer.GetCiv(),
@ -41,6 +46,7 @@ GuiInterface.prototype.GetSimulationState = function(player)
"team": cmpPlayer.GetTeam(),
"diplomacy": cmpPlayer.GetDiplomacy(),
"phase": cmpPlayer.GetPhase(),
"statistics": cmpPlayerStatisticsTracker.GetStatistics()
};
ret.players.push(playerData);
}

View File

@ -79,6 +79,7 @@ Health.prototype.Kill = function()
Health.prototype.Reduce = function(amount)
{
var state = { "killed": false };
if (amount >= this.hitpoints)
{
// If this is the first time we reached 0, then die.
@ -86,6 +87,8 @@ Health.prototype.Reduce = function(amount)
// might get called multiple times)
if (this.hitpoints)
{
state.killed = true;
PlaySound("death", this.entity);
if (this.template.DeathType == "corpse")
@ -121,6 +124,7 @@ Health.prototype.Reduce = function(amount)
Engine.PostMessage(this.entity, MT_HealthChanged, { "from": old, "to": this.hitpoints });
}
return state;
};
Health.prototype.Increase = function(amount)

View File

@ -73,6 +73,7 @@ Identity.prototype.Schema =
"<value>Organic</value>" +
"<value>Structure</value>" +
"<value>Civic</value>" +
"<value>CivCentre</value>" +
"<value>Economic</value>" +
"<value>Defensive</value>" +
"<value>Village</value>" +

View File

@ -2,10 +2,10 @@ function Looter() {}
Looter.prototype.Schema =
"<empty/>";
/*
* TODO: this all needs to be designed and implemented
*/
Engine.RegisterComponentType(IID_Looter, "Looter", Looter);

View File

@ -121,15 +121,28 @@ Player.prototype.GetResourceCounts = function()
return this.resourceCount;
};
Player.prototype.AddResource = function(type, amount)
/**
* Add resource of specified type to player and increase gathered resources statistics
* @param type Generic type of resource (string)
* @param amount Amount of resource, whick should be added (integer)
* @param specificType Specific type of resource (string, optional)
*/
Player.prototype.AddResource = function(type, amount, specificType)
{
this.resourceCount[type] += (+amount);
var cmpStatisticsTracker = Engine.QueryInterface(this.entity, IID_StatisticsTracker);
cmpStatisticsTracker.IncreaseResourceGatheredCounter(type, amount, specificType);
};
/**
* Add resources to player but not increase gathered resources statistics
*/
Player.prototype.AddResources = function(amounts)
{
for (var type in amounts)
{
this.resourceCount[type] += (+amounts[type]);
}
};
Player.prototype.TrySubtractResources = function(amounts)
@ -177,6 +190,7 @@ Player.prototype.GetConquestCriticalEntitiesCount = function()
return this.conquestCriticalEntitiesCount;
};
Player.prototype.GetTeam = function()
{
return this.team;
@ -207,24 +221,29 @@ Player.prototype.SetPhase = function(p)
this.phase = p;
};
// Keep track of population effects of all entities that
// become owned or unowned by this player
/**
* Keep track of population effects of all entities that
* become owned or unowned by this player
*/
Player.prototype.OnGlobalOwnershipChanged = function(msg)
{
var classes = [];
var isConquestCritical = false;
// Load class list only if we're going to need it
if (msg.from == this.playerID || msg.to == this.playerID)
{
var cmpIdentity = Engine.QueryInterface(msg.entity, IID_Identity);
if (cmpIdentity)
classes = cmpIdentity.GetClassesList();
{
var classes = cmpIdentity.GetClassesList();
isConquestCritical = classes.indexOf("ConquestCritical") != -1;
}
}
if (msg.from == this.playerID)
{
if (classes.indexOf("ConquestCritical") != -1)
this.conquestCriticalEntitiesCount--;
if (isConquestCritical)
this.conquestCriticalEntitiesCount--;
var cost = Engine.QueryInterface(msg.entity, IID_Cost);
if (cost)
@ -236,9 +255,9 @@ Player.prototype.OnGlobalOwnershipChanged = function(msg)
if (msg.to == this.playerID)
{
if (classes.indexOf("ConquestCritical") != -1)
if (isConquestCritical)
this.conquestCriticalEntitiesCount++;
var cost = Engine.QueryInterface(msg.entity, IID_Cost);
if (cost)
{

View File

@ -79,7 +79,7 @@ ResourceGatherer.prototype.PerformGather = function(target)
var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
var cmpPlayer = Engine.QueryInterface(cmpPlayerManager.GetPlayerByID(cmpOwnership.GetOwner()), IID_Player);
cmpPlayer.AddResource(type.generic, status.amount);
cmpPlayer.AddResource(type.generic, status.amount, type.specific);
// Tell the target we're gathering from it
Engine.PostMessage(target, MT_ResourceGather,

View File

@ -0,0 +1,112 @@
function StatisticsTracker() {}
StatisticsTracker.prototype.Schema =
"<a:component type='system'/><empty/>";
StatisticsTracker.prototype.Init = function()
{
// units
this.unitsTrained = 0;
this.unitsLost = 0;
this.enemyUnitsKilled = 0;
//buildings
this.buildingsConstructed = 0;
this.buildingsLost = 0;
this.enemyBuildingsDestroyed = 0;
// civ centres
this.civCentresBuilt = 0;
this.enemyCivCentresDestroyed = 0;
// resources
this.resourcesGathered = {
"food": 0,
"wood": 0,
"metal": 0,
"stone": 0,
"vegetarianFood": 0
}
};
StatisticsTracker.prototype.GetStatistics = function()
{
return {
"unitsTrained": this.unitsTrained,
"unitsLost": this.unitsLost,
"enemyUnitsKilled": this.enemyUnitsKilled,
"buildingsConstructed": this.buildingsConstructed,
"buildingsLost": this.buildingsLost,
"enemyBuildingsDestroyed": this.enemyBuildingsDestroyed,
"civCentresBuilt": this.civCentresBuilt,
"enemyCivCentresDestroyed": this.enemyCivCentresDestroyed,
"resourcesGathered": this.resourcesGathered
};
};
StatisticsTracker.prototype.IncreaseTrainedUnitsCounter = function()
{
return this.unitsTrained++;
};
StatisticsTracker.prototype.IncreaseConstructedBuildingsCounter = function()
{
return this.buildingsConstructed++;
};
StatisticsTracker.prototype.IncreaseBuiltCivCentresCounter = function()
{
return this.civCentresBuilt++;
};
StatisticsTracker.prototype.KilledEntity = function(targetEntity)
{
var cmpTargetEntityIdentity = Engine.QueryInterface(targetEntity, IID_Identity);
if (cmpTargetEntityIdentity)
{
var classes = cmpTargetEntityIdentity.GetClassesList();
// we want to deal only with real structures, not foundations
var cmpFoundation = Engine.QueryInterface(targetEntity, IID_Foundation);
var targetIsStructure = classes.indexOf("Structure") != -1 && cmpFoundation == null;
var targetIsUnit = classes.indexOf("Unit") != -1;
var targetIsCivCentre = classes.indexOf("CivCentre") != -1;
var cmpTargetOwnership = Engine.QueryInterface(targetEntity, IID_Ownership);
// don't increase counters if target player is gaia (player 0)
if (cmpTargetOwnership.GetOwner() != 0)
{
if (targetIsUnit) this.enemyUnitsKilled++;
if (targetIsStructure) this.enemyBuildingsDestroyed++;
if (targetIsCivCentre) this.enemyCivCentresDestroyed++;
}
}
};
StatisticsTracker.prototype.LostEntity = function(lostEntity)
{
var cmpLostEntityIdentity = Engine.QueryInterface(lostEntity, IID_Identity);
if (cmpLostEntityIdentity)
{
var classes = cmpLostEntityIdentity.GetClassesList();
// we want to deal only with real structures, not foundations
var cmpFoundation = Engine.QueryInterface(lostEntity, IID_Foundation);
var lostEntityIsStructure = classes.indexOf("Structure") != -1 && cmpFoundation == null;
var lostEntityIsUnit = classes.indexOf("Unit") != -1;
if (lostEntityIsUnit) this.unitsLost++;
if (lostEntityIsStructure) this.buildingsLost++;
}
};
/**
* @param type Generic type of resource (string)
* @param amount Amount of resource, whick should be added (integer)
* @param specificType Specific type of resource (string, optional)
*/
StatisticsTracker.prototype.IncreaseResourceGatheredCounter = function(type, amount, specificType)
{
this.resourcesGathered[type] += amount;
if (type == "food" && (specificType == "fruit" || specificType == "grain"))
this.resourcesGathered["vegetarianFood"] += amount;
};
Engine.RegisterComponentType(IID_StatisticsTracker, "StatisticsTracker", StatisticsTracker);

View File

@ -218,7 +218,10 @@ TrainingQueue.prototype.SpawnUnits = function(templateName, count)
var cmpNewOwnership = Engine.QueryInterface(ent, IID_Ownership);
cmpNewOwnership.SetOwner(cmpOwnership.GetOwner());
var cmpPlayerStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker);
cmpPlayerStatisticsTracker.IncreaseTrainedUnitsCounter();
ents.push(ent);
// Play a sound, but only for the first in the batch (to avoid nasty phasing effects)

View File

@ -0,0 +1 @@
Engine.RegisterInterface("StatisticsTracker");

View File

@ -9,6 +9,8 @@ Engine.LoadComponentScript("interfaces/RallyPoint.js");
Engine.LoadComponentScript("interfaces/ResourceGatherer.js");
Engine.LoadComponentScript("interfaces/ResourceSupply.js");
Engine.LoadComponentScript("interfaces/TrainingQueue.js");
Engine.LoadComponentScript("interfaces/Timer.js");
Engine.LoadComponentScript("interfaces/StatisticsTracker.js");
Engine.LoadComponentScript("GuiInterface.js");
var cmp = ConstructComponent(SYSTEM_ENTITY, "GuiInterface");
@ -28,6 +30,11 @@ AddMock(SYSTEM_ENTITY, IID_RangeManager, {
GetLosCircular: function() { return false; },
});
AddMock(SYSTEM_ENTITY, IID_Timer, {
GetTime: function() { return 0; },
SetTimeout: function(ent, iid, funcname, time, data) { return 0; },
});
AddMock(100, IID_Player, {
GetName: function() { return "Player 1"; },
@ -41,6 +48,29 @@ AddMock(100, IID_Player, {
GetTeam: function() { return -1; },
GetDiplomacy: function() { return []; },
GetPhase: function() { return ""; },
GetConquestCriticalEntitiesCount: function() { return 1; },
});
AddMock(100, IID_StatisticsTracker, {
GetStatistics: function() {
return {
"unitsTrained": 10,
"unitsLost": 9,
"buildingsConstructed": 5,
"buildingsLost": 4,
"civCentresBuilt": 1,
"resourcesGathered": {
"food": 100,
"wood": 0,
"metal": 0,
"stone": 0,
"vegetarianFood": 0,
},
};
},
IncreaseTrainedUnitsCounter: function() { return 1; },
IncreaseConstructedBuildingsCounter: function() { return 1; },
IncreaseBuiltCivCentresCounter: function() { return 1; },
});
AddMock(101, IID_Player, {
@ -55,6 +85,29 @@ AddMock(101, IID_Player, {
GetTeam: function() { return -1; },
GetDiplomacy: function() { return [1]; },
GetPhase: function() { return "village"; },
GetConquestCriticalEntitiesCount: function() { return 1; },
});
AddMock(101, IID_StatisticsTracker, {
GetStatistics: function() {
return {
"unitsTrained": 10,
"unitsLost": 9,
"buildingsConstructed": 5,
"buildingsLost": 4,
"civCentresBuilt": 1,
"resourcesGathered": {
"food": 100,
"wood": 0,
"metal": 0,
"stone": 0,
"vegetarianFood": 0,
},
};
},
IncreaseTrainedUnitsCounter: function() { return 1; },
IncreaseConstructedBuildingsCounter: function() { return 1; },
IncreaseBuiltCivCentresCounter: function() { return 1; },
});
TS_ASSERT_UNEVAL_EQUALS(cmp.GetSimulationState(), {
@ -71,6 +124,20 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetSimulationState(), {
team: -1,
diplomacy: [],
phase: "",
statistics: {
unitsTrained: 10,
unitsLost: 9,
buildingsConstructed: 5,
buildingsLost: 4,
civCentresBuilt: 1,
resourcesGathered: {
food: 100,
wood: 0,
metal: 0,
stone: 0,
vegetarianFood: 0,
},
},
},
{
name: "Player 2",
@ -84,8 +151,23 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetSimulationState(), {
team: -1,
diplomacy: [1],
phase: "village",
statistics: {
unitsTrained: 10,
unitsLost: 9,
buildingsConstructed: 5,
buildingsLost: 4,
civCentresBuilt: 1,
resourcesGathered: {
food: 100,
wood: 0,
metal: 0,
stone: 0,
vegetarianFood: 0,
},
},
}
],
timeElapsed: 0,
circularMap: false,
});

View File

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Entity>
<Player/>
<StatisticsTracker/>
</Entity>

View File

@ -3,7 +3,11 @@
<Identity>
<GenericName>Civic Centre</GenericName>
<Tooltip>Build upon a settlement to capture territory.</Tooltip>
<Classes datatype="tokens">Village Defensive</Classes>
<Classes datatype="tokens">
Village
Defensive
CivCentre
</Classes>
<Icon>structures/civic_centre.png</Icon>
</Identity>
<BuildRestrictions>