Changed the way panic is activated.
authorbenblan <benblan@3ce38193-f967-438d-acd5-fc4e68e0da95>
Tue, 30 Sep 2014 19:24:47 +0000 (19:24 +0000)
committerbenblan <benblan@3ce38193-f967-438d-acd5-fc4e68e0da95>
Tue, 30 Sep 2014 19:24:47 +0000 (19:24 +0000)
12 files changed:
freesynd/branches/rework-actions/src/ia/action.cpp
freesynd/branches/rework-actions/src/ia/behaviour.cpp
freesynd/branches/rework-actions/src/ia/behaviour.h
freesynd/branches/rework-actions/src/menus/gameplaymenu.cpp
freesynd/branches/rework-actions/src/menus/squadselection.cpp
freesynd/branches/rework-actions/src/menus/squadselection.h
freesynd/branches/rework-actions/src/mission.cpp
freesynd/branches/rework-actions/src/mission.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/ped.h

index f3b4d41f1290096c65edd7bf5af7b26cb3e46457..e4e2c45eb6465def652e50c87de0397b10a223f2 100644 (file)
@@ -391,7 +391,7 @@ bool PutdownWeaponAction::doExecute(int elapsed, Mission *pMission, PedInstance
         }
 
         if (pPed->selectedWeapon() == NULL && pWeapon->canShoot()) {
-            GameEvent::sendEvt(GameEvent::kMission, GameEvent::kEvtWeaponCleared);
+            GameEvent::sendEvt(GameEvent::kMission, GameEvent::kEvtWeaponCleared, pPed);
         }
         setSucceeded();
     }
index 889ae2d5a92f7d3b90ed0d0396d96ad2e5f00eda..b0bd92f3ad7330f92ad2025944d6af2892a5981e 100644 (file)
@@ -29,6 +29,7 @@
 #include "ped.h"
 #include "mission.h"
 #include "core/squad.h"
+#include "core/gamesession.h"
 
 //*************************************
 // Constant definition
@@ -49,10 +50,10 @@ void Behaviour::destroyComponents() {
     }
 }
 
-void Behaviour::handleBehaviourEvent(BehaviourEvent evtType) {
+void Behaviour::handleBehaviourEvent(BehaviourEvent evtType, void *pCtxt) {
     for (std::list < BehaviourComponent * >::iterator it = compLst_.begin();
             it != compLst_.end(); it++) {
-        (*it)->handleBehaviourEvent(evtType, pThisPed_);
+        (*it)->handleBehaviourEvent(pThisPed_, evtType, pCtxt);
     }
 }
 
@@ -108,7 +109,7 @@ void CommonAgentBehaviourComponent::execute(int elapsed, Mission *pMission, PedI
     }
 }
 
-void CommonAgentBehaviourComponent::handleBehaviourEvent(Behaviour::BehaviourEvent evtType, PedInstance *pPed) {
+void CommonAgentBehaviourComponent::handleBehaviourEvent(PedInstance *pPed, Behaviour::BehaviourEvent evtType, void *pCtxt) {
     switch(evtType) {
     case Behaviour::kBehvEvtHit:
         if (pPed->hasMinimumVersionOfMod(Mod::MOD_CHEST, Mod::MOD_V2)) {
@@ -139,7 +140,7 @@ void PersuaderBehaviourComponent::execute(int elapsed, Mission *pMission, PedIns
     }
 }
 
-void PersuaderBehaviourComponent::handleBehaviourEvent(Behaviour::BehaviourEvent evtType, PedInstance *pPed) {
+void PersuaderBehaviourComponent::handleBehaviourEvent(PedInstance *pPed, Behaviour::BehaviourEvent evtType, void *pCtxt) {
     switch(evtType) {
     case Behaviour::kBehvEvtPersuadotronActivated:
         doUsePersuadotron_ = true;
@@ -164,7 +165,7 @@ void PersuadedBehaviourComponent::execute(int elapsed, Mission *pMission, PedIns
     }
 }
 
-void PersuadedBehaviourComponent::handleBehaviourEvent(Behaviour::BehaviourEvent evtType, PedInstance *pPed) {
+void PersuadedBehaviourComponent::handleBehaviourEvent(PedInstance *pPed, Behaviour::BehaviourEvent evtType, void *pCtxt) {
 
 }
 
@@ -209,32 +210,35 @@ void PanicComponent::execute(int elapsed, Mission *pMission, PedInstance *pPed)
     }
 }
 
-void PanicComponent::handleBehaviourEvent(Behaviour::BehaviourEvent evtType, PedInstance *pPed) {
+void PanicComponent::handleBehaviourEvent(PedInstance *pPed, Behaviour::BehaviourEvent evtType, void *pCtxt) {
     switch(evtType) {
-    case Behaviour::kBehvEvtPanicEnabled:
-        setEnabled(true);
+    case Behaviour::kBehvEvtWeaponOut:
+        if (!pPed->isPanicImmuned()) {
+            setEnabled(true);
+        }
         break;
-    case Behaviour::kBehvEvtPanicDisabled:
-        setEnabled(false);
-        if (panicking_) {
-            pPed->restoreDefaultAction();
-            panicking_ = false;
+    case Behaviour::kBehvEvtWeaponCleared:
+        if (g_Session.getMission()->numArmedPeds() == 0) {
+            setEnabled(false);
+            if (panicking_) {
+                pPed->restoreDefaultAction();
+                panicking_ = false;
+            }
         }
         break;
     }
 }
 
 /*!
- * Return the first ped that is close to the given ped and who is armed.
+ * Return the first armed ped that is close to the given ped.
  * \param pMission
  * \param pPed
  * \return NULL if no ped is found
  */
 PedInstance * PanicComponent::findNearbyArmedPed(Mission *pMission, PedInstance *pPed) {
-    for (size_t i = 0; i < pMission->numPeds(); i++) {
-        PedInstance *pOtherPed = pMission->ped(i);
-        // Agent can only persuad peds from another group
-        if (pOtherPed->isArmed() && pPed->isCloseTo(pOtherPed, kScoutDistance)) {
+    for (size_t i = 0; i < pMission->numArmedPeds(); i++) {
+        PedInstance *pOtherPed = pMission->armedPedAtIndex(i);
+        if (pPed->isCloseTo(pOtherPed, kScoutDistance)) {
             return pOtherPed;
         }
     }
index 8b668cfd097af19b5e3f8f3fe6f94329dc84c27e..4da6a78ffd21b210433a5a23c737f885f0481875 100644 (file)
@@ -52,10 +52,10 @@ public:
         kBehvEvtPersuadotronDeactivated,
         //! An ped has been hit
         kBehvEvtHit,
-        //! Event to activate the panic component
-        kBehvEvtPanicEnabled,
-        //! Event to deactivate the panic component
-        kBehvEvtPanicDisabled
+        //! A ped has shown his weapon
+        kBehvEvtWeaponOut,
+        //! A ped has cleared his weapon
+        kBehvEvtWeaponCleared
     };
 
     virtual ~Behaviour();
@@ -68,7 +68,7 @@ public:
 
     virtual void execute(int elapsed, Mission *pMission);
 
-    virtual void handleBehaviourEvent(BehaviourEvent evtType);
+    virtual void handleBehaviourEvent(BehaviourEvent evtType, void *pCtxt = NULL);
 protected:
     void destroyComponents();
 protected:
@@ -92,7 +92,7 @@ public:
 
     virtual void execute(int elapsed, Mission *pMission, PedInstance *pPed) = 0;
 
-    virtual void handleBehaviourEvent(Behaviour::BehaviourEvent evtType, PedInstance *pPed){};
+    virtual void handleBehaviourEvent(PedInstance *pPed, Behaviour::BehaviourEvent evtType, void *pCtxt){};
 
 protected:
     bool enabled_;
@@ -112,7 +112,7 @@ public:
 
     void execute(int elapsed, Mission *pMission, PedInstance *pPed);
 
-    void handleBehaviourEvent(Behaviour::BehaviourEvent evtType, PedInstance *pPed);
+    void handleBehaviourEvent(PedInstance *pPed, Behaviour::BehaviourEvent evtType, void *pCtxt);
 private:
     /*! Flag to indicate whether ped can regenerate his health.*/
     bool doRegenerates_;
@@ -129,7 +129,7 @@ public:
 
     void execute(int elapsed, Mission *pMission, PedInstance *pPed);
 
-    void handleBehaviourEvent(Behaviour::BehaviourEvent evtType, PedInstance *pPed);
+    void handleBehaviourEvent(PedInstance *pPed, Behaviour::BehaviourEvent evtType, void *pCtxt);
 private:
     /*! Flag to indicate an agent can use his persuadotron.*/
     bool doUsePersuadotron_;
@@ -144,7 +144,7 @@ public:
 
     void execute(int elapsed, Mission *pMission, PedInstance *pPed);
 
-    void handleBehaviourEvent(Behaviour::BehaviourEvent evtType, PedInstance *pPed);
+    void handleBehaviourEvent(PedInstance *pPed, Behaviour::BehaviourEvent evtType, void *pCtxt);
 private:
     //! used for delaying checking of nearby weapon search
     fs_utils::Timer checkWeaponTimer_;
@@ -167,7 +167,7 @@ public:
 
     void execute(int elapsed, Mission *pMission, PedInstance *pPed);
 
-    void handleBehaviourEvent(Behaviour::BehaviourEvent evtType, 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 * findNearbyArmedPed(Mission *pMission, PedInstance *pPed);
index be111ab4da555872b9cff798d860e60f38f22b09..24a6978654cfe16ecb1d8d35476856ab81383cb0 100644 (file)
@@ -1475,30 +1475,21 @@ void GameplayMenu::handleGameEvent(GameEvent evt) {
         PedInstance *p_ped = static_cast<PedInstance *> (evt.pCtxt);
         updateSelectionForDeadAgent(p_ped);
     } else if (evt.type == GameEvent::kEvtWeaponOut) {
-        // some ped has shown a weapon, activate panic among civilians
-        cntArmedPed_ += 1;
-        if (cntArmedPed_ == 1) {
-            for (size_t i = 0; i < mission_->numPeds(); i++) {
-                PedInstance *pPed = mission_->ped(i);
-                if (pPed->type() == PedInstance::kPedTypeCivilian &&
-                        !pPed->isPanicImmuned()) {
-                    pPed->behaviour().handleBehaviourEvent(Behaviour::kBehvEvtPanicEnabled);
-                }
+        PedInstance *pPedSource = static_cast<PedInstance *> (evt.pCtxt);
+        mission_->addArmedPed(pPedSource);
+        for (size_t i = 0; i < mission_->numPeds(); i++) {
+            PedInstance *pPed = mission_->ped(i);
+            if (pPed != pPedSource) {
+                pPed->behaviour().handleBehaviourEvent(Behaviour::kBehvEvtWeaponOut, pPedSource);
             }
         }
     } else if (evt.type == GameEvent::kEvtWeaponCleared) {
-        // some ped has put his weapon away, deactivate panic among civilians
-        // we check value just to be sure not to go out of range
-        if (cntArmedPed_ > 1) {
-            cntArmedPed_ -= 1;
-        } else if (cntArmedPed_ == 1) {
-            cntArmedPed_ = 0;
-            for (size_t i = 0; i < mission_->numPeds(); i++) {
-                PedInstance *pPed = mission_->ped(i);
-                if (pPed->type() == PedInstance::kPedTypeCivilian &&
-                        !pPed->isPanicImmuned()) {
-                    pPed->behaviour().handleBehaviourEvent(Behaviour::kBehvEvtPanicDisabled);
-                }
+        PedInstance *pPedSource = static_cast<PedInstance *> (evt.pCtxt);
+        mission_->removeArmedPed(pPedSource);
+        for (size_t i = 0; i < mission_->numPeds(); i++) {
+            PedInstance *pPed = mission_->ped(i);
+            if (pPed != pPedSource) {
+                pPed->behaviour().handleBehaviourEvent(Behaviour::kBehvEvtWeaponCleared, pPedSource);
             }
         }
     }
index 079fee4a72cda8716fa39cca8d4688505c0f16c7..04ae972d8fbcc756de0db9464dcb847d35232f2e 100644 (file)
@@ -163,9 +163,10 @@ void SquadSelection::checkLeader(size_t agentNo) {
  */
 void SquadSelection::deselectAllWeapons() {
     for (SquadSelection::Iterator it = begin(); it != end(); ++it) {
-        WeaponInstance *pWi = (*it)->deselectWeapon();
+        PedInstance *pAgent = *it;
+        WeaponInstance *pWi = pAgent->deselectWeapon();
         if (pWi && pWi->canShoot()) {
-            GameEvent::sendEvt(GameEvent::kMission, GameEvent::kEvtWeaponCleared);
+            GameEvent::sendEvt(GameEvent::kMission, GameEvent::kEvtWeaponCleared, pAgent);
         }
     }
 }
index 1b72c66ff652feb8ea2e4c5f68a34238a418a4bb..ba172bf3ec18f8d6da4cb9376d334da56bafd973 100644 (file)
@@ -42,8 +42,14 @@ class SquadSelection {
       */
      class Iterator {
          public:
-            Iterator(size_t idx, SquadSelection *pSel) : idx_(idx), pSel_(pSel) {}
-            ~Iterator() {}
+            Iterator(size_t idx, SquadSelection *pSel) {
+                idx_ = idx;
+                pSel_ = pSel;
+            }
+
+            ~Iterator() {
+                idx_ = idx_;
+            }
 
             // The assignment and relational operators are straightforward
             Iterator& operator=(const Iterator& other)
index 6d8b81f4251005f8bfbd9cbfb65d5137e217da38..d917557deb5ad409bd7d52f6519c368ea1d170a2 100644 (file)
@@ -92,6 +92,7 @@ Mission::~Mission()
         delete statics_[i];
     for (unsigned int i = 0; i < objectives_.size(); i++)
         delete objectives_[i];
+    armedPedsVec_.clear();
     clrSurfaces();
 
     if (p_minimap_) {
@@ -108,6 +109,19 @@ void Mission::delPrjShot(size_t i) {
     prj_shots_.erase((prj_shots_.begin() + i));
 }
 
+/*!
+ * Removes given ped from the list of armed peds.
+ * \param pPed The ped to remove
+ */
+void Mission::removeArmedPed(PedInstance *pPed) {
+    for (size_t i = 0; i < armedPedsVec_.size();  i++) {
+        if (pPed == armedPedsVec_[i]) {
+            armedPedsVec_.erase(armedPedsVec_.begin() + i);
+            break;
+        }
+    }
+}
+
 /*!
  * Sets the given message with the current objective label.
  */
index 094b0ded8da09ecd5656e11fbddf79852953f495..5b7ea1873f3327e4a58a3ba97c7f68d008be7342 100644 (file)
@@ -210,6 +210,29 @@ public:
      */
     void delPrjShot(size_t i);
 
+    /*!
+     * Adds the given PedInstance to the list of armed peds.
+     * \param pPed The ped to add
+     */
+    void addArmedPed(PedInstance *pPed) {
+        armedPedsVec_.push_back(pPed);
+    }
+    /*!
+     * Returns the number of currently armed peds.
+     */
+    size_t numArmedPeds() { return armedPedsVec_.size(); }
+    /*!
+     * Return the PedInstance at the given index.
+     * \param i Index of the projectile
+     * \return The ped found.
+     */
+    PedInstance *armedPedAtIndex(size_t i) { return armedPedsVec_[i]; }
+    /*!
+     * Removes given ped from the list of armed peds.
+     * \param pPed The ped to remove
+     */
+    void removeArmedPed(PedInstance *pPed);
+
     /*! Return the mission statistics. */
     MissionStats *stats() { return &stats_; }
 
@@ -284,6 +307,11 @@ protected:
     std::vector<Static *> statics_;
     std::vector<SFXObject *> sfx_objects_;
     std::vector<ProjectileShot *> prj_shots_;
+    /*!
+     * A vector constantly updated with the peds that hold a weapon.
+     * It's used for performance reasons.
+     */
+    std::vector<PedInstance *> armedPedsVec_;
 
     std::vector <ObjectiveDesc *> objectives_;
     //std::vector <ObjectiveDesc> sub_objectives_;
index 76ec7fc19f0b0b56deb8020ee545d776b96a4ee0..d4beaf1969d08e92b22e2415b006188e0b9646fc 100644 (file)
@@ -116,20 +116,15 @@ void WeaponHolder::removeAllWeapons() {
  * Calls onWeaponDeselected() and onWeaponSelected().
  */
 void WeaponHolder::selectWeapon(uint8 n) {
-    bool noWeaponSelected = selected_weapon_ == kNoWeaponSelected;
     assert(n < weapons_.size());
     WeaponInstance *pNewWeapon = weapons_[n];
     if (canSelectWeapon(pNewWeapon)) {
-        // First deselect current weapon
-        deselectWeapon();
+        // First deselect current weapon if any
+        WeaponInstance *prevSelectedWeapon = deselectWeapon();
 
         selected_weapon_ = n;
-        handleWeaponSelected(pNewWeapon);
+        handleWeaponSelected(pNewWeapon, prevSelectedWeapon);
         updtPreferedWeapon();
-
-        if (noWeaponSelected && selectedWeapon()->canShoot()) {
-            GameEvent::sendEvt(GameEvent::kMission, GameEvent::kEvtWeaponOut);
-        }
     }
 }
 
index f05b407aaa1a2febbb0fa22aa31965621a6ed857..589e8522a548cac82167c4d599fe0330774fd464 100644 (file)
@@ -127,8 +127,9 @@ protected:
     /*!
      * Called when a weapon has been selected.
      * \param wi The selected weapon
+     * \param previousWeapon The previous selected weapon (can be null if no weapon was selected)
      */
-    virtual void handleWeaponSelected(WeaponInstance * wi) {}
+    virtual void handleWeaponSelected(WeaponInstance * wi, WeaponInstance * previousWeapon) {}
     //! Updates the prefered weapon criteria based on current selection
     void updtPreferedWeapon();
 protected:
index 3b58aa8126260af5896568b95095b2251dcc55f8..8549be3f1234e58b9c053377c1adfff8a509f5bd 100644 (file)
@@ -2299,8 +2299,9 @@ void PedInstance::handleWeaponDeselected(WeaponInstance * wi) {
 /*!
  * Called when a weapon has been selected.
  * \param wi The selected weapon
+ * \param previousWeapon The previous selected weapon (can be null if no weapon was selected)
  */
-void PedInstance::handleWeaponSelected(WeaponInstance * wi) {
+void PedInstance::handleWeaponSelected(WeaponInstance * wi, WeaponInstance * previousWeapon) {
     if (wi->usesAmmo()) {
         if (wi->ammoRemaining() == 0) {
             desc_state_ |= pd_smNoAmmunition;
@@ -2332,6 +2333,14 @@ void PedInstance::handleWeaponSelected(WeaponInstance * wi) {
         behaviour_.handleBehaviourEvent(Behaviour::kBehvEvtPersuadotronActivated);
         break;
     }
+
+    if (previousWeapon == NULL && selectedWeapon()->canShoot()) {
+        // alert if it's the first time the ped shows a shooting weapon
+        GameEvent::sendEvt(GameEvent::kMission, GameEvent::kEvtWeaponOut, this);
+    } else if (previousWeapon != NULL && previousWeapon->canShoot() && !selectedWeapon()->canShoot()) {
+        // or alert if ped go from a shooting weapon to a no shooting weapon like the persuadotron
+        GameEvent::sendEvt(GameEvent::kMission, GameEvent::kEvtWeaponCleared, this);
+    }
 }
 
 /*!
@@ -2620,7 +2629,7 @@ bool PedInstance::handleDeath(Mission *pMission, ShootableMapObject::DamageInfli
         updatePersuadedRelations(pMission->getSquad());
 
         if (selectedWeapon() && selectedWeapon()->canShoot()) {
-            GameEvent::sendEvt(GameEvent::kMission, GameEvent::kEvtWeaponCleared);
+            GameEvent::sendEvt(GameEvent::kMission, GameEvent::kEvtWeaponCleared, this);
         }
 
         switch (d.dtype) {
index 4a5d0d11d5a214e86a71e27ff05d902ba1237b8c..12f5832a46468f92e34d5f5fe420c8ee26629ed2 100644 (file)
@@ -901,11 +901,8 @@ protected:
      * \param wi The deselected weapon
      */
     void handleWeaponDeselected(WeaponInstance * wi);
-    /*!
-     * Called when a weapon has been selected.
-     * \param wi The selected weapon
-     */
-    void handleWeaponSelected(WeaponInstance * wi);
+    //! See WeaponHolder::handleWeaponSelected()
+    void handleWeaponSelected(WeaponInstance * wi, WeaponInstance * previousWeapon);
 
     //! Returns the number of points an agent must have to persuade a ped of given type
     uint16 getRequiredPointsToPersuade(PedType type);