1 #ifndef __THINGDEF_H
2 #define __THINGDEF_H
3
4 #include "doomtype.h"
5 #include "info.h"
6 #include "s_sound.h"
7 #include "sc_man.h"
8 #include "cmdlib.h"
9
10
11 class FScanner;
12
13
14 //==========================================================================
15 //
16 // A flag descriptor
17 //
18 //==========================================================================
19
20 struct FFlagDef
21 {
22 unsigned int flagbit;
23 const char *name;
24 int structoffset;
25 int fieldsize;
26 };
27
28 FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2);
29 void HandleDeprecatedFlags(AActor *defaults, FActorInfo *info, bool set, int index);
30 bool CheckDeprecatedFlags(const AActor *actor, FActorInfo *info, int index);
31 const char *GetFlagName(unsigned int flagnum, int flagoffset);
32 void ModActorFlag(AActor *actor, FFlagDef *fd, bool set);
33 INTBOOL CheckActorFlag(const AActor *actor, FFlagDef *fd);
34 INTBOOL CheckActorFlag(const AActor *owner, const char *flagname, bool printerror = true);
35
36 #define FLAG_NAME(flagnum, flagvar) GetFlagName(flagnum, myoffsetof(AActor, flagvar))
37
38
39 //==========================================================================
40 //
41 // State parser
42 //
43 //==========================================================================
44 class FxExpression;
45
46 struct FStateLabels;
47
48 enum EStateDefineFlags
49 {
50 SDF_NEXT = 0,
51 SDF_STATE = 1,
52 SDF_STOP = 2,
53 SDF_WAIT = 3,
54 SDF_LABEL = 4,
55 SDF_INDEX = 5,
56 SDF_MASK = 7,
57 SDF_DEHACKED = 8, // Identify a state as having been modified by a dehacked lump
58 };
59
60 struct FStateDefine
61 {
62 FName Label;
63 TArray<FStateDefine> Children;
64 FState *State;
65 BYTE DefineFlags;
66 };
67
68 class FStateDefinitions
69 {
70 TArray<FStateDefine> StateLabels;
71 FState *laststate;
72 FState *laststatebeforelabel;
73 intptr_t lastlabel;
74 TArray<FState> StateArray;
75
76 static FStateDefine *FindStateLabelInList(TArray<FStateDefine> &list, FName name, bool create);
77 static FStateLabels *CreateStateLabelList(TArray<FStateDefine> &statelist);
78 static void MakeStateList(const FStateLabels *list, TArray<FStateDefine> &dest);
79 static void RetargetStatePointers (intptr_t count, const char *target, TArray<FStateDefine> & statelist);
80 FStateDefine *FindStateAddress(const char *name);
81 FState *FindState(const char *name);
82
83 FState *ResolveGotoLabel (AActor *actor, const PClass *mytype, char *name);
84 static void FixStatePointers (FActorInfo *actor, TArray<FStateDefine> & list);
85 void ResolveGotoLabels (FActorInfo *actor, AActor *defaults, TArray<FStateDefine> & list);
86
87 public:
88
FStateDefinitions()89 FStateDefinitions()
90 {
91 laststate = NULL;
92 laststatebeforelabel = NULL;
93 lastlabel = -1;
94 }
95
96 void SetStateLabel (const char * statename, FState * state, BYTE defflags = SDF_STATE);
97 void AddStateLabel (const char * statename);
98 int GetStateLabelIndex (FName statename);
99 void InstallStates(FActorInfo *info, AActor *defaults);
100 int FinishStates (FActorInfo *actor, AActor *defaults);
101
102 void MakeStateDefines(const PClass *cls);
103 void AddStateDefines(const FStateLabels *list);
104 void RetargetStates (intptr_t count, const char *target);
105
106 bool SetGotoLabel(const char *string);
107 bool SetStop();
108 bool SetWait();
109 bool SetLoop();
110 bool AddStates(FState *state, const char *framechars);
GetStateCount()111 int GetStateCount() const { return StateArray.Size(); }
112
113 };
114
115 //==========================================================================
116 //
117 //
118 //
119 //==========================================================================
120
121 struct FStateExpression
122 {
123 FxExpression *expr;
124 const PClass *owner;
125 bool constant;
126 bool cloned;
127 };
128
129 class FStateExpressions
130 {
131 TArray<FStateExpression> expressions;
132
133 public:
~FStateExpressions()134 ~FStateExpressions() { Clear(); }
135 void Clear();
136 int Add(FxExpression *x, const PClass *o, bool c);
137 int Reserve(int num, const PClass *cls);
138 void Set(int num, FxExpression *x, bool cloned = false);
139 void Copy(int dest, int src, int cnt);
140 int ResolveAll();
141 FxExpression *Get(int no);
Size()142 unsigned int Size() { return expressions.Size(); }
143 };
144
145 extern FStateExpressions StateParams;
146
147
148 //==========================================================================
149 //
150 // Extra info maintained while defining an actor.
151 //
152 //==========================================================================
153 struct FDropItem;
154
155 struct Baggage
156 {
157 #ifdef _DEBUG
158 FString ClassName; // This is here so that during debugging the class name can be seen
159 #endif
160 FActorInfo *Info;
161 bool DropItemSet;
162 bool StateSet;
163 int CurrentState;
164 int Lumpnum;
165 FStateDefinitions statedef;
166
167 FDropItem *DropItemList;
168
169 FScriptPosition ScriptPosition;
170 };
171
ResetBaggage(Baggage * bag,const PClass * stateclass)172 inline void ResetBaggage (Baggage *bag, const PClass *stateclass)
173 {
174 bag->DropItemList = NULL;
175 bag->DropItemSet = false;
176 bag->CurrentState = 0;
177 bag->StateSet = false;
178 bag->statedef.MakeStateDefines(stateclass);
179 }
180
181 //==========================================================================
182 //
183 // Action function lookup
184 //
185 //==========================================================================
186
187 struct AFuncDesc
188 {
189 const char *Name;
190 actionf_p Function;
191 };
192
193 AFuncDesc *FindFunction(const char * string);
194
195
196 void ParseStates(FScanner &sc, FActorInfo *actor, AActor *defaults, Baggage &bag);
197
198 PSymbolActionFunction *FindGlobalActionFunction(const char *name);
199
200 //==========================================================================
201 //
202 // Property parser
203 //
204 //==========================================================================
205
206 FActorInfo *CreateNewActor(const FScriptPosition &sc, FName typeName, FName parentName, bool native);
207 void SetReplacement(FScanner &sc, FActorInfo *info, FName replaceName);
208
209 void HandleActorFlag(FScanner &sc, Baggage &bag, const char *part1, const char *part2, int mod);
210 void FinishActor(const FScriptPosition &sc, FActorInfo *info, Baggage &bag);
211 FxExpression *ParseParameter(FScanner &sc, PClass *cls, char type, bool constant);
212
213
214 enum
215 {
216 DEPF_UNUSED,
217 DEPF_FIREDAMAGE,
218 DEPF_ICEDAMAGE,
219 DEPF_LOWGRAVITY,
220 DEPF_LONGMELEERANGE,
221 DEPF_SHORTMISSILERANGE,
222 DEPF_PICKUPFLASH,
223 DEPF_QUARTERGRAVITY,
224 DEPF_FIRERESIST,
225 DEPF_HERETICBOUNCE,
226 DEPF_HEXENBOUNCE,
227 DEPF_DOOMBOUNCE,
228 DEPF_INTERHUBSTRIP,
229 };
230
231 enum
232 {
233 ACMETA_BASE = 0x83000,
234 ACMETA_DropItems, // Int (index into DropItemList)
235 ACMETA_ExplosionDamage,
236 ACMETA_ExplosionRadius,
237 ACMETA_DontHurtShooter,
238 ACMETA_MeleeSound,
239 ACMETA_MeleeDamage,
240 ACMETA_MissileName,
241 ACMETA_MissileHeight,
242 ACMETA_Lump,
243 };
244
245
246 // Types of old style decorations
247 enum EDefinitionType
248 {
249 DEF_Decoration,
250 DEF_BreakableDecoration,
251 DEF_Pickup,
252 DEF_Projectile,
253 };
254
255 #if defined(_MSC_VER)
256 #pragma data_seg(".areg$u")
257 #pragma data_seg(".greg$u")
258 #pragma data_seg(".mreg$u")
259 #pragma data_seg()
260
261 #define MSVC_ASEG __declspec(allocate(".areg$u"))
262 #define GCC_ASEG
263 #define MSVC_PSEG __declspec(allocate(".greg$u"))
264 #define GCC_PSEG
265 #define MSVC_MSEG __declspec(allocate(".mreg$u"))
266 #define GCC_MSEG
267 #else
268 #define MSVC_ASEG
269 #define GCC_ASEG __attribute__((section(SECTION_AREG))) __attribute__((used))
270 #define MSVC_PSEG
271 #define GCC_PSEG __attribute__((section(SECTION_GREG))) __attribute__((used))
272 #define MSVC_MSEG
273 #define GCC_MSEG __attribute__((section(SECTION_MREG))) __attribute__((used))
274 #endif
275
276
277 union FPropParam
278 {
279 int i;
280 float f;
281 const char *s;
282 };
283
284 typedef void (*PropHandler)(AActor *defaults, FActorInfo *info, Baggage &bag, FPropParam *params);
285
286 enum ECategory
287 {
288 CAT_PROPERTY, // Inheritable property
289 CAT_INFO // non-inheritable info (spawn ID, Doomednum, game filter, conversation ID)
290 };
291
292 struct FPropertyInfo
293 {
294 const char *name;
295 const char *params;
296 const PClass *cls;
297 PropHandler Handler;
298 int category;
299 };
300
301 struct FVariableInfo
302 {
303 const char *name;
304 intptr_t address;
305 const PClass *owner;
306 };
307
308
309 FPropertyInfo *FindProperty(const char * string);
310 FVariableInfo *FindVariable(const char * string, const PClass *cls);
311 int MatchString (const char *in, const char **strings);
312
313
314 #define DEFINE_PROPERTY_BASE(name, paramlist, clas, cat) \
315 static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, FActorInfo *info, Baggage &bag, FPropParam *params); \
316 static FPropertyInfo Prop_##name##_##paramlist##_##clas = \
317 { #name, #paramlist, RUNTIME_CLASS(A##clas), (PropHandler)Handler_##name##_##paramlist##_##clas, cat }; \
318 MSVC_PSEG FPropertyInfo *infoptr_##name##_##paramlist##_##clas GCC_PSEG = &Prop_##name##_##paramlist##_##clas; \
319 static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, FActorInfo *info, Baggage &bag, FPropParam *params)
320
321 #define DEFINE_PREFIXED_PROPERTY_BASE(prefix, name, paramlist, clas, cat) \
322 static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, FActorInfo *info, Baggage &bag, FPropParam *params); \
323 static FPropertyInfo Prop_##name##_##paramlist##_##clas = \
324 { #prefix"."#name, #paramlist, RUNTIME_CLASS(A##clas), (PropHandler)Handler_##name##_##paramlist##_##clas, cat }; \
325 MSVC_PSEG FPropertyInfo *infoptr_##name##_##paramlist##_##clas GCC_PSEG = &Prop_##name##_##paramlist##_##clas; \
326 static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, FActorInfo *info, Baggage &bag, FPropParam *params)
327
328
329 #define DEFINE_PROPERTY(name, paramlist, clas) DEFINE_PROPERTY_BASE(name, paramlist, clas, CAT_PROPERTY)
330 #define DEFINE_INFO_PROPERTY(name, paramlist, clas) DEFINE_PROPERTY_BASE(name, paramlist, clas, CAT_INFO)
331
332 #define DEFINE_CLASS_PROPERTY(name, paramlist, clas) DEFINE_PREFIXED_PROPERTY_BASE(clas, name, paramlist, clas, CAT_PROPERTY)
333 #define DEFINE_CLASS_PROPERTY_PREFIX(prefix, name, paramlist, clas) DEFINE_PREFIXED_PROPERTY_BASE(prefix, name, paramlist, clas, CAT_PROPERTY)
334
335 #define PROP_PARM_COUNT (params[0].i)
336
337 #define PROP_STRING_PARM(var, no) \
338 const char *var = params[(no)+1].s;
339
340 #define PROP_INT_PARM(var, no) \
341 int var = params[(no)+1].i;
342
343 #define PROP_FLOAT_PARM(var, no) \
344 float var = params[(no)+1].f;
345
346 #define PROP_FIXED_PARM(var, no) \
347 fixed_t var = fixed_t(params[(no)+1].f * FRACUNIT);
348
349 #define PROP_COLOR_PARM(var, no) \
350 int var = params[(no)+1].i== 0? params[(no)+2].i : V_GetColor(NULL, params[(no)+2].s);
351
352
353 #define DEFINE_GLOBAL_VARIABLE(name) \
354 static FVariableInfo GlobalDef__##name = { #name, intptr_t(&name), NULL }; \
355 MSVC_MSEG FVariableInfo *infoptr_GlobalDef__##name GCC_MSEG = &GlobalDef__##name;
356
357 #define DEFINE_MEMBER_VARIABLE(name, cls) \
358 static FVariableInfo GlobalDef__##name = { #name, static_cast<intptr_t>(myoffsetof(cls, name)), RUNTIME_CLASS(cls) }; \
359 MSVC_MSEG FVariableInfo *infoptr_GlobalDef__##name GCC_MSEG = &GlobalDef__##name;
360
361 #define DEFINE_MEMBER_VARIABLE_ALIAS(name, alias, cls) \
362 static FVariableInfo GlobalDef__##name = { #name, static_cast<intptr_t>(myoffsetof(cls, alias)), RUNTIME_CLASS(cls) }; \
363 MSVC_MSEG FVariableInfo *infoptr_GlobalDef__##name GCC_MSEG = &GlobalDef__##name;
364
365
366
367
368 struct StateCallData
369 {
370 FState *State;
371 bool Result;
372 };
373
374 // Macros to handle action functions. These are here so that I don't have to
375 // change every single use in case the parameters change.
376 #define DECLARE_ACTION(name) void AF_##name(AActor *self, AActor *stateowner, FState *, int, StateCallData *);
377 #define DECLARE_ACTION_PARAMS(name) void AFP_##name(AActor *self, AActor *stateowner, FState *, int, StateCallData *);
378
379 // This distinction is here so that CALL_ACTION produces errors when trying to
380 // access a function that requires parameters.
381 #define DEFINE_ACTION_FUNCTION(cls, name) \
382 void AF_##name (AActor *self, AActor *stateowner, FState *, int, StateCallData *); \
383 static AFuncDesc info_##cls##_##name = { #name, AF_##name }; \
384 MSVC_ASEG AFuncDesc *infoptr_##cls##_##name GCC_ASEG = &info_##cls##_##name; \
385 void AF_##name (AActor *self, AActor *stateowner, FState *CallingState, int, StateCallData *statecall)
386
387 #define DEFINE_ACTION_FUNCTION_PARAMS(cls, name) \
388 void AFP_##name (AActor *self, AActor *stateowner, FState *CallingState, int ParameterIndex, StateCallData *statecall); \
389 static AFuncDesc info_##cls##_##name = { #name, AFP_##name }; \
390 MSVC_ASEG AFuncDesc *infoptr_##cls##_##name GCC_ASEG = &info_##cls##_##name; \
391 void AFP_##name (AActor *self, AActor *stateowner, FState *CallingState, int ParameterIndex, StateCallData *statecall)
392
393 #define DECLARE_PARAMINFO AActor *self, AActor *stateowner, FState *CallingState, int ParameterIndex, StateCallData *statecall
394 #define PUSH_PARAMINFO self, stateowner, CallingState, ParameterIndex, statecall
395
396 #define CALL_ACTION(name,self) AF_##name(self, self, NULL, 0, NULL)
397
398
399 int EvalExpressionI (DWORD x, AActor *self);
400 int EvalExpressionCol (DWORD x, AActor *self);
401 FSoundID EvalExpressionSnd (DWORD x, AActor *self);
402 double EvalExpressionF (DWORD x, AActor *self);
403 fixed_t EvalExpressionFix (DWORD x, AActor *self);
404 FState *EvalExpressionState (DWORD x, AActor *self);
405 const PClass *EvalExpressionClass (DWORD x, AActor *self);
406 FName EvalExpressionName (DWORD x, AActor *self);
407
408 #define ACTION_PARAM_START(count)
409
410 #define ACTION_PARAM_INT(var, i) \
411 int var = EvalExpressionI(ParameterIndex+i, self);
412 #define ACTION_PARAM_BOOL(var,i) \
413 bool var = !!EvalExpressionI(ParameterIndex+i, self);
414 #define ACTION_PARAM_FIXED(var,i) \
415 fixed_t var = EvalExpressionFix(ParameterIndex+i, self);
416 #define ACTION_PARAM_FLOAT(var,i) \
417 float var = float(EvalExpressionF(ParameterIndex+i, self));
418 #define ACTION_PARAM_DOUBLE(var,i) \
419 double var = EvalExpressionF(ParameterIndex+i, self);
420 #define ACTION_PARAM_CLASS(var,i) \
421 const PClass *var = EvalExpressionClass(ParameterIndex+i, self);
422 #define ACTION_PARAM_STATE(var,i) \
423 FState *var = EvalExpressionState(ParameterIndex+i, stateowner);
424 #define ACTION_PARAM_COLOR(var,i) \
425 PalEntry var = EvalExpressionCol(ParameterIndex+i, self);
426 #define ACTION_PARAM_SOUND(var,i) \
427 FSoundID var = EvalExpressionSnd(ParameterIndex+i, self);
428 #define ACTION_PARAM_STRING(var,i) \
429 const char *var = EvalExpressionName(ParameterIndex+i, self);
430 #define ACTION_PARAM_NAME(var,i) \
431 FName var = EvalExpressionName(ParameterIndex+i, self);
432 #define ACTION_PARAM_ANGLE(var,i) \
433 angle_t var = angle_t(EvalExpressionF(ParameterIndex+i, self)*ANGLE_90/90.f);
434
435 #define ACTION_SET_RESULT(v) if (statecall != NULL) statecall->Result = v;
436
437 // Checks to see what called the current action function
438 #define ACTION_CALL_FROM_ACTOR() (CallingState == self->state)
439 #define ACTION_CALL_FROM_WEAPON() (self->player && CallingState != self->state && statecall == NULL)
440 #define ACTION_CALL_FROM_INVENTORY() (statecall != NULL)
441 #endif
442