Ticket #1537: chasing.2.diff

File chasing.2.diff, 15.6 KB (added by sanderd17, 10 years ago)
  • binaries/data/mods/public/simulation/components/UnitAI.js

     
    378378        // We use the distance between the entities to account for ranged attacks
    379379        var distance = DistanceBetweenEntities(this.entity, this.order.data.target) + (+this.template.FleeDistance);
    380380        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))
    382382        {
    383383            // We've started fleeing from the given target
    384384            if (this.IsAnimal())
     
    485485        }
    486486
    487487        // 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))
    489489        {
    490490            // We've started walking to the given point
    491491            if (this.IsAnimal())
     
    15871587                    }
    15881588                    else
    15891589                    {
    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))
    15911591                        {
    15921592                            this.SetNextState("APPROACHING");
    15931593                        }
     
    16141614                    // If we're not in range yet (maybe we stopped moving), move to target again
    16151615                    if (!this.CheckTargetAttackRange(this.order.data.target, IID_Attack, this.order.data.attackType))
    16161616                    {
    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))
    16181618                            this.SetNextState("APPROACHING");
    16191619                        else
    16201620                        {
     
    17151715                        // Can't reach it - try to chase after it
    17161716                        if (this.ShouldChaseTargetedEntity(target, this.order.data.force))
    17171717                        {
    1718                             if (this.MoveToTargetRange(target, IID_Attack, this.order.data.attackType))
     1718                            if (this.MoveToTargetAttackRange(target, this.order.data.attackType))
    17191719                            {
    17201720                                this.SetNextState("COMBAT.CHASING");
    17211721                                return;
     
    38433843        return false;
    38443844
    38453845    var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion);
    3846     return cmpUnitMotion.MoveToTargetRange(target, 0, 0);
     3846    return cmpUnitMotion.MoveToTargetRange(target, 0, 0, 0);
    38473847};
    38483848
    3849 UnitAI.prototype.MoveToTargetRange = function(target, iid, type)
     3849UnitAI.prototype.MoveToTargetRange = function(target, iid, type, time)
    38503850{
    38513851    if (!this.CheckTargetVisible(target))
    38523852        return false;
     
    38553855    if (!cmpRanged)
    38563856        return false;
    38573857    var range = cmpRanged.GetRange(type);
     3858    if (!time)
     3859        var time = 0;
    38583860
    38593861    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);
    38613863};
    38623864
    38633865/**
     
    38653867 * for melee attacks, this goes straight to the default range checks
    38663868 * for ranged attacks, the parabolic range is used
    38673869 */
    3868 UnitAI.prototype.MoveToTargetAttackRange = function(target, iid, type)
     3870UnitAI.prototype.MoveToTargetAttackRange = function(target, type)
    38693871{
     3872    var cmpAttack = Engine.QueryInterface(this.entity, IID_Attack);
     3873    var timers = cmpAttack.GetTimers(type);
     3874    var time = timers.prepare;
    38703875
    38713876    if(type!= "Ranged")
    3872         return this.MoveToTargetRange(target, iid, type);
     3877        return this.MoveToTargetRange(target, IID_Attack, type, time);
    38733878   
    38743879    if (!this.CheckTargetVisible(target))
    38753880        return false;
    38763881   
    3877     var cmpRanged = Engine.QueryInterface(this.entity, iid);
    3878     var range = cmpRanged.GetRange(type);
     3882    var range = cmpAttack.GetRange(type);
    38793883
    38803884    var thisCmpPosition = Engine.QueryInterface(this.entity, IID_Position);
    38813885    var s = thisCmpPosition.GetPosition();
     
    39003904    var guessedMaxRange = (range.max + parabolicMaxRange)/2;
    39013905
    39023906    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))
    39043908        return true;
    39053909
    39063910    // 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);
    39083912};
    39093913
    3910 UnitAI.prototype.MoveToTargetRangeExplicit = function(target, min, max)
     3914UnitAI.prototype.MoveToTargetRangeExplicit = function(target, min, max, time)
    39113915{
    39123916    if (!this.CheckTargetVisible(target))
    39133917        return false;
    39143918
     3919    if (!time)
     3920        var time = 0;
     3921
    39153922    var cmpUnitMotion = Engine.QueryInterface(this.entity, IID_UnitMotion);
    3916     return cmpUnitMotion.MoveToTargetRange(target, min, max);
     3923    return cmpUnitMotion.MoveToTargetRange(target, min, max, time);
    39173924};
    39183925
    39193926UnitAI.prototype.MoveToGarrisonRange = function(target)
     
    39273934    var range = cmpGarrisonHolder.GetLoadingRange();
    39283935
    39293936    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);
    39313938};
    39323939
    39333940UnitAI.prototype.CheckPointRangeExplicit = function(x, z, min, max)
  • source/simulation2/components/CCmpUnitMotion.cpp

     
    132132    bool m_FormationController;
    133133    fixed m_WalkSpeed, m_OriginalWalkSpeed; // in metres per second
    134134    fixed m_RunSpeed, m_OriginalRunSpeed;
     135    fixed m_TimeToStayInRange, m_TurnLength;
    135136    ICmpPathfinder::pass_class_t m_PassClass;
    136137    ICmpPathfinder::cost_class_t m_CostClass;
    137138
     
    297298        m_WalkSpeed = m_OriginalWalkSpeed = paramNode.GetChild("WalkSpeed").ToFixed();
    298299        m_Speed = m_WalkSpeed;
    299300        m_CurSpeed = fixed::Zero();
     301        m_TimeToStayInRange = fixed::Zero();
    300302
    301303        if (paramNode.GetChild("Run").IsOk())
    302304            m_RunSpeed = m_OriginalRunSpeed = paramNode.GetChild("Run").GetChild("Speed").ToFixed();
     
    350352
    351353        serialize.NumberFixed_Unbounded("speed", m_Speed);
    352354
     355        serialize.NumberFixed_Unbounded("timeToStayInRange", m_TimeToStayInRange);
     356        serialize.NumberFixed_Unbounded("turnLength", m_TurnLength);
     357
    353358        serialize.Bool("moving", m_Moving);
    354359        serialize.Bool("facePointAfterMove", m_FacePointAfterMove);
    355360
     
    379384        {
    380385            if (m_FormationController)
    381386            {
    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);
    384389            }
    385390            break;
    386391        }
     
    388393        {
    389394            if (!m_FormationController)
    390395            {
    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);
    393398            }
    394399            break;
    395400        }
     
    470475
    471476    virtual bool MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange);
    472477    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);
    474479    virtual bool IsInTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange);
    475480    virtual void MoveToFormationOffset(entity_id_t target, entity_pos_t x, entity_pos_t z);
    476481
     
    548553        GetSimContext().GetComponentManager().PostMessage(GetEntityId(), msg);
    549554    }
    550555
    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);
    552557
    553558    /**
    554559     * Handle the result of an asynchronous path query.
     
    9951000                        }
    9961001                        else
    9971002                        {
     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
    9981013                            // Not in formation, so just finish moving
    999 
    10001014                            StopMoving();
    10011015
    1002 
    10031016                            if (m_FacePointAfterMove)
    10041017                                FaceTowardsPointFromPos(pos, m_FinalGoal.x, m_FinalGoal.z);
    10051018                            // TODO: if the goal was a square building, we ought to point towards the
     
    13001313
    13011314bool CCmpUnitMotion::MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange)
    13021315{
    1303     return MoveToPointRange(x, z, minRange, maxRange, INVALID_ENTITY);
     1316    return MoveToPointRange(x, z, minRange, maxRange, INVALID_ENTITY, fixed::Zero());
    13041317}
    13051318
    1306 bool CCmpUnitMotion::MoveToPointRange(entity_pos_t x, entity_pos_t z, entity_pos_t minRange, entity_pos_t maxRange, entity_id_t target)
     1319bool 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)
    13071320{
    13081321    PROFILE("MoveToPointRange");
    13091322
     
    13131326
    13141327    CFixedVector2D pos = cmpPosition->GetPosition2D();
    13151328
     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
    13161349    ICmpPathfinder::Goal goal;
    13171350
    13181351    if (minRange.IsZero() && maxRange.IsZero())
     
    13811414    m_State = STATE_INDIVIDUAL_PATH;
    13821415    m_TargetEntity = target;
    13831416    m_TargetOffset = CFixedVector2D();
    1384     m_TargetMinRange = minRange;
    1385     m_TargetMaxRange = maxRange;
     1417    m_TargetMinRange = origMinRange;
     1418    m_TargetMaxRange = origMaxRange;
     1419    m_TimeToStayInRange = timeToStayInRange;
    13861420    m_FinalGoal = goal;
    13871421
    13881422    BeginPathing(pos, goal);
     
    14541488    return (errCircle < errSquare);
    14551489}
    14561490
    1457 bool CCmpUnitMotion::MoveToTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange)
     1491bool CCmpUnitMotion::MoveToTargetRange(entity_id_t target, entity_pos_t minRange, entity_pos_t maxRange, entity_pos_t timeToStayInRange)
    14581492{
    14591493    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    }
    14601504
     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
    14611514    CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle());
    14621515    if (!cmpPosition || !cmpPosition->IsInWorld())
    14631516        return false;
     
    15781631        m_State = STATE_INDIVIDUAL_PATH;
    15791632        m_TargetEntity = target;
    15801633        m_TargetOffset = CFixedVector2D();
    1581         m_TargetMinRange = minRange;
    1582         m_TargetMaxRange = maxRange;
     1634        m_TargetMinRange = origMinRange;
     1635        m_TargetMaxRange = origMaxRange;
     1636        m_TimeToStayInRange = timeToStayInRange;
    15831637        m_FinalGoal = goal;
    15841638
    15851639        BeginPathing(pos, goal);
     
    15961650
    15971651        CFixedVector2D targetPos = cmpTargetPosition->GetPosition2D();
    15981652
    1599         return MoveToPointRange(targetPos.X, targetPos.Y, minRange, maxRange, target);
     1653        return MoveToPointRange(targetPos.X, targetPos.Y, origMinRange, origMaxRange, target, timeToStayInRange);
    16001654    }
    16011655}
    16021656
     
    16091663    if (!cmpPosition || !cmpPosition->IsInWorld())
    16101664        return false;
    16111665
     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
    16121671    CFixedVector2D pos = cmpPosition->GetPosition2D();
    16131672
    16141673    CmpPtr<ICmpObstructionManager> cmpObstructionManager(GetSystemEntity());
  • source/simulation2/components/ICmpUnitMotion.cpp

     
    2626DEFINE_INTERFACE_METHOD_4("MoveToPointRange", bool, ICmpUnitMotion, MoveToPointRange, entity_pos_t, entity_pos_t, entity_pos_t, entity_pos_t)
    2727DEFINE_INTERFACE_METHOD_4("IsInPointRange", bool, ICmpUnitMotion, IsInPointRange, entity_pos_t, entity_pos_t, entity_pos_t, entity_pos_t)
    2828DEFINE_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)
     29DEFINE_INTERFACE_METHOD_4("MoveToTargetRange", bool, ICmpUnitMotion, MoveToTargetRange, entity_id_t, entity_pos_t, entity_pos_t, entity_pos_t)
    3030DEFINE_INTERFACE_METHOD_3("MoveToFormationOffset", void, ICmpUnitMotion, MoveToFormationOffset, entity_id_t, entity_pos_t, entity_pos_t)
    3131DEFINE_INTERFACE_METHOD_2("FaceTowardsPoint", void, ICmpUnitMotion, FaceTowardsPoint, entity_pos_t, entity_pos_t)
    3232DEFINE_INTERFACE_METHOD_0("StopMoving", void, ICmpUnitMotion, StopMoving)
     
    6060        return m_Script.Call<bool>("IsInTargetRange", target, minRange, maxRange);
    6161    }
    6262
    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)
    6464    {
    65         return m_Script.Call<bool>("MoveToTargetRange", target, minRange, maxRange);
     65        return m_Script.Call<bool>("MoveToTargetRange", target, minRange, maxRange, timeToStayInRange);
    6666    }
    6767
    6868    virtual void MoveToFormationOffset(entity_id_t target, entity_pos_t x, entity_pos_t z)
  • source/simulation2/components/ICmpUnitMotion.h

     
    6666     * and sends another MotionChanged after finishing moving.
    6767     * If maxRange is negative, then the maximum range is treated as infinity.
    6868     */
    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;
    7070
    7171    /**
    7272     * Join a formation, and move towards a given offset relative to the formation controller entity.