Ticket #2154: patch_townbell.diff
File patch_townbell.diff, 20.2 KB (added by , 11 years ago) |
---|
-
binaries/data/mods/public/art/textures/ui/session/icons/bell_level0.png
Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
-
binaries/data/mods/public/art/textures/ui/session/icons/bell_level1.png
Property changes on: binaries/data/mods/public/art/textures/ui/session/icons/bell_level0.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
-
binaries/data/mods/public/art/textures/ui/session/icons/bell_level2.png
Property changes on: binaries/data/mods/public/art/textures/ui/session/icons/bell_level1.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
-
binaries/data/mods/public/gui/session/input.js
Property changes on: binaries/data/mods/public/art/textures/ui/session/icons/bell_level2.png ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property
1841 1841 case "back-to-work": 1842 1842 backToWork(); 1843 1843 break; 1844 case "ring-town-bell-yellow": 1845 ringYellowAlert(); 1846 break; 1847 case "ring-town-bell-red": 1848 ringRedAlert(); 1849 break; 1850 case "ring-town-bell-end": 1851 ringEndOfAlert(); 1852 break; 1844 1853 default: 1845 1854 break; 1846 1855 } … … 2115 2124 2116 2125 } 2117 2126 2127 function ringYellowAlert() 2128 { 2129 var strikers = g_Selection.toList().filter(function(e) { 2130 var state = GetEntityState(e); 2131 if (state && state.townBellStriker && state.townBellStriker.level == "End") 2132 return true; 2133 return false; 2134 }); 2135 2136 Engine.PostNetworkCommand({"type": "ring-town-bell-yellow", "strikers": strikers}); 2137 } 2138 2139 function ringRedAlert() 2140 { 2141 var strikers = g_Selection.toList().filter(function(e) { 2142 var state = GetEntityState(e); 2143 if (state && state.townBellStriker && state.townBellStriker.level == "Yellow") 2144 return true; 2145 return false; 2146 }); 2147 2148 Engine.PostNetworkCommand({"type": "ring-town-bell-red", "strikers": strikers}); 2149 } 2150 2151 function ringEndOfAlert() 2152 { 2153 var strikers = g_Selection.toList().filter(function(e) { 2154 var state = GetEntityState(e); 2155 if (state && state.townBellStriker && (state.townBellStriker.level == "Yellow" || state.townBellStriker.level == "Red")) 2156 return true; 2157 return false; 2158 }); 2159 2160 Engine.PostNetworkCommand({"type": "ring-town-bell-end", "strikers": strikers}); 2161 } 2162 2118 2163 function clearSelection() 2119 2164 { 2120 2165 if(inputState==INPUT_BUILDING_PLACEMENT || inputState==INPUT_BUILDING_WALL_PATHING) -
binaries/data/mods/public/gui/session/utility_functions.js
302 302 "icon": "production.png" 303 303 }); 304 304 } 305 306 if(entState.townBellStriker) 307 { 308 switch(entState.townBellStriker.level) 309 { 310 case "End": 311 commands.push({ 312 "name": "ring-town-bell-yellow", 313 "tooltip": "Town Bell : Garrison all female citizens in the first nearby building", 314 "icon": "bell_level1.png" 315 }); 316 break; 317 case "Yellow": 318 commands.push({ 319 "name": "ring-town-bell-red", 320 "tooltip": "Red Alert : Garrison also the citizen-soldiers", 321 "icon": "bell_level2.png" 322 }); 323 commands.push({ 324 "name": "ring-town-bell-end", 325 "tooltip": "End of Alert", 326 "icon": "bell_level0.png" 327 }); 328 break; 329 case "Red": 330 commands.push({ 331 "name": "ring-town-bell-end", 332 "tooltip": "End of Alert", 333 "icon": "bell_level0.png" 334 }); 335 break; 336 default: 337 break; 338 } 339 } 305 340 306 341 return commands; 307 342 } -
binaries/data/mods/public/simulation/components/GarrisonHolder.js
261 261 262 262 /** 263 263 * Ejects units and orders them to move to the Rally Point. 264 * If a unit was garrisoned by a Town Bell and remembers any work, sends it back to this work. 264 265 * Returns true if successful, false if not 265 266 */ 266 267 GarrisonHolder.prototype.PerformEject = function(entities, forced) … … 268 269 if (!this.IsGarrisoningAllowed() && !forced) 269 270 return false; 270 271 271 var ejectedEntities = []; 272 var ejectedEntities = []; 273 var workers = []; 274 var nonWorkers = []; 272 275 var success = true; 273 276 for each (var entity in entities) 274 277 { 278 // Filter the units who shall go back to work after a Town Bell 279 var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI); 280 if (cmpUnitAI && cmpUnitAI.GetTownBellStriker() && cmpUnitAI.GetLastWorkOrder()) 281 workers.push(entity); 282 else 283 nonWorkers.push(entity); 284 275 285 if (this.Eject(entity, forced)) 276 286 { 277 287 var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); … … 282 292 else 283 293 success = false; 284 294 } 285 286 this.OrderWalkToRallyPoint(ejectedEntities); 295 296 var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); 297 ProcessCommand(cmpOwnership.GetOwner(), {"type": "back-to-work", "workers": workers}); 298 299 this.OrderWalkToRallyPoint(nonWorkers); 300 287 301 this.UpdateGarrisonFlag(); 288 302 289 303 return success; … … 291 305 292 306 /** 293 307 * Unload unit from the garrisoning entity and order them 294 * to move to the Rally Point 308 * to move to the Rally Point (or to its work after a Town Bell) 295 309 * Returns true if successful, false if not 296 310 */ 297 311 GarrisonHolder.prototype.Unload = function(entity, forced) … … 301 315 302 316 /** 303 317 * Unload one or all units that match a template and owner from 304 * the garrisoning entity and order them to move to the Rally Point 318 * the garrisoning entity and order them to move to the Rally Point (or to their work after a Town Bell) 305 319 * Returns true if successful, false if not 306 320 * 307 321 * extendedTemplate has the format "p"+ownerid+"&"+template … … 342 356 343 357 /** 344 358 * Unload all units with same owner as the entity 345 * and order them to move to the Rally Point 359 * and order them to move to the Rally Point (or to their work after a Town Bell) 346 360 * Returns true if all successful, false if not 347 361 */ 348 362 GarrisonHolder.prototype.UnloadAllOwn = function(forced) … … 366 380 367 381 /** 368 382 * Unload all units from the entity 369 * and order them to move to the Rally Point 383 * and order them to move to the Rally Point (or to their work after a Town Bell) 370 384 * Returns true if all successful, false if not 371 385 */ 372 386 GarrisonHolder.prototype.UnloadAll = function(forced) … … 376 390 }; 377 391 378 392 /** 393 * Unload all units garrisoned by the TownBellStriker striker 394 * and order them to move to the Rally Point (or to their work) 395 * Returns true if all successful, false if not 396 */ 397 GarrisonHolder.prototype.UnloadAllTownBell = function(striker, forced) 398 { 399 var entities = []; 400 for each (var entity in this.entities) 401 { 402 var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI); 403 if (cmpUnitAI && cmpUnitAI.GetTownBellStriker() == striker) 404 entities.push(entity); 405 } 406 407 return this.PerformEject(entities, forced); 408 }; 409 410 /** 379 411 * Used to check if the garrisoning entity's health has fallen below 380 412 * a certain limit after which all garrisoned units are unloaded 381 413 */ -
binaries/data/mods/public/simulation/components/GuiInterface.js
377 377 "healableClasses": cmpHeal.GetHealableClasses(), 378 378 }; 379 379 } 380 381 var cmpTownBellStriker = Engine.QueryInterface(ent, IID_TownBellStriker); 382 if(cmpTownBellStriker) 383 { 384 ret.townBellStriker = { 385 "level": cmpTownBellStriker.GetLevel(), 386 }; 387 } 380 388 381 389 ret.visibility = cmpRangeManager.GetLosVisibility(ent, player, false); 382 390 -
binaries/data/mods/public/simulation/components/TownBellStriker.js
1 function TownBellStriker() {} 2 3 TownBellStriker.prototype.Schema = "<element name='Range'><data type='nonNegativeInteger'/></element>"; 4 5 TownBellStriker.prototype.Init = function() 6 { 7 this.level = "End"; 8 }; 9 10 TownBellStriker.prototype.GetLevel = function() 11 { 12 return this.level; 13 }; 14 15 TownBellStriker.prototype.RingYellowAlert = function() 16 { 17 // Find units owned by this unit's player 18 var players = []; 19 var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); 20 if (cmpOwnership) 21 players.push(cmpOwnership.GetOwner()); 22 23 var rangeMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 24 var units = rangeMan.ExecuteQuery(this.entity, 0, this.template.Range, players, IID_UnitAI).filter( function(e){ 25 var cmpIdentity = Engine.QueryInterface(e, IID_Identity); 26 return (cmpIdentity && cmpIdentity.HasClass("Female")); 27 }); 28 29 this.level = "Yellow"; 30 31 for each(unit in units) 32 { 33 var cmpUnitAI = Engine.QueryInterface(unit, IID_UnitAI); 34 cmpUnitAI.AddOrder("TownBell", {"striker": this.entity}, false); 35 } 36 37 return true; 38 }; 39 40 TownBellStriker.prototype.RingRedAlert = function() 41 { 42 // Find units owned by this unit's player 43 var players = []; 44 var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); 45 if (cmpOwnership) 46 players.push(cmpOwnership.GetOwner()); 47 48 // If a yellow alert has already been struck, only give orders to the units who don't already have orders. 49 var rangeMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 50 var units = rangeMan.ExecuteQuery(this.entity, 0, this.template.Range, players, IID_UnitAI).filter( function(e){ 51 var cmpIdentity = Engine.QueryInterface(e, IID_Identity); 52 var cmpUnitAI = Engine.QueryInterface(e, IID_UnitAI); 53 return (cmpIdentity && (cmpIdentity.HasClass("Female") || cmpIdentity.HasClass("CitizenSoldier")) 54 && !cmpUnitAI.GetTownBellStriker() 55 ); 56 }); 57 58 this.level = "Red"; 59 60 for each(unit in units) 61 { 62 var cmpUnitAI = Engine.QueryInterface(unit, IID_UnitAI); 63 cmpUnitAI.AddOrder("TownBell", {"striker": this.entity}, false); 64 } 65 66 return true; 67 }; 68 69 TownBellStriker.prototype.RingEndOfAlert = function() 70 { 71 // Find buildings owned by this unit's player 72 var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); 73 if (cmpOwnership) 74 var player = cmpOwnership.GetOwner(); 75 else 76 return false; 77 78 var rangeMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 79 var holders = rangeMan.GetEntitiesByPlayer(player).filter( function(e) { 80 var cmpGarrisonHolder = Engine.QueryInterface(e, IID_GarrisonHolder); 81 if (cmpGarrisonHolder) 82 return true; 83 return false; 84 }); 85 86 this.level = "End"; 87 88 for each(holder in holders) 89 { 90 var cmpGarrisonHolder = Engine.QueryInterface(holder, IID_GarrisonHolder); 91 cmpGarrisonHolder.UnloadAllTownBell(this.entity, true); 92 } 93 94 return true; 95 }; 96 97 TownBellStriker.prototype.Deinit = function() 98 { 99 100 }; 101 102 TownBellStriker.prototype.OnUpdate = function(msg) 103 { 104 105 }; 106 107 Engine.RegisterComponentType(IID_TownBellStriker, "TownBellStriker", TownBellStriker); -
binaries/data/mods/public/simulation/components/UnitAI.js
620 620 } 621 621 }, 622 622 623 "Order.TownBell": function(msg) { 624 this.townBellStriker = this.order.data.striker; 625 626 // Find a target to garrison into, if we don't already have one 627 if(!this.garrisoningTarget) 628 { 629 var nearby = this.FindNearbyGarrisonHolder(); 630 if (nearby) 631 this.garrisoningTarget = nearby; 632 else 633 this.FinishOrder(); 634 } 635 636 if (this.MoveToTarget(this.garrisoningTarget)) 637 this.SetNextState("INDIVIDUAL.GARRISON.WALKING"); 638 else 639 { 640 // We do a range check before actually garrisoning 641 this.StopMoving(); 642 this.SetNextState("INDIVIDUAL.GARRISON.GARRISONED"); 643 } 644 }, 645 623 646 "Order.Cheering": function(msg) { 624 647 this.SetNextState("INDIVIDUAL.CHEERING"); 625 648 }, … … 2270 2293 this.StopTimer(); 2271 2294 } 2272 2295 }, 2296 2297 // Walking to a good place to garrison, used by Town Bell 2298 "WALKING": { 2299 "enter": function() { 2300 this.SelectAnimation("move"); 2301 }, 2273 2302 2303 "MoveCompleted": function(msg) { 2304 // check that we can garrison in the building we're supposed to garrison in 2305 var cmpGarrisonHolder = Engine.QueryInterface(this.garrisoningTarget, IID_GarrisonHolder); 2306 if (!cmpGarrisonHolder || cmpGarrisonHolder.GetCapacity() <= cmpGarrisonHolder.GetEntities().length) 2307 { 2308 // Try to find another nearby building 2309 var nearby = this.FindNearbyGarrisonHolder(); 2310 if (nearby) 2311 { 2312 this.garrisoningTarget = nearby; 2313 if (this.MoveToTarget(this.garrisoningTarget)) 2314 this.SetNextState("WALKING"); 2315 } 2316 else 2317 this.FinishOrder(); 2318 } 2319 else 2320 this.SetNextState("GARRISONED"); 2321 }, 2322 2323 "leave": function() { 2324 this.StopTimer(); 2325 }, 2326 }, 2327 2274 2328 "GARRISONED": { 2275 2329 "enter": function() { 2276 var target = this.order.data.target; 2330 // Target is not handled the same way with TownBell and direct garrisoning 2331 if(this.order.data.target) 2332 var target = this.order.data.target; 2333 else 2334 var target = this.garrisoningTarget; 2335 2277 2336 var cmpGarrisonHolder = Engine.QueryInterface(target, IID_GarrisonHolder); 2278 2337 2279 2338 // Check that we can garrison here … … 2528 2587 2529 2588 // To go back to work later 2530 2589 this.lastWorkOrder = undefined; 2590 2591 // Town Bell behaviour 2592 this.townBellStriker = undefined; 2593 this.garrisoningTarget = undefined; 2531 2594 2532 2595 // For preventing increased action rate due to Stop orders or target death. 2533 2596 this.lastAttacked = undefined; … … 2830 2893 var template = cmpTemplateManager.GetCurrentTemplateName(this.entity); 2831 2894 error("FinishOrder called for entity " + this.entity + " (" + template + ") when order queue is empty\n" + stack); 2832 2895 } 2896 2897 // Forget all information about Town Bells (typically when finishing the TownBell order) 2898 this.townBellStriker = undefined; 2899 this.garrisoningTarget = undefined; 2833 2900 2834 2901 // Remove the order from the queue, then forget it if it was a work to avoid trying to go back to it later. 2835 2902 var finishedOrder = this.orderQueue.shift(); … … 3008 3075 this.lastWorkOrder = order; 3009 3076 }; 3010 3077 3078 UnitAI.prototype.GetTownBellStriker = function() 3079 { 3080 return this.townBellStriker; 3081 }; 3082 3011 3083 UnitAI.prototype.TimerHandler = function(data, lateness) 3012 3084 { 3013 3085 // Reset the timer … … 3252 3324 }; 3253 3325 3254 3326 /** 3327 * Returns the entity ID of the nearest building in which the unit can garrison, 3328 * or undefined if none can be found close enough. 3329 */ 3330 UnitAI.prototype.FindNearbyGarrisonHolder = function() 3331 { 3332 var range = 64; // TODO: what's a sensible number? 3333 3334 // Find buildings owned by this unit's player 3335 var players = []; 3336 var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); 3337 if (cmpOwnership) 3338 players.push(cmpOwnership.GetOwner()); 3339 3340 var rangeMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 3341 var nearby = rangeMan.ExecuteQuery(this.entity, 0, range, players, IID_GarrisonHolder); 3342 for each (var ent in nearby) 3343 { 3344 var cmpGarrisonHolder = Engine.QueryInterface(ent, IID_GarrisonHolder); 3345 if (cmpGarrisonHolder.AllowedToGarrison(this.entity) && cmpGarrisonHolder.GetCapacity() > cmpGarrisonHolder.GetEntities().length) 3346 return ent; 3347 } 3348 3349 return undefined; 3350 }; 3351 3352 /** 3255 3353 * Play a sound appropriate to the current entity. 3256 3354 */ 3257 3355 UnitAI.prototype.PlaySound = function(name) -
binaries/data/mods/public/simulation/helpers/Commands.js
400 400 notifyBackToWorkFailure(player, worker) 401 401 } 402 402 break; 403 case "ring-town-bell-yellow": 404 var entities = FilterEntityList(cmd.strikers, player, controlAllUnits); 405 for each (var striker in entities) 406 { 407 var cmpTownBellStriker = Engine.QueryInterface(striker, IID_TownBellStriker); 408 if (!cmpTownBellStriker || !cmpTownBellStriker.RingYellowAlert()) 409 notifyBellFailure(player) 410 } 411 break; 412 413 case "ring-town-bell-red": 414 var entities = FilterEntityList(cmd.strikers, player, controlAllUnits); 415 for each (var striker in entities) 416 { 417 var cmpTownBellStriker = Engine.QueryInterface(striker, IID_TownBellStriker); 418 if (!cmpTownBellStriker || !cmpTownBellStriker.RingRedAlert()) 419 notifyBellFailure(player) 420 } 421 break; 422 423 case "ring-town-bell-end": 424 var entities = FilterEntityList(cmd.strikers, player, controlAllUnits); 425 for each (var striker in entities) 426 { 427 var cmpTownBellStriker = Engine.QueryInterface(striker, IID_TownBellStriker); 428 if (!cmpTownBellStriker || !cmpTownBellStriker.RingEndOfAlert()) 429 notifyBellFailure(player) 430 } 431 break; 403 432 404 433 case "formation": 405 434 GetFormationUnitAIs(entities, player, cmd.name).forEach(function(cmpUnitAI) { … … 539 568 } 540 569 541 570 /** 571 * Sends a GUI notification about Town Bells that failed to be struck 572 */ 573 function notifyBellFailure(player) 574 { 575 var cmpPlayer = QueryPlayerIDInterface(player, IID_Player); 576 var notification = {"player": cmpPlayer.GetPlayerID(), "message": "Unable to strike the Town Bell" }; 577 var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); 578 cmpGUIInterface.PushNotification(notification); 579 } 580 581 /** 542 582 * Get some information about the formations used by entities. 543 583 * The entities must have a UnitAI component. 544 584 */ -
binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre.xml
99 99 <Radius>140</Radius> 100 100 <Weight>65536</Weight> 101 101 </TerritoryInfluence> 102 <TownBellStriker> 103 <Range>140</Range> 104 </TownBellStriker> 102 105 <Vision> 103 106 <Range>90</Range> 104 107 </Vision>