- Timestamp:
- 08/24/11 00:43:34 (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
ps/trunk/binaries/data/mods/public/simulation/components/TrainingQueue.js
r9970 r10081 29 29 // "template": "units/example", 30 30 // "count": 10, 31 // "resources": { "wood": 100, ... }, 32 // "population": 1 0,31 // "resources": { "wood": 100, ... }, // resources per unit, multiply by count to get total 32 // "population": 1, // population per unit, multiply by count to get total 33 33 // "trainingStarted": false, // true iff we have reserved population 34 34 // "timeTotal": 15000, // msecs … … 37 37 38 38 this.timer = undefined; // g_ProgressInterval msec timer, active while the queue is non-empty 39 }; 40 39 40 this.entityCache = []; 41 this.spawnNotified = false; 42 }; 43 44 /* 45 * Returns list of entities that can be trained by this building. 46 */ 41 47 TrainingQueue.prototype.GetEntitiesList = function() 42 48 { … … 51 57 }; 52 58 59 /* 60 * Adds a new batch of identical units to the training queue. 61 */ 53 62 TrainingQueue.prototype.AddBatch = function(templateName, count, metadata) 54 63 { … … 66 75 return; 67 76 68 var costMult = count;69 70 77 // Apply a time discount to larger batches. 71 78 // TODO: work out what equation we should use here. … … 74 81 var time = timeMult * template.Cost.BuildTime; 75 82 76 var costs = {};83 var totalCosts = {}; 77 84 for each (var r in ["food", "wood", "stone", "metal"]) 78 costs[r] = Math.floor(costMult * template.Cost.Resources[r]);79 80 var population = template.Cost.Population * count;85 totalCosts[r] = Math.floor(count * template.Cost.Resources[r]); 86 87 var population = template.Cost.Population; 81 88 82 89 // TrySubtractResources should report error to player (they ran out of resources) 83 if (!cmpPlayer.TrySubtractResources( costs))90 if (!cmpPlayer.TrySubtractResources(totalCosts)) 84 91 return; 85 92 … … 90 97 "count": count, 91 98 "metadata": metadata, 92 "resources": costs,99 "resources": template.Cost.Resources, 93 100 "population": population, 94 101 "trainingStarted": false, … … 113 120 }; 114 121 122 /* 123 * Removes an existing batch of units from the training queue. 124 * Refunds resource costs and population reservations. 125 */ 115 126 TrainingQueue.prototype.RemoveBatch = function(id) 116 127 { 128 // Destroy any cached entities (those which didn't spawn for some reason) 129 for (var i = 0; i < this.entityCache.length; ++i) 130 { 131 Engine.DestroyEntity(this.entityCache[i]); 132 } 133 this.entityCache = []; 134 117 135 for (var i = 0; i < this.queue.length; ++i) 118 136 { … … 126 144 127 145 // Refund the resource cost for this batch 128 cmpPlayer.AddResources(item.resources); 146 var totalCosts = {}; 147 for each (var r in ["food", "wood", "stone", "metal"]) 148 totalCosts[r] = Math.floor(item.count * item.resources[r]); 149 150 cmpPlayer.AddResources(totalCosts); 129 151 130 152 // Remove reserved population slots if necessary 131 153 if (item.trainingStarted) 132 cmpPlayer.UnReservePopulationSlots(item.population );154 cmpPlayer.UnReservePopulationSlots(item.population * item.count); 133 155 134 156 // Remove from the queue … … 141 163 }; 142 164 165 /* 166 * Returns basic data from all batches in the training queue. 167 */ 143 168 TrainingQueue.prototype.GetQueue = function() 144 169 { … … 157 182 }; 158 183 184 /* 185 * Removes all existing batches from the queue. 186 */ 159 187 TrainingQueue.prototype.ResetQueue = function() 160 188 { … … 197 225 }; 198 226 199 227 /* 228 * This function creates the entities and places them in world if possible. 229 * returns the number of successfully spawned entities. 230 */ 200 231 TrainingQueue.prototype.SpawnUnits = function(templateName, count, metadata) 201 232 { … … 205 236 var cmpRallyPoint = Engine.QueryInterface(this.entity, IID_RallyPoint); 206 237 207 var ents = []; 238 var spawnedEnts = []; 239 240 if (this.entityCache.length == 0) 241 { 242 // We need entities to test spawning, but we don't want to waste resources, 243 // so only create them once and use as needed 244 for (var i = 0; i < count; ++i) 245 { 246 this.entityCache.push(Engine.AddEntity(templateName)); 247 } 248 } 208 249 209 250 for (var i = 0; i < count; ++i) 210 251 { 211 var ent = Engine.AddEntity(templateName); 212 252 var ent = this.entityCache[0]; 213 253 var pos = cmpFootprint.PickSpawnPoint(ent); 214 254 if (pos.y < 0) 215 255 { 216 // Whoops, something went wrong (maybe there wasn't any space to spawn the unit). 217 // What should we do here? 218 // For now, just move the unit into the middle of the building where it'll probably get stuck 219 pos = cmpPosition.GetPosition(); 256 // Fail: there wasn't any space to spawn the unit 257 break; 258 } 259 else 260 { 261 // Successfully spawned 262 var cmpNewPosition = Engine.QueryInterface(ent, IID_Position); 263 cmpNewPosition.JumpTo(pos.x, pos.z); 264 // TODO: what direction should they face in? 265 266 var cmpNewOwnership = Engine.QueryInterface(ent, IID_Ownership); 267 cmpNewOwnership.SetOwner(cmpOwnership.GetOwner()); 220 268 221 var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player); 222 var notification = {"player": cmpPlayer.GetPlayerID(), "message": "Can't find free space to spawn trained unit"}; 223 var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); 224 cmpGUIInterface.PushNotification(notification); 225 } 226 227 var cmpNewPosition = Engine.QueryInterface(ent, IID_Position); 228 cmpNewPosition.JumpTo(pos.x, pos.z); 229 // TODO: what direction should they face in? 230 231 var cmpNewOwnership = Engine.QueryInterface(ent, IID_Ownership); 232 cmpNewOwnership.SetOwner(cmpOwnership.GetOwner()); 233 234 var cmpPlayerStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker); 235 cmpPlayerStatisticsTracker.IncreaseTrainedUnitsCounter(); 236 237 ents.push(ent); 238 239 // Play a sound, but only for the first in the batch (to avoid nasty phasing effects) 240 if (i == 0) 241 PlaySound("trained", ent); 242 } 243 244 // If a rally point is set, walk towards it (in formation) 245 if (cmpRallyPoint) 246 { 247 var rallyPos = cmpRallyPoint.GetPosition(); 248 if (rallyPos) 249 { 250 ProcessCommand(cmpOwnership.GetOwner(), { 251 "type": "walk", 252 "entities": ents, 253 "x": rallyPos.x, 254 "z": rallyPos.z, 255 "queued": false 256 }); 257 } 258 } 259 260 Engine.PostMessage(this.entity, MT_TrainingFinished, { 261 "entities": ents, 262 "owner": cmpOwnership.GetOwner(), 263 "metadata": metadata, 264 }); 265 }; 266 269 var cmpPlayerStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker); 270 cmpPlayerStatisticsTracker.IncreaseTrainedUnitsCounter(); 271 272 // Play a sound, but only for the first in the batch (to avoid nasty phasing effects) 273 if (spawnedEnts.length == 0) 274 PlaySound("trained", ent); 275 276 this.entityCache.shift(); 277 spawnedEnts.push(ent); 278 } 279 } 280 281 if (spawnedEnts.length > 0) 282 { 283 // If a rally point is set, walk towards it (in formation) 284 if (cmpRallyPoint) 285 { 286 var rallyPos = cmpRallyPoint.GetPosition(); 287 if (rallyPos) 288 { 289 ProcessCommand(cmpOwnership.GetOwner(), { 290 "type": "walk", 291 "entities": spawnedEnts, 292 "x": rallyPos.x, 293 "z": rallyPos.z, 294 "queued": false 295 }); 296 } 297 } 298 299 Engine.PostMessage(this.entity, MT_TrainingFinished, { 300 "entities": spawnedEnts, 301 "owner": cmpOwnership.GetOwner(), 302 "metadata": metadata, 303 }); 304 } 305 306 return spawnedEnts.length; 307 }; 308 309 /* 310 * Increments progress on the first batch in the training queue, and blocks the 311 * queue if population limit is reached or some units failed to spawn. 312 */ 267 313 TrainingQueue.prototype.ProgressTimeout = function(data) 268 314 { … … 280 326 // Batch's training hasn't started yet. 281 327 // Try to reserve the necessary population slots 282 if (!cmpPlayer.TryReservePopulationSlots(item.population ))328 if (!cmpPlayer.TryReservePopulationSlots(item.population * item.count)) 283 329 { 284 330 // No slots available - don't train this batch now … … 287 333 // Set flag that training queue is blocked 288 334 cmpPlayer.BlockTrainingQueue(); 289 290 335 break; 291 336 } … … 304 349 } 305 350 306 // This item is finished now 307 time -= item.timeRemaining; 308 cmpPlayer.UnReservePopulationSlots(item.population); 309 this.SpawnUnits(item.template, item.count, item.metadata); 310 this.queue.shift(); 311 Engine.PostMessage(this.entity, MT_TrainingQueueChanged, { }); 351 var numSpawned = this.SpawnUnits(item.template, item.count, item.metadata); 352 if (numSpawned > 0) 353 { 354 // This could be only partially finised 355 cmpPlayer.UnReservePopulationSlots(item.population * numSpawned); 356 item.count -= numSpawned; 357 Engine.PostMessage(this.entity, MT_TrainingQueueChanged, { }); 358 } 359 360 if (item.count == 0) 361 { 362 // All entities spawned, this batch finished 363 time -= item.timeRemaining; 364 this.queue.shift(); 365 // Unset flag that training queue is blocked 366 cmpPlayer.UnBlockTrainingQueue(); 367 this.spawnNotified = false; 368 } 369 else 370 { 371 // Some entities failed to spawn 372 // Set flag that training queue is blocked 373 cmpPlayer.BlockTrainingQueue(); 374 375 if (!this.spawnNotified) 376 { 377 var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player); 378 var notification = {"player": cmpPlayer.GetPlayerID(), "message": "Can't find free space to spawn trained units" }; 379 var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); 380 cmpGUIInterface.PushNotification(notification); 381 this.spawnNotified = true; 382 } 383 break; 384 } 312 385 } 313 386
Note:
See TracChangeset
for help on using the changeset viewer.
