Ticket #1537: chasing.2.diff
File chasing.2.diff, 15.6 KB (added by , 10 years ago) |
---|
-
binaries/data/mods/public/simulation/components/UnitAI.js
378 378 // We use the distance between the entities to account for ranged attacks 379 379 var distance = DistanceBetweenEntities(this.entity, this.order.data.target) + (+this.template.FleeDistance); 380 380 var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); 381 if (cmpUnitMotion.MoveToTargetRange(this.order.data.target, distance, -1 ))381 if (cmpUnitMotion.MoveToTargetRange(this.order.data.target, distance, -1, 0)) 382 382 { 383 383 // We've started fleeing from the given target 384 384 if (this.IsAnimal()) … … 485 485 } 486 486 487 487 // Try to move within attack range 488 if (this.MoveToTargetAttackRange(this.order.data.target, IID_Attack,this.order.data.attackType))488 if (this.MoveToTargetAttackRange(this.order.data.target, this.order.data.attackType)) 489 489 { 490 490 // We've started walking to the given point 491 491 if (this.IsAnimal()) … … 1587 1587 } 1588 1588 else 1589 1589 { 1590 if (this.MoveToTargetAttackRange(this.order.data.target, IID_Attack,this.order.data.attackType))1590 if (this.MoveToTargetAttackRange(this.order.data.target, this.order.data.attackType)) 1591 1591 { 1592 1592 this.SetNextState("APPROACHING"); 1593 1593 } … … 1614 1614 // If we're not in range yet (maybe we stopped moving), move to target again 1615 1615 if (!this.CheckTargetAttackRange(this.order.data.target, IID_Attack, this.order.data.attackType)) 1616 1616 { 1617 if (this.MoveToTargetAttackRange(this.order.data.target, IID_Attack,this.order.data.attackType))1617 if (this.MoveToTargetAttackRange(this.order.data.target, this.order.data.attackType)) 1618 1618 this.SetNextState("APPROACHING"); 1619 1619 else 1620 1620 { … … 1715 1715 // Can't reach it - try to chase after it 1716 1716 if (this.ShouldChaseTargetedEntity(target, this.order.data.force)) 1717 1717 { 1718 if (this.MoveToTarget Range(target, IID_Attack, this.order.data.attackType))1718 if (this.MoveToTargetAttackRange(target, this.order.data.attackType)) 1719 1719 { 1720 1720 this.SetNextState("COMBAT.CHASING"); 1721 1721 return; … … 3843 3843 return false; 3844 3844 3845 3845 var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); 3846 return cmpUnitMotion.MoveToTargetRange(target, 0, 0 );3846 return cmpUnitMotion.MoveToTargetRange(target, 0, 0, 0); 3847 3847 }; 3848 3848 3849 UnitAI.prototype.MoveToTargetRange = function(target, iid, type )3849 UnitAI.prototype.MoveToTargetRange = function(target, iid, type, time) 3850 3850 { 3851 3851 if (!this.CheckTargetVisible(target)) 3852 3852 return false; … … 3855 3855 if (!cmpRanged) 3856 3856 return false; 3857 3857 var range = cmpRanged.GetRange(type); 3858 if (!time) 3859 var time = 0; 3858 3860 3859 3861 var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); 3860 return cmpUnitMotion.MoveToTargetRange(target, range.min, range.max );3862 return cmpUnitMotion.MoveToTargetRange(target, range.min, range.max, time); 3861 3863 }; 3862 3864 3863 3865 /** … … 3865 3867 * for melee attacks, this goes straight to the default range checks 3866 3868 * for ranged attacks, the parabolic range is used 3867 3869 */ 3868 UnitAI.prototype.MoveToTargetAttackRange = function(target, iid,type)3870 UnitAI.prototype.MoveToTargetAttackRange = function(target, type) 3869 3871 { 3872 var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack); 3873 var timers = cmpAttack.GetTimers(type); 3874 var time = timers.prepare; 3870 3875 3871 3876 if(type!= "Ranged") 3872 return this.MoveToTargetRange(target, iid, type);3877 return this.MoveToTargetRange(target, IID_Attack, type, time); 3873 3878 3874 3879 if (!this.CheckTargetVisible(target)) 3875 3880 return false; 3876 3881 3877 var cmpRanged = Engine.QueryInterface(this.entity, iid); 3878 var range = cmpRanged.GetRange(type); 3882 var range = cmpAttack.GetRange(type); 3879 3883 3880 3884 var thisCmpPosition = Engine.QueryInterface(this.entity, IID_Position); 3881 3885 var s = thisCmpPosition.GetPosition(); … … 3900 3904 var guessedMaxRange = (range.max + parabolicMaxRange)/2; 3901 3905 3902 3906 var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); 3903 if (cmpUnitMotion.MoveToTargetRange(target, range.min, guessedMaxRange ))3907 if (cmpUnitMotion.MoveToTargetRange(target, range.min, guessedMaxRange, time)) 3904 3908 return true; 3905 3909 3906 3910 // if that failed, try closer 3907 return cmpUnitMotion.MoveToTargetRange(target, range.min, Math.min(range.max, parabolicMaxRange) );3911 return cmpUnitMotion.MoveToTargetRange(target, range.min, Math.min(range.max, parabolicMaxRange), time); 3908 3912 }; 3909 3913 3910 UnitAI.prototype.MoveToTargetRangeExplicit = function(target, min, max )3914 UnitAI.prototype.MoveToTargetRangeExplicit = function(target, min, max, time) 3911 3915 { 3912 3916 if (!this.CheckTargetVisible(target)) 3913 3917 return false; 3914 3918 3919 if (!time) 3920 var time = 0; 3921 3915 3922 var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); 3916 return cmpUnitMotion.MoveToTargetRange(target, min, max );3923 return cmpUnitMotion.MoveToTargetRange(target, min, max, time); 3917 3924 }; 3918 3925 3919 3926 UnitAI.prototype.MoveToGarrisonRange = function(target) … … 3927 3934 var range = cmpGarrisonHolder.GetLoadingRange(); 3928 3935 3929 3936 var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion); 3930 return cmpUnitMotion.MoveToTargetRange(target, range.min, range.max );3937 return cmpUnitMotion.MoveToTargetRange(target, range.min, range.max, 0); 3931 3938 }; 3932 3939 3933 3940 UnitAI.prototype.CheckPointRangeExplicit = function(x, z, min, max) -
source/simulation2/components/CCmpUnitMotion.cpp
132 132 bool m_FormationController; 133 133 fixed m_WalkSpeed, m_OriginalWalkSpeed; // in metres per second 134 134 fixed m_RunSpeed, m_OriginalRunSpeed; 135 fixed m_TimeToStayInRange, m_TurnLength; 135 136 ICmpPathfinder::pass_class_t m_PassClass; 136 137 ICmpPathfinder::cost_class_t m_CostClass; 137 138 … … 297 298 m_WalkSpeed = m_OriginalWalkSpeed = paramNode.GetChild("WalkSpeed").ToFixed(); 298 299 m_Speed = m_WalkSpeed; 299 300 m_CurSpeed = fixed::Zero(); 301 m_TimeToStayInRange = fixed::Zero(); 300 302 301 303 if (paramNode.GetChild("Run").IsOk()) 302 304 m_RunSpeed = m_OriginalRunSpeed = paramNode.GetChild("Run").GetChild("Speed").ToFixed(); … … 350 352 351 353 serialize.NumberFixed_Unbounded("speed", m_Speed); 352 354 355 serialize.NumberFixed_Unbounded("timeToStayInRange", m_TimeToStayInRange); 356 serialize.NumberFixed_Unbounded("turnLength", m_TurnLength); 357 353 358 serialize.Bool("moving", m_Moving); 354 359 serialize.Bool("facePointAfterMove", m_FacePointAfterMove); 355 360 … … 379 384 { 380 385 if (m_FormationController) 381 386 { 382 fixed dt= static_cast<const CMessageUpdate_MotionFormation&> (msg).turnLength;383 Move( dt);387 m_TurnLength = static_cast<const CMessageUpdate_MotionFormation&> (msg).turnLength; 388 Move(m_TurnLength); 384 389 } 385 390 break; 386 391 } … … 388 393 { 389 394 if (!m_FormationController) 390 395 { 391 fixed dt = static_cast<const CMessageUpdate_MotionUnit&> (msg).turnLength;392 Move( dt);396 m_TurnLength = static_cast<const CMessageUpdate_MotionFormation&> (msg).turnLength; 397 Move(m_TurnLength); 393 398 } 394 399 break; 395 400 } … … 470 475 471 476 virtual bool MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange); 472 477 virtual bool IsInPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange); 473 virtual bool MoveToTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange );478 virtual bool MoveToTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange, entity_pos_t timeToStayInRange); 474 479 virtual bool IsInTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange); 475 480 virtual void MoveToFormationOffset(entity_id_t target, entity_pos_t x, entity_pos_t z); 476 481 … … 548 553 GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg); 549 554 } 550 555 551 bool MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange, entity_id_t target );556 bool MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange, entity_id_t target, entity_pos_t timeToStayInRange); 552 557 553 558 /** 554 559 * Handle the result of an asynchronous path query. … … 995 1000 } 996 1001 else 997 1002 { 1003 // check if target was reached in case of a moving target 1004 CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), m_TargetEntity); 1005 if 1006 ( 1007 cmpUnitMotion && 1008 cmpUnitMotion->IsMoving() && 1009 MoveToTargetRange(m_TargetEntity, m_TargetMinRange, m_TargetMaxRange, m_TimeToStayInRange) 1010 ) 1011 return; 1012 998 1013 // Not in formation, so just finish moving 999 1000 1014 StopMoving(); 1001 1015 1002 1003 1016 if (m_FacePointAfterMove) 1004 1017 FaceTowardsPointFromPos(pos, m_FinalGoal.x, m_FinalGoal.z); 1005 1018 // TODO: if the goal was a square building, we ought to point towards the … … 1300 1313 1301 1314 bool CCmpUnitMotion::MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange) 1302 1315 { 1303 return MoveToPointRange(x, z, minRange, maxRange, INVALID_ENTITY );1316 return MoveToPointRange(x, z, minRange, maxRange, INVALID_ENTITY, fixed::Zero()); 1304 1317 } 1305 1318 1306 bool CCmpUnitMotion::MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange, entity_id_t target )1319 bool CCmpUnitMotion::MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange, entity_id_t target, entity_pos_t timeToStayInRange) 1307 1320 { 1308 1321 PROFILE("MoveToPointRange"); 1309 1322 … … 1313 1326 1314 1327 CFixedVector2D pos = cmpPosition->GetPosition2D(); 1315 1328 1329 entity_pos_t overShoot = fixed::Zero(); 1330 entity_pos_t margin = fixed::Zero(); 1331 // if the target is also moving, take an overshoot into account 1332 CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), target); 1333 if (cmpUnitMotion) 1334 { 1335 margin = cmpUnitMotion->GetCurrentSpeed().Multiply(m_TurnLength); 1336 if (timeToStayInRange > m_TurnLength) 1337 overShoot = cmpUnitMotion->GetCurrentSpeed().Multiply(timeToStayInRange - m_TurnLength); 1338 } 1339 1340 entity_pos_t origMaxRange = maxRange + margin; 1341 entity_pos_t origMinRange = minRange; 1342 maxRange -= overShoot; 1343 minRange += overShoot; 1344 if (maxRange <= origMinRange && origMaxRange >= origMinRange) 1345 maxRange = origMinRange; 1346 if (maxRange > fixed::Zero() && minRange > maxRange) 1347 minRange = maxRange; 1348 1316 1349 ICmpPathfinder::Goal goal; 1317 1350 1318 1351 if (minRange.IsZero() && maxRange.IsZero()) … … 1381 1414 m_State = STATE_INDIVIDUAL_PATH; 1382 1415 m_TargetEntity = target; 1383 1416 m_TargetOffset = CFixedVector2D(); 1384 m_TargetMinRange = minRange; 1385 m_TargetMaxRange = maxRange; 1417 m_TargetMinRange = origMinRange; 1418 m_TargetMaxRange = origMaxRange; 1419 m_TimeToStayInRange = timeToStayInRange; 1386 1420 m_FinalGoal = goal; 1387 1421 1388 1422 BeginPathing(pos, goal); … … 1454 1488 return (errCircle < errSquare); 1455 1489 } 1456 1490 1457 bool CCmpUnitMotion::MoveToTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange )1491 bool CCmpUnitMotion::MoveToTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange, entity_pos_t timeToStayInRange) 1458 1492 { 1459 1493 PROFILE("MoveToTargetRange"); 1494 entity_pos_t overShoot = fixed::Zero(); 1495 entity_pos_t margin = fixed::Zero(); 1496 // if the target is also moving, take an overshoot into account 1497 CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), target); 1498 if (cmpUnitMotion) 1499 { 1500 margin = cmpUnitMotion->GetCurrentSpeed().Multiply(m_TurnLength); 1501 if (timeToStayInRange > m_TurnLength) 1502 overShoot = cmpUnitMotion->GetCurrentSpeed().Multiply(timeToStayInRange - m_TurnLength); 1503 } 1460 1504 1505 entity_pos_t origMaxRange = maxRange + margin; 1506 entity_pos_t origMinRange = minRange; 1507 maxRange -= overShoot; 1508 minRange += overShoot; 1509 if (maxRange <= origMinRange && origMaxRange >= origMinRange) 1510 maxRange = origMinRange; 1511 if (maxRange > fixed::Zero() && minRange > maxRange) 1512 minRange = maxRange; 1513 1461 1514 CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); 1462 1515 if (!cmpPosition || !cmpPosition->IsInWorld()) 1463 1516 return false; … … 1578 1631 m_State = STATE_INDIVIDUAL_PATH; 1579 1632 m_TargetEntity = target; 1580 1633 m_TargetOffset = CFixedVector2D(); 1581 m_TargetMinRange = minRange; 1582 m_TargetMaxRange = maxRange; 1634 m_TargetMinRange = origMinRange; 1635 m_TargetMaxRange = origMaxRange; 1636 m_TimeToStayInRange = timeToStayInRange; 1583 1637 m_FinalGoal = goal; 1584 1638 1585 1639 BeginPathing(pos, goal); … … 1596 1650 1597 1651 CFixedVector2D targetPos = cmpTargetPosition->GetPosition2D(); 1598 1652 1599 return MoveToPointRange(targetPos.X, targetPos.Y, minRange, maxRange, target);1653 return MoveToPointRange(targetPos.X, targetPos.Y, origMinRange, origMaxRange, target, timeToStayInRange); 1600 1654 } 1601 1655 } 1602 1656 … … 1609 1663 if (!cmpPosition || !cmpPosition->IsInWorld()) 1610 1664 return false; 1611 1665 1666 // if the target is also moving, take an overshoot into account 1667 CmpPtr<ICmpUnitMotion> cmpUnitMotion(GetSimContext(), target); 1668 if (cmpUnitMotion) 1669 maxRange += cmpUnitMotion->GetCurrentSpeed().Multiply(m_TurnLength); 1670 1612 1671 CFixedVector2D pos = cmpPosition->GetPosition2D(); 1613 1672 1614 1673 CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity()); -
source/simulation2/components/ICmpUnitMotion.cpp
26 26 DEFINE_INTERFACE_METHOD_4("MoveToPointRange", bool, ICmpUnitMotion, MoveToPointRange, entity_pos_t, entity_pos_t, entity_pos_t, entity_pos_t) 27 27 DEFINE_INTERFACE_METHOD_4("IsInPointRange", bool, ICmpUnitMotion, IsInPointRange, entity_pos_t, entity_pos_t, entity_pos_t, entity_pos_t) 28 28 DEFINE_INTERFACE_METHOD_3("IsInTargetRange", bool, ICmpUnitMotion, IsInTargetRange, entity_id_t, entity_pos_t, entity_pos_t) 29 DEFINE_INTERFACE_METHOD_ 3("MoveToTargetRange", bool, ICmpUnitMotion, MoveToTargetRange, entity_id_t, entity_pos_t, entity_pos_t)29 DEFINE_INTERFACE_METHOD_4("MoveToTargetRange", bool, ICmpUnitMotion, MoveToTargetRange, entity_id_t, entity_pos_t, entity_pos_t, entity_pos_t) 30 30 DEFINE_INTERFACE_METHOD_3("MoveToFormationOffset", void, ICmpUnitMotion, MoveToFormationOffset, entity_id_t, entity_pos_t, entity_pos_t) 31 31 DEFINE_INTERFACE_METHOD_2("FaceTowardsPoint", void, ICmpUnitMotion, FaceTowardsPoint, entity_pos_t, entity_pos_t) 32 32 DEFINE_INTERFACE_METHOD_0("StopMoving", void, ICmpUnitMotion, StopMoving) … … 60 60 return m_Script.Call<bool>("IsInTargetRange", target, minRange, maxRange); 61 61 } 62 62 63 virtual bool MoveToTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange )63 virtual bool MoveToTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange, entity_pos_t timeToStayInRange) 64 64 { 65 return m_Script.Call<bool>("MoveToTargetRange", target, minRange, maxRange );65 return m_Script.Call<bool>("MoveToTargetRange", target, minRange, maxRange, timeToStayInRange); 66 66 } 67 67 68 68 virtual void MoveToFormationOffset(entity_id_t target, entity_pos_t x, entity_pos_t z) -
source/simulation2/components/ICmpUnitMotion.h
66 66 * and sends another MotionChanged after finishing moving. 67 67 * If maxRange is negative, then the maximum range is treated as infinity. 68 68 */ 69 virtual bool MoveToTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange ) = 0;69 virtual bool MoveToTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange, entity_pos_t timeToStayInRange) = 0; 70 70 71 71 /** 72 72 * Join a formation, and move towards a given offset relative to the formation controller entity.