Persuasion work
authorbenblan <benblan@3ce38193-f967-438d-acd5-fc4e68e0da95>
Wed, 17 Sep 2014 04:33:57 +0000 (04:33 +0000)
committerbenblan <benblan@3ce38193-f967-438d-acd5-fc4e68e0da95>
Wed, 17 Sep 2014 04:33:57 +0000 (04:33 +0000)
* Refactored persuasion methods
* Mission::playersGroupId has been replaced by constant PedInstance::kPlayerGroupId
* Generaliztion of use of method PedInstance::isPersuaded()
* Renamed PedInstance::persuasion_points_ in PedInstance::totalPersuasionPoints_

freesynd/branches/rework-actions/src/ia/behaviour.cpp
freesynd/branches/rework-actions/src/ia/behaviour.h
freesynd/branches/rework-actions/src/menus/minimaprenderer.cpp
freesynd/branches/rework-actions/src/mission.cpp
freesynd/branches/rework-actions/src/mission.h
freesynd/branches/rework-actions/src/missionmanager.cpp
freesynd/branches/rework-actions/src/model/objectivedesc.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 52a0f5fc465116f6ad23075a41ef80b1689c7f46..a4448f492e884770c6a9730a5cc42e432b925d1a 100644 (file)
 #include "ia/behaviour.h"
 #include "ped.h"
 #include "mission.h"
+#include "core/squad.h"
 
 //*************************************
 // Constant definition
 //*************************************
-const int PersuaderBehaviourComponent::kMaxDistanceForPersuadotron = 100;
 const int CommonAgentBehaviourComponent::kRegeratesHealthStep = 1;
 const int PanicComponent::kScoutDistance = 1500;
 const int PanicComponent::kDistanceToRun = 500;
@@ -114,13 +114,11 @@ PersuaderBehaviourComponent::PersuaderBehaviourComponent():
 void PersuaderBehaviourComponent::execute(int elapsed, Mission *pMission, PedInstance *pPed) {
     // Check if Agent has selected his Persuadotron
     if (doUsePersuadotron_) {
-        for (size_t i = 0; i < pMission->numPeds(); i++) {
+        // iterate through all peds except our agents
+        for (size_t i = pMission->getSquad()->size(); i < pMission->numPeds(); i++) {
             PedInstance *pOtherPed = pMission->ped(i);
-            // Agent can only persuad peds from another group
-            if (pPed->objGroupID() != pOtherPed->objGroupID() &&
-                    pOtherPed->isAlive() &&
-                    pPed->isCloseTo(pOtherPed, kMaxDistanceForPersuadotron)) {
-                        pOtherPed->handlePersuadedBy(pPed);
+            if (pPed->canPersuade(pOtherPed)) {
+                pOtherPed->handlePersuadedBy(pPed);
             }
         }
     }
index ff0327a72dfc7e33a94014efc02f9a80189c1b47..1f2e6004c3ab8a68892ead052d81bf0482ebb26d 100644 (file)
@@ -121,9 +121,6 @@ private:
  */
 class PersuaderBehaviourComponent : public BehaviourComponent {
 public:
-    //! Amount of health regenerated each period
-    static const int kMaxDistanceForPersuadotron;
-
     PersuaderBehaviourComponent();
 
     void execute(int elapsed, Mission *pMission, PedInstance *pPed);
index 186cf7aa180efa6a799d2d979101aeeb3c2e3263..46f381a5a4f627fc16d824d2aac1034d7d012275 100644 (file)
@@ -567,8 +567,7 @@ void GamePlayMinimapRenderer::drawPedestrians(uint8 * a_minimap) {
         {
             int px = mapToMiniMapX(tx + 1, ox);
             int py = mapToMiniMapY(ty + 1, oy);
-            if (p_ped->isPersuaded())
-            {
+            if (p_ped->isPersuaded()) {
                 // col_Yellow circle with a black or lightgreen border (blinking)
                 uint8 borderColor = (mm_timer_ped.state()) ? fs_cmn::kColorLightGreen : fs_cmn::kColorBlack;
                 drawPedCircle(a_minimap, px, py, fs_cmn::kColorYellow, borderColor);
index 5420f5dced0faf4bee1f425736845c72dca76d01..6d8b81f4251005f8bfbd9cbfb65d5137e217da38 100644 (file)
@@ -72,7 +72,6 @@ Mission::Mission(const LevelData::MapInfos & map_infos)
     max_y_ = READ_LE_UINT16(map_infos.max_y) / 2;
     cur_objective_ = 0;
     p_minimap_ = NULL;
-    players_group_id_ = 1;
     p_squad_ = new Squad();
 }
 
index f7a745b3faf3486629dcb28bb2d360120e479393..094b0ded8da09ecd5656e11fbddf79852953f495 100644 (file)
@@ -250,7 +250,6 @@ public:
         bool checkTileOnly = false, double maxr = -1.0, double * distTo = NULL);
     void getInRangeAll(toDefineXYZ * cp, std::vector<ShootableMapObject *> & targets,
         uint8 mask, bool checkTileOnly = true, double maxr = -1.0);
-    uint32 playersGroupID() { return players_group_id_;}
 
     // map-tile surfaces
     // x + y * mmax_x_ + z * mmax_m_xy
@@ -309,11 +308,11 @@ protected:
 
     /*! Statistics : time, shots, ...*/
     MissionStats stats_;
-    // minimap in colours, map z = 0 tiles transformed based on
-    // walkdata->minimap_colours_ in function createMinimap
+    /*!
+     * minimap in colours, map z = 0 tiles transformed based on
+     * walkdata->minimap_colours_ in function createMinimap
+     */
     MiniMap *p_minimap_;
-   
-    uint32 players_group_id_;
     /*!
      * The squad selected for the mission. It contains only active agents.
      */
index 29158bc423025033062c3e68b3a524272d5d0997..a182b44a83be3ff6c1f61142ff33e96a5bf52385 100644 (file)
@@ -596,7 +596,7 @@ void MissionManager::createPeds(const LevelData::LevelDataAll &level_data, DataI
     std::map <uint32, std::string> obj_ids;
     // NOTE: not very useful way of remembering "Who is who"
     obj_ids[0] = "Undefined";
-    obj_ids[pMission->playersGroupID()] = "Players Agents or Persuaded";
+    obj_ids[PedInstance::kPlayerGroupId] = "Players Agents or Persuaded";
     obj_ids[2] = "Enemy Agents";
     obj_ids[3] = "Enemy Guards";
     obj_ids[4] = "Policemen";
@@ -608,7 +608,7 @@ void MissionManager::createPeds(const LevelData::LevelDataAll &level_data, DataI
         const LevelData::People & pedref = level_data.people[i];
         
         PedInstance *p =
-            peds.loadInstance(pedref, i, pMission->mapId(), pMission->playersGroupID());
+            peds.loadInstance(pedref, i, pMission->mapId(), PedInstance::kPlayerGroupId);
         if (p) {
             di.pindx[i] = pMission->numPeds();
             pMission->addPed(p);
index 159fd913d8cf5293a3a981d5689abb889d47da88..32dc6dc0703f121ed7d4928a6e0d0b42fc89a18e 100644 (file)
@@ -69,8 +69,7 @@ void ObjPersuade::evaluate(Mission *pMission) {
     {
         // Target is dead -> mission is failed
         endObjective(false);
-    } else if (p->isPersuaded())
-    {
+    } else if (p->isPersuaded()) {
         endObjective(true);
     }
 }
index 43cc0749f75ad6a1ee298951a4f7f6b47d4b711c..b60fda3a38118ce9f3d8e05e61f3c1b9f2f94544 100644 (file)
 #include "model/shot.h"
 #include "ia/behaviour.h"
 
+//*************************************
+// Constant definition
+//*************************************
 const int PedInstance::kAgentMaxHealth = 16;
 const int PedInstance::kDefaultShootReactionTime = 200;
+const int PedInstance::kMaxDistanceForPersuadotron = 100;
+const uint32 PedInstance::kPlayerGroupId = 1;
 
 Ped::Ped() {
     memset(stand_anims_, 0, sizeof(stand_anims_));
@@ -586,7 +591,7 @@ bool PedInstance::animate(int elapsed, Mission *mission) {
     }
 #if 0
 #ifdef _DEBUG
-    if ((desc_state_ & pd_smControlled) != 0) {
+    if (isPersuaded()) {
         for (uint32 indx = 0; indx < actions_queue_.size(); ++indx) {
             std::vector <actionQueueGroupType>::iterator it =
                 actions_queue_.begin() + indx;
@@ -1481,7 +1486,7 @@ bool PedInstance::animate(int elapsed, Mission *mission) {
                             it->main_act = std::distance(it->actions.begin(), searched);
                             if (obj_group_def_ == og_dmPolice
                                 // only non controlled will follow and wait
-                                && (desc_state_ & pd_smControlled) == 0)
+                                && !isPersuaded())
                             {
                                 // forcing showing a gun
                                 selectRequiredWeapon();
@@ -2075,7 +2080,7 @@ PedInstance::PedInstance(Ped *ped, uint16 id, int m, bool isOur) :
     obj_group_id_(0), old_obj_group_id_(0),
     drawn_anim_(PedInstance::ad_StandAnim),
     sight_range_(0), in_vehicle_(NULL),
-    owner_(NULL), persuasion_points_(0)
+    owner_(NULL)
 {
     hold_on_.wayFree = 0;
     rcv_damage_def_ = MapObject::ddmg_Ped;
@@ -2096,6 +2101,7 @@ PedInstance::PedInstance(Ped *ped, uint16 id, int m, bool isOur) :
     defaultAction_ = NULL;
     pUseWeaponAction_ = NULL;
     panicImmuned_ = false;
+    totalPersuasionPoints_ = 0;
 }
 
 PedInstance::~PedInstance()
@@ -2653,43 +2659,6 @@ bool PedInstance::handleDeath(Mission *pMission, ShootableMapObject::DamageInfli
     return health_ == 0;
 }
 
-/*!
- * Called when an agent tries to persuad this ped.
- * \param pAgent Agent trying to persuad
- */
-void PedInstance::handlePersuadedBy(PedInstance *pAgent) {
-    if (pAgent->canPersuade(persuasion_points_)) {
-
-        pAgent->addPersuaded(this);
-        setObjGroupID(pAgent->objGroupID());
-        pAgent->cpyEnemyDefs(enemy_group_defs_);
-        dropActQ();
-        owner_ = pAgent;
-        desc_state_ |= pd_smControlled;
-        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);
-    }
-}
-
 bool PedInstance::handleDamage(ShootableMapObject::DamageInflictType *d) {
     if (health_ <= 0 || rcv_damage_def_ == MapObject::ddmg_Invulnerable
         || (d->dtype & rcv_damage_def_) == 0)
@@ -2713,7 +2682,7 @@ bool PedInstance::handleDamage(ShootableMapObject::DamageInflictType *d) {
         clearDestination();
         destroyAllActions(true);
         switchActionStateTo(PedInstance::pa_smDead);
-        if ((desc_state_ & pd_smControlled) != 0 && owner_)
+        if (isPersuaded())
             owner_->rmvPersuaded(this);
 
         switch (d->dtype) {
@@ -2848,7 +2817,7 @@ bool PedInstance::isFriendWith(PedInstance *p) {
         return true;
     if (p->isInEmulatedGroupDef(obj_group_id_, obj_group_def_)) {
         if (obj_group_def_ == og_dmPolice
-            && (desc_state_ & pd_smControlled) == 0)
+            && !isPersuaded())
         {
             friends_not_seen_.insert(p);
         }
@@ -2931,7 +2900,7 @@ int PedInstance::getDefaultSpeed()
         speed_new = (int)((float)speed_new * adrenaline_->getMultiplier());
     }
 
-    if (desc_state_ == PedInstance::pd_smControlled) {
+    if (isPersuaded()) {
         speed_new *= owner_->getSpeedOwnerBoost();
         speed_new >>= 1;
     }
@@ -3053,47 +3022,116 @@ bool PedInstance::hasAccessCard()
         && pMod->getVersion() == Mod::MOD_V3 ? true : false;
 }
 
-bool PedInstance::isPersuaded()
-{
-    return (desc_state_ & pd_smControlled) != 0
-        && obj_group_id_ == g_Session.getMission()->playersGroupID();
-}
-
-bool PedInstance::canPersuade(int points) {
+/*!
+ * Returns the number of points an agent must have to persuade
+ * a ped of given type. Civilians or criminals are always persuaded.
+ * \param type The type of the ped to persuade.
+ */
+uint16 PedInstance::getRequiredPointsToPersuade(PedType type) {
     Mod *pMod = slots_[Mod::MOD_BRAIN];
-    if (pMod) {
-        switch (pMod->getVersion()) {
-            case Mod::MOD_V1:
-                // /=2
-                points >>= 1;
-                break;
-            case Mod::MOD_V2:
-                // *=4
-                points <<= 2;
-                points /= 3;
-                break;
-            case Mod::MOD_V3:
-                // /=4
-                points >>= 2;
-                break;
+    uint16 points = 0;
+    if (type == kPedTypeGuard) {
+        if (!pMod) {
+            points = 4;
+        } else if (pMod->getVersion() == Mod::MOD_V1) {
+            points = 2;
+        } else {
+            points = 1;
+        }
+    } else if (type == kPedTypePolice) {
+        if (!pMod) {
+            points = 8;
+        } else if (pMod->getVersion() == Mod::MOD_V1) {
+            points = 4;
+        } else if (pMod->getVersion() == Mod::MOD_V2) {
+            points = 3;
+        } else if (pMod->getVersion() == Mod::MOD_V3) {
+            points = 2;
+        }
+    } else if (type == kPedTypeAgent) {
+        if (!pMod) {
+            points = 32;
+        } else if (pMod->getVersion() == Mod::MOD_V1) {
+            points = 16;
+        } else if (pMod->getVersion() == Mod::MOD_V2) {
+            points = 11;
+        } else if (pMod->getVersion() == Mod::MOD_V3) {
+            points = 8;
         }
-        if (points == 0)
-            ++points;
     }
-    // always 1
-    int points_avail = 1;
-    for (std::set <PedInstance *>::iterator it = persuadedSet_.begin();
-         it != persuadedSet_.end(); ++it)
-    {
-        // NOTE: mods influence "to persuade" points, but not
-        // of already persuaded
-        points_avail += (*it)->persuasionPoints();
+
+    return points;
+}
+
+/*!
+ * Return true if this agent can persuade the given ped.
+ * A ped can be persuaded if he's not already persuaded or
+ * if its persuasion points are less or equal than the agent
+ * total persuasion points.
+ * \param pOtherPed Ped to persuade.
+ */
+bool PedInstance::canPersuade(PedInstance *pOtherPed) {
+    if (!pOtherPed->isPersuaded() && pOtherPed->isAlive() &&
+            isCloseTo(pOtherPed, kMaxDistanceForPersuadotron)) {
+        uint16 points = getRequiredPointsToPersuade(pOtherPed->type());
+        return points <= totalPersuasionPoints_;
     }
-    return points <= points_avail;
+
+    return false;
 }
 
+/*!
+ * Called when an agent tries to persuad this ped.
+ * \param pAgent Agent trying to persuad
+ */
+void PedInstance::handlePersuadedBy(PedInstance *pAgent) {
+    pAgent->addPersuaded(this);
+    setObjGroupID(pAgent->objGroupID());
+    pAgent->cpyEnemyDefs(enemy_group_defs_);
+    dropActQ();
+    owner_ = pAgent;
+    desc_state_ |= pd_smControlled;
+    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);
+}
+
+/*! 
+ * Adds given ped to the list of persuaded peds by this agent.
+ * Increments the persuasion points of this ped depending on the type
+ * of persuaded ped.
+ * \param p Persuaded ped
+ */
 void PedInstance::addPersuaded(PedInstance *p) {
     persuadedSet_.insert(p);
+    switch(p->type()) {
+    case kPedTypeGuard:
+        totalPersuasionPoints_ +=  3;
+    case kPedTypePolice:
+        totalPersuasionPoints_ +=  4;
+    case kPedTypeAgent:
+        totalPersuasionPoints_ +=  32;
+    default:
+        totalPersuasionPoints_ +=  1;
+    }
 }
 
 void PedInstance::rmvPersuaded(PedInstance *p) {
@@ -3110,7 +3148,7 @@ void PedInstance::rmvPersuaded(PedInstance *p) {
  * \param pSquad List of available agents
  */
 void PedInstance::updatePersuadedRelations(Squad *pSquad) {
-    if (IS_FLAG_SET(desc_state_, pd_smControlled) && owner_ != NULL) {
+    if (isPersuaded()) {
         owner_->rmvPersuaded(this);
         owner_ = NULL;
     } else if (isOurAgent()) {
index e6c6a61e0dc98ae877c16db359352951cd2c49ea..ab660913b349b5969a24bf4fdf032fb397559a24 100644 (file)
@@ -167,6 +167,8 @@ public:
     static const int kAgentMaxHealth;
     //! Default time for a ped between two shoots
     static const int kDefaultShootReactionTime;
+    //! Id of the group for the player's agents
+    static const uint32 kPlayerGroupId;
     /*!
      * Type of Ped.
      */
@@ -279,12 +281,6 @@ public:
     void setSightRange(int new_sight_range) { sight_range_ = new_sight_range; }
     int sightRange() { return sight_range_; }
 
-    void setPersuasionPoints(int points) { persuasion_points_ = points; }
-    int persuasionPoints() {return persuasion_points_; }
-    bool canPersuade(int points);
-    void addPersuaded(PedInstance *p);
-    void rmvPersuaded(PedInstance *p);
-
     void showPath(int scrollX, int scrollY);
 
     bool switchActionStateTo(uint32 as);
@@ -391,7 +387,18 @@ public:
     bool handleDeath(Mission *pMission, ShootableMapObject::DamageInflictType &d);
     bool handleDamage(ShootableMapObject::DamageInflictType *d);
 
-    //! Method called when an agent try to persuad this ped
+    //*************************************
+    // Persuasion
+    //*************************************
+    //! Return true if ped is persuaded
+    bool isPersuaded() { return IS_FLAG_SET(desc_state_, pd_smControlled); }
+    //! Returns true if this ped can persuade that ped
+    bool canPersuade(PedInstance *pOtherPed);
+    //! Adds given ped to the list of persuaded peds by this agent
+    void addPersuaded(PedInstance *p);
+    //! Removes given ped to the list of persuaded peds by this agent
+    void rmvPersuaded(PedInstance *p);
+    //! Method called when an agent persuads this ped
     void handlePersuadedBy(PedInstance *pAgent);
 
     bool inSightRange(MapObject *t);
@@ -874,7 +881,6 @@ public:
 
     void getAccuracy(double &base_acc);
     bool hasAccessCard();
-    bool isPersuaded();
 
     void cpyEnemyDefs(Mmuu32_t &eg_defs) { eg_defs = enemy_group_defs_; }
     bool isArmed() { return (desc_state_ & pd_smArmed) != 0; }
@@ -904,9 +910,14 @@ protected:
     //! 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.
     void updatePersuadedRelations(Squad *pSquad);
 protected:
+    //! Distance to persuade a ped
+    static const int kMaxDistanceForPersuadotron;
+
     Ped *ped_;
     //! Type of Ped
     PedType type_;
@@ -969,8 +980,8 @@ protected:
     //! controller of ped - for persuaded
     PedInstance *owner_;
     targetDescType last_firing_target_;
-    //! points needed to persuade ped
-    int persuasion_points_;
+    //! Points obtained by agents for persuading peds
+    uint16 totalPersuasionPoints_;
     //! The group of peds that this ped has persuaded
     std::set <PedInstance *> persuadedSet_;
     //! Tells whether the panic can react to panic or not
index 82c7147e1edf1a08ff5bd6878439cea6efa3c22e..8d7b93cb54715bd2325abd6083ded2ebb927dbb1 100644 (file)
@@ -854,7 +854,7 @@ void PedInstance::createDefQueue() {
         default_actions_.push_back(as);
     }
     as.actions.clear();
-    if ((desc_state_ & PedInstance::pd_smControlled) != 0) {
+    if (isPersuaded()) {
         createActQCheckOwner(as);
         as.group_desc = PedInstance::gd_mThink | PedInstance::gd_mFire;
         as.group_id = action_grp_id_++;
index b7d1b7b2abad481f9dd5f0168e061af2682e139f..fd491c95b4c23e850e659727a896ebafde6bfafb 100644 (file)
@@ -286,7 +286,6 @@ void PedManager::initEnemyAgent(PedInstance *pPed) {
     pPed->addMod(g_gameCtrl.mods().getHighestVersion(Mod::MOD_BRAIN));
     pPed->setTimeBeforeCheck(400);
     pPed->setBaseModAcc(0.5);
-    pPed->setPersuasionPoints(32);
 }
 
 /*!
@@ -301,7 +300,6 @@ void PedManager::initGuard(PedInstance *pPed) {
     pPed->setBaseSpeed(192);
     pPed->setTimeBeforeCheck(300);
     pPed->setBaseModAcc(0.45);
-    pPed->setPersuasionPoints(4);
 }
 
 /*!
@@ -316,7 +314,6 @@ void PedManager::initPolice(PedInstance *pPed) {
     pPed->setBaseSpeed(160);
     pPed->setTimeBeforeCheck(400);
     pPed->setBaseModAcc(0.4);
-    pPed->setPersuasionPoints(8);
 } 
 
 /*!
@@ -332,7 +329,6 @@ void PedManager::initCivilian(PedInstance *pPed) {
     pPed->setBaseSpeed(128);
     pPed->setTimeBeforeCheck(600);
     pPed->setBaseModAcc(0.2);
-    pPed->setPersuasionPoints(1);
 
     pPed->behaviour().addComponent(new PanicComponent());
 } 
@@ -348,5 +344,4 @@ void PedManager::initCriminal(PedInstance *pPed) {
     pPed->setBaseSpeed(128);
     pPed->setTimeBeforeCheck(500);
     pPed->setBaseModAcc(0.2);
-    pPed->setPersuasionPoints(1);
 }