Resolve "Toggle Free Look with Hotkey"
[ryzomcore.git] / ryzom / server / src / ai_service / profile.h
blobdadeb80af5fb36974a19cdbe6f21b49b98a5b898
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 /**
18 * This file defines the classes:
19 * - CProfileOwner
20 * - IAIProfileFactory
21 * - CAIGenericProfileFactory
22 * - CAIBaseProfile
23 * - CProfilePtr
26 #ifndef RYAI_AI_PROFILE_H
27 #define RYAI_AI_PROFILE_H
30 //#pragma warning (disable : 4355) // warning C4355: 'this' : used in base member initializer list
32 // This is the base class for defining NPC behaviour profiles
33 // The team infrastructure manages the allocation of AI profiles to bots
35 class CProfilePtr;
36 class IAIProfile;
38 //////////////////////////////////////////////////////////////////////////////
39 // CProfileOwner //
40 //////////////////////////////////////////////////////////////////////////////
42 class CProfileOwner
44 public:
45 virtual ~CProfileOwner() { }
48 //////////////////////////////////////////////////////////////////////////////
49 // IAIProfileFactory //
50 //////////////////////////////////////////////////////////////////////////////
52 class IAIProfileFactory
53 : public NLMISC::CDbgRefCount<IAIProfileFactory>
55 public:
56 friend class CProfilePtr;
57 virtual ~IAIProfileFactory() { }
58 virtual NLMISC::CSmartPtr<IAIProfile> createAIProfile(CProfileOwner *owner) = 0;
61 #define RYAI_DECLARE_PROFILE_FACTORY(ProfileClass) RYAI_DECLARE_FACTORY(IAIProfileFactory, ProfileClass, std::string);
62 #define RYAI_REGISTER_PROFILE_FACTORY(ProfileClass, KeyValue) RYAI_REGISTER_FACTORY(IAIProfileFactory, ProfileClass, std::string, std::string(KeyValue));
64 //////////////////////////////////////////////////////////////////////////////
65 // CAIGenericProfileFactory //
66 //////////////////////////////////////////////////////////////////////////////
68 template <class TProfile>
69 class CAIGenericProfileFactory
70 : public IAIProfileFactory
72 public:
73 NLMISC::CSmartPtr<IAIProfile> createAIProfile(CProfileOwner* owner)
75 return new TProfile(owner);
79 //////////////////////////////////////////////////////////////////////////////
80 // CAIBaseProfile //
81 //////////////////////////////////////////////////////////////////////////////
83 class IAIProfile
84 : public NLMISC::CRefCount
86 public:
87 virtual ~IAIProfile() { }
89 /// @name Virtual interface
90 //@{
91 // routine called when a profOwner starts to use a given profile
92 // note that bots have a data member called 'void *aiProfileData' reserved for the use of the profile code
93 // this data member should be setup here if it is to be used by the profile
94 virtual void beginProfile() = 0;
95 // routine called every time the profOwner is updated (frequency depends on player proximity, etc)
96 virtual void updateProfile(uint ticksSinceLastUpdate) = 0;
97 // routine called just before profOwner starts to use a new profile or when a profOwner dies
98 virtual void endProfile() = 0;
99 virtual AITYPES::TProfiles getAIProfileType() const = 0;
100 virtual std::string getOneLineInfoString() const = 0;
101 // routine called every time the profOwner's group changes state but profOwner maintains same ai profile
102 virtual void stateChangeProfile() = 0;
103 virtual void resumeProfile() = 0;
104 //@}
107 //////////////////////////////////////////////////////////////////////////////
108 // CAIBaseProfile //
109 //////////////////////////////////////////////////////////////////////////////
111 class CAIBaseProfile
112 : public IAIProfile
114 public:
115 virtual ~CAIBaseProfile() { }
117 /// @name IAIProfile base implementation
118 //@{
119 virtual void stateChangeProfile() { beginProfile(); }
120 virtual void resumeProfile() { }
121 //@}
124 //////////////////////////////////////////////////////////////////////////////
125 // CProfilePtr //
126 //////////////////////////////////////////////////////////////////////////////
128 class CProfilePtr
130 public:
131 enum TStartProfileType
133 START_BEGIN = 0,
134 START_RESUME
137 public:
138 CProfilePtr();
140 virtual ~CProfilePtr();
142 // std::string buildProfileDebugString() const;
143 virtual std::string getOneLineInfoString() const;
145 AITYPES::TProfiles getAIProfileType() const;
147 template <class T>
148 void setAIProfile(T* obj, IAIProfileFactory* profile, bool callStateChangedIfSame) const
150 if (profile)
152 setAIProfile(profile->createAIProfile(obj), callStateChangedIfSame);
156 void setAIProfile(NLMISC::CSmartPtr<IAIProfile> profile, bool callStateChangedIfSame = false, TStartProfileType startType = START_BEGIN) const;
158 void updateProfile(uint ticks) const;
160 void mayUpdateProfile(uint ticks) const;
162 IAIProfile* getAIProfile() const { return _AiProfile; }
163 NLMISC::CSmartPtr<IAIProfile> const& getAISpawnProfile() const { return _AiProfile; }
165 private:
166 mutable NLMISC::CSmartPtr<IAIProfile> _AiProfile;
167 mutable NLMISC::CSmartPtr<IAIProfile> _NextAiProfile;
168 mutable bool _NextAiProfileCallStateChangedIfSame;
170 mutable TStartProfileType _NextStartType;
171 mutable bool _IsUpdating;
174 //////////////////////////////////////////////////////////////////////////////
175 // Global functions //
176 //////////////////////////////////////////////////////////////////////////////
178 /// the lookup routine that serves as a kind of repository interface
179 IAIProfileFactory* lookupAIGrpProfile(char const* name);
181 /****************************************************************************/
182 /* Inlined methods */
183 /****************************************************************************/
185 //////////////////////////////////////////////////////////////////////////////
186 // CProfilePtr //
187 //////////////////////////////////////////////////////////////////////////////
189 inline
190 CProfilePtr::CProfilePtr()
191 : _AiProfile(NULL)
192 , _NextAiProfile(NULL)
193 , _NextStartType(START_BEGIN)
194 , _IsUpdating(false)
198 inline
199 CProfilePtr::~CProfilePtr()
201 _NextAiProfile = NULL;
202 _AiProfile = NULL;
205 inline
206 std::string CProfilePtr::getOneLineInfoString() const
208 if (_AiProfile.isNull())
209 return std::string("No Profile");
210 return _AiProfile->getOneLineInfoString();
213 inline
214 AITYPES::TProfiles CProfilePtr::getAIProfileType() const
216 if (!_AiProfile.isNull())
217 return _AiProfile->getAIProfileType();
218 return AITYPES::BAD_TYPE; // unknown
221 inline
222 void CProfilePtr::setAIProfile(NLMISC::CSmartPtr<IAIProfile> profile, bool callStateChangedIfSame, TStartProfileType startType) const
224 // :NOTE: profile can be NULL
225 if (_IsUpdating)
227 _NextAiProfileCallStateChangedIfSame = callStateChangedIfSame;
228 _NextAiProfile = profile;
229 _NextStartType = startType;
230 return;
233 if (!_AiProfile.isNull())
235 // we may use the == operator because it doesn't take account of parameters (which is bad) :(
236 if (callStateChangedIfSame==true && _AiProfile->getAIProfileType ()==profile->getAIProfileType ()) // if we already have this profile, then call its stateChangeProfile method
238 _AiProfile->stateChangeProfile();
239 return;
242 _AiProfile->endProfile();
243 _AiProfile = NULL;
246 if (!profile.isNull())
248 _AiProfile = profile;
249 if (startType==START_BEGIN)
250 _AiProfile->beginProfile();
251 else
252 _AiProfile->resumeProfile();
256 inline
257 void CProfilePtr::updateProfile(uint ticks) const
259 BOMB_IF(_AiProfile.isNull(),"Attempting updateProfile() with _AiProfile.isNull()",return);
261 _IsUpdating = true;
262 _AiProfile->updateProfile(ticks);
263 _IsUpdating = false;
265 if (!_NextAiProfile.isNull())
267 setAIProfile(_NextAiProfile, _NextAiProfileCallStateChangedIfSame, _NextStartType);
268 _NextAiProfile = NULL;
272 inline
273 void CProfilePtr::mayUpdateProfile(uint ticks) const
275 if (_AiProfile)
276 updateProfile(ticks);
279 #endif