Index: binaries/data/mods/public/gui/common/gamedescription.js =================================================================== --- binaries/data/mods/public/gui/common/gamedescription.js +++ binaries/data/mods/public/gui/common/gamedescription.js @@ -203,6 +203,12 @@ "label": title, "value": g_VictoryConditions.Description[victoryIdx] }); + + if (g_VictoryConditions.Name[victoryIdx] == "regicide") + titles.push({ + "label": translate("Hero Garrison"), + "value": g_GameAttributes.settings.RegicideGarrison + }); } if (g_GameAttributes.settings.RatingEnabled && Index: binaries/data/mods/public/gui/gamesetup/gamesetup.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/gamesetup.js +++ binaries/data/mods/public/gui/gamesetup/gamesetup.js @@ -519,7 +519,8 @@ "ExploreMap": "exploreMap", "DisableTreasures": "disableTreasures", "LockTeams": "lockTeams", - "LastManStanding" : "lastManStanding", + "LastManStanding": "lastManStanding", + "RegicideGarrison": "regicideGarrison", "CheatsEnabled": "enableCheats" }; @@ -1241,6 +1242,7 @@ { delete g_GameAttributes.settings.WonderDuration; delete g_GameAttributes.settings.LastManStanding; + delete g_GameAttributes.settings.RegicideGarrison; } if (mapSettings.PlayerData) @@ -1425,11 +1427,15 @@ setGUIBoolean("revealMap", "revealMapText", !!mapSettings.RevealMap); setGUIBoolean("lockTeams", "lockTeamsText", !!mapSettings.LockTeams); setGUIBoolean("lastManStanding", "lastManStandingText", !!mapSettings.LastManStanding); + setGUIBoolean("regicideGarrison", "regicideGarrisonText", !!mapSettings.RegicideGarrison); setGUIBoolean("enableRating", "enableRatingText", !!mapSettings.RatingEnabled); Engine.GetGUIObjectByName("optionWonderDuration").hidden = g_GameAttributes.settings.GameType && g_GameAttributes.settings.GameType != "wonder"; + Engine.GetGUIObjectByName("optionRegicideGarrison").hidden = + g_GameAttributes.settings.GameType && + g_GameAttributes.settings.GameType != "regicide"; Engine.GetGUIObjectByName("cheatWarningText").hidden = !g_IsNetworked || !mapSettings.CheatsEnabled; @@ -1448,7 +1454,8 @@ for (let ctrl of ["victoryCondition", "wonderDuration", "populationCap", "startingResources", "ceasefire", "revealMap", - "exploreMap", "disableTreasures", "lockTeams", "lastManStanding"]) + "exploreMap", "disableTreasures", "lockTeams", + "lastManStanding", "regicideGarrison"]) hideControl(ctrl, ctrl + "Text", notScenario); Engine.GetGUIObjectByName("civResetButton").hidden = !notScenario; Index: binaries/data/mods/public/gui/gamesetup/gamesetup.xml =================================================================== --- binaries/data/mods/public/gui/gamesetup/gamesetup.xml +++ binaries/data/mods/public/gui/gamesetup/gamesetup.xml @@ -347,7 +347,17 @@ - + + + Hero Garrison: + + + + + + Population Cap: @@ -357,7 +367,7 @@ - + Starting Resources: @@ -367,7 +377,7 @@ - + Ceasefire: @@ -452,7 +462,7 @@ name="hideMoreOptions" type="button" style="StoneButton" - size="50%-70 428 50%+70 456" + size="50%-70 458 50%+70 486" tooltip_style="onscreenToolTip" hotkey="cancel" > Index: binaries/data/mods/public/gui/session/unit_actions.js =================================================================== --- binaries/data/mods/public/gui/session/unit_actions.js +++ binaries/data/mods/public/gui/session/unit_actions.js @@ -642,7 +642,7 @@ }, "getActionInfo": function(entState, targetState) { - if (!hasClass(entState, "Unit") || + if (!hasClass(entState, "Unit") || hasClass(entState, "Ungarrisonable") || !targetState.garrisonHolder || !playerCheck(entState, targetState, ["Player", "MutualAlly"])) return false; Index: binaries/data/mods/public/maps/scripts/Regicide.js =================================================================== --- binaries/data/mods/public/maps/scripts/Regicide.js +++ binaries/data/mods/public/maps/scripts/Regicide.js @@ -6,6 +6,9 @@ Trigger.prototype.InitRegicideGame = function(msg) { + let cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager); + this.regicideGarrison = cmpEndGameManager.GetGameTypeSettings().regicideGarrison; + let playersCivs = []; for (let playerID = 1; playerID < TriggerHelper.GetNumberOfPlayers(); ++playerID) playersCivs[playerID] = QueryPlayerIDInterface(playerID).GetCiv(); @@ -30,7 +33,7 @@ if (heroTemplates[identity.Civ].indexOf(templateName) == -1) heroTemplates[identity.Civ].push({ - "templateName": templateName, + "templateName": this.regicideGarrison ? templateName : "ungarrisonable|" + templateName, "classes": classes }); } @@ -51,6 +54,28 @@ return 0; }; + let cmpWaterManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_WaterManager); + let cmpTerritoryManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager); + + let gaiaSpawnPreferences = (shipEnt, entity) => { + + let cmpIdentity = Engine.QueryInterface(entity, IID_Identity); + let cmpPosition = Engine.QueryInterface(entity, IID_Position); + let cmpShipPosition = Engine.QueryInterface(shipEnt, IID_Position); + + if (!cmpIdentity || !cmpPosition || !cmpPosition.IsInWorld()) + return Infinity; + + let pos = cmpPosition.GetPosition(); + + // Do not spawn heroes underwater + if (pos.y <= cmpWaterManager.GetWaterLevel(pos.x, pos.z) || + cmpTerritoryManager.GetOwner(pos.x, pos.z) != 0) + return Infinity; + + return Engine.QueryInterface(shipEnt, IID_Position).GetPosition2D().distanceTo(Vector2D.from3D(pos)); + } + // Attempt to spawn one hero per player let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); for (let playerID = 1; playerID < TriggerHelper.GetNumberOfPlayers(); ++playerID) @@ -58,6 +83,11 @@ let spawnPoints = cmpRangeManager.GetEntitiesByPlayer(playerID).sort((entity1, entity2) => getSpawnPreference(entity2) - getSpawnPreference(entity1)); + // Spawn the hero on land as close as possible + if (!this.regicideGarrison && TriggerHelper.EntityHasClass(spawnPoints[0], "Ship")) + spawnPoints = cmpRangeManager.GetEntitiesByPlayer(0).sort((entity1, entity2) => + gaiaSpawnPreferences(spawnPoints[0], entity1) - gaiaSpawnPreferences(spawnPoints[0], entity2)); + this.regicideHeroes[playerID] = this.SpawnRegicideHero(playerID, heroTemplates[playersCivs[playerID]], spawnPoints); } }; @@ -108,5 +138,6 @@ let cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger); cmpTrigger.regicideHeroes = []; +cmpTrigger.regicideGarrison = false; cmpTrigger.DoAfterDelay(0, "InitRegicideGame", {}); cmpTrigger.RegisterTrigger("OnOwnershipChanged", "CheckRegicideDefeat", { "enabled": true }); Index: binaries/data/mods/public/simulation/ai/petra/garrisonManager.js =================================================================== --- binaries/data/mods/public/simulation/ai/petra/garrisonManager.js +++ binaries/data/mods/public/simulation/ai/petra/garrisonManager.js @@ -171,7 +171,7 @@ /** This is just a pre-garrison state, while the entity walk to the garrison holder */ m.GarrisonManager.prototype.garrison = function(gameState, ent, holder, type) { - if (this.numberOfGarrisonedUnits(holder) >= holder.garrisonMax()) + if (this.numberOfGarrisonedUnits(holder) >= holder.garrisonMax() || ent.hasClass("Ungarrisonable")) return; this.registerHolder(gameState, holder); Index: binaries/data/mods/public/simulation/ai/petra/navalManager.js =================================================================== --- binaries/data/mods/public/simulation/ai/petra/navalManager.js +++ binaries/data/mods/public/simulation/ai/petra/navalManager.js @@ -379,6 +379,9 @@ */ m.NavalManager.prototype.requireTransport = function(gameState, entity, startIndex, endIndex, endPos) { + if (entity.hasClass("Ungarrisonable")) + return; + if (entity.getMetadata(PlayerID, "transport") !== undefined) { if (this.Config.debug > 0) Index: binaries/data/mods/public/simulation/components/GarrisonHolder.js =================================================================== --- binaries/data/mods/public/simulation/components/GarrisonHolder.js +++ binaries/data/mods/public/simulation/components/GarrisonHolder.js @@ -200,7 +200,7 @@ if (!cmpIdentity) return false; var entityClasses = cmpIdentity.GetClassesList(); - return MatchesClassList(entityClasses, this.template.List._string); + return MatchesClassList(entityClasses, this.template.List._string) && !cmpIdentity.HasClass("Ungarrisonable"); }; /** Index: binaries/data/mods/public/simulation/helpers/Setup.js =================================================================== --- binaries/data/mods/public/simulation/helpers/Setup.js +++ binaries/data/mods/public/simulation/helpers/Setup.js @@ -47,6 +47,8 @@ let gameTypeSettings = {}; if (settings.WonderDuration) gameTypeSettings.wonderDuration = settings.WonderDuration * 60 * 1000; + if (settings.GameType == "regicide") + gameTypeSettings.regicideGarrison = settings.RegicideGarrison; if (settings.GameType) cmpEndGameManager.SetGameType(settings.GameType, gameTypeSettings); Index: binaries/data/mods/public/simulation/templates/special_filter/ungarrisonable.xml =================================================================== --- binaries/data/mods/public/simulation/templates/special_filter/ungarrisonable.xml +++ binaries/data/mods/public/simulation/templates/special_filter/ungarrisonable.xml @@ -0,0 +1,6 @@ + + + + Ungarrisonable + +