]> github.com/historicalsource and other repositories - freesynd.git/commitdiff
Added PanicComponent to manage panic for civilian
authorbenblan <benblan@3ce38193-f967-438d-acd5-fc4e68e0da95>
Fri, 8 Aug 2014 21:35:29 +0000 (21:35 +0000)
committerbenblan <benblan@3ce38193-f967-438d-acd5-fc4e68e0da95>
Fri, 8 Aug 2014 21:35:29 +0000 (21:35 +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/mapobject.h
freesynd/branches/rework-actions/src/menus/gameplaymenu.cpp
freesynd/branches/rework-actions/src/missionmanager.cpp
freesynd/branches/rework-actions/src/ped.cpp
freesynd/branches/rework-actions/src/ped.h
freesynd/branches/rework-actions/src/pedactions.cpp
freesynd/branches/rework-actions/src/pedmanager.cpp

index 56ac88b33662cac54c788e0c16d8be384f739c31..59a63c711b73079b785e72ae2e865b21689eba1b 100644 (file)
@@ -43,6 +43,7 @@ const int WalkBurnHitAction::kTimeToWalkBurning = 1000;
 
 /*!
  * Default constructor.
+ * \param type What type of action.
  * \param origin Who has created this action.
  */
 Action::Action(ActionType type, CreatOrigin origin) {
@@ -51,6 +52,13 @@ Action::Action(ActionType type, CreatOrigin origin) {
     type_ = type;
 }
 
+/*!
+ * Reset the action.
+ */
+void Action::reset() {
+    status_ = kActStatusNotStarted;
+}
+
 /*!
  * Default constructor.
  * \param origin Who has created this action.
@@ -171,21 +179,24 @@ MovementAction(kActTypeWalk, origin) {
     maxDistanceToWalk_ = 0;
     dest.convertPosToXYZ(&dest_);
     targetState_ = PedInstance::pa_smWalking;
+    newSpeed_ = -1;
 }
 
-WalkToDirectionAction::WalkToDirectionAction(CreatOrigin origin) :
+WalkToDirectionAction::WalkToDirectionAction(CreatOrigin origin, int speed) :
 MovementAction(kActTypeWalk, origin) {
     maxDistanceToWalk_ = 0;
     dest_.x = -1;
     dest_.y = -1;
     dest_.z = -1;
     targetState_ = PedInstance::pa_smWalking;
+    newSpeed_ = speed;
 }
 
 void WalkToDirectionAction::doStart(Mission *pMission, PedInstance *pPed) {
     moveDirdesc_.clear();
     moveDirdesc_.bounce = true;
-    pPed->setSpeed(pPed->getDefaultSpeed());
+    pPed->setSpeed(newSpeed_ != -1? newSpeed_ : pPed->getDefaultSpeed());
+    distWalked_ = 0;
 }
 
 /*!
@@ -221,9 +232,8 @@ bool WalkToDirectionAction::doExecute(int elapsed, Mission *pMission, PedInstanc
         } else {
             endAction = true;
         }
-    } else {
-        distanceToWalk = maxDistanceToWalk_ != 0 ? 
-                                maxDistanceToWalk_ - distWalked_ : 0;
+    } else if (maxDistanceToWalk_ != 0) {
+        distanceToWalk = maxDistanceToWalk_ - distWalked_;
         pPed->moveToDir(pMission,
                         elapsed,
                         moveDirdesc_,
@@ -231,10 +241,13 @@ bool WalkToDirectionAction::doExecute(int elapsed, Mission *pMission, PedInstanc
                         -1, -1,
                         &distanceToWalk, true);
 
-        if (maxDistanceToWalk_ != 0) {
-            distWalked_ += distanceToWalk;
-            endAction = distWalked_ >= maxDistanceToWalk_;
-        }
+        distWalked_ += distanceToWalk;
+        endAction = distWalked_ >= maxDistanceToWalk_;
+    } else {
+        // just keep moving
+        pPed->moveToDir(pMission,
+                        elapsed,
+                        moveDirdesc_);
     }
 
     if (endAction) {
index 9bd8b7e3359c5daa982a3fa943363e0288c2850d..128c7a0592cdb89dc9d42f918309557df9670053 100644 (file)
@@ -107,8 +107,12 @@ namespace fs_actions {
         //! Entry point to execute the action
         virtual bool execute(int elapsed, Mission *pMission, PedInstance *pPed) = 0;
 
+        //! Returns origin of the action
+        CreatOrigin origin() { return origin_; }
         //! Returns the type of action
         ActionType type() { return type_; }
+        //! Returns true if action is running
+        bool isRunning() { return status_ == kActStatusRunning; }
         //! Returns true if action is waiting for animation to end
         bool isWaitingForAnimation() { return status_ == kActStatusWaitForAnim; }
         //! Returns true if action has succeeded or failed
@@ -122,6 +126,9 @@ namespace fs_actions {
         void setSucceeded() { status_ = kActStatusSucceeded; }
         //! Sets the status to Failed
         void setFailed() { status_ = kActStatusFailed; }
+
+        //! Reset the action
+        virtual void reset();
         
     protected:
         /*! The type of action.*/
@@ -219,7 +226,7 @@ namespace fs_actions {
         //! Walk to direction given by point
         WalkToDirectionAction(CreatOrigin origin, const PathNode &pn);
         //! Walk following ped's direction
-        WalkToDirectionAction(CreatOrigin origin);
+        WalkToDirectionAction(CreatOrigin origin, int speed = -1);
 
         void setmaxDistanceToWalk(int distance) { maxDistanceToWalk_ = distance; }
     protected:
@@ -233,6 +240,8 @@ namespace fs_actions {
         /*! Count the distance the ped has walked since starting the action.*/
         int distWalked_;
         int maxDistanceToWalk_;
+        /*! Speed used to walk to destination.*/
+        int newSpeed_;
     };
 
     /*!
index 50d5936ae51c20625d43635f2e0cf5323091e617..6d2d2bfbdd3bcefbb6f1cc807ee7baf5d2d7bea5 100644 (file)
 #include "ped.h"
 #include "mission.h"
 
-const int PersuaderBehaviourComponent::kMaxDistanceForPersuadotron = 50;
+//*************************************
+// Constant definition
+//*************************************
+const int PersuaderBehaviourComponent::kMaxDistanceForPersuadotron = 100;
 const int CommonAgentBehaviourComponent::kRegeratesHealthStep = 1;
+const int PanicComponent::kScoutDistance = 2000;
+const int PanicComponent::kDistanceToRun = 500;
 
 Behaviour::~Behaviour() {
     while(compLst_.size() != 0) {
@@ -133,3 +138,97 @@ void PersuaderBehaviourComponent::handleBehaviourEvent(Behaviour::BehaviourEvent
         doUsePersuadotron_ = false;
     }
 }
+
+PanicComponent::PanicComponent():
+        BehaviourComponent(), scoutTimer_(500) {
+    panicking_ = false;
+    pDefaultAction_ = NULL;
+}
+
+void PanicComponent::execute(int elapsed, Mission *pMission, PedInstance *pPed) {
+    if (pPed->isPanicImmuned()) {
+        return;
+    }
+
+    // True means ped must check if someone's armed around him
+    bool checkArmedPed = false;
+    fs_actions::MovementAction *pAction = pPed->currentAction();
+
+    if (pAction == NULL) {
+        // No action means that ped has finished running
+        // but we are still in panic mode, so check if there are armed people nearby
+        checkArmedPed = true;
+    } else if (!panicking_) {
+        // ped is walking calmly -> check if he should panic
+        if (scoutTimer_.update(elapsed)) {
+            checkArmedPed = true;
+        }
+    }
+
+    if (checkArmedPed) {
+        PedInstance *pArmedPed = findNearbyArmedPed(pMission, pPed);
+        if (pArmedPed) {
+            printf("Panic : %d\n", pPed->id());
+            runAway(pPed, pArmedPed, pAction);
+        } else if (pAction == NULL) {
+            // ped has finished panicking and there no reason to panick
+            // so continue walking normaly
+            pPed->addMovementAction(pDefaultAction_, false);
+            panicking_ = false;
+            printf("End Panic : %d\n", pPed->id());
+        }
+    }
+}
+
+void PanicComponent::handleBehaviourEvent(Behaviour::BehaviourEvent evtType, PedInstance *pPed) {
+    /*switch(evtType) {
+    case Behaviour::kBehvEvtPersuadotronActivated:
+        doUsePersuadotron_ = true;
+        break;
+    case Behaviour::kBehvEvtPersuadotronDeactivated:
+        doUsePersuadotron_ = false;
+    }*/
+}
+
+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)) {
+            return pOtherPed;
+        }
+    }
+    return NULL;
+}
+
+/*!
+ * Makes the ped runs in the opposite way of the armed ped.
+ * Saves the default action so it can be restored when the ped
+ * don't panic anymore.
+ * \param pPed The panicking ped
+ * \param pArmedPed The armed ped that caused the panic
+ * \param pWalkAction The action the ped was doing before panicking
+ */
+void  PanicComponent::runAway(PedInstance *pPed, PedInstance *pArmedPed, fs_actions::MovementAction *pWalkAction) {
+    // setting opposite direction for movement
+    toDefineXYZ thisPedLoc;
+    toDefineXYZ otherLoc;
+    pPed->convertPosToXYZ(&thisPedLoc);
+    pArmedPed->convertPosToXYZ(&otherLoc);
+    
+    pPed->setDirection(otherLoc.x - thisPedLoc.x,
+        otherLoc.y - thisPedLoc.y);
+    // Adds the action of running away
+    fs_actions::WalkToDirectionAction *pAction = 
+        new fs_actions::WalkToDirectionAction(fs_actions::kOrigAction, 256);
+    // walk for a certain distance
+    pAction->setmaxDistanceToWalk(kDistanceToRun);
+    pPed->addMovementAction(pAction, false);
+    panicking_ = true;
+
+    if (pWalkAction != NULL) {
+        // save and reset the default action
+        pDefaultAction_ = pWalkAction;
+        pDefaultAction_->reset();
+    }
+}
index cad4469b7eba15963d921c77fad611c3c220d3fb..a4f34b61ff9494668858a09d85495d7bdcd6c381 100644 (file)
@@ -27,6 +27,7 @@
 #include <list>
 
 #include "utils/timer.h"
+#include "ia/actions.h"
 
 class Mission;
 class PedInstance;
@@ -129,4 +130,37 @@ private:
     bool doUsePersuadotron_;
 };
 
+/*!
+ * Component for civilians who can panic when a gun is out.
+ * Civilians in cars and which have scripted actions don't panic.
+ * Civilians who have this component should only have one defaut action:
+ * walk continuously.
+ */
+class PanicComponent : public BehaviourComponent {
+public:
+    //! Range for looking for armed ped
+    static const int kScoutDistance;
+    //! The distance a panicking ped walks before calming down
+    static const int kDistanceToRun;
+
+    PanicComponent();
+
+    void execute(int elapsed, Mission *pMission, PedInstance *pPed);
+
+    void handleBehaviourEvent(Behaviour::BehaviourEvent evtType, PedInstance *pPed);
+private:
+    //! Checks whether there is an armed ped next to the ped : returns that ped
+    PedInstance * findNearbyArmedPed(Mission *pMission, PedInstance *pPed);
+    //! Makes the ped runs in the opposite direction from the armed ped
+    void  runAway(PedInstance *pPed, PedInstance *pArmedPed, fs_actions::MovementAction *pAction);
+private:
+    /*! This timer is used to delay checking by the ped in order to 
+     * not consume too much CPU.*/
+    fs_utils::Timer scoutTimer_;
+    /*! True when ped is currently in panic.*/
+    bool panicking_;
+    /*! */
+    fs_actions::MovementAction *pDefaultAction_;
+};
+
 #endif // IA_BEHAVIOUR_H_
\ No newline at end of file
index 3cd63941e36a9f0c3789ce7b779ea27c4dc5dc58..534e061436232843ec7677f97fd27c055967fb4e 100644 (file)
@@ -76,7 +76,7 @@ public:
         dmg_Persuasion = 0x0020,
         dmg_Heal = 0x0040,
         dmg_Panic = 0x0080,
-        dmg_Mental = (dmg_Persuasion | dmg_Panic),
+        // dmg_Mental = (dmg_Persuasion | dmg_Panic), not used
         dmg_All = 0xFFFF
     };
 
index 199e43e9710f615d83e25a558415779431769794..41c17e1a73508da4f53681f16ff3901e2eece6af 100644 (file)
@@ -775,7 +775,7 @@ void GameplayMenu::handleClickOnMap(int x, int y, int button, const int modKeys)
 
         if (target_) {
             printf("   > target(%i) : %s\n",
-                target_->getDebugID(), target_->natureName());
+                target_->id(), target_->natureName());
         }
         return;
     }
index cae8ddd2b28652b5bfb0105c2088ec59bbb54f65..b20eef3bef001d0173fad5d095ffec2a99aef541 100644 (file)
@@ -912,7 +912,7 @@ void MissionManager::createObjectives(const LevelData::LevelDataAll &level_data,
                     if ((cindx * 92 + 2) == bindx && di.pindx[cindx] != 0xFFFF) {
                         PedInstance *p = pMission->ped(di.pindx[cindx]);
                         objd = new ObjPersuade(p);
-                        p->setRcvDamageDef(MapObject::ddmg_PedPanicImmune);
+                        p->setPanicImmuned();
                         // Adds the ped to the list of peds to evacuate
                         peds_evacuate.push_back(p);
                     } else
@@ -925,7 +925,7 @@ void MissionManager::createObjectives(const LevelData::LevelDataAll &level_data,
                     cindx = (bindx - 2) / 92;
                     if ((cindx * 92 + 2) == bindx && di.pindx[cindx] != 0xFFFF) {
                         PedInstance *p = pMission->ped(di.pindx[cindx]);
-                        p->setRcvDamageDef(MapObject::ddmg_PedPanicImmune);
+                        p->setPanicImmuned();
                         objd = new ObjAssassinate(p);
                     } else
                         printf("0x02 incorrect offset");
@@ -937,7 +937,7 @@ void MissionManager::createObjectives(const LevelData::LevelDataAll &level_data,
                     cindx = (bindx - 2) / 92;
                     if ((cindx * 92 + 2) == bindx && di.pindx[cindx] != 0xFFFF) {
                         PedInstance *p = pMission->ped(di.pindx[cindx]);
-                        p->setRcvDamageDef(MapObject::ddmg_PedPanicImmune);
+                        p->setPanicImmuned();
                         objd = new ObjProtect(p);
                     } else
                         printf("0x03 incorrect offset");
index 03e4c20174259f346455731b5c4ae61ec1333ab5..6e5ded4419a71084c8d031628fd7d0fcc07a99d7 100644 (file)
@@ -2087,6 +2087,7 @@ PedInstance::PedInstance(Ped *ped, uint16 id, int m, bool isOur) :
     behaviour_.setOwner(this);
     currentAction_ = NULL;
     pUseWeaponAction_ = NULL;
+    panicImmuned_ = false;
 }
 
 PedInstance::~PedInstance()
@@ -2676,7 +2677,7 @@ void PedInstance::handlePersuadedBy(PedInstance *pAgent) {
         addDefActsToActions();
 
         setDrawnAnim(PedInstance::ad_PersuadedAnim);
-        setRcvDamageDef(MapObject::ddmg_PedPanicImmune);
+        setPanicImmuned();
         g_App.gameSounds().play(snd::PERSUADE);
     }
 }
index a017f817891f6d581b43385fb68a24c0c253af39..02ffa12f3beb019ffb18033aec07aa66dfa1ef2a 100644 (file)
@@ -216,6 +216,10 @@ public:
     bool hasEscaped() { return IS_FLAG_SET(desc_state_, pd_smEscaped); }
     //! Indicate that the ped has escaped
     void escape() { SET_FLAG(desc_state_, pd_smEscaped); }
+    //! Return true if ped don't panic
+    bool isPanicImmuned() { return panicImmuned_; }
+    //! Tells the ped not to panic
+    void setPanicImmuned() { panicImmuned_ = true; }
 
     typedef enum {
         ad_NoAnimation,
@@ -301,6 +305,8 @@ public:
     //*************************************
     //! Adds the given action to the list of actions
     void addMovementAction(fs_actions::MovementAction *pAction, bool appendAction);
+    //! Returns the ped's current movement action
+    fs_actions::MovementAction * currentAction() { return currentAction_; }
     //! Removes all ped's actions
     void destroyAllActions();
     //! Removes ped's action of using weapon
@@ -955,6 +961,8 @@ protected:
     //! points needed to persuade ped
     int persuasion_points_;
     std::set <PedInstance *> persuaded_group_;
+    //! Tells whether the panic can react to panic or not
+    bool panicImmuned_;
 
     bool walkable(int x, int y, int z) { return true; }
 
index 7b6d1c48d9160f95a72e37afb6be9c3547567db4..15ce02dddc7f18f2fda66a043da318cf7f0d1186 100644 (file)
@@ -41,7 +41,12 @@ void PedInstance::addMovementAction(fs_actions::MovementAction *pAction, bool ap
         }
         pAct->setNext(pAction);
     } else {
-        destroyAllActions();
+        if (currentAction_->origin() != fs_actions::kOrigScript &&
+            currentAction_->origin() != fs_actions::kOrigDefault) {
+            // for scripted and default actions, just forget reference
+            // actions will be reused
+            destroyAllActions();
+        }
         currentAction_ = pAction;
     }
 }
index 213089265d9ac0cf841efae2f05449a15dfb652a..b7d1b7b2abad481f9dd5f0168e061af2682e139f 100644 (file)
@@ -333,6 +333,8 @@ void PedManager::initCivilian(PedInstance *pPed) {
     pPed->setTimeBeforeCheck(600);
     pPed->setBaseModAcc(0.2);
     pPed->setPersuasionPoints(1);
+
+    pPed->behaviour().addComponent(new PanicComponent());
 } 
 
 /*!