1
0
forked from 0ad/0ad

Turn victory conditions into trigger scripts. Gui needs to be updated to allow combining of different victory conditions + to allow different lists per map. So there are no specific missions yet.

This was SVN commit r15427.
This commit is contained in:
sanderd17 2014-06-23 17:37:27 +00:00
parent b811066b85
commit 8915037631
10 changed files with 211 additions and 135 deletions

View File

@ -3,11 +3,10 @@
const DEFAULT_NETWORKED_MAP = "Acropolis 01";
const DEFAULT_OFFLINE_MAP = "Acropolis 01";
const VICTORY_DEFAULTIDX = 1;
// TODO: Move these somewhere like simulation\data\game_types.json, Atlas needs them too
// Translation: Type of victory condition.
const VICTORY_TEXT = [translateWithContext("victory", "Conquest"), translateWithContext("victory", "Wonder"), translateWithContext("victory", "None")];
const VICTORY_DATA = ["conquest", "wonder", "endless"];
const VICTORY_DEFAULTIDX = 0;
const POPULATION_CAP = ["50", "100", "150", "200", "250", "300", translate("Unlimited")];
const POPULATION_CAP_DATA = [50, 100, 150, 200, 250, 300, 10000];
const POPULATION_CAP_DEFAULTIDX = 5;
@ -158,6 +157,8 @@ function initMain()
mapFilters.list_data = getFilterIds();
g_GameAttributes.mapFilter = "default";
// Setup controls for host only
if (g_IsController)
{
@ -221,12 +222,16 @@ function initMain()
}
var victoryConditions = Engine.GetGUIObjectByName("victoryCondition");
victoryConditions.list = VICTORY_TEXT;
victoryConditions.list_data = VICTORY_DATA;
var victories = getVictoryConditions();
victoryConditions.list = victories.text;
victoryConditions.list_data = victories.data;
victoryConditions.onSelectionChange = function()
{ // Update attributes so other players can see change
if (this.selected != -1)
g_GameAttributes.settings.GameType = VICTORY_DATA[this.selected];
{
g_GameAttributes.settings.GameType = victories.data[this.selected];
g_GameAttributes.settings.VictoryScripts = victories.scripts[this.selected];
}
if (!g_IsInGuiUpdate)
updateGameAttributes();
@ -924,6 +929,10 @@ function launchGame()
if (g_GameAttributes.map == "random")
selectMap(Engine.GetGUIObjectByName("mapSelection").list_data[Math.floor(Math.random() *
(Engine.GetGUIObjectByName("mapSelection").list.length - 1)) + 1]);
if (!g_GameAttributes.settings.TriggerScripts)
g_GameAttributes.settings.TriggerScripts = g_GameAttributes.settings.VictoryScripts;
else
g_GameAttributes.settings.TriggerScripts = g_GameAttributes.settings.VictoryScripts.concat(g_GameAttrbutes.settings.TriggerScripts);
g_GameStarted = true;
g_GameAttributes.settings.mapType = g_GameAttributes.mapType;
var numPlayers = g_GameAttributes.settings.PlayerData.length;
@ -1061,7 +1070,8 @@ function onGameAttributesChange()
// We have to check for undefined on these properties as not all maps define them.
var sizeIdx = (mapSettings.Size !== undefined && g_MapSizes.tiles.indexOf(mapSettings.Size) != -1 ? g_MapSizes.tiles.indexOf(mapSettings.Size) : g_MapSizes["default"]);
var speedIdx = (g_GameAttributes.gameSpeed !== undefined && g_GameSpeeds.speeds.indexOf(g_GameAttributes.gameSpeed) != -1) ? g_GameSpeeds.speeds.indexOf(g_GameAttributes.gameSpeed) : g_GameSpeeds["default"];
var victoryIdx = (mapSettings.GameType !== undefined && VICTORY_DATA.indexOf(mapSettings.GameType) != -1 ? VICTORY_DATA.indexOf(mapSettings.GameType) : VICTORY_DEFAULTIDX);
var victories = getVictoryConditions();
var victoryIdx = (mapSettings.GameType !== undefined && victories.data.indexOf(mapSettings.GameType) != -1 ? victories.data.indexOf(mapSettings.GameType) : VICTORY_DEFAULTIDX);
enableCheats.checked = (mapSettings.CheatsEnabled === undefined || !mapSettings.CheatsEnabled ? false : true)
enableCheatsText.caption = (enableCheats.checked ? "Yes" : "No");
if (mapSettings.RatingEnabled !== undefined)
@ -1138,7 +1148,7 @@ function onGameAttributesChange()
mapSizeText.caption = g_MapSizes.names[sizeIdx];
revealMapText.caption = (mapSettings.RevealMap ? translate("Yes") : translate("No"));
exploreMapText.caption = (mapSettings.ExporeMap ? translate("Yes") : translate("No"));
victoryConditionText.caption = VICTORY_TEXT[victoryIdx];
victoryConditionText.caption = victories.text[victoryIdx];
lockTeamsText.caption = (mapSettings.LockTeams ? translate("Yes") : translate("No"));
}
@ -1194,7 +1204,7 @@ function onGameAttributesChange()
revealMapText.caption = (mapSettings.RevealMap ? translate("Yes") : translate("No"));
exploreMapText.caption = (mapSettings.ExploreMap ? translate("Yes") : translate("No"));
victoryConditionText.caption = VICTORY_TEXT[victoryIdx];
victoryConditionText.caption = victories.text[victoryIdx];
lockTeamsText.caption = (mapSettings.LockTeams ? translate("Yes") : translate("No"));
}
@ -1225,7 +1235,7 @@ function onGameAttributesChange()
mapSizeText.caption = translate("Default");
revealMapText.caption = (mapSettings.RevealMap ? translate("Yes") : translate("No"));
exploreMapText.caption = (mapSettings.ExploreMap ? translate("Yes") : translate("No"));
victoryConditionText.caption = VICTORY_TEXT[victoryIdx];
victoryConditionText.caption = victories.text[victoryIdx];
lockTeamsText.caption = (mapSettings.LockTeams ? translate("Yes") : translate("No"));
Engine.GetGUIObjectByName("populationCap").selected = POPULATION_CAP_DEFAULTIDX;
@ -1847,3 +1857,18 @@ function sendRegisterGameStanza()
};
Engine.SendRegisterGame(gameData);
}
function getVictoryConditions()
{
var r = {};
r.text = [translate("None")];
r.data = ["endless"];
r.scripts = [[]];
for (var vc in g_VictoryConditions)
{
r.data.push(vc);
r.text.push(g_VictoryConditions[vc].name);
r.scripts.push(g_VictoryConditions[vc].scripts);
}
return r;
}

View File

@ -7,6 +7,7 @@
<script file="gui/common/functions_global_object.js"/>
<script file="gui/common/functions_utility.js"/>
<script file="gui/gamesetup/gamesetup.js"/>
<script directory="gui/gamesetup/victory_conditions/"/>
<!-- Add a translucent black background to fade out the menu page -->
<object type="image" style="ModernWindow" size="0 0 100% 100%">

View File

@ -0,0 +1,21 @@
if (!g_VictoryConditions)
var g_VictoryConditions = {};
var vc = {};
vc.name = translate("Conquest");
vc.description = translate("Defeat all opponents");
/*
NOT SUPPORTED YET
vc.requirementsCheck = function(mapSettings)
{
// nothing required
return true;
};
*/
vc.scripts = ["scripts/Conquest.js"];
g_VictoryConditions.conquest = vc;
vc = null;

View File

@ -0,0 +1,21 @@
if (!g_VictoryConditions)
var g_VictoryConditions = {};
var vc = {};
vc.name = translate("Wonder");
vc.description = translate("Build a wonder to win");
/*
NOT SUPPORTED YET
vc.requirementsCheck = function(mapSettings)
{
// nothing required
return true;
};
*/
vc.scripts = ["scripts/Conquest.js", "scripts/WonderVictory.js"];
g_VictoryConditions.wonder = vc;
vc = null;

View File

@ -0,0 +1,70 @@
/*
* Check players the next turn. Avoids problems in Atlas, with promoting entities etc
*/
Trigger.prototype.CheckConquestCriticalEntities = function()
{
if (this.checkingConquestCriticalEntities)
return;
// wait a turn for actually checking the players
this.DoAfterDelay(100, "CheckConquestCriticalEntitiesNow", null);
this.checkingConquestCriticalEntities = true;
};
/*
* Check players immediately. Might cause problems with converting/promoting entities.
*/
Trigger.prototype.CheckConquestCriticalEntitiesNow = function()
{
this.checkingConquestCriticalEntities = false;
// for all other game types, defeat that player
var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
var cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
// Ignore gaia
var numPlayers = cmpPlayerManager.GetNumPlayers();
var cmpPlayers = [];
var allies = [];
var onlyAlliesLeft = true;
// If the player is currently active but needs to be defeated,
// mark that player as defeated
// cache the cmpPlayer instances of the other players and search the allies
for (var i = 1; i < numPlayers; i++)
{
// cmpPlayer should always exist for the player ids from 1 to numplayers
// so no tests on the existance of cmpPlayer are needed
var playerEntityId = cmpPlayerManager.GetPlayerByID(i);
cmpPlayers[i] = Engine.QueryInterface(playerEntityId, IID_Player);
if (cmpPlayers[i].GetState() != "active")
continue;
if (cmpPlayers[i].GetConquestCriticalEntitiesCount() == 0)
Engine.PostMessage(playerEntityId, MT_PlayerDefeated, { "playerId": i } );
else
{
if (!allies.length || cmpPlayers[allies[0]].IsMutualAlly(i))
allies.push(i);
else
onlyAlliesLeft = false;
}
}
// check if there are winners, or the game needs to continue
if (!allies.length || !onlyAlliesLeft || !(cmpEndGameManager.alliedVictory || allies.length == 1))
return;
for each (var p in allies)
cmpPlayers[p].SetState("won");
// Reveal the map to all players
var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
cmpRangeManager.SetLosRevealAll(-1, true);
};
var cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
var data = {"enabled": true};
cmpTrigger.RegisterTrigger("OnOwnershipChanged", "CheckConquestCriticalEntities", data);
// also check at the start of the game
cmpTrigger.DoAfterDelay(100, "CheckConquestCriticalEntities", null);
cmpTrigger.checkingConquestCriticalEntities = false;

View File

@ -0,0 +1,60 @@
Trigger.prototype.CheckWonderVictory = function(data)
{
warn(uneval(data));
var ent = data.entity;
var cmpWonder = Engine.QueryInterface(ent, IID_Wonder);
if (!cmpWonder)
return;
var timer = this.wonderVictoryTimers[ent];
var messages = this.wonderVictoryMessages[ent] || {};
var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
var cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
// remove existing messages if any
if (timer)
{
cmpTimer.CancelTimer(timer);
cmpGuiInterface.DeleteTimeNotification(messages.ownMessage);
cmpGuiInterface.DeleteTimeNotification(messages.otherMessage);
}
if (data.to <= 0)
return;
// create new messages, and start timer to register defeat.
var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
var numPlayers = cmpPlayerManager.GetNumPlayers();
var cmpPlayer = QueryOwnerInterface(ent, IID_Player);
var players = [];
for (var i = 1; i < numPlayers; i++)
if (i != data.to)
players.push(i);
var time = cmpWonder.GetTimeTillVictory()*1000;
messages.otherMessage = cmpGuiInterface.AddTimeNotification({
"message": markForTranslation("%(player)s will have won in %(time)s"),
"players": players,
"duration": time,
"parameters": {"player": cmpPlayer.GetName()},
"translateMessage": true,
"translateParameters": [],
});
messages.ownMessage = cmpGuiInterface.AddTimeNotification({
"message": markForTranslation("You will have won in %(time)s"),
"players": [data.to],
"duration": time,
"translateMessage": true,
});
timer = cmpTimer.SetTimeout(SYSTEM_ENTITY, IID_EndGameManager, "MarkPlayerAsWon", time, data.to);
this.wonderVictoryTimers[ent] = timer;
this.wonderVictoryMessages[ent] = messages;
}
var cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
var data = {"enabled": true};
cmpTrigger.RegisterTrigger("OnOwnershipChanged", "CheckWonderVictory", data);
cmpTrigger.wonderVictoryTimers = {};
cmpTrigger.wonderVictoryMessages = {};

View File

@ -58,69 +58,4 @@ EndGameManager.prototype.SetAlliedVictory = function(flag)
this.alliedVictory = flag;
};
/*
* Check players the next turn. Avoids problems in Atlas, with promoting entities etc
*/
EndGameManager.prototype.CheckConquestCriticalEntities = function()
{
if (this.timeout)
return;
// wait a turn for actually checking the players
var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
this.timeout = cmpTimer.SetTimeout(this.entity, IID_EndGameManager, "CheckConquestCriticalEntitiesNow", 100, null);
};
/*
* Check players immediately. Might cause problems with converting/promoting entities.
*/
EndGameManager.prototype.CheckConquestCriticalEntitiesNow = function()
{
if (this.timeout)
this.timeout = null;
if (this.gameType == "endless")
return;
// for all other game types, defeat that player
var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
// Ignore gaia
var numPlayers = cmpPlayerManager.GetNumPlayers();
var cmpPlayers = [];
var allies = [];
var onlyAlliesLeft = true;
// If the player is currently active but needs to be defeated,
// mark that player as defeated
// cache the cmpPlayer instances of the other players and search the allies
for (var i = 1; i < numPlayers; i++)
{
// cmpPlayer should always exist for the player ids from 1 to numplayers
// so no tests on the existance of cmpPlayer are needed
var playerEntityId = cmpPlayerManager.GetPlayerByID(i);
cmpPlayers[i] = Engine.QueryInterface(playerEntityId, IID_Player);
if (cmpPlayers[i].GetState() != "active")
continue;
if (cmpPlayers[i].GetConquestCriticalEntitiesCount() == 0)
Engine.PostMessage(playerEntityId, MT_PlayerDefeated, { "playerId": i } );
else
{
if (!allies.length || cmpPlayers[allies[0]].IsMutualAlly(i))
allies.push(i);
else
onlyAlliesLeft = false;
}
}
// check if there are winners, or the game needs to continue
if (!allies.length || !onlyAlliesLeft || !(this.alliedVictory || allies.length == 1))
return;
for each (var p in allies)
cmpPlayers[p].SetState("won");
// Reveal the map to all players
var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
cmpRangeManager.SetLosRevealAll(-1, true);
};
Engine.RegisterSystemComponentType(IID_EndGameManager, "EndGameManager", EndGameManager);

View File

@ -42,7 +42,6 @@ Player.prototype.Init = function()
"metal": markForTranslation("Metal"),
"stone": markForTranslation("Stone"),
}
Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager).CheckConquestCriticalEntities();
};
Player.prototype.SetPlayerID = function(id)
@ -586,9 +585,6 @@ Player.prototype.OnGlobalOwnershipChanged = function(msg)
if (!cmpFoundation && cmpIdentity && cmpIdentity.HasClass("ConquestCritical"))
this.conquestCriticalEntitiesCount--;
if (this.conquestCriticalEntitiesCount == 0) // end game when needed
Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager).CheckConquestCriticalEntities();
if (cmpCost)
this.popUsed -= cmpCost.GetPopCost();
@ -649,7 +645,6 @@ Player.prototype.OnPlayerDefeated = function(msg)
Player.prototype.OnDiplomacyChanged = function()
{
this.UpdateSharedLos();
Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager).CheckConquestCriticalEntities();
};
Player.prototype.SetCheatsEnabled = function(flag)

View File

@ -236,7 +236,7 @@ Trigger.prototype.OnGlobalTrainingFinished = function(msg)
Trigger.prototype.OnGlobalOwnershipChanged = function(msg)
{
this.CallEvent("OwnershipChanged", msg);
// data is {"entities": ents, "from": playerId, "to": playerId}
// data is {"entity": ent, "from": playerId, "to": playerId}
};
/**

View File

@ -9,61 +9,9 @@ Wonder.prototype.Init = function()
{
};
Wonder.prototype.OnOwnershipChanged = function(msg)
Wonder.prototype.GetTimeTillVictory = function()
{
this.ResetTimer(msg.to);
};
Wonder.prototype.OnGameTypeChanged = function()
{
var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
if (!cmpPlayer)
return;
this.ResetTimer(cmpPlayer.GetPlayerID());
};
Wonder.prototype.ResetTimer = function(ownerID)
{
var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
var cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
// remove existing messages if any
if (this.timer)
{
cmpTimer.CancelTimer(this.timer);
cmpGuiInterface.DeleteTimeNotification(this.ownMessage);
cmpGuiInterface.DeleteTimeNotification(this.otherMessage);
}
if (ownerID <= 0)
return;
var cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
if (!cmpEndGameManager.CheckGameType("wonder"))
return;
// create new messages, and start timer to register defeat.
var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
var numPlayers = cmpPlayerManager.GetNumPlayers();
var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
var players = [];
for (var i = 1; i < numPlayers; i++)
if (i != ownerID)
players.push(i);
this.otherMessage = cmpGuiInterface.AddTimeNotification({
"message": markForTranslation("%(player)s will have won in %(time)s"),
"players": players,
"duration": +this.template.TimeTillVictory*1000,
"parameters": {"player": cmpPlayer.GetName()},
"translateMessage": true,
"translateParameters": [],
});
this.ownMessage = cmpGuiInterface.AddTimeNotification({
"message": markForTranslation("You will have won in %(time)s"),
"players": [ownerID],
"duration": +this.template.TimeTillVictory*1000,
"translateMessage": true,
});
this.timer = cmpTimer.SetTimeout(SYSTEM_ENTITY, IID_EndGameManager, "MarkPlayerAsWon", +this.template.TimeTillVictory*1000, ownerID);
return +this.template.TimeTillVictory;
};
Engine.RegisterComponentType(IID_Wonder, "Wonder", Wonder);