Persuasion work
authorbenblan <benblan@3ce38193-f967-438d-acd5-fc4e68e0da95>
Mon, 22 Sep 2014 11:34:35 +0000 (11:34 +0000)
committerbenblan <benblan@3ce38193-f967-438d-acd5-fc4e68e0da95>
Mon, 22 Sep 2014 11:34:35 +0000 (11:34 +0000)
- Persuaded peds now follow owner
- Replaced unused state pa_smLeaveCar by new state pa_smHitByPersuadotron
- removed unused method PedInstance::createActQLeaveCar()
- Method PedInstance::insertHitAction() is now public
- Persuasion animation is now activated by set state to pa_smHitByPersuadotron
- PedInstance::handlePersuadedBy() is now called from new action PersuadedHitAction
- Removed unuesed method Weapon::doesMentalDmg()
- new class PersuadedBehaviourComponent (not finished)

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/menus/squadselection.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/vehicle.cpp
freesynd/branches/rework-actions/src/weapon.h

index 7eaaf03225df16cecce87e3963a9237bc79a0940..f3b4d41f1290096c65edd7bf5af7b26cb3e46457 100644 (file)
@@ -26,6 +26,7 @@
  ************************************************************************/
 
 #include "ia/actions.h"
+#include "app.h"
 #include "ped.h"
 #include "weapon.h"
 #include "vehicle.h"
@@ -302,8 +303,8 @@ bool EscapeAction::doExecute(int elapsed, Mission *pMission, PedInstance *pPed)
  * Class constructor.
  * \param pTarget The ped to follow.
  */
-FollowAction::FollowAction(PedInstance *pTarget) :
-MovementAction(kActTypeUndefined, kOrigUser) {
+FollowAction::FollowAction(fs_actions::CreatOrigin origin, PedInstance *pTarget) :
+MovementAction(kActTypeUndefined, origin) {
     pTarget_ = pTarget;
     targetState_ = PedInstance::pa_smWalking;
 }
@@ -608,6 +609,36 @@ bool WalkBurnHitAction::doExecute(int elapsed, Mission *pMission, PedInstance *p
     return true;
 }
 
+PersuadedHitAction::PersuadedHitAction(ShootableMapObject::DamageInflictType &d) : 
+HitAction(kOrigAction, d) {
+    targetState_ = PedInstance::pa_smHitByPersuadotron;
+}
+
+/*!
+ * 
+ * \param pMission Mission data
+ * \param pPed The ped executing the action.
+ */
+void PersuadedHitAction::doStart(Mission *pMission, PedInstance *pPed) {
+    status_ = kActStatusWaitForAnim;
+    g_App.gameSounds().play(snd::PERSUADE);
+}
+
+/*!
+ * 
+ * \param elapsed Time elapsed since last frame
+ * \param pMission Mission data
+ * \param pPed The ped executing the action.
+ */
+bool PersuadedHitAction::doExecute(int elapsed, Mission *pMission, PedInstance *pPed) {
+    if (status_ == kActStatusRunning) {
+        PedInstance *pAgent = static_cast<PedInstance *>(damage_.d_owner);
+        pPed->handlePersuadedBy(pAgent);
+        setSucceeded();
+    }
+    return true;
+}
+
 ShootAction::ShootAction(CreatOrigin origin, PathNode &aimedAt, WeaponInstance *pWeapon) : 
     UseWeaponAction(origin, kActTypeShoot, pWeapon) {
         aimedAt_ = aimedAt;
index ab585ef6a938d364be08b8d8fbab013ab8920dd3..707fb17e38115e73d101bcaeb661e0ee55ea72dc 100644 (file)
@@ -294,7 +294,7 @@ namespace fs_actions {
     class FollowAction : public MovementAction {
     public:
         //! Walt to given point
-        FollowAction(PedInstance *pTarget);
+        FollowAction(fs_actions::CreatOrigin origin, PedInstance *pTarget);
 
     protected:
         void doStart(Mission *pMission, PedInstance *pPed);
@@ -459,6 +459,18 @@ namespace fs_actions {
         fs_utils::Timer burnTimer_;
     };
 
+    /*!
+     * This action is used to represent a hit by a laser.
+     */
+    class PersuadedHitAction : public HitAction {
+    public:
+        //! 
+        PersuadedHitAction(ShootableMapObject::DamageInflictType &d);
+    protected:
+        void doStart(Mission *pMission, PedInstance *pPed);
+        bool doExecute(int elapsed, Mission *pMission, PedInstance *pPed);
+    };
+
     /*!
      * This action is for using a weapon. A ped can only have a single weapon action
      * at a given time.
index a4448f492e884770c6a9730a5cc42e432b925d1a..889ae2d5a92f7d3b90ed0d0396d96ad2e5f00eda 100644 (file)
@@ -38,6 +38,10 @@ const int PanicComponent::kScoutDistance = 1500;
 const int PanicComponent::kDistanceToRun = 500;
 
 Behaviour::~Behaviour() {
+    destroyComponents();
+}
+
+void Behaviour::destroyComponents() {
     while(compLst_.size() != 0) {
         BehaviourComponent *pComp = compLst_.front();
         compLst_.pop_front();
@@ -56,6 +60,14 @@ void Behaviour::addComponent(BehaviourComponent *pComp) {
     compLst_.push_back(pComp);
 }
 
+/*!
+ * Destroy existing components and set given one as new one
+ */
+void Behaviour::replaceAllcomponentsBy(BehaviourComponent *pComp) {
+    destroyComponents();
+    addComponent(pComp);
+}
+
 /*!
  * Run the execute method  of each component listed in the behaviour.
  * Component must be enabled.
@@ -118,7 +130,10 @@ void PersuaderBehaviourComponent::execute(int elapsed, Mission *pMission, PedIns
         for (size_t i = pMission->getSquad()->size(); i < pMission->numPeds(); i++) {
             PedInstance *pOtherPed = pMission->ped(i);
             if (pPed->canPersuade(pOtherPed)) {
-                pOtherPed->handlePersuadedBy(pPed);
+                ShootableMapObject::DamageInflictType dmg;
+                dmg.dtype = MapObject::dmg_Persuasion;
+                dmg.d_owner = pPed;
+                pOtherPed->insertHitAction(dmg);
             }
         }
     }
@@ -134,6 +149,25 @@ void PersuaderBehaviourComponent::handleBehaviourEvent(Behaviour::BehaviourEvent
     }
 }
 
+PersuadedBehaviourComponent::PersuadedBehaviourComponent():
+        BehaviourComponent(), checkWeaponTimer_(1000) {
+
+}
+
+void PersuadedBehaviourComponent::execute(int elapsed, Mission *pMission, PedInstance *pPed) {
+    // To be completed
+    if (checkWeaponTimer_.update(elapsed)) {
+        WeaponInstance *pWeapon = pPed->selectedWeapon();
+        if (pWeapon && pWeapon->ammoRemaining() == 0) {
+            pPed->addActionPutdown(0, false);
+        }
+    }
+}
+
+void PersuadedBehaviourComponent::handleBehaviourEvent(Behaviour::BehaviourEvent evtType, PedInstance *pPed) {
+
+}
+
 PanicComponent::PanicComponent():
         BehaviourComponent(), scoutTimer_(500) {
     panicking_ = false;
index 1f2e6004c3ab8a68892ead052d81bf0482ebb26d..8b668cfd097af19b5e3f8f3fe6f94329dc84c27e 100644 (file)
@@ -63,10 +63,14 @@ public:
     void setOwner(PedInstance *pPed) { pThisPed_ = pPed; }
     //! Adds a component to the behaviour
     void addComponent(BehaviourComponent *pComp);
+    //! Destroy existing components and set given one as new one
+    void replaceAllcomponentsBy(BehaviourComponent *pComp);
 
     virtual void execute(int elapsed, Mission *pMission);
 
     virtual void handleBehaviourEvent(BehaviourEvent evtType);
+protected:
+    void destroyComponents();
 protected:
     /*! The ped that use this behaviour.*/
     PedInstance *pThisPed_;
@@ -131,6 +135,21 @@ private:
     bool doUsePersuadotron_;
 };
 
+/*!
+ * Component for user of Persuadotron. Only our agents use this component.
+ */
+class PersuadedBehaviourComponent : public BehaviourComponent {
+public:
+    PersuadedBehaviourComponent();
+
+    void execute(int elapsed, Mission *pMission, PedInstance *pPed);
+
+    void handleBehaviourEvent(Behaviour::BehaviourEvent evtType, PedInstance *pPed);
+private:
+    //! used for delaying checking of nearby weapon search
+    fs_utils::Timer checkWeaponTimer_;
+};
+
 /*!
  * Component for civilians who can panic when a gun is out.
  * Civilians in cars and which have scripted actions don't panic.
index b52224d66d91f483d528d41833fd14672c856e39..079fee4a72cda8716fa39cca8d4688505c0f16c7 100644 (file)
@@ -227,13 +227,7 @@ void SquadSelection::followPed(PedInstance *pPed, bool addAction) {
     {
         PedInstance *pAgent = *it;
         if (!pAgent->inVehicle()) { // Agent must not be in a vehicle
-            /*PedInstance::actionQueueGroupType as;
-            pAgent->createActQFollowing(as, pPed, 0, 192);
-            as.main_act = as.actions.size() - 1;
-            as.group_desc = PedInstance::gd_mStandWalk;
-            as.origin_desc = fs_actions::kOrigUser;
-            pAgent->addAction(as, addAction);*/
-            pAgent->addActionFollowPed(pPed);
+            pAgent->addActionFollowPed(fs_actions::kOrigUser, pPed);
         }
     }
 }
index b60fda3a38118ce9f3d8e05e61f3c1b9f2f94544..3b58aa8126260af5896568b95095b2251dcc55f8 100644 (file)
@@ -227,6 +227,9 @@ bool PedInstance::switchActionStateTo(uint32 as) {
         case pa_smHitByLaser:
             state_ = pa_smHitByLaser;
             break;
+        case pa_smHitByPersuadotron:
+            state_ = pa_smHitByPersuadotron;
+            break;
         case pa_smFiring:
             state_ |= pa_smFiring;
             break;
@@ -252,9 +255,6 @@ bool PedInstance::switchActionStateTo(uint32 as) {
         case pa_smInCar:
             state_ = pa_smStanding | pa_smInCar;
             break;
-        case pa_smLeaveCar:
-            state_ = pa_smStanding | pa_smLeaveCar;
-            break;
         case pa_smDead:
             state_ = pa_smDead;
             break;
@@ -284,6 +284,7 @@ bool PedInstance::switchActionStateFrom(uint32 as) {
             break;
         case pa_smHit:
         case pa_smHitByLaser:
+        case pa_smHitByPersuadotron:
             state_ = pa_smStanding;
             break;
         case pa_smFiring:
@@ -312,9 +313,6 @@ bool PedInstance::switchActionStateFrom(uint32 as) {
         case pa_smInCar:
             state_ &= pa_smAll ^ (pa_smStanding | pa_smInCar);
             break;
-        case pa_smLeaveCar:
-            state_ = pa_smStanding;
-            break;
         case pa_smDead:
             state_ = pa_smDead;
 #ifdef _DEBUG
@@ -359,6 +357,8 @@ void PedInstance::setActionStateToDrawnAnim(void) {
         setDrawnAnim(PedInstance::ad_HitAnim);
     } else if ((state_ & pa_smHitByLaser) != 0) {
         setDrawnAnim(PedInstance::ad_VaporizeAnim);
+    } else if (IS_FLAG_SET(state_, pa_smHitByPersuadotron)) {
+        setDrawnAnim(PedInstance::ad_PersuadedAnim);
     }
 #ifdef _DEBUG
     if (state_ ==  pa_smNone)
@@ -3071,6 +3071,12 @@ uint16 PedInstance::getRequiredPointsToPersuade(PedType type) {
  * \param pOtherPed Ped to persuade.
  */
 bool PedInstance::canPersuade(PedInstance *pOtherPed) {
+    fs_actions::Action *pAction = pOtherPed->currentAction();
+    if (pAction != NULL && pAction->type() == fs_actions::Action::kActTypeHit) {
+        // cannot persuade a ped if he's currently being hit
+        return false;
+    }
+
     if (!pOtherPed->isPersuaded() && pOtherPed->isAlive() &&
             isCloseTo(pOtherPed, kMaxDistanceForPersuadotron)) {
         uint16 points = getRequiredPointsToPersuade(pOtherPed->type());
@@ -3086,32 +3092,23 @@ bool PedInstance::canPersuade(PedInstance *pOtherPed) {
  */
 void PedInstance::handlePersuadedBy(PedInstance *pAgent) {
     pAgent->addPersuaded(this);
+    SET_FLAG(desc_state_, pd_smControlled);
     setObjGroupID(pAgent->objGroupID());
-    pAgent->cpyEnemyDefs(enemy_group_defs_);
-    dropActQ();
     owner_ = pAgent;
-    desc_state_ |= pd_smControlled;
+    setPanicImmuned();
+
+    clearDestination();
+    destroyAllActions(true);
+    // set follow owner as new default
+    addActionFollowPed(fs_actions::kOrigDefault, pAgent);
+    behaviour_.replaceAllcomponentsBy(new PersuadedBehaviourComponent());
+
+    /////////////////// Check if still useful ////////////
+    pAgent->cpyEnemyDefs(enemy_group_defs_);
     friends_found_.clear();
     hostiles_found_.clear();
     hostile_desc_ = pAgent->hostileDesc();
-
-    // adding following behavior
-    PedInstance::actionQueueGroupType as;
-    as.group_id = 0;
-    as.group_desc = PedInstance::gd_mExclusive;
-    createActQWait(as, 2000);
-    as.main_act = as.actions.size() - 1;
-    as.origin_desc = fs_actions::kOrigEvent;
-    actions_queue_.push_back(as);
-
-    default_actions_.clear();
-    createDefQueue();
-
-    addDefActsToActions();
-
-    setDrawnAnim(PedInstance::ad_PersuadedAnim);
-    setPanicImmuned();
-    g_App.gameSounds().play(snd::PERSUADE);
+    //////////////////////////////////////////////////////
 }
 
 /*! 
index ab660913b349b5969a24bf4fdf032fb397559a24..4a5d0d11d5a214e86a71e27ff05d902ba1237b8c 100644 (file)
@@ -262,7 +262,7 @@ public:
         pa_smUsingCar = 0x0200,
         // passenger only
         pa_smInCar = 0x0400,
-        pa_smLeaveCar = 0x0800,
+        pa_smHitByPersuadotron = 0x0800,
         pa_smDead = 0x1000,
         // this object should be ignored in all Ai procedures
         pa_smUnavailable = 0x2000,
@@ -324,7 +324,7 @@ public:
     //! Adds a trigger to the actions
     void addActionTrigger(int32 range, const PathNode &loc);
     //! Adds action to follow a ped
-    void addActionFollowPed(PedInstance *pPed);
+    void addActionFollowPed(fs_actions::CreatOrigin origin, PedInstance *pPed);
     //! Adds action to put down weapon on the ground
     void addActionPutdown(uint8 weaponIndex, bool appendAction);
     //! Adds action to pick up weapon from the ground
@@ -341,6 +341,8 @@ public:
     void addActionShootAt(const PathNode &aimedPt);
     //! Adds action to use medikit
     void addActionUseMedikit();
+    //! Creates and insert a HitAction for the ped
+    void insertHitAction(DamageInflictType &d);
 
     //*************************************
     // Movement management
@@ -849,8 +851,6 @@ public:
         ShootableMapObject *tsmo, int32 dir = -1);
     void createActQUsingCar(actionQueueGroupType &as, PathNode *tpn,
         ShootableMapObject *tsmo);
-    void createActQLeaveCar(actionQueueGroupType &as,
-        ShootableMapObject *tsmo);
     void createActQWait(actionQueueGroupType& as, int tm_wait,
         uint8 desc = 0);
 
@@ -907,9 +907,6 @@ protected:
      */
     void handleWeaponSelected(WeaponInstance * wi);
 
-    //! Creates and insert a HitAction for the ped
-    void insertHitAction(DamageInflictType &d);
-
     //! Returns the number of points an agent must have to persuade a ped of given type
     uint16 getRequiredPointsToPersuade(PedType type);
     //! When a ped dies, changes the persuaded owner/persuaded_group relation.
index 8d7b93cb54715bd2325abd6083ded2ebb927dbb1..befae250e683be430810a8c68d9448b2cfe5c0a5 100644 (file)
@@ -144,8 +144,8 @@ void PedInstance::addActionTrigger(int32 range, const PathNode & loc) {
     addMovementAction(action, true);
 }
 
-void PedInstance::addActionFollowPed(PedInstance *pPed) {
-    fs_actions::FollowAction *pAction = new fs_actions::FollowAction(pPed);
+void PedInstance::addActionFollowPed(fs_actions::CreatOrigin origin, PedInstance *pPed) {
+    fs_actions::FollowAction *pAction = new fs_actions::FollowAction(origin, pPed);
     addMovementAction(pAction, false);
 }
 
@@ -209,7 +209,7 @@ void PedInstance::insertHitAction(DamageInflictType &d) {
             // it's an explosion : walk and burn
             pHitAct = new fs_actions::WalkBurnHitAction(d);
         }
-    } else if (d.dtype & dmg_Explosion) {
+    } else if (d.dtype == dmg_Explosion) {
         if (hasMinimumVersionOfMod(Mod::MOD_CHEST, Mod::MOD_V2)) {
             pHitAct = new fs_actions::RecoilHitAction(d);
         } else {
@@ -218,11 +218,13 @@ void PedInstance::insertHitAction(DamageInflictType &d) {
     } else if (d.dtype & (dmg_Bullet | dmg_Collision)) {
         // When hit by a bullet or collision, ped is ejected
         pHitAct = new fs_actions::RecoilHitAction(d);
-    } else if (d.dtype & dmg_Burn) {
+    } else if (d.dtype == dmg_Burn) {
         pHitAct = new fs_actions::WalkBurnHitAction(d);
-    } else if (d.dtype & dmg_Laser) {
+    } else if (d.dtype == dmg_Laser) {
         // When hit by a laser, ped is vaporized
         pHitAct = new fs_actions::LaserHitAction(d);
+    } else if (d.dtype == dmg_Persuasion) {
+        pHitAct = new fs_actions::PersuadedHitAction(d);
     }
 
     if (pHitAct != NULL) {
@@ -578,20 +580,6 @@ void PedInstance::createActQUsingCar(actionQueueGroupType &as, PathNode *tpn,
     as.actions.push_back(aq);
 }
 
-void PedInstance::createActQLeaveCar(actionQueueGroupType &as,
-        ShootableMapObject *tsmo)
-{
-    as.state = 1;
-    actionQueueType aq;
-    aq.as = PedInstance::pa_smLeaveCar;
-    aq.act_exec = PedInstance::ai_aLoseControl;
-    aq.state = 1;
-    aq.target.desc = 2;
-    aq.target.t_smo = tsmo;
-    aq.group_desc = PedInstance::gd_mExclusive;
-    as.actions.push_back(aq);
-}
-
 void PedInstance::createActQWait(actionQueueGroupType &as, int tm_wait, uint8 desc)
 {
     as.state = 1;
index 36e8e9e4bde2ec2fc9075025b80ea5410aedede7..bc6bf6e5a741c72389d514f0653c39e9d9835c2b 100644 (file)
@@ -804,7 +804,7 @@ bool VehicleInstance::move_vehicle(int elapsed)
  * \param d Damage description
  */
 void VehicleInstance::handleHit(ShootableMapObject::DamageInflictType &d) {
-    if (health_ <= 0 || d.dtype == MapObject::dmg_Persuasion)
+    if (health_ <= 0)
         return;
 
     decreaseHealth(d.dvalue);
index 3e7747433bf3e94b5993050425253c95ff548673..c5d89b0c1f94e1dfd7ba0be3e2b98d48a88b6d28 100644 (file)
@@ -125,10 +125,6 @@ public:
         return (shot_property_ & Weapon::spe_CanShoot) != 0;
     }
 
-    bool doesMentalDmg() {
-        return (dmg_type_ & MapObject::dmg_Persuasion) != 0;
-    }
-
     bool doesPhysicalDmg() {
         return (dmg_type_ & MapObject::dmg_Physical) != 0;
     }
@@ -365,10 +361,6 @@ public:
         return pWeaponClass_->canShoot();
     }
 
-    bool doesMentalDmg() {
-        return pWeaponClass_->doesMentalDmg();
-    }
-
     bool doesPhysicalDmg() {
         return pWeaponClass_->doesPhysicalDmg();
     }