Ticket #9: visualreplay-WIP-r12723.patch
File visualreplay-WIP-r12723.patch, 95.1 KB (added by , 12 years ago) |
---|
-
binaries/data/mods/public/gui/page_replay.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <page> 3 <include>common/setup.xml</include> 4 <include>common/styles.xml</include> 5 <include>common/sprite1.xml</include> 6 <include>common/icon_sprites.xml</include> 7 8 <include>common/common_sprites.xml</include> 9 <include>common/common_styles.xml</include> 10 11 <include>session/sprites.xml</include> 12 <include>session/styles.xml</include> 13 <include>replay/replay.xml</include> 14 <include>common/global.xml</include> 15 </page> -
binaries/data/mods/public/gui/replay/input.js
1 const SDL_BUTTON_LEFT = 1; 2 const SDL_BUTTON_MIDDLE = 2; 3 const SDL_BUTTON_RIGHT = 3; 4 const SDLK_LEFTBRACKET = 91; 5 const SDLK_RIGHTBRACKET = 93; 6 const SDLK_RSHIFT = 303; 7 const SDLK_LSHIFT = 304; 8 const SDLK_RCTRL = 305; 9 const SDLK_LCTRL = 306; 10 const SDLK_RALT = 307; 11 const SDLK_LALT = 308; 12 // TODO: these constants should be defined somewhere else instead, in 13 // case any other code wants to use them too 14 15 const ACTION_NONE = 0; 16 const ACTION_GARRISON = 1; 17 const ACTION_REPAIR = 2; 18 var preSelectedAction = ACTION_NONE; 19 20 const INPUT_NORMAL = 0; 21 const INPUT_SELECTING = 1; 22 const INPUT_BANDBOXING = 2; 23 24 var inputState = INPUT_NORMAL; 25 26 var mouseX = 0; 27 var mouseY = 0; 28 var mouseIsOverObject = false; 29 30 // Number of pixels the mouse can move before the action is considered a drag 31 var maxDragDelta = 4; 32 33 // Time in milliseconds in which a double click is recognized 34 const doubleClickTime = 500; 35 var doubleClickTimer = 0; 36 var doubleClicked = false; 37 // Store the previously clicked entity - ensure a double/triple click happens on the same entity 38 var prevClickedEntity = 0; 39 40 // Same double-click behaviour for hotkey presses 41 const doublePressTime = 500; 42 var doublePressTimer = 0; 43 var prevHotkey = 0; 44 45 46 var dragStart; // used for remembering mouse coordinates at start of drag operations 47 48 // Limits bandboxed selections to certain types of entities based on priority 49 function getPreferredEntities(ents) 50 { 51 var entStateList = []; 52 var preferredEnts = []; 53 54 // Check if there are units in the selection and get a list of entity states 55 for each (var ent in ents) 56 { 57 var entState = GetEntityState(ent); 58 if (!entState) 59 continue; 60 if (hasClass(entState, "Unit")) 61 preferredEnts.push(ent); 62 63 entStateList.push(entState); 64 } 65 66 // If there are no units, check if there are defensive entities in the selection 67 if (!preferredEnts.length) 68 for (var i = 0; i < ents.length; i++) 69 if (hasClass(entStateList[i], "Defensive")) 70 preferredEnts.push(ents[i]); 71 72 return preferredEnts; 73 } 74 75 // Removes any support units from the passed list of entities 76 function getMilitaryEntities(ents) 77 { 78 var militaryEnts = []; 79 for each (var ent in ents) 80 { 81 var entState = GetEntityState(ent); 82 if (!hasClass(entState, "Support")) 83 militaryEnts.push(ent); 84 } 85 return militaryEnts; 86 } 87 88 function handleInputBeforeGui(ev, hoveredObject) 89 { 90 // Capture mouse position so we can use it for displaying cursors, 91 // and key states 92 switch (ev.type) 93 { 94 case "mousebuttonup": 95 case "mousebuttondown": 96 case "mousemotion": 97 mouseX = ev.x; 98 mouseY = ev.y; 99 break; 100 } 101 102 // Remember whether the mouse is over a GUI object or not 103 mouseIsOverObject = (hoveredObject != null); 104 105 // Close the menu when interacting with the game world 106 if (!mouseIsOverObject && (ev.type =="mousebuttonup" || ev.type == "mousebuttondown") 107 && (ev.button == SDL_BUTTON_LEFT || ev.button == SDL_BUTTON_RIGHT)) 108 closeMenu(); 109 110 // State-machine processing: 111 // 112 // (This is for states which should override the normal GUI processing - events will 113 // be processed here before being passed on, and propagation will stop if this function 114 // returns true) 115 // 116 // TODO: it'd probably be nice to have a better state-machine system, with guaranteed 117 // entry/exit functions, since this is a bit broken now 118 119 switch (inputState) 120 { 121 case INPUT_BANDBOXING: 122 switch (ev.type) 123 { 124 case "mousemotion": 125 var x0 = dragStart[0]; 126 var y0 = dragStart[1]; 127 var x1 = ev.x; 128 var y1 = ev.y; 129 if (x0 > x1) { var t = x0; x0 = x1; x1 = t; } 130 if (y0 > y1) { var t = y0; y0 = y1; y1 = t; } 131 132 var bandbox = getGUIObjectByName("bandbox"); 133 bandbox.size = [x0, y0, x1, y1].join(" "); 134 bandbox.hidden = false; 135 136 // TODO: Should we handle "control all units" here as well? 137 var ents = Engine.PickFriendlyEntitiesInRect(x0, y0, x1, y1, Engine.GetPlayerID()); 138 g_Selection.setHighlightList(ents); 139 140 return false; 141 142 case "mousebuttonup": 143 if (ev.button == SDL_BUTTON_LEFT) 144 { 145 var x0 = dragStart[0]; 146 var y0 = dragStart[1]; 147 var x1 = ev.x; 148 var y1 = ev.y; 149 if (x0 > x1) { var t = x0; x0 = x1; x1 = t; } 150 if (y0 > y1) { var t = y0; y0 = y1; y1 = t; } 151 152 var bandbox = getGUIObjectByName("bandbox"); 153 bandbox.hidden = true; 154 155 // Get list of entities limited to preferred entities 156 // TODO: Should we handle "control all units" here as well? 157 var ents = Engine.PickFriendlyEntitiesInRect(x0, y0, x1, y1, Engine.GetPlayerID()); 158 var preferredEntities = getPreferredEntities(ents) 159 160 if (preferredEntities.length) 161 { 162 ents = preferredEntities; 163 164 if (Engine.HotkeyIsPressed("selection.milonly")) 165 { 166 var militaryEntities = getMilitaryEntities(ents); 167 if (militaryEntities.length) 168 ents = militaryEntities; 169 } 170 } 171 172 // Remove the bandbox hover highlighting 173 g_Selection.setHighlightList([]); 174 175 // Update the list of selected units 176 if (Engine.HotkeyIsPressed("selection.add")) 177 { 178 g_Selection.addList(ents); 179 } 180 else if (Engine.HotkeyIsPressed("selection.remove")) 181 { 182 g_Selection.removeList(ents); 183 } 184 else 185 { 186 g_Selection.reset(); 187 g_Selection.addList(ents); 188 } 189 190 inputState = INPUT_NORMAL; 191 return true; 192 } 193 else if (ev.button == SDL_BUTTON_RIGHT) 194 { 195 // Cancel selection 196 var bandbox = getGUIObjectByName("bandbox"); 197 bandbox.hidden = true; 198 199 g_Selection.setHighlightList([]); 200 201 inputState = INPUT_NORMAL; 202 return true; 203 } 204 break; 205 } 206 break; 207 } 208 209 return false; 210 } 211 212 function handleInputAfterGui(ev) 213 { 214 if (ev.hotkey == "session.showstatusbars") 215 { 216 g_ShowAllStatusBars = (ev.type == "hotkeydown"); 217 recalculateStatusBarDisplay(); 218 } 219 220 // State-machine processing: 221 222 switch (inputState) 223 { 224 case INPUT_NORMAL: 225 switch (ev.type) 226 { 227 case "mousemotion": 228 // Highlight the first hovered entity (if any) 229 var ents = Engine.PickEntitiesAtPoint(ev.x, ev.y); 230 if (ents.length) 231 g_Selection.setHighlightList([ents[0]]); 232 else 233 g_Selection.setHighlightList([]); 234 235 return false; 236 237 case "mousebuttondown": 238 if (ev.button == SDL_BUTTON_LEFT) 239 { 240 dragStart = [ ev.x, ev.y ]; 241 inputState = INPUT_SELECTING; 242 return true; 243 } 244 break; 245 } 246 break; 247 248 case INPUT_SELECTING: 249 switch (ev.type) 250 { 251 case "mousemotion": 252 // If the mouse moved further than a limit, switch to bandbox mode 253 var dragDeltaX = ev.x - dragStart[0]; 254 var dragDeltaY = ev.y - dragStart[1]; 255 256 if (Math.abs(dragDeltaX) >= maxDragDelta || Math.abs(dragDeltaY) >= maxDragDelta) 257 { 258 inputState = INPUT_BANDBOXING; 259 return false; 260 } 261 262 var ents = Engine.PickEntitiesAtPoint(ev.x, ev.y); 263 g_Selection.setHighlightList(ents); 264 return false; 265 266 case "mousebuttonup": 267 if (ev.button == SDL_BUTTON_LEFT) 268 { 269 var ents = Engine.PickEntitiesAtPoint(ev.x, ev.y); 270 if (!ents.length) 271 { 272 if (!Engine.HotkeyIsPressed("selection.add") && !Engine.HotkeyIsPressed("selection.remove")) 273 { 274 g_Selection.reset(); 275 resetIdleUnit(); 276 } 277 inputState = INPUT_NORMAL; 278 return true; 279 } 280 281 var selectedEntity = ents[0]; 282 var now = new Date(); 283 284 // If camera following and we select different unit, stop 285 if (Engine.GetFollowedEntity() != selectedEntity) 286 { 287 Engine.CameraFollow(0); 288 } 289 290 if ((now.getTime() - doubleClickTimer < doubleClickTime) && (selectedEntity == prevClickedEntity)) 291 { 292 // Double click or triple click has occurred 293 var showOffscreen = Engine.HotkeyIsPressed("selection.offscreen"); 294 var matchRank = true; 295 var templateToMatch; 296 297 // Check for double click or triple click 298 if (!doubleClicked) 299 { 300 // If double click hasn't already occurred, this is a double click. 301 // Select similar units regardless of rank 302 templateToMatch = Engine.GuiInterfaceCall("GetEntityState", selectedEntity).identity.selectionGroupName; 303 if (templateToMatch) 304 { 305 matchRank = false; 306 } 307 else 308 { // No selection group name defined, so fall back to exact match 309 templateToMatch = Engine.GuiInterfaceCall("GetEntityState", selectedEntity).template; 310 } 311 312 doubleClicked = true; 313 // Reset the timer so the user has an extra period 'doubleClickTimer' to do a triple-click 314 doubleClickTimer = now.getTime(); 315 } 316 else 317 { 318 // Double click has already occurred, so this is a triple click. 319 // Select units matching exact template name (same rank) 320 templateToMatch = Engine.GuiInterfaceCall("GetEntityState", selectedEntity).template; 321 } 322 323 // TODO: Should we handle "control all units" here as well? 324 ents = Engine.PickSimilarFriendlyEntities(templateToMatch, showOffscreen, matchRank, false); 325 } 326 else 327 { 328 // It's single click right now but it may become double or triple click 329 doubleClicked = false; 330 doubleClickTimer = now.getTime(); 331 prevClickedEntity = selectedEntity; 332 333 // We only want to include the first picked unit in the selection 334 ents = [ents[0]]; 335 } 336 337 // Update the list of selected units 338 if (Engine.HotkeyIsPressed("selection.add")) 339 { 340 g_Selection.addList(ents); 341 } 342 else if (Engine.HotkeyIsPressed("selection.remove")) 343 { 344 g_Selection.removeList(ents); 345 } 346 else 347 { 348 g_Selection.reset(); 349 g_Selection.addList(ents); 350 } 351 352 inputState = INPUT_NORMAL; 353 return true; 354 } 355 break; 356 } 357 break; 358 } 359 return false; 360 } 361 362 // Called by unit selection buttons 363 function changePrimarySelectionGroup(templateName) 364 { 365 if (Engine.HotkeyIsPressed("session.deselectgroup")) 366 g_Selection.makePrimarySelection(templateName, true); 367 else 368 g_Selection.makePrimarySelection(templateName, false); 369 } 370 371 372 // Set the camera to follow the given unit 373 function setCameraFollow(entity) 374 { 375 // Follow the given entity if it's a unit 376 if (entity) 377 { 378 var entState = GetEntityState(entity); 379 if (entState && hasClass(entState, "Unit")) 380 { 381 Engine.CameraFollow(entity); 382 return; 383 } 384 } 385 386 // Otherwise stop following 387 Engine.CameraFollow(0); 388 } 389 390 var lastIdleUnit = 0; 391 var currIdleClass = 0; 392 var lastIdleType = undefined; 393 394 function resetIdleUnit() 395 { 396 lastIdleUnit = 0; 397 currIdleClass = 0; 398 lastIdleType = undefined; 399 } 400 401 function findIdleUnit(classes) 402 { 403 var append = Engine.HotkeyIsPressed("selection.add"); 404 var selectall = Engine.HotkeyIsPressed("selection.offscreen"); 405 406 // Reset the last idle unit, etc., if the selection type has changed. 407 var type = classes.join(); 408 if (selectall || type != lastIdleType) 409 resetIdleUnit(); 410 lastIdleType = type; 411 412 // If selectall is true, there is no limit and it's necessary to iterate 413 // over all of the classes, resetting only when the first match is found. 414 var matched = false; 415 416 for (var i = 0; i < classes.length; ++i) 417 { 418 var data = { idleClass: classes[currIdleClass], prevUnit: lastIdleUnit, limit: 1 }; 419 if (append) 420 data.excludeUnits = g_Selection.toList(); 421 422 if (selectall) 423 data = { idleClass: classes[currIdleClass] }; 424 425 // Check if we have new valid entity 426 var idleUnits = Engine.GuiInterfaceCall("FindIdleUnits", data); 427 if (idleUnits.length && idleUnits[0] != lastIdleUnit) 428 { 429 lastIdleUnit = idleUnits[0]; 430 if (!append && (!selectall || selectall && !matched)) 431 g_Selection.reset() 432 433 if (selectall) 434 g_Selection.addList(idleUnits); 435 else 436 { 437 g_Selection.addList([lastIdleUnit]); 438 Engine.CameraFollow(lastIdleUnit); 439 return; 440 } 441 442 matched = true; 443 } 444 445 lastIdleUnit = 0; 446 currIdleClass = (currIdleClass + 1) % classes.length; 447 } 448 449 // TODO: display a message or play a sound to indicate no more idle units, or something 450 // Reset for next cycle 451 resetIdleUnit(); 452 } 453 454 // Ignored: we ignore these callbacks in replay mode 455 function removeFromProductionQueue() {}; 456 function unloadTemplate() {}; 457 function unloadAll() {}; -
binaries/data/mods/public/gui/replay/input.js
-
binaries/data/mods/public/gui/replay/menu.js
Property changes on: binaries/data/mods/public/gui/replay/input.js ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property
1 const PAUSE = "Pause"; 2 const RESUME = "Resume"; 3 4 /* 5 * MENU POSITION CONSTANTS 6 */ 7 8 // Menu / panel border size 9 const MARGIN = 4; 10 11 // Includes the main menu button 12 const NUM_BUTTONS = 4; 13 14 // Regular menu buttons 15 const BUTTON_HEIGHT = 32; 16 17 // The position where the bottom of the menu will end up (currently 228) 18 const END_MENU_POSITION = (BUTTON_HEIGHT * NUM_BUTTONS) + MARGIN; 19 20 // Menu starting position: bottom 21 const MENU_BOTTOM = 0; 22 23 // Menu starting position: top 24 const MENU_TOP = MENU_BOTTOM - END_MENU_POSITION; 25 26 // Menu starting position: overall 27 const INITIAL_MENU_POSITION = "100%-164 " + MENU_TOP + " 100% " + MENU_BOTTOM; 28 29 // Number of pixels per millisecond to move 30 const MENU_SPEED = 1.2; 31 32 var isMenuOpen = false; 33 var menu; 34 35 // Ignore size defined in XML and set the actual menu size here 36 function initMenuPosition() 37 { 38 menu = getGUIObjectByName("menu"); 39 menu.size = INITIAL_MENU_POSITION; 40 } 41 42 43 // ============================================================================= 44 // Overall Menu 45 // ============================================================================= 46 // 47 // Slide menu 48 function updateMenuPosition(dt) 49 { 50 if (isMenuOpen) 51 { 52 var maxOffset = END_MENU_POSITION - menu.size.bottom; 53 if (maxOffset > 0) 54 { 55 var offset = Math.min(MENU_SPEED * dt, maxOffset); 56 var size = menu.size; 57 size.top += offset; 58 size.bottom += offset; 59 menu.size = size; 60 } 61 } 62 else 63 { 64 var maxOffset = menu.size.top - MENU_TOP; 65 if (maxOffset > 0) 66 { 67 var offset = Math.min(MENU_SPEED * dt, maxOffset); 68 var size = menu.size; 69 size.top -= offset; 70 size.bottom -= offset; 71 menu.size = size; 72 } 73 } 74 } 75 76 // Opens the menu by revealing the screen which contains the menu 77 function openMenu() 78 { 79 // playButtonSound(); 80 isMenuOpen = true; 81 } 82 83 // Closes the menu and resets position 84 function closeMenu() 85 { 86 // playButtonSound(); 87 isMenuOpen = false; 88 } 89 90 function toggleMenu() 91 { 92 if (isMenuOpen == true) 93 closeMenu(); 94 else 95 openMenu(); 96 } 97 98 // Menu buttons 99 // ============================================================================= 100 function settingsMenuButton() 101 { 102 closeMenu(); 103 closeOpenDialogs(); 104 openSettings(true); 105 } 106 107 function pauseMenuButton() 108 { 109 togglePause(); 110 } 111 112 function resignMenuButton() 113 { 114 closeMenu(); 115 closeOpenDialogs(); 116 pauseGame(); 117 var btCaptions = ["Yes", "No"]; 118 var btCode = [resignGame, resumeGame]; 119 messageBox(400, 200, "Are you sure you want to resign?", "Confirmation", 0, btCaptions, btCode); 120 } 121 122 function exitMenuButton() 123 { 124 closeMenu(); 125 closeOpenDialogs(); 126 pauseGame(); 127 var btCaptions = ["Yes", "No"]; 128 var btCode = [leaveGame, resumeGame]; 129 messageBox(400, 200, "Are you sure you want to quit?", "Confirmation", 0, btCaptions, btCode); 130 } 131 132 function openDeleteDialog(selection) 133 { 134 closeMenu(); 135 closeOpenDialogs(); 136 137 var deleteSelectedEntities = function () 138 { 139 Engine.PostNetworkCommand({"type": "delete-entities", "entities": selection}); 140 }; 141 142 var btCaptions = ["Yes", "No"]; 143 var btCode = [deleteSelectedEntities, resumeGame]; 144 145 messageBox(400, 200, "Destroy everything currently selected?", "Delete", 0, btCaptions, btCode); 146 } 147 148 // Menu functions 149 // ============================================================================= 150 151 function openSettings(pause) 152 { 153 getGUIObjectByName("settingsDialogPanel").hidden = false; 154 if (pause) 155 pauseGame(); 156 } 157 158 function closeSettings(resume) 159 { 160 getGUIObjectByName("settingsDialogPanel").hidden = true; 161 if (resume) 162 resumeGame(); 163 } 164 165 function pauseGame() 166 { 167 getGUIObjectByName("pauseButtonText").caption = RESUME; 168 getGUIObjectByName("pauseOverlay").hidden = false; 169 setPaused(true); 170 } 171 172 function resumeGame() 173 { 174 getGUIObjectByName("pauseButtonText").caption = PAUSE; 175 getGUIObjectByName("pauseOverlay").hidden = true; 176 setPaused(false); 177 } 178 179 function togglePause() 180 { 181 closeMenu(); 182 closeOpenDialogs(); 183 184 var pauseOverlay = getGUIObjectByName("pauseOverlay"); 185 186 if (pauseOverlay.hidden) 187 { 188 getGUIObjectByName("pauseButtonText").caption = RESUME; 189 setPaused(true); 190 191 } 192 else 193 { 194 setPaused(false); 195 getGUIObjectByName("pauseButtonText").caption = PAUSE; 196 } 197 198 pauseOverlay.hidden = !pauseOverlay.hidden; 199 } 200 201 function toggleDeveloperOverlay() 202 { 203 var devCommands = getGUIObjectByName("devCommands"); 204 devCommands.hidden = !devCommands.hidden; 205 } 206 207 function closeOpenDialogs() 208 { 209 closeMenu(); 210 closeSettings(false); 211 } -
binaries/data/mods/public/gui/replay/menu.js
-
binaries/data/mods/public/gui/replay/replay.js
Property changes on: binaries/data/mods/public/gui/replay/menu.js ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property
1 // Network Mode 2 var g_IsNetworked = false; 3 4 // Cache the basic player data (name, civ, color) 5 var g_Players = []; 6 // Cache the useful civ data 7 var g_CivData = {}; 8 9 var g_PlayerAssignments = { "local": { "name": "You", "player": 1 } }; 10 11 // Cache dev-mode settings that are frequently or widely used 12 var g_DevSettings = { 13 controlAll: false 14 }; 15 16 // Whether status bars should be shown for all of the player's units. 17 var g_ShowAllStatusBars = false; 18 19 // Indicate when one of the current player's training queues is blocked 20 // (this is used to support population counter blinking) 21 var g_IsTrainingBlocked = false; 22 23 // Cache EntityStates 24 var g_EntityStates = {}; // {id:entState} 25 26 // Whether the player has lost/won and reached the end of their game 27 var g_GameEnded = false; 28 29 // Colors to flash when pop limit reached 30 const DEFAULT_POPULATION_COLOR = "white"; 31 const POPULATION_ALERT_COLOR = "orange"; 32 33 function GetEntityState(entId) 34 { 35 if (!(entId in g_EntityStates)) 36 { 37 var entState = Engine.GuiInterfaceCall("GetEntityState", entId); 38 g_EntityStates[entId] = entState; 39 } 40 41 return g_EntityStates[entId]; 42 } 43 44 // Cache TemplateData 45 var g_TemplateData = {}; // {id:template} 46 47 48 function GetTemplateData(templateName) 49 { 50 if (!(templateName in g_TemplateData)) 51 { 52 var template = Engine.GuiInterfaceCall("GetTemplateData", templateName); 53 g_TemplateData[templateName] = template; 54 } 55 56 return g_TemplateData[templateName]; 57 } 58 59 // Cache TechnologyData 60 var g_TechnologyData = {}; // {id:template} 61 62 function GetTechnologyData(technologyName) 63 { 64 if (!(technologyName in g_TechnologyData)) 65 { 66 var template = Engine.GuiInterfaceCall("GetTechnologyData", technologyName); 67 g_TechnologyData[technologyName] = template; 68 } 69 70 return g_TechnologyData[technologyName]; 71 } 72 73 // Init 74 function init(initData, hotloadData) 75 { 76 if (initData) 77 { 78 g_IsNetworked = initData.isNetworked; // Set network mode 79 g_PlayerAssignments = initData.playerAssignments; 80 81 // Cache the player data 82 // (This may be updated at runtime by handleNetMessage) 83 g_Players = getPlayerData(g_PlayerAssignments); 84 } 85 else // Needed for autostart loading option 86 { 87 g_Players = getPlayerData(null); 88 } 89 90 // Cache civ data 91 g_CivData = loadCivData(); 92 g_CivData["gaia"] = { "Code": "gaia", "Name": "Gaia", "Emblem": "session/icons/groups.png" }; 93 94 initMenuPosition(); // set initial position 95 96 // Populate player selection dropdown 97 var playerNames = []; 98 var playerIDs = []; 99 for (var player in g_Players) 100 { 101 playerNames.push(g_Players[player].name); 102 playerIDs.push(player); 103 } 104 105 var viewPlayerDropdown = getGUIObjectByName("viewPlayer"); 106 viewPlayerDropdown.list = playerNames; 107 viewPlayerDropdown.list_data = playerIDs; 108 viewPlayerDropdown.selected = 1; 109 110 // If in Atlas editor, disable the exit button 111 if (Engine.IsAtlasRunning()) 112 getGUIObjectByName("menuExitButton").enabled = false; 113 114 if (hotloadData) 115 { 116 g_Selection.selected = hotloadData.selection; 117 } 118 119 onSimulationUpdate(); 120 121 // Report the performance after 5 seconds (when we're still near 122 // the initial camera view) and a minute (when the profiler will 123 // have settled down if framerates as very low), to give some 124 // extremely rough indications of performance 125 setTimeout(function() { reportPerformance(5); }, 5000); 126 setTimeout(function() { reportPerformance(60); }, 60000); 127 } 128 129 function selectViewPlayer(playerID) 130 { 131 Engine.SetPlayerID(playerID); 132 getGUIObjectByName("civIcon").sprite = "stretched:" + g_CivData[g_Players[playerID].civ].Emblem; 133 getGUIObjectByName("civIcon").tooltip = g_CivData[g_Players[playerID].civ].Name; 134 } 135 136 function reportPerformance(time) 137 { 138 var settings = Engine.GetMapSettings(); 139 var data = { 140 time: time, 141 map: settings.Name, 142 seed: settings.Seed, // only defined for random maps 143 size: settings.Size, // only defined for random maps 144 profiler: Engine.GetProfilerState() 145 }; 146 147 Engine.SubmitUserReport("profile", 3, JSON.stringify(data)); 148 } 149 150 function leaveGame() 151 { 152 var extendedSimState = Engine.GuiInterfaceCall("GetExtendedSimulationState"); 153 154 var mapSettings = Engine.GetMapSettings(); 155 156 endGame(); 157 158 Engine.SwitchGuiPage("page_summary.xml", { 159 "gameResult" : "Replay mode ended", 160 "timeElapsed" : extendedSimState.timeElapsed, 161 "playerStates": extendedSimState.players, 162 "players": g_Players, 163 "mapSettings": mapSettings 164 }); 165 } 166 167 // Return some data that we'll use when hotloading this file after changes 168 function getHotloadData() 169 { 170 return { selection: g_Selection.selected }; 171 } 172 173 var lastTickTime = new Date; 174 175 /** 176 * Called every frame. 177 */ 178 function onTick() 179 { 180 var now = new Date; 181 var tickLength = new Date - lastTickTime; 182 lastTickTime = now; 183 184 while (true) 185 { 186 var message = Engine.PollNetworkClient(); 187 if (!message) 188 break; 189 handleNetMessage(message); 190 } 191 192 // If the selection changed, we need to regenerate the sim display (the display depends on both the 193 // simulation state and the current selection). 194 if (g_Selection.dirty) 195 { 196 onSimulationUpdate(); 197 198 // Display rally points for selected buildings 199 Engine.GuiInterfaceCall("DisplayRallyPoint", { "entities": g_Selection.toList() }); 200 } 201 202 // Run timers 203 updateTimers(); 204 205 // Animate menu 206 updateMenuPosition(tickLength); 207 208 // When training is blocked, flash population (alternates colour every 500msec) 209 if (g_IsTrainingBlocked && (Date.now() % 1000) < 500) 210 getGUIObjectByName("resourcePop").textcolor = POPULATION_ALERT_COLOR; 211 else 212 getGUIObjectByName("resourcePop").textcolor = DEFAULT_POPULATION_COLOR; 213 214 // Clear renamed entities list 215 Engine.GuiInterfaceCall("ClearRenamedEntities"); 216 } 217 218 function onReplayFinished() 219 { 220 closeMenu(); 221 closeOpenDialogs(); 222 pauseGame(); 223 var btCaptions = ["Yes", "No"]; 224 var btCode = [leaveGame, resumeGame]; 225 messageBox(400, 200, "The replay has finished. Do you want to quit?", "Confirmation", 0, btCaptions, btCode); 226 } 227 228 /** 229 * Recomputes GUI state that depends on simulation state or selection state. Called directly every simulation 230 * update (see session.xml), or from onTick when the selection has changed. 231 */ 232 function onSimulationUpdate() 233 { 234 g_Selection.dirty = false; 235 g_EntityStates = {}; 236 g_TemplateData = {}; 237 g_TechnologyData = {}; 238 239 var simState = Engine.GuiInterfaceCall("GetSimulationState"); 240 241 // If we're called during init when the game is first loading, there will be no simulation yet, so do nothing 242 if (!simState) 243 return; 244 245 handleNotifications(); 246 247 if (g_ShowAllStatusBars) 248 recalculateStatusBarDisplay(); 249 250 updateDebug(simState); 251 updatePlayerDisplay(simState); 252 updateSelectionDetails(true); 253 updateResearchDisplay(); 254 updateTimeElapsedCounter(simState); 255 } 256 257 function updateDebug(simState) 258 { 259 var debug = getGUIObjectByName("debug"); 260 261 if (getGUIObjectByName("devDisplayState").checked) 262 { 263 debug.hidden = false; 264 } 265 else 266 { 267 debug.hidden = true; 268 return; 269 } 270 271 var conciseSimState = deepcopy(simState); 272 conciseSimState.players = "<<<omitted>>>"; 273 var text = "simulation: " + uneval(conciseSimState); 274 275 var selection = g_Selection.toList(); 276 if (selection.length) 277 { 278 var entState = GetEntityState(selection[0]); 279 if (entState) 280 { 281 var template = GetTemplateData(entState.template); 282 text += "\n\nentity: {\n"; 283 for (var k in entState) 284 text += " "+k+":"+uneval(entState[k])+"\n"; 285 text += "}\n\ntemplate: " + uneval(template); 286 } 287 } 288 289 debug.caption = text; 290 } 291 292 function updatePlayerDisplay(simState) 293 { 294 var playerState = simState.players[Engine.GetPlayerID()]; 295 if (!playerState) 296 return; 297 298 getGUIObjectByName("resourceFood").caption = playerState.resourceCounts.food; 299 getGUIObjectByName("resourceWood").caption = playerState.resourceCounts.wood; 300 getGUIObjectByName("resourceStone").caption = playerState.resourceCounts.stone; 301 getGUIObjectByName("resourceMetal").caption = playerState.resourceCounts.metal; 302 getGUIObjectByName("resourcePop").caption = playerState.popCount + "/" + playerState.popLimit; 303 304 g_IsTrainingBlocked = playerState.trainingBlocked; 305 } 306 307 function selectAndMoveTo(ent) 308 { 309 var entState = GetEntityState(ent); 310 if (!entState) 311 return; 312 313 g_Selection.reset(); 314 g_Selection.addList([ent]); 315 316 var position = entState.position; 317 Engine.CameraMoveTo(position.x, position.z); 318 } 319 320 function updateResearchDisplay() 321 { 322 var researchStarted = Engine.GuiInterfaceCall("GetStartedResearch", Engine.GetPlayerID()); 323 if (!researchStarted) 324 return; 325 326 // Set up initial positioning. 327 var buttonSideLength = getGUIObjectByName("researchStartedButton[0]").size.right; 328 for (var i = 0; i < 10; ++i) 329 { 330 var button = getGUIObjectByName("researchStartedButton[" + i + "]"); 331 var size = button.size; 332 size.top = (4 + buttonSideLength) * i; 333 size.bottom = size.top + buttonSideLength; 334 button.size = size; 335 } 336 337 var numButtons = 0; 338 for (var tech in researchStarted) 339 { 340 // Show at most 10 in-progress techs. 341 if (numButtons >= 10) 342 break; 343 344 var template = GetTechnologyData(tech); 345 var button = getGUIObjectByName("researchStartedButton[" + numButtons + "]"); 346 button.hidden = false; 347 button.tooltip = getEntityNames(template); 348 button.onpress = (function(e) { return function() { selectAndMoveTo(e) } })(researchStarted[tech].researcher); 349 350 var icon = "stretched:session/portraits/" + template.icon; 351 getGUIObjectByName("researchStartedIcon[" + numButtons + "]").sprite = icon; 352 353 // Scale the progress indicator. 354 var size = getGUIObjectByName("researchStartedProgressSlider[" + numButtons + "]").size; 355 356 // Buttons are assumed to be square, so left/right offsets can be used for top/bottom. 357 size.top = size.left + Math.round(researchStarted[tech].progress * (size.right - size.left)); 358 getGUIObjectByName("researchStartedProgressSlider[" + numButtons + "]").size = size; 359 360 ++numButtons; 361 } 362 363 // Hide unused buttons. 364 for (var i = numButtons; i < 10; ++i) 365 getGUIObjectByName("researchStartedButton[" + i + "]").hidden = true; 366 } 367 368 function updateTimeElapsedCounter(simState) 369 { 370 var timeElapsedCounter = getGUIObjectByName("timeElapsedCounter"); 371 timeElapsedCounter.caption = timeToString(simState.timeElapsed); 372 } 373 374 // Toggles the display of status bars for all of the player's entities. 375 function recalculateStatusBarDisplay() 376 { 377 if (g_ShowAllStatusBars) 378 var entities = Engine.PickFriendlyEntitiesOnScreen(Engine.GetPlayerID()); 379 else 380 { 381 var selected = g_Selection.toList(); 382 for each (var ent in g_Selection.highlighted) 383 selected.push(ent); 384 385 // Remove selected entities from the 'all entities' array, to avoid disabling their status bars. 386 var entities = Engine.GuiInterfaceCall("GetPlayerEntities").filter( 387 function(idx) { return (selected.indexOf(idx) == -1); } 388 ); 389 } 390 391 Engine.GuiInterfaceCall("SetStatusBars", { "entities": entities, "enabled": g_ShowAllStatusBars }); 392 } 393 394 // Temporarily adding this here 395 const AMBIENT_TEMPERATE = "temperate"; 396 var currentAmbient; 397 function playRandomAmbient(type) 398 { 399 switch (type) 400 { 401 case AMBIENT_TEMPERATE: 402 // Seem to need the underscore at the end of "temperate" to avoid crash 403 // (Might be caused by trying to randomly load day_temperate.xml) 404 // currentAmbient = newRandomSound("ambient", "temperate_", "dayscape"); 405 406 const AMBIENT = "audio/ambient/dayscape/day_temperate_gen_03.ogg"; 407 currentAmbient = new AmbientSound(AMBIENT); 408 409 if (currentAmbient) 410 { 411 currentAmbient.loop(); 412 } 413 break; 414 415 default: 416 console.write("Unrecognized ambient type: " + type); 417 break; 418 } 419 } 420 421 // Temporarily adding this here 422 function stopAmbient() 423 { 424 if (currentAmbient) 425 { 426 currentAmbient.free(); 427 currentAmbient = null; 428 } 429 } -
binaries/data/mods/public/gui/replay/replay.js
-
binaries/data/mods/public/gui/replay/replay.xml
Property changes on: binaries/data/mods/public/gui/replay/replay.js ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property
1 <?xml version="1.0" encoding="utf-8"?> 2 3 <objects> 4 5 <script file="gui/common/functions_civinfo.js"/> 6 <script file="gui/common/functions_utility.js" /> 7 <script file="gui/common/functions_global_object.js" /> 8 <script file="gui/common/timer.js"/> 9 <script file="gui/replay/input.js"/> 10 <script file="gui/replay/menu.js"/> 11 <script file="gui/replay/replay.js"/> 12 <script file="gui/session/messages.js"/> 13 <script file="gui/session/selection.js"/> 14 <script file="gui/session/selection_details.js"/> 15 <script file="gui/session/unit_commands.js"/> 16 <script file="gui/session/utility_functions.js"/> 17 18 <object name="sn" hotkey="session.gui.toggle"> 19 <action on="Tick"> 20 onTick(); 21 </action> 22 23 <action on="SimulationUpdate"> 24 onSimulationUpdate(); 25 </action> 26 27 <action on="ReplayFinished"> 28 onReplayFinished(); 29 </action> 30 31 <action on="Press"> 32 this.hidden = !this.hidden; 33 </action> 34 35 <!-- ================================ ================================ --> 36 <!-- HOTKEYS (For some reason, they won't work properly unless outside menu) --> 37 <!-- ================================ ================================ --> 38 39 <!-- Exit button Hotkey --> 40 <!-- 41 <action on="Press"><![CDATA[ 42 messageBox(400, 200, "Do you really want to quit?", "Confirmation", 0, 43 ["Yes", "No!"], [leaveGame, null]); 44 ]]></action> 45 --> 46 47 <object hotkey="leave"> 48 <action on="Press">closeOpenDialogs();</action> 49 </object> 50 51 <!-- Menu --> 52 <object hotkey="menu.toggle"> 53 <action on="Press">openMenu();</action> 54 </object> 55 56 <!-- Unit silhouettes --> 57 <object hotkey="silhouettes"> 58 <action on="Press">renderer.silhouettes = !renderer.silhouettes;</action> 59 </object> 60 61 <!-- Sky --> 62 <object hotkey="showsky"> 63 <action on="Press">renderer.showsky = !renderer.showsky;</action> 64 </object> 65 66 <!-- Pause --> 67 <object hotkey="pause"> 68 <action on="Press">togglePause();</action> 69 </object> 70 71 <!-- camera.follow mode - follow the first unit in the selection --> 72 <object hotkey="camera.follow"> 73 <action on="Press">setCameraFollow(g_Selection.toList()[0]);</action> 74 </object> 75 76 <!-- Find idle warrior - TODO: Potentially move this to own UI button? --> 77 <object hotkey="selection.idlewarrior"> 78 <action on="Press">findIdleUnit(["Hero", "Champion", "CitizenSoldier", "Siege", "Warship"]);</action> 79 </object> 80 81 <!-- ================================ ================================ --> 82 <!-- Developer / Debug items --> 83 <!-- ================================ ================================ --> 84 85 <!-- Debug text --> 86 <object name="debug" 87 type="text" 88 size="0 70 80% 100%" 89 ghost="true" 90 textcolor="yellow" 91 font="mono-stroke-10" 92 /> 93 94 <!-- Dev/cheat commands --> 95 <object name="devCommands" size="100%-156 50%-88 100%-8 50%+88" type="image" sprite="devCommandsBackground" z="40" 96 hidden="true" hotkey="session.devcommands.toggle"> 97 <action on="Press"> 98 toggleDeveloperOverlay(); 99 </action> 100 101 <object size="0 16 100%-18 32" type="text" style="devCommandsText">Display selection state</object> 102 <object size="100%-16 16 100% 32" type="checkbox" name="devDisplayState" style="StoneCrossBox"/> 103 104 <object size="0 32 100%-18 48" type="text" style="devCommandsText">Pathfinder overlay</object> 105 <object size="100%-16 32 100% 48" type="checkbox" style="StoneCrossBox"> 106 <action on="Press">Engine.GuiInterfaceCall("SetPathfinderDebugOverlay", this.checked);</action> 107 </object> 108 109 <object size="0 48 100%-18 64" type="text" style="devCommandsText">Obstruction overlay</object> 110 <object size="100%-16 48 100% 64" type="checkbox" style="StoneCrossBox"> 111 <action on="Press">Engine.GuiInterfaceCall("SetObstructionDebugOverlay", this.checked);</action> 112 </object> 113 114 <object size="0 64 100%-18 80" type="text" style="devCommandsText">Unit motion overlay</object> 115 <object size="100%-16 64 100% 80" type="checkbox" style="StoneCrossBox"> 116 <action on="Press">g_Selection.SetMotionDebugOverlay(this.checked);</action> 117 </object> 118 119 <object size="0 80 100%-18 96" type="text" style="devCommandsText">Range overlay</object> 120 <object size="100%-16 80 100% 96" type="checkbox" style="StoneCrossBox"> 121 <action on="Press">Engine.GuiInterfaceCall("SetRangeDebugOverlay", this.checked);</action> 122 </object> 123 124 <object size="0 96 100%-18 112" type="text" style="devCommandsText">Bounding box overlay</object> 125 <object size="100%-16 96 100% 112" type="checkbox" style="StoneCrossBox"> 126 <action on="Press">Engine.SetBoundingBoxDebugOverlay(this.checked);</action> 127 </object> 128 129 <object size="0 112 100%-18 128" type="text" style="devCommandsText">Restrict camera</object> 130 <object size="100%-16 112 100% 128" type="checkbox" style="StoneCrossBox" checked="true"> 131 <action on="Press">gameView.constrainCamera = this.checked;</action> 132 </object> 133 134 <object size="0 128 100%-18 144" type="text" style="devCommandsText">Reveal map</object> 135 <object size="100%-16 128 100% 144" type="checkbox" name="devCommandsRevealMap" style="StoneCrossBox"> 136 <action on="Press">Engine.PostNetworkCommand({"type": "reveal-map", "enable": this.checked});</action> 137 </object> 138 139 </object> 140 141 <!-- ================================ ================================ --> 142 <!-- Time elapsed counter --> 143 <!-- ================================ ================================ --> 144 <object size="100%-100 50 100%-10 70" type="text" name="timeElapsedCounter" style="SettingsText" hotkey="timeelapsedcounter.toggle" ghost="true"> 145 <action on="Press"><![CDATA[ 146 this.hidden = !this.hidden; 147 ]]> 148 </action> 149 </object> 150 151 <object size="50%-400 50 50%-50 100" type="text" font="serif-bold-24" textcolor="white" ghost="true">Non-interactive Replay Mode</object> 152 153 <!-- ================================ ================================ --> 154 <!-- Pause Overlay --> 155 <!-- ================================ ================================ --> 156 <object type="button" 157 name="pauseOverlay" 158 size="0 0 100% 100%" 159 tooltip_style="sessionToolTip" 160 hidden="true" 161 z="0" 162 > 163 <object size="0 0 100% 100%" type="image" sprite="devCommandsBackground" ghost="true" z="0"/> 164 <object size="50%-128 50%-20 50%+128 50%+20" type="text" style="PauseText" ghost="true" z="0">Replay Paused</object> 165 <object size="50%-128 50%+20 50%+128 50%+30" type="text" style="PauseMessageText" ghost="true" z="0">Click to Resume Replay</object> 166 <action on="Press">togglePause();</action> 167 </object> 168 169 <!-- ================================ ================================ --> 170 <!-- Notification Area --> 171 <!-- ================================ ================================ --> 172 <object name="notificationPanel" type="image" size="50%-300 60 50%+300 120" ghost="true"> 173 <object name="notificationText" size="0 0 100% 100%" type="text" style="notificationPanel" ghost="true"/> 174 </object> 175 176 <!-- ================================ ================================ --> 177 <!-- Chat --> 178 <!-- ================================ ================================ --> 179 180 <!-- Chat panel --> 181 <object name="chatPanel" size="0 130 100% 100%-240" type="image" ghost="true"> 182 <object name="chatText" size="3 1 100%-1 100%-1" type="text" style="chatPanel" ghost="true"/> 183 </object> 184 185 <!-- ================================ ================================ --> 186 <!-- Settings Window --> 187 <!-- ================================ ================================ --> 188 <object name="settingsDialogPanel" 189 style="StoneDialog" 190 type="image" 191 size="50%-180 50%-200 50%+180 50%+100" 192 hidden="true" 193 > 194 <object type="text" style="TitleText" size="50%-96 -16 50%+96 16">Settings</object> 195 196 <object style="TranslucentPanelThinBorder" 197 type="image" 198 size="32 32 100%-32 100%-70" 199 > 200 <!-- Settings / shadows --> 201 <object size="0 10 100%-80 35" type="text" style="RightLabelText" ghost="true">Enable Shadows</object> 202 <object name="shadowsCheckbox" size="100%-56 15 100%-30 40" type="checkbox" style="StoneCrossBox" checked="true"> 203 <action on="Load">if (renderer.shadows) this.checked = true; else this.checked = false;</action> 204 <action on="Press">renderer.shadows = this.checked;</action> 205 </object> 206 207 <!-- Settings / Shadow PCF --> 208 <object size="0 35 100%-80 60" type="text" style="RightLabelText" ghost="true">Enable Shadow Filtering</object> 209 <object name="shadowPCFCheckbox" size="100%-56 40 100%-30 65" type="checkbox" style="StoneCrossBox" checked="true"> 210 <action on="Load">if (renderer.shadowPCF) this.checked = true; else this.checked = false;</action> 211 <action on="Press">renderer.shadowPCF = this.checked;</action> 212 </object> 213 214 <!-- Settings / Water --> 215 <object size="0 60 100%-80 85" type="text" style="RightLabelText" ghost="true">Enable Water Reflections</object> 216 <object name="fancyWaterCheckbox" size="100%-56 65 100%-30 90" type="checkbox" style="StoneCrossBox" checked="true"> 217 <action on="Load">if (renderer.fancyWater) this.checked = true; else this.checked = false;</action> 218 <action on="Press">renderer.fancyWater = this.checked;</action> 219 </object> 220 221 <!-- Settings / Particles --> 222 <object size="0 85 100%-80 110" type="text" style="RightLabelText" ghost="true">Enable Particles</object> 223 <object name="particlesCheckbox" size="100%-56 90 100%-30 115" type="checkbox" style="StoneCrossBox" checked="true"> 224 <action on="Load">if (renderer.particles) this.checked = true; else this.checked = false;</action> 225 <action on="Press">renderer.particles = this.checked;</action> 226 </object> 227 228 <!-- Settings / Unit Silhouettes --> 229 <object size="0 110 100%-80 135" type="text" style="RightLabelText" ghost="true">Enable Unit Silhouettes</object> 230 <object name="silhouettesCheckbox" size="100%-56 115 100%-30 140" type="checkbox" style="StoneCrossBox" checked="true"> 231 <action on="Load">if (renderer.silhouettes) this.checked = true; else this.checked = false;</action> 232 <action on="Press">renderer.silhouettes = this.checked;</action> 233 </object> 234 235 <!-- Settings / Dev Overlay --> 236 <object size="0 160 100%-80 185" type="text" style="RightLabelText" ghost="true">Developer Overlay</object> 237 <object size="100%-56 165 100%-30 190" type="checkbox" style="StoneCrossBox" checked="false"> 238 <action on="Press">toggleDeveloperOverlay();</action> 239 </object> 240 </object> 241 242 <!-- Close button --> 243 <object type="button" 244 style="StoneButton" 245 size="50%-64 100%-52 50%+64 100%-24" 246 tooltip_style="sessionToolTip" 247 > 248 Close 249 <action on="Press">closeSettings(true);</action> 250 </object> 251 </object> 252 253 <!-- ================================ ================================ --> 254 <!-- Top Panel --> 255 <!-- ================================ ================================ --> 256 <object name="topPanel" 257 type="image" 258 sprite="topPanel" 259 size="-3 0 100%+3 36" 260 > 261 <!-- ================================ ================================ --> 262 <!-- Player resource bar --> 263 <!-- ================================ ================================ --> 264 <object 265 size="10 0 45% 100%" 266 > 267 <!-- Food --> 268 <object size="0 0 90 100%" type="image" style="resourceCounter" tooltip="Food" tooltip_style="sessionToolTipBold"> 269 <object size="0 -4 40 36" type="image" sprite="stretched:session/icons/resources/food.png" ghost="true"/> 270 <object size="32 0 100% 100%-2" type="text" style="resourceText" name="resourceFood"/> 271 </object> 272 273 <!-- Wood --> 274 <object size="90 0 180 100%" type="image" style="resourceCounter" tooltip="Wood" tooltip_style="sessionToolTipBold"> 275 <object size="0 -4 40 36" type="image" sprite="stretched:session/icons/resources/wood.png" ghost="true"/> 276 <object size="32 0 100% 100%-2" type="text" style="resourceText" name="resourceWood"/> 277 </object> 278 279 <!-- Stone --> 280 <object size="180 0 270 100%" type="image" style="resourceCounter" tooltip="Stone" tooltip_style="sessionToolTipBold"> 281 <object size="0 -4 40 36" type="image" sprite="stretched:session/icons/resources/stone.png" ghost="true"/> 282 <object size="32 0 100% 100%-2" type="text" style="resourceText" name="resourceStone"/> 283 </object> 284 285 <!-- Metal --> 286 <object size="270 0 360 100%" type="image" style="resourceCounter" tooltip="Metal" tooltip_style="sessionToolTipBold"> 287 <object size="0 -4 40 36" type="image" sprite="stretched:session/icons/resources/metal.png" ghost="true"/> 288 <object size="32 0 100% 100%-2" type="text" style="resourceText" name="resourceMetal"/> 289 </object> 290 291 <!-- Population --> 292 <object size="360 0 450 100%" type="image" style="resourceCounter" tooltip="Population (current / limit)" tooltip_style="sessionToolTipBold"> 293 <object size="0 -4 40 34" type="image" sprite="stretched:session/icons/resources/population.png" ghost="true"/> 294 <object size="32 0 100% 100%-2" type="text" style="resourceText" name="resourcePop"/> 295 </object> 296 </object> 297 298 <!-- ================================ ================================ --> 299 <!-- Civ Icon --> 300 <!-- ================================ ================================ --> 301 <object size="50%-48 -26 50%+48 70" name="civIcon" type="image" tooltip_style="sessionToolTipBold"/> 302 303 <object size="50%+50 5 50%+150 100%-5" name="viewPlayer" type="dropdown" style="StoneDropDown" tooltip_style="sessionToolTipBold" tooltip="Choose player to view"> 304 <action on="SelectionChange">selectViewPlayer(this.selected);</action> 305 </object> 306 307 <!-- ================================ ================================ --> 308 <!-- Phase --> 309 <!-- ================================ ================================ --> 310 <!--<object size="50%+50 4 50%+300 100%-2" name="PhaseTitleBar" type="text" font="serif-bold-stroke-14" textcolor="white"> Death Match :: Village Phase</object>--> 311 312 313 <!-- ================================ ================================ --> 314 <!-- ALPHA LABELS (alpha, build time, revision) --> 315 <!-- ================================ ================================ --> 316 317 <!-- Displays Alpha name and number --> 318 <object size="70%-50 0 70%+128 100%" name="alphaLabel" type="text" style="CenteredLabelText" text_valign="top" ghost="true"> 319 ALPHA XI : Kronos<!-- IMPORTANT: remember to update pregame/mainmenu.xml in sync with this --> 320 321 <!-- Displays build date and revision number--> 322 <object size="50%-128 0 50%+128 100%-2" name="buildTimeLabel" type="text" style="BuildNameText" ghost="true"> 323 <action on="Load"><![CDATA[this.caption = buildTime(0) + " (" + buildTime(2) + ")";]]> 324 </action> 325 </object> 326 </object> 327 328 <!-- ================================ ================================ --> 329 <!-- Menu Button --> 330 <!-- ================================ ================================ --> 331 <object type="button" 332 name="menuButton" 333 size="100%-164 4 100%-8 32" 334 style="StoneButtonFancy" 335 tooltip_style="sessionToolTip" 336 z="70" 337 > 338 <!-- This object covers up the text on the menu 339 buttons as they slide by so that you don't see 340 them on top of the main menu button --> 341 <object size="0 -4 100% 0" type="image" sprite="horizontalThinBorder" ghost="true"/> 342 343 <object size="50%-32 50%-16 50%+32 50%+16" type="image" sprite="menuButton" ghost="true">MENU</object> 344 <action on="Press"> 345 toggleMenu(); 346 </action> 347 </object> <!-- END OF MENU BUTTON --> 348 </object> <!-- END OF TOP PANEL --> 349 350 <!-- ================================ ================================ --> 351 <!-- Menu --> 352 <!-- ================================ ================================ --> 353 <object name="menu" 354 style="StonePanelThinBorder" 355 type="image" 356 hidden="false" 357 z="40" 358 > 359 <object size="4 36 100%-4 50%+20"> 360 361 <!-- Settings button --> 362 <object type="button" 363 name="settingsButton" 364 style="StoneButtonFancy" 365 size="0 0 100% 28" 366 tooltip_style="sessionToolTip" 367 > 368 Settings 369 <action on="Press">settingsMenuButton();</action> 370 </object> 371 372 <!-- Exit button --> 373 <object type="button" 374 name="menuExitButton" 375 style="StoneButtonFancy" 376 size="0 32 100% 60" 377 tooltip_style="sessionToolTip" 378 > 379 Exit 380 <action on="Press">exitMenuButton();</action> 381 </object> 382 383 <!-- Pause / Resume Button --> 384 <object type="button" 385 name="pauseButton" 386 style="StoneButtonFancy" 387 size="0 64 100% 92" 388 tooltip_style="sessionToolTip" 389 > 390 <object name="pauseButtonText" type="text" style="CenteredButtonText" ghost="true">Pause</object> 391 <action on="Press">togglePause();</action> 392 </object> 393 </object> 394 </object> 395 396 <!-- In-progress research --> 397 <object size="100%-50 85 100%-10 100%-200"> 398 <repeat count="10"> 399 <object name="researchStartedButton[n]" hidden="true" style="iconButton" type="button" size="0 0 40 40" tooltip_style="sessionToolTipBottom"> 400 <object name="researchStartedIcon[n]" ghost="true" type="image" size="3 3 37 37"/> 401 <object name="researchStartedProgressSlider[n]" type="image" sprite="queueProgressSlider" ghost="true" size="3 3 37 37"/> 402 </object> 403 </repeat> 404 </object> 405 406 <!-- ================================ ================================ --> 407 <!-- Unit Selection Groups --> 408 <!-- ================================ ================================ --> 409 <!--<object 410 name="unitGroupPanel" 411 size="0% 50%-216 0%+36 50%+144" 412 > 413 <repeat count="10"> 414 <object name="unitGroupButton[n]" size="0 0 36 36" type="button" hidden="false" style="iconButton" tooltip_style="sessionToolTipBottomBold" 415 tooltip="Click to select grouped units."> 416 <object name="unitGroupIcon[n]" size="3 3 33 33" type="image" sprite="groupsIcon" ghost="true"/> 417 <object name="unitGroupLabel[n]" type="text" style="largeCenteredOutlinedText" ghost="true"/> 418 </object> 419 </repeat> 420 </object>--> 421 422 <!-- ================================ ================================ --> 423 <!-- Information tooltip 424 Follows the mouse around if 'independent' is set to 'true'. --> 425 <!-- ================================ ================================ --> 426 <object name="informationTooltip" type="tooltip" independent="true" style="informationTooltip"/> 427 428 <!-- ================================ ================================ --> 429 <!-- Wall-dragging tooltip. Shows the total cost of building a wall while the player is dragging it. --> 430 <!-- ================================ ================================ --> 431 <object name="wallDragTooltip" type="tooltip" independent="true" style="informationTooltip"/> 432 433 <!-- ================================ ================================ --> 434 <!-- START of BOTTOM PANEL --> 435 <!-- ================================ ================================ --> 436 437 <object size="50%-512 100%-180 50%+512 100%"> 438 439 <!-- ================================ ================================ --> 440 <!-- Minimap --> 441 <!-- ================================ ================================ --> 442 <object 443 name="minimapPanel" 444 size="0 100%-212 212 100%" 445 type="image" 446 sprite="mapPanel" 447 z="20" 448 > 449 <object name="minimap" 450 type="minimap" 451 size="14 14 100%-14 100%-14" 452 > 453 <action on="WorldClick">handleMinimapEvent(arguments[0]);</action> 454 </object> 455 456 <object name="minimapOverlay" size="10 10 100%-10 100%-10" type="image" sprite="stretched:session/minimap_circle.png" ghost="true"/> 457 458 <!-- Idle Worker Button --> 459 <object type="image" 460 size="100%-36 4 100%-4 36" 461 > 462 <object type="button" 463 style="iconButton" 464 tooltip_style="sessionToolTip" 465 tooltip="Find idle worker" 466 hotkey="selection.idleworker" 467 > 468 <!-- TODO: should highlight the button if there's non-zero idle workers --> 469 <object size="0 0 100% 100%" type="image" sprite="idleWorker" ghost="true" /> 470 <action on="Press">findIdleUnit(["Female", "Trade", "FishingBoat", "CitizenSoldier", "Healer"]);</action> 471 </object> 472 </object> 473 </object> 474 475 <!-- ================================ ================================ --> 476 <!-- Supplemental Details Panel (Left of Selection Details) --> 477 <!-- ================================ ================================ --> 478 <object size="50%-304 100%-170 50%-110 100%" name="supplementalSelectionDetails" type="image" sprite="supplementalDetailsPanel" z="20"> 479 480 <object name="unitFormationPanel" 481 size="24 12 100% 100%" 482 > 483 <object size="0 0 100% 100%"> 484 <repeat count="16"> 485 <object name="unitFormationButton[n]" hidden="true" style="iconButton" type="button" size="0 0 36 36" tooltip_style="sessionToolTipBottomBold" z="100"> 486 <object name="unitFormationIcon[n]" type="image" ghost="true" size="3 3 33 33"/> 487 <object name="unitFormationSelection[n]" hidden="true" type="image" ghost="true" size="3 3 33 33" sprite="stretched:session/icons/corners.png"/> 488 </object> 489 </repeat> 490 </object> 491 </object> 492 493 <object name="unitGarrisonPanel" 494 size="24 12 100% 100%" 495 > 496 <object size="0 0 100% 100%"> 497 <repeat count="12"> 498 <object name="unitGarrisonButton[n]" hidden="true" style="iconButton" type="button" size="0 0 36 36" tooltip_style="sessionToolTipBottomBold" z="100"> 499 <object name="unitGarrisonIcon[n]" type="image" ghost="true" size="3 3 33 33"/> 500 <object name="unitGarrisonCount[n]" ghost="true" style="groupIconsText" type="text" size="0 0 100% 100%"/> 501 </object> 502 </repeat> 503 </object> 504 </object> 505 506 <object name="unitBarterPanel" 507 size="6 36 100% 100%" 508 hidden="true" 509 > 510 <object ghost="true" style="resourceText" type="text" size="0 0 100% 20">Exchange resources:</object> 511 <object size="0 32 100% 78"> 512 <repeat count="4"> 513 <object name="unitBarterSellButton[n]" style="iconButton" type="button" size="0 0 46 46" tooltip_style="sessionToolTipBottomBold"> 514 <object name="unitBarterSellIcon[n]" type="image" ghost="true" size="3 3 43 43"/> 515 <object name="unitBarterSellUnaffordable[n]" hidden="true" type="image" ghost="true" size="3 3 43 43" sprite="colour: 255 0 0 60"/> 516 <object name="unitBarterSellAmount[n]" ghost="true" style="resourceText" type="text" size="0 0 100% 50%"/> 517 <object name="unitBarterSellSelection[n]" hidden="true" type="image" ghost="true" size="3 3 43 43" sprite="stretched:session/icons/corners.png"/> 518 </object> 519 </repeat> 520 </object> 521 <object size="0 78 100% 124"> 522 <repeat count="4"> 523 <object name="unitBarterBuyButton[n]" style="iconButton" type="button" size="0 0 46 46" tooltip_style="sessionToolTipBottomBold"> 524 <object name="unitBarterBuyIcon[n]" type="image" ghost="true" size="3 3 43 43"/> 525 <object name="unitBarterBuyUnaffordable[n]" hidden="true" type="image" ghost="true" size="3 3 43 43" sprite="colour: 255 0 0 60"/> 526 <object name="unitBarterBuyAmount[n]" ghost="true" style="resourceText" type="text" size="0 0 100% 50%"/> 527 </object> 528 </repeat> 529 </object> 530 </object> 531 532 <!-- Stance Selection --> 533 <object name="unitStancePanel" 534 style="TranslucentPanel" 535 size="4 100%-43 100%-4 100%-4" 536 type="text" 537 > 538 <object size="1 2 100% 100%"> 539 <repeat count="5"> 540 <object name="unitStanceButton[n]" hidden="true" style="iconButton" type="button" size="0 0 36 36" tooltip_style="sessionToolTipBottomBold" z="100"> 541 <object name="unitStanceIcon[n]" type="image" ghost="true" size="3 3 33 33"/> 542 <object name="unitStanceSelection[n]" hidden="true" type="image" ghost="true" size="3 3 33 33" sprite="stretched:session/icons/corners.png"/> 543 </object> 544 </repeat> 545 </object> 546 </object> 547 </object> 548 549 <!-- ================================ ================================ --> 550 <!-- Selection Details Panel (Middle) --> 551 <!-- ================================ ================================ --> 552 <object name="selectionDetails" 553 type="image" 554 sprite="selectionDetailsPanel" 555 size="50%-114 100%-205 50%+114 100%" 556 hidden="false" 557 > 558 <!-- Unit details for Single Unit --> 559 <object size="50%-112 0 50%+112 100%" name="detailsAreaSingle"> 560 561 <!-- Stats Bars --> 562 <object size= "2 0 100%-2 98" type="image" tooltip_style="sessionToolTip"> 563 564 <object size="0 8 100% 60" type="image" sprite="edgedPanelShader"> 565 <!-- Health bar --> 566 <object size="88 0 100% 24" name="healthSection"> 567 <object size="0 0 100% 16" name="healthLabel" type="text" style="StatsTextLeft" ghost="true">Health:</object> 568 <object size="0 0 100% 16" name="healthStats" type="text" style="StatsTextRight" ghost="true"/> 569 <object size="1 16 100% 23" name="health" type="image"> 570 <object type="image" sprite="barBorder" ghost="true" size="-1 -1 100%+1 100%+1"/> 571 <object type="image" sprite="healthBackground" ghost="true"/> 572 <object type="image" sprite="healthForeground" ghost="true" name="healthBar"/> 573 <object type="image" sprite="statsBarShaderHorizontal" ghost="true"/> 574 </object> 575 </object> 576 577 <!-- Stamina bar --> 578 <object size="88 28 100% 52" name="staminaSection"> 579 <object size="0 0 100% 16" name="staminaLabel" type="text" style="StatsTextLeft" ghost="true">Stamina:</object> 580 <object size="0 0 100% 16" name="staminaStats" type="text" style="StatsTextRight" ghost="true"/> 581 <object size="1 16 100% 23" name="stamina" type="image"> 582 <object type="image" sprite="barBorder" ghost="true" size="-1 -1 100%+1 100%+1"/> 583 <object type="image" sprite="staminaBackground" ghost="true"/> 584 <object type="image" sprite="staminaForeground" ghost="true" name="staminaBar"/> 585 <object type="image" sprite="statsBarShaderHorizontal" ghost="true"/> 586 </object> 587 </object> 588 589 <!-- Resource bar --> 590 <object size="88 28 100% 52" name="resourceSection"> 591 <object size="0 0 100% 16" name="resourceLabel" type="text" style="StatsTextLeft" ghost="true"/> 592 <object size="0 0 100% 16" name="resourceStats" type="text" style="StatsTextRight" ghost="true"/> 593 <object size="1 16 100% 23" name="resources" type="image"> 594 <object type="image" sprite="barBorder" ghost="true" size="-1 -1 100%+1 100%+1"/> 595 <object type="image" sprite="resourceBackground" ghost="true"/> 596 <object type="image" sprite="resourceForeground" ghost="true" name="resourceBar"/> 597 <object type="image" sprite="statsBarShaderHorizontal" ghost="true"/> 598 </object> 599 </object> 600 </object> 601 602 <object size="0 60 100% 96" type="image" sprite="edgedPanelShader"> 603 <!-- Attack and Armor --> 604 <object size="90 -2 126 34" name="attackAndArmorStats" type="image" sprite="stretched:session/icons/stances/defensive.png" tooltip="Attack and Armor" tooltip_style="sessionToolTip"/> 605 606 <!-- Resource carrying icon/counter --> 607 <object size="100%-78 -2 100%-28 34" type="text" name="resourceCarryingText" style="CarryingTextRight"/> 608 <object size="100%-36 -2 100% 34" type="image" name="resourceCarryingIcon"/> 609 </object> 610 611 <!-- Big unit icon --> 612 <object size="-8 -8 88 88" type="image" name="iconBorder" sprite="iconBorder" tooltip_style="sessionToolTip"> 613 <object size="1 1 100%-1 100%-1" type="image" name="icon" ghost="true"/> 614 615 <!-- Experience bar --> 616 <object size="2 2 6 100%-2" type="image" name="experience" tooltip="Experience" tooltip_style="sessionToolTip"> 617 <object type="image" sprite="barBorder" ghost="true" size="-1 -1 100%+1 100%+1"/> 618 <object type="image" sprite="experienceBackground" ghost="true"/> 619 <object type="image" sprite="experienceForeground" ghost="true" name="experienceBar"/> 620 <object type="image" sprite="statsBarShaderVertical" ghost="true"/> 621 </object> 622 623 <object z="20" size="4 4 20 20" name="rankIcon" type="image" tooltip="Rank" tooltip_style="sessionToolTip"/> 624 </object> 625 </object> 626 627 <!-- Names (this must come before the attack and armor icon to avoid clipping issues) --> 628 <object size="2 96 100%-2 100%-36" name="statsArea" type="image" sprite="edgedPanelShader"> 629 630 <!-- These images are used to clip off the top and bottom of the civ icon --> 631 <object z="30" size="0 -5 100% 40" ghost="true" type="image" sprite="remove"/> 632 <object z="30" size="0 100%-5 100% 100%+40" ghost="true" type="image" sprite="remove"/> 633 634 <object z="30" size="0 2 100% 45" ghost="true"> 635 <!-- Specific Name --> 636 <object size="0 0 100% 20" name="specific" ghost="true" type="text" style="SpecificNameCentered"/> 637 638 <!-- Generic Name --> 639 <object size="0 15 100% 36" name="generic" ghost="true" type="text" style="GenericNameCentered"/> 640 </object> 641 642 <!-- Player Name and Civ --> 643 <object size="0 40 100% 100%"> 644 <object size="50%-64 50%-64 50%+64 50%+64" name="playerCivIcon" type="image" ghost="true"/> 645 <object size="0 0 100% 100%" name="playerColorBackground" type="image" sprite="playerColorBackground" ghost="true"/> 646 <object size="0 0 100% 100%" type="image" sprite="bottomEdgedPanelShader" ghost="true"/> 647 648 <!-- Why is this being automatically ghosted? In the mean time, set ghost to false --> 649 <object ghost="false" size="0 0 100% 100%-5" name="player" type="text" style="largeCenteredOutlinedText" tooltip_style="sessionToolTip"/> 650 </object> 651 </object> 652 653 </object> 654 655 <!-- Unit details for Multiple Units --> 656 <object size="50%-112 0 50%+112 100%" name="detailsAreaMultiple"> 657 658 <object name="unitSelectionPanel" 659 size="20 12 100%-20 100%" 660 > 661 <object size="0 0 100% 100%"> 662 <repeat count="16"> 663 <object name="unitSelectionButton[n]" hidden="true" style="iconButton" type="button" size="0 0 36 36" tooltip_style="sessionToolTipBold" z="100"> 664 <object name="unitSelectionIcon[n]" type="image" ghost="true" size="3 3 33 33"/> 665 <object name="unitSelectionCount[n]" ghost="true" style="groupIconsText" type="text" size="0 0 100% 100%"/> 666 <object size="0 100%-3 100% 100%" name="unitSelectionHealth[n]" ghost="true"> 667 </object> 668 </object> 669 </repeat> 670 </object> 671 </object> 672 673 <!-- Total --> 674 <object size="100%-42 12 100%-8 46" type="image" sprite="groupsIcon"> 675 <object size="0 0 100% 100%" type="text" style="largeCenteredOutlinedText" name="numberOfUnits"/> 676 </object> 677 678 <!-- Stats Bars --> 679 <object size= "100%-38 50 100%-18 100%-44" type="image" tooltip_style="sessionToolTip"> 680 <!-- Health bar --> 681 <object size="4 0 11 100%" type="image" name="healthMultiple" tooltip="Hitpoints" tooltip_style="sessionToolTip"> 682 <object type="image" sprite="barBorder" ghost="true" size="-1 -1 100%+1 100%+1"/> 683 <object type="image" sprite="healthBackground" ghost="true"/> 684 <object type="image" sprite="healthForeground" ghost="true" name="healthBarMultiple"/> 685 <object type="image" sprite="statsBarShaderVertical" ghost="true"/> 686 </object> 687 688 <!-- Stamina bar --> 689 <object size="15 0 22 100%" type="image" name="staminaMultiple" tooltip="Stamina" tooltip_style="sessionToolTipBold"> 690 <object type="image" sprite="barBorder" ghost="true" size="-1 -1 100%+1 100%+1"/> 691 <object type="image" sprite="staminaBackground" ghost="true"/> 692 <object type="image" sprite="staminaForeground" ghost="true" name="staminaBarMultiple"/> 693 <object type="image" sprite="statsBarShaderVertical" ghost="true"/> 694 </object> 695 </object> 696 </object> 697 698 <!-- Unit Commands --> 699 <object name="unitCommandPanel" 700 size="0 100%-36 100% 100%-4" 701 type="image" 702 z="30" 703 > 704 <object size="0 1 100% 100%"> 705 <repeat count="6"> 706 <object name="unitCommandButton[n]" hidden="true" style="iconButton" type="button" size="0 0 32 32" tooltip_style="sessionToolTipBottomBold"> 707 <object name="unitCommandIcon[n]" ghost="true" type="image" size="0 0 100% 100%" style="commandIcon"/> 708 <object name="unitCommandCount[n]" ghost="true" style="groupIconsText" type="text" size="0 0 100% 100%"/> 709 </object> 710 </repeat> 711 </object> 712 </object> 713 714 <!-- shading for unit commands area --> 715 <object z="50" size="4 100%-36 100%-4 100%-4" ghost="true" type="image" sprite="bottomEdgedPanelShader"/> 716 717 </object> <!-- END OF SELECTION DETAILS --> 718 719 <!-- ================================ ================================ --> 720 <!-- Commands Panel (Right of Selection Details) --> 721 <!-- ================================ ================================ --> 722 <object name="unitCommands" 723 type="image" 724 sprite="unitCommandsPanel" 725 size="50%+110 100%-170 50%+512 100%" 726 hidden="false" 727 z="20" 728 > 729 <object name="unitConstructionPanel" 730 size="10 12 100% 100%" 731 > 732 <object size="0 0 100% 100%"> 733 <repeat count="24"> 734 <object name="unitConstructionButton[n]" hidden="true" style="iconButton" type="button" size="0 0 46 46" tooltip_style="sessionToolTipBottom"> 735 <object name="unitConstructionIcon[n]" type="image" ghost="true" size="3 3 43 43"/> 736 <object name="unitConstructionUnaffordable[n]" hidden="true" type="image" ghost="true" size="3 3 43 43" sprite="colour: 255 0 0 127"/> 737 </object> 738 </repeat> 739 </object> 740 </object> 741 742 <object name="unitResearchPanel" 743 size="10 100%-102 100% 100%" 744 > 745 <object size="0 0 100% 100%"> 746 <repeat count="16"> 747 <object name="unitResearchButton[n]" hidden="true" style="iconButton" type="button" size="0 0 46 46" tooltip_style="sessionToolTipBottom"> 748 <object name="unitResearchIcon[n]" type="image" ghost="true" size="3 3 43 43"/> 749 <object name="unitResearchSelection[n]" hidden="true" type="image" ghost="true" size="3 3 43 43" sprite="colour: 255 0 0 127"/> 750 <object name="unitResearchUnaffordable[n]" hidden="true" type="image" ghost="true" size="3 3 43 43" sprite="colour: 255 0 0 60"/> 751 </object> 752 </repeat> 753 <repeat count="8"> 754 <object name="unitResearchPair[n]" hidden="true" size="0 0 46 92"> 755 <object name="unitResearchPairIcon[n]" type="image" ghost="true" size="8 38 38 54" sprite="stretched:session/icons/vertical_pair.png"/> 756 </object> 757 </repeat> 758 </object> 759 </object> 760 761 <object name="unitTrainingPanel" 762 size="10 12 100% 100%" 763 > 764 <object size="0 0 100% 100%"> 765 <repeat count="24"> 766 <object name="unitTrainingButton[n]" hidden="true" style="iconButton" type="button" size="0 0 46 46" tooltip_style="sessionToolTipBottom"> 767 <object name="unitTrainingIcon[n]" type="image" ghost="true" size="3 3 43 43"/> 768 <object name="unitTrainingUnaffordable[n]" hidden="true" type="image" ghost="true" size="3 3 43 43" sprite="colour: 255 0 0 127"/> 769 </object> 770 </repeat> 771 </object> 772 </object> 773 774 <object name="unitTradingPanel" 775 size="10 12 100% 100%" 776 > 777 <object size="0 0 100% 100%"> 778 <repeat count="4"> 779 <object name="unitTradingButton[n]" style="iconButton" type="button" size="0 0 46 46" tooltip_style="sessionToolTipBottom"> 780 <object name="unitTradingIcon[n]" type="image" ghost="true" size="3 3 43 43"/> 781 <object name="unitTradingSelection[n]" hidden="true" type="image" ghost="true" size="3 3 43 43" sprite="stretched:session/icons/corners.png"/> 782 </object> 783 </repeat> 784 </object> 785 </object> 786 787 <object name="unitQueuePanel" 788 size="4 -56 100% 0" 789 type="image" 790 sprite="queuePanelShader" 791 > 792 <object size="-4 -2 52 54" type="image" sprite="stretched:session/icons/production.png" tooltip_style="sessionToolTipBottom" tooltip="Production queue"> 793 <object name="queueProgress" ghost="true" style="iconButtonProgress" type="text"/> 794 </object> 795 796 <object size="48 6 100% 100%"> 797 <repeat count="16"> 798 <object name="unitQueueButton[n]" hidden="true" style="iconButton" type="button" size="0 0 40 40" tooltip_style="sessionToolTipBottom"> 799 <object name="unitQueueIcon[n]" ghost="true" type="image" size="3 3 37 37"/> 800 <object name="unitQueueProgressSlider[n]" type="image" sprite="queueProgressSlider" ghost="true" size="3 3 37 37" z="20"/> 801 <object name="unitQueueCount[n]" ghost="true" style="groupIconsText" type="text" z="20"/> 802 </object> 803 </repeat> 804 </object> 805 </object> 806 807 <object name="unitGatePanel" 808 size="10 12 100% 100%" 809 > 810 <object size="0 0 100% 100%"> 811 <repeat count="8"> 812 <object name="unitGateButton[n]" hidden="true" style="iconButton" type="button" size="0 0 46 46" tooltip_style="sessionToolTipBottom"> 813 <object name="unitGateIcon[n]" type="image" ghost="true" size="3 3 43 43"/> 814 <object name="unitGateSelection[n]" hidden="true" type="image" ghost="true" size="3 3 43 43" sprite="stretched:session/icons/corners.png"/> 815 <object name="unitGateUnaffordable[n]" hidden="true" type="image" ghost="true" size="3 3 43 43" sprite="colour: 255 0 0 127"/> 816 </object> 817 </repeat> 818 </object> 819 </object> 820 821 </object> <!-- END OF UNIT COMMANDS --> 822 823 </object><!-- END OF BOTTOM PANEL --> 824 825 </object> <!-- END OF SN OBJECT --> 826 827 <!-- ================================ ================================ --> 828 <!-- Selection bandbox --> 829 <!-- ================================ ================================ --> 830 <object name="bandbox" type="image" sprite="bandbox" ghost="true" hidden="true" z="200"/> 831 832 <!-- ================================ ================================ --> 833 <!-- Network status --> 834 <!-- ================================ ================================ --> 835 <object name="netStatus" type="text" style="netStatus" z="100" hidden="true"> 836 <object type="button" 837 name="disconnectedExitButton" 838 style="StoneButton" 839 size="50%-84 50%+128 50%+84 50%+160" 840 tooltip_style="sessionToolTip" 841 hidden="true" 842 > 843 <object size="0 0 100% 100%" type="text" style="CenteredButtonText" name="disconnectedExitButtonText" ghost="true">Return to Main Menu</object> 844 <action on="Press">leaveGame()</action> 845 </object> 846 847 </object> 848 849 </objects> -
binaries/data/mods/public/gui/session/selection_details.js
254 254 } 255 255 256 256 // Updates middle entity Selection Details Panel 257 function updateSelectionDetails( )257 function updateSelectionDetails(replay) 258 258 { 259 259 var supplementalDetailsPanel = getGUIObjectByName("supplementalSelectionDetails"); 260 260 var detailsPanel = getGUIObjectByName("selectionDetails"); … … 296 296 commandsPanel.hidden = false; 297 297 298 298 // Fill out commands panel for specific unit selected (or first unit of primary group) 299 updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, selection );299 updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, selection, replay); 300 300 } -
binaries/data/mods/public/gui/session/unit_commands.js
852 852 * @param supplementalDetailsPanel Reference to the "supplementalSelectionDetails" GUI Object 853 853 * @param commandsPanel Reference to the "commandsPanel" GUI Object 854 854 * @param selection Array of currently selected entity IDs. 855 * @param replay True if we're in visual replay mode 855 856 */ 856 function updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, selection )857 function updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, selection, replay) 857 858 { 858 859 // Panels that are active 859 860 var usedPanels = {}; 860 861 861 862 // If the selection is friendly units, add the command panels 862 863 var player = Engine.GetPlayerID(); 863 if ( entState.player == player || g_DevSettings.controlAll)864 if (replay || entState.player == player || g_DevSettings.controlAll) 864 865 { 865 866 if (selection.length > 1) 866 867 setupUnitPanel(SELECTION, usedPanels, entState, g_Selection.groups.getTemplateNames(), 867 868 function (entType) { changePrimarySelectionGroup(entType); } ); 868 869 869 var commands = getEntityCommandsList(entState); 870 if (commands.length) 871 setupUnitPanel(COMMAND, usedPanels, entState, commands, 872 function (item) { performCommand(entState.id, item.name); } ); 870 if (!replay) 871 { 872 var commands = getEntityCommandsList(entState); 873 if (commands.length) 874 setupUnitPanel(COMMAND, usedPanels, entState, commands, 875 function (item) { performCommand(entState.id, item.name); } ); 876 } 873 877 874 878 if (entState.garrisonHolder) 875 879 { … … 885 889 function (item) { unloadTemplate(item); } ); 886 890 } 887 891 888 var formations = Engine.GuiInterfaceCall("GetAvailableFormations"); 889 if (hasClass(entState, "Unit") && !hasClass(entState, "Animal") && !entState.garrisonHolder && formations.length) 892 if (!replay) 890 893 { 891 setupUnitPanel(FORMATION, usedPanels, entState, formations, 892 function (item) { performFormation(entState.id, item); } ); 893 } 894 var formations = Engine.GuiInterfaceCall("GetAvailableFormations"); 895 if (hasClass(entState, "Unit") && !hasClass(entState, "Animal") && !entState.garrisonHolder && formations.length) 896 { 897 setupUnitPanel(FORMATION, usedPanels, entState, formations, 898 function (item) { performFormation(entState.id, item); } ); 899 } 894 900 895 // TODO: probably should load the stance list from a data file,896 // and/or vary depending on what units are selected897 var stances = ["violent", "aggressive", "passive", "defensive", "standground"];898 if (hasClass(entState, "Unit") && !hasClass(entState, "Animal") && stances.length)899 {900 setupUnitPanel(STANCE, usedPanels, entState, stances,901 function (item) { performStance(entState.id, item); } );902 }901 // TODO: probably should load the stance list from a data file, 902 // and/or vary depending on what units are selected 903 var stances = ["violent", "aggressive", "passive", "defensive", "standground"]; 904 if (hasClass(entState, "Unit") && !hasClass(entState, "Animal") && stances.length) 905 { 906 setupUnitPanel(STANCE, usedPanels, entState, stances, 907 function (item) { performStance(entState.id, item); } ); 908 } 903 909 904 getGUIObjectByName("unitBarterPanel").hidden = !entState.barterMarket;905 if (entState.barterMarket)906 {907 usedPanels["Barter"] = 1;908 setupUnitBarterPanel(entState);909 }910 getGUIObjectByName("unitBarterPanel").hidden = !entState.barterMarket; 911 if (entState.barterMarket) 912 { 913 usedPanels["Barter"] = 1; 914 setupUnitBarterPanel(entState); 915 } 910 916 911 var buildableEnts = [];912 var trainableEnts = [];913 var state;914 // Get all buildable and trainable entities915 for (var i in selection)916 {917 if ((state = GetEntityState(selection[i])) && state.buildEntities && state.buildEntities.length)918 buildableEnts = buildableEnts.concat(state.buildEntities);919 if ((state = GetEntityState(selection[i])) && state.production && state.production.entities.length)920 trainableEnts = trainableEnts.concat(state.production.entities);921 }922 923 // Remove duplicates924 removeDupes(buildableEnts);925 removeDupes(trainableEnts);917 var buildableEnts = []; 918 var trainableEnts = []; 919 var state; 920 // Get all buildable and trainable entities 921 for (var i in selection) 922 { 923 if ((state = GetEntityState(selection[i])) && state.buildEntities && state.buildEntities.length) 924 buildableEnts = buildableEnts.concat(state.buildEntities); 925 if ((state = GetEntityState(selection[i])) && state.production && state.production.entities.length) 926 trainableEnts = trainableEnts.concat(state.production.entities); 927 } 928 929 // Remove duplicates 930 removeDupes(buildableEnts); 931 removeDupes(trainableEnts); 926 932 927 // Whether the GUI's right panel has been filled.928 var rightUsed = true;933 // Whether the GUI's right panel has been filled. 934 var rightUsed = true; 929 935 930 // The first selected entity's type has priority. 931 if (entState.buildEntities) 932 setupUnitPanel(CONSTRUCTION, usedPanels, entState, buildableEnts, startBuildingPlacement); 933 else if (entState.production && entState.production.entities) 934 setupUnitPanel(TRAINING, usedPanels, entState, trainableEnts, 935 function (trainEntType) { addTrainingToQueue(selection, trainEntType); } ); 936 else if (entState.trader) 937 setupUnitTradingPanel(usedPanels, entState, selection); 938 else if (!entState.foundation && entState.gate || hasClass(entState, "LongWall")) 939 { 940 // Allow long wall pieces to be converted to gates 941 var longWallTypes = {}; 942 var walls = []; 943 var gates = []; 944 for (var i in selection) 936 // The first selected entity's type has priority. 937 if (entState.buildEntities) 938 setupUnitPanel(CONSTRUCTION, usedPanels, entState, buildableEnts, startBuildingPlacement); 939 else if (entState.production && entState.production.entities) 940 setupUnitPanel(TRAINING, usedPanels, entState, trainableEnts, 941 function (trainEntType) { addTrainingToQueue(selection, trainEntType); } ); 942 else if (entState.trader) 943 setupUnitTradingPanel(usedPanels, entState, selection); 944 else if (!entState.foundation && entState.gate || hasClass(entState, "LongWall")) 945 945 { 946 state = GetEntityState(selection[i]); 947 if (hasClass(state, "LongWall") && !state.gate && !longWallTypes[state.template]) 946 // Allow long wall pieces to be converted to gates 947 var longWallTypes = {}; 948 var walls = []; 949 var gates = []; 950 for (var i in selection) 948 951 { 949 var gateTemplate = getWallGateTemplate(state.id);950 if ( gateTemplate)952 state = GetEntityState(selection[i]); 953 if (hasClass(state, "LongWall") && !state.gate && !longWallTypes[state.template]) 951 954 { 952 var wallName = GetTemplateData(state.template).name.generic; 953 var gateName = GetTemplateData(gateTemplate).name.generic; 955 var gateTemplate = getWallGateTemplate(state.id); 956 if (gateTemplate) 957 { 958 var wallName = GetTemplateData(state.template).name.generic; 959 var gateName = GetTemplateData(gateTemplate).name.generic; 954 960 955 walls.push({ 956 "tooltip": "Convert " + wallName + " to " + gateName, 957 "template": gateTemplate, 958 "callback": function (item) { transformWallToGate(item.template); } 959 }); 961 walls.push({ 962 "tooltip": "Convert " + wallName + " to " + gateName, 963 "template": gateTemplate, 964 "callback": function (item) { transformWallToGate(item.template); } 965 }); 966 } 967 968 // We only need one entity per type. 969 longWallTypes[state.template] = true; 960 970 } 971 else if (state.gate && !gates.length) 972 for (var j = 0; j < GATE_ACTIONS.length; ++j) 973 gates.push({ 974 "gate": state.gate, 975 "tooltip": GATE_ACTIONS[j] + " gate", 976 "locked": j == 0, 977 "callback": function (item) { lockGate(item.locked); } 978 }); 979 // Show both 'locked' and 'unlocked' as active if the selected gates have both lock states. 980 else if (state.gate && state.gate.locked != gates[0].gate.locked) 981 for (var j = 0; j < gates.length; ++j) 982 delete gates[j].gate.locked; 983 } 961 984 962 // We only need one entity per type. 963 longWallTypes[state.template] = true; 964 } 965 else if (state.gate && !gates.length) 966 for (var j = 0; j < GATE_ACTIONS.length; ++j) 967 gates.push({ 968 "gate": state.gate, 969 "tooltip": GATE_ACTIONS[j] + " gate", 970 "locked": j == 0, 971 "callback": function (item) { lockGate(item.locked); } 972 }); 973 // Show both 'locked' and 'unlocked' as active if the selected gates have both lock states. 974 else if (state.gate && state.gate.locked != gates[0].gate.locked) 975 for (var j = 0; j < gates.length; ++j) 976 delete gates[j].gate.locked; 985 // Place wall conversion options after gate lock/unlock icons. 986 var items = gates.concat(walls); 987 if (items.length) 988 setupUnitPanel(GATE, usedPanels, entState, items); 989 else 990 rightUsed = false; 977 991 } 978 979 // Place wall conversion options after gate lock/unlock icons.980 var items = gates.concat(walls);981 if (items.length)982 setupUnitPanel(GATE, usedPanels, entState, items);983 992 else 984 993 rightUsed = false; 985 }986 else987 rightUsed = false;988 994 989 if (!rightUsed)990 {991 // The right pane is empty. Fill the pane with a sane type.992 // Prefer buildables for units and trainables for structures.993 if (buildableEnts.length && (hasClass(entState, "Unit") || !trainableEnts.length))994 setupUnitPanel(CONSTRUCTION, usedPanels, entState, buildableEnts, startBuildingPlacement);995 else if (trainableEnts.length)996 setupUnitPanel(TRAINING, usedPanels, entState, trainableEnts,997 function (trainEntType) { addTrainingToQueue(selection, trainEntType); } );998 }995 if (!rightUsed) 996 { 997 // The right pane is empty. Fill the pane with a sane type. 998 // Prefer buildables for units and trainables for structures. 999 if (buildableEnts.length && (hasClass(entState, "Unit") || !trainableEnts.length)) 1000 setupUnitPanel(CONSTRUCTION, usedPanels, entState, buildableEnts, startBuildingPlacement); 1001 else if (trainableEnts.length) 1002 setupUnitPanel(TRAINING, usedPanels, entState, trainableEnts, 1003 function (trainEntType) { addTrainingToQueue(selection, trainEntType); } ); 1004 } 999 1005 1000 // Show technologies if the active panel has at most one row of icons. 1001 if (entState.production && entState.production.technologies.length) 1002 { 1003 var activepane = usedPanels[CONSTRUCTION] ? buildableEnts.length : trainableEnts.length; 1004 if (selection.length == 1 || activepane <= 8) 1005 setupUnitPanel(RESEARCH, usedPanels, entState, entState.production.technologies, 1006 function (researchType) { addResearchToQueue(entState.id, researchType); } ); 1006 // Show technologies if the active panel has at most one row of icons. 1007 if (entState.production && entState.production.technologies.length) 1008 { 1009 var activepane = usedPanels[CONSTRUCTION] ? buildableEnts.length : trainableEnts.length; 1010 if (selection.length == 1 || activepane <= 8) 1011 setupUnitPanel(RESEARCH, usedPanels, entState, entState.production.technologies, 1012 function (researchType) { addResearchToQueue(entState.id, researchType); } ); 1013 } 1007 1014 } 1008 1015 1009 1016 if (entState.production && entState.production.queue.length) -
binaries/data/mods/public/gui/summary/summary.js
276 276 function onTick() 277 277 { 278 278 // Update music state 279 global.music.updateTimer(); 279 if (global.music) 280 global.music.updateTimer(); 280 281 } -
source/gui/scripting/ScriptFunctions.cpp
167 167 return -1; 168 168 } 169 169 170 void SetPlayerID(void* UNUSED(cbdata), int id) 171 { 172 if (g_Game) 173 g_Game->SetPlayerID(id); 174 } 175 170 176 std::wstring GetDefaultPlayerName(void* UNUSED(cbdata)) 171 177 { 172 178 std::wstring name = g_PlayerName.FromUTF8(); … … 617 623 // Misc functions 618 624 scriptInterface.RegisterFunction<std::wstring, std::wstring, &SetCursor>("SetCursor"); 619 625 scriptInterface.RegisterFunction<int, &GetPlayerID>("GetPlayerID"); 626 scriptInterface.RegisterFunction<void, int, &SetPlayerID>("SetPlayerID"); 620 627 scriptInterface.RegisterFunction<std::wstring, &GetDefaultPlayerName>("GetDefaultPlayerName"); 621 628 scriptInterface.RegisterFunction<void, std::string, &OpenURL>("OpenURL"); 622 629 scriptInterface.RegisterFunction<void, &RestartInAtlas>("RestartInAtlas"); -
source/network/NetTurnManager.cpp
465 465 466 466 467 467 468 CNetReplayTurnManager::CNetReplayTurnManager(CSimulation2& simulation, IReplayLogger& replay) : 469 CNetLocalTurnManager(simulation, replay) 470 { 471 } 472 473 void CNetReplayTurnManager::StoreReplayCommand(u32 turn, int player, const std::string& command) 474 { 475 m_ReplayCommands[turn][player].push_back(command); 476 } 477 478 void CNetReplayTurnManager::NotifyFinishedUpdate(u32 turn) 479 { 480 DoTurn(turn); 481 } 482 483 void CNetReplayTurnManager::DoTurn(u32 turn) 484 { 485 std::map<int, std::vector<std::string> > playerCommands = m_ReplayCommands[turn]; 486 std::map<int, std::vector<std::string> >::iterator it; 487 for (it = playerCommands.begin(); it != playerCommands.end(); ++it) 488 { 489 int player = it->first; 490 for (size_t i = 0; i < it->second.size(); ++i) 491 { 492 CScriptValRooted data = m_Simulation2.GetScriptInterface().ParseJSON(it->second[i]); 493 AddCommand(m_ClientId, player, data, m_CurrentTurn + 1); 494 } 495 } 496 } 497 498 499 500 468 501 CNetServerTurnManager::CNetServerTurnManager(CNetServerWorker& server) : 469 502 m_NetServer(server), m_ReadyTurn(1), m_TurnLength(DEFAULT_TURN_LENGTH_MP) 470 503 { -
source/network/NetTurnManager.h
22 22 23 23 #include <list> 24 24 #include <map> 25 #include <vector> 25 26 26 27 class CNetServerWorker; 27 28 class CNetClient; … … 227 228 virtual void NotifyFinishedUpdate(u32 turn); 228 229 }; 229 230 231 /** 232 * Implementation of CNetTurnManager for replay games. 233 */ 234 class CNetReplayTurnManager : public CNetLocalTurnManager 235 { 236 public: 237 CNetReplayTurnManager(CSimulation2& simulation, IReplayLogger& replay); 230 238 239 void StoreReplayCommand(u32 turn, int player, const std::string& command); 240 241 protected: 242 virtual void NotifyFinishedUpdate(u32 turn); 243 244 void DoTurn(u32 turn); 245 246 std::map<u32, std::map<int, std::vector<std::string> > > m_ReplayCommands; 247 }; 248 249 231 250 /** 232 251 * The server-side counterpart to CNetClientTurnManager. 233 252 * Records the turn state of each client, and sends turn advancement messages -
source/ps/Game.cpp
59 59 * Constructor 60 60 * 61 61 **/ 62 CGame::CGame(bool disableGraphics ):62 CGame::CGame(bool disableGraphics, bool replayLog): 63 63 m_World(new CWorld(this)), 64 64 m_Simulation2(new CSimulation2(&m_World->GetUnitManager(), m_World->GetTerrain())), 65 65 m_GameView(disableGraphics ? NULL : new CGameView(this)), … … 67 67 m_Paused(false), 68 68 m_SimRate(1.0f), 69 69 m_PlayerID(-1), 70 m_IsSavedGame(false) 70 m_IsSavedGame(false), 71 m_IsReplay(false), 72 m_ReplayStream(NULL) 71 73 { 72 m_ReplayLogger = new CReplayLogger(m_Simulation2->GetScriptInterface());73 74 // TODO: should use CDummyReplayLogger unless activated by cmd-line arg, perhaps? 75 if (replayLog) 76 m_ReplayLogger = new CReplayLogger(m_Simulation2->GetScriptInterface()); 77 else 78 m_ReplayLogger = new CDummyReplayLogger(); 74 79 75 80 // Need to set the CObjectManager references after various objects have 76 81 // been initialised, so do it here rather than via the initialisers above. … … 97 102 delete m_Simulation2; 98 103 delete m_World; 99 104 delete m_ReplayLogger; 105 delete m_ReplayStream; 100 106 } 101 107 102 108 void CGame::SetTurnManager(CNetTurnManager* turnManager) … … 161 167 if (m_IsSavedGame) 162 168 RegMemFun(this, &CGame::LoadInitialState, L"Loading game", 1000); 163 169 170 if (m_IsReplay) 171 RegMemFun(this, &CGame::LoadReplayData, L"Loading replay data", 1000); 172 164 173 LDR_EndRegistering(); 165 174 } 166 175 … … 184 193 return 0; 185 194 } 186 195 196 int CGame::LoadReplayData() 197 { 198 ENSURE(m_IsReplay); 199 ENSURE(!m_ReplayPath.empty()); 200 201 CNetReplayTurnManager* replayTurnMgr = static_cast<CNetReplayTurnManager*>(GetTurnManager()); 202 203 u32 currentTurn = 0; 204 std::string type; 205 while ((*m_ReplayStream >> type).good()) 206 { 207 if (type == "turn") 208 { 209 u32 turn = 0; 210 u32 turnLength = 0; 211 *m_ReplayStream >> turn >> turnLength; 212 ENSURE(turn == currentTurn); 213 } 214 else if (type == "cmd") 215 { 216 int player; 217 *m_ReplayStream >> player; 218 219 std::string line; 220 std::getline(*m_ReplayStream, line); 221 replayTurnMgr->StoreReplayCommand(currentTurn, player, line); 222 } 223 else if (type == "hash" || type == "hash-quick") 224 { 225 // Ignored for now 226 std::string replayHash; 227 *m_ReplayStream >> replayHash; 228 } 229 else if (type == "end") 230 { 231 currentTurn++; 232 } 233 else 234 { 235 CancelLoad(L"Failed to load replay data (unrecognized content)"); 236 } 237 } 238 m_FinalReplayTurn = currentTurn + 1; 239 240 return 0; 241 } 242 243 void CGame::StartReplay(const std::string& replayPath) 244 { 245 m_IsReplay = true; 246 247 SetTurnManager(new CNetReplayTurnManager(*m_Simulation2, GetReplayLogger())); 248 249 m_ReplayPath = replayPath; 250 m_ReplayStream = new std::ifstream(m_ReplayPath.c_str()); 251 ENSURE(m_ReplayStream->good()); 252 253 std::string type; 254 ENSURE((*m_ReplayStream >> type).good() && type == "start"); 255 256 std::string line; 257 std::getline(*m_ReplayStream, line); 258 CScriptValRooted attribs = m_Simulation2->GetScriptInterface().ParseJSON(line); 259 StartGame(attribs, ""); 260 } 261 187 262 /** 188 263 * Game initialization has been completed. Set game started flag and start the session. 189 264 * … … 285 360 g_GUI->SendEventToAll("SimulationUpdate"); 286 361 } 287 362 363 if (m_IsReplay && m_TurnManager->GetCurrentTurn() == m_FinalReplayTurn) 364 g_GUI->SendEventToAll("ReplayFinished"); 365 288 366 GetView()->GetLOSTexture().MakeDirty(); 289 367 } 290 368 -
source/ps/Game.h
19 19 #define INCLUDED_GAME 20 20 21 21 #include "ps/Errors.h" 22 #include <map> 22 23 #include <vector> 23 24 24 25 #include "scriptinterface/ScriptVal.h" … … 65 66 CNetTurnManager* m_TurnManager; 66 67 67 68 public: 68 CGame(bool disableGraphics = false );69 CGame(bool disableGraphics = false, bool replayLog = true); 69 70 ~CGame(); 70 71 71 72 /** … … 76 77 void StartGame(const CScriptValRooted& attribs, const std::string& savedState); 77 78 PSRETURN ReallyStartGame(); 78 79 80 void StartReplay(const std::string& replayPath); 81 79 82 /** 80 83 * Periodic heartbeat that controls the process. performs all per-frame updates. 81 84 * Simulation update is called and game status update is called. … … 168 171 int LoadInitialState(); 169 172 std::string m_InitialSavedState; // valid between RegisterInit and LoadInitialState 170 173 bool m_IsSavedGame; // true if loading a saved game; false for a new game 174 175 int LoadReplayData(); 176 std::string m_ReplayPath; 177 bool m_IsReplay; 178 std::istream* m_ReplayStream; 179 u32 m_FinalReplayTurn; 171 180 }; 172 181 173 182 extern CGame *g_Game; -
source/ps/GameSetup/GameSetup.cpp
825 825 } 826 826 827 827 bool Autostart(const CmdLineArgs& args); 828 bool VisualReplay(const CmdLineArgs& args); 828 829 829 830 void Init(const CmdLineArgs& args, int UNUSED(flags)) 830 831 { … … 983 984 984 985 try 985 986 { 986 if (! Autostart(args))987 if (!VisualReplay(args) && !Autostart(args)) 987 988 { 988 989 const bool setup_gui = ((flags & INIT_NO_GUI) == 0); 989 990 InitPs(setup_gui, L"page_pregame.xml", JSVAL_VOID); … … 1017 1018 g_DoRenderCursor = RenderingState; 1018 1019 } 1019 1020 1021 bool VisualReplay(const CmdLineArgs& args) 1022 { 1023 CStr replayPath = args.Get("replay-visual"); 1024 if (!replayPath.empty()) 1025 { 1026 g_Game = new CGame(false, false); 1027 1028 g_Game->SetPlayerID(1); 1029 g_Game->StartReplay(replayPath); 1030 1031 // TODO: Non progressive load can fail - need a decent way to handle this 1032 LDR_NonprogressiveLoad(); 1033 1034 PSRETURN ret = g_Game->ReallyStartGame(); 1035 ENSURE(ret == PSRETURN_OK); 1036 1037 InitPs(true, L"page_replay.xml", JSVAL_VOID); 1038 return true; 1039 } 1040 1041 return false; 1042 } 1043 1020 1044 bool Autostart(const CmdLineArgs& args) 1021 1045 { 1022 1046 /* -
source/ps/Replay.cpp
128 128 g_ScriptStatsTable = new CScriptStatsTable; 129 129 g_ProfileViewer.AddRootTable(g_ScriptStatsTable); 130 130 131 CGame game(true );131 CGame game(true, false); 132 132 g_Game = &game; 133 133 134 134 // Need some stuff for terrain movement costs: