1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2014 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
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
;
44 class CFightFaunaProfile
;
46 extern NLMISC::CVariable
<float> SpeedFactor
;
48 //////////////////////////////////////////////////////////////////////////////
50 //////////////////////////////////////////////////////////////////////////////
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.
61 # ifndef NL_COMP_MINGW
62 friend class CTargetable
<T
>;
66 typedef NLMISC::CDbgPtr
<T
> TPtr
;
70 TARGET_TYPE_FIGHT
= 0,
72 TARGET_TYPE_UNREACHABLE
,
77 uint32 _ChooseLastTime
;
79 /// @name Constructor and destructor
82 virtual ~CTargetable();
85 virtual void targetDied () { }
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;
101 /// @name Target management
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();
116 /// @name Fight management
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
; }
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
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
);
143 uint32 _TargeterCount
[TARGET_TYPE_MAX
];
144 TPtr _FirstTargeters
[TARGET_TYPE_MAX
];
147 TTargetType _TargetType
;
150 /// @name Fight management
152 float _FightTargetersWeight
;
153 float _FightTargetersValue
;
157 static CKnapsackSolver::Algorithm _TargeterChoiceAlgorithm
;
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
>
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
192 virtual void healerAdded(CAIEntityPhysical
* entity
) = 0;
193 virtual void healerRemoved(CAIEntityPhysical
* entity
) = 0;
196 class CAIEntityPhysical
;
198 class CAIEntityPhysicalLocator
201 static CAIEntityPhysicalLocator
* getInstance();
203 static CAIEntityPhysicalLocator
* _Instance
;
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
);
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
>
220 , public CSpawnable
<CPersistentOfPhysical
>
221 , public CTargetable
<CAIEntityPhysical
>
224 /// @name Constructor and destructor
226 CAIEntityPhysical(CPersistentOfPhysical
&owner
, TDataSetRow
const& entityIndex
, NLMISC::CEntityId
const& id
, float radius
, uint32 level
, RYAI_MAP_CRUNCH::TAStarFlag
const& AStarFlags
);
227 virtual ~CAIEntityPhysical();
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
; }
248 /// @name Mirror accessors
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
);
269 /// @name Virtual accessors
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;
280 virtual void processEvent(CCombatInterface::CEvent
const& event
) = 0;
286 float& food() { return _food
; }
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; }
304 virtual bool canMove() const;
305 float walkSpeed() const;
306 float runSpeed() const;
309 /// @name Healer count management
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(); }
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;
322 virtual float getSpeedFactor() const { return 1.f
; }
325 friend class CFightFaunaProfile
;
327 // position and orientation (only changeable by bots).
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
;
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
;
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
385 /// @name Constructor
387 CModEntityPhysical(CPersistentOfPhysical
& owner
, TDataSetRow
const& entityIndex
, NLMISC::CEntityId
const& id
, float radius
, uint32 level
, RYAI_MAP_CRUNCH::TAStarFlag
const& AStarFlags
);
390 /// @name Accessors (setters)
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
; }
400 void setOutpostSide(OUTPOSTENUMS::TPVPSide side
) { _InOutpostSide
= (side
==OUTPOSTENUMS::OutpostAttacker
); }
403 /// @name Targeting overrides
405 virtual void targetDied() { _targetRow
= TDataSetRow(); }
406 virtual void setTarget(CAIEntityPhysical
* target
);
407 virtual void setVisualTarget(CAIEntityPhysical
* target
);
408 virtual void setUnreachableTarget(CAIEntityPhysical
* target
);
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
);
416 bool setPos(CAIPos
const& pos
);
418 bool moveTo(CAIPos
const& newPos
, RYAI_MAP_CRUNCH::TAStarFlag
const& denyFlags
);
420 /// If this method is extracted from the class definition VC++ fails to instantiate it.
422 bool moveBy(W vect
, RYAI_MAP_CRUNCH::TAStarFlag
const& denyFlags
)
424 if (!wpos().isValid())
427 CAIVector
posVect(pos());
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();
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;