Ticket #1907: corral-v2.diff
File corral-v2.diff, 21.0 KB (added by , 11 years ago) |
---|
-
binaries/data/mods/public/gui/session/selection_details.js
159 159 getGUIObjectByName("resourceCarryingText").caption = entState.resourceSupply.gatherers.length + " / " + entState.resourceSupply.maxGatherers + " "; 160 160 getGUIObjectByName("resourceCarryingIcon").tooltip = "Current/max gatherers"; 161 161 } 162 // And for number of corraled animals 163 else if (entState.corral) 164 { 165 getGUIObjectByName("resourceCarryingIcon").hidden = false; 166 getGUIObjectByName("resourceCarryingText").hidden = false; 167 getGUIObjectByName("resourceCarryingIcon").sprite = "stretched:session/portraits/gaia/fauna_sheep.png"; 168 getGUIObjectByName("resourceCarryingText").caption = entState.corral.entities.length + " / " + entState.corral.capacity + " "; 169 getGUIObjectByName("resourceCarryingIcon").tooltip = "Current/max corraled animals"; 170 } 162 171 else 163 172 { 164 173 getGUIObjectByName("resourceCarryingIcon").hidden = true; -
binaries/data/mods/public/gui/session/input.js
232 232 if (targetState.garrisonHolder.entities.length >= targetState.garrisonHolder.capacity) 233 233 tooltip = "[color=\"orange\"]" + tooltip + "[/color]"; 234 234 } 235 if (targetState.corral) 236 { 237 data.command = "corral"; 238 data.target = target; 239 cursor = "action-gather-milk"; 240 tooltip = "Current corraled: " + targetState.corral.entities.length 241 + "/" + targetState.corral.capacity; 242 if (targetState.corral.entities.length >= targetState.corral.capacity) 243 tooltip = "[color=\"orange\"]" + tooltip + "[/color]"; 244 } 235 245 else if (targetState.resourceSupply) 236 246 { 237 247 var resourceType = targetState.resourceSupply.type; … … 333 343 } 334 344 } 335 345 break; 346 case "corral": 347 if (hasClass(entState, "Unit") && targetState.corral) 348 { 349 var tooltip = "Current corraled: " + targetState.corral.entities.length 350 + "/" + targetState.corral.capacity; 351 if (targetState.corral.entities.length >= targetState.corral.capacity) 352 tooltip = "[color=\"orange\"]" + tooltip + "[/color]"; 353 return {"possible": Engine.GuiInterfaceCall("CanBeCorraled", {"entity": entState.id, "corral": target}), "tooltip": tooltip}; 354 } 355 break; 336 356 case "setup-trade-route": 337 357 // If ground or sea trade possible 338 358 if (!targetState.foundation && ((entState.trader && hasClass(entState, "Organic") && (playerOwned || allyOwned) && hasClass(targetState, "Market")) || … … 499 519 { 500 520 return {"type": "garrison", "cursor": "action-garrison", "tooltip": actionInfo.tooltip, "target": target}; 501 521 } 522 else if (Engine.HotkeyIsPressed("session.corral") && (actionInfo = getActionInfo("corral", target)).possible) 523 { 524 return {"type": "corral", "cursor": "action-gather-milk", "tooltip": actionInfo.tooltip, "target": target}; 525 } 502 526 else if (Engine.HotkeyIsPressed("session.attackmove") && getActionInfo("attack-move", target).possible) 503 527 { 504 528 return {"type": "attack-move", "cursor": "action-attack-move"}; … … 653 677 return preferredEnts; 654 678 } 655 679 680 // Removes any units with special orders (i.e. escort) 681 function getNoOrderEntities(ents) 682 { 683 var noOrderEnts = []; 684 for each (var ent in ents) 685 { 686 var entState = GetEntityState(ent); 687 if (entState.unitAI.special) 688 continue; 689 noOrderEnts.push(ent); 690 } 691 return noOrderEnts; 692 } 693 656 694 // Removes any support units from the passed list of entities 657 695 function getMilitaryEntities(ents) 658 696 { … … 750 788 } 751 789 } 752 790 791 // By default, we do not want to select units with special orders 792 if (!Engine.HotkeyIsPressed("selection.includeorder")) 793 ents = getNoOrderEntities(ents); 794 753 795 // Remove the bandbox hover highlighting 754 796 g_Selection.setHighlightList([]); 755 797 … … 1206 1248 1207 1249 // TODO: Should we handle "control all units" here as well? 1208 1250 ents = Engine.PickSimilarFriendlyEntities(templateToMatch, showOffscreen, matchRank, false); 1251 1252 // By default, we do not want to select units with special orders 1253 if (!Engine.HotkeyIsPressed("selection.includeorder")) 1254 ents = getNoOrderEntities(ents); 1209 1255 } 1210 1256 else 1211 1257 { … … 1381 1427 Engine.GuiInterfaceCall("PlaySound", { "name": "order_garrison", "entity": selection[0] }); 1382 1428 return true; 1383 1429 1430 case "corral": 1431 Engine.PostNetworkCommand({"type": "corral", "entities": selection, "target": action.target, "queued": queued}); 1432 // Engine.GuiInterfaceCall("PlaySound", { "name": "order_garrison", "entity": selection[0] }); 1433 return true; 1434 1384 1435 case "set-rallypoint": 1385 1436 var pos = undefined; 1386 1437 // if there is a position set in the action then use this so that when setting a -
binaries/data/mods/public/gui/session/session.xml
988 988 <object size="90 -2 126 34" name="attackAndArmorStats" type="image" sprite="stretched:session/icons/stances/defensive.png" tooltip="Attack and Armor" tooltip_style="sessionToolTip"/> 989 989 990 990 <!-- Resource carrying icon/counter --> 991 <!-- Used also for number of gatherers/builders -->991 <!-- Used also for number of gatherers/builders/corraled --> 992 992 <object size="100%-78 -2 100%-28 34" type="text" name="resourceCarryingText" style="CarryingTextRight"/> 993 993 <object size="100%-36 -2 100% 34" type="image" name="resourceCarryingIcon" tooltip_style="sessionToolTip"/> 994 994 </object> -
binaries/data/mods/public/simulation/templates/gaia/fauna_sheep.xml
12 12 <Classes datatype="tokens">Domestic</Classes> 13 13 <Icon>gaia/fauna_sheep.png</Icon> 14 14 </Identity> 15 <UnitAI> 16 <CorralType>food</CorralType> 17 <CorralRate>0.4</CorralRate> 18 </UnitAI> 15 19 <Sound> 16 20 <SoundGroups> 17 21 <select>actor/fauna/animal/sheep.xml</select> -
binaries/data/mods/public/simulation/templates/gaia/fauna_pig.xml
5 5 <SpecificName>Pig</SpecificName> 6 6 <Icon>gaia/fauna_pig.png</Icon> 7 7 </Identity> 8 <UnitAI> 9 <CorralType>food</CorralType> 10 <CorralRate>0.4</CorralRate> 11 </UnitAI> 8 12 <StatusBars> 9 13 <HeightOffset>5.0</HeightOffset> 10 14 </StatusBars> -
binaries/data/mods/public/simulation/templates/template_structure_resource_corral.xml
10 10 <Square width="12.0" depth="22.0"/> 11 11 <Height>5.0</Height> 12 12 </Footprint> 13 <GarrisonHolder> 14 <Max>10</Max> 15 <EjectHealth>0.1</EjectHealth> 16 <List datatype="tokens">Animal</List> 17 <BuffHeal>1</BuffHeal> 18 <LoadingRange>2</LoadingRange> 19 </GarrisonHolder> 13 <Corral> 14 <MaxCapacity>10</MaxCapacity> 15 <Range>6</Range> 16 </Corral> 20 17 <Health> 21 18 <Max>500</Max> 22 19 <SpawnEntityOnDeath>rubble/rubble_2x4</SpawnEntityOnDeath> -
binaries/data/mods/public/simulation/helpers/Commands.js
319 319 } 320 320 break; 321 321 322 case "corral": 323 GetFormationUnitAIs(entities, player).forEach(function(cmpUnitAI) { 324 cmpUnitAI.SetCorraled(cmd.target, cmd.queued); 325 }); 326 break; 327 322 328 case "stop": 323 329 GetFormationUnitAIs(entities, player).forEach(function(cmpUnitAI) { 324 330 cmpUnitAI.Stop(cmd.queued); -
binaries/data/mods/public/simulation/components/GuiInterface.js
272 272 }; 273 273 } 274 274 275 var cmpCorral = Engine.QueryInterface(ent, IID_Corral); 276 if (cmpCorral) 277 { 278 ret.corral = { 279 "entities": cmpCorral.GetEntities(), 280 "capacity": cmpCorral.GetCapacity() 281 }; 282 } 283 275 284 var cmpResourceGatherer = Engine.QueryInterface(ent, IID_ResourceGatherer); 276 285 if (cmpResourceGatherer) 277 286 { … … 318 327 ret.unitAI = { 319 328 "state": cmpUnitAI.GetCurrentState(), 320 329 "orders": cmpUnitAI.GetOrders(), 330 "special": undefined 321 331 }; 332 if (cmpUnitAI.corral) 333 ret.unitAI.special = "corraled"; 322 334 // Add some information needed for ungarrisoning 323 335 if (cmpUnitAI.isGarrisoned && ret.player) 324 336 ret.template = "p" + ret.player + "&" + ret.template; … … 1670 1682 return cmpAttack.CanAttack(data.target); 1671 1683 }; 1672 1684 1685 GuiInterface.prototype.CanBeCorraled = function(player, data) 1686 { 1687 var cmpCorral = Engine.QueryInterface(data.corral, IID_Corral); 1688 if (!cmpCorral) 1689 return false; 1690 1691 return cmpCorral.CanBeCorraled(data.entity); 1692 }; 1693 1673 1694 /* 1674 1695 * Returns batch build time. 1675 1696 */ … … 1754 1775 "GetTradingRouteGain": 1, 1755 1776 "GetTradingDetails": 1, 1756 1777 "CanAttack": 1, 1778 "CanBeCorraled": 1, 1757 1779 "GetBatchTime": 1, 1758 1780 1759 1781 "SetPathfinderDebugOverlay": 1, -
binaries/data/mods/public/simulation/components/UnitAI.js
46 46 "<ref name='positiveDecimal'/>" + 47 47 "</element>"+ 48 48 "</interleave>" + 49 "</optional>" + 50 "<optional>" + 51 "<interleave>" + 52 "<element name='CorralType' a:help='Production type when corraled'>" + 53 "<choice>" + 54 "<value>food</value>" + 55 "<value>metal</value>" + 56 "</choice>" + 57 "</element>" + 58 "<element name='CorralRate' a:help='Production rate per sec when corraled'>" + 59 "<ref name='positiveDecimal'/>" + 60 "</element>" + 61 "</interleave>" + 49 62 "</optional>"; 50 63 51 64 // Unit stances. … … 609 622 } 610 623 }, 611 624 625 "Order.Corral": function(msg) { 626 var cmpCorral = Engine.QueryInterface(msg.data.target, IID_Corral); 627 if (!cmpCorral) 628 { 629 this.FinishOrder(); 630 return; 631 } 632 633 var range = cmpCorral.GetRange(); 634 if (this.MoveToTargetRangeExplicit(this.order.data.target, 0, range)) 635 { 636 this.SetNextState("ANIMAL.CORRAL.APPROACHING"); 637 } 638 else 639 { 640 this.StopMoving(); 641 this.SetNextState("ANIMAL.CORRAL.CORRALED"); 642 } 643 }, 644 612 645 "Order.Cheering": function(msg) { 613 646 this.SetNextState("INDIVIDUAL.CHEERING"); 614 647 }, … … 894 927 this.SetNextStateAlwaysEntering("MEMBER"); 895 928 }, 896 929 930 "Order.Corral": function(msg) { 931 var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); 932 cmpFormation.SetRearrange(false); 933 cmpFormation.CallMemberFunction("SetCorraled", [msg.data.target, false]); 934 935 this.SetNextStateAlwaysEntering("MEMBER"); 936 }, 937 897 938 "IDLE": { 898 939 }, 899 940 … … 2346 2387 this.SetNextState("FLEEING"); 2347 2388 }, 2348 2389 2390 2391 "Order.Corral": function(msg) { 2392 var cmpCorral = Engine.QueryInterface(msg.data.target, IID_Corral); 2393 if (!cmpCorral) 2394 { 2395 this.FinishOrder(); 2396 return; 2397 } 2398 2399 var range = cmpCorral.GetRange(); 2400 if (this.MoveToTargetRangeExplicit(this.order.data.target, 0, range)) 2401 { 2402 this.SetNextState("ANIMAL.CORRAL.APPROACHING"); 2403 } 2404 else 2405 { 2406 this.StopMoving(); 2407 this.SetNextState("ANIMAL.CORRAL.CORRALED"); 2408 } 2409 }, 2410 2349 2411 "IDLE": { 2350 2412 // (We need an IDLE state so that FinishOrder works) 2351 2413 … … 2356 2418 }, 2357 2419 }, 2358 2420 2421 'CORRAL': { 2422 'APPROACHING': { 2423 "MoveCompleted": function() { 2424 var cmpCorral = Engine.QueryInterface(this.order.data.target, IID_Corral); 2425 if (cmpCorral) 2426 { 2427 var range = cmpCorral.GetRange(); 2428 var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); 2429 if (cmpUnitMotion.IsInTargetRange(this.order.data.target, 0, range)) 2430 { 2431 this.SetNextState("ANIMAL.CORRAL.CORRALED"); 2432 return; 2433 } 2434 } 2435 this.FinishOrder(); 2436 }, 2437 }, 2438 2439 'CORRALED': { 2440 "enter": function() { 2441 this.corral = this.order.data.target; 2442 var cmpCorral = Engine.QueryInterface(this.corral, IID_Corral); 2443 if (!cmpCorral || !cmpCorral.AddCorraled(this.entity)) 2444 { 2445 this.SetNextState("ROAMING"); 2446 return true; 2447 } 2448 this.SelectAnimation("feeding"); 2449 return false; 2450 }, 2451 2452 "Order.UnsetCorraled": function() { 2453 this.FinishOrder(); 2454 }, 2455 2456 "leave": function() { 2457 if (this.corral) 2458 { 2459 var cmpCorral = Engine.QueryInterface(this.corral, IID_Corral); 2460 if (cmpCorral) 2461 cmpCorral.RemoveCorraled(this.entity); 2462 delete this.corral; 2463 } 2464 }, 2465 }, 2466 }, 2467 2359 2468 "ROAMING": { 2360 2469 "enter": function() { 2361 2470 // Walk in a random direction … … 3661 3770 case "ReturnResource": 3662 3771 case "Repair": 3663 3772 case "Garrison": 3773 case "Corral": 3664 3774 // Find the target unit's position 3665 3775 var cmpTargetPosition = Engine.QueryInterface(order.data.target, IID_Position); 3666 3776 if (!cmpTargetPosition || !cmpTargetPosition.IsInWorld()) … … 4401 4511 4402 4512 //// Animal specific functions //// 4403 4513 4514 /** 4515 * Adds setcorraled order to the queue, forced by the player. 4516 */ 4517 UnitAI.prototype.SetCorraled = function(target, queued) 4518 { 4519 var cmpCorral = Engine.QueryInterface(target, IID_Corral); 4520 if (!cmpCorral || !cmpCorral.CanBeCorraled(this.entity)) 4521 { 4522 this.WalkToTarget(target, queued); 4523 return; 4524 } 4525 this.AddOrder("Corral", { "target": target, "force": true }, queued); 4526 }; 4527 4528 /** 4529 * Adds unsetcorraled order to the queue. 4530 */ 4531 UnitAI.prototype.UnsetCorraled = function() 4532 { 4533 if (this.corral) 4534 this.AddOrder("UnsetCorraled", null, false); 4535 }; 4536 4537 UnitAI.prototype.GetCorralRate = function() 4538 { 4539 return +(this.template.CorralRate || 0); 4540 }; 4541 4542 UnitAI.prototype.GetCorralType = function() 4543 { 4544 return (this.template.CorralType || null); 4545 }; 4546 4404 4547 UnitAI.prototype.MoveRandomly = function(distance) 4405 4548 { 4406 4549 // We want to walk in a random direction, but avoid getting stuck -
binaries/data/mods/public/simulation/components/interfaces/Corral.js
1 Engine.RegisterInterface("Corral"); 2 3 // Message of the form { }, 4 // sent to the current entity whenever the corraled units change. 5 Engine.RegisterMessageType("CorraledUnitsChanged"); -
binaries/data/mods/public/simulation/components/Corral.js
1 function Corral() {} 2 3 Corral.prototype.Schema = 4 "<element name='MaxCapacity' a:help='Maximum number of corraled units'>" + 5 "<ref name='nonNegativeDecimal'/>" + 6 "</element>" + 7 "<element name='Range' a:help='Range distance of corraled units'>" + 8 "<ref name='nonNegativeDecimal'/>" + 9 "</element>"; 10 11 Corral.prototype.Init = function() 12 { 13 this.entities = []; 14 this.increment = 1; 15 this.timer = undefined; 16 }; 17 18 Corral.prototype.GetCapacity = function() 19 { 20 return +this.template.MaxCapacity; 21 }; 22 23 Corral.prototype.GetEntities = function() 24 { 25 return this.entities; 26 }; 27 28 Corral.prototype.GetRange = function() 29 { 30 return +this.template.Range; 31 }; 32 33 /** 34 * Returns true if the entity ent can be corraled inside, 35 */ 36 Corral.prototype.CanBeCorraled = function(ent) 37 { 38 var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI); 39 if (!cmpUnitAI) 40 return false; 41 // Formation controllers should always respond to commands 42 if (cmpUnitAI.IsFormationController()) 43 return true; 44 45 // The entity must have a corral type not null 46 var entType = cmpUnitAI.GetCorralType(); 47 if (entType == null) 48 return false; 49 // And if there is already a corraled unit, it must have the same type 50 var type = this.GetType(); 51 if (type != null && type != entType) 52 return false; 53 return true; 54 }; 55 56 Corral.prototype.AddCorraled = function(ent) 57 { 58 if (this.entities.indexOf(ent) != -1 || this.entities.length >= this.GetCapacity()) 59 return false; 60 this.entities.push(ent); 61 Engine.PostMessage(this.entity, MT_CorraledUnitsChanged, {}); 62 return true; 63 }; 64 65 Corral.prototype.RemoveCorraled = function(ent) 66 { 67 if (this.entities.indexOf(ent) == -1) 68 return; 69 this.entities.splice(this.entities.indexOf(ent), 1); 70 Engine.PostMessage(this.entity, MT_CorraledUnitsChanged, {}); 71 }; 72 73 Corral.prototype.GetRate = function() 74 { 75 var rate = 0; 76 for each (var ent in this.entities) 77 { 78 var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI); 79 rate += cmpUnitAI.GetCorralRate(); 80 } 81 rate = ApplyTechModificationsToEntity("Corral/Rate", rate, this.entity); 82 return rate; 83 } 84 85 Corral.prototype.GetType = function() 86 { 87 var type = null; 88 if (this.entities.length > 0) 89 { 90 var cmpUnitAI = Engine.QueryInterface(this.entities[0], IID_UnitAI); 91 type= cmpUnitAI.GetCorralType(); 92 } 93 return type; 94 } 95 96 /** 97 * Called every second. Produce food (in corrals) 98 */ 99 Corral.prototype.Timeout = function(data) 100 { 101 var type = this.GetType(); 102 var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 103 if (type != null) 104 { 105 var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player); 106 cmpPlayer.AddResource(type, this.increment); 107 var cmpStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker); 108 if (cmpStatisticsTracker) 109 cmpStatisticsTracker.IncreaseResourceGatheredCounter(type, this.increment); 110 111 var rate = this.GetRate(); 112 this.increment = this.entities.length; 113 this.timer = cmpTimer.SetTimeout(this.entity, IID_Corral, "Timeout", this.increment*1000/rate, {}); 114 } 115 else 116 { 117 cmpTimer.CancelTimer(this.timer); 118 this.timer = undefined; 119 } 120 }; 121 122 123 Corral.prototype.OnCorraledUnitsChanged = function(msg) 124 { 125 if (this.entities.length > 0 && !this.timer) 126 { 127 var rate = this.GetRate(); 128 this.increment = this.entities.length; 129 var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 130 this.timer = cmpTimer.SetTimeout(this.entity, IID_Corral, "Timeout", this.increment*1000/rate, {}); 131 } 132 else if (this.entities.length == 0 && this.timer) 133 { 134 var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 135 cmpTimer.CancelTimer(this.timer); 136 this.timer = undefined; 137 } 138 }; 139 140 Corral.prototype.OnDestroy = function() 141 { 142 if (this.timer) 143 { 144 var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 145 cmpTimer.CancelTimer(this.timer); 146 } 147 148 for (var i = this.entities.length; i > 0; --i) 149 { 150 var cmpUnitAI = Engine.QueryInterface(this.entities[i-1], IID_UnitAI); 151 if (cmpUnitAI) 152 cmpUnitAI.UnsetCorraled(); 153 } 154 }; 155 156 157 Engine.RegisterComponentType(IID_Corral, "Corral", Corral); -
binaries/data/config/default.cfg
270 270 hotkey.session.attack = "Ctrl+Alt" ; Modifier to force attack instead of another action 271 271 hotkey.session.garrison = Ctrl ; Modifier to garrison when clicking on building 272 272 hotkey.session.attackmove = Ctrl ; Modifier to attackmove when clicking on a point 273 hotkey.session.corral = Ctrl ; Modifier to corral an animal 273 274 hotkey.session.queue = Shift ; Modifier to queue unit orders instead of replacing 274 275 hotkey.session.batchtrain = Shift ; Modifier to train units in batches 275 276 hotkey.session.massbarter = Shift ; Modifier to barter bunch of resources … … 278 279 hotkey.session.deselectgroup = Ctrl ; Modifier to deselect units when clicking group icon, instead of selecting 279 280 hotkey.session.rotate.cw = RightBracket ; Rotate building placement preview clockwise 280 281 hotkey.session.rotate.ccw = LeftBracket ; Rotate building placement preview anticlockwise 282 hotkey.selection.includeorder = F1 ; Include in selection the units with special orders 281 283 hotkey.timewarp.fastforward = Space ; If timewarp mode enabled, speed up the game 282 284 hotkey.timewarp.rewind = Backspace ; If timewarp mode enabled, go back to earlier point in the game 283 285