Resolve "Toggle Free Look with Hotkey"
[ryzomcore.git] / ryzom / server / src / ai_service / ai_entity_physical.h
blobdf045023d8d0dc5c7317de699f586384b95b2dfe
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2014 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #ifndef RYAI_ENTITY_PHYSICAL_H
24 #define RYAI_ENTITY_PHYSICAL_H
26 #include "ai_entity.h"
27 #include "ai_pos_mirror.h"
28 #include "persistent_spawnable.h"
29 #include "ai_share/world_map.h"
30 #include "server_share/combat_state.h"
31 #include "world_container.h"
32 #include "ai_entity_matrix.h"
33 #include "server_share/action_flags.h"
34 #include "combat_interface.h"
36 #include "world_map_link.h"
38 #include "knapsack_solver.h"
40 #include "nel/misc/variable.h"
42 class CAIEntityPhysical;
43 class CPetOwner;
44 class CFightFaunaProfile;
46 extern NLMISC::CVariable<float> SpeedFactor;
48 //////////////////////////////////////////////////////////////////////////////
49 // CTargetable //
50 //////////////////////////////////////////////////////////////////////////////
52 /** Targeting system
53 There are both the targeter and the targetable in the same class for
54 template easier manipulation reasons.
55 @note Don't forget to call detachFromTargeting() in T dtor.
57 template <class T>
58 class CTargetable
60 #ifdef NL_OS_WINDOWS
61 # ifndef NL_COMP_MINGW
62 friend class CTargetable<T>;
63 # endif
64 #endif
65 public:
66 typedef NLMISC::CDbgPtr<T> TPtr;
67 // typedef T* TPtr;
68 enum TTargetType
70 TARGET_TYPE_FIGHT = 0,
71 TARGET_TYPE_VISUAL,
72 TARGET_TYPE_UNREACHABLE,
73 TARGET_TYPE_MAX
76 float _AggroScore;
77 uint32 _ChooseLastTime;
79 /// @name Constructor and destructor
80 //@{
81 CTargetable();
82 virtual ~CTargetable();
83 //@}
85 virtual void targetDied () { }
87 /// @name Accessors
88 //@{
89 TPtr const& firstTargeter() const { return _FirstTargeters[TARGET_TYPE_FIGHT]; }
90 TPtr const& firstVisualTargeter() const { return _FirstTargeters[TARGET_TYPE_VISUAL]; }
91 TPtr const& firstUnreachableTargeter() const { return _FirstTargeters[TARGET_TYPE_UNREACHABLE]; }
93 TPtr const& nextTargeter() const { return _NextTargeter; }
95 uint32 targeterCount() const { return _TargeterCount[TARGET_TYPE_FIGHT]; }
96 uint32 visualTargeterCount() const { return _TargeterCount[TARGET_TYPE_VISUAL]; }
97 uint32 unreachableTargeterCount() const { return _TargeterCount[TARGET_TYPE_UNREACHABLE]; }
98 uint32 totalTargeterCount() const;
99 //@}
101 /// @name Target management
102 //@{
103 virtual void setTarget(T* target);
104 virtual void setVisualTarget(T* target);
105 virtual void setUnreachableTarget(T* target);
107 TPtr getTarget() const;
108 TPtr getVisualTarget() const;
109 TPtr getUnreachableTarget() const;
111 void detachFromTargeters();
112 /// Detach from targeters and target
113 void detachFromTargeting();
114 //@}
116 /// @name Fight management
117 //@{
118 virtual float getFreeFightSpaceRatio() const { return std::max(fightTargetersFreeWeight()/fightTargetersWeightMax(), 0.f); }
119 virtual float fightWeight() const { return _DefaultFightWeight; }
120 virtual float fightValue() const { return _DefaultFightValue; }
121 virtual float fightTargetersWeightMax() const { return _DefaultFightTargetersWeightMax; }
122 virtual float fightTargetersWeight() const { return _FightTargetersWeight; }
123 virtual float fightTargetersFreeWeight() const { return fightTargetersWeightMax() - fightTargetersWeight(); }
124 virtual float fightTargetersValue() const { return _FightTargetersValue; }
125 //@}
127 private:
128 void setTarget(TTargetType type, TPtr const& target);
129 TPtr getTarget(TTargetType type) const;
131 /// @name Targeter management
132 /// These functions are responsible to set/unset the actual _Target pointer in targeters
133 //@{
134 void linkTargeter (TTargetType type, TPtr const& targeter, TPtr const& nextTargeter);
135 void unlinkTargeter (TTargetType type, TPtr const& targeter);
136 void addTargeter (TTargetType type, TPtr const& targeter);
137 void removeTargeter (TTargetType type, TPtr const& targeter);
138 void tryToAddTargeter(TTargetType type, TPtr const& targeter);
139 //@}
141 private:
142 // Target stuff
143 uint32 _TargeterCount[TARGET_TYPE_MAX];
144 TPtr _FirstTargeters[TARGET_TYPE_MAX];
145 // Targeter stuff
146 TPtr _Target;
147 TTargetType _TargetType;
148 TPtr _NextTargeter;
150 /// @name Fight management
151 //@{
152 float _FightTargetersWeight;
153 float _FightTargetersValue;
154 //@}
156 public:
157 static CKnapsackSolver::Algorithm _TargeterChoiceAlgorithm;
158 private:
159 static float const _DefaultFightTargetersWeightMax;
160 static float const _DefaultFightWeight;
161 static float const _DefaultFightValue;
164 class CPersistentOfPhysical :
165 public NLMISC::CDbgRefCount<CPersistentOfPhysical>,
166 public CPersistent<CAIEntityPhysical>,
167 public CWorldMapLink<CPersistentOfPhysical>
169 public:
170 bool isAt16MetersPos(uint16 x, uint16 y) const;
172 /// You must overload this access to cast the objet with a custom more proper type. ( you know what StepH meant? )
173 CAIEntityPhysical* getSpawnObj() const;
175 /// Retrieve an info string on the entity
176 virtual std::string getOneLineInfoString() const =0;
179 typedef std::vector<NLMISC::CDbgPtr<CPersistentOfPhysical> > TPersistentList;
181 //////////////////////////////////////////////////////////////////////////////
182 // CAIEntityPhysical //
183 //////////////////////////////////////////////////////////////////////////////
185 // :KLUDGE: These should be in game_share
186 typedef uint32 TAllianceId;
187 typedef uint32 TAIAlias;
189 class IAIEntityPhysicalHealer
191 public:
192 virtual void healerAdded(CAIEntityPhysical* entity) = 0;
193 virtual void healerRemoved(CAIEntityPhysical* entity) = 0;
196 class CAIEntityPhysical;
198 class CAIEntityPhysicalLocator
200 public:
201 static CAIEntityPhysicalLocator* getInstance();
202 private:
203 static CAIEntityPhysicalLocator* _Instance;
205 public:
206 CAIEntityPhysical* getEntity(TDataSetRow const& row) const;
207 CAIEntityPhysical* getEntity(NLMISC::CEntityId const& id) const;
208 void addEntity(TDataSetRow const& row, NLMISC::CEntityId const& id, CAIEntityPhysical* entity);
209 void delEntity(TDataSetRow const& row, NLMISC::CEntityId const& id, CAIEntityPhysical* entity);
210 private:
211 std::map<TDataSetRow, CAIEntityPhysical*> _EntitiesByRow;
212 std::map<NLMISC::CEntityId, CAIEntityPhysical*> _EntitiesById;
215 /// CAIEntityPhysical is the common parent of bots, players and any other
216 /// physical objects that have an existence in the world.
217 class CAIEntityPhysical
218 : public NLMISC::CDbgRefCount<CAIEntityPhysical>
219 , public CAIEntity
220 , public CSpawnable<CPersistentOfPhysical>
221 , public CTargetable<CAIEntityPhysical>
223 public:
224 /// @name Constructor and destructor
225 //@{
226 CAIEntityPhysical(CPersistentOfPhysical &owner, TDataSetRow const& entityIndex, NLMISC::CEntityId const& id, float radius, uint32 level, RYAI_MAP_CRUNCH::TAStarFlag const& AStarFlags);
227 virtual ~CAIEntityPhysical();
228 //@}
230 /// @name Accessors
231 //@{
232 NLMISC::CEntityId const& getEntityId() const { return _id; }
233 float radius() const { return _radius; }
234 CAIPosMirror const& pos() const { return _pos; }
235 virtual CAIPos aipos() const { return CAIPos(_pos); }
236 CAICoord const& x() const { return _pos.x(); }
237 CAICoord const& y() const { return _pos.y(); }
238 sint32 h() const { return _pos.h(); }
239 CAngle theta() const { return _pos.theta(); }
240 float hpPercentage() const { return (float)currentHitPoints()/(float)maxHitPoints(); }
241 TDataSetRow const& dataSetRow() const { return _dataSetRow; }
242 uint32 level() const { return _Level; }
243 RYAI_MAP_CRUNCH::CWorldPosition const& wpos() const { return _wpos; }
244 void setWPos(RYAI_MAP_CRUNCH::CWorldPosition const& pos);
245 RYAI_MAP_CRUNCH::TAStarFlag const& getAStarFlag() const { return _AStarFlags; }
246 //@}
248 /// @name Mirror accessors
249 //@{
250 TYPE_CURRENT_HIT_POINTS currentHitPoints() const { return _CurrentHitPoint(); }
251 TYPE_MAX_HIT_POINTS maxHitPoints() const { return _MaxHitPoint(); }
252 TYPE_VISION_COUNTER currentVisionCounter() const { return _VisionCounter(); }
253 bool havePlayersAround() const;
255 /// Return the alias of the outpost where the bot is, or 0 if outside of an outpost
256 TAIAlias outpostAlias() const { return _InOutpostAlias.getValue(); }
257 uint8 outpostSide() const { return _InOutpostSide.getValue(); }
259 uint32 getInstanceNumber() const { return _instanceNumber(); };
260 MBEHAV::EMode getMode() const { return (MBEHAV::EMode)_mode().Mode; }
261 MBEHAV::EBehaviour getBehaviour() const { return (MBEHAV::EBehaviour)_behaviour().Behaviour; }
262 bool isAlive() const { return getMode()!=MBEHAV::DEATH; }
264 RYZOMACTIONFLAGS::TActionFlag getActionFlags() const { return (RYZOMACTIONFLAGS::TActionFlag)_ActionFlags(); }
265 void setActionFlags(RYZOMACTIONFLAGS::TActionFlag const& flag);
266 void removeActionFlags(RYZOMACTIONFLAGS::TActionFlag const& flag);
267 //@}
269 /// @name Virtual accessors
270 //@{
271 virtual bool isBotAttackable() const = 0;
273 /// The returned type can be different from the type in the CEntityId (ex: pack_animal instead of creature for all player's mektoubs)
274 virtual RYZOMID::TTypeId getRyzomType() const = 0;
275 virtual float getCollisionDist(float angTo) const;
276 //@}
278 /// @name Fighting
279 //@{
280 virtual void processEvent(CCombatInterface::CEvent const& event) = 0;
281 //@}
283 /// @name Effects
284 //@{
285 // Food
286 float& food() { return _food; }
288 // Stun cast
289 sint32& stun() { return _Stuned; }
290 bool isStuned() const { return _Stuned!=0; }
292 sint32& root() { return _Rooted; }
293 bool isRooted() const { return _Rooted!=0; }
295 sint32& blind() { return _Blinded; }
296 bool isBlinded() const { return _Blinded!=0; }
298 sint32& fear() { return _Feared; }
299 bool isFeared() const { return _Feared!=0; }
300 //@}
302 /// @name Movement
303 //@{
304 virtual bool canMove() const;
305 float walkSpeed() const;
306 float runSpeed() const;
307 //@}
309 /// @name Healer count management
310 //@{
311 virtual void addHealer(IAIEntityPhysicalHealer* healer) { _Healers.insert(healer); if (healer) healer->healerAdded(this); }
312 virtual void delHealer(IAIEntityPhysicalHealer* healer) { _Healers.erase(healer); if (healer) healer->healerRemoved(this); }
313 virtual sint getHealerCount() { return (sint)_Healers.size(); }
314 //@}
316 static int _PlayerVisibilityDistance;
318 virtual sint32 getFame(std::string const& faction, bool modulated = false, bool returnUnknowValue = false) const;
319 virtual sint32 getFameIndexed(uint32 factionIndex, bool modulated = false, bool returnUnknowValue = false) const;
321 protected:
322 virtual float getSpeedFactor() const { return 1.f; }
324 protected:
325 friend class CFightFaunaProfile;
327 // position and orientation (only changeable by bots).
328 CAIPosMirror _pos;
330 private:
332 // done to hide access except for CModEntityPhysical ..
333 friend class CModEntityPhysical;
335 // entity index - for MIRRORS
336 TDataSetRow _dataSetRow;
338 RYAI_MAP_CRUNCH::CWorldPosition _wpos;
340 // instance number
341 CMirrorPropValue<uint32> _instanceNumber;
343 // generic visual properties
344 CMirrorPropValue<MBEHAV::TMode> _mode;
345 CMirrorPropValueRO<MBEHAV::CBehaviour> _behaviour;
346 CMirrorPropValue<TYPE_TARGET_ID> _targetRow;
348 CMirrorPropValueRO<float> _RunSpeed;
349 CMirrorPropValueRO<float> _WalkSpeed;
351 CMirrorPropValueRO<TYPE_CURRENT_HIT_POINTS> _CurrentHitPoint;
352 CMirrorPropValueRO<TYPE_MAX_HIT_POINTS> _MaxHitPoint;
353 CMirrorPropValueRO<TYPE_VISION_COUNTER> _VisionCounter;
354 CMirrorPropValue<TYPE_IN_OUTPOST_ZONE_ALIAS> _InOutpostAlias;
355 CMirrorPropValue<TYPE_IN_OUTPOST_ZONE_SIDE> _InOutpostSide;
357 /// flags used by AI service to know the state of the entity
358 CMirrorPropValue<uint16> _ActionFlags;
360 sint32 _Stuned; // Is the bot stuned ?
361 sint32 _Rooted; // Is the bot rooted ?
362 sint32 _Blinded; // Is the bot blinded ?
363 sint32 _Feared; // Is the bot Feared ?
365 NLMISC::CEntityId _id;
366 float _radius;
367 float _food;
369 uint32 _Level;
371 RYAI_MAP_CRUNCH::TAStarFlag _AStarFlags;
373 std::multiset<IAIEntityPhysicalHealer*> _Healers;
376 //////////////////////////////////////////////////////////////////////////////
377 // CModEntityPhysical //
378 //////////////////////////////////////////////////////////////////////////////
380 class CModEntityPhysical
381 : public NLMISC::CDbgRefCount<CModEntityPhysical>
382 , public CAIEntityPhysical
384 public:
385 /// @name Constructor
386 //@{
387 CModEntityPhysical(CPersistentOfPhysical& owner, TDataSetRow const& entityIndex, NLMISC::CEntityId const& id, float radius, uint32 level, RYAI_MAP_CRUNCH::TAStarFlag const& AStarFlags);
388 //@}
390 /// @name Accessors (setters)
391 //@{
392 virtual void setTheta(CAngle theta) { _pos.setTheta(theta); }
393 void setMode(MBEHAV::EMode m);
394 void setInstanceNumber(uint32 instanceNumber) { _instanceNumber = instanceNumber; };
395 void setBehaviour(MBEHAV::EBehaviour b) { CMirrors::setBehaviour(dataSetRow(), b); }
397 /// The AIS may set only the alias of the outpost where a bot is, or a character the EGS sets is
398 void setOutpostAlias(TAIAlias alias) { _InOutpostAlias = alias; }
399 ///
400 void setOutpostSide(OUTPOSTENUMS::TPVPSide side) { _InOutpostSide = (side==OUTPOSTENUMS::OutpostAttacker); }
401 //@}
403 /// @name Targeting overrides
404 //@{
405 virtual void targetDied() { _targetRow = TDataSetRow(); }
406 virtual void setTarget(CAIEntityPhysical* target);
407 virtual void setVisualTarget(CAIEntityPhysical* target);
408 virtual void setUnreachableTarget(CAIEntityPhysical* target);
409 //@}
411 /// @name Movement
412 //@{
413 /// Fast routine (but you must ensure that pos and wpos are related)
414 void setPos(CAIPos const& pos, RYAI_MAP_CRUNCH::CWorldPosition const& wpos);
415 /// Slow routine
416 bool setPos(CAIPos const& pos);
417 /// Set position
418 bool moveTo(CAIPos const& newPos, RYAI_MAP_CRUNCH::TAStarFlag const& denyFlags);
419 /// Change position
420 /// If this method is extracted from the class definition VC++ fails to instantiate it.
421 template <class W>
422 bool moveBy(W vect, RYAI_MAP_CRUNCH::TAStarFlag const& denyFlags)
424 if (!wpos().isValid())
425 return false;
427 CAIVector posVect(pos());
428 posVect += vect;
430 // first we try from the real position (not bound).
431 CAIPos destPos(posVect, h(), theta());
432 return moveTo(destPos, denyFlags);
435 /// Calculate the repulsion with other bots and players
436 CAIVector calcRepulsion(CAIPos const& pos) const;
437 bool calcStraightRepulsion(CAIPos const& pos, CAIVector& repulsion) const;
439 void setMoveDecalage(CAIVector const& decalage) { _Decalage = decalage; }
440 CAIVector const& moveDecalage() const { return _Decalage; }
441 void resetDecalage();
442 //@}
444 private:
445 CAIVector calcRepulsionFrom(CAIVector const& pos, const std::vector<const CAIEntityPhysical*>& entities) const;
446 bool calcStraightRepulsionFrom(CAIVector const& pos, const std::vector<const CAIEntityPhysical*>& entities, CAIVector& repulsion) const;
448 private:
449 CAIVector _Decalage;
452 #endif