Ticket #1391: shipgarrison-v5.diff
File shipgarrison-v5.diff, 17.4 KB (added by , 11 years ago) |
---|
-
binaries/data/mods/public/simulation/components/UnitAI.js
160 160 // ignore 161 161 }, 162 162 163 "PickupCanceled": function(msg) { 164 // ignore 165 }, 166 163 167 // Formation handlers: 164 168 165 169 "FormationLeave": function(msg) { … … 328 332 } 329 333 }, 330 334 335 "Order.PickupUnit": function(msg) { 336 var cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder); 337 if (!cmpGarrisonHolder || cmpGarrisonHolder.IsFull()) 338 { 339 this.FinishOrder(); 340 return; 341 } 342 343 if (this.MoveToTarget(this.order.data.target)) 344 { 345 this.SetNextState("INDIVIDUAL.PICKUP.APPROACHING"); 346 } 347 else 348 { 349 // We are already at the target, or can't move at all 350 this.StopMoving(); 351 this.SetNextState("INDIVIDUAL.PICKUP.LOADING"); 352 } 353 }, 354 331 355 "Order.Flee": function(msg) { 332 356 // We use the distance between the enities to account for ranged attacks 333 357 var distance = DistanceBetweenEntities(this.entity, this.order.data.target) + (+this.template.FleeDistance); … … 597 621 return; 598 622 } 599 623 600 if (this.MoveTo Target(this.order.data.target))624 if (this.MoveToGarrisonRange(this.order.data.target)) 601 625 { 602 626 this.SetNextState("INDIVIDUAL.GARRISON.APPROACHING"); 603 627 } … … 716 740 }, 717 741 718 742 "Order.Garrison": function(msg) { 719 // TODO: on what should we base this range? 743 if (!Engine.QueryInterface(msg.data.target, IID_GarrisonHolder)) 744 { 745 this.FinishOrder(); 746 return; 747 } 720 748 // Check if we are already in range, otherwise walk there 721 if (!this.Check TargetRangeExplicit(msg.data.target, 0, 10))749 if (!this.CheckGarrisonRange(msg.data.target)) 722 750 { 723 if (!this. TargetIsAlive(msg.data.target) || !this.CheckTargetVisible(msg.data.target))724 // The target was destroyed751 if (!this.CheckTargetVisible(msg.data.target)) 752 { 725 753 this.FinishOrder(); 754 return; 755 } 726 756 else 757 { 727 758 // Out of range; move there in formation 728 this.PushOrderFront("WalkToTargetRange", { "target": msg.data.target, "min": 0, "max": 10 }); 729 return; 759 if (this.MoveToGarrisonRange(msg.data.target)) 760 { 761 this.SetNextState("GARRISON.APPROACHING"); 762 return; 763 } 764 } 730 765 } 731 766 732 var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); 733 // We don't want to rearrange the formation if the individual units are carrying 734 // out a task and one of the members dies/leaves the formation. 735 cmpFormation.SetRearrange(false); 736 cmpFormation.CallMemberFunction("Garrison", [msg.data.target, false]); 737 738 this.SetNextStateAlwaysEntering("MEMBER"); 767 this.SetNextState("GARRISON.GARRISONING"); 739 768 }, 740 769 741 770 "Order.Gather": function(msg) { … … 966 995 }, 967 996 }, 968 997 998 "GARRISON":{ 999 "enter": function() { 1000 // If the garrisonholder should pickup, warn it so it can take needed action 1001 var cmpGarrisonHolder = Engine.QueryInterface(this.order.data.target, IID_GarrisonHolder); 1002 if (cmpGarrisonHolder && cmpGarrisonHolder.ShouldPickup()) 1003 { 1004 this.pickup = this.order.data.target; // temporary, deleted in "leave" 1005 Engine.PostMessage(this.pickup, MT_PickupRequested, { "entity": this.entity }); 1006 } 1007 }, 1008 1009 "leave": function() { 1010 // If a pickup has been requested and not yet canceled, cancel it 1011 if (this.pickup) 1012 { 1013 Engine.PostMessage(this.pickup, MT_PickupCanceled, { "entity": this.entity }); 1014 delete this.pickup; 1015 } 1016 }, 1017 1018 1019 "APPROACHING": { 1020 "MoveStarted": function(msg) { 1021 var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); 1022 cmpFormation.SetRearrange(true); 1023 cmpFormation.MoveMembersIntoFormation(true, true); 1024 }, 1025 1026 "MoveCompleted": function(msg) { 1027 this.SetNextState("GARRISONING"); 1028 }, 1029 }, 1030 1031 "GARRISONING": { 1032 "enter": function() { 1033 // If a pickup has been requested, cancel it as it will be requested by members 1034 if (this.pickup) 1035 { 1036 Engine.PostMessage(this.pickup, MT_PickupCanceled, { "entity": this.entity }); 1037 delete this.pickup; 1038 } 1039 var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); 1040 // We don't want to rearrange the formation if the individual units are carrying 1041 // out a task and one of the members dies/leaves the formation. 1042 cmpFormation.SetRearrange(false); 1043 cmpFormation.CallMemberFunction("Garrison", [this.order.data.target, false]); 1044 this.SetNextStateAlwaysEntering("MEMBER"); 1045 }, 1046 }, 1047 }, 1048 969 1049 "FORMING": { 970 1050 "MoveStarted": function(msg) { 971 1051 var cmpFormation = Engine.QueryInterface(this.entity, IID_Formation); … … 2186 2266 }, 2187 2267 2188 2268 "GARRISON": { 2269 "enter": function() { 2270 // If the garrisonholder should pickup, warn it so it can take needed action 2271 var cmpGarrisonHolder = Engine.QueryInterface(this.order.data.target, IID_GarrisonHolder); 2272 if (cmpGarrisonHolder && cmpGarrisonHolder.ShouldPickup()) 2273 { 2274 this.pickup = this.order.data.target; // temporary, deleted in "leave" 2275 Engine.PostMessage(this.pickup, MT_PickupRequested, { "entity": this.entity }); 2276 } 2277 }, 2278 2279 "leave": function() { 2280 // If a pickup has been requested and not yet canceled, cancel it 2281 if (this.pickup) 2282 { 2283 Engine.PostMessage(this.pickup, MT_PickupCanceled, { "entity": this.entity }); 2284 delete this.pickup; 2285 } 2286 2287 if (this.stationary) 2288 delete this.stationary; 2289 }, 2290 2189 2291 "APPROACHING": { 2190 2292 "enter": function() { 2191 2293 this.SelectAnimation("move"); … … 2194 2296 "MoveCompleted": function() { 2195 2297 this.SetNextState("GARRISONED"); 2196 2298 }, 2197 2198 "leave": function() {2199 this.StopTimer();2200 }2201 2299 }, 2202 2300 2203 2301 "GARRISONED": { … … 2229 2327 this.SetGathererAnimationOverride(); 2230 2328 } 2231 2329 } 2330 2331 // If a pickup has been requested, remove it 2332 if (this.pickup) 2333 { 2334 Engine.PostMessage(this.pickup, MT_PickupCanceled, { "entity": this.entity }); 2335 delete this.pickup; 2336 } 2232 2337 2233 2338 return false; 2234 2339 } 2235 2340 } 2236 2341 else 2237 2342 { 2238 // Unable to reach the target, try again2239 // (or follow if it's a moving target) 2240 if (this. MoveToTarget(target))2343 // Unable to reach the target, we try again or follow it if it's a moving target 2344 2345 if (this.stationary && this.stationary.n > 10) 2241 2346 { 2242 this.SetNextState("APPROACHING"); 2243 return false; 2347 // If we've been stationary in the last trials, we delay the following trials 2348 // and eventually stop trying (more trials if target can pickup and not full to leave it time to come)) 2349 if (!cmpGarrisonHolder.ShouldPickup() || cmpGarrisonHolder.IsFull() || this.stationary.n > 100) 2350 { 2351 this.FinishOrder(); 2352 return true; 2353 } 2244 2354 } 2355 2356 var pos = Engine.QueryInterface(this.entity, IID_Position).GetPosition(); 2357 if (!this.stationary || Math.abs(this.stationary.x-pos.x) > 0.00001 || Math.abs(this.stationary.z-pos.z) > 0.00001) 2358 this.stationary = { "x": pos.x, "z": pos.z, "n": 0}; 2359 else 2360 this.stationary.n += 1; 2361 2362 if (this.stationary.n < 5) 2363 this.StartTimer(0); 2364 else if (this.stationary.n < 10) 2365 this.StartTimer(200); 2366 else 2367 this.StartTimer(1000); 2368 2369 return false; 2245 2370 } 2246 2371 } 2247 2372 // Garrisoning failed for some reason, so finish the order 2248 2373 this.FinishOrder(); 2249 2374 return true; 2250 2375 }, 2376 2377 "Timer": function(msg) { 2378 if (this.MoveToGarrisonRange(this.order.data.target)) 2379 { 2380 // If the target should pickup, warn it again from time to time (in case its orders were changed) 2381 if (this.pickup && this.stationary.n%5 == 0) 2382 Engine.PostMessage(this.pickup, MT_PickupRequested, { "entity": this.entity }); 2383 this.SetNextState("APPROACHING"); 2384 } 2385 else 2386 { 2387 this.FinishOrder(); 2388 } 2389 }, 2251 2390 2252 2391 "Order.Ungarrison": function() { 2253 2392 if (this.FinishOrder()) … … 2256 2395 2257 2396 "leave": function() { 2258 2397 this.isGarrisoned = false; 2259 } 2398 }, 2260 2399 }, 2261 2400 }, 2262 2401 … … 2316 2455 // Ignore attacks while unpacking 2317 2456 }, 2318 2457 }, 2458 2459 "PICKUP": { 2460 "APPROACHING": { 2461 "enter": function() { 2462 this.SelectAnimation("move"); 2463 }, 2464 2465 "MoveCompleted": function() { 2466 this.SetNextState("LOADING"); 2467 }, 2468 2469 "PickupCanceled": function() { 2470 this.StopMoving(); 2471 this.FinishOrder(); 2472 }, 2473 }, 2474 2475 "LOADING": { 2476 "enter": function() { 2477 this.SelectAnimation("idle"); 2478 var cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder); 2479 if (!cmpGarrisonHolder || cmpGarrisonHolder.IsFull()) 2480 { 2481 this.FinishOrder(); 2482 return true; 2483 } 2484 return false; 2485 }, 2486 2487 "PickupCanceled": function() { 2488 this.FinishOrder(); 2489 }, 2490 }, 2491 }, 2319 2492 }, 2320 2493 2321 2494 "ANIMAL": { … … 2585 2758 this.SetupRangeQueries(); 2586 2759 }; 2587 2760 2761 UnitAI.prototype.OnPickupRequested = function(msg) 2762 { 2763 var cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder); 2764 if (cmpGarrisonHolder && !cmpGarrisonHolder.IsFull()) 2765 { 2766 // First check if we already have such a requirement 2767 for each (var order in this.orderQueue) 2768 { 2769 if (order.type == "PickupUnit" && order.data.target == msg.entity) 2770 return; 2771 } 2772 // Insert the PickUp order after the last forced order 2773 this.PushOrderAfterForced("PickupUnit", { "target": msg.entity }); 2774 } 2775 }; 2776 2777 UnitAI.prototype.OnPickupCanceled = function(msg) 2778 { 2779 var cmpUnitAI = Engine.QueryInterface(msg.entity, IID_UnitAI); 2780 for (var i = 0; i < this.orderQueue.length; ++i) 2781 { 2782 if (this.orderQueue[i].type == "PickupUnit" && this.orderQueue[i].data.target == msg.entity) 2783 { 2784 if (i == 0) 2785 UnitFsm.ProcessMessage(this, {"type": "PickupCanceled", "data": msg}); 2786 else 2787 this.orderQueue.splice(i, 1); 2788 break; 2789 } 2790 } 2791 }; 2792 2588 2793 // Wrapper function that sets up the normal, healer, and Gaia range queries. 2589 2794 UnitAI.prototype.SetupRangeQueries = function() 2590 2795 { … … 2850 3055 } 2851 3056 }; 2852 3057 3058 /** 3059 * Insert an order after the last forced order onto the queue 3060 * and after the other orders of the same type 3061 */ 3062 UnitAI.prototype.PushOrderAfterForced = function(type, data) 3063 { 3064 if (!this.order || ((!this.order.data || !this.order.data.force) && this.order.type != type)) 3065 { 3066 this.PushOrderFront(type, data); 3067 } 3068 else 3069 { 3070 for (var i = 1; i < this.orderQueue.length; ++i) 3071 { 3072 if (this.orderQueue[i].data && this.orderQueue[i].data.force) 3073 continue; 3074 if (this.orderQueue[i].type == type) 3075 continue; 3076 this.orderQueue.splice(i, 0, {"type": type, "data": data}); 3077 return; 3078 } 3079 this.PushOrder(type, data); 3080 } 3081 }; 3082 2853 3083 UnitAI.prototype.ReplaceOrder = function(type, data) 2854 3084 { 2855 3085 // Special cases of orders that shouldn't be replaced: … … 3288 3518 return cmpUnitMotion.MoveToTargetRange(target, min, max); 3289 3519 }; 3290 3520 3521 UnitAI.prototype.MoveToGarrisonRange = function(target) 3522 { 3523 if (!this.CheckTargetVisible(target)) 3524 return false; 3525 3526 var cmpGarrisonHolder = Engine.QueryInterface(target, IID_GarrisonHolder); 3527 if (!cmpGarrisonHolder) 3528 return false; 3529 var range = cmpGarrisonHolder.GetLoadingRange(); 3530 3531 var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); 3532 return cmpUnitMotion.MoveToTargetRange(target, range.min, range.max); 3533 }; 3534 3291 3535 UnitAI.prototype.CheckPointRangeExplicit = function(x, z, min, max) 3292 3536 { 3293 3537 var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); … … 3312 3556 UnitAI.prototype.CheckGarrisonRange = function(target) 3313 3557 { 3314 3558 var cmpGarrisonHolder = Engine.QueryInterface(target, IID_GarrisonHolder); 3559 if (!cmpGarrisonHolder) 3560 return false; 3315 3561 var range = cmpGarrisonHolder.GetLoadingRange(); 3316 3562 3317 3563 var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); -
binaries/data/mods/public/simulation/components/interfaces/UnitAI.js
11 11 // Message of the form { "to": orderData }. 12 12 // sent whenever the unit changes state 13 13 Engine.RegisterMessageType("UnitAIOrderDataChanged"); 14 15 // Message of the form { "entity": entity }, 16 // sent whenever a pickup is requested 17 Engine.RegisterMessageType("PickupRequested"); 18 19 // Message of the form { "entity": entity }, 20 // sent whenever a pickup is no more needed 21 Engine.RegisterMessageType("PickupCanceled"); -
binaries/data/mods/public/simulation/components/GarrisonHolder.js
18 18 "</element>" + 19 19 "<element name='LoadingRange' a:help='The maximum distance from this holder at which entities are allowed to garrison. Should be about 2.0 for land entities and preferably greater for ships'>" + 20 20 "<ref name='nonNegativeDecimal'/>" + 21 "</element>"; 21 "</element>" + 22 "<optional>" + 23 "<element name='Pickup' a:help='This garrisonHolder will move to pick up units to be garrisoned'>" + 24 "<data type='boolean'/>" + 25 "</element>" + 26 "</optional>"; 22 27 23 28 /** 24 29 * Initialize GarrisonHolder Component … … 41 46 }; 42 47 43 48 /** 49 * Return true if this garrisonHolder should pickup units 50 */ 51 GarrisonHolder.prototype.ShouldPickup = function() 52 { 53 return (this.template.Pickup || false); 54 }; 55 56 57 /** 44 58 * Return the list of entities garrisoned inside 45 59 */ 46 60 GarrisonHolder.prototype.GetEntities = function() … … 67 81 }; 68 82 69 83 /** 84 * Return true if this garrisonHolder is full 85 */ 86 GarrisonHolder.prototype.IsFull = function() 87 { 88 return this.entities.length >= this.GetCapacity(); 89 }; 90 91 /** 70 92 * Get the heal rate with which garrisoned units will be healed 71 93 */ 72 94 GarrisonHolder.prototype.GetHealRate = function() -
binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_fishing.xml
25 25 <List datatype="tokens">Support Infantry</List> 26 26 <BuffHeal>1</BuffHeal> 27 27 <LoadingRange>10</LoadingRange> 28 <Pickup>true</Pickup> 28 29 </GarrisonHolder> 29 30 <Identity> 30 31 <GenericName>Fishing Boat</GenericName> … … 42 43 <treasure disable=""/> 43 44 </Rates> 44 45 </ResourceGatherer> 45 <Sound>46 <SoundGroups>47 <order_walk>actor/ship/boat_move.xml</order_walk>48 <order_attack>actor/ship/boat_move.xml</order_attack>49 </SoundGroups>50 </Sound>51 46 <UnitMotion> 52 47 <WalkSpeed>8.5</WalkSpeed> 53 48 </UnitMotion> -
binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_bireme.xml
35 35 <List datatype="tokens">Support Infantry Cavalry</List> 36 36 <BuffHeal>1</BuffHeal> 37 37 <LoadingRange>10</LoadingRange> 38 <Pickup>true</Pickup> 38 39 </GarrisonHolder> 39 40 <Health> 40 41 <Max>800</Max> -
binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_quinquereme.xml
31 31 <List datatype="tokens">Support Infantry Cavalry Siege</List> 32 32 <BuffHeal>1</BuffHeal> 33 33 <LoadingRange>10</LoadingRange> 34 <Pickup>true</Pickup> 34 35 </GarrisonHolder> 35 36 <Health> 36 37 <Max>2000</Max> -
binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_merchant.xml
17 17 <List datatype="tokens">Support Infantry Cavalry</List> 18 18 <BuffHeal>1</BuffHeal> 19 19 <LoadingRange>10</LoadingRange> 20 <Pickup>true</Pickup> 20 21 </GarrisonHolder> 21 22 <Health> 22 23 <Max>400</Max> -
binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_trireme.xml
35 35 <List datatype="tokens">Support Infantry Cavalry Siege</List> 36 36 <BuffHeal>1</BuffHeal> 37 37 <LoadingRange>10</LoadingRange> 38 <Pickup>true</Pickup> 38 39 </GarrisonHolder> 39 40 <Health> 40 41 <Max>1400</Max>