1 /*
2 ** thingdef-properties.cpp
3 **
4 ** Actor definitions - properties and flags handling
5 **
6 **---------------------------------------------------------------------------
7 ** Copyright 2002-2007 Christoph Oelckers
8 ** Copyright 2004-2007 Randy Heit
9 ** All rights reserved.
10 **
11 ** Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions
13 ** are met:
14 **
15 ** 1. Redistributions of source code must retain the above copyright
16 ** notice, this list of conditions and the following disclaimer.
17 ** 2. Redistributions in binary form must reproduce the above copyright
18 ** notice, this list of conditions and the following disclaimer in the
19 ** documentation and/or other materials provided with the distribution.
20 ** 3. The name of the author may not be used to endorse or promote products
21 ** derived from this software without specific prior written permission.
22 ** 4. When not used as part of ZDoom or a ZDoom derivative, this code will be
23 ** covered by the terms of the GNU General Public License as published by
24 ** the Free Software Foundation; either version 2 of the License, or (at
25 ** your option) any later version.
26 **
27 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
28 ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
29 ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
30 ** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
31 ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
32 ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36 ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 **---------------------------------------------------------------------------
38 **
39 */
40
41 #include "gi.h"
42 #include "actor.h"
43 #include "info.h"
44 #include "tarray.h"
45 #include "w_wad.h"
46 #include "templates.h"
47 #include "r_defs.h"
48 #include "a_pickups.h"
49 #include "s_sound.h"
50 #include "cmdlib.h"
51 #include "p_lnspec.h"
52 #include "a_action.h"
53 #include "decallib.h"
54 #include "m_random.h"
55 #include "i_system.h"
56 #include "p_local.h"
57 #include "p_effect.h"
58 #include "v_palette.h"
59 #include "doomerrors.h"
60 #include "a_hexenglobal.h"
61 #include "a_weaponpiece.h"
62 #include "p_conversation.h"
63 #include "v_text.h"
64 #include "thingdef.h"
65 #include "a_sharedglobal.h"
66 #include "r_data/r_translate.h"
67 #include "a_morph.h"
68 #include "colormatcher.h"
69 #include "teaminfo.h"
70 #include "v_video.h"
71 #include "r_data/colormaps.h"
72
73
74 //==========================================================================
75 //
76 // Gets a class pointer and performs an error check for correct type
77 //
78 //==========================================================================
FindClassTentative(const char * name,const char * ancestor)79 static const PClass *FindClassTentative(const char *name, const char *ancestor)
80 {
81 // "" and "none" mean 'no class'
82 if (name == NULL || *name == 0 || !stricmp(name, "none"))
83 {
84 return NULL;
85 }
86
87 const PClass *anc = PClass::FindClass(ancestor);
88 assert(anc != NULL); // parent classes used here should always be natively defined
89 const PClass *cls = const_cast<PClass*>(anc)->FindClassTentative(name);
90 assert (cls != NULL); // cls can not ne NULL here
91 if (!cls->IsDescendantOf(anc))
92 {
93 I_Error("%s does not inherit from %s\n", name, ancestor);
94 }
95 return cls;
96 }
97
98 //==========================================================================
99 //
100 // Sets or clears a flag, taking field width into account.
101 //
102 //==========================================================================
ModActorFlag(AActor * actor,FFlagDef * fd,bool set)103 void ModActorFlag(AActor *actor, FFlagDef *fd, bool set)
104 {
105 // Little-Endian machines only need one case, because all field sizes
106 // start at the same address. (Unless the machine has unaligned access
107 // exceptions, in which case you'll need multiple cases for it too.)
108 #ifdef __BIG_ENDIAN__
109 if (fd->fieldsize == 4)
110 #endif
111 {
112 DWORD *flagvar = (DWORD *)((char *)actor + fd->structoffset);
113 if (set)
114 {
115 *flagvar |= fd->flagbit;
116 }
117 else
118 {
119 *flagvar &= ~fd->flagbit;
120 }
121 }
122 #ifdef __BIG_ENDIAN__
123 else if (fd->fieldsize == 2)
124 {
125 WORD *flagvar = (WORD *)((char *)actor + fd->structoffset);
126 if (set)
127 {
128 *flagvar |= fd->flagbit;
129 }
130 else
131 {
132 *flagvar &= ~fd->flagbit;
133 }
134 }
135 else
136 {
137 assert(fd->fieldsize == 1);
138 BYTE *flagvar = (BYTE *)((char *)actor + fd->structoffset);
139 if (set)
140 {
141 *flagvar |= fd->flagbit;
142 }
143 else
144 {
145 *flagvar &= ~fd->flagbit;
146 }
147 }
148 #endif
149 }
150
151 //==========================================================================
152 //
153 // Returns whether an actor flag is true or not.
154 //
155 //==========================================================================
156
CheckActorFlag(const AActor * owner,FFlagDef * fd)157 INTBOOL CheckActorFlag(const AActor *owner, FFlagDef *fd)
158 {
159 if (fd->structoffset == -1)
160 {
161 return CheckDeprecatedFlags(owner, owner->GetClass()->ActorInfo, fd->flagbit);
162 }
163 else
164 #ifdef __BIG_ENDIAN__
165 if (fd->fieldsize == 4)
166 #endif
167 {
168 return fd->flagbit & *(DWORD *)(((char*)owner) + fd->structoffset);
169 }
170 #ifdef __BIG_ENDIAN__
171 else if (fd->fieldsize == 2)
172 {
173 return fd->flagbit & *(WORD *)(((char*)owner) + fd->structoffset);
174 }
175 else
176 {
177 assert(fd->fieldsize == 1);
178 return fd->flagbit & *(BYTE *)(((char*)owner) + fd->structoffset);
179 }
180 #endif
181 }
182
CheckActorFlag(const AActor * owner,const char * flagname,bool printerror)183 INTBOOL CheckActorFlag(const AActor *owner, const char *flagname, bool printerror)
184 {
185 const char *dot = strchr (flagname, '.');
186 FFlagDef *fd;
187 const PClass *cls = owner->GetClass();
188
189 if (dot != NULL)
190 {
191 FString part1(flagname, dot-flagname);
192 fd = FindFlag (cls, part1, dot+1);
193 }
194 else
195 {
196 fd = FindFlag (cls, flagname, NULL);
197 }
198
199 if (fd != NULL)
200 {
201 return CheckActorFlag(owner, fd);
202 }
203 else
204 {
205 if (printerror) Printf("Unknown flag '%s' in '%s'\n", flagname, cls->TypeName.GetChars());
206 return false;
207 }
208 }
209
210 //===========================================================================
211 //
212 // HandleDeprecatedFlags
213 //
214 // Handles the deprecated flags and sets the respective properties
215 // to appropriate values. This is solely intended for backwards
216 // compatibility so mixing this with code that is aware of the real
217 // properties is not recommended
218 //
219 //===========================================================================
HandleDeprecatedFlags(AActor * defaults,FActorInfo * info,bool set,int index)220 void HandleDeprecatedFlags(AActor *defaults, FActorInfo *info, bool set, int index)
221 {
222 switch (index)
223 {
224 case DEPF_FIREDAMAGE:
225 defaults->DamageType = set? NAME_Fire : NAME_None;
226 break;
227 case DEPF_ICEDAMAGE:
228 defaults->DamageType = set? NAME_Ice : NAME_None;
229 break;
230 case DEPF_LOWGRAVITY:
231 defaults->gravity = set? FRACUNIT/8 : FRACUNIT;
232 break;
233 case DEPF_SHORTMISSILERANGE:
234 defaults->maxtargetrange = set? 896*FRACUNIT : 0;
235 break;
236 case DEPF_LONGMELEERANGE:
237 defaults->meleethreshold = set? 196*FRACUNIT : 0;
238 break;
239 case DEPF_QUARTERGRAVITY:
240 defaults->gravity = set? FRACUNIT/4 : FRACUNIT;
241 break;
242 case DEPF_FIRERESIST:
243 info->SetDamageFactor(NAME_Fire, set? FRACUNIT/2 : FRACUNIT);
244 break;
245 // the bounce flags will set the compatibility bounce modes to remain compatible
246 case DEPF_HERETICBOUNCE:
247 defaults->BounceFlags &= ~(BOUNCE_TypeMask|BOUNCE_UseSeeSound);
248 if (set) defaults->BounceFlags |= BOUNCE_HereticCompat;
249 break;
250 case DEPF_HEXENBOUNCE:
251 defaults->BounceFlags &= ~(BOUNCE_TypeMask|BOUNCE_UseSeeSound);
252 if (set) defaults->BounceFlags |= BOUNCE_HexenCompat;
253 break;
254 case DEPF_DOOMBOUNCE:
255 defaults->BounceFlags &= ~(BOUNCE_TypeMask|BOUNCE_UseSeeSound);
256 if (set) defaults->BounceFlags |= BOUNCE_DoomCompat;
257 break;
258 case DEPF_PICKUPFLASH:
259 if (set)
260 {
261 static_cast<AInventory*>(defaults)->PickupFlash = FindClassTentative("PickupFlash", "Actor");
262 }
263 else
264 {
265 static_cast<AInventory*>(defaults)->PickupFlash = NULL;
266 }
267 break;
268 case DEPF_INTERHUBSTRIP: // Old system was 0 or 1, so if the flag is cleared, assume 1.
269 static_cast<AInventory*>(defaults)->InterHubAmount = set ? 0 : 1;
270 default:
271 break; // silence GCC
272 }
273 }
274
275 //===========================================================================
276 //
277 // CheckDeprecatedFlags
278 //
279 // Checks properties related to deprecated flags, and returns true only
280 // if the relevant properties are configured exactly as they would have
281 // been by setting the flag in HandleDeprecatedFlags.
282 //
283 //===========================================================================
284
CheckDeprecatedFlags(const AActor * actor,FActorInfo * info,int index)285 bool CheckDeprecatedFlags(const AActor *actor, FActorInfo *info, int index)
286 {
287 // A deprecated flag is false if
288 // a) it hasn't been added here
289 // b) any property of the actor differs from what it would be after setting the flag using HandleDeprecatedFlags
290
291 // Deprecated flags are normally replaced by something more flexible, which means a multitude of related configurations
292 // will report "false".
293
294 switch (index)
295 {
296 case DEPF_FIREDAMAGE:
297 return actor->DamageType == NAME_Fire;
298 case DEPF_ICEDAMAGE:
299 return actor->DamageType == NAME_Ice;
300 case DEPF_LOWGRAVITY:
301 return actor->gravity == FRACUNIT/8;
302 case DEPF_SHORTMISSILERANGE:
303 return actor->maxtargetrange == 896*FRACUNIT;
304 case DEPF_LONGMELEERANGE:
305 return actor->meleethreshold == 196*FRACUNIT;
306 case DEPF_QUARTERGRAVITY:
307 return actor->gravity == FRACUNIT/4;
308 case DEPF_FIRERESIST:
309 if (info->DamageFactors)
310 {
311 fixed_t *df = info->DamageFactors->CheckKey(NAME_Fire);
312 return df && (*df) == FRACUNIT / 2;
313 }
314 return false;
315
316 case DEPF_HERETICBOUNCE:
317 return (actor->BounceFlags & (BOUNCE_TypeMask|BOUNCE_UseSeeSound)) == BOUNCE_HereticCompat;
318
319 case DEPF_HEXENBOUNCE:
320 return (actor->BounceFlags & (BOUNCE_TypeMask|BOUNCE_UseSeeSound)) == BOUNCE_HexenCompat;
321
322 case DEPF_DOOMBOUNCE:
323 return (actor->BounceFlags & (BOUNCE_TypeMask|BOUNCE_UseSeeSound)) == BOUNCE_DoomCompat;
324
325 case DEPF_PICKUPFLASH:
326 return static_cast<const AInventory*>(actor)->PickupFlash == PClass::FindClass("PickupFlash");
327 // A pure name lookup may or may not be more efficient, but I know no static identifier for PickupFlash.
328
329 case DEPF_INTERHUBSTRIP:
330 return !(static_cast<const AInventory*>(actor)->InterHubAmount);
331 }
332
333 return false; // Any entirely unknown flag is not set
334 }
335
336 //==========================================================================
337 //
338 //
339 //
340 //==========================================================================
MatchString(const char * in,const char ** strings)341 int MatchString (const char *in, const char **strings)
342 {
343 int i;
344
345 for (i = 0; *strings != NULL; i++)
346 {
347 if (!stricmp(in, *strings++))
348 {
349 return i;
350 }
351 }
352 return -1;
353 }
354
355 //==========================================================================
356 //
357 // Info Property handlers
358 //
359 //==========================================================================
360
361 //==========================================================================
362 //
363 //==========================================================================
DEFINE_INFO_PROPERTY(game,S,Actor)364 DEFINE_INFO_PROPERTY(game, S, Actor)
365 {
366 PROP_STRING_PARM(str, 0);
367 if (!stricmp(str, "Doom"))
368 {
369 info->GameFilter |= GAME_Doom;
370 }
371 else if (!stricmp(str, "Heretic"))
372 {
373 info->GameFilter |= GAME_Heretic;
374 }
375 else if (!stricmp(str, "Hexen"))
376 {
377 info->GameFilter |= GAME_Hexen;
378 }
379 else if (!stricmp(str, "Raven"))
380 {
381 info->GameFilter |= GAME_Raven;
382 }
383 else if (!stricmp(str, "Strife"))
384 {
385 info->GameFilter |= GAME_Strife;
386 }
387 else if (!stricmp(str, "Chex"))
388 {
389 info->GameFilter |= GAME_Chex;
390 }
391 else if (!stricmp(str, "Any"))
392 {
393 info->GameFilter = GAME_Any;
394 }
395 else
396 {
397 I_Error ("Unknown game type %s", str);
398 }
399 }
400
401 //==========================================================================
402 //
403 //==========================================================================
DEFINE_INFO_PROPERTY(spawnid,I,Actor)404 DEFINE_INFO_PROPERTY(spawnid, I, Actor)
405 {
406 PROP_INT_PARM(id, 0);
407 if (id<0 || id>65535)
408 {
409 I_Error ("SpawnID must be in the range [0,65535]");
410 }
411 else info->SpawnID=(WORD)id;
412 }
413
414 //==========================================================================
415 //
416 //==========================================================================
DEFINE_INFO_PROPERTY(conversationid,IiI,Actor)417 DEFINE_INFO_PROPERTY(conversationid, IiI, Actor)
418 {
419 PROP_INT_PARM(convid, 0);
420 PROP_INT_PARM(id1, 1);
421 PROP_INT_PARM(id2, 2);
422
423 if (convid <= 0 || convid > 65535) return; // 0 is not usable because the dialogue scripts use it as 'no object'.
424 else info->ConversationID=(WORD)convid;
425 }
426
427 //==========================================================================
428 //
429 // Property handlers
430 //
431 //==========================================================================
432
433 //==========================================================================
434 //
435 //==========================================================================
436 DEFINE_PROPERTY(skip_super, 0, Actor)
437 {
438 if (info->Class->IsDescendantOf(RUNTIME_CLASS(AInventory)))
439 {
440 bag.ScriptPosition.Message(MSG_WARNING,
441 "'skip_super' in definition of inventory item '%s' ignored.", info->Class->TypeName.GetChars() );
442 return;
443 }
444 if (bag.StateSet)
445 {
446 bag.ScriptPosition.Message(MSG_WARNING,
447 "'skip_super' must appear before any state definitions.");
448 return;
449 }
450
451 memcpy ((void *)defaults, (void *)GetDefault<AActor>(), sizeof(AActor));
452 if (bag.DropItemList != NULL)
453 {
454 FreeDropItemChain (bag.DropItemList);
455 }
456 ResetBaggage (&bag, RUNTIME_CLASS(AActor));
457 }
458
459 //==========================================================================
460 //
461 //==========================================================================
DEFINE_PROPERTY(tag,S,Actor)462 DEFINE_PROPERTY(tag, S, Actor)
463 {
464 PROP_STRING_PARM(str, 0);
465 defaults->SetTag(str);
466 }
467
468 //==========================================================================
469 //
470 //==========================================================================
DEFINE_PROPERTY(health,I,Actor)471 DEFINE_PROPERTY(health, I, Actor)
472 {
473 PROP_INT_PARM(id, 0);
474 defaults->health=id;
475 }
476
477 //==========================================================================
478 //
479 //==========================================================================
DEFINE_PROPERTY(gibhealth,I,Actor)480 DEFINE_PROPERTY(gibhealth, I, Actor)
481 {
482 PROP_INT_PARM(id, 0);
483 info->Class->Meta.SetMetaInt (AMETA_GibHealth, id);
484 }
485
486 //==========================================================================
487 //
488 //==========================================================================
DEFINE_PROPERTY(woundhealth,I,Actor)489 DEFINE_PROPERTY(woundhealth, I, Actor)
490 {
491 PROP_INT_PARM(id, 0);
492 info->Class->Meta.SetMetaInt (AMETA_WoundHealth, id);
493 }
494
495 //==========================================================================
496 //
497 //==========================================================================
DEFINE_PROPERTY(reactiontime,I,Actor)498 DEFINE_PROPERTY(reactiontime, I, Actor)
499 {
500 PROP_INT_PARM(id, 0);
501 defaults->reactiontime=id;
502 }
503
504 //==========================================================================
505 //
506 //==========================================================================
DEFINE_PROPERTY(painchance,ZI,Actor)507 DEFINE_PROPERTY(painchance, ZI, Actor)
508 {
509 PROP_STRING_PARM(str, 0);
510 PROP_INT_PARM(id, 1);
511 if (str == NULL)
512 {
513 defaults->PainChance=id;
514 }
515 else
516 {
517 FName painType;
518 if (!stricmp(str, "Normal")) painType = NAME_None;
519 else painType=str;
520
521 info->SetPainChance(painType, id);
522 }
523 }
524
525 //==========================================================================
526 //
527 //==========================================================================
DEFINE_PROPERTY(painthreshold,I,Actor)528 DEFINE_PROPERTY(painthreshold, I, Actor)
529 {
530 PROP_INT_PARM(id, 0);
531
532 defaults->PainThreshold = id;
533 }
534
535 //==========================================================================
536 //
537 //==========================================================================
DEFINE_PROPERTY(damage,X,Actor)538 DEFINE_PROPERTY(damage, X, Actor)
539 {
540 PROP_INT_PARM(id, 0);
541
542 // Damage can either be a single number, in which case it is subject
543 // to the original damage calculation rules. Or, it can be an expression
544 // and will be calculated as-is, ignoring the original rules. For
545 // compatibility reasons, expressions must be enclosed within
546 // parentheses.
547
548 defaults->Damage = id;
549 }
550
551 //==========================================================================
552 //
553 //==========================================================================
DEFINE_PROPERTY(projectilekickback,I,Actor)554 DEFINE_PROPERTY(projectilekickback, I, Actor)
555 {
556 PROP_INT_PARM(id, 0);
557
558 defaults->projectileKickback = id;
559 }
560
561 //==========================================================================
562 //
563 //==========================================================================
DEFINE_PROPERTY(speed,F,Actor)564 DEFINE_PROPERTY(speed, F, Actor)
565 {
566 PROP_FIXED_PARM(id, 0);
567 defaults->Speed = id;
568 }
569
570 //==========================================================================
571 //
572 //==========================================================================
DEFINE_PROPERTY(floatspeed,F,Actor)573 DEFINE_PROPERTY(floatspeed, F, Actor)
574 {
575 PROP_FIXED_PARM(id, 0);
576 defaults->FloatSpeed=id;
577 }
578
579 //==========================================================================
580 //
581 //==========================================================================
DEFINE_PROPERTY(radius,F,Actor)582 DEFINE_PROPERTY(radius, F, Actor)
583 {
584 PROP_FIXED_PARM(id, 0);
585 defaults->radius=id;
586 }
587
588 //==========================================================================
589 //
590 //==========================================================================
DEFINE_PROPERTY(height,F,Actor)591 DEFINE_PROPERTY(height, F, Actor)
592 {
593 PROP_FIXED_PARM(id, 0);
594 defaults->height=id;
595 }
596
597 //==========================================================================
598 //
599 //==========================================================================
DEFINE_PROPERTY(projectilepassheight,F,Actor)600 DEFINE_PROPERTY(projectilepassheight, F, Actor)
601 {
602 PROP_FIXED_PARM(id, 0);
603 defaults->projectilepassheight=id;
604 }
605
606 //==========================================================================
607 //
608 //==========================================================================
DEFINE_PROPERTY(mass,I,Actor)609 DEFINE_PROPERTY(mass, I, Actor)
610 {
611 PROP_INT_PARM(id, 0);
612 defaults->Mass=id;
613 }
614
615 //==========================================================================
616 //
617 //==========================================================================
DEFINE_PROPERTY(xscale,F,Actor)618 DEFINE_PROPERTY(xscale, F, Actor)
619 {
620 PROP_FIXED_PARM(id, 0);
621 defaults->scaleX = id;
622 }
623
624 //==========================================================================
625 //
626 //==========================================================================
DEFINE_PROPERTY(yscale,F,Actor)627 DEFINE_PROPERTY(yscale, F, Actor)
628 {
629 PROP_FIXED_PARM(id, 0);
630 defaults->scaleY = id;
631 }
632
633 //==========================================================================
634 //
635 //==========================================================================
DEFINE_PROPERTY(scale,F,Actor)636 DEFINE_PROPERTY(scale, F, Actor)
637 {
638 PROP_FIXED_PARM(id, 0);
639 defaults->scaleX = defaults->scaleY = id;
640 }
641
642 //==========================================================================
643 //
644 //==========================================================================
DEFINE_PROPERTY(floatbobphase,I,Actor)645 DEFINE_PROPERTY(floatbobphase, I, Actor)
646 {
647 PROP_INT_PARM(id, 0);
648 if (id < -1 || id >= 64) I_Error ("FloatBobPhase must be in range [-1,63]");
649 defaults->FloatBobPhase = id;
650 }
651
652 //==========================================================================
653 //
654 //==========================================================================
DEFINE_PROPERTY(args,Iiiii,Actor)655 DEFINE_PROPERTY(args, Iiiii, Actor)
656 {
657 for (int i = 0; i < PROP_PARM_COUNT; i++)
658 {
659 PROP_INT_PARM(id, i);
660 defaults->args[i] = id;
661 }
662 defaults->flags2|=MF2_ARGSDEFINED;
663 }
664
665 //==========================================================================
666 //
667 //==========================================================================
DEFINE_PROPERTY(seesound,S,Actor)668 DEFINE_PROPERTY(seesound, S, Actor)
669 {
670 PROP_STRING_PARM(str, 0);
671 defaults->SeeSound = str;
672 }
673
674 //==========================================================================
675 //
676 //==========================================================================
DEFINE_PROPERTY(attacksound,S,Actor)677 DEFINE_PROPERTY(attacksound, S, Actor)
678 {
679 PROP_STRING_PARM(str, 0);
680 defaults->AttackSound = str;
681 }
682
683 //==========================================================================
684 //
685 //==========================================================================
DEFINE_PROPERTY(bouncesound,S,Actor)686 DEFINE_PROPERTY(bouncesound, S, Actor)
687 {
688 PROP_STRING_PARM(str, 0);
689 defaults->BounceSound = str;
690 }
691
692 //==========================================================================
693 //
694 //==========================================================================
DEFINE_PROPERTY(wallbouncesound,S,Actor)695 DEFINE_PROPERTY(wallbouncesound, S, Actor)
696 {
697 PROP_STRING_PARM(str, 0);
698 defaults->WallBounceSound = str;
699 }
700
701 //==========================================================================
702 //
703 //==========================================================================
DEFINE_PROPERTY(painsound,S,Actor)704 DEFINE_PROPERTY(painsound, S, Actor)
705 {
706 PROP_STRING_PARM(str, 0);
707 defaults->PainSound = str;
708 }
709
710 //==========================================================================
711 //
712 //==========================================================================
DEFINE_PROPERTY(deathsound,S,Actor)713 DEFINE_PROPERTY(deathsound, S, Actor)
714 {
715 PROP_STRING_PARM(str, 0);
716 defaults->DeathSound = str;
717 }
718
719 //==========================================================================
720 //
721 //==========================================================================
DEFINE_PROPERTY(activesound,S,Actor)722 DEFINE_PROPERTY(activesound, S, Actor)
723 {
724 PROP_STRING_PARM(str, 0);
725 defaults->ActiveSound = str;
726 }
727
728 //==========================================================================
729 //
730 //==========================================================================
DEFINE_PROPERTY(howlsound,S,Actor)731 DEFINE_PROPERTY(howlsound, S, Actor)
732 {
733 PROP_STRING_PARM(str, 0);
734 info->Class->Meta.SetMetaInt (AMETA_HowlSound, S_FindSound(str));
735 }
736
737 //==========================================================================
738 //
739 //==========================================================================
DEFINE_PROPERTY(crushpainsound,S,Actor)740 DEFINE_PROPERTY(crushpainsound, S, Actor)
741 {
742 PROP_STRING_PARM(str, 0);
743 defaults->CrushPainSound = str;
744 }
745
746 //==========================================================================
747 //
748 //==========================================================================
DEFINE_PROPERTY(dropitem,S_i_i,Actor)749 DEFINE_PROPERTY(dropitem, S_i_i, Actor)
750 {
751 PROP_STRING_PARM(type, 0);
752
753 // create a linked list of dropitems
754 if (!bag.DropItemSet)
755 {
756 bag.DropItemSet = true;
757 bag.DropItemList = NULL;
758 }
759
760 FDropItem *di = new FDropItem;
761
762 di->Name =type;
763 di->probability=255;
764 di->amount=-1;
765
766 if (PROP_PARM_COUNT > 1)
767 {
768 PROP_INT_PARM(prob, 1);
769 di->probability = prob;
770 if (PROP_PARM_COUNT > 2)
771 {
772 PROP_INT_PARM(amt, 2);
773 di->amount = amt;
774 }
775 }
776 di->Next = bag.DropItemList;
777 bag.DropItemList = di;
778 }
779
780 //==========================================================================
781 //
782 //==========================================================================
DEFINE_PROPERTY(renderstyle,S,Actor)783 DEFINE_PROPERTY(renderstyle, S, Actor)
784 {
785 PROP_STRING_PARM(str, 0);
786 static const char * renderstyles[]={
787 "NONE", "NORMAL", "FUZZY", "SOULTRANS", "OPTFUZZY", "STENCIL",
788 "TRANSLUCENT", "ADD", "SHADED", "SHADOW", "SUBTRACT", "ADDSTENCIL", "ADDSHADED", NULL };
789
790 static const int renderstyle_values[]={
791 STYLE_None, STYLE_Normal, STYLE_Fuzzy, STYLE_SoulTrans, STYLE_OptFuzzy,
792 STYLE_TranslucentStencil, STYLE_Translucent, STYLE_Add, STYLE_Shaded,
793 STYLE_Shadow, STYLE_Subtract, STYLE_AddStencil, STYLE_AddShaded};
794
795 // make this work for old style decorations, too.
796 if (!strnicmp(str, "style_", 6)) str+=6;
797
798 int style = MatchString(str, renderstyles);
799 if (style < 0) I_Error("Unknown render style '%s'", str);
800 defaults->RenderStyle = LegacyRenderStyles[renderstyle_values[style]];
801 }
802
803 //==========================================================================
804 //
805 //==========================================================================
806 DEFINE_PROPERTY(defaultalpha, 0, Actor)
807 {
808 defaults->alpha = gameinfo.gametype == GAME_Heretic ? HR_SHADOW : HX_SHADOW;
809 }
810
811 //==========================================================================
812 //
813 //==========================================================================
DEFINE_PROPERTY(alpha,F,Actor)814 DEFINE_PROPERTY(alpha, F, Actor)
815 {
816 PROP_FIXED_PARM(id, 0);
817 defaults->alpha = id;
818 }
819
820 //==========================================================================
821 //
822 //==========================================================================
DEFINE_PROPERTY(obituary,S,Actor)823 DEFINE_PROPERTY(obituary, S, Actor)
824 {
825 PROP_STRING_PARM(str, 0);
826 info->Class->Meta.SetMetaString (AMETA_Obituary, str);
827 }
828
829 //==========================================================================
830 //
831 //==========================================================================
DEFINE_PROPERTY(hitobituary,S,Actor)832 DEFINE_PROPERTY(hitobituary, S, Actor)
833 {
834 PROP_STRING_PARM(str, 0);
835 info->Class->Meta.SetMetaString (AMETA_HitObituary, str);
836 }
837
838 //==========================================================================
839 //
840 //==========================================================================
841 DEFINE_PROPERTY(donthurtshooter, 0, Actor)
842 {
843 info->Class->Meta.SetMetaInt (ACMETA_DontHurtShooter, true);
844 }
845
846 //==========================================================================
847 //
848 //==========================================================================
DEFINE_PROPERTY(explosionradius,I,Actor)849 DEFINE_PROPERTY(explosionradius, I, Actor)
850 {
851 PROP_INT_PARM(id, 0);
852 info->Class->Meta.SetMetaInt (ACMETA_ExplosionRadius, id);
853 }
854
855 //==========================================================================
856 //
857 //==========================================================================
DEFINE_PROPERTY(explosiondamage,I,Actor)858 DEFINE_PROPERTY(explosiondamage, I, Actor)
859 {
860 PROP_INT_PARM(id, 0);
861 info->Class->Meta.SetMetaInt (ACMETA_ExplosionDamage, id);
862 }
863
864 //==========================================================================
865 //
866 //==========================================================================
DEFINE_PROPERTY(deathheight,F,Actor)867 DEFINE_PROPERTY(deathheight, F, Actor)
868 {
869 PROP_FIXED_PARM(h, 0);
870 // AActor::Die() uses a height of 0 to mean "cut the height to 1/4",
871 // so if a height of 0 is desired, store it as -1.
872 info->Class->Meta.SetMetaFixed (AMETA_DeathHeight, h <= 0 ? -1 : h);
873 }
874
875 //==========================================================================
876 //
877 //==========================================================================
DEFINE_PROPERTY(burnheight,F,Actor)878 DEFINE_PROPERTY(burnheight, F, Actor)
879 {
880 PROP_FIXED_PARM(h, 0);
881 // The note above for AMETA_DeathHeight also applies here.
882 info->Class->Meta.SetMetaFixed (AMETA_BurnHeight, h <= 0 ? -1 : h);
883 }
884
885 //==========================================================================
886 //
887 //==========================================================================
DEFINE_PROPERTY(maxtargetrange,F,Actor)888 DEFINE_PROPERTY(maxtargetrange, F, Actor)
889 {
890 PROP_FIXED_PARM(id, 0);
891 defaults->maxtargetrange = id;
892 }
893
894 //==========================================================================
895 //
896 //==========================================================================
DEFINE_PROPERTY(meleethreshold,F,Actor)897 DEFINE_PROPERTY(meleethreshold, F, Actor)
898 {
899 PROP_FIXED_PARM(id, 0);
900 defaults->meleethreshold = id;
901 }
902
903 //==========================================================================
904 //
905 //==========================================================================
DEFINE_PROPERTY(meleedamage,I,Actor)906 DEFINE_PROPERTY(meleedamage, I, Actor)
907 {
908 PROP_INT_PARM(id, 0);
909 info->Class->Meta.SetMetaInt (ACMETA_MeleeDamage, id);
910 }
911
912 //==========================================================================
913 //
914 //==========================================================================
DEFINE_PROPERTY(meleerange,F,Actor)915 DEFINE_PROPERTY(meleerange, F, Actor)
916 {
917 PROP_FIXED_PARM(id, 0);
918 defaults->meleerange = id;
919 }
920
921 //==========================================================================
922 //
923 //==========================================================================
DEFINE_PROPERTY(meleesound,S,Actor)924 DEFINE_PROPERTY(meleesound, S, Actor)
925 {
926 PROP_STRING_PARM(str, 0);
927 info->Class->Meta.SetMetaInt (ACMETA_MeleeSound, S_FindSound(str));
928 }
929
930 //==========================================================================
931 //
932 //==========================================================================
DEFINE_PROPERTY(missiletype,S,Actor)933 DEFINE_PROPERTY(missiletype, S, Actor)
934 {
935 PROP_STRING_PARM(str, 0);
936 info->Class->Meta.SetMetaInt (ACMETA_MissileName, FName(str));
937 }
938
939 //==========================================================================
940 //
941 //==========================================================================
DEFINE_PROPERTY(missileheight,F,Actor)942 DEFINE_PROPERTY(missileheight, F, Actor)
943 {
944 PROP_FIXED_PARM(id, 0);
945 info->Class->Meta.SetMetaFixed (ACMETA_MissileHeight, id);
946 }
947
948 //==========================================================================
949 //
950 //==========================================================================
DEFINE_PROPERTY(pushfactor,F,Actor)951 DEFINE_PROPERTY(pushfactor, F, Actor)
952 {
953 PROP_FIXED_PARM(id, 0);
954 defaults->pushfactor = id;
955 }
956
957 //==========================================================================
958 //
959 //==========================================================================
DEFINE_PROPERTY(translation,L,Actor)960 DEFINE_PROPERTY(translation, L, Actor)
961 {
962 PROP_INT_PARM(type, 0);
963
964 if (type == 0)
965 {
966 PROP_INT_PARM(trans, 1);
967 int max = 6;// (gameinfo.gametype == GAME_Strife || (info->GameFilter&GAME_Strife)) ? 6 : 2;
968 if (trans < 0 || trans > max)
969 {
970 I_Error ("Translation must be in the range [0,%d]", max);
971 }
972 defaults->Translation = TRANSLATION(TRANSLATION_Standard, trans);
973 }
974 else
975 {
976 FRemapTable CurrentTranslation;
977
978 CurrentTranslation.MakeIdentity();
979 for(int i = 1; i < PROP_PARM_COUNT; i++)
980 {
981 PROP_STRING_PARM(str, i);
982 if (i== 1 && PROP_PARM_COUNT == 2 && !stricmp(str, "Ice"))
983 {
984 defaults->Translation = TRANSLATION(TRANSLATION_Standard, 7);
985 return;
986 }
987 else
988 {
989 CurrentTranslation.AddToTranslation(str);
990 }
991 }
992 defaults->Translation = CurrentTranslation.StoreTranslation ();
993 }
994 }
995
996 //==========================================================================
997 //
998 //==========================================================================
DEFINE_PROPERTY(stencilcolor,C,Actor)999 DEFINE_PROPERTY(stencilcolor, C, Actor)
1000 {
1001 PROP_COLOR_PARM(color, 0);
1002
1003 defaults->fillcolor = color | (ColorMatcher.Pick (RPART(color), GPART(color), BPART(color)) << 24);
1004 }
1005
1006 //==========================================================================
1007 //
1008 //==========================================================================
DEFINE_PROPERTY(bloodcolor,C,Actor)1009 DEFINE_PROPERTY(bloodcolor, C, Actor)
1010 {
1011 PROP_COLOR_PARM(color, 0);
1012
1013 PalEntry pe = color;
1014 pe.a = CreateBloodTranslation(pe);
1015 info->Class->Meta.SetMetaInt (AMETA_BloodColor, pe);
1016 }
1017
1018
1019 //==========================================================================
1020 //
1021 //==========================================================================
DEFINE_PROPERTY(bloodtype,Sss,Actor)1022 DEFINE_PROPERTY(bloodtype, Sss, Actor)
1023 {
1024 PROP_STRING_PARM(str, 0)
1025 PROP_STRING_PARM(str1, 1)
1026 PROP_STRING_PARM(str2, 2)
1027
1028 FName blood = str;
1029 // normal blood
1030 info->Class->Meta.SetMetaInt (AMETA_BloodType, blood);
1031
1032 if (PROP_PARM_COUNT > 1)
1033 {
1034 blood = str1;
1035 }
1036 // blood splatter
1037 info->Class->Meta.SetMetaInt (AMETA_BloodType2, blood);
1038
1039 if (PROP_PARM_COUNT > 2)
1040 {
1041 blood = str2;
1042 }
1043 // axe blood
1044 info->Class->Meta.SetMetaInt (AMETA_BloodType3, blood);
1045 }
1046
1047 //==========================================================================
1048 //
1049 //==========================================================================
DEFINE_PROPERTY(bouncetype,S,Actor)1050 DEFINE_PROPERTY(bouncetype, S, Actor)
1051 {
1052 static const char *names[] = { "None", "Doom", "Heretic", "Hexen", "DoomCompat", "HereticCompat", "HexenCompat", "Grenade", "Classic", NULL };
1053 static const ActorBounceFlag flags[] = { BOUNCE_None,
1054 BOUNCE_Doom, BOUNCE_Heretic, BOUNCE_Hexen,
1055 BOUNCE_DoomCompat, BOUNCE_HereticCompat, BOUNCE_HexenCompat,
1056 BOUNCE_Grenade, BOUNCE_Classic, };
1057 PROP_STRING_PARM(id, 0);
1058 int match = MatchString(id, names);
1059 if (match < 0)
1060 {
1061 I_Error("Unknown bouncetype %s", id);
1062 match = 0;
1063 }
1064 defaults->BounceFlags &= ~(BOUNCE_TypeMask | BOUNCE_UseSeeSound);
1065 defaults->BounceFlags |= flags[match];
1066 if (defaults->BounceFlags & (BOUNCE_Actors | BOUNCE_AllActors))
1067 {
1068 // PASSMOBJ is irrelevant for normal missiles, but not for bouncers.
1069 defaults->flags2 |= MF2_PASSMOBJ;
1070 }
1071 }
1072
1073 //==========================================================================
1074 //
1075 //==========================================================================
DEFINE_PROPERTY(bouncefactor,F,Actor)1076 DEFINE_PROPERTY(bouncefactor, F, Actor)
1077 {
1078 PROP_FIXED_PARM(id, 0);
1079 defaults->bouncefactor = clamp<fixed_t>(id, 0, FRACUNIT);
1080 }
1081
1082 //==========================================================================
1083 //
1084 //==========================================================================
DEFINE_PROPERTY(wallbouncefactor,F,Actor)1085 DEFINE_PROPERTY(wallbouncefactor, F, Actor)
1086 {
1087 PROP_FIXED_PARM(id, 0);
1088 defaults->wallbouncefactor = clamp<fixed_t>(id, 0, FRACUNIT);
1089 }
1090
1091 //==========================================================================
1092 //
1093 //==========================================================================
DEFINE_PROPERTY(bouncecount,I,Actor)1094 DEFINE_PROPERTY(bouncecount, I, Actor)
1095 {
1096 PROP_INT_PARM(id, 0);
1097 defaults->bouncecount = id;
1098 }
1099
1100 //==========================================================================
1101 //
1102 //==========================================================================
DEFINE_PROPERTY(weaveindexXY,I,Actor)1103 DEFINE_PROPERTY(weaveindexXY, I, Actor)
1104 {
1105 PROP_INT_PARM(id, 0);
1106 defaults->WeaveIndexXY = id;
1107 }
1108
1109 //==========================================================================
1110 //
1111 //==========================================================================
DEFINE_PROPERTY(weaveindexZ,I,Actor)1112 DEFINE_PROPERTY(weaveindexZ, I, Actor)
1113 {
1114 PROP_INT_PARM(id, 0);
1115 defaults->WeaveIndexZ = id;
1116 }
1117
1118 //==========================================================================
1119 //
1120 //==========================================================================
DEFINE_PROPERTY(minmissilechance,I,Actor)1121 DEFINE_PROPERTY(minmissilechance, I, Actor)
1122 {
1123 PROP_INT_PARM(id, 0);
1124 defaults->MinMissileChance=id;
1125 }
1126
1127 //==========================================================================
1128 //
1129 //==========================================================================
DEFINE_PROPERTY(damagetype,S,Actor)1130 DEFINE_PROPERTY(damagetype, S, Actor)
1131 {
1132 PROP_STRING_PARM(str, 0);
1133 if (!stricmp(str, "Normal")) defaults->DamageType = NAME_None;
1134 else defaults->DamageType=str;
1135 }
1136
1137 //==========================================================================
1138
1139 //==========================================================================
DEFINE_PROPERTY(paintype,S,Actor)1140 DEFINE_PROPERTY(paintype, S, Actor)
1141 {
1142 PROP_STRING_PARM(str, 0);
1143 if (!stricmp(str, "Normal")) defaults->PainType = NAME_None;
1144 else defaults->PainType=str;
1145 }
1146
1147 //==========================================================================
1148
1149 //==========================================================================
DEFINE_PROPERTY(deathtype,S,Actor)1150 DEFINE_PROPERTY(deathtype, S, Actor)
1151 {
1152 PROP_STRING_PARM(str, 0);
1153 if (!stricmp(str, "Normal")) defaults->DeathType = NAME_None;
1154 else defaults->DeathType=str;
1155 }
1156
1157 //==========================================================================
1158 //
1159 //==========================================================================
DEFINE_PROPERTY(damagefactor,ZF,Actor)1160 DEFINE_PROPERTY(damagefactor, ZF, Actor)
1161 {
1162 PROP_STRING_PARM(str, 0);
1163 PROP_FIXED_PARM(id, 1);
1164
1165 if (str == NULL)
1166 {
1167 defaults->DamageFactor = id;
1168 }
1169 else
1170 {
1171 FName dmgType;
1172 if (!stricmp(str, "Normal")) dmgType = NAME_None;
1173 else dmgType=str;
1174
1175 info->SetDamageFactor(dmgType, id);
1176 }
1177 }
1178
1179 //==========================================================================
1180 //
1181 //==========================================================================
DEFINE_PROPERTY(decal,S,Actor)1182 DEFINE_PROPERTY(decal, S, Actor)
1183 {
1184 PROP_STRING_PARM(str, 0);
1185 defaults->DecalGenerator = (FDecalBase *)intptr_t(int(FName(str)));
1186 }
1187
1188 //==========================================================================
1189 //
1190 //==========================================================================
DEFINE_PROPERTY(maxstepheight,F,Actor)1191 DEFINE_PROPERTY(maxstepheight, F, Actor)
1192 {
1193 PROP_FIXED_PARM(i, 0);
1194 defaults->MaxStepHeight = i;
1195 }
1196
1197 //==========================================================================
1198 //
1199 //==========================================================================
DEFINE_PROPERTY(maxdropoffheight,F,Actor)1200 DEFINE_PROPERTY(maxdropoffheight, F, Actor)
1201 {
1202 PROP_FIXED_PARM(i, 0);
1203 defaults->MaxDropOffHeight = i;
1204 }
1205
1206 //==========================================================================
1207 //
1208 //==========================================================================
DEFINE_PROPERTY(poisondamage,Iii,Actor)1209 DEFINE_PROPERTY(poisondamage, Iii, Actor)
1210 {
1211 PROP_INT_PARM(poisondamage, 0);
1212 PROP_INT_PARM(poisonduration, 1);
1213 PROP_INT_PARM(poisonperiod, 2);
1214
1215 defaults->PoisonDamage = poisondamage;
1216 if (PROP_PARM_COUNT == 1)
1217 {
1218 defaults->PoisonDuration = INT_MIN;
1219 }
1220 else
1221 {
1222 defaults->PoisonDuration = poisonduration;
1223
1224 if (PROP_PARM_COUNT > 2)
1225 defaults->PoisonPeriod = poisonperiod;
1226 else
1227 defaults->PoisonPeriod = 0;
1228 }
1229 }
1230
1231 //==========================================================================
1232 //
1233 //==========================================================================
DEFINE_PROPERTY(poisondamagetype,S,Actor)1234 DEFINE_PROPERTY(poisondamagetype, S, Actor)
1235 {
1236 PROP_STRING_PARM(poisondamagetype, 0);
1237
1238 defaults->PoisonDamageType = poisondamagetype;
1239 }
1240
1241 //==========================================================================
1242 //
1243 //==========================================================================
DEFINE_PROPERTY(fastspeed,F,Actor)1244 DEFINE_PROPERTY(fastspeed, F, Actor)
1245 {
1246 PROP_FIXED_PARM(i, 0);
1247 info->Class->Meta.SetMetaFixed (AMETA_FastSpeed, i);
1248 }
1249
1250 //==========================================================================
1251 //
1252 //==========================================================================
DEFINE_PROPERTY(radiusdamagefactor,F,Actor)1253 DEFINE_PROPERTY(radiusdamagefactor, F, Actor)
1254 {
1255 PROP_FIXED_PARM(i, 0);
1256 info->Class->Meta.SetMetaFixed (AMETA_RDFactor, i);
1257 }
1258
1259 //==========================================================================
1260 //
1261 //==========================================================================
DEFINE_PROPERTY(cameraheight,F,Actor)1262 DEFINE_PROPERTY(cameraheight, F, Actor)
1263 {
1264 PROP_FIXED_PARM(i, 0);
1265 info->Class->Meta.SetMetaFixed (AMETA_CameraHeight, i);
1266 }
1267
1268 //==========================================================================
1269 //
1270 //==========================================================================
DEFINE_PROPERTY(vspeed,F,Actor)1271 DEFINE_PROPERTY(vspeed, F, Actor)
1272 {
1273 PROP_FIXED_PARM(i, 0);
1274 defaults->velz = i;
1275 }
1276
1277 //==========================================================================
1278 //
1279 //==========================================================================
DEFINE_PROPERTY(gravity,F,Actor)1280 DEFINE_PROPERTY(gravity, F, Actor)
1281 {
1282 PROP_FIXED_PARM(i, 0);
1283
1284 if (i < 0) I_Error ("Gravity must not be negative.");
1285 defaults->gravity = i;
1286 }
1287
1288 //==========================================================================
1289 //
1290 //==========================================================================
DEFINE_PROPERTY(friction,F,Actor)1291 DEFINE_PROPERTY(friction, F, Actor)
1292 {
1293 PROP_FIXED_PARM(i, 0);
1294
1295 if (i < 0) I_Error ("Friction must not be negative.");
1296 defaults->Friction = i;
1297 }
1298
1299 //==========================================================================
1300 //
1301 //==========================================================================
DEFINE_PROPERTY(species,S,Actor)1302 DEFINE_PROPERTY(species, S, Actor)
1303 {
1304 PROP_STRING_PARM(n, 0);
1305 defaults->Species = n;
1306 }
1307
1308 //==========================================================================
1309 //
1310 //==========================================================================
1311 DEFINE_PROPERTY(clearflags, 0, Actor)
1312 {
1313 defaults->flags = 0;
1314 defaults->flags2 &= MF2_ARGSDEFINED; // this flag must not be cleared
1315 defaults->flags3 = 0;
1316 defaults->flags4 = 0;
1317 defaults->flags5 = 0;
1318 defaults->flags6 = 0;
1319 defaults->flags7 = 0;
1320 }
1321
1322 //==========================================================================
1323 //
1324 //==========================================================================
1325 DEFINE_PROPERTY(monster, 0, Actor)
1326 {
1327 // sets the standard flags for a monster
1328 defaults->flags|=MF_SHOOTABLE|MF_COUNTKILL|MF_SOLID;
1329 defaults->flags2|=MF2_PUSHWALL|MF2_MCROSS|MF2_PASSMOBJ;
1330 defaults->flags3|=MF3_ISMONSTER;
1331 defaults->flags4|=MF4_CANUSEWALLS;
1332 }
1333
1334 //==========================================================================
1335 //
1336 //==========================================================================
1337 DEFINE_PROPERTY(projectile, 0, Actor)
1338 {
1339 // sets the standard flags for a projectile
1340 defaults->flags|=MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE;
1341 defaults->flags2|=MF2_IMPACT|MF2_PCROSS|MF2_NOTELEPORT;
1342 if (gameinfo.gametype&GAME_Raven) defaults->flags5|=MF5_BLOODSPLATTER;
1343 }
1344
1345 //==========================================================================
1346 //
1347 //==========================================================================
DEFINE_PROPERTY(activation,N,Actor)1348 DEFINE_PROPERTY(activation, N, Actor)
1349 {
1350 // How the thing behaves when activated by death, USESPECIAL or BUMPSPECIAL
1351 PROP_INT_PARM(val, 0);
1352 defaults->activationtype = val;
1353 }
1354
1355 //==========================================================================
1356 //
1357 //==========================================================================
DEFINE_PROPERTY(designatedteam,I,Actor)1358 DEFINE_PROPERTY(designatedteam, I, Actor)
1359 {
1360 PROP_INT_PARM(val, 0);
1361 if(val < 0 || (val >= (signed) Teams.Size() && val != TEAM_NONE))
1362 I_Error("Invalid team designation.\n");
1363 defaults->DesignatedTeam = val;
1364 }
1365
1366 //==========================================================================
1367 // [BB]
1368 //==========================================================================
DEFINE_PROPERTY(visibletoteam,I,Actor)1369 DEFINE_PROPERTY(visibletoteam, I, Actor)
1370 {
1371 PROP_INT_PARM(i, 0);
1372 defaults->VisibleToTeam=i+1;
1373 }
1374
1375 //==========================================================================
1376 // [BB]
1377 //==========================================================================
DEFINE_PROPERTY(visibletoplayerclass,Ssssssssssssssssssss,Actor)1378 DEFINE_PROPERTY(visibletoplayerclass, Ssssssssssssssssssss, Actor)
1379 {
1380 info->VisibleToPlayerClass.Clear();
1381 for(int i = 0;i < PROP_PARM_COUNT;++i)
1382 {
1383 PROP_STRING_PARM(n, i);
1384 if (*n != 0)
1385 info->VisibleToPlayerClass.Push(FindClassTentative(n, "PlayerPawn"));
1386 }
1387 }
1388
1389 //==========================================================================
1390 //
1391 //==========================================================================
DEFINE_PROPERTY(accuracy,I,Actor)1392 DEFINE_PROPERTY(accuracy, I, Actor)
1393 {
1394 PROP_INT_PARM(i, 0);
1395 defaults->accuracy = i;
1396 }
1397
1398 //==========================================================================
1399 //
1400 //==========================================================================
DEFINE_PROPERTY(stamina,I,Actor)1401 DEFINE_PROPERTY(stamina, I, Actor)
1402 {
1403 PROP_INT_PARM(i, 0);
1404 defaults->stamina = i;
1405 }
1406
1407 //==========================================================================
1408 //
1409 //==========================================================================
DEFINE_PROPERTY(telefogsourcetype,S,Actor)1410 DEFINE_PROPERTY(telefogsourcetype, S, Actor)
1411 {
1412 PROP_STRING_PARM(str, 0);
1413 defaults->TeleFogSourceType = FindClassTentative(str,"Actor");
1414 }
1415
1416 //==========================================================================
1417 //
1418 //==========================================================================
DEFINE_PROPERTY(telefogdesttype,S,Actor)1419 DEFINE_PROPERTY(telefogdesttype, S, Actor)
1420 {
1421 PROP_STRING_PARM(str, 0);
1422 defaults->TeleFogDestType = FindClassTentative(str, "Actor");
1423 }
1424
1425 //==========================================================================
1426 //
1427 //==========================================================================
DEFINE_PROPERTY(ripperlevel,I,Actor)1428 DEFINE_PROPERTY(ripperlevel, I, Actor)
1429 {
1430 PROP_INT_PARM(id, 0);
1431 if (id < 0)
1432 {
1433 I_Error ("RipperLevel must not be negative");
1434 }
1435 defaults->RipperLevel = id;
1436 }
1437
1438 //==========================================================================
1439 //
1440 //==========================================================================
DEFINE_PROPERTY(riplevelmin,I,Actor)1441 DEFINE_PROPERTY(riplevelmin, I, Actor)
1442 {
1443 PROP_INT_PARM(id, 0);
1444 if (id < 0)
1445 {
1446 I_Error ("RipLevelMin must not be negative");
1447 }
1448 defaults->RipLevelMin = id;
1449 }
1450
1451 //==========================================================================
1452 //
1453 //==========================================================================
DEFINE_PROPERTY(riplevelmax,I,Actor)1454 DEFINE_PROPERTY(riplevelmax, I, Actor)
1455 {
1456 PROP_INT_PARM(id, 0);
1457 if (id < 0)
1458 {
1459 I_Error ("RipLevelMax must not be negative");
1460 }
1461 defaults->RipLevelMax = id;
1462 }
1463
1464 //==========================================================================
1465 //
1466 // Special inventory properties
1467 //
1468 //==========================================================================
1469
1470 //==========================================================================
1471 //
1472 //==========================================================================
DEFINE_CLASS_PROPERTY(restrictedto,Ssssssssssssssssssss,Inventory)1473 DEFINE_CLASS_PROPERTY(restrictedto, Ssssssssssssssssssss, Inventory)
1474 {
1475 info->RestrictedToPlayerClass.Clear();
1476 for(int i = 0;i < PROP_PARM_COUNT;++i)
1477 {
1478 PROP_STRING_PARM(n, i);
1479 if (*n != 0)
1480 info->RestrictedToPlayerClass.Push(FindClassTentative(n, "PlayerPawn"));
1481 }
1482 }
1483
1484 //==========================================================================
1485 //
1486 //==========================================================================
DEFINE_CLASS_PROPERTY(forbiddento,Ssssssssssssssssssss,Inventory)1487 DEFINE_CLASS_PROPERTY(forbiddento, Ssssssssssssssssssss, Inventory)
1488 {
1489 info->ForbiddenToPlayerClass.Clear();
1490 for(int i = 0;i < PROP_PARM_COUNT;++i)
1491 {
1492 PROP_STRING_PARM(n, i);
1493 if (*n != 0)
1494 info->ForbiddenToPlayerClass.Push(FindClassTentative(n, "PlayerPawn"));
1495 }
1496 }
1497
1498 //==========================================================================
1499 //
1500 //==========================================================================
DEFINE_CLASS_PROPERTY(backpackamount,I,Ammo)1501 DEFINE_CLASS_PROPERTY(backpackamount, I, Ammo)
1502 {
1503 PROP_INT_PARM(i, 0);
1504 defaults->BackpackAmount = i;
1505 }
1506
1507 //==========================================================================
1508 //
1509 //==========================================================================
DEFINE_CLASS_PROPERTY(backpackmaxamount,I,Ammo)1510 DEFINE_CLASS_PROPERTY(backpackmaxamount, I, Ammo)
1511 {
1512 PROP_INT_PARM(i, 0);
1513 defaults->BackpackMaxAmount = i;
1514 }
1515
1516 //==========================================================================
1517 //
1518 //==========================================================================
DEFINE_CLASS_PROPERTY(dropamount,I,Ammo)1519 DEFINE_CLASS_PROPERTY(dropamount, I, Ammo)
1520 {
1521 PROP_INT_PARM(i, 0);
1522 info->Class->Meta.SetMetaInt (AIMETA_DropAmount, i);
1523 }
1524
1525 //==========================================================================
1526 //
1527 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(armor,maxsaveamount,I,BasicArmorBonus)1528 DEFINE_CLASS_PROPERTY_PREFIX(armor, maxsaveamount, I, BasicArmorBonus)
1529 {
1530 PROP_INT_PARM(i, 0);
1531 defaults->MaxSaveAmount = i;
1532 }
1533
1534 //==========================================================================
1535 //
1536 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(armor,maxbonus,I,BasicArmorBonus)1537 DEFINE_CLASS_PROPERTY_PREFIX(armor, maxbonus, I, BasicArmorBonus)
1538 {
1539 PROP_INT_PARM(i, 0);
1540 defaults->BonusCount = i;
1541 }
1542
1543 //==========================================================================
1544 //
1545 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(armor,maxbonusmax,I,BasicArmorBonus)1546 DEFINE_CLASS_PROPERTY_PREFIX(armor, maxbonusmax, I, BasicArmorBonus)
1547 {
1548 PROP_INT_PARM(i, 0);
1549 defaults->BonusMax = i;
1550 }
1551
1552 //==========================================================================
1553 //
1554 //==========================================================================
DEFINE_CLASS_PROPERTY(saveamount,I,Armor)1555 DEFINE_CLASS_PROPERTY(saveamount, I, Armor)
1556 {
1557 PROP_INT_PARM(i, 0);
1558
1559 // Special case here because this property has to work for 2 unrelated classes
1560 if (info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup)))
1561 {
1562 ((ABasicArmorPickup*)defaults)->SaveAmount=i;
1563 }
1564 else if (info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)))
1565 {
1566 ((ABasicArmorBonus*)defaults)->SaveAmount=i;
1567 }
1568 else
1569 {
1570 I_Error("\"Armor.SaveAmount\" requires an actor of type \"Armor\"");
1571 }
1572 }
1573
1574 //==========================================================================
1575 //
1576 //==========================================================================
DEFINE_CLASS_PROPERTY(savepercent,F,Armor)1577 DEFINE_CLASS_PROPERTY(savepercent, F, Armor)
1578 {
1579 PROP_FIXED_PARM(i, 0);
1580
1581 i = clamp(i, 0, 100*FRACUNIT)/100;
1582 // Special case here because this property has to work for 2 unrelated classes
1583 if (info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup)))
1584 {
1585 ((ABasicArmorPickup*)defaults)->SavePercent = i;
1586 }
1587 else if (info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)))
1588 {
1589 ((ABasicArmorBonus*)defaults)->SavePercent = i;
1590 }
1591 else
1592 {
1593 I_Error("\"Armor.SavePercent\" requires an actor of type \"Armor\"\n");
1594 }
1595 }
1596
1597 //==========================================================================
1598 //
1599 //==========================================================================
DEFINE_CLASS_PROPERTY(maxabsorb,I,Armor)1600 DEFINE_CLASS_PROPERTY(maxabsorb, I, Armor)
1601 {
1602 PROP_INT_PARM(i, 0);
1603
1604 // Special case here because this property has to work for 2 unrelated classes
1605 if (info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup)))
1606 {
1607 ((ABasicArmorPickup*)defaults)->MaxAbsorb = i;
1608 }
1609 else if (info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)))
1610 {
1611 ((ABasicArmorBonus*)defaults)->MaxAbsorb = i;
1612 }
1613 else
1614 {
1615 I_Error("\"Armor.MaxAbsorb\" requires an actor of type \"Armor\"\n");
1616 }
1617 }
1618
1619 //==========================================================================
1620 //
1621 //==========================================================================
DEFINE_CLASS_PROPERTY(maxfullabsorb,I,Armor)1622 DEFINE_CLASS_PROPERTY(maxfullabsorb, I, Armor)
1623 {
1624 PROP_INT_PARM(i, 0);
1625
1626 // Special case here because this property has to work for 2 unrelated classes
1627 if (info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup)))
1628 {
1629 ((ABasicArmorPickup*)defaults)->MaxFullAbsorb = i;
1630 }
1631 else if (info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)))
1632 {
1633 ((ABasicArmorBonus*)defaults)->MaxFullAbsorb = i;
1634 }
1635 else
1636 {
1637 I_Error("\"Armor.MaxFullAbsorb\" requires an actor of type \"Armor\"\n");
1638 }
1639 }
1640
1641 //==========================================================================
1642 //
1643 //==========================================================================
DEFINE_CLASS_PROPERTY(amount,I,Inventory)1644 DEFINE_CLASS_PROPERTY(amount, I, Inventory)
1645 {
1646 PROP_INT_PARM(i, 0);
1647 defaults->Amount = i;
1648 }
1649
1650 //==========================================================================
1651 //
1652 //==========================================================================
DEFINE_CLASS_PROPERTY(icon,S,Inventory)1653 DEFINE_CLASS_PROPERTY(icon, S, Inventory)
1654 {
1655 PROP_STRING_PARM(i, 0);
1656
1657 if (i == NULL || i[0] == '\0')
1658 {
1659 defaults->Icon.SetNull();
1660 }
1661 else
1662 {
1663 defaults->Icon = TexMan.CheckForTexture(i, FTexture::TEX_MiscPatch);
1664 if (!defaults->Icon.isValid())
1665 {
1666 // Don't print warnings if the item is for another game or if this is a shareware IWAD.
1667 // Strife's teaser doesn't contain all the icon graphics of the full game.
1668 if ((info->GameFilter == GAME_Any || info->GameFilter & gameinfo.gametype) &&
1669 !(gameinfo.flags&GI_SHAREWARE) && Wads.GetLumpFile(bag.Lumpnum) != 0)
1670 {
1671 bag.ScriptPosition.Message(MSG_WARNING,
1672 "Icon '%s' for '%s' not found\n", i, info->Class->TypeName.GetChars());
1673 }
1674 }
1675 }
1676 }
1677
1678 //==========================================================================
1679 //
1680 //==========================================================================
DEFINE_CLASS_PROPERTY(interhubamount,I,Inventory)1681 DEFINE_CLASS_PROPERTY(interhubamount, I, Inventory)
1682 {
1683 PROP_INT_PARM(i, 0);
1684 defaults->InterHubAmount = i;
1685 }
1686
1687 //==========================================================================
1688 //
1689 //==========================================================================
DEFINE_CLASS_PROPERTY(maxamount,I,Inventory)1690 DEFINE_CLASS_PROPERTY(maxamount, I, Inventory)
1691 {
1692 PROP_INT_PARM(i, 0);
1693 defaults->MaxAmount = i;
1694 }
1695
1696 //==========================================================================
1697 //
1698 //==========================================================================
1699 DEFINE_CLASS_PROPERTY(defmaxamount, 0, Inventory)
1700 {
1701 defaults->MaxAmount = gameinfo.definventorymaxamount;
1702 }
1703
1704
1705 //==========================================================================
1706 //
1707 //==========================================================================
DEFINE_CLASS_PROPERTY(pickupflash,S,Inventory)1708 DEFINE_CLASS_PROPERTY(pickupflash, S, Inventory)
1709 {
1710 PROP_STRING_PARM(str, 0);
1711 defaults->PickupFlash = FindClassTentative(str, "Actor");
1712 }
1713
1714 //==========================================================================
1715 //
1716 //==========================================================================
DEFINE_CLASS_PROPERTY(pickupmessage,T,Inventory)1717 DEFINE_CLASS_PROPERTY(pickupmessage, T, Inventory)
1718 {
1719 PROP_STRING_PARM(str, 0);
1720 info->Class->Meta.SetMetaString(AIMETA_PickupMessage, str);
1721 }
1722
1723 //==========================================================================
1724 //
1725 //==========================================================================
DEFINE_CLASS_PROPERTY(pickupsound,S,Inventory)1726 DEFINE_CLASS_PROPERTY(pickupsound, S, Inventory)
1727 {
1728 PROP_STRING_PARM(str, 0);
1729 defaults->PickupSound = str;
1730 }
1731
1732 //==========================================================================
1733 // Dummy for Skulltag compatibility...
1734 //==========================================================================
DEFINE_CLASS_PROPERTY(pickupannouncerentry,S,Inventory)1735 DEFINE_CLASS_PROPERTY(pickupannouncerentry, S, Inventory)
1736 {
1737 }
1738
1739 //==========================================================================
1740 //
1741 //==========================================================================
DEFINE_CLASS_PROPERTY(respawntics,I,Inventory)1742 DEFINE_CLASS_PROPERTY(respawntics, I, Inventory)
1743 {
1744 PROP_INT_PARM(i, 0);
1745 defaults->RespawnTics = i;
1746 }
1747
1748 //==========================================================================
1749 //
1750 //==========================================================================
DEFINE_CLASS_PROPERTY(usesound,S,Inventory)1751 DEFINE_CLASS_PROPERTY(usesound, S, Inventory)
1752 {
1753 PROP_STRING_PARM(str, 0);
1754 defaults->UseSound = str;
1755 }
1756
1757 //==========================================================================
1758 //
1759 //==========================================================================
DEFINE_CLASS_PROPERTY(givequest,I,Inventory)1760 DEFINE_CLASS_PROPERTY(givequest, I, Inventory)
1761 {
1762 PROP_INT_PARM(i, 0);
1763 info->Class->Meta.SetMetaInt(AIMETA_GiveQuest, i);
1764 }
1765
1766 //==========================================================================
1767 //
1768 //==========================================================================
DEFINE_CLASS_PROPERTY(lowmessage,IT,Health)1769 DEFINE_CLASS_PROPERTY(lowmessage, IT, Health)
1770 {
1771 PROP_INT_PARM(i, 0);
1772 PROP_STRING_PARM(str, 1);
1773 info->Class->Meta.SetMetaInt(AIMETA_LowHealth, i);
1774 info->Class->Meta.SetMetaString(AIMETA_LowHealthMessage, str);
1775 }
1776
1777 //==========================================================================
1778 //
1779 //==========================================================================
DEFINE_CLASS_PROPERTY(autouse,I,HealthPickup)1780 DEFINE_CLASS_PROPERTY(autouse, I, HealthPickup)
1781 {
1782 PROP_INT_PARM(i, 0);
1783 defaults->autousemode = i;
1784 }
1785
1786 //==========================================================================
1787 //
1788 //==========================================================================
DEFINE_CLASS_PROPERTY(number,I,PuzzleItem)1789 DEFINE_CLASS_PROPERTY(number, I, PuzzleItem)
1790 {
1791 PROP_INT_PARM(i, 0);
1792 defaults->PuzzleItemNumber = i;
1793 }
1794
1795 //==========================================================================
1796 //
1797 //==========================================================================
DEFINE_CLASS_PROPERTY(failmessage,T,PuzzleItem)1798 DEFINE_CLASS_PROPERTY(failmessage, T, PuzzleItem)
1799 {
1800 PROP_STRING_PARM(str, 0);
1801 info->Class->Meta.SetMetaString(AIMETA_PuzzFailMessage, str);
1802 }
1803
1804 //==========================================================================
1805 //
1806 //==========================================================================
DEFINE_CLASS_PROPERTY(ammogive,I,Weapon)1807 DEFINE_CLASS_PROPERTY(ammogive, I, Weapon)
1808 {
1809 PROP_INT_PARM(i, 0);
1810 defaults->AmmoGive1 = i;
1811 }
1812
1813 //==========================================================================
1814 //
1815 //==========================================================================
DEFINE_CLASS_PROPERTY(ammogive1,I,Weapon)1816 DEFINE_CLASS_PROPERTY(ammogive1, I, Weapon)
1817 {
1818 PROP_INT_PARM(i, 0);
1819 defaults->AmmoGive1 = i;
1820 }
1821
1822 //==========================================================================
1823 //
1824 //==========================================================================
DEFINE_CLASS_PROPERTY(ammogive2,I,Weapon)1825 DEFINE_CLASS_PROPERTY(ammogive2, I, Weapon)
1826 {
1827 PROP_INT_PARM(i, 0);
1828 defaults->AmmoGive2 = i;
1829 }
1830
1831 //==========================================================================
1832 //
1833 //==========================================================================
DEFINE_CLASS_PROPERTY(ammotype,S,Weapon)1834 DEFINE_CLASS_PROPERTY(ammotype, S, Weapon)
1835 {
1836 PROP_STRING_PARM(str, 0);
1837 if (!stricmp(str, "none") || *str == 0) defaults->AmmoType1 = NULL;
1838 else defaults->AmmoType1 = FindClassTentative(str, "Ammo");
1839 }
1840
1841 //==========================================================================
1842 //
1843 //==========================================================================
DEFINE_CLASS_PROPERTY(ammotype1,S,Weapon)1844 DEFINE_CLASS_PROPERTY(ammotype1, S, Weapon)
1845 {
1846 PROP_STRING_PARM(str, 0);
1847 if (!stricmp(str, "none") || *str == 0) defaults->AmmoType1 = NULL;
1848 else defaults->AmmoType1 = FindClassTentative(str, "Ammo");
1849 }
1850
1851 //==========================================================================
1852 //
1853 //==========================================================================
DEFINE_CLASS_PROPERTY(ammotype2,S,Weapon)1854 DEFINE_CLASS_PROPERTY(ammotype2, S, Weapon)
1855 {
1856 PROP_STRING_PARM(str, 0);
1857 if (!stricmp(str, "none") || *str == 0) defaults->AmmoType1 = NULL;
1858 else defaults->AmmoType2 = FindClassTentative(str, "Ammo");
1859 }
1860
1861 //==========================================================================
1862 //
1863 //==========================================================================
DEFINE_CLASS_PROPERTY(ammouse,I,Weapon)1864 DEFINE_CLASS_PROPERTY(ammouse, I, Weapon)
1865 {
1866 PROP_INT_PARM(i, 0);
1867 defaults->AmmoUse1 = i;
1868 }
1869
1870 //==========================================================================
1871 //
1872 //==========================================================================
DEFINE_CLASS_PROPERTY(ammouse1,I,Weapon)1873 DEFINE_CLASS_PROPERTY(ammouse1, I, Weapon)
1874 {
1875 PROP_INT_PARM(i, 0);
1876 defaults->AmmoUse1 = i;
1877 }
1878
1879 //==========================================================================
1880 //
1881 //==========================================================================
DEFINE_CLASS_PROPERTY(ammouse2,I,Weapon)1882 DEFINE_CLASS_PROPERTY(ammouse2, I, Weapon)
1883 {
1884 PROP_INT_PARM(i, 0);
1885 defaults->AmmoUse2 = i;
1886 }
1887
1888 //==========================================================================
1889 //
1890 //==========================================================================
DEFINE_CLASS_PROPERTY(kickback,I,Weapon)1891 DEFINE_CLASS_PROPERTY(kickback, I, Weapon)
1892 {
1893 PROP_INT_PARM(i, 0);
1894 defaults->Kickback = i;
1895 }
1896
1897 //==========================================================================
1898 //
1899 //==========================================================================
1900 DEFINE_CLASS_PROPERTY(defaultkickback, 0, Weapon)
1901 {
1902 defaults->Kickback = gameinfo.defKickback;
1903 }
1904
1905 //==========================================================================
1906 //
1907 //==========================================================================
DEFINE_CLASS_PROPERTY(readysound,S,Weapon)1908 DEFINE_CLASS_PROPERTY(readysound, S, Weapon)
1909 {
1910 PROP_STRING_PARM(str, 0);
1911 defaults->ReadySound = str;
1912 }
1913
1914 //==========================================================================
1915 //
1916 //==========================================================================
DEFINE_CLASS_PROPERTY(selectionorder,I,Weapon)1917 DEFINE_CLASS_PROPERTY(selectionorder, I, Weapon)
1918 {
1919 PROP_INT_PARM(i, 0);
1920 defaults->SelectionOrder = i;
1921 }
1922
1923 //==========================================================================
1924 //
1925 //==========================================================================
DEFINE_CLASS_PROPERTY(minselectionammo1,I,Weapon)1926 DEFINE_CLASS_PROPERTY(minselectionammo1, I, Weapon)
1927 {
1928 PROP_INT_PARM(i, 0);
1929 defaults->MinSelAmmo1 = i;
1930 }
1931
1932 //==========================================================================
1933 //
1934 //==========================================================================
DEFINE_CLASS_PROPERTY(minselectionammo2,I,Weapon)1935 DEFINE_CLASS_PROPERTY(minselectionammo2, I, Weapon)
1936 {
1937 PROP_INT_PARM(i, 0);
1938 defaults->MinSelAmmo2 = i;
1939 }
1940
1941 //==========================================================================
1942 //
1943 //==========================================================================
DEFINE_CLASS_PROPERTY(sisterweapon,S,Weapon)1944 DEFINE_CLASS_PROPERTY(sisterweapon, S, Weapon)
1945 {
1946 PROP_STRING_PARM(str, 0);
1947 defaults->SisterWeaponType = FindClassTentative(str, "Weapon");
1948 }
1949
1950 //==========================================================================
1951 //
1952 //==========================================================================
DEFINE_CLASS_PROPERTY(upsound,S,Weapon)1953 DEFINE_CLASS_PROPERTY(upsound, S, Weapon)
1954 {
1955 PROP_STRING_PARM(str, 0);
1956 defaults->UpSound = str;
1957 }
1958
1959 //==========================================================================
1960 //
1961 //==========================================================================
DEFINE_CLASS_PROPERTY(yadjust,F,Weapon)1962 DEFINE_CLASS_PROPERTY(yadjust, F, Weapon)
1963 {
1964 PROP_FIXED_PARM(i, 0);
1965 defaults->YAdjust = i;
1966 }
1967
1968 //==========================================================================
1969 //
1970 //==========================================================================
DEFINE_CLASS_PROPERTY(bobstyle,S,Weapon)1971 DEFINE_CLASS_PROPERTY(bobstyle, S, Weapon)
1972 {
1973 static const char *names[] = { "Normal", "Inverse", "Alpha", "InverseAlpha", "Smooth", "InverseSmooth", NULL };
1974 static const int styles[] = { AWeapon::BobNormal,
1975 AWeapon::BobInverse, AWeapon::BobAlpha, AWeapon::BobInverseAlpha,
1976 AWeapon::BobSmooth, AWeapon::BobInverseSmooth, };
1977 PROP_STRING_PARM(id, 0);
1978 int match = MatchString(id, names);
1979 if (match < 0)
1980 {
1981 I_Error("Unknown bobstyle %s", id);
1982 match = 0;
1983 }
1984 defaults->BobStyle = styles[match];
1985 }
1986
1987 //==========================================================================
1988 //
1989 //==========================================================================
DEFINE_CLASS_PROPERTY(bobspeed,F,Weapon)1990 DEFINE_CLASS_PROPERTY(bobspeed, F, Weapon)
1991 {
1992 PROP_FIXED_PARM(i, 0);
1993 defaults->BobSpeed = i;
1994 }
1995
1996 //==========================================================================
1997 //
1998 //==========================================================================
DEFINE_CLASS_PROPERTY(bobrangex,F,Weapon)1999 DEFINE_CLASS_PROPERTY(bobrangex, F, Weapon)
2000 {
2001 PROP_FIXED_PARM(i, 0);
2002 defaults->BobRangeX = i;
2003 }
2004
2005 //==========================================================================
2006 //
2007 //==========================================================================
DEFINE_CLASS_PROPERTY(bobrangey,F,Weapon)2008 DEFINE_CLASS_PROPERTY(bobrangey, F, Weapon)
2009 {
2010 PROP_FIXED_PARM(i, 0);
2011 defaults->BobRangeY = i;
2012 }
2013
2014 //==========================================================================
2015 //
2016 //==========================================================================
DEFINE_CLASS_PROPERTY(slotnumber,I,Weapon)2017 DEFINE_CLASS_PROPERTY(slotnumber, I, Weapon)
2018 {
2019 PROP_INT_PARM(i, 0);
2020 info->Class->Meta.SetMetaInt(AWMETA_SlotNumber, i);
2021 }
2022
2023 //==========================================================================
2024 //
2025 //==========================================================================
DEFINE_CLASS_PROPERTY(slotpriority,F,Weapon)2026 DEFINE_CLASS_PROPERTY(slotpriority, F, Weapon)
2027 {
2028 PROP_FIXED_PARM(i, 0);
2029 info->Class->Meta.SetMetaFixed(AWMETA_SlotPriority, i);
2030 }
2031
2032 //==========================================================================
2033 //
2034 //==========================================================================
DEFINE_CLASS_PROPERTY(preferredskin,S,Weapon)2035 DEFINE_CLASS_PROPERTY(preferredskin, S, Weapon)
2036 {
2037 PROP_STRING_PARM(str, 0);
2038 // NoOp - only for Skulltag compatibility
2039 }
2040
2041 //==========================================================================
2042 //
2043 //==========================================================================
DEFINE_CLASS_PROPERTY(number,I,WeaponPiece)2044 DEFINE_CLASS_PROPERTY(number, I, WeaponPiece)
2045 {
2046 PROP_INT_PARM(i, 0);
2047 defaults->PieceValue = 1 << (i-1);
2048 }
2049
2050 //==========================================================================
2051 //
2052 //==========================================================================
DEFINE_CLASS_PROPERTY(weapon,S,WeaponPiece)2053 DEFINE_CLASS_PROPERTY(weapon, S, WeaponPiece)
2054 {
2055 PROP_STRING_PARM(str, 0);
2056 defaults->WeaponClass = FindClassTentative(str, "Weapon");
2057 }
2058
2059 //==========================================================================
2060 //
2061 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(powerup,color,C_f,Inventory)2062 DEFINE_CLASS_PROPERTY_PREFIX(powerup, color, C_f, Inventory)
2063 {
2064 static const char *specialcolormapnames[] = {
2065 "INVERSEMAP", "GOLDMAP", "REDMAP", "GREENMAP", "BLUEMAP", NULL };
2066
2067 int alpha;
2068 PalEntry * pBlendColor;
2069
2070 if (info->Class->IsDescendantOf(RUNTIME_CLASS(APowerup)))
2071 {
2072 pBlendColor = &((APowerup*)defaults)->BlendColor;
2073 }
2074 else if (info->Class->IsDescendantOf(RUNTIME_CLASS(APowerupGiver)))
2075 {
2076 pBlendColor = &((APowerupGiver*)defaults)->BlendColor;
2077 }
2078 else
2079 {
2080 I_Error("\"powerup.color\" requires an actor of type \"Powerup\"\n");
2081 return;
2082 }
2083
2084 PROP_INT_PARM(mode, 0);
2085 PROP_INT_PARM(color, 1);
2086
2087 if (mode == 1)
2088 {
2089 PROP_STRING_PARM(name, 1);
2090
2091 // We must check the old special colormap names for compatibility
2092 int v = MatchString(name, specialcolormapnames);
2093 if (v >= 0)
2094 {
2095 *pBlendColor = MakeSpecialColormap(v);
2096 return;
2097 }
2098 else if (!stricmp(name, "none") && info->Class->IsDescendantOf(RUNTIME_CLASS(APowerupGiver)))
2099 {
2100 *pBlendColor = MakeSpecialColormap(65535);
2101 return;
2102 }
2103
2104 color = V_GetColor(NULL, name);
2105 }
2106 if (PROP_PARM_COUNT > 2)
2107 {
2108 PROP_FLOAT_PARM(falpha, 2);
2109 alpha=int(falpha*255);
2110 }
2111 else alpha = 255/3;
2112
2113 alpha=clamp<int>(alpha, 0, 255);
2114 if (alpha != 0) *pBlendColor = MAKEARGB(alpha, 0, 0, 0) | color;
2115 else *pBlendColor = 0;
2116 }
2117
2118 //==========================================================================
2119 //
2120 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(powerup,colormap,FFFfff,Inventory)2121 DEFINE_CLASS_PROPERTY_PREFIX(powerup, colormap, FFFfff, Inventory)
2122 {
2123 PalEntry * pBlendColor;
2124
2125 if (info->Class->IsDescendantOf(RUNTIME_CLASS(APowerup)))
2126 {
2127 pBlendColor = &((APowerup*)defaults)->BlendColor;
2128 }
2129 else if (info->Class->IsDescendantOf(RUNTIME_CLASS(APowerupGiver)))
2130 {
2131 pBlendColor = &((APowerupGiver*)defaults)->BlendColor;
2132 }
2133 else
2134 {
2135 I_Error("\"powerup.colormap\" requires an actor of type \"Powerup\"\n");
2136 return;
2137 }
2138
2139 if (PROP_PARM_COUNT == 3)
2140 {
2141 PROP_FLOAT_PARM(r, 0);
2142 PROP_FLOAT_PARM(g, 1);
2143 PROP_FLOAT_PARM(b, 2);
2144 *pBlendColor = MakeSpecialColormap(AddSpecialColormap(0, 0, 0, r, g, b));
2145 }
2146 else if (PROP_PARM_COUNT == 6)
2147 {
2148 PROP_FLOAT_PARM(r1, 0);
2149 PROP_FLOAT_PARM(g1, 1);
2150 PROP_FLOAT_PARM(b1, 2);
2151 PROP_FLOAT_PARM(r2, 3);
2152 PROP_FLOAT_PARM(g2, 4);
2153 PROP_FLOAT_PARM(b2, 5);
2154 *pBlendColor = MakeSpecialColormap(AddSpecialColormap(r1, g1, b1, r2, g2, b2));
2155 }
2156 else
2157 {
2158 I_Error("\"power.colormap\" must have either 3 or 6 parameters\n");
2159 }
2160 }
2161
2162 //==========================================================================
2163 //
2164 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(powerup,duration,I,Inventory)2165 DEFINE_CLASS_PROPERTY_PREFIX(powerup, duration, I, Inventory)
2166 {
2167 int *pEffectTics;
2168
2169 if (info->Class->IsDescendantOf(RUNTIME_CLASS(APowerup)))
2170 {
2171 pEffectTics = &((APowerup*)defaults)->EffectTics;
2172 }
2173 else if (info->Class->IsDescendantOf(RUNTIME_CLASS(APowerupGiver)))
2174 {
2175 pEffectTics = &((APowerupGiver*)defaults)->EffectTics;
2176 }
2177 else
2178 {
2179 I_Error("\"powerup.duration\" requires an actor of type \"Powerup\"\n");
2180 return;
2181 }
2182
2183 PROP_INT_PARM(i, 0);
2184 *pEffectTics = (i >= 0) ? i : -i * TICRATE;
2185 }
2186
2187 //==========================================================================
2188 //
2189 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(powerup,strength,F,Inventory)2190 DEFINE_CLASS_PROPERTY_PREFIX(powerup, strength, F, Inventory)
2191 {
2192 fixed_t *pStrength;
2193
2194 if (info->Class->IsDescendantOf(RUNTIME_CLASS(APowerup)))
2195 {
2196 pStrength = &((APowerup*)defaults)->Strength;
2197 }
2198 else if (info->Class->IsDescendantOf(RUNTIME_CLASS(APowerupGiver)))
2199 {
2200 pStrength = &((APowerupGiver*)defaults)->Strength;
2201 }
2202 else
2203 {
2204 I_Error("\"powerup.strength\" requires an actor of type \"Powerup\"\n");
2205 return;
2206 }
2207 PROP_FIXED_PARM(f, 0);
2208 *pStrength = f;
2209 }
2210
2211 //==========================================================================
2212 //
2213 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(powerup,mode,S,Inventory)2214 DEFINE_CLASS_PROPERTY_PREFIX(powerup, mode, S, Inventory)
2215 {
2216 PROP_STRING_PARM(str, 0);
2217 FName *pMode;
2218 if (info->Class->IsDescendantOf(RUNTIME_CLASS(APowerup)))
2219 {
2220 pMode = &((APowerup*)defaults)->Mode;
2221 }
2222 else if (info->Class->IsDescendantOf(RUNTIME_CLASS(APowerupGiver)))
2223 {
2224 pMode = &((APowerupGiver*)defaults)->Mode;
2225 }
2226 else
2227 {
2228 I_Error("\"powerup.mode\" requires an actor of type \"Powerup\"\n");
2229 return;
2230 }
2231 *pMode = (FName)str;
2232 }
2233
2234 //==========================================================================
2235 //
2236 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(powerup,type,S,PowerupGiver)2237 DEFINE_CLASS_PROPERTY_PREFIX(powerup, type, S, PowerupGiver)
2238 {
2239 PROP_STRING_PARM(str, 0);
2240
2241 // Yuck! What was I thinking when I decided to prepend "Power" to the name?
2242 // Now it's too late to change it...
2243 const PClass *cls = PClass::FindClass(str);
2244 if (cls == NULL || !cls->IsDescendantOf(RUNTIME_CLASS(APowerup)))
2245 {
2246 FString st;
2247 st.Format("%s%s", strnicmp(str, "power", 5)? "Power" : "", str);
2248 cls = FindClassTentative(st, "Powerup");
2249 }
2250
2251 defaults->PowerupType = cls;
2252 }
2253
2254 //==========================================================================
2255 //
2256 // [GRB] Special player properties
2257 //
2258 //==========================================================================
2259
2260 //==========================================================================
2261 //
2262 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,displayname,S,PlayerPawn)2263 DEFINE_CLASS_PROPERTY_PREFIX(player, displayname, S, PlayerPawn)
2264 {
2265 PROP_STRING_PARM(str, 0);
2266 info->Class->Meta.SetMetaString (APMETA_DisplayName, str);
2267 }
2268
2269 //==========================================================================
2270 //
2271 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,soundclass,S,PlayerPawn)2272 DEFINE_CLASS_PROPERTY_PREFIX(player, soundclass, S, PlayerPawn)
2273 {
2274 PROP_STRING_PARM(str, 0);
2275
2276 FString tmp = str;
2277 tmp.ReplaceChars (' ', '_');
2278 info->Class->Meta.SetMetaString (APMETA_SoundClass, tmp);
2279 }
2280
2281 //==========================================================================
2282 //
2283 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,face,S,PlayerPawn)2284 DEFINE_CLASS_PROPERTY_PREFIX(player, face, S, PlayerPawn)
2285 {
2286 PROP_STRING_PARM(str, 0);
2287 FString tmp = str;
2288
2289 tmp.ToUpper();
2290 if (tmp.Len() != 3)
2291 {
2292 bag.ScriptPosition.Message(MSG_WARNING,
2293 "Invalid face '%s' for '%s';\nSTF replacement codes must be 3 characters.\n",
2294 tmp.GetChars(), info->Class->TypeName.GetChars ());
2295 }
2296
2297 bool valid = (
2298 (((tmp[0] >= 'A') && (tmp[0] <= 'Z')) || ((tmp[0] >= '0') && (tmp[0] <= '9'))) &&
2299 (((tmp[1] >= 'A') && (tmp[1] <= 'Z')) || ((tmp[1] >= '0') && (tmp[1] <= '9'))) &&
2300 (((tmp[2] >= 'A') && (tmp[2] <= 'Z')) || ((tmp[2] >= '0') && (tmp[2] <= '9')))
2301 );
2302 if (!valid)
2303 {
2304 bag.ScriptPosition.Message(MSG_WARNING,
2305 "Invalid face '%s' for '%s';\nSTF replacement codes must be alphanumeric.\n",
2306 tmp.GetChars(), info->Class->TypeName.GetChars ());
2307 }
2308
2309 info->Class->Meta.SetMetaString (APMETA_Face, tmp);
2310 }
2311
2312 //==========================================================================
2313 //
2314 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,colorrange,I_I,PlayerPawn)2315 DEFINE_CLASS_PROPERTY_PREFIX(player, colorrange, I_I, PlayerPawn)
2316 {
2317 PROP_INT_PARM(start, 0);
2318 PROP_INT_PARM(end, 1);
2319
2320 if (start > end)
2321 swapvalues (start, end);
2322
2323 info->Class->Meta.SetMetaInt (APMETA_ColorRange, (start & 255) | ((end & 255) << 8));
2324 }
2325
2326 //==========================================================================
2327 //
2328 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,colorset,ISIIIiiiiiiiiiiiiiiiiiiiiiiii,PlayerPawn)2329 DEFINE_CLASS_PROPERTY_PREFIX(player, colorset, ISIIIiiiiiiiiiiiiiiiiiiiiiiii, PlayerPawn)
2330 {
2331 PROP_INT_PARM(setnum, 0);
2332 PROP_STRING_PARM(setname, 1);
2333 PROP_INT_PARM(rangestart, 2);
2334 PROP_INT_PARM(rangeend, 3);
2335 PROP_INT_PARM(representative_color, 4);
2336
2337 FPlayerColorSet color;
2338 color.Name = setname;
2339 color.Lump = -1;
2340 color.FirstColor = rangestart;
2341 color.LastColor = rangeend;
2342 color.RepresentativeColor = representative_color;
2343 color.NumExtraRanges = 0;
2344
2345 if (PROP_PARM_COUNT > 5)
2346 {
2347 int count = PROP_PARM_COUNT - 5;
2348 int start = 5;
2349
2350 while (count >= 4)
2351 {
2352 PROP_INT_PARM(range_start, start+0);
2353 PROP_INT_PARM(range_end, start+1);
2354 PROP_INT_PARM(first_color, start+2);
2355 PROP_INT_PARM(last_color, start+3);
2356 int extra = color.NumExtraRanges++;
2357 assert (extra < (int)countof(color.Extra));
2358
2359 color.Extra[extra].RangeStart = range_start;
2360 color.Extra[extra].RangeEnd = range_end;
2361 color.Extra[extra].FirstColor = first_color;
2362 color.Extra[extra].LastColor = last_color;
2363 count -= 4;
2364 start += 4;
2365 }
2366 if (count != 0)
2367 {
2368 bag.ScriptPosition.Message(MSG_WARNING, "Extra ranges require 4 parameters each.\n");
2369 }
2370 }
2371
2372 if (setnum < 0)
2373 {
2374 bag.ScriptPosition.Message(MSG_WARNING, "Color set number must not be negative.\n");
2375 }
2376 else
2377 {
2378 info->SetColorSet(setnum, &color);
2379 }
2380 }
2381
2382 //==========================================================================
2383 //
2384 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,colorsetfile,ISSI,PlayerPawn)2385 DEFINE_CLASS_PROPERTY_PREFIX(player, colorsetfile, ISSI, PlayerPawn)
2386 {
2387 PROP_INT_PARM(setnum, 0);
2388 PROP_STRING_PARM(setname, 1);
2389 PROP_STRING_PARM(rangefile, 2);
2390 PROP_INT_PARM(representative_color, 3);
2391
2392 FPlayerColorSet color;
2393 color.Name = setname;
2394 color.Lump = Wads.CheckNumForName(rangefile);
2395 color.RepresentativeColor = representative_color;
2396 color.NumExtraRanges = 0;
2397
2398 if (setnum < 0)
2399 {
2400 bag.ScriptPosition.Message(MSG_WARNING, "Color set number must not be negative.\n");
2401 }
2402 else if (color.Lump >= 0)
2403 {
2404 info->SetColorSet(setnum, &color);
2405 }
2406 }
2407
2408 //==========================================================================
2409 //
2410 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,clearcolorset,I,PlayerPawn)2411 DEFINE_CLASS_PROPERTY_PREFIX(player, clearcolorset, I, PlayerPawn)
2412 {
2413 PROP_INT_PARM(setnum, 0);
2414
2415 if (setnum < 0)
2416 {
2417 bag.ScriptPosition.Message(MSG_WARNING, "Color set number must not be negative.\n");
2418 }
2419 else
2420 {
2421 info->SetColorSet(setnum, NULL);
2422 }
2423 }
2424
2425 //==========================================================================
2426 //
2427 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,attackzoffset,F,PlayerPawn)2428 DEFINE_CLASS_PROPERTY_PREFIX(player, attackzoffset, F, PlayerPawn)
2429 {
2430 PROP_FIXED_PARM(z, 0);
2431 defaults->AttackZOffset = z;
2432 }
2433
2434 //==========================================================================
2435 //
2436 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,jumpz,F,PlayerPawn)2437 DEFINE_CLASS_PROPERTY_PREFIX(player, jumpz, F, PlayerPawn)
2438 {
2439 PROP_FIXED_PARM(z, 0);
2440 defaults->JumpZ = z;
2441 }
2442
2443 //==========================================================================
2444 //
2445 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,GruntSpeed,F,PlayerPawn)2446 DEFINE_CLASS_PROPERTY_PREFIX(player, GruntSpeed, F, PlayerPawn)
2447 {
2448 PROP_FIXED_PARM(z, 0);
2449 defaults->GruntSpeed = z;
2450 }
2451
2452 //==========================================================================
2453 //
2454 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,FallingScreamSpeed,FF,PlayerPawn)2455 DEFINE_CLASS_PROPERTY_PREFIX(player, FallingScreamSpeed, FF, PlayerPawn)
2456 {
2457 PROP_FIXED_PARM(minz, 0);
2458 PROP_FIXED_PARM(maxz, 1);
2459 defaults->FallingScreamMinSpeed = minz;
2460 defaults->FallingScreamMaxSpeed = maxz;
2461 }
2462
2463 //==========================================================================
2464 //
2465 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,spawnclass,L,PlayerPawn)2466 DEFINE_CLASS_PROPERTY_PREFIX(player, spawnclass, L, PlayerPawn)
2467 {
2468 PROP_INT_PARM(type, 0);
2469
2470 if (type == 0)
2471 {
2472 PROP_INT_PARM(val, 1);
2473 if (val > 0) defaults->SpawnMask |= 1<<(val-1);
2474 }
2475 else
2476 {
2477 for(int i=1; i<PROP_PARM_COUNT; i++)
2478 {
2479 PROP_STRING_PARM(str, i);
2480
2481 if (!stricmp(str, "Any"))
2482 defaults->SpawnMask = 0;
2483 else if (!stricmp(str, "Fighter"))
2484 defaults->SpawnMask |= 1;
2485 else if (!stricmp(str, "Cleric"))
2486 defaults->SpawnMask |= 2;
2487 else if (!stricmp(str, "Mage"))
2488 defaults->SpawnMask |= 4;
2489
2490 }
2491 }
2492 }
2493
2494 //==========================================================================
2495 //
2496 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,viewheight,F,PlayerPawn)2497 DEFINE_CLASS_PROPERTY_PREFIX(player, viewheight, F, PlayerPawn)
2498 {
2499 PROP_FIXED_PARM(z, 0);
2500 defaults->ViewHeight = z;
2501 }
2502
2503 //==========================================================================
2504 //
2505 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,userange,F,PlayerPawn)2506 DEFINE_CLASS_PROPERTY_PREFIX(player, userange, F, PlayerPawn)
2507 {
2508 PROP_FIXED_PARM(z, 0);
2509 defaults->UseRange = z;
2510 }
2511
2512 //==========================================================================
2513 //
2514 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,aircapacity,F,PlayerPawn)2515 DEFINE_CLASS_PROPERTY_PREFIX(player, aircapacity, F, PlayerPawn)
2516 {
2517 PROP_FIXED_PARM(z, 0);
2518 defaults->AirCapacity = z;
2519 }
2520
2521 //==========================================================================
2522 //
2523 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,forwardmove,F_f,PlayerPawn)2524 DEFINE_CLASS_PROPERTY_PREFIX(player, forwardmove, F_f, PlayerPawn)
2525 {
2526 PROP_FIXED_PARM(m, 0);
2527 defaults->ForwardMove1 = defaults->ForwardMove2 = m;
2528 if (PROP_PARM_COUNT > 1)
2529 {
2530 PROP_FIXED_PARM(m2, 1);
2531 defaults->ForwardMove2 = m2;
2532 }
2533 }
2534
2535 //==========================================================================
2536 //
2537 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,sidemove,F_f,PlayerPawn)2538 DEFINE_CLASS_PROPERTY_PREFIX(player, sidemove, F_f, PlayerPawn)
2539 {
2540 PROP_FIXED_PARM(m, 0);
2541 defaults->SideMove1 = defaults->SideMove2 = m;
2542 if (PROP_PARM_COUNT > 1)
2543 {
2544 PROP_FIXED_PARM(m2, 1);
2545 defaults->SideMove2 = m2;
2546 }
2547 }
2548
2549 //==========================================================================
2550 //
2551 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,maxhealth,I,PlayerPawn)2552 DEFINE_CLASS_PROPERTY_PREFIX(player, maxhealth, I, PlayerPawn)
2553 {
2554 PROP_INT_PARM(z, 0);
2555 defaults->MaxHealth = z;
2556 }
2557
2558 //==========================================================================
2559 //
2560 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,mugshotmaxhealth,I,PlayerPawn)2561 DEFINE_CLASS_PROPERTY_PREFIX(player, mugshotmaxhealth, I, PlayerPawn)
2562 {
2563 PROP_INT_PARM(z, 0);
2564 defaults->MugShotMaxHealth = z;
2565 }
2566
2567 //==========================================================================
2568 //
2569 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,runhealth,I,PlayerPawn)2570 DEFINE_CLASS_PROPERTY_PREFIX(player, runhealth, I, PlayerPawn)
2571 {
2572 PROP_INT_PARM(z, 0);
2573 defaults->RunHealth = z;
2574 }
2575
2576 //==========================================================================
2577 //
2578 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,morphweapon,S,PlayerPawn)2579 DEFINE_CLASS_PROPERTY_PREFIX(player, morphweapon, S, PlayerPawn)
2580 {
2581 PROP_STRING_PARM(z, 0);
2582 defaults->MorphWeapon = FName(z);
2583 }
2584
2585 //==========================================================================
2586 //
2587 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,flechettetype,S,PlayerPawn)2588 DEFINE_CLASS_PROPERTY_PREFIX(player, flechettetype, S, PlayerPawn)
2589 {
2590 PROP_STRING_PARM(str, 0);
2591 defaults->FlechetteType = FindClassTentative(str, "ArtiPoisonBag");
2592 }
2593
2594 //==========================================================================
2595 //
2596 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,scoreicon,S,PlayerPawn)2597 DEFINE_CLASS_PROPERTY_PREFIX(player, scoreicon, S, PlayerPawn)
2598 {
2599 PROP_STRING_PARM(z, 0);
2600 defaults->ScoreIcon = TexMan.CheckForTexture(z, FTexture::TEX_MiscPatch);
2601 if (!defaults->ScoreIcon.isValid())
2602 {
2603 bag.ScriptPosition.Message(MSG_WARNING,
2604 "Icon '%s' for '%s' not found\n", z, info->Class->TypeName.GetChars ());
2605 }
2606 }
2607
2608 //==========================================================================
2609 //
2610 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,crouchsprite,S,PlayerPawn)2611 DEFINE_CLASS_PROPERTY_PREFIX(player, crouchsprite, S, PlayerPawn)
2612 {
2613 PROP_STRING_PARM(z, 0);
2614 if (strlen(z) == 4)
2615 {
2616 defaults->crouchsprite = GetSpriteIndex (z);
2617 }
2618 else if (*z == 0)
2619 {
2620 defaults->crouchsprite = 0;
2621 }
2622 else
2623 {
2624 I_Error("Sprite name must have exactly 4 characters");
2625 }
2626 }
2627
2628 //==========================================================================
2629 //
2630 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,damagescreencolor,Cfs,PlayerPawn)2631 DEFINE_CLASS_PROPERTY_PREFIX(player, damagescreencolor, Cfs, PlayerPawn)
2632 {
2633 PROP_COLOR_PARM(c, 0);
2634
2635 PalEntry color = c;
2636
2637 if (PROP_PARM_COUNT < 3) // Because colors count as 2 parms
2638 {
2639 color.a = 255;
2640 defaults->DamageFade = color;
2641 }
2642 else if (PROP_PARM_COUNT < 4)
2643 {
2644 PROP_FLOAT_PARM(a, 2);
2645
2646 color.a = BYTE(255 * clamp(a, 0.f, 1.f));
2647 defaults->DamageFade = color;
2648 }
2649 else
2650 {
2651 PROP_FLOAT_PARM(a, 2);
2652 PROP_STRING_PARM(type, 3);
2653
2654 color.a = BYTE(255 * clamp(a, 0.f, 1.f));
2655 info->SetPainFlash(type, color);
2656 }
2657 }
2658
2659 //==========================================================================
2660 //
2661 // [GRB] Store start items in drop item list
2662 //
2663 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,startitem,S_i,PlayerPawn)2664 DEFINE_CLASS_PROPERTY_PREFIX(player, startitem, S_i, PlayerPawn)
2665 {
2666 PROP_STRING_PARM(str, 0);
2667
2668 // create a linked list of startitems
2669 if (!bag.DropItemSet)
2670 {
2671 bag.DropItemSet = true;
2672 bag.DropItemList = NULL;
2673 }
2674
2675 FDropItem * di=new FDropItem;
2676
2677 di->Name = str;
2678 di->probability = 255;
2679 di->amount = 1;
2680 if (PROP_PARM_COUNT > 1)
2681 {
2682 PROP_INT_PARM(amt, 1);
2683 di->amount = amt;
2684 }
2685 di->Next = bag.DropItemList;
2686 bag.DropItemList = di;
2687 }
2688
2689 //==========================================================================
2690 //
2691 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,invulnerabilitymode,S,PlayerPawn)2692 DEFINE_CLASS_PROPERTY_PREFIX(player, invulnerabilitymode, S, PlayerPawn)
2693 {
2694 PROP_STRING_PARM(str, 0);
2695 info->Class->Meta.SetMetaInt (APMETA_InvulMode, (FName)str);
2696 }
2697
2698 //==========================================================================
2699 //
2700 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,healradiustype,S,PlayerPawn)2701 DEFINE_CLASS_PROPERTY_PREFIX(player, healradiustype, S, PlayerPawn)
2702 {
2703 PROP_STRING_PARM(str, 0);
2704 info->Class->Meta.SetMetaInt (APMETA_HealingRadius, (FName)str);
2705 }
2706
2707 //==========================================================================
2708 //
2709 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,hexenarmor,FFFFF,PlayerPawn)2710 DEFINE_CLASS_PROPERTY_PREFIX(player, hexenarmor, FFFFF, PlayerPawn)
2711 {
2712 for (int i=0;i<5;i++)
2713 {
2714 PROP_FIXED_PARM(val, i);
2715 info->Class->Meta.SetMetaFixed (APMETA_Hexenarmor0+i, val);
2716 }
2717 }
2718
2719 //==========================================================================
2720 //
2721 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,portrait,S,PlayerPawn)2722 DEFINE_CLASS_PROPERTY_PREFIX(player, portrait, S, PlayerPawn)
2723 {
2724 PROP_STRING_PARM(val, 0);
2725 info->Class->Meta.SetMetaString (APMETA_Portrait, val);
2726 }
2727
2728 //==========================================================================
2729 //
2730 //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player,weaponslot,ISsssssssssssssssssssssssssssssssssssssssssss,PlayerPawn)2731 DEFINE_CLASS_PROPERTY_PREFIX(player, weaponslot, ISsssssssssssssssssssssssssssssssssssssssssss, PlayerPawn)
2732 {
2733 PROP_INT_PARM(slot, 0);
2734
2735 if (slot < 0 || slot > 9)
2736 {
2737 I_Error("Slot must be between 0 and 9.");
2738 }
2739 else
2740 {
2741 FString weapons;
2742
2743 for(int i = 1; i < PROP_PARM_COUNT; ++i)
2744 {
2745 PROP_STRING_PARM(str, i);
2746 weapons << ' ' << str;
2747 }
2748 info->Class->Meta.SetMetaString(APMETA_Slot0 + slot, &weapons[1]);
2749 }
2750 }
2751
2752 //==========================================================================
2753 //
2754 //==========================================================================
DEFINE_CLASS_PROPERTY(playerclass,S,MorphProjectile)2755 DEFINE_CLASS_PROPERTY(playerclass, S, MorphProjectile)
2756 {
2757 PROP_STRING_PARM(str, 0);
2758 defaults->PlayerClass = FName(str);
2759 }
2760
2761 //==========================================================================
2762 //
2763 //==========================================================================
DEFINE_CLASS_PROPERTY(monsterclass,S,MorphProjectile)2764 DEFINE_CLASS_PROPERTY(monsterclass, S, MorphProjectile)
2765 {
2766 PROP_STRING_PARM(str, 0);
2767 defaults->MonsterClass = FName(str);
2768 }
2769
2770 //==========================================================================
2771 //
2772 //==========================================================================
DEFINE_CLASS_PROPERTY(duration,I,MorphProjectile)2773 DEFINE_CLASS_PROPERTY(duration, I, MorphProjectile)
2774 {
2775 PROP_INT_PARM(i, 0);
2776 defaults->Duration = i >= 0 ? i : -i*TICRATE;
2777 }
2778
2779 //==========================================================================
2780 //
2781 //==========================================================================
DEFINE_CLASS_PROPERTY(morphstyle,M,MorphProjectile)2782 DEFINE_CLASS_PROPERTY(morphstyle, M, MorphProjectile)
2783 {
2784 PROP_INT_PARM(i, 0);
2785 defaults->MorphStyle = i;
2786 }
2787
2788 //==========================================================================
2789 //
2790 //==========================================================================
DEFINE_CLASS_PROPERTY(morphflash,S,MorphProjectile)2791 DEFINE_CLASS_PROPERTY(morphflash, S, MorphProjectile)
2792 {
2793 PROP_STRING_PARM(str, 0);
2794 defaults->MorphFlash = FName(str);
2795 }
2796
2797 //==========================================================================
2798 //
2799 //==========================================================================
DEFINE_CLASS_PROPERTY(unmorphflash,S,MorphProjectile)2800 DEFINE_CLASS_PROPERTY(unmorphflash, S, MorphProjectile)
2801 {
2802 PROP_STRING_PARM(str, 0);
2803 defaults->UnMorphFlash = FName(str);
2804 }
2805
2806 //==========================================================================
2807 //
2808 //==========================================================================
DEFINE_CLASS_PROPERTY(playerclass,S,PowerMorph)2809 DEFINE_CLASS_PROPERTY(playerclass, S, PowerMorph)
2810 {
2811 PROP_STRING_PARM(str, 0);
2812 defaults->PlayerClass = FName(str);
2813 }
2814
2815 //==========================================================================
2816 //
2817 //==========================================================================
DEFINE_CLASS_PROPERTY(morphstyle,M,PowerMorph)2818 DEFINE_CLASS_PROPERTY(morphstyle, M, PowerMorph)
2819 {
2820 PROP_INT_PARM(i, 0);
2821 defaults->MorphStyle = i;
2822 }
2823
2824 //==========================================================================
2825 //
2826 //==========================================================================
DEFINE_CLASS_PROPERTY(morphflash,S,PowerMorph)2827 DEFINE_CLASS_PROPERTY(morphflash, S, PowerMorph)
2828 {
2829 PROP_STRING_PARM(str, 0);
2830 defaults->MorphFlash = FName(str);
2831 }
2832
2833 //==========================================================================
2834 //
2835 //==========================================================================
DEFINE_CLASS_PROPERTY(unmorphflash,S,PowerMorph)2836 DEFINE_CLASS_PROPERTY(unmorphflash, S, PowerMorph)
2837 {
2838 PROP_STRING_PARM(str, 0);
2839 defaults->UnMorphFlash = FName(str);
2840 }
2841
2842
2843