Ticket #3102: t3102_survival_4.diff
File t3102_survival_4.diff, 12.7 KB (added by , 8 years ago) |
---|
-
binaries/data/mods/public/maps/random/survivalofthefittest.js
for (var i = 0; i < numPlayers; i++) 196 196 3, // elevation 197 197 4 // blend radius 198 198 ); 199 199 createArea(placer, [terrainPainter, elevationPainter, paintClass(clWater)], null); 200 200 201 // creating female citizens201 // Creating seeker woman (these need to have a lower ID than other starting woman for InitGame to identify them) 202 202 var femaleLocation = getTIPIADBON([ix, iz], [mapSize / 2, mapSize / 2], [-3 , 3.5], 1, 3); 203 203 if (femaleLocation !== undefined) 204 204 { 205 205 placeObject(femaleLocation[0], femaleLocation[1], "skirmish/units/default_support_female_citizen", id, playerAngle[i] + PI); 206 206 addToClass(floor(femaleLocation[0]), floor(femaleLocation[1]), clWomen); -
binaries/data/mods/public/maps/random/survivalofthefittest_triggers.js
1 var treasures = 2 [ 1 // Time in minutes when treasures are distributed periodically without random offset. 2 var treasureTime = 3; 3 4 // Time in minutes when resources are distributed periodically without random offset. 5 var provideResourcesTime = 1.25; 6 7 // Time in minutes after which resources are distributed periodically. 8 var provideResourcesOffset = 14 + 2 * Math.random(); 9 10 var treasures = [ 3 11 "gaia/special_treasure_food_barrel", 4 12 "gaia/special_treasure_food_bin", 5 13 "gaia/special_treasure_food_crate", 6 14 "gaia/special_treasure_food_jars", 7 15 "gaia/special_treasure_metal", 8 16 "gaia/special_treasure_stone", 9 17 "gaia/special_treasure_wood", 10 18 "gaia/special_treasure_wood", 11 19 "gaia/special_treasure_wood" 12 20 ]; 13 var attackerEntityTemplates = 14 [ 21 22 var resourceMessage = false; 23 24 // Templates of the attacking units, sorted by civ 25 var attackerEntityTemplates = [ 15 26 [ 16 27 "units/athen_champion_infantry", 17 28 "units/athen_champion_marine", 18 29 "units/athen_champion_ranged", 19 "units/athen_ siege_lithobolos_packed",20 "units/athen_ siege_oxybeles_packed",30 "units/athen_mechanical_siege_lithobolos_packed", 31 "units/athen_mechanical_siege_oxybeles_packed" 21 32 ], 22 33 [ 23 34 "units/brit_champion_cavalry", 24 35 "units/brit_champion_infantry", 25 "units/brit_mechanical_siege_ram" ,36 "units/brit_mechanical_siege_ram" 26 37 ], 27 38 [ 28 39 "units/cart_champion_cavalry", 29 40 "units/cart_champion_elephant", 30 41 "units/cart_champion_infantry", 31 "units/cart_champion_pikeman" ,42 "units/cart_champion_pikeman" 32 43 ], 33 44 [ 34 45 "units/gaul_champion_cavalry", 35 46 "units/gaul_champion_fanatic", 36 47 "units/gaul_champion_infantry", 37 "units/gaul_mechanical_siege_ram" ,48 "units/gaul_mechanical_siege_ram" 38 49 ], 39 50 [ 40 51 "units/iber_champion_cavalry", 41 52 "units/iber_champion_infantry", 42 "units/iber_mechanical_siege_ram" ,53 "units/iber_mechanical_siege_ram" 43 54 ], 44 55 [ 45 56 "units/mace_champion_cavalry", 46 57 "units/mace_champion_infantry_a", 47 58 "units/mace_champion_infantry_e", 48 59 "units/mace_mechanical_siege_lithobolos_packed", 49 "units/mace_mechanical_siege_oxybeles_packed" ,60 "units/mace_mechanical_siege_oxybeles_packed" 50 61 ], 51 62 [ 52 63 "units/maur_champion_chariot", 53 64 "units/maur_champion_elephant", 54 65 "units/maur_champion_infantry", 55 66 "units/maur_champion_maiden", 56 "units/maur_champion_maiden_archer" ,67 "units/maur_champion_maiden_archer" 57 68 ], 58 69 [ 59 70 "units/pers_champion_cavalry", 60 "units/pers_champion_infantry",61 71 "units/pers_champion_elephant", 72 "units/pers_champion_infantry" 62 73 ], 63 74 [ 64 75 "units/ptol_champion_cavalry", 65 "units/ptol_champion_elephant" ,76 "units/ptol_champion_elephant" 66 77 ], 67 78 [ 68 79 "units/rome_champion_cavalry", 69 80 "units/rome_champion_infantry", 70 81 "units/rome_mechanical_siege_ballista_packed", 71 "units/rome_mechanical_siege_scorpio_packed" ,82 "units/rome_mechanical_siege_scorpio_packed" 72 83 ], 73 84 [ 74 85 "units/sele_champion_cavalry", 75 86 "units/sele_champion_chariot", 76 87 "units/sele_champion_elephant", 77 88 "units/sele_champion_infantry_pikeman", 78 "units/sele_champion_infantry_swordsman" ,89 "units/sele_champion_infantry_swordsman" 79 90 ], 80 91 [ 81 92 "units/spart_champion_infantry_pike", 82 93 "units/spart_champion_infantry_spear", 83 94 "units/spart_champion_infantry_sword", 84 "units/spart_mechanical_siege_ram" ,95 "units/spart_mechanical_siege_ram" 85 96 ], 86 97 ]; 87 98 88 99 Trigger.prototype.StartAnEnemyWave = function() 89 100 { 90 101 let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 91 102 let attackerEntities = attackerEntityTemplates[Math.floor(Math.random() * attackerEntityTemplates.length)]; 92 103 // A soldier for each 2-3 minutes of the game. Should be waves of 20 soldiers after an hour 93 let nextTime = Math.round(120000 + Math.random() * 60 000);104 let nextTime = Math.round(120000 + Math.random() * 60 * 1000); 94 105 let attackerCount = Math.round(cmpTimer.GetTime() / nextTime / attackerEntities.length); 95 106 96 // spawn attackers 97 let attackers = []; 98 for (let attackerEntity of attackerEntities) 99 attackers.push(TriggerHelper.SpawnUnitsFromTriggerPoints("A", attackerEntity, attackerCount, 0)); 107 let attackers = attackerEntities.map(ent => 108 TriggerHelper.SpawnUnitsFromTriggerPoints("A", ent, attackerCount, 0)); 100 109 101 110 for (let entityType of attackers) 102 111 { 103 112 for (let origin in entityType) 104 113 { 105 114 let cmpPlayer = QueryOwnerInterface(+origin, IID_Player); 106 if ( cmpPlayer.GetState() != "active")115 if (!cmpPlayer || !cmpTrigger.playerCivicCenter[cmpPlayer.GetPlayerID()]) 107 116 continue; 108 117 109 let cmpPosition = Engine.QueryInterface(this.playerCivicCenter[cmpPlayer.GetPlayerID()], IID_Position);110 // this shouldn't happen if the player is still active118 let cmpPosition = Engine.QueryInterface(cmpTrigger.playerCivicCenter[cmpPlayer.GetPlayerID()], IID_Position); 119 // This shouldn't happen if the player is still active 111 120 if (!cmpPosition || !cmpPosition.IsInWorld) 112 121 continue; 113 122 114 // store the x and z coordinates in the command115 let cmd = cmpPosition.GetPosition();116 cmd.type = "attack-walk";117 cmd.entities = entityType[origin];118 cmd.queued = true;119 cmd.targetClasses = undefined;120 // send the attack-walk command121 ProcessCommand(0, cmd);123 let pos = cmpPosition.GetPosition(); 124 ProcessCommand(0, { 125 "type": "attack-walk", 126 "entities": entityType[origin], 127 "x": pos.x, 128 "z": pos.z, 129 "queued": true 130 }); 122 131 } 123 132 } 124 133 125 134 let cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); 126 135 cmpGUIInterface.PushNotification({ … … Trigger.prototype.StartAnEnemyWave = fun 128 137 "translateMessage": true 129 138 }); 130 139 cmpTrigger.DoAfterDelay(nextTime, "StartAnEnemyWave", {}); // The next wave will come in 3 minutes 131 140 }; 132 141 142 /** 143 * Find all of the civic centers and females, disable some structures, setup activity watch. 144 */ 133 145 Trigger.prototype.InitGame = function() 134 146 { 135 147 let numberOfPlayers = TriggerHelper.GetNumberOfPlayers(); 136 // Find all of the civic centers, disable some structures137 148 for (let i = 1; i < numberOfPlayers; ++i) 138 149 { 139 150 let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 140 151 let playerEntities = cmpRangeManager.GetEntitiesByPlayer(i); // Get all of each player's entities 141 152 153 let foundSeeker = false; 142 154 for (let entity of playerEntities) 155 { 143 156 if (TriggerHelper.EntityHasClass(entity, "CivilCentre")) 144 157 cmpTrigger.playerCivicCenter[i] = entity; 158 159 if (TriggerHelper.EntityHasClass(entity, "Female") && !foundSeeker) 160 { 161 foundSeeker = true; 162 let cmpDamageReceiver = Engine.QueryInterface(entity, IID_DamageReceiver); 163 cmpDamageReceiver.SetInvulnerability(true); 164 165 let cmpHealth = Engine.QueryInterface(entity, IID_Health); 166 cmpHealth.SetUndeletable(true); 167 } 168 } 145 169 } 146 170 147 171 // Fix alliances 148 172 /* Until we can do something about limiting the victory conditions available for this map to "None" 149 173 for (let i = 1; i < numberOfPlayers; ++i) … … Trigger.prototype.InitGame = function() 156 180 }*/ 157 181 158 182 // Make gaia black 159 183 QueryPlayerIDInterface(0).SetColor(0, 0, 0); 160 184 161 // Place the treasures162 185 this.PlaceTreasures(); 163 186 164 187 // Disable farms, civic centers and walls for all players 165 188 for (let i = 1; i < numberOfPlayers; ++i) 166 189 { 167 190 let cmpPlayer = QueryPlayerIDInterface(i); 168 191 let civ = cmpPlayer.GetCiv(); 192 169 193 cmpPlayer.SetDisabledTemplates([ 170 194 "structures/" + civ + "_field", 171 195 "structures/" + civ + "_corral", 172 196 "structures/" + civ + "_civil_centre", 173 197 "structures/" + civ + "_military_colony", … … Trigger.prototype.PlaceTreasures = funct 181 205 { 182 206 let point = ["B", "C", "D"][Math.floor(Math.random() * 3)]; 183 207 let triggerPoints = cmpTrigger.GetTriggerPoints(point); 184 208 for (let point of triggerPoints) 185 209 { 186 let template = treasures[Math.floor(Math.random() * treasures.length)] 187 TriggerHelper.SpawnUnits(point, template, 1, 0); 210 let template = treasures[Math.floor(Math.random() * treasures.length)]; 211 let cmpPosition = Engine.QueryInterface(point, IID_Position); 212 let ent = Engine.AddEntity(template); 213 214 let cmpEntOwnership = Engine.QueryInterface(ent, IID_Ownership); 215 let cmpEntPosition = Engine.QueryInterface(ent, IID_Position); 216 217 if (cmpEntOwnership) 218 cmpEntOwnership.SetOwner(0); 219 220 let xOffset = RandomInt(0, 23); 221 let zOffset = RandomInt(0, 23); 222 223 if (Math.random() >= 0.8) 224 { 225 xOffset += RandomInt(5, 8); 226 zOffset += RandomInt(5, 8); 227 } 228 229 if (Math.round(Math.random()) == 1) 230 xOffset = -xOffset; 231 232 if (Math.round(Math.random()) == 1) 233 zOffset = -zOffset; 234 235 cmpEntPosition.JumpTo(cmpPosition.GetPosition().x + xOffset, cmpPosition.GetPosition().z - zOffset); 188 236 } 189 cmpTrigger.DoAfterDelay(4*60*1000, "PlaceTreasures", {}); //Place more treasures after 4 minutes 237 238 cmpTrigger.DoAfterDelay((treasureTime + Math.random()) * 60 * 1000, "PlaceTreasures", {}); 239 240 let cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); 241 cmpGUIInterface.PushNotification({ 242 "message": markForTranslation("New treasures have been placed!"), 243 "translateMessage": true 244 }); 190 245 }; 191 246 192 247 Trigger.prototype.InitializeEnemyWaves = function() 193 248 { 194 249 let time = (5 + Math.round(Math.random() * 10)) * 60 * 1000; 195 250 let cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); 251 cmpGUIInterface.PushNotification({ 252 "message": markForTranslation("Welcome to Survival of the Fittest"), 253 "translateMessage": true 254 }); 255 cmpGUIInterface.PushNotification({ 256 "message": markForTranslation("Collect treasures with your woman to prepare for the enemies."), 257 "translateMessage": true 258 }); 196 259 cmpGUIInterface.AddTimeNotification({ 197 260 "message": markForTranslation("The first wave will start in %(time)s!"), 198 261 "translateMessage": true 199 262 }, time); 263 200 264 cmpTrigger.DoAfterDelay(time, "StartAnEnemyWave", {}); 201 265 }; 202 266 203 267 Trigger.prototype.DefeatPlayerOnceCCIsDestroyed = function(data) 204 268 { 205 // Defeat a player that has lost his civic center 206 if (data.entity == cmpTrigger.playerCivicCenter[data.from]) 207 { 269 if (data.entity == cmpTrigger.playerCivicCenter[data.from] && data.to == -1) 208 270 TriggerHelper.DefeatPlayer(data.from); 271 }; 209 272 210 // Check if only one player remains. He will be the winner. 211 let lastPlayerStanding = 0; 212 let numPlayersStanding = 0; 213 let numberOfPlayers = TriggerHelper.GetNumberOfPlayers(); 214 for (let i = 1; i < numberOfPlayers; ++i) 215 { 216 if (QueryPlayerIDInterface(i).GetState() == "active") 217 { 218 lastPlayerStanding = i; 219 ++numPlayersStanding; 220 } 221 } 222 if (numPlayersStanding == 1) 223 TriggerHelper.SetPlayerWon(lastPlayerStanding); 273 Trigger.prototype.provideResources = function(data) 274 { 275 if (!resourceMessage) 276 { 277 let cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); 278 cmpGUIInterface.PushNotification({ 279 "message": markForTranslation("From now on, all players will receive some resources from time to time."), 280 "translateMessage": true 281 }); 282 resourceMessage = true; 283 } 284 285 let resources = {}; 286 for (let type of ["food", "wood", "stone", "metal"]) 287 resources[type] = 50 + Math.round(Math.random() * 100); 288 289 let numberOfPlayers = TriggerHelper.GetNumberOfPlayers(); 290 for (let i = 1; i < numberOfPlayers; ++i) 291 { 292 let cmpPlayer = QueryPlayerIDInterface(i); 293 cmpPlayer.AddResources(resources); 224 294 } 295 296 cmpTrigger.DoAfterDelay((provideResourcesTime + Math.random() / 2) * 60 * 1000, "provideResources" , {}); 225 297 }; 226 298 227 299 var cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger); 228 300 cmpTrigger.playerCivicCenter = {}; 301 229 302 cmpTrigger.DoAfterDelay(0, "InitGame", {}); 230 303 cmpTrigger.DoAfterDelay(1000, "InitializeEnemyWaves", {}); 304 cmpTrigger.DoAfterDelay(provideResourcesOffset * 60 * 1000, "provideResources" , {}); 231 305 232 306 cmpTrigger.RegisterTrigger("OnOwnershipChanged", "DefeatPlayerOnceCCIsDestroyed", { "enabled": true });