1 /************************************************************************
2  *                                                                      *
3  *  FreeSynd - a remake of the classic Bullfrog game "Syndicate".       *
4  *                                                                      *
5  *   Copyright (C) 2005  Stuart Binge  <skbinge@gmail.com>              *
6  *   Copyright (C) 2005  Joost Peters  <joostp@users.sourceforge.net>   *
7  *   Copyright (C) 2006  Trent Waddington <qg@biodome.org>              *
8  *   Copyright (C) 2006  Tarjei Knapstad <tarjei.knapstad@gmail.com>    *
9  *   Copyright (C) 2010  Bohdan Stelmakh <chamel@users.sourceforge.net> *
10  *                                                                      *
11  *    This program is free software;  you can redistribute it and / or  *
12  *  modify it  under the  terms of the  GNU General  Public License as  *
13  *  published by the Free Software Foundation; either version 2 of the  *
14  *  License, or (at your option) any later version.                     *
15  *                                                                      *
16  *    This program is  distributed in the hope that it will be useful,  *
17  *  but WITHOUT  ANY WARRANTY;  without even  the implied  warranty of  *
18  *  MERCHANTABILITY  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  *
19  *  General Public License for more details.                            *
20  *                                                                      *
21  *    You can view the GNU  General Public License, online, at the GNU  *
22  *  project's  web  site;  see <http://www.gnu.org/licenses/gpl.html>.  *
23  *  The full text of the license is also included in the file COPYING.  *
24  *                                                                      *
25  ************************************************************************/
26 
27 #include <stdio.h>
28 #include <assert.h>
29 
30 #include "utils/log.h"
31 #include "pedmanager.h"
32 #include "core/gamecontroller.h"
33 
PedManager()34 PedManager::PedManager()
35 {
36 }
37 
initAnimation(Ped * pedanim,unsigned short baseAnim)38 void PedManager::initAnimation(Ped *pedanim, unsigned short baseAnim)
39 {
40     if (baseAnim == 1) {
41         pedanim->setStandAnim(Weapon::Unarmed_Anim, 0 + baseAnim);
42         pedanim->setWalkAnim(Weapon::Unarmed_Anim, 8 + baseAnim);
43         pedanim->setStandAnim(Weapon::EnergyShield_Anim, 16 + baseAnim);
44         pedanim->setStandAnim(Weapon::Pistol_Anim, 24 + baseAnim);
45         pedanim->setStandAnim(Weapon::Uzi_Anim, 24 + baseAnim);
46         pedanim->setStandAnim(Weapon::Shotgun_Anim, 24 + baseAnim);
47         pedanim->setStandAnim(Weapon::Gauss_Anim, 24 + baseAnim);
48         pedanim->setStandAnim(Weapon::Minigun_Anim, 32 + baseAnim);
49         pedanim->setStandAnim(Weapon::Laser_Anim, 24 + baseAnim);
50         pedanim->setStandAnim(Weapon::Flamer_Anim, 40 + baseAnim);
51         pedanim->setStandAnim(Weapon::LongRange_Anim, 48 + baseAnim);
52         pedanim->setWalkAnim(Weapon::EnergyShield_Anim, 56 + baseAnim);
53         pedanim->setWalkAnim(Weapon::Pistol_Anim, 64 + baseAnim);
54         pedanim->setWalkAnim(Weapon::Uzi_Anim, 64 + baseAnim);
55         pedanim->setWalkAnim(Weapon::Shotgun_Anim, 64 + baseAnim);
56         pedanim->setWalkAnim(Weapon::Gauss_Anim, 64 + baseAnim);
57         pedanim->setWalkAnim(Weapon::Minigun_Anim, 72 + baseAnim);
58         pedanim->setWalkAnim(Weapon::Laser_Anim, 64 + baseAnim);
59         pedanim->setWalkAnim(Weapon::Flamer_Anim, 80 + baseAnim);
60         pedanim->setWalkAnim(Weapon::LongRange_Anim, 88 + baseAnim);
61         // I think 97 was the original pistol shoot anim, but it wasn't sexy enough.
62         //pedanim->setStandFireAnim(Weapon::Laser_Anim, 96 + baseAnim);
63         pedanim->setStandFireAnim(Weapon::Pistol_Anim, 104 + baseAnim);
64         pedanim->setStandFireAnim(Weapon::Uzi_Anim, 104 + baseAnim);
65         pedanim->setStandFireAnim(Weapon::Shotgun_Anim, 104 + baseAnim);
66         pedanim->setStandFireAnim(Weapon::Gauss_Anim, 104 + baseAnim);
67         pedanim->setStandFireAnim(Weapon::Minigun_Anim, 112 + baseAnim);
68         pedanim->setStandFireAnim(Weapon::Laser_Anim, 120 + baseAnim);
69         pedanim->setStandFireAnim(Weapon::Flamer_Anim, 128 + baseAnim);
70         pedanim->setStandFireAnim(Weapon::LongRange_Anim, 136 + baseAnim);
71         pedanim->setWalkFireAnim(Weapon::Pistol_Anim, 152 + baseAnim);
72         pedanim->setWalkFireAnim(Weapon::Uzi_Anim, 152 + baseAnim);
73         pedanim->setWalkFireAnim(Weapon::Shotgun_Anim, 152 + baseAnim);
74         pedanim->setWalkFireAnim(Weapon::Gauss_Anim, 152 + baseAnim);
75         pedanim->setWalkFireAnim(Weapon::Minigun_Anim, 160 + baseAnim);
76         pedanim->setWalkFireAnim(Weapon::Laser_Anim, 168 + baseAnim);
77         pedanim->setWalkFireAnim(Weapon::Flamer_Anim, 176 + baseAnim);
78         pedanim->setWalkFireAnim(Weapon::LongRange_Anim, 184 + baseAnim);
79     } else {
80         // NOTE: peds other then agents have pistol like animations for
81         // all weapons
82         pedanim->setStandAnim(Weapon::Unarmed_Anim, 0 + baseAnim);
83         pedanim->setWalkAnim(Weapon::Unarmed_Anim, 8 + baseAnim);
84         pedanim->setStandAnim(Weapon::EnergyShield_Anim, 0 + baseAnim);
85         pedanim->setStandAnim(Weapon::Pistol_Anim, 24 + baseAnim);
86         pedanim->setStandAnim(Weapon::Uzi_Anim, 24 + baseAnim);
87         pedanim->setStandAnim(Weapon::Shotgun_Anim, 24 + baseAnim);
88         pedanim->setStandAnim(Weapon::Gauss_Anim, 24 + baseAnim);
89         pedanim->setStandAnim(Weapon::Minigun_Anim, 24 + baseAnim);
90         pedanim->setStandAnim(Weapon::Laser_Anim, 24 + baseAnim);
91         pedanim->setStandAnim(Weapon::Flamer_Anim, 24 + baseAnim);
92         pedanim->setStandAnim(Weapon::LongRange_Anim, 24 + baseAnim);
93         pedanim->setWalkAnim(Weapon::EnergyShield_Anim, 24 + baseAnim);
94         pedanim->setWalkAnim(Weapon::Pistol_Anim, 64 + baseAnim);
95         pedanim->setWalkAnim(Weapon::Uzi_Anim, 64 + baseAnim);
96         pedanim->setWalkAnim(Weapon::Shotgun_Anim, 64 + baseAnim);
97         pedanim->setWalkAnim(Weapon::Gauss_Anim, 64 + baseAnim);
98         pedanim->setWalkAnim(Weapon::Minigun_Anim, 64 + baseAnim);
99         pedanim->setWalkAnim(Weapon::Laser_Anim, 64 + baseAnim);
100         pedanim->setWalkAnim(Weapon::Flamer_Anim, 64 + baseAnim);
101         pedanim->setWalkAnim(Weapon::LongRange_Anim, 64 + baseAnim);
102         // I think 97 was the original pistol shoot anim, but it wasn't sexy enough.
103         //pedanim->setStandFireAnim(Weapon::Laser_Anim, 96 + baseAnim);
104         pedanim->setStandFireAnim(Weapon::Pistol_Anim, 104 + baseAnim);
105         pedanim->setStandFireAnim(Weapon::Uzi_Anim, 104 + baseAnim);
106         pedanim->setStandFireAnim(Weapon::Shotgun_Anim, 104 + baseAnim);
107         pedanim->setStandFireAnim(Weapon::Gauss_Anim, 104 + baseAnim);
108         pedanim->setStandFireAnim(Weapon::Minigun_Anim, 104 + baseAnim);
109         pedanim->setStandFireAnim(Weapon::Laser_Anim, 104 + baseAnim);
110         pedanim->setStandFireAnim(Weapon::Flamer_Anim, 104 + baseAnim);
111         pedanim->setStandFireAnim(Weapon::LongRange_Anim, 104 + baseAnim);
112         pedanim->setWalkFireAnim(Weapon::Pistol_Anim, 104 + baseAnim);
113         pedanim->setWalkFireAnim(Weapon::Uzi_Anim, 104 + baseAnim);
114         pedanim->setWalkFireAnim(Weapon::Shotgun_Anim, 104 + baseAnim);
115         pedanim->setWalkFireAnim(Weapon::Gauss_Anim, 104 + baseAnim);
116         pedanim->setWalkFireAnim(Weapon::Minigun_Anim, 104 + baseAnim);
117         pedanim->setWalkFireAnim(Weapon::Laser_Anim, 104 + baseAnim);
118         pedanim->setWalkFireAnim(Weapon::Flamer_Anim, 104 + baseAnim);
119         pedanim->setWalkFireAnim(Weapon::LongRange_Anim, 104 + baseAnim);
120     }
121     pedanim->setPickupAnim(192 + baseAnim);
122     pedanim->setHitAnim(193 + baseAnim);
123     pedanim->setVaporizeAnim(197 + baseAnim);
124     pedanim->setSinkAnim(201 + baseAnim);
125     // 203 - die, 204 - dead, agent only
126     pedanim->setDieAgentAnim(203 + baseAnim);
127     pedanim->setDeadAgentAnim(205);
128     pedanim->setDieAnim(205 + baseAnim);
129     pedanim->setDeadAnim(206 + baseAnim);
130     // when this burning should be used?
131     pedanim->setStandBurnAnim(208);
132     // this one used when hit with flamethrower
133     pedanim->setWalkBurnAnim(209);
134     pedanim->setDieBurnAnim(210);
135     pedanim->setSmokeBurnAnim(211);
136     pedanim->setDeadBurnAnim(828);
137     pedanim->setPersuadeAnim(236);
138 }
139 
140 /*!
141  * Instanciate a PedInstance from the given data.
142  * \param gamdata
143  * \param ped_idx Index of the ped in the file.
144  * \param map id of the map
145  * \return NULL if the ped could not be created.
146  */
loadInstance(const LevelData::People & gamdata,uint16 ped_idx,int map,uint32 playerGroupId)147 PedInstance *PedManager::loadInstance(const LevelData::People & gamdata, uint16 ped_idx, int map, uint32 playerGroupId)
148 {
149     if(gamdata.type == 0x0 ||
150         gamdata.location == LevelData::kPeopleLocNotVisible ||
151         gamdata.location == LevelData::kPeopleLocAboveWalkSurf)
152         return NULL;
153 
154     bool isOurAgent = ped_idx < AgentManager::kMaxSlot;
155     if (isOurAgent && !g_gameCtrl.agents().isSquadSlotActive(ped_idx)) {
156         // Creates agent only if he's active
157         return NULL;
158     }if (ped_idx >= 4 && ped_idx < 8) {
159         // Ped between index 4 and 7 are not used
160         // In original game must be the place where persuaded agents were stored
161         return NULL;
162     }
163 
164     Ped *pedanim = new Ped();
165     initAnimation(pedanim, READ_LE_UINT16(gamdata.index_base_anim));
166     PedInstance *newped = new PedInstance(pedanim, ped_idx, map, isOurAgent);
167 
168     int hp = READ_LE_INT16(gamdata.health);
169     if (isOurAgent) {
170         // not in all missions our agents health is 16, this fixes it
171         hp = PedInstance::kAgentMaxHealth;
172     }else if (hp <= 0) {
173         hp = 2;
174     }
175 
176     newped->setStartHealth(hp);
177 
178     newped->setDirection(gamdata.orientation);
179     if (gamdata.state == LevelData::kPeopleStateDead) {
180         newped->setDrawnAnim(PedInstance::ad_DeadAnim);
181         newped->setHealth(-1);
182         newped->setStateMasks(PedInstance::pa_smDead);
183     } else {
184         newped->setHealth(hp);
185         newped->setStateMasks(PedInstance::pa_smStanding);
186         if (gamdata.state == 0x10) {
187             LOG(Log::k_FLG_GAME, "PedManager","loadInstance", ("Unhandled gamedata state for ped %d", newped->id()))
188 /*            PedInstance::actionQueueGroupType as;
189             newped->createActQWalking(as, NULL, NULL, gamdata.orientation);
190             as.main_act = as.actions.size() - 1;
191             as.group_desc = PedInstance::gd_mStandWalk;
192             as.origin_desc = fs_action::kOrigDefault;
193             newped->addActQToQueue(as);
194 */
195         }
196     }
197     // this is tile based Z we get, realword Z is in gamdata,
198     // for correct calculations of viewpoint, target hit etc.
199     // Zr = (Zt * 128) / 256
200     int z = READ_LE_UINT16(gamdata.mapposz) >> 7;
201     // some peds have z = 0 - map paraguay
202     int oz = gamdata.mapposz[0] & 0x7F;
203     newped->setSizeX(32);
204     newped->setSizeY(32);
205     newped->setSizeZ(256);
206     //printf("x %i y %i z %i ox %i oy %i oz %i\n", gamdata.mapposx[1], gamdata.mapposy[1], z, gamdata.mapposx[0], gamdata.mapposy[0], oz);
207     newped->setPosition(gamdata.mapposx[1], gamdata.mapposy[1],
208                         z, gamdata.mapposx[0],
209                         gamdata.mapposy[0], oz);
210     newped->setTypeFromValue(gamdata.type_ped);
211 
212     newped->setAllAdrenaLevels(gamdata.adrena_amount,
213         gamdata.adrena_dependency, gamdata.adrena_effect);
214     newped->setAllInteliLevels(gamdata.inteli_amount,
215         gamdata.inteli_dependency, gamdata.inteli_effect);
216     newped->setAllPercepLevels(gamdata.percep_amount,
217         gamdata.percep_dependency, gamdata.percep_effect);
218 
219     if (isOurAgent) {
220         // We're loading one of our agents
221         Agent *pAg = g_gameCtrl.agents().squadMember(ped_idx);
222         initOurAgent(pAg, playerGroupId, newped);
223     } else {
224         unsigned int mt = newped->type();
225         newped->setObjGroupDef(mt);
226         if (mt == PedInstance::og_dmAgent) {
227             initEnemyAgent(newped);
228         } else if (mt == PedInstance::og_dmGuard) {
229             initGuard(newped);
230         } else if (mt == PedInstance::og_dmPolice) {
231             initPolice(newped);
232         } else if (mt == PedInstance::og_dmCivilian) {
233             initCivilian(newped);
234         } else if (mt == PedInstance::og_dmCriminal) {
235             initCriminal(newped);
236         }
237         newped->setSightRange(7 * 256);
238     }
239 
240     return newped;
241 }
242 
243 /*!
244  * Initialize the ped instance as one of our agent.
245  * \param pAgent The agent reference
246  * \param obj_group_id Id of the agent's group.
247  * \param pPed The ped to initialize
248  */
initOurAgent(Agent * pAgent,unsigned int obj_group_id,PedInstance * pPed)249 void PedManager::initOurAgent(Agent *pAgent, unsigned int obj_group_id, PedInstance *pPed) {
250     LOG(Log::k_FLG_GAME, "PedManager","initOurAgent", ("Create player agent with id %d", pAgent->getId()))
251 
252     while (pAgent->numWeapons()) {
253         WeaponInstance *wi = pAgent->removeWeaponAtIndex(0);
254         pPed->addWeapon(wi);
255         wi->setOwner(pPed);
256     }
257     *((ModOwner *)pPed) = *((ModOwner *)pAgent);
258 
259     pPed->setObjGroupID(obj_group_id);
260     pPed->setObjGroupDef(PedInstance::og_dmAgent);
261     pPed->addEnemyGroupDef(2);
262     pPed->addEnemyGroupDef(3);
263     pPed->setHostileDesc(PedInstance::pd_smArmed);
264     pPed->setSightRange(7 * 256);
265     pPed->setBaseSpeed(256);
266     pPed->setTimeBeforeCheck(400);
267     pPed->setBaseModAcc(0.5);
268 
269     // Set components of behaviour for our agent
270     pPed->behaviour().addComponent(new CommonAgentBehaviourComponent(pPed));
271     pPed->behaviour().addComponent(new PersuaderBehaviourComponent());
272 }
273 
274 /*!
275  * Initialize the ped instance as an enemy agent.
276  * \param p_agent The agent reference
277  * \param obj_group_id Id of the agent's group.
278  * \param pPed The ped to initialize
279  */
initEnemyAgent(PedInstance * pPed)280 void PedManager::initEnemyAgent(PedInstance *pPed) {
281     LOG(Log::k_FLG_GAME, "PedManager","initEnemyAgent", ("Create enemy agent with id %d", pPed->id()))
282 
283     pPed->setObjGroupID(2);
284     pPed->addEnemyGroupDef(1);
285     pPed->setBaseSpeed(256);
286     // enemies get top version of mods
287     pPed->addMod(g_gameCtrl.mods().getHighestVersion(Mod::MOD_LEGS));
288     pPed->addMod(g_gameCtrl.mods().getHighestVersion(Mod::MOD_LEGS));
289     pPed->addMod(g_gameCtrl.mods().getHighestVersion(Mod::MOD_ARMS));
290     pPed->addMod(g_gameCtrl.mods().getHighestVersion(Mod::MOD_CHEST));
291     pPed->addMod(g_gameCtrl.mods().getHighestVersion(Mod::MOD_HEART));
292     pPed->addMod(g_gameCtrl.mods().getHighestVersion(Mod::MOD_EYES));
293     pPed->addMod(g_gameCtrl.mods().getHighestVersion(Mod::MOD_BRAIN));
294     pPed->setTimeBeforeCheck(400);
295     pPed->setBaseModAcc(0.5);
296 
297     pPed->behaviour().addComponent(new PlayerHostileBehaviourComponent());
298 }
299 
300 /*!
301  * Initialize the ped instance as a guard.
302  * \param p_agent The agent reference
303  * \param obj_group_id Id of the agent's group.
304  * \param pPed The ped to initialize
305  */
initGuard(PedInstance * pPed)306 void PedManager::initGuard(PedInstance *pPed) {
307     LOG(Log::k_FLG_GAME, "PedManager","initGuard", ("Create guard with id %d", pPed->id()))
308 
309     pPed->setObjGroupID(3);
310     pPed->addEnemyGroupDef(1);
311     pPed->setBaseSpeed(192);
312     pPed->setTimeBeforeCheck(300);
313     pPed->setBaseModAcc(0.45);
314 
315     pPed->behaviour().addComponent(new PlayerHostileBehaviourComponent());
316 }
317 
318 /*!
319  * Initialize the ped instance as a police.
320  * \param p_agent The agent reference
321  * \param obj_group_id Id of the agent's group.
322  * \param pPed The ped to initialize
323  */
initPolice(PedInstance * pPed)324 void PedManager::initPolice(PedInstance *pPed) {
325     LOG(Log::k_FLG_GAME, "PedManager","initPolice", ("Create police with id %d", pPed->id()))
326 
327     pPed->setObjGroupID(4);
328     pPed->setHostileDesc(PedInstance::pd_smArmed);
329     pPed->setBaseSpeed(160);
330     pPed->setTimeBeforeCheck(400);
331     pPed->setBaseModAcc(0.4);
332 
333     pPed->behaviour().addComponent(new PoliceBehaviourComponent());
334 }
335 
336 /*!
337  * Initialize the ped instance as a civilian.
338  * \param p_agent The agent reference
339  * \param obj_group_id Id of the agent's group.
340  * \param pPed The ped to initialize
341  */
initCivilian(PedInstance * pPed)342 void PedManager::initCivilian(PedInstance *pPed) {
343     LOG(Log::k_FLG_GAME, "PedManager","initCivilian", ("Create civilian with id %d", pPed->id()))
344 
345     pPed->setObjGroupID(5);
346     pPed->addEnemyGroupDef(6);
347     pPed->setHostileDesc(PedInstance::pd_smArmed);
348     pPed->setBaseSpeed(128);
349     pPed->setTimeBeforeCheck(600);
350     pPed->setBaseModAcc(0.2);
351 
352     pPed->behaviour().addComponent(new PanicComponent());
353 }
354 
355 /*!
356  * Initialize the ped instance as a criminal.
357  * \param p_agent The agent reference
358  * \param obj_group_id Id of the agent's group.
359  * \param pPed The ped to initialize
360  */
initCriminal(PedInstance * pPed)361 void PedManager::initCriminal(PedInstance *pPed) {
362     LOG(Log::k_FLG_GAME, "PedManager","initCriminal", ("Create criminal with id %d", pPed->id()))
363 
364     pPed->setObjGroupID(6);
365     pPed->setBaseSpeed(128);
366     pPed->setTimeBeforeCheck(500);
367     pPed->setBaseModAcc(0.2);
368 }
369