2010-08-12 00:16:16 +02:00
// Network Mode
var g _IsNetworked = false ;
2013-11-07 21:07:24 +01:00
// Is this user in control of game settings (i.e. is a network server, or offline player)
var g _IsController ;
2013-11-08 10:52:48 +01:00
// Match ID for tracking
2013-11-08 16:28:38 +01:00
var g _MatchID ;
2014-03-17 00:29:27 +01:00
// Is this user an observer?
var g _IsObserver = false ;
2013-11-07 21:07:24 +01:00
2010-08-12 00:16:16 +02:00
// Cache the basic player data (name, civ, color)
var g _Players = [ ] ;
2010-10-30 06:02:42 +02:00
// Cache the useful civ data
var g _CivData = { } ;
2013-04-04 01:24:22 +02:00
var g _GameSpeeds = { } ;
var g _CurrentSpeed ;
2014-04-20 22:51:48 +02:00
var g _PlayerAssignments = { "local" : { "name" : translate ( "You" ) , "player" : 1 } } ;
2010-08-12 21:31:17 +02:00
2010-06-30 23:34:44 +02:00
// Cache dev-mode settings that are frequently or widely used
var g _DevSettings = {
controlAll : false
} ;
2012-07-24 06:14:09 +02:00
// Whether status bars should be shown for all of the player's units.
var g _ShowAllStatusBars = false ;
2010-09-04 15:24:52 +02:00
// Indicate when one of the current player's training queues is blocked
// (this is used to support population counter blinking)
2012-04-20 19:21:04 +02:00
var g _IsTrainingBlocked = false ;
2010-09-04 15:24:52 +02:00
2013-04-10 23:05:46 +02:00
// Cache simulation state (updated on every simulation update)
var g _SimState ;
2010-08-28 23:12:52 +02:00
// Cache EntityStates
var g _EntityStates = { } ; // {id:entState}
2010-10-01 22:51:21 +02:00
// Whether the player has lost/won and reached the end of their game
var g _GameEnded = false ;
2013-03-25 06:01:36 +01:00
var g _Disconnected = false ; // Lost connection to server
2013-11-07 21:07:24 +01:00
// Holds player states from the last tick
var g _CachedLastStates = "" ;
2011-09-07 03:43:56 +02:00
// Colors to flash when pop limit reached
const DEFAULT _POPULATION _COLOR = "white" ;
const POPULATION _ALERT _COLOR = "orange" ;
2013-11-30 18:30:08 +01:00
// List of additional entities to highlight
var g _ShowGuarding = false ;
var g _ShowGuarded = false ;
var g _AdditionalHighlight = [ ] ;
2014-01-06 14:48:17 +01:00
// for saving the hitpoins of the hero (is there a better way to do that?)
// Should be possible with AttackDetection but might be an overkill because it would have to loop
// always through the list of all ongoing attacks...
var g _previousHeroHitPoints = undefined ;
2014-01-06 14:32:48 +01:00
2013-04-10 23:05:46 +02:00
function GetSimState ( )
{
if ( ! g _SimState )
g _SimState = Engine . GuiInterfaceCall ( "GetSimulationState" ) ;
return g _SimState ;
}
2010-08-28 23:12:52 +02:00
function GetEntityState ( entId )
{
if ( ! ( entId in g _EntityStates ) )
{
var entState = Engine . GuiInterfaceCall ( "GetEntityState" , entId ) ;
2013-12-08 11:02:19 +01:00
if ( entState )
entState . extended = false ;
2010-08-28 23:12:52 +02:00
g _EntityStates [ entId ] = entState ;
}
return g _EntityStates [ entId ] ;
}
2013-12-08 11:02:19 +01:00
function GetExtendedEntityState ( entId )
{
if ( entId in g _EntityStates )
var entState = g _EntityStates [ entId ] ;
else
var entState = Engine . GuiInterfaceCall ( "GetEntityState" , entId ) ;
if ( ! entState || entState . extended )
return entState ;
var extension = Engine . GuiInterfaceCall ( "GetExtendedEntityState" , entId ) ;
for ( var prop in extension )
entState [ prop ] = extension [ prop ] ;
entState . extended = true ;
g _EntityStates [ entId ] = entState ;
return entState ;
}
2010-08-28 23:12:52 +02:00
// Cache TemplateData
var g _TemplateData = { } ; // {id:template}
2014-04-20 22:51:48 +02:00
var g _TemplateDataWithoutLocalization = { } ;
2010-08-28 23:12:52 +02:00
2010-10-30 06:02:42 +02:00
2010-08-28 23:12:52 +02:00
function GetTemplateData ( templateName )
{
if ( ! ( templateName in g _TemplateData ) )
{
var template = Engine . GuiInterfaceCall ( "GetTemplateData" , templateName ) ;
2014-04-20 22:51:48 +02:00
translateObjectKeys ( template , [ "specific" , "generic" , "tooltip" ] ) ;
2010-08-28 23:12:52 +02:00
g _TemplateData [ templateName ] = template ;
}
return g _TemplateData [ templateName ] ;
}
2014-04-20 22:51:48 +02:00
function GetTemplateDataWithoutLocalization ( templateName )
{
if ( ! ( templateName in g _TemplateDataWithoutLocalization ) )
{
var template = Engine . GuiInterfaceCall ( "GetTemplateData" , templateName ) ;
g _TemplateDataWithoutLocalization [ templateName ] = template ;
}
return g _TemplateDataWithoutLocalization [ templateName ] ;
}
2012-04-20 19:21:04 +02:00
// Cache TechnologyData
var g _TechnologyData = { } ; // {id:template}
function GetTechnologyData ( technologyName )
{
if ( ! ( technologyName in g _TechnologyData ) )
{
var template = Engine . GuiInterfaceCall ( "GetTechnologyData" , technologyName ) ;
2014-04-20 22:51:48 +02:00
translateObjectKeys ( template , [ "specific" , "generic" , "description" , "tooltip" , "requirementsTooltip" ] ) ;
2012-04-20 19:21:04 +02:00
g _TechnologyData [ technologyName ] = template ;
}
return g _TechnologyData [ technologyName ] ;
}
2010-08-28 23:12:52 +02:00
// Init
2010-06-30 23:34:44 +02:00
function init ( initData , hotloadData )
{
2010-08-12 00:16:16 +02:00
if ( initData )
{
g _IsNetworked = initData . isNetworked ; // Set network mode
2013-11-07 21:07:24 +01:00
g _IsController = initData . isController ; // Set controller mode
2010-08-12 21:31:17 +02:00
g _PlayerAssignments = initData . playerAssignments ;
2013-11-07 21:07:24 +01:00
g _MatchID = initData . attribs . matchID ;
2010-11-03 01:21:52 +01:00
// Cache the player data
// (This may be updated at runtime by handleNetMessage)
g _Players = getPlayerData ( g _PlayerAssignments ) ;
2012-05-07 06:18:54 +02:00
if ( initData . savedGUIData )
restoreSavedGameData ( initData . savedGUIData ) ;
2013-04-04 01:24:22 +02:00
2014-01-04 11:14:53 +01:00
Engine . GetGUIObjectByName ( "gameSpeedButton" ) . hidden = g _IsNetworked ;
2010-08-12 00:16:16 +02:00
}
2010-08-12 05:01:33 +02:00
else // Needed for autostart loading option
{
2011-08-31 04:41:21 +02:00
g _Players = getPlayerData ( null ) ;
2010-08-12 05:01:33 +02:00
}
2011-08-31 04:41:21 +02:00
2010-10-30 06:02:42 +02:00
// Cache civ data
g _CivData = loadCivData ( ) ;
2014-04-20 22:51:48 +02:00
g _CivData [ "gaia" ] = { "Code" : "gaia" , "Name" : translate ( "Gaia" ) } ;
2014-03-17 00:29:27 +01:00
if ( Engine . GetPlayerID ( ) <= 0 )
{
g _IsObserver = true ;
// Hide stuff observers don't use.
Engine . GetGUIObjectByName ( "food" ) . hidden = true ;
Engine . GetGUIObjectByName ( "wood" ) . hidden = true ;
Engine . GetGUIObjectByName ( "stone" ) . hidden = true ;
Engine . GetGUIObjectByName ( "metal" ) . hidden = true ;
Engine . GetGUIObjectByName ( "population" ) . hidden = true ;
Engine . GetGUIObjectByName ( "diplomacyButton1" ) . hidden = true ;
Engine . GetGUIObjectByName ( "tradeButton1" ) . hidden = true ;
Engine . GetGUIObjectByName ( "menuResignButton" ) . enabled = false ;
Engine . GetGUIObjectByName ( "pauseButton" ) . enabled = false ;
Engine . GetGUIObjectByName ( "observerText" ) . hidden = false ;
}
else
{
// TODO: Get a civ icon for gaia/observers.
Engine . GetGUIObjectByName ( "civIcon" ) . sprite = "stretched:" + g _CivData [ g _Players [ Engine . GetPlayerID ( ) ] . civ ] . Emblem ;
Engine . GetGUIObjectByName ( "civIcon" ) . tooltip = g _CivData [ g _Players [ Engine . GetPlayerID ( ) ] . civ ] . Name ;
}
2010-08-14 06:34:49 +02:00
2013-04-04 01:24:22 +02:00
g _GameSpeeds = initGameSpeeds ( ) ;
g _CurrentSpeed = Engine . GetSimRate ( ) ;
2014-01-04 11:14:53 +01:00
var gameSpeed = Engine . GetGUIObjectByName ( "gameSpeed" ) ;
2013-04-04 01:24:22 +02:00
gameSpeed . list = g _GameSpeeds . names ;
gameSpeed . list _data = g _GameSpeeds . speeds ;
var idx = g _GameSpeeds . speeds . indexOf ( g _CurrentSpeed ) ;
gameSpeed . selected = idx != - 1 ? idx : g _GameSpeeds [ "default" ] ;
gameSpeed . onSelectionChange = function ( ) { changeGameSpeed ( + this . list _data [ this . selected ] ) ; }
2011-09-06 20:15:27 +02:00
initMenuPosition ( ) ; // set initial position
2011-05-04 21:31:01 +02:00
2013-07-29 02:53:44 +02:00
// Populate player selection dropdown
var playerNames = [ ] ;
var playerIDs = [ ] ;
for ( var player in g _Players )
{
playerNames . push ( g _Players [ player ] . name ) ;
playerIDs . push ( player ) ;
}
2014-01-04 11:14:53 +01:00
var viewPlayerDropdown = Engine . GetGUIObjectByName ( "viewPlayer" ) ;
2013-07-29 02:53:44 +02:00
viewPlayerDropdown . list = playerNames ;
viewPlayerDropdown . list _data = playerIDs ;
2013-07-29 22:01:09 +02:00
viewPlayerDropdown . selected = Engine . GetPlayerID ( ) ;
2013-07-29 02:53:44 +02:00
2012-04-20 03:41:54 +02:00
// If in Atlas editor, disable the exit button
if ( Engine . IsAtlasRunning ( ) )
2014-01-04 11:14:53 +01:00
Engine . GetGUIObjectByName ( "menuExitButton" ) . enabled = false ;
2012-04-20 03:41:54 +02:00
2011-05-04 21:31:01 +02:00
if ( hotloadData )
{
g _Selection . selected = hotloadData . selection ;
}
2011-08-31 04:41:21 +02:00
else
2011-05-04 21:31:01 +02:00
{
2011-09-11 05:30:41 +02:00
// Starting for the first time:
2011-09-14 14:46:34 +02:00
initMusic ( ) ;
2014-03-17 00:29:27 +01:00
if ( ! g _IsObserver ) {
var civMusic = g _CivData [ g _Players [ Engine . GetPlayerID ( ) ] . civ ] . Music ;
global . music . storeTracks ( civMusic ) ;
}
2011-09-11 05:30:41 +02:00
global . music . setState ( global . music . states . PEACE ) ;
playRandomAmbient ( "temperate" ) ;
2011-05-04 21:31:01 +02:00
}
2013-11-07 19:06:52 +01:00
if ( Engine . ConfigDB _GetValue ( "user" , "gui.session.timeelapsedcounter" ) === "true" )
2014-01-04 11:14:53 +01:00
Engine . GetGUIObjectByName ( "timeElapsedCounter" ) . hidden = false ;
2013-11-07 19:06:52 +01:00
2010-06-30 23:34:44 +02:00
onSimulationUpdate ( ) ;
2011-02-19 04:14:37 +01:00
// Report the performance after 5 seconds (when we're still near
// the initial camera view) and a minute (when the profiler will
// have settled down if framerates as very low), to give some
// extremely rough indications of performance
setTimeout ( function ( ) { reportPerformance ( 5 ) ; } , 5000 ) ;
setTimeout ( function ( ) { reportPerformance ( 60 ) ; } , 60000 ) ;
}
2013-07-29 02:53:44 +02:00
function selectViewPlayer ( playerID )
{
Engine . SetPlayerID ( playerID ) ;
2014-03-17 00:29:27 +01:00
if ( playerID > 0 ) {
2014-01-04 11:14:53 +01:00
Engine . GetGUIObjectByName ( "civIcon" ) . sprite = "stretched:" + g _CivData [ g _Players [ playerID ] . civ ] . Emblem ;
Engine . GetGUIObjectByName ( "civIcon" ) . tooltip = g _CivData [ g _Players [ playerID ] . civ ] . Name ;
2013-07-29 02:53:44 +02:00
}
}
2011-09-11 05:30:41 +02:00
2011-02-19 04:14:37 +01:00
function reportPerformance ( time )
{
2011-04-28 03:21:02 +02:00
var settings = Engine . GetMapSettings ( ) ;
2011-02-19 04:14:37 +01:00
var data = {
time : time ,
2011-04-28 03:21:02 +02:00
map : settings . Name ,
2011-04-29 19:32:35 +02:00
seed : settings . Seed , // only defined for random maps
size : settings . Size , // only defined for random maps
2011-02-19 04:14:37 +01:00
profiler : Engine . GetProfilerState ( )
} ;
2011-08-31 04:41:21 +02:00
2011-04-29 19:32:35 +02:00
Engine . SubmitUserReport ( "profile" , 3 , JSON . stringify ( data ) ) ;
2010-06-30 23:34:44 +02:00
}
2014-02-21 21:02:23 +01:00
/ * *
* Resign a player .
* @ param leaveGameAfterResign If player is quitting after resignation .
* /
function resignGame ( leaveGameAfterResign )
2012-08-05 20:07:56 +02:00
{
2013-04-10 23:05:46 +02:00
var simState = GetSimState ( ) ;
2012-08-05 20:07:56 +02:00
2013-04-10 23:05:46 +02:00
// Players can't resign if they've already won or lost.
2013-03-25 06:01:36 +01:00
if ( simState . players [ Engine . GetPlayerID ( ) ] . state != "active" || g _Disconnected )
2012-08-05 20:07:56 +02:00
return ;
// Tell other players that we have given up and been defeated
Engine . PostNetworkCommand ( {
"type" : "defeat-player" ,
"playerId" : Engine . GetPlayerID ( )
} ) ;
global . music . setState ( global . music . states . DEFEAT ) ;
2014-02-21 21:02:23 +01:00
// Resume the game if not resigning.
if ( ! leaveGameAfterResign )
resumeGame ( ) ;
2012-08-05 20:07:56 +02:00
}
2014-02-21 21:02:23 +01:00
/ * *
* Leave the game
* @ param willRejoin If player is going to be rejoining a networked game .
* /
function leaveGame ( willRejoin )
2010-06-30 23:34:44 +02:00
{
2010-11-14 20:09:13 +01:00
var extendedSimState = Engine . GuiInterfaceCall ( "GetExtendedSimulationState" ) ;
2013-11-07 21:07:24 +01:00
var mapSettings = Engine . GetMapSettings ( ) ;
2010-10-01 22:51:21 +02:00
var gameResult ;
2013-11-07 21:07:24 +01:00
2014-03-17 00:29:27 +01:00
if ( g _IsObserver )
2010-10-01 22:51:21 +02:00
{
2014-03-17 00:29:27 +01:00
// Observers don't win/lose.
2014-04-20 22:51:48 +02:00
gameResult = translate ( "You have left the game." ) ;
2014-03-17 00:29:27 +01:00
global . music . setState ( global . music . states . VICTORY ) ;
2010-10-01 22:51:21 +02:00
}
2014-03-17 00:29:27 +01:00
else
2010-10-01 22:51:21 +02:00
{
2014-03-17 00:29:27 +01:00
var playerState = extendedSimState . players [ Engine . GetPlayerID ( ) ] ;
if ( g _Disconnected )
2014-04-20 22:51:48 +02:00
gameResult = translate ( "You have been disconnected." ) ;
2014-03-17 00:29:27 +01:00
else if ( playerState . state == "won" )
2014-04-20 22:51:48 +02:00
gameResult = translate ( "You have won the battle!" ) ;
2014-03-17 00:29:27 +01:00
else if ( playerState . state == "defeated" )
2014-04-20 22:51:48 +02:00
gameResult = translate ( "You have been defeated..." ) ;
2014-03-17 00:29:27 +01:00
else // "active"
2014-02-21 21:02:23 +01:00
{
2014-03-17 00:29:27 +01:00
global . music . setState ( global . music . states . DEFEAT ) ;
if ( willRejoin )
2014-04-20 22:51:48 +02:00
gameResult = translate ( "You have left the game." ) ;
2014-03-17 00:29:27 +01:00
else
{
2014-04-20 22:51:48 +02:00
gameResult = translate ( "You have abandoned the game." ) ;
2014-03-17 00:29:27 +01:00
resignGame ( true ) ;
}
2014-02-21 21:02:23 +01:00
}
2010-10-01 22:51:21 +02:00
}
2011-09-11 05:30:41 +02:00
stopAmbient ( ) ;
2014-01-04 11:14:53 +01:00
Engine . EndGame ( ) ;
2011-08-31 04:41:21 +02:00
2013-11-08 16:28:44 +01:00
if ( g _IsController && Engine . HasXmppClient ( ) )
2013-11-07 21:07:24 +01:00
Engine . SendUnregisterGame ( ) ;
2013-11-08 16:28:44 +01:00
2011-09-11 05:30:41 +02:00
Engine . SwitchGuiPage ( "page_summary.xml" , {
"gameResult" : gameResult ,
"timeElapsed" : extendedSimState . timeElapsed ,
2012-06-26 00:11:47 +02:00
"playerStates" : extendedSimState . players ,
2012-08-05 04:18:44 +02:00
"players" : g _Players ,
2012-06-26 00:11:47 +02:00
"mapSettings" : mapSettings
2011-09-11 05:30:41 +02:00
} ) ;
2010-06-30 23:34:44 +02:00
}
// Return some data that we'll use when hotloading this file after changes
function getHotloadData ( )
{
return { selection : g _Selection . selected } ;
}
2011-10-30 02:07:28 +02:00
// Return some data that will be stored in saved game files
function getSavedGameData ( )
{
var data = { } ;
data . playerAssignments = g _PlayerAssignments ;
2012-05-07 06:18:54 +02:00
data . groups = g _Groups . groups ;
// TODO: any other gui state?
2011-10-30 02:07:28 +02:00
return data ;
}
2011-09-12 00:42:40 +02:00
2012-05-07 06:18:54 +02:00
function restoreSavedGameData ( data )
{
2014-04-06 18:27:57 +02:00
// Restore camera if any
if ( data . camera )
Engine . SetCameraData ( data . camera . PosX , data . camera . PosY , data . camera . PosZ ,
data . camera . RotX , data . camera . RotY , data . camera . Zoom ) ;
2013-10-11 01:58:29 +02:00
// Clear selection when loading a game
g _Selection . reset ( ) ;
2012-05-07 06:18:54 +02:00
// Restore control groups
2013-05-13 00:28:02 +02:00
for ( var groupNumber in data . groups )
2012-05-07 06:18:54 +02:00
{
g _Groups . groups [ groupNumber ] . groups = data . groups [ groupNumber ] . groups ;
g _Groups . groups [ groupNumber ] . ents = data . groups [ groupNumber ] . ents ;
}
updateGroups ( ) ;
}
2011-10-30 02:07:28 +02:00
var lastTickTime = new Date ;
2014-01-08 05:22:34 +01:00
var lastXmppClientPoll = Date . now ( ) ;
2012-05-05 21:22:22 +02:00
/ * *
* Called every frame .
* /
2010-06-30 23:34:44 +02:00
function onTick ( )
{
2011-10-30 02:07:28 +02:00
var now = new Date ;
var tickLength = new Date - lastTickTime ;
lastTickTime = now ;
2010-10-01 22:51:21 +02:00
checkPlayerState ( ) ;
2010-07-02 23:28:48 +02:00
while ( true )
{
var message = Engine . PollNetworkClient ( ) ;
if ( ! message )
break ;
handleNetMessage ( message ) ;
}
2012-03-08 21:42:28 +01:00
updateCursorAndTooltip ( ) ;
2010-06-30 23:34:44 +02:00
2012-05-05 21:22:22 +02:00
// If the selection changed, we need to regenerate the sim display (the display depends on both the
// simulation state and the current selection).
2010-06-30 23:34:44 +02:00
if ( g _Selection . dirty )
2010-08-05 12:20:47 +02:00
{
2013-12-05 19:50:29 +01:00
g _Selection . dirty = false ;
2010-06-30 23:34:44 +02:00
onSimulationUpdate ( ) ;
2010-08-05 12:20:47 +02:00
// Display rally points for selected buildings
2014-03-17 00:29:27 +01:00
if ( ! g _IsObserver )
Engine . GuiInterfaceCall ( "DisplayRallyPoint" , { "entities" : g _Selection . toList ( ) } ) ;
2010-08-05 12:20:47 +02:00
}
2010-08-11 23:04:09 +02:00
// Run timers
updateTimers ( ) ;
2010-09-28 16:19:13 +02:00
2011-09-11 05:30:41 +02:00
// Animate menu
2011-10-30 02:07:28 +02:00
updateMenuPosition ( tickLength ) ;
2011-08-31 04:41:21 +02:00
2010-09-28 16:19:13 +02:00
// When training is blocked, flash population (alternates colour every 500msec)
2012-04-20 19:21:04 +02:00
if ( g _IsTrainingBlocked && ( Date . now ( ) % 1000 ) < 500 )
2014-01-04 11:14:53 +01:00
Engine . GetGUIObjectByName ( "resourcePop" ) . textcolor = POPULATION _ALERT _COLOR ;
2010-09-04 15:24:52 +02:00
else
2014-01-04 11:14:53 +01:00
Engine . GetGUIObjectByName ( "resourcePop" ) . textcolor = DEFAULT _POPULATION _COLOR ;
2011-08-31 04:41:21 +02:00
2011-08-31 00:29:03 +02:00
// Clear renamed entities list
2011-10-23 23:00:59 +02:00
Engine . GuiInterfaceCall ( "ClearRenamedEntities" ) ;
2010-06-30 23:34:44 +02:00
}
2010-10-01 22:51:21 +02:00
function checkPlayerState ( )
{
2013-11-07 21:07:24 +01:00
// Once the game ends, we're done here.
2014-03-17 00:29:27 +01:00
if ( g _GameEnded || g _IsObserver )
2013-11-07 21:07:24 +01:00
return ;
// Send a game report for each player in this game.
var m _simState = GetSimState ( ) ;
var playerState = m _simState . players [ Engine . GetPlayerID ( ) ] ;
var tempStates = "" ;
for each ( var player in m _simState . players ) { tempStates += player . state + "," ; }
2011-08-31 04:41:21 +02:00
2013-11-07 21:07:24 +01:00
if ( g _CachedLastStates != tempStates )
2010-10-01 22:51:21 +02:00
{
2013-11-07 21:07:24 +01:00
g _CachedLastStates = tempStates ;
reportGame ( Engine . GuiInterfaceCall ( "GetExtendedSimulationState" ) ) ;
}
2012-08-05 20:07:56 +02:00
2013-11-07 21:07:24 +01:00
// If the local player hasn't finished playing, we return here to avoid the victory/defeat messages.
if ( playerState . state == "active" )
return ;
// We can't resign once the game is over.
2014-01-04 11:14:53 +01:00
Engine . GetGUIObjectByName ( "menuResignButton" ) . enabled = false ;
2013-11-07 21:07:24 +01:00
// Make sure nothing is open to avoid stacking.
closeMenu ( ) ;
closeOpenDialogs ( ) ;
// Make sure this doesn't run again.
g _GameEnded = true ;
if ( Engine . IsAtlasRunning ( ) )
{
// If we're in Atlas, we can't leave the game
2014-04-20 22:51:48 +02:00
var btCaptions = [ translate ( "OK" ) ] ;
2013-11-07 21:07:24 +01:00
var btCode = [ null ] ;
2014-04-20 22:51:48 +02:00
var message = translate ( "Press OK to continue" ) ;
2013-11-07 21:07:24 +01:00
}
else
{
2014-05-04 04:44:14 +02:00
var btCaptions = [ translate ( "No" ) , translate ( "Yes" ) ] ;
var btCode = [ null , leaveGame ] ;
2014-04-20 22:51:48 +02:00
var message = translate ( "Do you want to quit?" ) ;
2013-11-07 21:07:24 +01:00
}
if ( playerState . state == "defeated" )
{
global . music . setState ( global . music . states . DEFEAT ) ;
2014-04-20 22:51:48 +02:00
messageBox ( 400 , 200 , message , translate ( "DEFEATED!" ) , 0 , btCaptions , btCode ) ;
2010-10-01 22:51:21 +02:00
}
2013-11-07 21:07:24 +01:00
else if ( playerState . state == "won" )
{
global . music . setState ( global . music . states . VICTORY ) ;
// TODO: Reveal map directly instead of this silly proxy.
2014-01-04 11:14:53 +01:00
if ( ! Engine . GetGUIObjectByName ( "devCommandsRevealMap" ) . checked )
Engine . GetGUIObjectByName ( "devCommandsRevealMap" ) . checked = true ;
2014-04-20 22:51:48 +02:00
messageBox ( 400 , 200 , message , translate ( "VICTORIOUS!" ) , 0 , btCaptions , btCode ) ;
2013-11-07 21:07:24 +01:00
}
2010-10-01 22:51:21 +02:00
}
2013-04-04 01:24:22 +02:00
function changeGameSpeed ( speed )
{
// For non-networked games only
if ( ! g _IsNetworked )
{
Engine . SetSimRate ( speed ) ;
g _CurrentSpeed = speed ;
}
}
2012-05-05 21:22:22 +02:00
/ * *
* Recomputes GUI state that depends on simulation state or selection state . Called directly every simulation
* update ( see session . xml ) , or from onTick when the selection has changed .
* /
2010-06-30 23:34:44 +02:00
function onSimulationUpdate ( )
{
2010-08-28 23:12:52 +02:00
g _EntityStates = { } ;
g _TemplateData = { } ;
2012-04-20 19:21:04 +02:00
g _TechnologyData = { } ;
2011-08-31 04:41:21 +02:00
2013-04-10 23:05:46 +02:00
g _SimState = Engine . GuiInterfaceCall ( "GetSimulationState" ) ;
2010-10-30 20:25:34 +02:00
2010-06-30 23:34:44 +02:00
// If we're called during init when the game is first loading, there will be no simulation yet, so do nothing
2013-04-10 23:05:46 +02:00
if ( ! g _SimState )
2010-06-30 23:34:44 +02:00
return ;
2010-08-14 00:02:27 +02:00
handleNotifications ( ) ;
2010-08-14 00:06:19 +02:00
2012-07-24 06:14:09 +02:00
if ( g _ShowAllStatusBars )
recalculateStatusBarDisplay ( ) ;
2013-11-30 18:30:08 +01:00
if ( g _ShowGuarding || g _ShowGuarded )
updateAdditionalHighlight ( ) ;
2013-04-10 23:05:46 +02:00
updateHero ( ) ;
2011-04-26 20:19:16 +02:00
updateGroups ( ) ;
2013-04-10 23:05:46 +02:00
updateDebug ( ) ;
updatePlayerDisplay ( ) ;
2010-08-12 00:16:16 +02:00
updateSelectionDetails ( ) ;
2011-02-11 12:17:32 +01:00
updateBuildingPlacementPreview ( ) ;
2013-04-10 23:05:46 +02:00
updateTimeElapsedCounter ( ) ;
2014-03-17 00:29:27 +01:00
updateTimeNotifications ( ) ;
2013-01-20 23:47:59 +01:00
2014-03-17 00:29:27 +01:00
if ( ! g _IsObserver )
{
updateResearchDisplay ( ) ;
// Update music state on basis of battle state.
var battleState = Engine . GuiInterfaceCall ( "GetBattleState" , Engine . GetPlayerID ( ) ) ;
if ( battleState )
global . music . setState ( global . music . states [ battleState ] ) ;
}
2014-01-06 14:32:48 +01:00
}
/ * *
* updates a status bar on the GUI
* nameOfBar : name of the bar
* points : points to show
* maxPoints : max points
* direction : gets less from ( right to left ) 0 ; ( top to bottom ) 1 ; ( left to right ) 2 ; ( bottom to top ) 3 ;
* /
function updateGUIStatusBar ( nameOfBar , points , maxPoints , direction )
{
// check, if optional direction parameter is valid.
2014-01-06 21:13:55 +01:00
if ( ! direction || ! ( direction >= 0 && direction < 4 ) )
2014-01-06 14:32:48 +01:00
direction = 0 ;
// get the bar and update it
var statusBar = Engine . GetGUIObjectByName ( nameOfBar ) ;
2014-01-06 14:48:17 +01:00
if ( ! statusBar )
return ;
2014-01-06 14:32:48 +01:00
2014-01-06 14:48:17 +01:00
var healthSize = statusBar . size ;
var value = 100 * Math . max ( 0 , Math . min ( 1 , points / maxPoints ) ) ;
// inverse bar
if ( direction == 2 || direction == 3 )
value = 100 - value ;
if ( direction == 0 )
healthSize . rright = value ;
else if ( direction == 1 )
healthSize . rbottom = value ;
else if ( direction == 2 )
healthSize . rleft = value ;
else if ( direction == 3 )
healthSize . rtop = value ;
// update bar
statusBar . size = healthSize ;
2010-06-30 23:34:44 +02:00
}
2014-01-06 14:32:48 +01:00
2013-04-10 23:05:46 +02:00
function updateHero ( )
2013-04-03 19:27:55 +02:00
{
2013-04-10 23:05:46 +02:00
var simState = GetSimState ( ) ;
2013-04-03 19:27:55 +02:00
var playerState = simState . players [ Engine . GetPlayerID ( ) ] ;
2014-01-06 14:32:48 +01:00
var unitHeroPanel = Engine . GetGUIObjectByName ( "unitHeroPanel" ) ;
2014-01-04 11:14:53 +01:00
var heroButton = Engine . GetGUIObjectByName ( "unitHeroButton" ) ;
2013-04-03 19:27:55 +02:00
if ( ! playerState || playerState . heroes . length <= 0 )
{
2014-01-06 14:48:17 +01:00
g _previousHeroHitPoints = undefined ;
2014-01-06 14:32:48 +01:00
unitHeroPanel . hidden = true ;
2013-04-03 19:27:55 +02:00
return ;
}
2014-01-04 11:14:53 +01:00
var heroImage = Engine . GetGUIObjectByName ( "unitHeroImage" ) ;
2013-12-08 11:02:19 +01:00
var heroState = GetExtendedEntityState ( playerState . heroes [ 0 ] ) ;
2013-04-03 19:27:55 +02:00
var template = GetTemplateData ( heroState . template ) ;
heroImage . sprite = "stretched:session/portraits/" + template . icon ;
2013-09-16 11:14:16 +02:00
var hero = playerState . heroes [ 0 ] ;
2013-04-03 19:27:55 +02:00
2013-10-10 23:23:19 +02:00
heroButton . onpress = function ( )
{
2013-09-16 11:14:16 +02:00
if ( ! Engine . HotkeyIsPressed ( "selection.add" ) )
2013-10-10 23:23:19 +02:00
g _Selection . reset ( ) ;
g _Selection . addList ( [ hero ] ) ;
2013-09-16 11:14:16 +02:00
} ;
2013-10-10 23:23:19 +02:00
heroButton . ondoublepress = function ( ) { selectAndMoveTo ( getEntityOrHolder ( hero ) ) ; } ;
2014-01-06 14:32:48 +01:00
unitHeroPanel . hidden = false ;
2013-04-03 19:27:55 +02:00
// Setup tooltip
2014-04-24 15:33:15 +02:00
var tooltip = "[font=\"sans-bold-16\"]" + template . name . specific + "[/font]" ;
var healthLabel = "[font=\"sans-bold-13\"]" + translate ( "Health:" ) + "[/font]" ;
2014-04-20 22:51:48 +02:00
tooltip += "\n" + sprintf ( translate ( "%(label)s %(current)s / %(max)s" ) , { label : healthLabel , current : heroState . hitpoints , max : heroState . maxHitpoints } ) ;
2014-04-27 10:03:15 +02:00
if ( heroState . attack )
{
var attackLabel = "[font=\"sans-bold-13\"]" + getAttackTypeLabel ( heroState . attack . type ) + "[/font]" ;
if ( heroState . attack . type == "Ranged" )
// Show max attack range if ranged attack, also convert to tiles (4m per tile)
tooltip += "\n" + sprintf (
translate ( "%(attackLabel)s %(details)s, %(rangeLabel)s %(range)s" ) ,
{
attackLabel : attackLabel ,
details : damageTypeDetails ( heroState . attack ) ,
rangeLabel : "[font=\"sans-bold-13\"]" + translate ( "Range:" ) + "[/font]" ,
2014-05-02 12:32:21 +02:00
range : Math . round ( heroState . attack . maxRange ) + " [font=\"sans-10\"][color=\"orange\"]" + translate ( "meters" ) + "[/color][/font]" ,
2014-04-27 10:03:15 +02:00
}
) ;
else
2014-05-02 12:32:21 +02:00
tooltip += "\n" + sprintf ( translate ( "%(label)s %(details)s" ) , { label : attackLabel , details : damageTypeDetails ( heroState . attack ) } ) ;
2014-04-27 10:03:15 +02:00
}
2013-04-03 19:27:55 +02:00
2014-04-24 15:33:15 +02:00
var armorLabel = "[font=\"sans-bold-13\"]" + translate ( "Armor:" ) + "[/font]" ;
2014-05-02 12:32:21 +02:00
tooltip += "\n" + sprintf ( translate ( "%(label)s %(details)s" ) , { label : armorLabel , details : damageTypeDetails ( heroState . armour ) } ) ;
2013-04-03 19:27:55 +02:00
tooltip += "\n" + template . tooltip ;
heroButton . tooltip = tooltip ;
2014-01-06 14:32:48 +01:00
// update heros health bar
updateGUIStatusBar ( "heroHealthBar" , heroState . hitpoints , heroState . maxHitpoints ) ;
// define the hit points if not defined
2014-01-06 14:48:17 +01:00
if ( ! g _previousHeroHitPoints )
g _previousHeroHitPoints = heroState . hitpoints ;
2014-01-06 14:32:48 +01:00
// check, if the health of the hero changed since the last update
2014-01-06 14:48:17 +01:00
if ( heroState . hitpoints < g _previousHeroHitPoints )
2014-01-06 14:32:48 +01:00
{
2014-01-06 14:48:17 +01:00
g _previousHeroHitPoints = heroState . hitpoints ;
2014-01-06 14:32:48 +01:00
// trigger the animation
2014-01-29 15:49:36 +01:00
startColorFade ( "heroHitOverlay" , 100 , 0 , colorFade _attackUnit , true , smoothColorFadeRestart _attackUnit ) ;
2014-01-06 14:32:48 +01:00
return ;
}
}
2011-04-26 20:19:16 +02:00
function updateGroups ( )
{
var guiName = "Group" ;
2011-06-18 00:13:39 +02:00
g _Groups . update ( ) ;
2011-04-26 20:19:16 +02:00
for ( var i = 0 ; i < 10 ; i ++ )
{
2014-01-04 11:14:53 +01:00
var button = Engine . GetGUIObjectByName ( "unit" + guiName + "Button[" + i + "]" ) ;
var label = Engine . GetGUIObjectByName ( "unit" + guiName + "Label[" + i + "]" ) . caption = i ;
2011-04-26 20:19:16 +02:00
if ( g _Groups . groups [ i ] . getTotalCount ( ) == 0 )
button . hidden = true ;
else
button . hidden = false ;
2012-04-24 17:58:02 +02:00
button . onpress = ( function ( i ) { return function ( ) { performGroup ( ( Engine . HotkeyIsPressed ( "selection.add" ) ? "add" : "select" ) , i ) ; } } ) ( i ) ;
2011-06-06 21:31:34 +02:00
button . ondoublepress = ( function ( i ) { return function ( ) { performGroup ( "snap" , i ) ; } } ) ( i ) ;
2014-01-10 17:51:13 +01:00
button . onpressright = ( function ( i ) { return function ( ) { performGroup ( "breakUp" , i ) ; } } ) ( i ) ;
2011-04-26 20:19:16 +02:00
}
var numButtons = i ;
var rowLength = 1 ;
var numRows = Math . ceil ( numButtons / rowLength ) ;
2014-01-04 11:14:53 +01:00
var buttonSideLength = Engine . GetGUIObjectByName ( "unit" + guiName + "Button[0]" ) . size . bottom ;
2011-04-26 20:19:16 +02:00
var buttonSpacer = buttonSideLength + 1 ;
for ( var i = 0 ; i < numRows ; i ++ )
layoutButtonRow ( i , guiName , buttonSideLength , buttonSpacer , rowLength * i , rowLength * ( i + 1 ) ) ;
}
2013-04-10 23:05:46 +02:00
function updateDebug ( )
2010-06-30 23:34:44 +02:00
{
2013-04-10 23:05:46 +02:00
var simState = GetSimState ( ) ;
2014-01-04 11:14:53 +01:00
var debug = Engine . GetGUIObjectByName ( "debug" ) ;
2010-06-30 23:34:44 +02:00
2014-01-04 11:14:53 +01:00
if ( Engine . GetGUIObjectByName ( "devDisplayState" ) . checked )
2010-06-30 23:34:44 +02:00
{
debug . hidden = false ;
}
else
{
debug . hidden = true ;
return ;
}
2011-06-09 18:40:29 +02:00
var conciseSimState = deepcopy ( simState ) ;
conciseSimState . players = "<<<omitted>>>" ;
var text = "simulation: " + uneval ( conciseSimState ) ;
2011-08-31 04:41:21 +02:00
2010-06-30 23:34:44 +02:00
var selection = g _Selection . toList ( ) ;
if ( selection . length )
{
2013-12-08 11:02:19 +01:00
var entState = GetExtendedEntityState ( selection [ 0 ] ) ;
2010-06-30 23:34:44 +02:00
if ( entState )
{
2010-08-28 23:12:52 +02:00
var template = GetTemplateData ( entState . template ) ;
2011-06-09 18:40:29 +02:00
text += "\n\nentity: {\n" ;
for ( var k in entState )
text += " " + k + ":" + uneval ( entState [ k ] ) + "\n" ;
text += "}\n\ntemplate: " + uneval ( template ) ;
2010-06-30 23:34:44 +02:00
}
}
debug . caption = text ;
}
2013-04-10 23:05:46 +02:00
function updatePlayerDisplay ( )
2010-06-30 23:34:44 +02:00
{
2013-04-10 23:05:46 +02:00
var simState = GetSimState ( ) ;
2010-06-30 23:34:44 +02:00
var playerState = simState . players [ Engine . GetPlayerID ( ) ] ;
2010-06-30 23:41:04 +02:00
if ( ! playerState )
return ;
2014-01-31 13:01:49 +01:00
Engine . GetGUIObjectByName ( "resourceFood" ) . caption = Math . floor ( playerState . resourceCounts . food ) ;
Engine . GetGUIObjectByName ( "resourceWood" ) . caption = Math . floor ( playerState . resourceCounts . wood ) ;
Engine . GetGUIObjectByName ( "resourceStone" ) . caption = Math . floor ( playerState . resourceCounts . stone ) ;
Engine . GetGUIObjectByName ( "resourceMetal" ) . caption = Math . floor ( playerState . resourceCounts . metal ) ;
2014-01-04 11:14:53 +01:00
Engine . GetGUIObjectByName ( "resourcePop" ) . caption = playerState . popCount + "/" + playerState . popLimit ;
2011-08-31 04:41:21 +02:00
2012-04-20 19:21:04 +02:00
g _IsTrainingBlocked = playerState . trainingBlocked ;
2010-06-30 23:34:44 +02:00
}
2011-09-11 05:30:41 +02:00
2012-07-31 04:03:25 +02:00
function selectAndMoveTo ( ent )
{
var entState = GetEntityState ( ent ) ;
2013-04-06 21:32:07 +02:00
if ( ! entState || ! entState . position )
2012-07-31 04:03:25 +02:00
return ;
g _Selection . reset ( ) ;
g _Selection . addList ( [ ent ] ) ;
var position = entState . position ;
Engine . CameraMoveTo ( position . x , position . z ) ;
}
function updateResearchDisplay ( )
{
var researchStarted = Engine . GuiInterfaceCall ( "GetStartedResearch" , Engine . GetPlayerID ( ) ) ;
if ( ! researchStarted )
return ;
// Set up initial positioning.
2014-01-04 11:14:53 +01:00
var buttonSideLength = Engine . GetGUIObjectByName ( "researchStartedButton[0]" ) . size . right ;
2012-07-31 04:03:25 +02:00
for ( var i = 0 ; i < 10 ; ++ i )
{
2014-01-04 11:14:53 +01:00
var button = Engine . GetGUIObjectByName ( "researchStartedButton[" + i + "]" ) ;
2012-07-31 04:03:25 +02:00
var size = button . size ;
size . top = ( 4 + buttonSideLength ) * i ;
size . bottom = size . top + buttonSideLength ;
button . size = size ;
}
var numButtons = 0 ;
for ( var tech in researchStarted )
{
// Show at most 10 in-progress techs.
2012-07-31 05:39:35 +02:00
if ( numButtons >= 10 )
2012-07-31 04:03:25 +02:00
break ;
var template = GetTechnologyData ( tech ) ;
2014-01-04 11:14:53 +01:00
var button = Engine . GetGUIObjectByName ( "researchStartedButton[" + numButtons + "]" ) ;
2012-07-31 04:03:25 +02:00
button . hidden = false ;
2012-08-27 09:07:33 +02:00
button . tooltip = getEntityNames ( template ) ;
2012-07-31 04:03:25 +02:00
button . onpress = ( function ( e ) { return function ( ) { selectAndMoveTo ( e ) } } ) ( researchStarted [ tech ] . researcher ) ;
var icon = "stretched:session/portraits/" + template . icon ;
2014-01-04 11:14:53 +01:00
Engine . GetGUIObjectByName ( "researchStartedIcon[" + numButtons + "]" ) . sprite = icon ;
2012-07-31 04:03:25 +02:00
// Scale the progress indicator.
2014-01-04 11:14:53 +01:00
var size = Engine . GetGUIObjectByName ( "researchStartedProgressSlider[" + numButtons + "]" ) . size ;
2012-07-31 04:03:25 +02:00
// Buttons are assumed to be square, so left/right offsets can be used for top/bottom.
size . top = size . left + Math . round ( researchStarted [ tech ] . progress * ( size . right - size . left ) ) ;
2014-01-04 11:14:53 +01:00
Engine . GetGUIObjectByName ( "researchStartedProgressSlider[" + numButtons + "]" ) . size = size ;
2012-07-31 04:03:25 +02:00
++ numButtons ;
}
// Hide unused buttons.
for ( var i = numButtons ; i < 10 ; ++ i )
2014-01-04 11:14:53 +01:00
Engine . GetGUIObjectByName ( "researchStartedButton[" + i + "]" ) . hidden = true ;
2012-07-31 04:03:25 +02:00
}
2013-04-10 23:05:46 +02:00
function updateTimeElapsedCounter ( )
2011-10-14 01:20:34 +02:00
{
2013-04-10 23:05:46 +02:00
var simState = GetSimState ( ) ;
2014-01-04 11:14:53 +01:00
var timeElapsedCounter = Engine . GetGUIObjectByName ( "timeElapsedCounter" ) ;
2014-04-20 22:51:48 +02:00
if ( g _CurrentSpeed != 1.0 )
timeElapsedCounter . caption = sprintf ( translate ( "%(time)s (%(speed)sx)" ) , { time : timeToString ( simState . timeElapsed ) , speed : Engine . FormatDecimalNumberIntoString ( g _CurrentSpeed ) } ) ;
else
timeElapsedCounter . caption = timeToString ( simState . timeElapsed ) ;
2011-10-14 01:20:34 +02:00
}
2011-09-11 05:30:41 +02:00
2012-07-24 06:14:09 +02:00
// Toggles the display of status bars for all of the player's entities.
function recalculateStatusBarDisplay ( )
{
if ( g _ShowAllStatusBars )
var entities = Engine . PickFriendlyEntitiesOnScreen ( Engine . GetPlayerID ( ) ) ;
else
{
var selected = g _Selection . toList ( ) ;
for each ( var ent in g _Selection . highlighted )
selected . push ( ent ) ;
// Remove selected entities from the 'all entities' array, to avoid disabling their status bars.
var entities = Engine . GuiInterfaceCall ( "GetPlayerEntities" ) . filter (
function ( idx ) { return ( selected . indexOf ( idx ) == - 1 ) ; }
) ;
}
Engine . GuiInterfaceCall ( "SetStatusBars" , { "entities" : entities , "enabled" : g _ShowAllStatusBars } ) ;
}
2013-11-30 18:30:08 +01:00
// Update the additional list of entities to be highlighted.
function updateAdditionalHighlight ( )
{
var entsAdd = [ ] ; // list of entities units to be highlighted
var entsRemove = [ ] ;
var highlighted = g _Selection . toList ( ) ;
for each ( var ent in g _Selection . highlighted )
highlighted . push ( ent ) ;
if ( g _ShowGuarding )
{
// flag the guarding entities to add in this additional highlight
for each ( var sel in g _Selection . selected )
{
var state = GetEntityState ( sel ) ;
if ( ! state . guard || ! state . guard . entities . length )
continue ;
for each ( var ent in state . guard . entities )
if ( highlighted . indexOf ( ent ) == - 1 && entsAdd . indexOf ( ent ) == - 1 )
entsAdd . push ( ent ) ;
}
}
if ( g _ShowGuarded )
{
// flag the guarded entities to add in this additional highlight
for each ( var sel in g _Selection . selected )
{
var state = GetEntityState ( sel ) ;
if ( ! state . unitAI || ! state . unitAI . isGuarding )
continue ;
var ent = state . unitAI . isGuarding ;
if ( highlighted . indexOf ( ent ) == - 1 && entsAdd . indexOf ( ent ) == - 1 )
entsAdd . push ( ent ) ;
}
}
// flag the entities to remove (from the previously added) from this additional highlight
for each ( var ent in g _AdditionalHighlight )
if ( highlighted . indexOf ( ent ) == - 1 && entsAdd . indexOf ( ent ) == - 1 && entsRemove . indexOf ( ent ) == - 1 )
entsRemove . push ( ent ) ;
_setHighlight ( entsAdd , HIGHLIGHTED _ALPHA , true ) ;
_setHighlight ( entsRemove , 0 , false ) ;
g _AdditionalHighlight = entsAdd ;
}
2011-09-11 05:30:41 +02:00
// Temporarily adding this here
const AMBIENT _TEMPERATE = "temperate" ;
var currentAmbient ;
function playRandomAmbient ( type )
{
switch ( type )
{
case AMBIENT _TEMPERATE :
// Seem to need the underscore at the end of "temperate" to avoid crash
// (Might be caused by trying to randomly load day_temperate.xml)
// currentAmbient = newRandomSound("ambient", "temperate_", "dayscape");
const AMBIENT = "audio/ambient/dayscape/day_temperate_gen_03.ogg" ;
2013-06-10 15:58:43 +02:00
Engine . PlayAmbientSound ( AMBIENT , true ) ;
2011-09-11 05:30:41 +02:00
break ;
default :
2014-04-20 22:51:48 +02:00
Engine . Console _Write ( sprintf ( translate ( "Unrecognized ambient type: %(ambientType)s" ) , { ambientType : type } ) ) ;
2011-09-11 05:30:41 +02:00
break ;
}
}
// Temporarily adding this here
function stopAmbient ( )
{
if ( currentAmbient )
{
2012-08-15 02:10:44 +02:00
currentAmbient . free ( ) ;
2011-09-11 05:30:41 +02:00
currentAmbient = null ;
}
2011-10-14 01:20:34 +02:00
}
2014-04-20 22:51:48 +02:00
function getBuildString ( )
{
return sprintf ( translate ( "Build: %(buildDate)s (%(revision)s)" ) , { buildDate : Engine . GetBuildTimestamp ( 0 ) , revision : Engine . GetBuildTimestamp ( 2 ) } ) ;
}
function showTimeWarpMessageBox ( )
{
messageBox ( 500 , 250 , translate ( "Note: time warp mode is a developer option, and not intended for use over long periods of time. Using it incorrectly may cause the game to run out of memory or crash." ) , translate ( "Time warp mode" ) , 2 ) ;
}
2013-11-07 21:07:24 +01:00
// Send a report on the game status to the lobby
function reportGame ( extendedSimState )
{
2014-04-16 16:00:09 +02:00
if ( ! Engine . HasXmppClient ( ) || ! Engine . IsRankedGame ( ) )
2013-11-08 16:28:44 +01:00
return ;
2014-01-29 19:30:56 +01:00
// units
var unitsClasses = [
"total" ,
"Infantry" ,
"Worker" ,
"Female" ,
"Cavalry" ,
"Champion" ,
"Hero" ,
"Ship"
] ;
var unitsCountersTypes = [
"unitsTrained" ,
"unitsLost" ,
"enemyUnitsKilled"
] ;
// buildings
var buildingsClasses = [
"total" ,
"CivCentre" ,
"House" ,
"Economic" ,
"Outpost" ,
"Military" ,
"Fortress" ,
"Wonder"
] ;
var buildingsCountersTypes = [
"buildingsConstructed" ,
"buildingsLost" ,
"enemyBuildingsDestroyed"
] ;
// resources
var resourcesTypes = [
"wood" ,
"food" ,
"stone" ,
"metal"
] ;
var resourcesCounterTypes = [
"resourcesGathered" ,
"resourcesUsed" ,
"resourcesSold" ,
"resourcesBought"
] ;
2013-11-08 16:28:44 +01:00
2014-01-29 19:30:56 +01:00
var playerStatistics = { } ;
2014-01-29 20:00:47 +01:00
2013-11-07 21:07:24 +01:00
// Unit Stats
2014-01-29 19:30:56 +01:00
for each ( var unitCounterType in unitsCountersTypes )
{
if ( ! playerStatistics [ unitCounterType ] )
playerStatistics [ unitCounterType ] = { } ;
for each ( var unitsClass in unitsClasses )
playerStatistics [ unitCounterType ] [ unitsClass ] = "" ;
}
2014-01-29 20:00:47 +01:00
2014-01-29 19:30:56 +01:00
playerStatistics . unitsLostValue = "" ;
playerStatistics . unitsKilledValue = "" ;
2013-11-07 21:07:24 +01:00
// Building stats
2014-01-29 19:30:56 +01:00
for each ( var buildingCounterType in buildingsCountersTypes )
{
if ( ! playerStatistics [ buildingCounterType ] )
playerStatistics [ buildingCounterType ] = { } ;
for each ( var buildingsClass in buildingsClasses )
playerStatistics [ buildingCounterType ] [ buildingsClass ] = "" ;
}
2014-01-29 20:00:47 +01:00
2014-01-29 19:30:56 +01:00
playerStatistics . buildingsLostValue = "" ;
playerStatistics . enemyBuildingsDestroyedValue = "" ;
// Resources
for each ( var resourcesCounterType in resourcesCounterTypes )
{
if ( ! playerStatistics [ resourcesCounterType ] )
playerStatistics [ resourcesCounterType ] = { } ;
for each ( var resourcesType in resourcesTypes )
playerStatistics [ resourcesCounterType ] [ resourcesType ] = "" ;
}
playerStatistics . resourcesGathered . vegetarianFood = "" ;
2014-01-29 20:00:47 +01:00
2014-01-29 19:30:56 +01:00
playerStatistics . tradeIncome = "" ;
2013-11-07 21:07:24 +01:00
// Tribute
2014-01-29 19:30:56 +01:00
playerStatistics . tributesSent = "" ;
playerStatistics . tributesReceived = "" ;
2014-02-16 07:06:16 +01:00
// Total
playerStatistics . economyScore = "" ;
playerStatistics . militaryScore = "" ;
playerStatistics . totalScore = "" ;
2013-11-07 21:07:24 +01:00
// Various
2014-01-29 19:30:56 +01:00
playerStatistics . treasuresCollected = "" ;
playerStatistics . feminisation = "" ;
playerStatistics . percentMapExplored = "" ;
2013-11-07 21:07:24 +01:00
var mapName = Engine . GetMapSettings ( ) . Name ;
2014-01-29 19:30:56 +01:00
var playerStates = "" ;
var playerCivs = "" ;
var teams = "" ;
var teamsLocked = true ;
2013-11-07 21:07:24 +01:00
// Serialize the statistics for each player into a comma-separated list.
for each ( var player in extendedSimState . players )
{
2014-01-29 19:30:56 +01:00
playerStates += player . state + "," ;
playerCivs += player . civ + "," ;
teams += player . team + "," ;
teamsLocked = teamsLocked && player . teamsLocked ;
for each ( var resourcesCounterType in resourcesCounterTypes )
for each ( var resourcesType in resourcesTypes )
playerStatistics [ resourcesCounterType ] [ resourcesType ] += player . statistics [ resourcesCounterType ] [ resourcesType ] + "," ;
playerStatistics . resourcesGathered . vegetarianFood += player . statistics . resourcesGathered . vegetarianFood + "," ;
2014-01-29 20:00:47 +01:00
2014-01-29 19:30:56 +01:00
for each ( var unitCounterType in unitsCountersTypes )
for each ( var unitsClass in unitsClasses )
playerStatistics [ unitCounterType ] [ unitsClass ] += player . statistics [ unitCounterType ] [ unitsClass ] + "," ;
2014-01-29 20:00:47 +01:00
2014-01-29 19:30:56 +01:00
for each ( var buildingCounterType in buildingsCountersTypes )
for each ( var buildingsClass in buildingsClasses )
playerStatistics [ buildingCounterType ] [ buildingsClass ] += player . statistics [ buildingCounterType ] [ buildingsClass ] + "," ;
2014-02-16 07:06:16 +01:00
var total = 0 ;
for each ( var res in player . statistics . resourcesGathered )
total += res ;
playerStatistics . economyScore += total + "," ;
playerStatistics . militaryScore += Math . round ( ( player . statistics . enemyUnitsKilledValue +
player . statistics . enemyBuildingsDestroyedValue ) / 10 ) + "," ;
playerStatistics . totalScore += ( total + Math . round ( ( player . statistics . enemyUnitsKilledValue +
player . statistics . enemyBuildingsDestroyedValue ) / 10 ) ) + "," ;
2014-01-29 19:30:56 +01:00
playerStatistics . tradeIncome += player . statistics . tradeIncome + "," ;
playerStatistics . tributesSent += player . statistics . tributesSent + "," ;
playerStatistics . tributesReceived += player . statistics . tributesReceived + "," ;
playerStatistics . percentMapExplored += player . statistics . percentMapExplored + "," ;
playerStatistics . treasuresCollected += player . statistics . treasuresCollected + "," ;
2013-11-07 21:07:24 +01:00
}
// Send the report with serialized data
2014-01-29 19:30:56 +01:00
var reportObject = { } ;
reportObject . timeElapsed = extendedSimState . timeElapsed ;
reportObject . playerStates = playerStates ;
reportObject . playerID = Engine . GetPlayerID ( ) ;
reportObject . matchID = g _MatchID ;
reportObject . civs = playerCivs ;
reportObject . teams = teams ;
2014-01-29 20:00:47 +01:00
reportObject . teamsLocked = String ( teamsLocked ) ;
2014-01-29 19:30:56 +01:00
reportObject . mapName = mapName ;
2014-02-16 07:06:16 +01:00
reportObject . economyScore = playerStatistics . economyScore ;
reportObject . militaryScore = playerStatistics . militaryScore ;
reportObject . totalScore = playerStatistics . totalScore ;
2014-01-29 19:30:56 +01:00
for each ( var rct in resourcesCounterTypes )
{
for each ( var rt in resourcesTypes )
reportObject [ rt + rct . substr ( 9 ) ] = playerStatistics [ rct ] [ rt ] ;
// eg. rt = food rct.substr = Gathered rct = resourcesGathered
}
reportObject . vegetarianFoodGathered = playerStatistics . resourcesGathered . vegetarianFood ;
for each ( var type in unitsClasses )
{
// eg. type = Infantry (type.substr(0,1)).toLowerCase()+type.substr(1) = infantry
reportObject [ ( type . substr ( 0 , 1 ) ) . toLowerCase ( ) + type . substr ( 1 ) + "UnitsTrained" ] = playerStatistics . unitsTrained [ type ] ;
reportObject [ ( type . substr ( 0 , 1 ) ) . toLowerCase ( ) + type . substr ( 1 ) + "UnitsLost" ] = playerStatistics . unitsLost [ type ] ;
reportObject [ "enemy" + type + "UnitsKilled" ] = playerStatistics . enemyUnitsKilled [ type ] ;
}
for each ( var type in buildingsClasses )
{
reportObject [ ( type . substr ( 0 , 1 ) ) . toLowerCase ( ) + type . substr ( 1 ) + "BuildingsConstructed" ] = playerStatistics . buildingsConstructed [ type ] ;
reportObject [ ( type . substr ( 0 , 1 ) ) . toLowerCase ( ) + type . substr ( 1 ) + "BuildingsLost" ] = playerStatistics . buildingsLost [ type ] ;
reportObject [ "enemy" + type + "BuildingsDestroyed" ] = playerStatistics . enemyBuildingsDestroyed [ type ] ;
2014-01-29 20:00:47 +01:00
}
2014-01-29 19:30:56 +01:00
reportObject . tributesSent = playerStatistics . tributesSent ;
reportObject . tributesReceived = playerStatistics . tributesReceived ;
2014-02-01 04:55:24 +01:00
reportObject . percentMapExplored = playerStatistics . percentMapExplored ;
2014-01-29 19:30:56 +01:00
reportObject . treasuresCollected = playerStatistics . treasuresCollected ;
reportObject . tradeIncome = playerStatistics . tradeIncome ;
2014-01-29 20:00:47 +01:00
2014-01-29 19:30:56 +01:00
Engine . SendGameReport ( reportObject ) ;
2013-11-07 21:07:24 +01:00
}
2014-01-24 19:40:01 +01:00