Ticket #2154: patch_townbell.3.diff
File patch_townbell.3.diff, 20.7 KB (added by , 10 years ago) |
---|
-
binaries/data/mods/public/audio/interface/alarm/alarm_alert_0.xml
1 <?xml version="1.0" encoding="utf-8" standalone="no" ?> 2 <SoundGroup> 3 <Omnipresent>1</Omnipresent> 4 <HeardBy>owner</HeardBy> 5 <Gain>0.25</Gain> 6 <Pitch>1</Pitch> 7 <Priority>100</Priority> 8 <ConeGain>1</ConeGain> 9 <ConeInner>360</ConeInner> 10 <ConeOuter>360</ConeOuter> 11 <Looping>0</Looping> 12 <RandOrder>1</RandOrder> 13 <RandGain>1</RandGain> 14 <GainUpper>0.25</GainUpper> 15 <GainLower>0.2</GainLower> 16 <RandPitch>1</RandPitch> 17 <PitchUpper>1.1</PitchUpper> 18 <PitchLower>0.9</PitchLower> 19 <Threshold>1</Threshold> 20 <Decay>3</Decay> 21 <Replacement>alarmalert0.ogg</Replacement> 22 <Path>audio/interface/alarm/</Path> 23 <Sound>alarmalert0.ogg</Sound> 24 </SoundGroup> -
binaries/data/mods/public/audio/interface/alarm/alarm_alert_1.xml
1 <?xml version="1.0" encoding="utf-8" standalone="no" ?> 2 <SoundGroup> 3 <Omnipresent>1</Omnipresent> 4 <HeardBy>owner</HeardBy> 5 <Gain>0.25</Gain> 6 <Pitch>1</Pitch> 7 <Priority>100</Priority> 8 <ConeGain>1</ConeGain> 9 <ConeInner>360</ConeInner> 10 <ConeOuter>360</ConeOuter> 11 <Looping>0</Looping> 12 <RandOrder>1</RandOrder> 13 <RandGain>1</RandGain> 14 <GainUpper>0.25</GainUpper> 15 <GainLower>0.2</GainLower> 16 <RandPitch>1</RandPitch> 17 <PitchUpper>1.1</PitchUpper> 18 <PitchLower>0.9</PitchLower> 19 <Threshold>1</Threshold> 20 <Decay>3</Decay> 21 <Replacement>alarmalert1.ogg</Replacement> 22 <Path>audio/interface/alarm/</Path> 23 <Sound>alarmalert1.ogg</Sound> 24 </SoundGroup> -
binaries/data/mods/public/audio/interface/alarm/alarm_alert_2.xml
1 <?xml version="1.0" encoding="utf-8" standalone="no" ?> 2 <SoundGroup> 3 <Omnipresent>1</Omnipresent> 4 <HeardBy>owner</HeardBy> 5 <Gain>0.25</Gain> 6 <Pitch>1</Pitch> 7 <Priority>100</Priority> 8 <ConeGain>1</ConeGain> 9 <ConeInner>360</ConeInner> 10 <ConeOuter>360</ConeOuter> 11 <Looping>0</Looping> 12 <RandOrder>1</RandOrder> 13 <RandGain>1</RandGain> 14 <GainUpper>0.25</GainUpper> 15 <GainLower>0.2</GainLower> 16 <RandPitch>1</RandPitch> 17 <PitchUpper>1.1</PitchUpper> 18 <PitchLower>0.9</PitchLower> 19 <Threshold>1</Threshold> 20 <Decay>3</Decay> 21 <Replacement>alarmalert2.ogg</Replacement> 22 <Path>audio/interface/alarm/</Path> 23 <Sound>alarmalert2.ogg</Sound> 24 </SoundGroup> -
binaries/data/mods/public/gui/session/input.js
1844 1844 case "back-to-work": 1845 1845 backToWork(); 1846 1846 break; 1847 case "increase-alert-level": 1848 increaseAlertLevel(); 1849 break; 1850 case "alert-end": 1851 endOfAlert(); 1852 break; 1847 1853 default: 1848 1854 break; 1849 1855 } … … 2106 2112 2107 2113 } 2108 2114 2115 function increaseAlertLevel() 2116 { 2117 var raisers = g_Selection.toList().filter(function(e) { 2118 var state = GetEntityState(e); 2119 if (state && state.alertRaiser && state.alertRaiser.canIncreaseLevel) 2120 return true; 2121 return false; 2122 }); 2123 2124 Engine.PostNetworkCommand({"type": "increase-alert-level", "entities": raisers}); 2125 } 2126 2127 function endOfAlert() 2128 { 2129 var raisers = g_Selection.toList().filter(function(e) { 2130 var state = GetEntityState(e); 2131 if (state && state.alertRaiser && state.alertRaiser.hasRaisedAlert) 2132 return true; 2133 return false; 2134 }); 2135 2136 Engine.PostNetworkCommand({"type": "alert-end", "entities": raisers}); 2137 } 2138 2109 2139 function clearSelection() 2110 2140 { 2111 2141 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.alertRaiser) 307 { 308 if(entState.alertRaiser.canIncreaseLevel) 309 commands.push({ 310 "name": "increase-alert-level", 311 "tooltip": "Raise the alert ! Or raise it again to protect more units.", 312 "icon": "bell_level1.png" 313 }); 314 315 if(entState.alertRaiser.hasRaisedAlert) 316 commands.push({ 317 "name": "alert-end", 318 "tooltip": "End of alert.", 319 "icon": "bell_level0.png" 320 }); 321 } 305 322 306 323 return commands; 307 324 } -
binaries/data/mods/public/simulation/components/AlertRaiser.js
1 function AlertRaiser() {} 2 3 AlertRaiser.prototype.Schema = 4 "<element name='MaximumLevel'><data type='nonNegativeInteger'/></element>" + 5 "<element name='Range'><data type='nonNegativeInteger'/></element>"; 6 7 AlertRaiser.prototype.Init = function() 8 { 9 this.level = 0; 10 11 // Remember the units ordered to garrison 12 this.garrisonedUnits = []; 13 this.walkingUnits = []; 14 }; 15 16 AlertRaiser.prototype.GetLevel = function() 17 { 18 return this.level; 19 }; 20 21 AlertRaiser.prototype.HasRaisedAlert = function() 22 { 23 return this.level > 0; 24 }; 25 26 AlertRaiser.prototype.CanIncreaseLevel = function() 27 { 28 return (this.template.MaximumLevel > this.level); 29 }; 30 31 AlertRaiser.prototype.SoundAlert = function() 32 { 33 var alertString = "alert" + String(this.level); 34 PlaySound(alertString, this.entity); 35 }; 36 37 AlertRaiser.prototype.IncreaseAlertLevel = function() 38 { 39 if(!this.CanIncreaseLevel()) 40 return false; 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 this.level++; 49 this.SoundAlert(); 50 51 // Select units to put under alert 52 // If an alert has already been raised, only give orders to the units who don't already have orders. 53 var rangeMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 54 var level = this.level; 55 var units = rangeMan.ExecuteQuery(this.entity, 0, this.template.Range, players, IID_UnitAI).filter( function(e){ 56 var cmpUnitAI = Engine.QueryInterface(e, IID_UnitAI); 57 return (!cmpUnitAI.IsUnderAlert() && !cmpUnitAI.IsAnimal() && cmpUnitAI.ReactsToAlert(level)); 58 }); 59 60 for each(unit in units) 61 { 62 var cmpUnitAI = Engine.QueryInterface(unit, IID_UnitAI); 63 cmpUnitAI.ReplaceOrder("Alert", {"raiser": this.entity, "force": true}); 64 this.walkingUnits.push(unit); 65 } 66 67 return true; 68 }; 69 70 AlertRaiser.prototype.OnUnitGarrisonedAfterAlert = function(msg) 71 { 72 this.garrisonedUnits.push({"holder": msg.holder, "unit": msg.unit}); 73 74 var index = this.walkingUnits.indexOf(msg.unit); 75 if (index != -1) 76 this.walkingUnits.splice(index, 1); 77 78 } 79 80 AlertRaiser.prototype.EndOfAlert = function() 81 { 82 this.level = 0; 83 this.SoundAlert(); 84 85 // First, handle units not yet garrisoned 86 for each(unit in this.walkingUnits) 87 { 88 var cmpUnitAI = Engine.QueryInterface(unit, IID_UnitAI); 89 if (cmpUnitAI) 90 { 91 cmpUnitAI.ResetAlert(); 92 93 if (cmpUnitAI.HasWorkOrders()) 94 cmpUnitAI.BackToWork(); 95 else 96 cmpUnitAI.ReplaceOrder("Stop", undefined); 97 } 98 } 99 this.walkingUnits = []; 100 101 // Then, eject garrisoned units 102 for each(slot in this.garrisonedUnits) 103 { 104 var cmpGarrisonHolder = Engine.QueryInterface(slot.holder, IID_GarrisonHolder); 105 var cmpUnitAI = Engine.QueryInterface(slot.unit, IID_UnitAI); 106 107 if(cmpGarrisonHolder) 108 { 109 var success = cmpGarrisonHolder.PerformEject([slot.unit], true); 110 if (success && cmpUnitAI) 111 { 112 cmpUnitAI.ResetAlert(); 113 if (cmpUnitAI.HasWorkOrders()) 114 cmpUnitAI.BackToWork(); 115 } 116 } 117 } 118 this.garrisonedUnits = []; 119 120 return true; 121 }; 122 123 Engine.RegisterComponentType(IID_AlertRaiser, "AlertRaiser", AlertRaiser); -
binaries/data/mods/public/simulation/components/GarrisonHolder.js
247 247 cmpAura.ApplyGarrisonBonus(this.entity); 248 248 249 249 Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {}); 250 251 var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI); 252 if (cmpUnitAI && cmpUnitAI.GetAlertRaiser()) 253 Engine.PostMessage(cmpUnitAI.GetAlertRaiser(), MT_UnitGarrisonedAfterAlert, {"holder": this.entity, "unit": entity}); 254 250 255 return true; 251 256 }; 252 257 -
binaries/data/mods/public/simulation/components/GuiInterface.js
350 350 "state": cmpUnitAI.GetCurrentState(), 351 351 "orders": cmpUnitAI.GetOrders(), 352 352 "hasWorkOrders": cmpUnitAI.HasWorkOrders(), 353 "isUnderAlert": cmpUnitAI.IsUnderAlert(), 353 354 }; 354 355 // Add some information needed for ungarrisoning 355 356 if (cmpUnitAI.isGarrisoned && ret.player !== undefined) … … 378 379 "healableClasses": cmpHeal.GetHealableClasses(), 379 380 }; 380 381 } 382 383 var cmpAlertRaiser = Engine.QueryInterface(ent, IID_AlertRaiser); 384 if(cmpAlertRaiser) 385 { 386 ret.alertRaiser = { 387 "level": cmpAlertRaiser.GetLevel(), 388 "canIncreaseLevel": cmpAlertRaiser.CanIncreaseLevel(), 389 "hasRaisedAlert": cmpAlertRaiser.HasRaisedAlert(), 390 }; 391 } 381 392 382 393 ret.visibility = cmpRangeManager.GetLosVisibility(ent, player, false); 383 394 -
binaries/data/mods/public/simulation/components/interfaces/AlertRaiser.js
1 Engine.RegisterInterface("AlertRaiser"); 2 No newline at end of file -
binaries/data/mods/public/simulation/components/interfaces/GarrisonHolder.js
4 4 // sent to the current entity whenever the garrisoned units change. 5 5 Engine.RegisterMessageType("GarrisonedUnitsChanged"); 6 6 7 // Message of the form { "holder": this.entity, "unit" : unit } sent to the AlertRaiser 8 // which ordered the unit "unit" to garrison. 9 Engine.RegisterMessageType("UnitGarrisonedAfterAlert"); -
binaries/data/mods/public/simulation/components/UnitAI.js
3 3 UnitAI.prototype.Schema = 4 4 "<a:help>Controls the unit's movement, attacks, etc, in response to commands from the player.</a:help>" + 5 5 "<a:example/>" + 6 "<element name='AlertReactiveLevel'>" + 7 "<data type='nonNegativeInteger'/>" + 8 "</element>" + 6 9 "<element name='DefaultStance'>" + 7 10 "<choice>" + 8 11 "<value>violent</value>" + … … 664 667 this.SetNextState("INDIVIDUAL.AUTOGARRISON"); 665 668 }, 666 669 670 "Order.Alert": function(msg) { 671 this.alertRaiser = this.order.data.raiser; 672 673 // Find a target to garrison into, if we don't already have one 674 if(!this.garrisoningTarget) 675 { 676 var nearby = this.FindNearbyGarrisonHolder(); 677 if (nearby) 678 this.garrisoningTarget = nearby; 679 else 680 this.FinishOrder(); 681 } 682 683 this.ReplaceOrder("Garrison", {"target": this.garrisoningTarget}); 684 }, 685 667 686 "Order.Cheering": function(msg) { 668 687 this.SetNextState("INDIVIDUAL.CHEERING"); 669 688 }, … … 2383 2402 }, 2384 2403 2385 2404 "MoveCompleted": function() { 2386 this.SetNextState("GARRISONED"); 2405 if(this.garrisoningTarget) // We're under Alert 2406 { 2407 // check that we can garrison in the building we're supposed to garrison in 2408 var cmpGarrisonHolder = Engine.QueryInterface(this.garrisoningTarget, IID_GarrisonHolder); 2409 if (!cmpGarrisonHolder || cmpGarrisonHolder.GetCapacity() <= cmpGarrisonHolder.GetEntities().length) 2410 { 2411 // Try to find another nearby building 2412 var nearby = this.FindNearbyGarrisonHolder(); 2413 if (nearby) 2414 { 2415 this.garrisoningTarget = nearby; 2416 if (this.MoveToTarget(this.garrisoningTarget)) 2417 this.SetNextState("APPROACHING"); 2418 } 2419 else 2420 this.FinishOrder(); 2421 } 2422 else 2423 this.SetNextState("GARRISONED"); 2424 } 2425 else 2426 this.SetNextState("GARRISONED"); 2387 2427 }, 2388 2428 }, 2389 2429 2390 2430 "GARRISONED": { 2391 2431 "enter": function() { 2392 var target = this.order.data.target; 2432 // Target is not handled the same way with Alert and direct garrisoning 2433 if(this.order.data.target) 2434 var target = this.order.data.target; 2435 else 2436 { 2437 if(!this.garrisoningTarget) 2438 { 2439 // We've been unable to find a target nearby, so give up 2440 this.FinishOrder(); 2441 return true; 2442 } 2443 var target = this.garrisoningTarget; 2444 } 2445 2393 2446 var cmpGarrisonHolder = Engine.QueryInterface(target, IID_GarrisonHolder); 2394 2447 2395 2448 // Check that we can garrison here … … 2712 2765 // Queue of remembered works 2713 2766 this.workOrders = []; 2714 2767 2768 // "Town Bell" behaviour 2769 this.alertRaiser = undefined; 2770 this.garrisoningTarget = undefined; 2771 2715 2772 // For preventing increased action rate due to Stop orders or target death. 2716 2773 this.lastAttacked = undefined; 2717 2774 this.lastHealed = undefined; … … 2719 2776 this.SetStance(this.template.DefaultStance); 2720 2777 }; 2721 2778 2779 UnitAI.prototype.ReactsToAlert = function(level) 2780 { 2781 return (this.template.AlertReactiveLevel <= level) 2782 }; 2783 2784 UnitAI.prototype.IsUnderAlert = function() 2785 { 2786 return (this.garrisoningTarget != undefined); 2787 }; 2788 2789 UnitAI.prototype.ResetAlert = function() 2790 { 2791 this.garrisoningTarget = undefined; 2792 }; 2793 2722 2794 UnitAI.prototype.IsFormationController = function() 2723 2795 { 2724 2796 return (this.template.FormationController == "true"); … … 3318 3390 this.workOrders = orders; 3319 3391 }; 3320 3392 3393 UnitAI.prototype.GetAlertRaiser = function() 3394 { 3395 return this.alertRaiser; 3396 }; 3397 3321 3398 UnitAI.prototype.TimerHandler = function(data, lateness) 3322 3399 { 3323 3400 // Reset the timer … … 3562 3639 }; 3563 3640 3564 3641 /** 3642 * Returns the entity ID of the nearest building in which the unit can garrison, 3643 * or undefined if none can be found close enough. 3644 */ 3645 UnitAI.prototype.FindNearbyGarrisonHolder = function() 3646 { 3647 var range = 128; // TODO: what's a sensible number? 3648 3649 // Find buildings owned by this unit's player 3650 var players = []; 3651 var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); 3652 if (cmpOwnership) 3653 players.push(cmpOwnership.GetOwner()); 3654 3655 var rangeMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 3656 var nearby = rangeMan.ExecuteQuery(this.entity, 0, range, players, IID_GarrisonHolder); 3657 for each (var ent in nearby) 3658 { 3659 var cmpGarrisonHolder = Engine.QueryInterface(ent, IID_GarrisonHolder); 3660 // We only want to garrison in buildings, not in moving units like ships,... 3661 var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI); 3662 if (!cmpUnitAI && cmpGarrisonHolder.AllowedToGarrison(this.entity) && cmpGarrisonHolder.GetCapacity() > cmpGarrisonHolder.GetEntities().length) 3663 return ent; 3664 } 3665 3666 return undefined; 3667 }; 3668 3669 /** 3565 3670 * Play a sound appropriate to the current entity. 3566 3671 */ 3567 3672 UnitAI.prototype.PlaySound = function(name) -
binaries/data/mods/public/simulation/helpers/Commands.js
399 399 notifyUnloadFailure(player, garrisonHolder) 400 400 } 401 401 break; 402 403 case "increase-alert-level": 404 for each (var raiser in entities) 405 { 406 var cmpAlertRaiser = Engine.QueryInterface(raiser, IID_AlertRaiser); 407 if (!cmpAlertRaiser || !cmpAlertRaiser.IncreaseAlertLevel()) 408 notifyAlertFailure(player); 409 } 410 break; 411 412 case "alert-end": 413 for each (var raiser in entities) 414 { 415 var cmpAlertRaiser = Engine.QueryInterface(raiser, IID_AlertRaiser); 416 if (!cmpAlertRaiser || !cmpAlertRaiser.EndOfAlert()) 417 notifyAlertFailure(player); 418 } 419 break; 402 420 403 421 case "formation": 404 422 GetFormationUnitAIs(entities, player, cmd.name).forEach(function(cmpUnitAI) { … … 538 556 } 539 557 540 558 /** 559 * Sends a GUI notification about Alerts that failed to be raised 560 */ 561 function notifyAlertFailure(player) 562 { 563 var cmpPlayer = QueryPlayerIDInterface(player, IID_Player); 564 var notification = {"player": cmpPlayer.GetPlayerID(), "message": "Unable to sound the horns" }; 565 var cmpGUIInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); 566 cmpGUIInterface.PushNotification(notification); 567 } 568 569 /** 541 570 * Get some information about the formations used by entities. 542 571 * The entities must have a UnitAI component. 543 572 */ -
binaries/data/mods/public/simulation/templates/special/formation.xml
14 14 <TurnRate>6.0</TurnRate> 15 15 </Position> 16 16 <UnitAI> 17 <AlertReactiveLevel>2</AlertReactiveLevel> 17 18 <DefaultStance>aggressive</DefaultStance> 18 19 <FleeDistance>12.0</FleeDistance> 19 20 <FormationController>true</FormationController> -
binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre.xml
91 91 <constructed>interface/complete/building/complete_civ_center.xml</constructed> 92 92 <attack>attack/weapon/arrowfly.xml</attack> 93 93 <death>attack/destruction/building_collapse_large.xml</death> 94 <alert0>interface/alarm/alarm_alert_0.xml</alert0> 95 <alert1>interface/alarm/alarm_alert_1.xml</alert1> 96 <alert2>interface/alarm/alarm_alert_2.xml</alert2> 94 97 </SoundGroups> 95 98 </Sound> 96 99 <TerritoryInfluence> … … 98 101 <Radius>140</Radius> 99 102 <Weight>65536</Weight> 100 103 </TerritoryInfluence> 104 <AlertRaiser> 105 <MaximumLevel>2</MaximumLevel> 106 <Range>140</Range> 107 </AlertRaiser> 101 108 <Vision> 102 109 <Range>90</Range> 103 110 </Vision> -
binaries/data/mods/public/simulation/templates/template_unit.xml
99 99 <HeightOffset>5.0</HeightOffset> 100 100 </StatusBars> 101 101 <UnitAI> 102 <AlertReactiveLevel>2</AlertReactiveLevel> 102 103 <DefaultStance>aggressive</DefaultStance> 103 104 <FleeDistance>12.0</FleeDistance> 104 105 <FormationController>false</FormationController> -
binaries/data/mods/public/simulation/templates/template_unit_support_female_citizen.xml
86 86 <Stamina> 87 87 <Max>500</Max> 88 88 </Stamina> 89 <UnitAI> 90 <AlertReactiveLevel>1</AlertReactiveLevel> 91 </UnitAI> 89 92 <UnitMotion> 90 93 <WalkSpeed>8.0</WalkSpeed> 91 94 <Run>