OpenMoHAA 0.82.1
Loading...
Searching...
No Matches
characterstate.h
1/*
2===========================================================================
3Copyright (C) 2024 the OpenMoHAA team
4
5This file is part of OpenMoHAA source code.
6
7OpenMoHAA source code is free software; you can redistribute it
8and/or modify it under the terms of the GNU General Public License as
9published by the Free Software Foundation; either version 2 of the License,
10or (at your option) any later version.
11
12OpenMoHAA source code is distributed in the hope that it will be
13useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with OpenMoHAA source code; if not, write to the Free Software
19Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20===========================================================================
21*/
22
23// characterstate.h: Character state
24
25#pragma once
26
27#include "g_local.h"
28#include "entity.h"
29#include "script.h"
30
31enum testcondition_t {
32 TC_ISTRUE, // no prefix
33 TC_ISFALSE, // !
34 TC_EDGETRUE, // +
35 TC_EDGEFALSE // -
36};
37
38enum movecontrol_t {
39 MOVECONTROL_NONE,
40 MOVECONTROL_USER, // Quake style
41 MOVECONTROL_LEGS, // Quake style, legs state system active
42 MOVECONTROL_USER_MOVEANIM,
43 MOVECONTROL_ANIM, // move based on animation, with full collision testing
44 MOVECONTROL_ABSOLUTE, // move based on animation, with full collision testing but no turning
45 MOVECONTROL_HANGING, // move based on animation, with full collision testing, hanging
46 MOVECONTROL_ROPE_GRAB,
47 MOVECONTROL_ROPE_RELEASE,
48 MOVECONTROL_ROPE_MOVE,
49 MOVECONTROL_PICKUPENEMY,
50 MOVECONTROL_PUSH,
51 MOVECONTROL_CLIMBWALL,
52 MOVECONTROL_USEANIM,
53 MOVECONTROL_CROUCH,
54 MOVECONTROL_LOOPUSEANIM,
55 MOVECONTROL_USEOBJECT,
56 MOVECONTROL_COOLOBJECT,
57};
58
59enum cameratype_t {
60 CAMERA_TOPDOWN,
61 CAMERA_BEHIND,
62 CAMERA_FRONT,
63 CAMERA_SIDE,
64 CAMERA_BEHIND_FIXED,
65 CAMERA_SIDE_LEFT,
66 CAMERA_SIDE_RIGHT,
67 CAMERA_BEHIND_NOPITCH
68};
69
70#define DEFAULT_MOVETYPE MOVECONTROL_NONE
71#define DEFAULT_CAMERA CAMERA_BEHIND
72
73class Conditional;
74
75template<class Type>
76struct Condition {
77 const char *name;
78 qboolean (Type::*func)(Conditional& condition);
79};
80
81class Conditional : public Class
82{
83private:
84 qboolean result;
85 qboolean previous_result;
86 bool checked;
87
88public:
89 CLASS_PROTOTYPE(Conditional);
90
91 Condition<Class> condition;
92 Container<str> parmList;
93
94 bool getResult(testcondition_t test, Entity& ent);
95 const char *getName(void);
96
97 Conditional(Condition<Class>& condition);
98 Conditional();
99
100 const char *getParm(int number);
101 void addParm(str parm);
102 int numParms(void);
103 void clearCheck(void);
104 void clearPrevious(void);
105};
106
107inline void Conditional::addParm(str parm)
108{
109 parmList.AddObject(parm);
110}
111
112inline const char *Conditional::getParm(int number)
113{
114 if ((number < 1) || (number > parmList.NumObjects())) {
115 gi.Error(ERR_DROP, "Parm #%d out of range on %s condition\n", number, condition.name);
116 }
117 return parmList.ObjectAt(number).c_str();
118}
119
120inline int Conditional::numParms(void)
121{
122 return parmList.NumObjects();
123}
124
125inline void Conditional::clearCheck(void)
126{
127 checked = false;
128}
129
130inline void Conditional::clearPrevious(void)
131{
132 previous_result = 0;
133}
134
135inline const char *Conditional::getName(void)
136{
137 return condition.name;
138}
139
140inline bool Conditional::getResult(testcondition_t test, Entity& ent)
141{
142 if (condition.func && !checked) {
143 checked = true;
144 previous_result = result;
145
146 result = (ent.*condition.func)(*this);
147 }
148
149 switch (test) {
150 case TC_ISFALSE:
151 return !result;
152
153 case TC_EDGETRUE:
154 return result && !previous_result;
155
156 case TC_EDGEFALSE:
157 return !result && previous_result;
158
159 case TC_ISTRUE:
160 default:
161 return result != false;
162 }
163}
164
165class State;
166class StateMap;
167
168class Expression : public Class
169{
170private:
171 struct condition_t {
172 testcondition_t test;
173 int condition_index;
174 };
175
176 str value;
177 Container<condition_t> conditions;
178
179public:
180 Expression();
181 Expression(const Expression& exp);
182 Expression(Script& script, State& state);
183
184 void operator=(const Expression& exp);
185
186 bool getResult(State& state, Entity& ent, Container<Conditional *> *sent_conditionals);
187 const char *getValue(void);
188};
189
190inline void Expression::operator=(const Expression& exp)
191{
192 int i;
193
194 value = exp.value;
195
196 conditions.FreeObjectList();
197 for (i = 1; i <= exp.conditions.NumObjects(); i++) {
198 conditions.AddObject(exp.conditions.ObjectAt(i));
199 }
200}
201
202inline const char *Expression::getValue(void)
203{
204 return value.c_str();
205}
206
207class State : public Class
208{
209private:
210 Container<int> condition_indexes;
211
212 StateMap& statemap;
213
214 str name;
215
216 str nextState;
217 movecontrol_t movetype;
218 cameratype_t cameratype;
219
220 str behaviorName;
221 Container<str> behaviorParmList;
222
223 float minTime;
224 float maxTime;
225
226 Container<Expression> legAnims;
227 Container<Expression> m_actionAnims;
228 int m_iActionAnimType;
229
231 Container<str> entryCommands;
232 Container<str> exitCommands;
233
234 void readNextState(Script& script);
235 void readMoveType(Script& script);
236 void readCamera(Script& script);
237 void readLegs(Script& script);
238 void readAction(Script& script);
239 void readBehavior(Script& script);
240 void readTime(Script& script);
241 void readStates(Script& script);
242 void readCommands(Script& script, Container<str>& container);
243
244 void ParseAndProcessCommand(str command, Entity *target);
245
246public:
247 State(const char *name, Script& script, StateMap& map);
248
249 State *Evaluate(Entity& ent, Container<Conditional *> *ent_conditionals);
250 int addCondition(const char *name, Script& script);
251 void CheckStates(void);
252
253 const char *getName(void);
254
255 const char *getLegAnim(Entity& ent, Container<Conditional *> *sent_conditionals);
256 const char *getActionAnim(Entity& ent, Container<Conditional *> *sent_conditionals, int *piAnimType = NULL);
257 const char *getBehaviorName(void);
258 State *getNextState(void);
259 movecontrol_t getMoveType(void);
260 cameratype_t getCameraType(void);
261 qboolean setCameraType(str ctype);
262
263 const char *getBehaviorParm(int number = 1);
264 void addBehaviorParm(str parm);
265 int numBehaviorParms(void);
266
267 float getMinTime(void);
268 float getMaxTime(void);
269 void ProcessEntryCommands(Entity *target);
270 void ProcessExitCommands(Entity *target);
271 void GetLegAnims(Container<const char *> *c);
272 void GetActionAnims(Container<const char *> *c);
273};
274
275inline void State::addBehaviorParm(str parm)
276{
277 behaviorParmList.AddObject(parm);
278}
279
280inline const char *State::getBehaviorParm(int number)
281{
282 return behaviorParmList.ObjectAt(number).c_str();
283}
284
285inline int State::numBehaviorParms(void)
286{
287 return behaviorParmList.NumObjects();
288}
289
290class StateMap : public Class
291{
292private:
293 Container<State *> stateList;
294 Condition<Class> *current_conditions;
295 Container<Conditional *> *current_conditionals;
296 str filename;
297
298public:
299 StateMap(const char *filename, Condition<Class> *conditions, Container<Conditional *> *conditionals);
300 ~StateMap();
301
302 Condition<Class> *getCondition(const char *name);
303 int findConditional(Conditional *condition);
304 int addConditional(Conditional *condition);
305 Conditional *getConditional(const char *name);
306 void GetAllAnims(Container<const char *> *c);
307 State *FindState(const char *name);
308 const char *Filename();
309};
310
311inline const char *StateMap::Filename(void)
312{
313 return filename.c_str();
314}
315
316inline const char *State::getName(void)
317{
318 return name.c_str();
319}
320
321inline State *State::getNextState(void)
322{
323 return statemap.FindState(nextState.c_str());
324}
325
326inline movecontrol_t State::getMoveType(void)
327{
328 return movetype;
329}
330
331inline cameratype_t State::getCameraType(void)
332{
333 return cameratype;
334}
335
336void ClearCachedStatemaps(void);
337StateMap *GetStatemap(
338 str filename,
339 Condition<Class> *conditions,
340 Container<Conditional *> *conditionals,
341 qboolean reload,
342 qboolean cache_only = false
343);
344void CacheStatemap(str filename, Condition<Class> *conditions);
Definition characterstate.h:82
Definition container.h:85
Definition entity.h:203
Definition characterstate.h:169
Definition script.h:60
Definition characterstate.h:291
Definition characterstate.h:208
Definition str.h:77
Definition characterstate.h:76
Definition puff.c:88