Ticket #3168: t3168_let_observer_change_perspective_v1.patch
File t3168_let_observer_change_perspective_v1.patch, 28.0 KB (added by , 8 years ago) |
---|
-
binaries/data/mods/public/gui/session/menu.js
function exitMenuButton() 140 140 "buttons": [resumeGame, leaveGame] 141 141 } 142 142 }; 143 143 144 144 let messageType = g_IsNetworked && g_IsController ? "host" : 145 (g_IsNetworked && !g_GameEnded && !g_IsObserver? "client" : "singleplayer");145 (g_IsNetworked && !g_GameEnded && Engine.GetPlayerID() != -1 ? "client" : "singleplayer"); 146 146 147 147 messageBox( 148 148 400, 200, 149 149 messageTypes[messageType].caption, 150 150 translate("Confirmation"), … … function closeChat() 218 218 Engine.GetGUIObjectByName("chatInput").caption = ""; // Clear chat input 219 219 Engine.GetGUIObjectByName("chatInput").blur(); // Remove focus 220 220 Engine.GetGUIObjectByName("chatDialogPanel").hidden = true; 221 221 } 222 222 223 /** 224 * Chat is sent via GUID, not playerID. 225 */ 223 226 function updateTeamCheckbox(check) 224 227 { 225 228 Engine.GetGUIObjectByName("toggleTeamChatLabel").hidden = g_IsObserver; 226 229 let toggleTeamChat = Engine.GetGUIObjectByName("toggleTeamChat"); 227 230 toggleTeamChat.hidden = g_IsObserver; … … function tributeResource(data) 264 267 265 268 function openDiplomacy() 266 269 { 267 270 if (g_IsTradeOpen) 268 271 closeTrade(); 269 g_IsDiplomacyOpen = true;270 272 271 let we = Engine.GetPlayerID(); 273 if (g_ViewedPlayer < 1) 274 { 275 closeDiplomacy(); 276 return; 277 } 278 279 g_IsDiplomacyOpen = true; 272 280 273 281 // Get offset for one line 274 282 let onesize = Engine.GetGUIObjectByName("diplomacyPlayer[0]").size; 275 283 let rowsize = onesize.bottom - onesize.top; 276 284 … … function openDiplomacy() 290 298 291 299 Engine.GetGUIObjectByName("diplomacyPlayerName["+(i-1)+"]").caption = "[color=\"" + playerColor + "\"]" + g_Players[i].name + "[/color]"; 292 300 Engine.GetGUIObjectByName("diplomacyPlayerCiv["+(i-1)+"]").caption = g_CivData[g_Players[i].civ].Name; 293 301 294 302 Engine.GetGUIObjectByName("diplomacyPlayerTeam["+(i-1)+"]").caption = (g_Players[i].team < 0) ? translateWithContext("team", "None") : g_Players[i].team+1; 295 296 if (i != we) 297 Engine.GetGUIObjectByName("diplomacyPlayerTheirs["+(i-1)+"]").caption = (g_Players[i].isAlly[we] ? translate("Ally") : (g_Players[i].isNeutral[we] ? translate("Neutral") : translate("Enemy"))); 303 Engine.GetGUIObjectByName("diplomacyPlayerTheirs["+(i-1)+"]").caption = g_Players[i].isAlly[g_ViewedPlayer] ? translate("Ally") : (g_Players[i].isNeutral[g_ViewedPlayer] ? translate("Neutral") : translate("Enemy")); 298 304 299 305 // Don't display the options for ourself, or if we or the other player aren't active anymore 300 if (i == we || g_Players[we].state != "active" || g_Players[i].state != "active")306 if (i == g_ViewedPlayer || g_Players[g_ViewedPlayer].state != "active" || g_Players[i].state != "active") 301 307 { 302 308 // Hide the unused/unselectable options 303 309 for (let a of ["TributeFood", "TributeWood", "TributeStone", "TributeMetal", "Ally", "Neutral", "Enemy"]) 304 310 Engine.GetGUIObjectByName("diplomacyPlayer"+a+"["+(i-1)+"]").hidden = true; 305 311 Engine.GetGUIObjectByName("diplomacyAttackRequest["+(i-1)+"]").hidden = true; … … function openDiplomacy() 337 343 }; 338 344 if (!isBatchTrainPressed) 339 345 g_FlushTributing(); 340 346 }; 341 347 })(i, resource, button); 348 button.enabled = controlsPlayer(g_ViewedPlayer); 342 349 button.hidden = false; 343 350 button.tooltip = formatTributeTooltip(g_Players[i], resource, 100); 344 351 } 345 352 346 353 // Attack Request 347 354 let simState = GetSimState(); 348 355 let button = Engine.GetGUIObjectByName("diplomacyAttackRequest["+(i-1)+"]"); 349 button.hidden = simState.ceasefireActive || !(g_Players[i].isEnemy[we]); 356 button.hidden = simState.ceasefireActive || !(g_Players[i].isEnemy[g_ViewedPlayer]); 357 button.enabled = controlsPlayer(g_ViewedPlayer); 350 358 button.tooltip = translate("Request your allies to attack this enemy"); 351 button.onpress = (function(i , we){ return function() {352 Engine.PostNetworkCommand({ "type": "attack-request", "source": we, "target": i });353 }; })(i , we);359 button.onpress = (function(i) { return function() { 360 Engine.PostNetworkCommand({ "type": "attack-request", "source": g_ViewedPlayer, "target": i }); 361 }; })(i); 354 362 355 363 // Skip our own teams on teams locked 356 if (g_Players[ we].teamsLocked && g_Players[we].team != -1 && g_Players[we].team == g_Players[i].team)364 if (g_Players[g_ViewedPlayer].teamsLocked && g_Players[g_ViewedPlayer].team != -1 && g_Players[g_ViewedPlayer].team == g_Players[i].team) 357 365 continue; 358 366 359 367 // Diplomacy settings 360 368 // Set up the buttons 361 369 for (let setting of ["Ally", "Neutral", "Enemy"]) 362 370 { 363 371 let button = Engine.GetGUIObjectByName("diplomacyPlayer"+setting+"["+(i-1)+"]"); 364 372 365 button.caption = g_Players[ we]["is"+setting][i] ? translate("x") : "";373 button.caption = g_Players[g_ViewedPlayer]["is" + setting][i] ? translate("x") : ""; 366 374 button.onpress = (function(e){ return function() { setDiplomacy(e); }; })({ "player": i, "to": setting.toLowerCase() }); 375 button.enabled = controlsPlayer(g_ViewedPlayer); 367 376 button.hidden = simState.ceasefireActive; 368 377 } 369 378 } 370 379 371 380 Engine.GetGUIObjectByName("diplomacyDialogPanel").hidden = false; … … function toggleDiplomacy() 387 396 388 397 function openTrade() 389 398 { 390 399 if (g_IsDiplomacyOpen) 391 400 closeDiplomacy(); 401 402 if (g_ViewedPlayer < 1) 403 { 404 closeTrade(); 405 return; 406 } 407 392 408 g_IsTradeOpen = true; 393 409 394 410 var updateButtons = function() 395 411 { 396 412 for (var res in button) 397 413 { 398 414 button[res].label.caption = proba[res] + "%"; 399 if (res == selec) 400 { 401 button[res].sel.hidden = false; 402 button[res].up.hidden = true; 403 button[res].dn.hidden = true; 404 } 405 else 406 { 407 button[res].sel.hidden = true; 408 button[res].up.hidden = (proba[res] == 100 || proba[selec] == 0); 409 button[res].dn.hidden = (proba[res] == 0 || proba[selec] == 100); 410 } 415 416 button[res].sel.hidden = !controlsPlayer(g_ViewedPlayer) || res != selec; 417 button[res].up.hidden = !controlsPlayer(g_ViewedPlayer) || res == selec || proba[res] == 100 || proba[selec] == 0; 418 button[res].dn.hidden = !controlsPlayer(g_ViewedPlayer) || res == selec || proba[res] == 0 || proba[selec] == 100; 411 419 } 412 420 }; 413 421 414 var proba = Engine.GuiInterfaceCall("GetTradingGoods" );422 var proba = Engine.GuiInterfaceCall("GetTradingGoods", g_ViewedPlayer); 415 423 var button = {}; 416 424 var selec = RESOURCES[0]; 417 425 for (var i = 0; i < RESOURCES.length; ++i) 418 426 { 419 427 var buttonResource = Engine.GetGUIObjectByName("tradeResource["+i+"]"); … … function openTrade() 434 442 var buttonUp = Engine.GetGUIObjectByName("tradeArrowUp["+i+"]"); 435 443 var buttonDn = Engine.GetGUIObjectByName("tradeArrowDn["+i+"]"); 436 444 var iconSel = Engine.GetGUIObjectByName("tradeResourceSelection["+i+"]"); 437 445 button[resource] = { "up": buttonUp, "dn": buttonDn, "label": label, "sel": iconSel }; 438 446 447 buttonResource.enabled = controlsPlayer(g_ViewedPlayer); 439 448 buttonResource.onpress = (function(resource){ 440 449 return function() { 441 450 if (Engine.HotkeyIsPressed("session.fulltradeswap")) 442 451 { 443 452 for (var ress of RESOURCES) … … function openTrade() 448 457 selec = resource; 449 458 updateButtons(); 450 459 }; 451 460 })(resource); 452 461 462 buttonUp.enabled = controlsPlayer(g_ViewedPlayer); 453 463 buttonUp.onpress = (function(resource){ 454 464 return function() { 455 465 proba[resource] += Math.min(STEP, proba[selec]); 456 466 proba[selec] -= Math.min(STEP, proba[selec]); 457 467 Engine.PostNetworkCommand({"type": "set-trading-goods", "tradingGoods": proba}); 458 468 updateButtons(); 459 469 }; 460 470 })(resource); 461 471 472 buttonDn.enabled = controlsPlayer(g_ViewedPlayer); 462 473 buttonDn.onpress = (function(resource){ 463 474 return function() { 464 475 proba[selec] += Math.min(STEP, proba[resource]); 465 476 proba[resource] -= Math.min(STEP, proba[resource]); 466 477 Engine.PostNetworkCommand({"type": "set-trading-goods", "tradingGoods": proba}); … … function openTrade() 468 479 }; 469 480 })(resource); 470 481 } 471 482 updateButtons(); 472 483 473 let traderNumber = Engine.GuiInterfaceCall("GetTraderNumber" );484 let traderNumber = Engine.GuiInterfaceCall("GetTraderNumber", g_ViewedPlayer); 474 485 Engine.GetGUIObjectByName("landTraders").caption = getIdleLandTradersText(traderNumber); 475 486 Engine.GetGUIObjectByName("shipTraders").caption = getIdleShipTradersText(traderNumber); 476 487 477 488 Engine.GetGUIObjectByName("tradeDialogPanel").hidden = false; 478 489 } … … function openStrucTree() 645 656 closeOpenDialogs(); 646 657 pauseGame(); 647 658 648 659 // TODO add info about researched techs and unlocked entities 649 660 Engine.PushGuiPage("page_structree.xml", { 650 "civ" : g_Players[ Engine.GetPlayerID()].civ,661 "civ" : g_Players[g_ViewedPlayer].civ, 651 662 "callback": "resumeGame", 652 663 }); 653 664 } 654 665 655 666 /** -
binaries/data/mods/public/gui/session/messages.js
function getCheatsData() 267 267 * @param {string} text 268 268 * @returns {boolean} - True if a cheat was executed. 269 269 */ 270 270 function executeCheat(text) 271 271 { 272 if ( g_IsObserver|| !g_Players[Engine.GetPlayerID()].cheatsEnabled)272 if (Engine.GetPlayerID() == -1 || !g_Players[Engine.GetPlayerID()].cheatsEnabled) 273 273 return false; 274 274 275 275 // Find the cheat code that is a prefix of the user input 276 276 let cheatCode = Object.keys(g_Cheats).find(cheatCode => text.indexOf(cheatCode) == 0); 277 277 if (!cheatCode) … … function formatDefeatMessage(msg) 566 566 }); 567 567 } 568 568 569 569 function formatDiplomacyMessage(msg) 570 570 { 571 // Check observer first 572 let use = { 573 "observer": g_IsObserver, 574 "active": Engine.GetPlayerID() == msg.sourcePlayer, 575 "passive": Engine.GetPlayerID() == msg.targetPlayer 576 }; 577 578 let messageType = Object.keys(use).find(v => use[v]); 579 if (!messageType) 571 let messageType; 572 switch (Engine.GetPlayerID()) 573 { 574 // Check observer first, since we also want to see if the selected player in the developer-overlay has changed the diplomacy 575 case -1: 576 messageType = "observer"; 577 break; 578 case msg.sourcePlayer: 579 messageType = "active"; 580 break; 581 case msg.targetPlayer: 582 messageType = "passive"; 583 break; 584 default: 580 585 return ""; 586 } 581 587 582 588 return sprintf(g_DiplomacyMessages[messageType][msg.status], { 583 589 "player": colorizePlayernameByID(messageType == "active" ? msg.targetPlayer : msg.sourcePlayer), 584 590 "player2": colorizePlayernameByID(messageType == "active" ? msg.sourcePlayer : msg.targetPlayer) 585 591 }); … … function formatDiplomacyMessage(msg) 587 593 588 594 function formatTributeMessage(msg) 589 595 { 590 596 // Check observer first, since we also want to see if the selected player in the developer-overlay has sent tributes 591 597 let message = ""; 592 if ( g_IsObserver)598 if (Engine.GetPlayerID() == -1) 593 599 message = translate("%(player)s has sent %(player2)s %(amounts)s."); 594 600 else if (msg.targetPlayer == Engine.GetPlayerID()) 595 601 message = translate("%(player)s has sent you %(amounts)s."); 596 602 597 603 return sprintf(message, { … … function formatChatCommand(msg) 664 670 function checkChatAddressee(msg) 665 671 { 666 672 if (msg.text[0] != '/') 667 673 return true; 668 674 669 if ( g_IsObserver)675 if (Engine.GetPlayerID() == -1) 670 676 return false; 671 677 672 678 let cmd = msg.text.split(/\s/)[0]; 673 679 msg.text = msg.text.substr(cmd.length + 1); 674 680 -
binaries/data/mods/public/gui/session/session.js
var g_IsController; 20 20 /** 21 21 * Unique ID for lobby reports 22 22 */ 23 23 var g_MatchID; 24 24 25 /** 26 * True if the current user has observer capabilities. 27 */ 25 28 var g_IsObserver = false; 26 29 30 /** 31 * The playerID selected in the change perspective tool. 32 */ 33 var g_ViewedPlayer = Engine.GetPlayerID(); 34 27 35 // Cache the basic player data (name, civ, color) 28 36 var g_Players = []; 29 37 30 38 var lastTickTime = new Date(); 31 39 … … var g_CivData = {}; 36 44 37 45 var g_PlayerAssignments = { "local": { "name": translate("You"), "player": 1 } }; 38 46 39 47 // Cache dev-mode settings that are frequently or widely used 40 48 var g_DevSettings = { 49 "changePerspective": false, 41 50 "controlAll": false 42 51 }; 43 52 44 53 // Whether status bars should be shown for all of the player's units. 45 54 var g_ShowAllStatusBars = false; … … function init(initData, hotloadData) 180 189 } 181 190 182 191 g_CivData = loadCivData(); 183 192 g_CivData.gaia = { "Code": "gaia", "Name": translate("Gaia") }; 184 193 185 if (Engine.GetPlayerID() <= 0) 186 g_IsObserver = true; 194 setObserverMode(Engine.GetPlayerID() == -1); 187 195 188 196 updateTopPanel(); 189 197 190 198 let gameSpeed = Engine.GetGUIObjectByName("gameSpeed"); 191 199 gameSpeed.list = g_GameSpeeds.Title; … … function init(initData, hotloadData) 194 202 gameSpeed.selected = gameSpeedIdx != -1 ? gameSpeedIdx : g_GameSpeeds.Default; 195 203 gameSpeed.onSelectionChange = function() { changeGameSpeed(+this.list_data[this.selected]); }; 196 204 initMenuPosition(); 197 205 198 206 // Populate player selection dropdown 199 let playerNames = [ ];200 let playerIDs = [ ];207 let playerNames = ["Observer"]; 208 let playerIDs = [-1]; 201 209 for (let player in g_Players) 202 210 { 203 211 playerNames.push(g_Players[player].name); 204 212 playerIDs.push(player); 205 213 } 206 214 207 215 let viewPlayerDropdown = Engine.GetGUIObjectByName("viewPlayer"); 208 216 viewPlayerDropdown.list = playerNames; 209 217 viewPlayerDropdown.list_data = playerIDs; 210 viewPlayerDropdown.selected = Engine.GetPlayerID() ;218 viewPlayerDropdown.selected = Engine.GetPlayerID() + 1; 211 219 212 220 // If in Atlas editor, disable the exit button 213 221 if (Engine.IsAtlasRunning()) 214 222 Engine.GetGUIObjectByName("menuExitButton").enabled = false; 215 223 216 224 if (hotloadData) 217 225 g_Selection.selected = hotloadData.selection; 218 226 219 227 // Starting for the first time: 220 228 initMusic(); 221 if ( !g_IsObserver)229 if (Engine.GetPlayerID() != -1) 222 230 global.music.storeTracks(g_CivData[g_Players[Engine.GetPlayerID()].civ].Music); 223 231 global.music.setState(global.music.states.PEACE); 224 232 playAmbient(); 225 233 226 234 onSimulationUpdate(); … … function init(initData, hotloadData) 234 242 // and it generates a massive amount of data to transmit and store 235 243 //setTimeout(function() { reportPerformance(5); }, 5000); 236 244 //setTimeout(function() { reportPerformance(60); }, 60000); 237 245 } 238 246 247 function toggleChangePerspective(enabled) 248 { 249 g_DevSettings.changePerspective = enabled; 250 Engine.GetGUIObjectByName("viewPlayer").hidden = !enabled && !g_IsObserver; 251 selectViewPlayer(g_ViewedPlayer); 252 } 253 254 /** 255 * Change perspective tool. 256 * Shown to observers or when enabling the developers option. 257 */ 239 258 function selectViewPlayer(playerID) 240 259 { 241 Engine.SetPlayerID(playerID); 260 if (playerID < -1 || playerID > g_Players.length - 1 || 261 !g_DevSettings.changePerspective && !g_IsObserver) 262 return; 263 264 g_ViewedPlayer = playerID; 265 Engine.SetPlayerID(g_DevSettings.changePerspective ? playerID : -1); 266 242 267 updateTopPanel(); 268 onSimulationUpdate(); 269 270 let viewPlayer = Engine.GetGUIObjectByName("viewPlayer"); 271 let alphaLabel = Engine.GetGUIObjectByName("alphaLabel"); 272 alphaLabel.hidden = g_ViewedPlayer > 0 && !viewPlayer.hidden; 273 if (g_ViewedPlayer < 1) 274 alphaLabel.size = "200 0 100%-475 100%"; 275 else 276 alphaLabel.size = "50%+20 0 100%-226 100%"; 243 277 244 278 if (g_IsDiplomacyOpen) 245 279 openDiplomacy(); 246 280 247 281 if (g_IsTradeOpen) 248 282 openTrade(); 283 } 284 285 function setObserverMode(enabled) 286 { 287 g_IsObserver = enabled; 249 288 250 let playerState = GetSimState().players[playerID]; 251 g_DevSettings.controlAll = playerState && playerState.controlsAll; 289 let viewPlayerDropdown = Engine.GetGUIObjectByName("viewPlayer"); 290 291 viewPlayerDropdown.hidden = !enabled; 292 if (enabled) 293 viewPlayerDropdown.selected = 0; 252 294 253 let control = Engine.GetGUIObjectByName("devControlAll"); 254 control.checked = g_DevSettings.controlAll; 255 control.enabled = playerID > 0; 295 Engine.GetGUIObjectByName("alphaLabel").hidden = enabled; 256 296 } 257 297 258 298 /** 259 299 * Returns true if the current user can issue commands for that player. 260 300 */ … … function controlsPlayer(playerID) 263 303 return Engine.GetPlayerID() == playerID || g_DevSettings.controlAll; 264 304 } 265 305 266 306 function updateTopPanel() 267 307 { 268 let playerID = Engine.GetPlayerID(); 269 let isPlayer = playerID > 0; 308 let isPlayer = g_ViewedPlayer > 0; 270 309 if (isPlayer) 271 310 { 272 let civName = g_CivData[g_Players[ playerID].civ].Name;273 Engine.GetGUIObjectByName("civIcon").sprite = "stretched:" + g_CivData[g_Players[ playerID].civ].Emblem;311 let civName = g_CivData[g_Players[g_ViewedPlayer].civ].Name; 312 Engine.GetGUIObjectByName("civIcon").sprite = "stretched:" + g_CivData[g_Players[g_ViewedPlayer].civ].Emblem; 274 313 Engine.GetGUIObjectByName("civIconOverlay").tooltip = sprintf(translate("%(civ)s - Structure Tree"), { "civ": civName }); 275 314 } 276 315 277 316 // Hide stuff gaia/observers don't use. 278 317 Engine.GetGUIObjectByName("food").hidden = !isPlayer; 279 318 Engine.GetGUIObjectByName("wood").hidden = !isPlayer; 280 319 Engine.GetGUIObjectByName("stone").hidden = !isPlayer; 281 320 Engine.GetGUIObjectByName("metal").hidden = !isPlayer; 282 321 Engine.GetGUIObjectByName("population").hidden = !isPlayer; 283 322 Engine.GetGUIObjectByName("civIcon").hidden = !isPlayer; 284 323 Engine.GetGUIObjectByName("diplomacyButton1").hidden = !isPlayer; 285 324 Engine.GetGUIObjectByName("tradeButton1").hidden = !isPlayer; 286 Engine.GetGUIObjectByName("observerText").hidden = playerID >= 0;325 Engine.GetGUIObjectByName("observerText").hidden = isPlayer; 287 326 288 327 // Disable stuff observers shouldn't use 289 let isActive = isPlayer && GetSimState().players[ playerID].state == "active";328 let isActive = isPlayer && GetSimState().players[g_ViewedPlayer].state == "active" && controlsPlayer(g_ViewedPlayer); 290 329 Engine.GetGUIObjectByName("pauseButton").enabled = isActive || !g_IsNetworked; 291 330 Engine.GetGUIObjectByName("menuResignButton").enabled = isActive; 292 331 293 332 // Enable observer-only "summary" button. 294 Engine.GetGUIObjectByName("summaryButton").enabled = !isActive;333 Engine.GetGUIObjectByName("summaryButton").enabled = Engine.GetPlayerID() == -1; 295 334 } 296 335 297 336 function reportPerformance(time) 298 337 { 299 338 let settings = Engine.GetMapSettings(); … … function leaveGame(willRejoin) 341 380 { 342 381 let extendedSimState = Engine.GuiInterfaceCall("GetExtendedSimulationState"); 343 382 let mapSettings = Engine.GetMapSettings(); 344 383 let gameResult; 345 384 346 if ( g_IsObserver)385 if (Engine.GetPlayerID() == -1) 347 386 { 348 387 // Observers don't win/lose. 349 388 gameResult = translate("You have left the game."); 350 389 global.music.setState(global.music.states.VICTORY); 351 390 } … … function onTick() 456 495 g_Selection.dirty = false; 457 496 458 497 onSimulationUpdate(); 459 498 460 499 // Display rally points for selected buildings 461 if ( !g_IsObserver)500 if (Engine.GetPlayerID() != -1) 462 501 Engine.GuiInterfaceCall("DisplayRallyPoint", { "entities": g_Selection.toList() }); 463 502 } 464 503 465 504 updateTimers(); 466 505 … … function onTick() 472 511 Engine.GuiInterfaceCall("ClearRenamedEntities"); 473 512 } 474 513 475 514 function checkPlayerState() 476 515 { 477 if (g_GameEnded || g_IsObserver)516 if (g_GameEnded || Engine.GetPlayerID() < 1) 478 517 return; 479 518 480 519 // Send a game report for each player in this game. 481 520 let m_simState = GetSimState(); 482 521 let playerState = m_simState.players[Engine.GetPlayerID()]; … … function checkPlayerState() 523 562 524 563 if (playerState.state == "defeated") 525 564 { 526 565 title = translate("DEFEATED!"); 527 566 global.music.setState(global.music.states.DEFEAT); 567 setObserverMode(true); 528 568 } 529 569 else if (playerState.state == "won") 530 570 { 531 571 title = translate("VICTORIOUS!"); 532 572 global.music.setState(global.music.states.VICTORY); … … function onSimulationUpdate() 572 612 573 613 updateHero(); 574 614 updateGroups(); 575 615 updateDebug(); 576 616 updatePlayerDisplay(); 617 updateResearchDisplay(); 577 618 updateSelectionDetails(); 578 619 updateBuildingPlacementPreview(); 579 620 updateTimeNotifications(); 580 621 581 if ( Engine.GetPlayerID()> 0)622 if (g_ViewedPlayer > 0) 582 623 { 583 let playerState = GetSimState().players[ Engine.GetPlayerID()];624 let playerState = GetSimState().players[g_ViewedPlayer]; 584 625 g_DevSettings.controlAll = playerState && playerState.controlsAll; 585 626 Engine.GetGUIObjectByName("devControlAll").checked = g_DevSettings.controlAll; 586 627 } 587 628 588 if (!g_IsObserver) 589 updateResearchDisplay(); 590 591 if (!g_IsObserver && !g_GameEnded) 629 if (g_ViewedPlayer != -1 && !g_GameEnded) 592 630 { 593 631 // Update music state on basis of battle state. 594 let battleState = Engine.GuiInterfaceCall("GetBattleState", Engine.GetPlayerID());595 if (battleState )632 let battleState = Engine.GuiInterfaceCall("GetBattleState", g_ViewedPlayer); 633 if (battleState && global.music) 596 634 global.music.setState(global.music.states[battleState]); 597 635 } 598 636 } 599 637 600 638 function onReplayFinished() … … function updateGUIStatusBar(nameOfBar, p 649 687 } 650 688 651 689 652 690 function updateHero() 653 691 { 654 let playerState = GetSimState().players[Engine.GetPlayerID()];655 692 let unitHeroPanel = Engine.GetGUIObjectByName("unitHeroPanel"); 656 693 let heroButton = Engine.GetGUIObjectByName("unitHeroButton"); 657 694 695 let playerState = GetSimState().players[g_ViewedPlayer]; 658 696 if (!playerState || playerState.heroes.length <= 0) 659 697 { 660 698 g_PreviousHeroHitPoints = undefined; 661 699 unitHeroPanel.hidden = true; 662 700 return; … … function updateHero() 691 729 heroButton.tooltip = tooltip; 692 730 693 731 // update heros health bar 694 732 updateGUIStatusBar("heroHealthBar", heroState.hitpoints, heroState.maxHitpoints); 695 733 696 // define the hit points if not defined 734 let heroHP = { 735 "hitpoints": heroState.hitpoints, 736 "player": g_ViewedPlayer 737 }; 738 697 739 if (!g_PreviousHeroHitPoints) 698 g_PreviousHeroHitPoints = hero State.hitpoints;699 740 g_PreviousHeroHitPoints = heroHP; 741 700 742 // if the health of the hero changed since the last update, trigger the animation 701 if ( heroState.hitpoints < g_PreviousHeroHitPoints)743 if (g_PreviousHeroHitPoints.player == heroHP.player && g_PreviousHeroHitPoints.hitpoints > heroHP.hitpoints) 702 744 startColorFade("heroHitOverlay", 100, 0, colorFade_attackUnit, true, smoothColorFadeRestart_attackUnit); 703 745 704 g_PreviousHeroHitPoints = hero State.hitpoints;746 g_PreviousHeroHitPoints = heroHP; 705 747 } 706 748 707 708 749 function updateGroups() 709 750 { 710 751 let guiName = "Group"; 711 752 g_Groups.update(); 712 753 for (let i = 0; i < 10; ++i) … … function updateDebug() 754 795 debug.caption = text.replace(/\[/g, "\\["); 755 796 } 756 797 757 798 function updatePlayerDisplay() 758 799 { 759 let playerState = GetSimState().players[ Engine.GetPlayerID()];800 let playerState = GetSimState().players[g_ViewedPlayer]; 760 801 if (!playerState) 761 802 return; 762 803 763 804 Engine.GetGUIObjectByName("resourceFood").caption = Math.floor(playerState.resourceCounts.food); 764 805 Engine.GetGUIObjectByName("resourceWood").caption = Math.floor(playerState.resourceCounts.wood); … … function selectAndMoveTo(ent) 784 825 Engine.CameraMoveTo(position.x, position.z); 785 826 } 786 827 787 828 function updateResearchDisplay() 788 829 { 789 let researchStarted = Engine.GuiInterfaceCall("GetStartedResearch", Engine.GetPlayerID()); 790 if (!researchStarted) 791 return; 830 let researchStarted = Engine.GuiInterfaceCall("GetStartedResearch", g_ViewedPlayer); 792 831 793 832 // Set up initial positioning. 794 833 let buttonSideLength = Engine.GetGUIObjectByName("researchStartedButton[0]").size.right; 795 834 for (let i = 0; i < 10; ++i) 796 835 { -
binaries/data/mods/public/gui/session/session.xml
69 69 70 70 <object size="0 16 100%-18 32" type="text" style="devCommandsText"> 71 71 <translatableAttribute id="caption">Change perspective</translatableAttribute> 72 72 </object> 73 73 <object size="100%-16 16 100% 32" type="checkbox" style="ModernTickBox"> 74 <action on="Press"> Engine.GetGUIObjectByName("viewPlayer").hidden = !this.checked;</action>74 <action on="Press">toggleChangePerspective(this.checked);</action> 75 75 </object> 76 76 77 77 <object size="0 32 100%-18 48" type="text" style="devCommandsText"> 78 78 <translatableAttribute id="caption">Display selection state</translatableAttribute> 79 79 </object> -
binaries/data/mods/public/gui/session/top_panel.xml
12 12 <!-- ================================ ================================ --> 13 13 14 14 <!-- ================================ ================================ --> 15 15 <!-- Switch the view perspective to another player's (largely for AI development) --> 16 16 <!-- ================================ ================================ --> 17 <object size=" 50%+50 5 50%+150100%-5" name="viewPlayer" type="dropdown" hidden="true" style="ModernDropDown" tooltip_style="sessionToolTipBold">17 <object size="100%-465 5 100%-265 100%-5" name="viewPlayer" type="dropdown" hidden="true" style="ModernDropDown" tooltip_style="sessionToolTipBold"> 18 18 <translatableAttribute id="tooltip">Choose player to view</translatableAttribute> 19 <action on="SelectionChange">selectViewPlayer(this.selected );</action>19 <action on="SelectionChange">selectViewPlayer(this.selected - 1);</action> 20 20 </object> 21 21 22 22 <!-- ================================ ================================ --> 23 <!-- Observer Mode Warning-->23 <!-- Observer Mode Label --> 24 24 <!-- ================================ ================================ --> 25 25 <object size="50 4 50% 100%-2" name="observerText" type="text" style="ModernLabelText" text_align="left" hidden="true"> 26 <translatableAttribute id="caption">Observer Mode (experimental)</translatableAttribute>26 <translatableAttribute id="caption">Observer Mode</translatableAttribute> 27 27 </object> 28 28 29 29 </object> -
binaries/data/mods/public/simulation/components/GuiInterface.js
GuiInterface.prototype.CheckTechnologyRe 613 613 return cmpTechnologyManager.CanResearch(data.tech); 614 614 }; 615 615 616 616 // Returns technologies that are being actively researched, along with 617 617 // which entity is researching them and how far along the research is. 618 GuiInterface.prototype.GetStartedResearch = function(player )618 GuiInterface.prototype.GetStartedResearch = function(player, viewedPlayer) 619 619 { 620 let cmpTechnologyManager = QueryPlayerIDInterface( player, IID_TechnologyManager);620 let cmpTechnologyManager = QueryPlayerIDInterface(viewedPlayer, IID_TechnologyManager); 621 621 if (!cmpTechnologyManager) 622 return false;622 return {}; 623 623 624 624 let ret = {}; 625 625 for (let tech in cmpTechnologyManager.GetTechsStarted()) 626 626 { 627 627 ret[tech] = { "researcher": cmpTechnologyManager.GetResearcher(tech) }; … … GuiInterface.prototype.GetStartedResearc 633 633 } 634 634 return ret; 635 635 }; 636 636 637 637 // Returns the battle state of the player. 638 GuiInterface.prototype.GetBattleState = function(player )638 GuiInterface.prototype.GetBattleState = function(player, viewedPlayer) 639 639 { 640 let cmpBattleDetection = QueryPlayerIDInterface( player, IID_BattleDetection);640 let cmpBattleDetection = QueryPlayerIDInterface(viewedPlayer, IID_BattleDetection); 641 641 642 642 if (!cmpBattleDetection) 643 643 return false; 644 644 645 645 return cmpBattleDetection.GetState(); … … GuiInterface.prototype.SetMotionDebugOve 1771 1771 GuiInterface.prototype.SetRangeDebugOverlay = function(player, enabled) 1772 1772 { 1773 1773 Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager).SetDebugOverlay(enabled); 1774 1774 }; 1775 1775 1776 GuiInterface.prototype.GetTraderNumber = function(player )1776 GuiInterface.prototype.GetTraderNumber = function(player, viewedPlayer) 1777 1777 { 1778 1778 let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 1779 let traders = cmpRangeManager.GetEntitiesByPlayer( player).filter(e => Engine.QueryInterface(e, IID_Trader));1779 let traders = cmpRangeManager.GetEntitiesByPlayer(viewedPlayer).filter(e => Engine.QueryInterface(e, IID_Trader)); 1780 1780 1781 1781 let landTrader = { "total": 0, "trading": 0, "garrisoned": 0 }; 1782 1782 let shipTrader = { "total": 0, "trading": 0 }; 1783 1783 1784 1784 for each (let ent in traders) … … GuiInterface.prototype.GetTraderNumber = 1810 1810 } 1811 1811 1812 1812 return { "landTrader": landTrader, "shipTrader": shipTrader }; 1813 1813 }; 1814 1814 1815 GuiInterface.prototype.GetTradingGoods = function(player )1815 GuiInterface.prototype.GetTradingGoods = function(player, viewedPlayer) 1816 1816 { 1817 return QueryPlayerIDInterface( player).GetTradingGoods();1817 return QueryPlayerIDInterface(viewedPlayer).GetTradingGoods(); 1818 1818 }; 1819 1819 1820 1820 GuiInterface.prototype.OnGlobalEntityRenamed = function(msg) 1821 1821 { 1822 1822 this.renamedEntities.push(msg);