- Timestamp:
- 06/24/11 14:35:15 (14 years ago)
- Location:
- ps/trunk
- Files:
-
- 7 edited
-
binaries/data/mods/public/gui/session/unit_commands.js (modified) (2 diffs)
-
binaries/data/mods/public/simulation/components/GuiInterface.js (modified) (2 diffs)
-
binaries/data/mods/public/simulation/components/UnitAI.js (modified) (29 diffs)
-
source/simulation2/components/CCmpRangeManager.cpp (modified) (1 diff)
-
source/simulation2/components/CCmpUnitMotion.cpp (modified) (2 diffs)
-
source/simulation2/components/ICmpRangeManager.cpp (modified) (1 diff)
-
source/simulation2/components/ICmpRangeManager.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
ps/trunk/binaries/data/mods/public/gui/session/unit_commands.js
r9645 r9657 275 275 else if (guiName == "Stance") 276 276 { 277 var stanceSelected = Engine.GuiInterfaceCall(" StanceSelected", {277 var stanceSelected = Engine.GuiInterfaceCall("IsStanceSelected", { 278 278 "ents": g_Selection.toList(), 279 279 "stance": item … … 386 386 var formations = getEntityFormationsList(entState); 387 387 if (isUnit(entState) && !isAnimal(entState) && !entState.garrisonHolder && formations.length) 388 { 388 389 setupUnitPanel("Formation", usedPanels, entState, formations, 389 390 function (item) { performFormation(entState.id, item); } ); 390 391 var stances = ["violent","aggressive","passive","defensive","stand"]; 391 } 392 393 // TODO: probably should load the stance list from a data file, 394 // and/or vary depending on what units are selected 395 var stances = ["violent", "aggressive", "passive", "defensive", "stand"]; 392 396 if (isUnit(entState) && !isAnimal(entState) && !entState.garrisonHolder && stances.length) 397 { 393 398 setupUnitPanel("Stance", usedPanels, entState, stances, 394 399 function (item) { performStance(entState.id, item); } ); 400 } 395 401 396 402 if (entState.buildEntities && entState.buildEntities.length) -
ps/trunk/binaries/data/mods/public/simulation/components/GuiInterface.js
r9631 r9657 299 299 }; 300 300 301 GuiInterface.prototype. StanceSelected = function(player, data)301 GuiInterface.prototype.IsStanceSelected = function(player, data) 302 302 { 303 303 for each (var ent in data.ents) … … 568 568 569 569 "CanMoveEntsIntoFormation": 1, 570 " StanceSelected": 1,570 "IsStanceSelected": 1, 571 571 572 572 "SetSelectionHighlight": 1, -
ps/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
r9632 r9657 6 6 "<element name='DefaultStance'>" + 7 7 "<choice>" + 8 "<value>violent</value>" + 8 9 "<value>aggressive</value>" + 9 10 "<value>defensive</value>" + 10 11 "<value>passive</value>" + 12 "<value>stand</value>" + 11 13 "</choice>" + 12 14 "</element>" + … … 46 48 "</optional>"; 47 49 48 // Very basic stance support (currently just for test maps where we don't want 49 // everyone killing each other immediately after loading, and for female citizens) 50 // Unit stances. 50 51 // There some targeting options: 51 52 // targetVisibleEnemies: anything in vision range is a viable target … … 54 55 // respondFlee: run away 55 56 // respondChase: start chasing after the enemy 56 // TODO: maybe add respondStandGround, respondHoldGround (allow chasing a short distance then return), 57 // targetAggressiveEnemies (don't worry about lone scouts, do worry around armies slaughtering 58 // the guy standing next to you), etc. 59 // TODO: even this limited version isn't implemented properly yet (e.g. it can't handle 60 // dynamic stance changes). 57 // respondChaseBeyondVision: start chasing, and don't stop even if it's out 58 // of this unit's vision range (though still visible to the player) 59 // respondStandGround: attack enemy but don't move at all 60 // respondHoldGround: attack enemy but don't move far from current position 61 // TODO: maybe add targetAggressiveEnemies (don't worry about lone scouts, 62 // do worry around armies slaughtering the guy standing next to you), etc. 61 63 var g_Stances = { 62 64 "violent": { … … 65 67 respondFlee: false, 66 68 respondChase: true, 67 respond StandGround : false,68 respond HoldGround: false,69 respond ChaseToHell : true,69 respondChaseBeyondVision: true, 70 respondStandGround: false, 71 respondHoldGround: false, 70 72 }, 71 73 "aggressive": { … … 74 76 respondFlee: false, 75 77 respondChase: true, 76 respondStandGround : false, 77 respondHoldGround : false, 78 respondChaseBeyondVision: false, 79 respondStandGround: false, 80 respondHoldGround: false, 78 81 }, 79 82 "defensive": { … … 82 85 respondFlee: false, 83 86 respondChase: false, 84 respondStandGround : false, 85 respondHoldGround : true, 87 respondChaseBeyondVision: false, 88 respondStandGround: false, 89 respondHoldGround: true, 86 90 }, 87 91 "passive": { … … 90 94 respondFlee: true, 91 95 respondChase: false, 92 respondStandGround : false, 93 respondHoldGround : false, 96 respondChaseBeyondVision: false, 97 respondStandGround: false, 98 respondHoldGround: false, 94 99 }, 95 100 "stand": { … … 98 103 respondFlee: false, 99 104 respondChase: false, 100 respondStandGround : true, 101 respondHoldGround : false, 105 respondChaseBeyondVision: false, 106 respondStandGround: true, 107 respondHoldGround: false, 102 108 }, 103 109 }; … … 136 142 "EntityRenamed": function(msg) { 137 143 // ignore 138 },139 140 "StanceChanged": function(msg) {141 if (this.StanceSpecificQuery(this.stance,true))142 return;143 144 }, 144 145 … … 247 248 this.attackType = type; 248 249 250 // If we are already at the target, try attacking it from here 249 251 if (this.CheckTargetRange(this.order.data.target, IID_Attack, this.attackType)) 250 252 { 251 // We are already at the target252 // so try attacking it from here.253 253 this.StopMoving(); 254 254 if (this.IsAnimal()) … … 256 256 else 257 257 this.SetNextState("INDIVIDUAL.COMBAT.ATTACKING"); 258 } 258 return; 259 } 260 261 // If we can't reach the target, but are standing ground, 262 // then abandon this attack order 263 if (this.GetStance().respondStandGround && !this.order.data.force) 264 { 265 this.FinishOrder(); 266 return; 267 } 268 259 269 // Try to move within attack range 260 else if ((!this.GetStance().respondStandGround || this.order.data.force) &&this.MoveToTargetRange(this.order.data.target, IID_Attack, this.attackType))270 if (this.MoveToTargetRange(this.order.data.target, IID_Attack, this.attackType)) 261 271 { 262 272 // We've started walking to the given point … … 265 275 else 266 276 this.SetNextState("INDIVIDUAL.COMBAT.APPROACHING"); 267 } 268 else 269 this.FinishOrder(); 277 return; 278 } 279 280 // We can't reach the target, and can't move towards it, 281 // so abandon this attack order 282 this.FinishOrder(); 270 283 }, 271 284 … … 515 528 // so immediately check whether there's anybody nearby to attack. 516 529 // (If anyone approaches later, it'll be handled via LosRangeUpdate.) 517 if (this. StanceSpecificQuery(this.stance))518 return true; 530 if (this.FindNewTargets()) 531 return true; // (abort the FSM transition since we may have already switched state) 519 532 520 533 // Nobody to attack - stay in idle … … 573 586 } 574 587 }, 575 576 "StanceChanged": function(msg) {577 if (this.StanceSpecificQuery(this.stance))578 return;579 },580 588 }, 581 589 … … 635 643 636 644 "Timer": function(msg) { 637 if ( !this.ChaseTargetedEntity(this.order.data.target, this.order.data.force))645 if (this.ShouldAbandonChase(this.order.data.target, this.order.data.force)) 638 646 { 639 647 this.StopMoving(); 640 648 this.FinishOrder(); 641 649 642 // we return to ourposition650 // Return to our original position 643 651 if (this.GetStance().respondHoldGround) 644 652 this.WalkToHeldPosition(); … … 692 700 } 693 701 694 if (this.ChaseTargetedEntity(this.order.data.target)) 702 // Can't reach it - try to chase after it 703 if (this.ShouldChaseTargetedEntity(this.order.data.target, this.order.data.force)) 695 704 { 696 705 if (this.MoveToTargetRange(this.order.data.target, IID_Attack, this.attackType)) … … 707 716 return; 708 717 709 // see if we can switch to a new nearby enemy710 if (this. StanceSpecificQuery(this.stance, true))718 // See if we can switch to a new nearby enemy 719 if (this.FindNewTargets()) 711 720 return; 712 721 713 // we return to ourposition722 // Return to our original position 714 723 if (this.GetStance().respondHoldGround) 715 { 716 if (this.WalkToHeldPosition()) 717 return; 718 } 724 this.WalkToHeldPosition(); 719 725 }, 720 726 … … 734 740 735 741 "Timer": function(msg) { 736 if ( !this.ChaseTargetedEntity(this.order.data.target))742 if (this.ShouldAbandonChase(this.order.data.target, this.order.data.force)) 737 743 { 738 744 this.StopMoving(); 739 745 this.FinishOrder(); 740 746 741 // we return to ourposition747 // Return to our original position 742 748 if (this.GetStance().respondHoldGround) 743 749 this.WalkToHeldPosition(); … … 1366 1372 UnitAI.prototype.OnOwnershipChanged = function(msg) 1367 1373 { 1368 this.SetupRangeQuery( msg.to);1374 this.SetupRangeQuery(); 1369 1375 }; 1370 1376 … … 1383 1389 // which can be attacked. 1384 1390 // This should be called whenever our ownership changes. 1385 UnitAI.prototype.SetupRangeQuery = function(owner) 1386 { 1391 UnitAI.prototype.SetupRangeQuery = function() 1392 { 1393 var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); 1394 var owner = cmpOwnership.GetOwner(); 1395 1387 1396 var rangeMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 1388 1397 var playerMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager); … … 1411 1420 } 1412 1421 1413 var range = this. StanceSpecificRange();1414 1415 this.losRangeQuery = rangeMan.CreateActiveQuery(this.entity, 0, range.max, players, IID_DamageReceiver);1422 var range = this.GetQueryRange(); 1423 1424 this.losRangeQuery = rangeMan.CreateActiveQuery(this.entity, range.min, range.max, players, IID_DamageReceiver); 1416 1425 rangeMan.EnableActiveQuery(this.losRangeQuery); 1417 } 1426 }; 1418 1427 1419 1428 //// FSM linkage functions //// … … 1862 1871 UnitAI.prototype.MoveToTarget = function(target) 1863 1872 { 1873 if (!this.CheckTargetVisible(target)) 1874 return false; 1875 1864 1876 var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); 1865 1877 return cmpUnitMotion.MoveToTargetRange(target, 0, 0); … … 1868 1880 UnitAI.prototype.MoveToTargetRange = function(target, iid, type) 1869 1881 { 1882 if (!this.CheckTargetVisible(target)) 1883 return false; 1884 1870 1885 var cmpRanged = Engine.QueryInterface(this.entity, iid); 1871 1886 var range = cmpRanged.GetRange(type); … … 1877 1892 UnitAI.prototype.MoveToTargetRangeExplicit = function(target, min, max) 1878 1893 { 1894 if (!this.CheckTargetVisible(target)) 1895 return false; 1896 1879 1897 var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); 1880 1898 return cmpUnitMotion.MoveToTargetRange(target, min, max); … … 1888 1906 var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); 1889 1907 return cmpUnitMotion.IsInTargetRange(target, range.min, range.max); 1908 }; 1909 1910 /** 1911 * Returns true if the target entity is visible through the FoW/SoD. 1912 */ 1913 UnitAI.prototype.CheckTargetVisible = function(target) 1914 { 1915 var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); 1916 if (!cmpOwnership) 1917 return false; 1918 1919 var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 1920 if (!cmpRangeManager) 1921 return false; 1922 1923 if (cmpRangeManager.GetLosVisibility(target, cmpOwnership.GetOwner()) == "hidden") 1924 return false; 1925 1926 // Either visible directly, or visible in fog 1927 return true; 1890 1928 }; 1891 1929 … … 1943 1981 1944 1982 return distance < range; 1945 } 1983 }; 1946 1984 1947 1985 UnitAI.prototype.GetBestAttack = function() … … 1972 2010 1973 2011 /** 1974 * Try to find one of the given entities which can be attacked ,1975 * within zone.2012 * Try to find one of the given entities which can be attacked 2013 * and which is close to the hold position, and start attacking it. 1976 2014 * Returns true if it found something to attack. 1977 2015 */ … … 2018 2056 }; 2019 2057 2058 /** 2059 * Returns true if we should stop following the target entity. 2060 */ 2061 UnitAI.prototype.ShouldAbandonChase = function(target, force) 2062 { 2063 // Stop if we're in hold-ground mode and it's too far from the holding point 2064 if (this.GetStance().respondHoldGround) 2065 { 2066 if (!this.CheckTargetDistanceFromHeldPosition(target, this.attackType)) 2067 return true; 2068 } 2069 2070 // Stop if it's left our vision range, unless we're especially persistent 2071 if (!force && !this.GetStance().respondChaseBeyondVision) 2072 { 2073 if (!this.CheckTargetIsInVisionRange(target)) 2074 return true; 2075 } 2076 2077 // (Note that CCmpUnitMotion will detect if the target is lost in FoW, 2078 // and will continue moving to its last seen position and then stop) 2079 2080 return false; 2081 }; 2082 2020 2083 /* 2021 * Try to chase targeted entity given our current stance 2084 * Returns whether we should chase the targeted entity, 2085 * given our current stance. 2022 2086 */ 2023 UnitAI.prototype.ChaseTargetedEntity = function(ent, force) 2024 { 2025 if (this.GetStance().respondChase) 2026 { 2027 if (this.CheckTargetIsInVisionRange(ent)) 2028 { 2029 return true; 2030 } 2031 } 2032 2033 if (this.GetStance().respondChaseToHell || force) 2034 { 2035 //if ( TODO : Check ent is not in Shroud of Darkness) 2036 { 2037 return true; 2038 } 2039 } 2040 2041 if (this.GetStance().respondHoldGround) 2042 { 2043 if (this.CheckTargetDistanceFromHeldPosition(ent, this.attackType)) 2044 { 2045 return true; 2046 } 2047 } 2048 2049 return false; 2050 2051 } 2087 UnitAI.prototype.ShouldChaseTargetedEntity = function(target, force) 2088 { 2089 if (this.GetStance().respondChase) 2090 return true; 2091 2092 if (force) 2093 return true; 2094 2095 return false; 2096 }; 2052 2097 2053 2098 //// External interface functions //// … … 2290 2335 this.StopMoving(); 2291 2336 2292 UnitFsm.ProcessMessage(this, {"type": "StanceChanged", "stance": stance}); 2337 // Reset the range query, since the range depends on stance 2338 this.SetupRangeQuery(); 2293 2339 } 2294 2340 2295 UnitAI.prototype.StanceSpecificQuery = function(stance, disable) 2296 { 2297 if (!g_Stances[stance]) 2298 { 2299 error("UnitAI: Setting to invalid stance '"+stance+"'"); 2300 return false; 2301 } 2302 2341 /** 2342 * Resets losRangeQuery, and if there are some targets in range that we can 2343 * attack then we start attacking and this returns true; otherwise, returns false. 2344 */ 2345 UnitAI.prototype.FindNewTargets = function() 2346 { 2303 2347 if (!this.losRangeQuery) 2304 2348 return false; 2305 2349 2306 var range = this.StanceSpecificRange();2307 2308 2350 var rangeMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); 2309 var ents = rangeMan. ModifyRangeActiveQuery(this.losRangeQuery, range.min, range.max);2310 2311 if ( disable && !this.IsAnimal())2312 r angeMan.DisableActiveQuery(this.losRangeQuery);2351 var ents = rangeMan.ResetActiveQuery(this.losRangeQuery); 2352 2353 if (!this.GetStance().targetVisibleEnemies) 2354 return false; 2313 2355 2314 2356 return this.RespondToTargetedEntities(ents); 2315 2357 }; 2316 2358 2317 UnitAI.prototype. StanceSpecificRange = function()2359 UnitAI.prototype.GetQueryRange = function() 2318 2360 { 2319 2361 var ret = { "min": 0, "max": 0 }; -
ps/trunk/source/simulation2/components/CCmpRangeManager.cpp
r9631 r9657 458 458 459 459 return (tag_t)id; 460 }461 462 virtual std::vector<entity_id_t> ModifyRangeActiveQuery(tag_t tag,463 entity_pos_t minRange, entity_pos_t maxRange)464 {465 std::map<tag_t, Query>::iterator it = m_Queries.find(tag);466 if (it == m_Queries.end())467 {468 LOGERROR(L"CCmpRangeManager: ModifyRangeActiveQuery called with invalid tag %d", tag);469 std::vector<entity_id_t> r;470 return r;471 }472 473 Query& q = it->second;474 q.minRange = minRange;475 q.maxRange = maxRange;476 return ResetActiveQuery(tag);477 460 } 478 461 -
ps/trunk/source/simulation2/components/CCmpUnitMotion.cpp
r9605 r9657 23 23 #include "ICmpObstruction.h" 24 24 #include "ICmpObstructionManager.h" 25 #include "ICmpOwnership.h" 25 26 #include "ICmpPosition.h" 26 27 #include "ICmpPathfinder.h" 28 #include "ICmpRangeManager.h" 27 29 #include "simulation2/MessageTypes.h" 28 30 #include "simulation2/helpers/Geometry.h" … … 1004 1006 return false; 1005 1007 1008 // Fail if the target is no longer visible to this entity's owner 1009 // (in which case we'll continue moving to its last known location, 1010 // unless it comes back into view before we reach that location) 1011 CmpPtr<ICmpOwnership> cmpOwnership(GetSimContext(), GetEntityId()); 1012 if (!cmpOwnership.null()) 1013 { 1014 CmpPtr<ICmpRangeManager> cmpRangeManager(GetSimContext(), SYSTEM_ENTITY); 1015 if (!cmpRangeManager.null()) 1016 { 1017 if (cmpRangeManager->GetLosVisibility(m_TargetEntity, cmpOwnership->GetOwner()) == ICmpRangeManager::VIS_HIDDEN) 1018 return false; 1019 } 1020 } 1021 1006 1022 // The target moved and we need to update our current path; 1007 1023 // change the goal here and expect our caller to start the path request -
ps/trunk/source/simulation2/components/ICmpRangeManager.cpp
r9631 r9657 37 37 DEFINE_INTERFACE_METHOD_5("ExecuteQuery", std::vector<entity_id_t>, ICmpRangeManager, ExecuteQuery, entity_id_t, entity_pos_t, entity_pos_t, std::vector<int>, int) 38 38 DEFINE_INTERFACE_METHOD_5("CreateActiveQuery", ICmpRangeManager::tag_t, ICmpRangeManager, CreateActiveQuery, entity_id_t, entity_pos_t, entity_pos_t, std::vector<int>, int) 39 DEFINE_INTERFACE_METHOD_3("ModifyRangeActiveQuery", std::vector<entity_id_t>, ICmpRangeManager, ModifyRangeActiveQuery, ICmpRangeManager::tag_t, entity_pos_t, entity_pos_t)40 39 DEFINE_INTERFACE_METHOD_1("DestroyActiveQuery", void, ICmpRangeManager, DestroyActiveQuery, ICmpRangeManager::tag_t) 41 40 DEFINE_INTERFACE_METHOD_1("EnableActiveQuery", void, ICmpRangeManager, EnableActiveQuery, ICmpRangeManager::tag_t) -
ps/trunk/source/simulation2/components/ICmpRangeManager.h
r9631 r9657 103 103 104 104 /** 105 * Modify an active query's range parameters and execute a ResetActiveQuery.106 * @param tag identifier of query.107 * @param minRange non-negative minimum distance in metres (inclusive).108 * @param maxRange non-negative maximum distance in metres (inclusive); or -1.0 to ignore distance.109 * @return list of entities matching the query, ordered by increasing distance from the source entity.110 */111 virtual std::vector<entity_id_t> ModifyRangeActiveQuery(tag_t tag,112 entity_pos_t minRange, entity_pos_t maxRange) = 0;113 114 /**115 105 * Destroy a query and clean up resources. This must be called when an entity no longer needs its 116 106 * query (e.g. when the entity is destroyed).
Note:
See TracChangeset
for help on using the changeset viewer.
