1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
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.
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/>.
18 * This file defines the classes:
21 * - CAIGenericProfileFactory
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
38 //////////////////////////////////////////////////////////////////////////////
40 //////////////////////////////////////////////////////////////////////////////
45 virtual ~CProfileOwner() { }
48 //////////////////////////////////////////////////////////////////////////////
49 // IAIProfileFactory //
50 //////////////////////////////////////////////////////////////////////////////
52 class IAIProfileFactory
53 : public NLMISC::CDbgRefCount
<IAIProfileFactory
>
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
73 NLMISC::CSmartPtr
<IAIProfile
> createAIProfile(CProfileOwner
* owner
)
75 return new TProfile(owner
);
79 //////////////////////////////////////////////////////////////////////////////
81 //////////////////////////////////////////////////////////////////////////////
84 : public NLMISC::CRefCount
87 virtual ~IAIProfile() { }
89 /// @name Virtual interface
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;
107 //////////////////////////////////////////////////////////////////////////////
109 //////////////////////////////////////////////////////////////////////////////
115 virtual ~CAIBaseProfile() { }
117 /// @name IAIProfile base implementation
119 virtual void stateChangeProfile() { beginProfile(); }
120 virtual void resumeProfile() { }
124 //////////////////////////////////////////////////////////////////////////////
126 //////////////////////////////////////////////////////////////////////////////
131 enum TStartProfileType
140 virtual ~CProfilePtr();
142 // std::string buildProfileDebugString() const;
143 virtual std::string
getOneLineInfoString() const;
145 AITYPES::TProfiles
getAIProfileType() const;
148 void setAIProfile(T
* obj
, IAIProfileFactory
* profile
, bool callStateChangedIfSame
) const
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
; }
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 //////////////////////////////////////////////////////////////////////////////
187 //////////////////////////////////////////////////////////////////////////////
190 CProfilePtr::CProfilePtr()
192 , _NextAiProfile(NULL
)
193 , _NextStartType(START_BEGIN
)
199 CProfilePtr::~CProfilePtr()
201 _NextAiProfile
= NULL
;
206 std::string
CProfilePtr::getOneLineInfoString() const
208 if (_AiProfile
.isNull())
209 return std::string("No Profile");
210 return _AiProfile
->getOneLineInfoString();
214 AITYPES::TProfiles
CProfilePtr::getAIProfileType() const
216 if (!_AiProfile
.isNull())
217 return _AiProfile
->getAIProfileType();
218 return AITYPES::BAD_TYPE
; // unknown
222 void CProfilePtr::setAIProfile(NLMISC::CSmartPtr
<IAIProfile
> profile
, bool callStateChangedIfSame
, TStartProfileType startType
) const
224 // :NOTE: profile can be NULL
227 _NextAiProfileCallStateChangedIfSame
= callStateChangedIfSame
;
228 _NextAiProfile
= profile
;
229 _NextStartType
= startType
;
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();
242 _AiProfile
->endProfile();
246 if (!profile
.isNull())
248 _AiProfile
= profile
;
249 if (startType
==START_BEGIN
)
250 _AiProfile
->beginProfile();
252 _AiProfile
->resumeProfile();
257 void CProfilePtr::updateProfile(uint ticks
) const
259 BOMB_IF(_AiProfile
.isNull(),"Attempting updateProfile() with _AiProfile.isNull()",return);
262 _AiProfile
->updateProfile(ticks
);
265 if (!_NextAiProfile
.isNull())
267 setAIProfile(_NextAiProfile
, _NextAiProfileCallStateChangedIfSame
, _NextStartType
);
268 _NextAiProfile
= NULL
;
273 void CProfilePtr::mayUpdateProfile(uint ticks
) const
276 updateProfile(ticks
);