Ticket #3102: t3102_survival_5.diff
File t3102_survival_5.diff, 11.6 KB (added by , 8 years ago) |
---|
-
binaries/data/mods/public/maps/random/survivalofthefittest.js
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 { -
binaries/data/mods/public/maps/random/survivalofthefittest_triggers.js
1 var treasures = 2 [ 1 /** 2 * Time in minutes to the first enemy wave. 3 */ 4 var firstAttackWave = 5 + 10 * Math.random(); 5 6 /** 7 * Time after which resources are distributed periodically. 8 */ 9 var provideResourcesOffset = 14 + 2 * Math.random(); 10 11 /** 12 * Time interval between enemy waves. 13 */ 14 var attackerWaveInterval = [2, 3]; 15 16 /** 17 * Time interval when treasures are distributed periodically. 18 */ 19 var treasureInterval = [3, 4]; 20 21 /** 22 * Time interval after which resources are distributed periodically. 23 */ 24 var provideResourcesInterval = [1.25, 1.75]; 25 26 /** 27 * Amount of miliseconds in minute. 28 */ 29 const minutes = 60 * 1000; 30 31 var treasures = [ 3 32 "gaia/special_treasure_food_barrel", 4 33 "gaia/special_treasure_food_bin", 5 34 "gaia/special_treasure_food_crate", … … 10 39 "gaia/special_treasure_wood", 11 40 "gaia/special_treasure_wood" 12 41 ]; 13 var attackerEntityTemplates = 14 [ 42 43 /** 44 * Templates of the attacking units, sorted by civ 45 */ 46 var attackerTemplates = [ 15 47 [ 16 48 "units/athen_champion_infantry", 17 49 "units/athen_champion_marine", 18 50 "units/athen_champion_ranged", 19 "units/athen_ siege_lithobolos_packed",20 "units/athen_ siege_oxybeles_packed",51 "units/athen_mechanical_siege_lithobolos_packed", 52 "units/athen_mechanical_siege_oxybeles_packed", 21 53 ], 22 54 [ 23 55 "units/brit_champion_cavalry", … … 88 120 Trigger.prototype.StartAnEnemyWave = function() 89 121 { 90 122 let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 91 let attackerEntities = attackerEntityTemplates[Math.floor(Math.random() * attackerEntityTemplates.length)]; 92 // 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() * 60000); 94 let attackerCount = Math.round(cmpTimer.GetTime() / nextTime / attackerEntities.length); 123 let templates = attackerTemplates[Math.floor(Math.random() * attackerTemplates.length)]; 124 let nextTime = Math.round(RandomReal(attackerWaveInterval) * minutes); 125 let attackerCount = Math.ceil(cmpTimer.GetTime() / nextTime / templates.length); 95 126 96 // spawn attackers 97 let attackers = []; 98 for (let attackerEntity of attackerEntities) 99 attackers.push(TriggerHelper.SpawnUnitsFromTriggerPoints("A", attackerEntity, attackerCount, 0)); 127 let attackers = templates.map(ent => 128 TriggerHelper.SpawnUnitsFromTriggerPoints("A", ent, attackerCount, 0)); 100 129 101 130 for (let entityType of attackers) 102 {103 131 for (let origin in entityType) 104 132 { 105 133 let cmpPlayer = QueryOwnerInterface(+origin, IID_Player); 106 if ( cmpPlayer.GetState() != "active")134 if (!cmpPlayer || !cmpTrigger.playerCivicCenter[cmpPlayer.GetPlayerID()]) 107 135 continue; 108 136 109 let cmpPosition = Engine.QueryInterface(this.playerCivicCenter[cmpPlayer.GetPlayerID()], IID_Position);110 // this shouldn't happen if the player is still active137 let cmpPosition = Engine.QueryInterface(cmpTrigger.playerCivicCenter[cmpPlayer.GetPlayerID()], IID_Position); 138 // This shouldn't happen if the player is still active 111 139 if (!cmpPosition || !cmpPosition.IsInWorld) 112 140 continue; 113 141 114 // store the x and z coordinates in the command 115 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 command 121 ProcessCommand(0, cmd); 142 let pos = cmpPosition.GetPosition(); 143 ProcessCommand(0, { 144 "type": "attack-walk", 145 "entities": entityType[origin], 146 "x": pos.x, 147 "z": pos.z, 148 "targetClasses": undefined, 149 "queued": true 150 }); 122 151 } 123 }124 152 125 153 let cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); 126 154 cmpGUIInterface.PushNotification({ … … 127 155 "message": markForTranslation("An enemy wave is attacking!"), 128 156 "translateMessage": true 129 157 }); 130 cmpTrigger.DoAfterDelay(nextTime, "StartAnEnemyWave", {}); // The next wave will come in 3 minutes158 cmpTrigger.DoAfterDelay(nextTime, "StartAnEnemyWave", {}); 131 159 }; 132 160 161 /** 162 * Find all of the civic centers and females, disable some structures, setup activity watch. 163 */ 133 164 Trigger.prototype.InitGame = function() 134 165 { 135 166 let numberOfPlayers = TriggerHelper.GetNumberOfPlayers(); 136 // Find all of the civic centers, disable some structures137 167 for (let i = 1; i < numberOfPlayers; ++i) 138 168 { 139 169 let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 140 170 let playerEntities = cmpRangeManager.GetEntitiesByPlayer(i); // Get all of each player's entities 141 171 172 let foundSeeker = false; 142 173 for (let entity of playerEntities) 174 { 143 175 if (TriggerHelper.EntityHasClass(entity, "CivilCentre")) 144 176 cmpTrigger.playerCivicCenter[i] = entity; 177 178 if (TriggerHelper.EntityHasClass(entity, "Female") && !foundSeeker) 179 { 180 foundSeeker = true; 181 let cmpDamageReceiver = Engine.QueryInterface(entity, IID_DamageReceiver); 182 cmpDamageReceiver.SetInvulnerability(true); 183 184 let cmpHealth = Engine.QueryInterface(entity, IID_Health); 185 cmpHealth.SetUndeletable(true); 186 } 187 } 145 188 } 146 189 147 190 // Fix alliances … … 158 201 // Make gaia black 159 202 QueryPlayerIDInterface(0).SetColor(0, 0, 0); 160 203 161 // Place the treasures 162 this.PlaceTreasures(); 204 this.placeTreasures(); 163 205 164 206 // Disable farms, civic centers and walls for all players 165 207 for (let i = 1; i < numberOfPlayers; ++i) … … 166 208 { 167 209 let cmpPlayer = QueryPlayerIDInterface(i); 168 210 let civ = cmpPlayer.GetCiv(); 211 169 212 cmpPlayer.SetDisabledTemplates([ 170 213 "structures/" + civ + "_field", 171 214 "structures/" + civ + "_corral", … … 177 220 } 178 221 }; 179 222 180 Trigger.prototype. PlaceTreasures = function()223 Trigger.prototype.placeTreasures = function() 181 224 { 182 225 let point = ["B", "C", "D"][Math.floor(Math.random() * 3)]; 183 226 let triggerPoints = cmpTrigger.GetTriggerPoints(point); 184 227 for (let point of triggerPoints) 185 228 { 186 let template = treasures[Math.floor(Math.random() * treasures.length)] 187 TriggerHelper.SpawnUnits(point, template, 1, 0); 229 let template = treasures[Math.floor(Math.random() * treasures.length)]; 230 let cmpPosition = Engine.QueryInterface(point, IID_Position); 231 let ent = Engine.AddEntity(template); 232 233 let cmpEntOwnership = Engine.QueryInterface(ent, IID_Ownership); 234 let cmpEntPosition = Engine.QueryInterface(ent, IID_Position); 235 236 if (cmpEntOwnership) 237 cmpEntOwnership.SetOwner(0); 238 239 let xOffset = RandomInt(0, 23); 240 let zOffset = RandomInt(0, 23); 241 242 if (Math.random() >= 0.8) 243 { 244 xOffset += RandomInt(5, 8); 245 zOffset += RandomInt(5, 8); 246 } 247 248 if (Math.round(Math.random()) == 1) 249 xOffset = -xOffset; 250 251 if (Math.round(Math.random()) == 1) 252 zOffset = -zOffset; 253 254 cmpEntPosition.JumpTo(cmpPosition.GetPosition().x + xOffset, cmpPosition.GetPosition().z - zOffset); 188 255 } 189 cmpTrigger.DoAfterDelay(4*60*1000, "PlaceTreasures", {}); //Place more treasures after 4 minutes 256 257 cmpTrigger.DoAfterDelay(RandomReal(treasureInterval) * minutes, "placeTreasures", {}); 258 259 let cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); 260 cmpGUIInterface.PushNotification({ 261 "message": markForTranslation("New treasures have been placed!"), 262 "translateMessage": true 263 }); 190 264 }; 191 265 192 266 Trigger.prototype.InitializeEnemyWaves = function() 193 267 { 194 let time = (5 + Math.round(Math.random() * 10)) * 60 * 1000;195 268 let cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); 269 270 cmpGUIInterface.PushNotification({ 271 "message": markForTranslation("Welcome to Survival of the Fittest"), 272 "translateMessage": true 273 }); 274 275 cmpGUIInterface.PushNotification({ 276 "message": markForTranslation("Collect treasures with your woman to prepare for the enemies."), 277 "translateMessage": true 278 }); 279 280 let time = firstAttackWave * minutes; 196 281 cmpGUIInterface.AddTimeNotification({ 197 282 "message": markForTranslation("The first wave will start in %(time)s!"), 198 283 "translateMessage": true … … 200 285 cmpTrigger.DoAfterDelay(time, "StartAnEnemyWave", {}); 201 286 }; 202 287 203 Trigger.prototype. DefeatPlayerOnceCCIsDestroyed = function(data)288 Trigger.prototype.defeatPlayerOnceCCIsDestroyed = function(data) 204 289 { 205 // Defeat a player that has lost his civic center 206 if (data.entity == cmpTrigger.playerCivicCenter[data.from]) 207 { 290 if (data.entity == cmpTrigger.playerCivicCenter[data.from] && data.to == -1) 208 291 TriggerHelper.DefeatPlayer(data.from); 292 }; 209 293 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); 294 Trigger.prototype.provideResources = function(data) 295 { 296 if (data.first) 297 { 298 let cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); 299 cmpGUIInterface.PushNotification({ 300 "message": markForTranslation("From now on, all players will receive some resources from time to time."), 301 "translateMessage": true 302 }); 224 303 } 304 305 let resources = {}; 306 for (let type of ["food", "wood", "stone", "metal"]) 307 resources[type] = 50 + Math.round(Math.random() * 100); 308 309 let numberOfPlayers = TriggerHelper.GetNumberOfPlayers(); 310 for (let i = 1; i < numberOfPlayers; ++i) 311 QueryPlayerIDInterface(i).AddResources(resources); 312 313 cmpTrigger.DoAfterDelay(RandomReal(provideResourcesInterval) * minutes, "provideResources", {}); 225 314 }; 226 315 227 316 var cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger); 228 317 cmpTrigger.playerCivicCenter = {}; 318 229 319 cmpTrigger.DoAfterDelay(0, "InitGame", {}); 230 320 cmpTrigger.DoAfterDelay(1000, "InitializeEnemyWaves", {}); 321 cmpTrigger.DoAfterDelay(provideResourcesOffset * minutes, "provideResourcesFirst", { "first": true }); 231 322 232 cmpTrigger.RegisterTrigger("OnOwnershipChanged", " DefeatPlayerOnceCCIsDestroyed", { "enabled": true });323 cmpTrigger.RegisterTrigger("OnOwnershipChanged", "defeatPlayerOnceCCIsDestroyed", { "enabled": true }); -
binaries/data/mods/public/simulation/helpers/Random.js
1 1 /** 2 * Returns a random real in given interval. 3 */ 4 function RandomReal(interval) 5 { 6 let min = Math.min(interval[0], interval[1]); 7 let max = Math.max(interval[0], interval[1]); 8 return min + (max - min) * Math.random(); 9 } 10 11 /** 2 12 * Returns a random integer from min (inclusive) to max (exclusive) 3 13 */ 4 14 function RandomInt(min, max) … … 6 16 return Math.floor(min + Math.random() * (max-min)); 7 17 } 8 18 19 Engine.RegisterGlobal("RandomReal", RandomReal); 9 20 Engine.RegisterGlobal("RandomInt", RandomInt);