Ticket #3102: t3102_survival_6.2.diff
File t3102_survival_6.2.diff, 18.7 KB (added by , 8 years ago) |
---|
-
binaries/data/mods/public/globalscripts/random.js
1 // TODO: rename/change these functions, so the bounds are more clear 2 3 /* 4 * Return a random floating point number using Math.random library 5 * 6 * If no parameter given, the returned float is in the interval [0, 1) 7 * If one parameter given, it's maxval, and the returned float is in the interval [0, maxval) 8 * If two parameters are given, they are minval and maxval, and the returned float is in the interval [minval, maxval) 9 */ 10 function randFloat() 11 { 12 if (arguments.length == 0) 13 return Math.random(); 14 else if (arguments.length == 1) 15 return randFloat() * arguments[0]; 16 else if (arguments.length == 2) 17 { 18 let minVal = arguments[0]; 19 let maxVal = arguments[1]; 20 return minVal + randFloat() * (maxVal - minVal); 21 } 22 else 23 { 24 error("randFloat: invalid number of arguments: "+arguments.length); 25 return undefined; 26 } 27 } 28 29 /* 30 * Return a random integer using Math.random library 31 * 32 * If no parameter given, the returned integer is in the interval [0, 1] 33 * If one parameter given, it's maxval, and the returned integer is in the interval [0, maxval) 34 * If two parameters are given, they are minval and maxval, and the returned integer is in the interval [minval, maxval) 35 */ 36 function randInt() 37 { 38 if (arguments.length == 0) 39 return Math.round(randFloat()); 40 else if (arguments.length == 1) 41 return Math.floor(randFloat(arguments[0])); 42 else if (arguments.length == 2) 43 return Math.floor(randFloat(arguments[0], arguments[1])); 44 else 45 { 46 error("randInt: invalid number of arguments: "+arguments.length); 47 return undefined; 48 } 49 } -
binaries/data/mods/public/gui/common/functions_utility.js
3 3 */ 4 4 var g_LastNickNotification = -1; 5 5 6 function getRandom(randomMin, randomMax)7 {8 // Returns a random whole number in a min..max range.9 // NOTE: There should probably be an engine function for this,10 // since we'd need to keep track of random seeds for replays.11 12 var randomNum = randomMin + (randomMax-randomMin)*Math.random(); // num is random, from A to B13 return Math.round(randomNum);14 }15 16 6 // Get list of XML files in pathname with recursion, excepting those starting with _ 17 7 function getXMLFileList(pathname) 18 8 { -
binaries/data/mods/public/gui/common/music.js
132 132 133 133 Music.prototype.getRandomTrack = function(tracks) 134 134 { 135 return tracks[ getRandom(0, tracks.length-1)];135 return tracks[randInt(0, tracks.length)]; 136 136 }; 137 137 138 138 Music.prototype.startPlayList = function(tracks, fadeInPeriod, isLooping) -
binaries/data/mods/public/gui/loading/loading.js
14 14 if (tipTextLoadingArray.length > 0) 15 15 { 16 16 // Set tip text 17 let tipTextFilePath = tipTextLoadingArray[ getRandom(0, tipTextLoadingArray.length-1)];17 let tipTextFilePath = tipTextLoadingArray[randInt(0, tipTextLoadingArray.length)]; 18 18 let tipText = Engine.TranslateLines(Engine.ReadFile(tipTextFilePath)); 19 19 20 20 if (tipText) … … 63 63 64 64 // Pick a random quote of the day (each line is a separate tip). 65 65 let quoteArray = Engine.ReadFileLines("gui/text/quotes.txt"); 66 Engine.GetGUIObjectByName("quoteText").caption = translate(quoteArray[ getRandom(0, quoteArray.length-1)]);66 Engine.GetGUIObjectByName("quoteText").caption = translate(quoteArray[randInt(0, quoteArray.length)]); 67 67 } 68 68 69 69 function displayProgress() -
binaries/data/mods/public/maps/random/rmgen/random.js
1 // TODO: rename/change these functions, so the bounds are more clear2 3 /*4 * Return a random floating point number using Math.random library5 *6 * If no parameter given, the returned float is in the interval [0, 1)7 * If two parameters are given, they are minval and maxval, and the returned float is in the interval [minval, maxval)8 */9 function randFloat()10 {11 if (arguments.length == 0)12 {13 return Math.random();14 }15 else if (arguments.length == 2)16 {17 var minVal = arguments[0];18 var maxVal = arguments[1];19 20 return minVal + randFloat() * (maxVal - minVal);21 }22 else23 {24 error("randFloat: invalid number of arguments: "+arguments.length);25 return undefined;26 }27 }28 29 /*30 * Return a random integer using Math.random library31 *32 * If one parameter given, it's maxval, and the returned integer is in the interval [0, maxval)33 * If two parameters are given, they are minval and maxval, and the returned integer is in the interval [minval, maxval]34 */35 function randInt()36 {37 if (arguments.length == 1)38 {39 var maxVal = arguments[0];40 return Math.floor(Math.random() * maxVal);41 }42 else if (arguments.length == 2)43 {44 var minVal = arguments[0];45 var maxVal = arguments[1];46 47 return minVal + randInt(maxVal - minVal + 1);48 }49 else50 {51 error("randInt: invalid number of arguments: "+arguments.length);52 return undefined;53 }54 } -
binaries/data/mods/public/maps/random/survivalofthefittest.js
Property changes on: binaries/data/mods/public/maps/random/rmgen/random.js ___________________________________________________________________ Deleted: svn:eol-style ## -1 +0,0 ## -native \ No newline at end of property
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, 15]; 5 6 /** 7 * Time after which resources are distributed periodically. 8 */ 9 var provideResourcesOffset = [14, 16]; 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 interval of resources distributed. 28 */ 29 var resourceAmountInterval = [50, 150]; 30 31 /** 32 * Amount of miliseconds in minute. 33 */ 34 const minutes = 60 * 1000; 35 36 var treasures = [ 3 37 "gaia/special_treasure_food_barrel", 4 38 "gaia/special_treasure_food_bin", 5 39 "gaia/special_treasure_food_crate", … … 10 44 "gaia/special_treasure_wood", 11 45 "gaia/special_treasure_wood" 12 46 ]; 13 var attackerEntityTemplates = 14 [ 47 48 /** 49 * Templates of the attacking units, sorted by civ 50 */ 51 var attackerTemplates = [ 15 52 [ 16 53 "units/athen_champion_infantry", 17 54 "units/athen_champion_marine", 18 55 "units/athen_champion_ranged", 19 "units/athen_ siege_lithobolos_packed",20 "units/athen_ siege_oxybeles_packed",56 "units/athen_mechanical_siege_lithobolos_packed", 57 "units/athen_mechanical_siege_oxybeles_packed", 21 58 ], 22 59 [ 23 60 "units/brit_champion_cavalry", … … 88 125 Trigger.prototype.StartAnEnemyWave = function() 89 126 { 90 127 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); 128 let templates = attackerTemplates[Math.floor(Math.random() * attackerTemplates.length)]; 129 let nextTime = randFloat(attackerWaveInterval[0], attackerWaveInterval[1]) * minutes; 130 let attackerCount = Math.ceil(cmpTimer.GetTime() / nextTime / templates.length); 95 131 96 // spawn attackers 97 let attackers = []; 98 for (let attackerEntity of attackerEntities) 99 attackers.push(TriggerHelper.SpawnUnitsFromTriggerPoints("A", attackerEntity, attackerCount, 0)); 132 let attackers = templates.map(ent => 133 TriggerHelper.SpawnUnitsFromTriggerPoints("A", ent, attackerCount, 0)); 100 134 101 135 for (let entityType of attackers) 102 {103 136 for (let origin in entityType) 104 137 { 138 // Destroy attackers for non active players 105 139 let cmpPlayer = QueryOwnerInterface(+origin, IID_Player); 106 if (cmpPlayer.GetState() != "active") 140 if (!cmpPlayer || !cmpTrigger.playerCivicCenter[cmpPlayer.GetPlayerID()]) 141 { 142 Engine.DestroyEntity(+entityType[origin]) 107 143 continue; 144 } 108 145 109 let cmpPosition = Engine.QueryInterface(this.playerCivicCenter[cmpPlayer.GetPlayerID()], IID_Position);110 // this shouldn't happen if the player is still active146 let cmpPosition = Engine.QueryInterface(cmpTrigger.playerCivicCenter[cmpPlayer.GetPlayerID()], IID_Position); 147 // This shouldn't happen if the player is still active 111 148 if (!cmpPosition || !cmpPosition.IsInWorld) 112 149 continue; 113 150 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); 151 let pos = cmpPosition.GetPosition(); 152 ProcessCommand(0, { 153 "type": "attack-walk", 154 "entities": entityType[origin], 155 "x": pos.x, 156 "z": pos.z, 157 "targetClasses": undefined, 158 "queued": true 159 }); 122 160 } 123 }124 161 125 162 let cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); 126 163 cmpGUIInterface.PushNotification({ … … 127 164 "message": markForTranslation("An enemy wave is attacking!"), 128 165 "translateMessage": true 129 166 }); 130 cmpTrigger.DoAfterDelay(nextTime, "StartAnEnemyWave", {}); // The next wave will come in 3 minutes167 cmpTrigger.DoAfterDelay(nextTime, "StartAnEnemyWave", {}); 131 168 }; 132 169 170 /** 171 * Find all of the civic centers and females, disable some structures, setup activity watch. 172 */ 133 173 Trigger.prototype.InitGame = function() 134 174 { 175 // Set random offset on consts 176 firstAttackWave = randFloat(firstAttackWave[0], firstAttackWave[1]); 177 provideResourcesOffset = randFloat(provideResourcesOffset[0], provideResourcesOffset[1]); 178 135 179 let numberOfPlayers = TriggerHelper.GetNumberOfPlayers(); 136 // Find all of the civic centers, disable some structures137 180 for (let i = 1; i < numberOfPlayers; ++i) 138 181 { 139 182 let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 140 183 let playerEntities = cmpRangeManager.GetEntitiesByPlayer(i); // Get all of each player's entities 141 184 185 let foundSeeker = false; 142 186 for (let entity of playerEntities) 187 { 143 188 if (TriggerHelper.EntityHasClass(entity, "CivilCentre")) 144 189 cmpTrigger.playerCivicCenter[i] = entity; 190 191 if (TriggerHelper.EntityHasClass(entity, "Female") && !foundSeeker) 192 { 193 foundSeeker = true; 194 let cmpDamageReceiver = Engine.QueryInterface(entity, IID_DamageReceiver); 195 cmpDamageReceiver.SetInvulnerability(true); 196 197 let cmpHealth = Engine.QueryInterface(entity, IID_Health); 198 cmpHealth.SetUndeletable(true); 199 } 200 } 145 201 } 146 202 147 203 // Fix alliances … … 158 214 // Make gaia black 159 215 QueryPlayerIDInterface(0).SetColor(0, 0, 0); 160 216 161 // Place the treasures162 217 this.PlaceTreasures(); 163 218 164 219 // Disable farms, civic centers and walls for all players … … 166 221 { 167 222 let cmpPlayer = QueryPlayerIDInterface(i); 168 223 let civ = cmpPlayer.GetCiv(); 224 169 225 cmpPlayer.SetDisabledTemplates([ 170 226 "structures/" + civ + "_field", 171 227 "structures/" + civ + "_corral", … … 172 228 "structures/" + civ + "_civil_centre", 173 229 "structures/" + civ + "_military_colony", 174 230 "structures/" + civ + "_wallset_stone", 231 "structures/brit_crannog", 175 232 "other/wallset_palisade" 176 233 ]); 177 234 } … … 183 240 let triggerPoints = cmpTrigger.GetTriggerPoints(point); 184 241 for (let point of triggerPoints) 185 242 { 186 let template = treasures[Math.floor(Math.random() * treasures.length)] 187 TriggerHelper.SpawnUnits(point, template, 1, 0); 243 let template = treasures[Math.floor(Math.random() * treasures.length)]; 244 let cmpPosition = Engine.QueryInterface(point, IID_Position); 245 let ent = Engine.AddEntity(template); 246 247 let cmpEntOwnership = Engine.QueryInterface(ent, IID_Ownership); 248 let cmpEntPosition = Engine.QueryInterface(ent, IID_Position); 249 250 if (cmpEntOwnership) 251 cmpEntOwnership.SetOwner(0); 252 253 let xOffset = randInt(0, 23); 254 let zOffset = randInt(0, 23); 255 256 if (Math.random() >= 0.8) 257 { 258 xOffset += randInt(5, 8); 259 zOffset += randInt(5, 8); 260 } 261 262 if (Math.round(Math.random()) == 1) 263 xOffset = -xOffset; 264 265 if (Math.round(Math.random()) == 1) 266 zOffset = -zOffset; 267 268 cmpEntPosition.JumpTo(cmpPosition.GetPosition().x + xOffset, cmpPosition.GetPosition().z - zOffset); 188 269 } 189 cmpTrigger.DoAfterDelay(4*60*1000, "PlaceTreasures", {}); //Place more treasures after 4 minutes 270 271 cmpTrigger.DoAfterDelay(randFloat(treasureInterval[0], treasureInterval[1]) * minutes, "PlaceTreasures", {}); 272 273 let cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); 274 cmpGUIInterface.PushNotification({ 275 "message": markForTranslation("New treasures have been placed!"), 276 "translateMessage": true 277 }); 190 278 }; 191 279 192 280 Trigger.prototype.InitializeEnemyWaves = function() 193 281 { 194 let time = (5 + Math.round(Math.random() * 10)) * 60 * 1000;195 282 let cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); 283 284 cmpGUIInterface.PushNotification({ 285 "message": markForTranslation("Welcome to Survival of the Fittest"), 286 "translateMessage": true 287 }); 288 289 cmpGUIInterface.PushNotification({ 290 "message": markForTranslation("Collect treasures with your woman to prepare for the enemies."), 291 "translateMessage": true 292 }); 293 294 let time = firstAttackWave * minutes; 196 295 cmpGUIInterface.AddTimeNotification({ 197 296 "message": markForTranslation("The first wave will start in %(time)s!"), 198 297 "translateMessage": true … … 202 301 203 302 Trigger.prototype.DefeatPlayerOnceCCIsDestroyed = function(data) 204 303 { 205 // Defeat a player that has lost his civic center 206 if (data.entity == cmpTrigger.playerCivicCenter[data.from]) 207 { 304 if (data.entity == cmpTrigger.playerCivicCenter[data.from] && data.to == -1) 208 305 TriggerHelper.DefeatPlayer(data.from); 306 }; 209 307 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); 308 Trigger.prototype.ProvideResources = function(data) 309 { 310 if (data.first) 311 { 312 let cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); 313 cmpGUIInterface.PushNotification({ 314 "message": markForTranslation("From now on, all players will receive some resources from time to time."), 315 "translateMessage": true 316 }); 224 317 } 318 319 let resources = {}; 320 for (let type of ["food", "wood", "stone", "metal"]) 321 resources[type] = randInt(resourceAmountInterval[0], resourceAmountInterval[1]); 322 323 let numberOfPlayers = TriggerHelper.GetNumberOfPlayers(); 324 for (let i = 1; i < numberOfPlayers; ++i) 325 QueryPlayerIDInterface(i).AddResources(resources); 326 327 cmpTrigger.DoAfterDelay(randFloat(provideResourcesInterval[0], provideResourcesInterval[1]) * minutes, "ProvideResources", {}); 225 328 }; 226 329 227 330 var cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger); 228 331 cmpTrigger.playerCivicCenter = {}; 332 229 333 cmpTrigger.DoAfterDelay(0, "InitGame", {}); 230 334 cmpTrigger.DoAfterDelay(1000, "InitializeEnemyWaves", {}); 335 cmpTrigger.DoAfterDelay(provideResourcesOffset * minutes, "ProvideResources", { "first": true }); 231 336 232 337 cmpTrigger.RegisterTrigger("OnOwnershipChanged", "DefeatPlayerOnceCCIsDestroyed", { "enabled": true }); -
binaries/data/mods/public/simulation/components/UnitAI.js
3115 3115 this.SelectAnimation("walk", false, this.GetWalkSpeed()); 3116 3116 this.MoveRandomly(+this.template.RoamDistance); 3117 3117 // Set a random timer to switch to feeding state 3118 this.StartTimer( RandomInt(+this.template.RoamTimeMin, +this.template.RoamTimeMax));3118 this.StartTimer(randInt(+this.template.RoamTimeMin, +this.template.RoamTimeMax)); 3119 3119 this.SetFacePointAfterMove(false); 3120 3120 }, 3121 3121 … … 3160 3160 // Stop and eat for a while 3161 3161 this.SelectAnimation("feeding"); 3162 3162 this.StopMoving(); 3163 this.StartTimer( RandomInt(+this.template.FeedTimeMin, +this.template.FeedTimeMax));3163 this.StartTimer(randInt(+this.template.FeedTimeMin, +this.template.FeedTimeMax)); 3164 3164 }, 3165 3165 3166 3166 "leave": function() { -
binaries/data/mods/public/simulation/helpers/Random.js
1 /**2 * Returns a random integer from min (inclusive) to max (exclusive)3 */4 function RandomInt(min, max)5 {6 return Math.floor(min + Math.random() * (max-min));7 }8 9 Engine.RegisterGlobal("RandomInt", RandomInt);