Rework action for police
authorbenblan <benblan@3ce38193-f967-438d-acd5-fc4e68e0da95>
Sat, 24 Jan 2015 12:16:00 +0000 (12:16 +0000)
committerbenblan <benblan@3ce38193-f967-438d-acd5-fc4e68e0da95>
Sat, 24 Jan 2015 12:16:00 +0000 (12:16 +0000)
freesynd/branches/rework-actions/src/ia/action.cpp
freesynd/branches/rework-actions/src/ia/actions.h
freesynd/branches/rework-actions/src/ia/behaviour.cpp
freesynd/branches/rework-actions/src/ia/behaviour.h
freesynd/branches/rework-actions/src/model/weaponholder.cpp
freesynd/branches/rework-actions/src/model/weaponholder.h
freesynd/branches/rework-actions/src/ped.cpp
freesynd/branches/rework-actions/src/pedmanager.cpp

index 1c72a177e5ac1e741c5fe2633b429a6e6ca1e8f0..86ef5422a2df78495b66cd6d353dc66198028cdd 100644 (file)
@@ -484,6 +484,27 @@ bool DriveVehicleAction::doExecute(int elapsed, Mission *pMission, PedInstance *
     return true;
 }
 
+WaitAndWarnAction::WaitAndWarnAction(PedInstance *pPed) : 
+MovementAction(kActTypeUndefined, kOrigDefault, true), waitTimer_(1000) {
+    pTarget_ = pPed;
+}
+
+void WaitAndWarnAction::doStart(Mission *pMission, PedInstance *pPed) {
+    waitTimer_.reset();
+    pPed->clearDestination();
+}
+
+bool WaitAndWarnAction::doExecute(int elapsed, Mission *pMission, PedInstance *pPed) {
+    if (waitTimer_.update(elapsed)) {
+        setSucceeded();
+        return true;
+    }
+
+    // TODO : Add warning
+
+    return false;
+}
+
 HitAction::HitAction(CreatOrigin origin, ShootableMapObject::DamageInflictType &d) : 
 MovementAction(kActTypeHit, origin) {
     damage_.aimedLoc = d.aimedLoc;
index 62a40b9c851a094fb1102e3b2721eecb9b63482b..0937bbc908356aec99f646932d165d3f8dd2596d 100644 (file)
@@ -381,6 +381,24 @@ namespace fs_actions {
         PathNode dest_;
     };
 
+    /*!
+     * This action is specific to police.
+     * When executing this action, ped waits then warn player agent.
+     */
+    class WaitAndWarnAction : public MovementAction {
+    public:
+        WaitAndWarnAction(PedInstance *pPed);
+
+    protected:
+        void doStart(Mission *pMission, PedInstance *pPed);
+        bool doExecute(int elapsed, Mission *pMission, PedInstance *pPed);
+    protected:
+        /*! The ped watched by this police ped.*/
+        PedInstance *pTarget_;
+        /*! Duration of waiting.*/
+        fs_utils::Timer waitTimer_;
+    };
+
     /*!
      * A HitAction is used to implement the reaction of the ped to an impact.
      * When a Ped is hit by a shot, a HitAction is created and inserted directly
index 01de77f5305de8c16430209c40c25fa9deafbbb5..f2f0a8187f1d27c50cd7f6f800bceaf0cbcfb077 100644 (file)
@@ -38,6 +38,7 @@ const int CommonAgentBehaviourComponent::kRegeratesHealthStep = 1;
 const int PanicComponent::kScoutDistance = 1500;
 const int PanicComponent::kDistanceToRun = 500;
 const double PersuadedBehaviourComponent::kMaxRangeForSearchingWeapon = 500.0;
+const int PoliceBehaviourComponent::kPoliceScoutDistance = 1500;
 
 Behaviour::~Behaviour() {
     destroyComponents();
@@ -325,3 +326,69 @@ void  PanicComponent::runAway(PedInstance *pPed, PedInstance *pArmedPed, fs_acti
     pPed->addMovementAction(pAction, false);
     panicking_ = true;
 }
+
+PoliceBehaviourComponent::PoliceBehaviourComponent():
+        BehaviourComponent(), scoutTimer_(134) {
+    status_ = kPoliceStatusOnPatrol;
+    pTarget_ = NULL;
+}
+
+void PoliceBehaviourComponent::execute(int elapsed, Mission *pMission, PedInstance *pPed) {
+    if (status_ == kPoliceStatusAlert && scoutTimer_.update(elapsed)) {
+        PedInstance *pArmedGuy = findArmedPedNotPolice(pMission, pPed);
+        if (pArmedGuy != NULL) {
+            status_ = kPoliceStatusFollowAndShoot;
+            followAndShootTarget(pPed, pArmedGuy);
+        }
+    }
+}
+
+void PoliceBehaviourComponent::handleBehaviourEvent(PedInstance *pPed, Behaviour::BehaviourEvent evtType, void *pCtxt) {
+    switch(evtType) {
+    case Behaviour::kBehvEvtWeaponOut:
+        if (status_ == kPoliceStatusOnPatrol && !pPed->inVehicle()) {
+            // When someone get his weapon out, police is on alert
+            status_ = kPoliceStatusAlert;
+        }
+        break;
+    case Behaviour::kBehvEvtWeaponCleared:
+        // When no more enemies have weapons out, patrol again
+        
+        break;
+    }
+}
+
+/*!
+ * Return a ped that has his weapon out and is not a police man and is close to this policeman.
+ */
+PedInstance * PoliceBehaviourComponent::findArmedPedNotPolice(Mission *pMission, PedInstance *pPed) {
+    for (size_t i = 0; i < pMission->numArmedPeds(); i++) {
+        PedInstance *pOtherPed = pMission->armedPedAtIndex(i);
+        if (pPed != pOtherPed && pOtherPed->type() != PedInstance::kPedTypePolice && pPed->isCloseTo(pOtherPed, kPoliceScoutDistance)) {
+            return pOtherPed;
+        }
+    }
+    return NULL;
+}
+
+void PoliceBehaviourComponent::followAndShootTarget(PedInstance *pPed, PedInstance *pArmedGuy) {
+    pTarget_ = pArmedGuy;
+    // Select a loaded weapon for ped
+    WeaponHolder::WeaponSelectCriteria crit;
+    crit.desc = WeaponHolder::WeaponSelectCriteria::kCritLoadedShoot;
+    crit.use_ranks = true;
+    pPed->selectRequiredWeapon(&crit);
+    // stop walking
+    pPed->clearDestination();
+    // quit walking now 
+    // TODO : change state management
+    pPed->leaveState(PedInstance::pa_smWalking);
+    pPed->destroyAllActions(true);
+    // Set new actions
+    fs_actions::WaitAndWarnAction *pWarnAction = new fs_actions::WaitAndWarnAction(pPed);
+    pPed->addMovementAction(pWarnAction, false);
+    //fs_actions::FollowAction *pFollowAction = new fs_actions::FollowAction(fs_actions::kOrigDefault, pPed);
+    //pPed->addMovementAction(pFollowAction, true);
+    //pPed->addActionFollowPed(fs_actions::kOrigDefault, pArmedGuy);
+    pPed->addMovementAction(new fs_actions::ResetScriptedAction(), true);
+}
\ No newline at end of file
index 91afb4fe1b813aa8180c7836b43d10b4cf8b8d96..3f38784a6834ce70f211d7b335a979381d088017 100644 (file)
@@ -208,4 +208,38 @@ private:
     bool panicking_;
 };
 
+class PoliceBehaviourComponent : public BehaviourComponent {
+public:
+    PoliceBehaviourComponent();
+
+    void execute(int elapsed, Mission *pMission, PedInstance *pPed);
+
+    void handleBehaviourEvent(PedInstance *pPed, Behaviour::BehaviourEvent evtType, void *pCtxt);
+private:
+    //! Checks whether there is an armed ped next to the ped : returns that ped
+    PedInstance * findArmedPedNotPolice(Mission *pMission, PedInstance *pPed);
+    //! Initiate the process of following and shooting at a target
+    void followAndShootTarget(PedInstance *pPed, PedInstance *pArmedGuy);
+private:
+    static const int kPoliceScoutDistance;
+    /*!
+     * Status of police behaviour.
+     */
+    enum PoliceStatus {
+        //! Default status
+        kPoliceStatusOnPatrol,
+        //! Search for someone who pulled his gun
+        kPoliceStatusAlert,
+        //! Move closer from target to shoot at him
+        kPoliceStatusFollowAndShoot
+    };
+
+    PoliceStatus status_;
+    /*! This timer is used to delay checking by the ped in order to 
+     * not consume too much CPU.*/
+    fs_utils::Timer scoutTimer_;
+    /*! The ped that the police officer is watching and eventually shooting at.*/
+    PedInstance *pTarget_;
+};
+
 #endif // IA_BEHAVIOUR_H_
\ No newline at end of file
index d4beaf1969d08e92b22e2415b006188e0b9646fc..1127ab46e6d4c344c540a2df110bfebaad8687e1 100644 (file)
@@ -280,6 +280,14 @@ bool WeaponHolder::selectRequiredWeapon(WeaponSelectCriteria *pw_to_use) {
                 }
             }
             break;
+        case WeaponSelectCriteria::kCritLoadedShoot:
+            for (uint8 i = 0; i < sz; ++i) {
+                WeaponInstance *pWI = weapons_[i];
+                if (pWI->canShoot() && pWI->ammoRemaining() > 0) {
+                    found_weapons.push_back(std::make_pair(pWI->rank(), i));
+                }
+            }
+            break;
     }
 
     if (!found_weapons.empty()) {
index 589e8522a548cac82167c4d599fe0330774fd464..9daacfa6d1321f1f3e309cdd13b8fe022bc9aa74 100644 (file)
@@ -58,7 +58,8 @@ public:
             kCritWeaponType = 3,        // wpn_type
             kCritDamageStrict = 4,      // type == dmg_type
             kCritDamageNonStrict = 5,   // type & dmg_type != 0
-            kCritPlayerSelection = 6    // Manage selection from weapon selector
+            kCritPlayerSelection = 6,   // Manage selection from weapon selector
+            kCritLoadedShoot = 7        // select weapon who can shoot and has ammo
         };
         //! Union descriptor
         CriteriaType desc;
index db0c19e6e7032f116c1abf8cb8ba8fc663e35627..23110bf9d0672c74bd671205bce556828ae06cda 100644 (file)
@@ -567,6 +567,7 @@ int PedInstance::getTimeBetweenShoots(WeaponInstance *pWeapon) {
 bool PedInstance::useNewAnimation() {
     return isOurAgent() 
         || type() == kPedTypeCivilian
+        || type() == kPedTypePolice
         ;
 }
 
@@ -1540,7 +1541,7 @@ bool PedInstance::animate(int elapsed, Mission *mission) {
                         aqt->multi_var.time_var.desc = 2;
                         aqt->multi_var.time_var.elapsed = 0;
                     }
-                }
+                } // fin de find enemy
                 if ((aqt->act_exec & PedInstance::ai_aFindNonFriend) != 0
                     && (aqt->state & 128) == 0)
                 {
index fd491c95b4c23e850e659727a896ebafde6bfafb..73f2c96152037a8545200b6e76c83a0046bf4cc5 100644 (file)
@@ -314,6 +314,8 @@ void PedManager::initPolice(PedInstance *pPed) {
     pPed->setBaseSpeed(160);
     pPed->setTimeBeforeCheck(400);
     pPed->setBaseModAcc(0.4);
+
+    pPed->behaviour().addComponent(new PoliceBehaviourComponent());
 } 
 
 /*!