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