- Removed the old meta data system. All meta data is now stored in subclasses of PClass. This

should simplify scripting, since it means that meta fields can be treated (mostly) the same as
  normal fields.

SVN r2242 (scripting)
This commit is contained in:
Randy Heit 2010-03-25 20:38:00 +00:00
parent f88f601230
commit 604b5ef673
62 changed files with 903 additions and 803 deletions

View file

@ -492,48 +492,17 @@ struct line_t;
struct secplane_t; struct secplane_t;
struct FStrifeDialogueNode; struct FStrifeDialogueNode;
enum class DDropItem : public DObject
{
AMETA_BASE = 0x12000,
AMETA_Obituary, // string (player was killed by this actor)
AMETA_HitObituary, // string (player was killed by this actor in melee)
AMETA_DeathHeight, // fixed (height on normal death)
AMETA_BurnHeight, // fixed (height on burning death)
AMETA_StrifeName, // string (for named Strife objects)
AMETA_BloodColor, // colorized blood
AMETA_GibHealth, // negative health below which this monster dies an extreme death
AMETA_WoundHealth, // health needed to enter wound state
AMETA_PoisonDamage, // Amount of poison damage
AMETA_FastSpeed, // Speed in fast mode
AMETA_RDFactor, // Radius damage factor
AMETA_CameraHeight, // Height of camera when used as such
AMETA_HowlSound, // Sound being played when electrocuted or poisoned
AMETA_BloodType, // Blood replacement type
AMETA_BloodType2, // Bloodsplatter replacement type
AMETA_BloodType3, // AxeBlood replacement type
};
struct FDropItem
{
FName Name;
int probability;
int amount;
FDropItem * Next;
};
class FDropItemPtrArray : public TArray<FDropItem *>
{ {
DECLARE_CLASS(DDropItem, DObject)
HAS_OBJECT_POINTERS
public: public:
~FDropItemPtrArray(); DDropItem *Next;
FName Name;
int Probability;
int Amount;
}; };
extern FDropItemPtrArray DropItemList;
void FreeDropItemChain(FDropItem *chain);
int StoreDropItemChain(FDropItem *chain);
// Map Object definition. // Map Object definition.
class AActor : public DThinker class AActor : public DThinker
@ -556,7 +525,7 @@ public:
return (AActor *)(RUNTIME_TYPE(this)->Defaults); return (AActor *)(RUNTIME_TYPE(this)->Defaults);
} }
FDropItem *GetDropItems(); DDropItem *GetDropItems() const;
// Return true if the monster should use a missile attack, false for melee // Return true if the monster should use a missile attack, false for melee
bool SuggestMissileAttack (fixed_t dist); bool SuggestMissileAttack (fixed_t dist);
@ -702,7 +671,11 @@ public:
void Crash(); void Crash();
// Return starting health adjusted by skill level // Return starting health adjusted by skill level
int SpawnHealth(); int SpawnHealth() const;
int GetGibHealth() const;
fixed_t GetCameraHeight() const;
// Check for monsters that count as kill but excludes all friendlies. // Check for monsters that count as kill but excludes all friendlies.
bool CountsAsKill() const bool CountsAsKill() const

View file

@ -142,7 +142,7 @@ struct StyleName
static TArray<StyleName> StyleNames; static TArray<StyleName> StyleNames;
static TArray<PClassActor *> AmmoNames; static TArray<PClassAmmo *> AmmoNames;
static TArray<PClassActor *> WeaponNames; static TArray<PClassActor *> WeaponNames;
// DeHackEd trickery to support MBF-style parameters // DeHackEd trickery to support MBF-style parameters
@ -1869,20 +1869,16 @@ static int PatchMisc (int dummy)
player->health = deh.StartHealth; player->health = deh.StartHealth;
// Hm... I'm not sure that this is the right way to change this info... // Hm... I'm not sure that this is the right way to change this info...
unsigned int index = PClass::FindClass(NAME_DoomPlayer)->Meta.GetMetaInt (ACMETA_DropItems) - 1; DDropItem *di = PClass::FindActor(NAME_DoomPlayer)->DropItems;
if (index >= 0 && index < DropItemList.Size())
{
FDropItem * di = DropItemList[index];
while (di != NULL) while (di != NULL)
{ {
if (di->Name == NAME_Clip) if (di->Name == NAME_Clip)
{ {
di->amount = deh.StartBullets; di->Amount = deh.StartBullets;
} }
di = di->Next; di = di->Next;
} }
} }
}
// 0xDD means "enable infighting" // 0xDD means "enable infighting"
@ -2780,12 +2776,12 @@ static bool LoadDehSupp ()
} }
else else
{ {
PClass *cls = PClass::FindClass(sc.String); PClassAmmo *cls = dyn_cast<PClassAmmo>(PClass::FindClass(sc.String));
if (cls == NULL || cls->ParentClass != RUNTIME_CLASS(AAmmo)) if (cls == NULL)
{ {
sc.ScriptError("Unknown ammo type '%s'", sc.String); sc.ScriptError("Unknown ammo type '%s'", sc.String);
} }
AmmoNames.Push(static_cast<PClassActor *>(cls)); AmmoNames.Push(cls);
} }
if (sc.CheckString("}")) break; if (sc.CheckString("}")) break;
sc.MustGetStringName(","); sc.MustGetStringName(",");

View file

@ -2099,7 +2099,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
case DEM_SUMMONFRIEND2: case DEM_SUMMONFRIEND2:
case DEM_SUMMONFOE2: case DEM_SUMMONFOE2:
{ {
const PClass *typeinfo; PClassActor *typeinfo;
int angle = 0; int angle = 0;
SWORD tid = 0; SWORD tid = 0;
BYTE special = 0; BYTE special = 0;
@ -2114,8 +2114,8 @@ void Net_DoCommand (int type, BYTE **stream, int player)
for(i = 0; i < 5; i++) args[i] = ReadLong(stream); for(i = 0; i < 5; i++) args[i] = ReadLong(stream);
} }
typeinfo = PClass::FindClass (s); typeinfo = PClass::FindActor(s);
if (typeinfo != NULL && typeinfo->IsKindOf(RUNTIME_CLASS(PClassActor))) if (typeinfo != NULL)
{ {
AActor *source = players[player].mo; AActor *source = players[player].mo;
if (source != NULL) if (source != NULL)
@ -2318,7 +2318,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
case DEM_MORPHEX: case DEM_MORPHEX:
{ {
s = ReadString (stream); s = ReadString (stream);
const char *msg = cht_Morph (players + player, PClass::FindClass (s), false); const char *msg = cht_Morph (players + player, dyn_cast<PClassPlayerPawn>(PClass::FindClass (s)), false);
if (player == consoleplayer) if (player == consoleplayer)
{ {
Printf ("%s\n", *msg != '\0' ? msg : "Morph failed."); Printf ("%s\n", *msg != '\0' ? msg : "Morph failed.");
@ -2383,7 +2383,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
} }
for(int i = 0; i < count; ++i) for(int i = 0; i < count; ++i)
{ {
PClassActor *wpn = Net_ReadWeapon(stream); PClassWeapon *wpn = Net_ReadWeapon(stream);
players[player].weapons.AddSlot(slot, wpn, player == consoleplayer); players[player].weapons.AddSlot(slot, wpn, player == consoleplayer);
} }
} }
@ -2392,7 +2392,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
case DEM_ADDSLOT: case DEM_ADDSLOT:
{ {
int slot = ReadByte(stream); int slot = ReadByte(stream);
PClassActor *wpn = Net_ReadWeapon(stream); PClassWeapon *wpn = Net_ReadWeapon(stream);
players[player].weapons.AddSlot(slot, wpn, player == consoleplayer); players[player].weapons.AddSlot(slot, wpn, player == consoleplayer);
} }
break; break;
@ -2400,7 +2400,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
case DEM_ADDSLOTDEFAULT: case DEM_ADDSLOTDEFAULT:
{ {
int slot = ReadByte(stream); int slot = ReadByte(stream);
PClassActor *wpn = Net_ReadWeapon(stream); PClassWeapon *wpn = Net_ReadWeapon(stream);
players[player].weapons.AddSlotDefault(slot, wpn, player == consoleplayer); players[player].weapons.AddSlotDefault(slot, wpn, player == consoleplayer);
} }
break; break;

View file

@ -169,9 +169,9 @@ int D_PlayerClassToInt (const char *classname)
{ {
for (unsigned int i = 0; i < PlayerClasses.Size (); ++i) for (unsigned int i = 0; i < PlayerClasses.Size (); ++i)
{ {
const PClass *type = PlayerClasses[i].Type; PClassPlayerPawn *type = PlayerClasses[i].Type;
if (stricmp (type->Meta.GetMetaString (APMETA_DisplayName), classname) == 0) if (type->DisplayName.IsNotEmpty() && stricmp(type->DisplayName, classname) == 0)
{ {
return i; return i;
} }
@ -556,7 +556,7 @@ void D_WriteUserInfoStrings (int i, BYTE **stream, bool compact)
{ {
userinfo_t *info = &players[i].userinfo; userinfo_t *info = &players[i].userinfo;
const PClass *type = PlayerClasses[info->PlayerClass].Type; PClassPlayerPawn *type = PlayerClasses[info->PlayerClass].Type;
if (!compact) if (!compact)
{ {
@ -582,8 +582,7 @@ void D_WriteUserInfoStrings (int i, BYTE **stream, bool compact)
info->neverswitch, info->neverswitch,
(float)(info->MoveBob) / 65536.f, (float)(info->MoveBob) / 65536.f,
(float)(info->StillBob) / 65536.f, (float)(info->StillBob) / 65536.f,
info->PlayerClass == -1 ? "Random" : info->PlayerClass == -1 ? "Random" : D_EscapeUserInfo(type->DisplayName).GetChars()
D_EscapeUserInfo(type->Meta.GetMetaString (APMETA_DisplayName)).GetChars()
); );
} }
else else
@ -611,8 +610,7 @@ void D_WriteUserInfoStrings (int i, BYTE **stream, bool compact)
info->neverswitch, info->neverswitch,
(float)(info->MoveBob) / 65536.f, (float)(info->MoveBob) / 65536.f,
(float)(info->StillBob) / 65536.f, (float)(info->StillBob) / 65536.f,
info->PlayerClass == -1 ? "Random" : info->PlayerClass == -1 ? "Random" : D_EscapeUserInfo(type->DisplayName).GetChars()
D_EscapeUserInfo(type->Meta.GetMetaString (APMETA_DisplayName)).GetChars()
); );
} }
} }
@ -837,7 +835,7 @@ CCMD (playerinfo)
Printf ("MoveBob: %g\n", ui->MoveBob/65536.f); Printf ("MoveBob: %g\n", ui->MoveBob/65536.f);
Printf ("StillBob: %g\n", ui->StillBob/65536.f); Printf ("StillBob: %g\n", ui->StillBob/65536.f);
Printf ("PlayerClass: %s (%d)\n", Printf ("PlayerClass: %s (%d)\n",
ui->PlayerClass == -1 ? "Random" : PlayerClasses[ui->PlayerClass].Type->Meta.GetMetaString (APMETA_DisplayName), ui->PlayerClass == -1 ? "Random" : PlayerClasses[ui->PlayerClass].Type->DisplayName.GetChars(),
ui->PlayerClass); ui->PlayerClass);
if (argv.argc() > 2) PrintMiscActorInfo(players[i].mo); if (argv.argc() > 2) PrintMiscActorInfo(players[i].mo);
} }

View file

@ -44,38 +44,30 @@
//Added by MC: //Added by MC:
#include "b_bot.h" #include "b_bot.h"
enum
{
APMETA_BASE = 0x95000,
APMETA_DisplayName, // display name (used in menus etc.)
APMETA_SoundClass, // sound class
APMETA_Face, // doom status bar face (when used)
APMETA_ColorRange, // skin color range
APMETA_InvulMode,
APMETA_HealingRadius,
APMETA_Hexenarmor0,
APMETA_Hexenarmor1,
APMETA_Hexenarmor2,
APMETA_Hexenarmor3,
APMETA_Hexenarmor4,
APMETA_Slot0,
APMETA_Slot1,
APMETA_Slot2,
APMETA_Slot3,
APMETA_Slot4,
APMETA_Slot5,
APMETA_Slot6,
APMETA_Slot7,
APMETA_Slot8,
APMETA_Slot9,
};
class player_t; class player_t;
class PClassPlayerPawn : public PClassActor
{
DECLARE_CLASS(PClassPlayerPawn, PClassActor);
protected:
virtual void Derive(PClass *newclass);
public:
PClassPlayerPawn();
FString DisplayName; // Display name (used in menus, etc.)
FString SoundClass; // Sound class
FString Face; // Doom status bar face (when used)
FString Slot[10];
FName InvulMode;
FName HealingRadiusType;
fixed_t HexenArmor[5];
BYTE ColorRangeStart; // Skin color range
BYTE ColorRangeEnd;
};
class APlayerPawn : public AActor class APlayerPawn : public AActor
{ {
DECLARE_CLASS (APlayerPawn, AActor) DECLARE_CLASS_WITH_META(APlayerPawn, AActor, PClassPlayerPawn)
HAS_OBJECT_POINTERS HAS_OBJECT_POINTERS
public: public:
virtual void Serialize (FArchive &arc); virtual void Serialize (FArchive &arc);
@ -431,7 +423,7 @@ public:
bool CheckSkin (int skin); bool CheckSkin (int skin);
const PClass *Type; PClassPlayerPawn *Type;
DWORD Flags; DWORD Flags;
TArray<int> Skins; TArray<int> Skins;
}; };

View file

@ -60,134 +60,6 @@ ClassReg DObject::RegistrationInfo =
}; };
_DECLARE_TI(DObject) _DECLARE_TI(DObject)
FMetaTable::~FMetaTable ()
{
FreeMeta ();
}
FMetaTable::FMetaTable (const FMetaTable &other)
{
Meta = NULL;
CopyMeta (&other);
}
FMetaTable &FMetaTable::operator = (const FMetaTable &other)
{
CopyMeta (&other);
return *this;
}
void FMetaTable::FreeMeta ()
{
while (Meta != NULL)
{
FMetaData *meta = Meta;
switch (meta->Type)
{
case META_String:
delete[] meta->Value.String;
break;
default:
break;
}
Meta = meta->Next;
delete meta;
}
}
void FMetaTable::CopyMeta (const FMetaTable *other)
{
const FMetaData *meta_src;
FMetaData **meta_dest;
FreeMeta ();
meta_src = other->Meta;
meta_dest = &Meta;
while (meta_src != NULL)
{
FMetaData *newmeta = new FMetaData (meta_src->Type, meta_src->ID);
switch (meta_src->Type)
{
case META_String:
newmeta->Value.String = copystring (meta_src->Value.String);
break;
default:
newmeta->Value = meta_src->Value;
break;
}
*meta_dest = newmeta;
meta_dest = &newmeta->Next;
meta_src = meta_src->Next;
}
*meta_dest = NULL;
}
FMetaData *FMetaTable::FindMeta (EMetaType type, DWORD id) const
{
FMetaData *meta = Meta;
while (meta != NULL)
{
if (meta->ID == id && meta->Type == type)
{
return meta;
}
meta = meta->Next;
}
return NULL;
}
FMetaData *FMetaTable::FindMetaDef (EMetaType type, DWORD id)
{
FMetaData *meta = FindMeta (type, id);
if (meta == NULL)
{
meta = new FMetaData (type, id);
meta->Next = Meta;
meta->Value.String = NULL;
Meta = meta;
}
return meta;
}
void FMetaTable::SetMetaInt (DWORD id, int parm)
{
FMetaData *meta = FindMetaDef (META_Int, id);
meta->Value.Int = parm;
}
int FMetaTable::GetMetaInt (DWORD id, int def) const
{
FMetaData *meta = FindMeta (META_Int, id);
return meta != NULL ? meta->Value.Int : def;
}
void FMetaTable::SetMetaFixed (DWORD id, fixed_t parm)
{
FMetaData *meta = FindMetaDef (META_Fixed, id);
meta->Value.Fixed = parm;
}
fixed_t FMetaTable::GetMetaFixed (DWORD id, fixed_t def) const
{
FMetaData *meta = FindMeta (META_Fixed, id);
return meta != NULL ? meta->Value.Fixed : def;
}
void FMetaTable::SetMetaString (DWORD id, const char *parm)
{
FMetaData *meta = FindMetaDef (META_String, id);
ReplaceString (&meta->Value.String, parm);
}
const char *FMetaTable::GetMetaString (DWORD id) const
{
FMetaData *meta = FindMeta (META_String, id);
return meta != NULL ? meta->Value.String : NULL;
}
CCMD (dumpclasses) CCMD (dumpclasses)
{ {
// This is by no means speed-optimized. But it's an informational console // This is by no means speed-optimized. But it's an informational console

View file

@ -80,56 +80,6 @@ class DPillar;
class PClassActor; class PClassActor;
enum EMetaType
{
META_Int, // An int
META_Fixed, // A fixed point number
META_String, // A string
};
class FMetaData
{
private:
FMetaData (EMetaType type, uint32 id) : Type(type), ID(id) {}
FMetaData *Next;
EMetaType Type;
uint32 ID;
union
{
int Int;
char *String;
fixed_t Fixed;
} Value;
friend class FMetaTable;
};
class FMetaTable
{
public:
FMetaTable() : Meta(NULL) {}
FMetaTable(const FMetaTable &other);
~FMetaTable();
FMetaTable &operator = (const FMetaTable &other);
void SetMetaInt (uint32 id, int parm);
void SetMetaFixed (uint32 id, fixed_t parm);
void SetMetaString (uint32 id, const char *parm); // The string is copied
int GetMetaInt (uint32 id, int def=0) const;
fixed_t GetMetaFixed (uint32 id, fixed_t def=0) const;
const char *GetMetaString (uint32 id) const;
FMetaData *FindMeta (EMetaType type, uint32 id) const;
private:
FMetaData *Meta;
FMetaData *FindMetaDef (EMetaType type, uint32 id);
void FreeMeta ();
void CopyMeta (const FMetaTable *other);
};
#define RUNTIME_TYPE(object) (object->GetClass()) // Passed an object, returns the type of that object #define RUNTIME_TYPE(object) (object->GetClass()) // Passed an object, returns the type of that object
#define RUNTIME_CLASS_CASTLESS(cls) (cls::RegistrationInfo.MyClass) // Passed a native class name, returns a PClass representing that class #define RUNTIME_CLASS_CASTLESS(cls) (cls::RegistrationInfo.MyClass) // Passed a native class name, returns a PClass representing that class
#define RUNTIME_CLASS(cls) ((cls::MetaClass *)RUNTIME_CLASS_CASTLESS(cls)) // Like above, but returns the true type of the meta object #define RUNTIME_CLASS(cls) ((cls::MetaClass *)RUNTIME_CLASS_CASTLESS(cls)) // Like above, but returns the true type of the meta object
@ -140,6 +90,12 @@ enum
{ {
CLASSREG_PClass, CLASSREG_PClass,
CLASSREG_PClassActor, CLASSREG_PClassActor,
CLASSREG_PClassInventory,
CLASSREG_PClassAmmo,
CLASSREG_PClassHealth,
CLASSREG_PClassPuzzleItem,
CLASSREG_PClassWeapon,
CLASSREG_PClassPlayerPawn
}; };
struct ClassReg struct ClassReg
@ -149,8 +105,8 @@ struct ClassReg
ClassReg *ParentType; ClassReg *ParentType;
const size_t *Pointers; const size_t *Pointers;
void (*ConstructNative)(void *); void (*ConstructNative)(void *);
unsigned int SizeOf:31; unsigned int SizeOf:29;
unsigned int MetaClassNum:1; unsigned int MetaClassNum:3;
PClass *RegisterClass(); PClass *RegisterClass();
}; };
@ -159,7 +115,7 @@ enum EInPlace { EC_InPlace };
#define DECLARE_ABSTRACT_CLASS(cls,parent) \ #define DECLARE_ABSTRACT_CLASS(cls,parent) \
public: \ public: \
virtual PClass *StaticType() const { return RegistrationInfo.MyClass; } \ virtual PClass *StaticType() const; \
static ClassReg RegistrationInfo, * const RegistrationInfoPtr; \ static ClassReg RegistrationInfo, * const RegistrationInfoPtr; \
private: \ private: \
typedef parent Super; \ typedef parent Super; \
@ -205,7 +161,8 @@ protected: \
create, \ create, \
sizeof(cls), \ sizeof(cls), \
cls::MetaClassNum }; \ cls::MetaClassNum }; \
_DECLARE_TI(cls) _DECLARE_TI(cls) \
PClass *cls::StaticType() const { return RegistrationInfo.MyClass; }
#define _IMP_CREATE_OBJ(cls) \ #define _IMP_CREATE_OBJ(cls) \
void cls::InPlaceConstructor(void *mem) { new((EInPlace *)mem) cls; } void cls::InPlaceConstructor(void *mem) { new((EInPlace *)mem) cls; }

View file

@ -38,6 +38,8 @@
#include "templates.h" #include "templates.h"
#include "autosegs.h" #include "autosegs.h"
#include "v_text.h" #include "v_text.h"
#include "a_pickups.h"
#include "d_player.h"
IMPLEMENT_POINTY_CLASS(PClass) IMPLEMENT_POINTY_CLASS(PClass)
DECLARE_POINTER(ParentClass) DECLARE_POINTER(ParentClass)
@ -121,6 +123,7 @@ PClass::PClass()
Defaults = NULL; Defaults = NULL;
bRuntimeClass = false; bRuntimeClass = false;
ClassIndex = ~0; ClassIndex = ~0;
ConstructNative = NULL;
} }
PClass::~PClass() PClass::~PClass()
@ -135,6 +138,18 @@ PClass::~PClass()
PClass *ClassReg::RegisterClass() PClass *ClassReg::RegisterClass()
{ {
static ClassReg *const metaclasses[] =
{
&PClass::RegistrationInfo,
&PClassActor::RegistrationInfo,
&PClassInventory::RegistrationInfo,
&PClassAmmo::RegistrationInfo,
&PClassHealth::RegistrationInfo,
&PClassPuzzleItem::RegistrationInfo,
&PClassWeapon::RegistrationInfo,
&PClassPlayerPawn::RegistrationInfo,
};
// MyClass may have already been created by a previous recursive call. // MyClass may have already been created by a previous recursive call.
// Or this may be a recursive call for a previously created class. // Or this may be a recursive call for a previously created class.
if (MyClass != NULL) if (MyClass != NULL)
@ -145,30 +160,35 @@ PClass *ClassReg::RegisterClass()
// Add type to list // Add type to list
PClass *cls; PClass *cls;
switch (MetaClassNum) if (MetaClassNum >= countof(metaclasses))
{ {
case CLASSREG_PClass:
cls = new PClass;
break;
case CLASSREG_PClassActor:
cls = new PClassActor;
break;
default:
assert(0 && "Class registry has an invalid meta class identifier"); assert(0 && "Class registry has an invalid meta class identifier");
} }
if (this == &PClass::RegistrationInfo)
{
cls = new PClass;
}
else
{
if (metaclasses[MetaClassNum]->MyClass == NULL)
{ // Make sure the meta class is already registered before registering this one
metaclasses[MetaClassNum]->RegisterClass();
}
cls = static_cast<PClass *>(metaclasses[MetaClassNum]->MyClass->CreateNew());
}
MyClass = cls; MyClass = cls;
PClass::m_Types.Push(cls); PClass::m_Types.Push(cls);
cls->TypeName = FName(Name+1); cls->TypeName = FName(Name+1);
if (ParentType != NULL)
{
cls->ParentClass = ParentType->RegisterClass();
}
cls->Size = SizeOf; cls->Size = SizeOf;
cls->Pointers = Pointers; cls->Pointers = Pointers;
cls->ConstructNative = ConstructNative; cls->ConstructNative = ConstructNative;
cls->InsertIntoHash(); cls->InsertIntoHash();
if (ParentType != NULL)
{
cls->ParentClass = ParentType->RegisterClass();
}
return cls; return cls;
} }
@ -231,7 +251,7 @@ PClass *PClass::FindClass (FName zaname)
} }
// Create a new object that this class represents // Create a new object that this class represents
DObject *PClass::CreateNew () const DObject *PClass::CreateNew() const
{ {
BYTE *mem = (BYTE *)M_Malloc (Size); BYTE *mem = (BYTE *)M_Malloc (Size);
assert (mem != NULL); assert (mem != NULL);
@ -247,6 +267,23 @@ DObject *PClass::CreateNew () const
return (DObject *)mem; return (DObject *)mem;
} }
// Copies inheritable values into the derived class and other miscellaneous setup.
void PClass::Derive(PClass *newclass)
{
newclass->ParentClass = this;
newclass->ConstructNative = ConstructNative;
// Set up default instance of the new class.
newclass->Defaults = (BYTE *)M_Malloc(newclass->Size);
memcpy(newclass->Defaults, Defaults, Size);
if (newclass->Size > Size)
{
memset(newclass->Defaults + Size, 0, newclass->Size - Size);
}
newclass->Symbols.SetParentTable(&this->Symbols);
}
// Create a new class based on an existing class // Create a new class based on an existing class
PClass *PClass::CreateDerivedClass (FName name, unsigned int size) PClass *PClass::CreateDerivedClass (FName name, unsigned int size)
{ {
@ -275,34 +312,16 @@ PClass *PClass::CreateDerivedClass (FName name, unsigned int size)
} }
type->TypeName = name; type->TypeName = name;
type->ParentClass = this;
type->Size = size; type->Size = size;
type->Pointers = NULL; type->bRuntimeClass = true;
type->ConstructNative = ConstructNative; Derive(type);
if (!notnew) if (!notnew)
{ {
type->ClassIndex = m_Types.Push (type); type->ClassIndex = m_Types.Push (type);
}
type->Meta = Meta;
// Set up default instance of the new class.
type->Defaults = (BYTE *)M_Malloc(size);
memcpy (type->Defaults, Defaults, Size);
if (size > Size)
{
memset (type->Defaults + Size, 0, size - Size);
}
type->FlatPointers = NULL;
type->bRuntimeClass = true;
type->Symbols.SetParentTable (&this->Symbols);
if (!notnew)
{
type->InsertIntoHash(); type->InsertIntoHash();
} }
// If this class has an actor info, then any classes derived from it // If this class is for an actor, push it onto the RuntimeActors stack.
// also need an actor info.
if (type->IsKindOf(RUNTIME_CLASS(PClassActor))) if (type->IsKindOf(RUNTIME_CLASS(PClassActor)))
{ {
m_RuntimeActors.Push(static_cast<PClassActor *>(type)); m_RuntimeActors.Push(static_cast<PClassActor *>(type));
@ -351,17 +370,13 @@ PClass *PClass::FindClassTentative (FName name)
break; break;
} }
} }
PClass *type = new PClassActor; PClass *type = static_cast<PClass *>(GetClass()->CreateNew());
DPrintf("Creating placeholder class %s : %s\n", name.GetChars(), TypeName.GetChars()); DPrintf("Creating placeholder class %s : %s\n", name.GetChars(), TypeName.GetChars());
type->TypeName = name; type->TypeName = name;
type->ParentClass = this; type->ParentClass = this;
type->Size = -1; type->Size = -1;
type->Pointers = NULL;
type->ConstructNative = NULL;
type->ClassIndex = m_Types.Push (type); type->ClassIndex = m_Types.Push (type);
type->Defaults = NULL;
type->FlatPointers = NULL;
type->bRuntimeClass = true; type->bRuntimeClass = true;
type->InsertIntoHash(); type->InsertIntoHash();
return type; return type;

View file

@ -153,6 +153,8 @@ class PClass : public DObject
{ {
DECLARE_CLASS(PClass, DObject); DECLARE_CLASS(PClass, DObject);
HAS_OBJECT_POINTERS; HAS_OBJECT_POINTERS;
protected:
virtual void Derive(PClass *newclass);
public: public:
static void StaticInit (); static void StaticInit ();
static void StaticShutdown (); static void StaticShutdown ();
@ -164,7 +166,6 @@ public:
const size_t *Pointers; // object pointers defined by this class *only* const size_t *Pointers; // object pointers defined by this class *only*
const size_t *FlatPointers; // object pointers defined by this class and all its superclasses; not initialized by default const size_t *FlatPointers; // object pointers defined by this class and all its superclasses; not initialized by default
PClass *HashNext; PClass *HashNext;
FMetaTable Meta;
BYTE *Defaults; BYTE *Defaults;
bool bRuntimeClass; // class was defined at run-time, not compile-time bool bRuntimeClass; // class was defined at run-time, not compile-time
unsigned short ClassIndex; unsigned short ClassIndex;

View file

@ -180,8 +180,8 @@ static void SpawnFly(AActor *self, const PClass *spawntype, FSoundID sound)
FName SpawnName; FName SpawnName;
FDropItem *di; // di will be our drop item list iterator DDropItem *di; // di will be our drop item list iterator
FDropItem *drop; // while drop stays as the reference point. DDropItem *drop; // while drop stays as the reference point.
int n = 0; int n = 0;
// First see if this cube has its own actor list // First see if this cube has its own actor list
@ -197,11 +197,11 @@ static void SpawnFly(AActor *self, const PClass *spawntype, FSoundID sound)
{ {
if (di->Name != NAME_None) if (di->Name != NAME_None)
{ {
if (di->amount < 0) if (di->Amount < 0)
{ {
di->amount = 1; // default value is -1, we need a positive value. di->Amount = 1; // default value is -1, we need a positive value.
} }
n += di->amount; // this is how we can weight the list. n += di->Amount; // this is how we can weight the list.
} }
} }
di = drop; di = drop;
@ -210,7 +210,7 @@ static void SpawnFly(AActor *self, const PClass *spawntype, FSoundID sound)
{ {
if (di->Name != NAME_None) if (di->Name != NAME_None)
{ {
n -= di->amount; // logically, none of the -1 values have survived by now. n -= di->Amount; // logically, none of the -1 values have survived by now.
} }
if ((di->Next != NULL) && (n >= 0)) if ((di->Next != NULL) && (n >= 0))
{ {

View file

@ -390,7 +390,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMissile)
if (!weapon->DepleteAmmo (weapon->bAltFire)) if (!weapon->DepleteAmmo (weapon->bAltFire))
return 0; return 0;
} }
P_SpawnPlayerMissile (self, PClass::FindClass("Rocket")); P_SpawnPlayerMissile (self, PClass::FindActor("Rocket"));
return 0; return 0;
} }
@ -452,7 +452,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FirePlasma)
} }
} }
P_SpawnPlayerMissile (self, PClass::FindClass("PlasmaBall")); P_SpawnPlayerMissile (self, PClass::FindActor("PlasmaBall"));
return 0; return 0;
} }
@ -537,7 +537,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireBFG)
return 0; return 0;
} }
P_SpawnPlayerMissile (self, 0, 0, 0, PClass::FindClass("BFGBall"), self->angle, NULL, NULL, !!(dmflags2 & DF2_NO_FREEAIMBFG)); P_SpawnPlayerMissile (self, 0, 0, 0, PClass::FindActor("BFGBall"), self->angle, NULL, NULL, !!(dmflags2 & DF2_NO_FREEAIMBFG));
return 0; return 0;
} }
@ -619,7 +619,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BFGsound)
DEFINE_ACTION_FUNCTION(AActor, A_FireOldBFG) DEFINE_ACTION_FUNCTION(AActor, A_FireOldBFG)
{ {
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
const PClass * plasma[] = {PClass::FindClass("PlasmaBall1"), PClass::FindClass("PlasmaBall2")}; PClassActor *plasma[] = { PClass::FindActor("PlasmaBall1"), PClass::FindActor("PlasmaBall2") };
AActor * mo = NULL; AActor * mo = NULL;
player_t *player; player_t *player;

View file

@ -65,7 +65,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Tracer)
return 0; return 0;
// spawn a puff of smoke behind the rocket // spawn a puff of smoke behind the rocket
P_SpawnPuff (self, PClass::FindClass(NAME_BulletPuff), self->x, self->y, self->z, 0, 3); P_SpawnPuff (self, PClass::FindActor(NAME_BulletPuff), self->x, self->y, self->z, 0, 3);
smoke = Spawn ("RevenantTracerSmoke", self->x - self->velx, smoke = Spawn ("RevenantTracerSmoke", self->x - self->velx,
self->y - self->vely, self->z, ALLOW_REPLACE); self->y - self->vely, self->z, ALLOW_REPLACE);

View file

@ -83,7 +83,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Srcr1Attack)
return 0; return 0;
} }
const PClass *fx = PClass::FindClass("SorcererFX1"); PClassActor *fx = PClass::FindActor("SorcererFX1");
if (self->health > (self->SpawnHealth()/3)*2) if (self->health > (self->SpawnHealth()/3)*2)
{ // Spit one fireball { // Spit one fireball
P_SpawnMissileZ (self, self->z + 48*FRACUNIT, self->target, fx ); P_SpawnMissileZ (self, self->z + 48*FRACUNIT, self->target, fx );
@ -225,7 +225,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Srcr2Attack)
if (pr_s2a() < chance) if (pr_s2a() < chance)
{ // Wizard spawners { // Wizard spawners
const PClass *fx = PClass::FindClass("Sorcerer2FX2"); PClassActor *fx = PClass::FindActor("Sorcerer2FX2");
if (fx) if (fx)
{ {
P_SpawnMissileAngle (self, fx, self->angle-ANG45, FRACUNIT/2); P_SpawnMissileAngle (self, fx, self->angle-ANG45, FRACUNIT/2);
@ -234,7 +234,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Srcr2Attack)
} }
else else
{ // Blue bolt { // Blue bolt
P_SpawnMissile (self, self->target, PClass::FindClass("Sorcerer2FX1")); P_SpawnMissile (self, self->target, PClass::FindActor("Sorcerer2FX1"));
} }
return 0; return 0;
} }

View file

@ -168,8 +168,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireGoldWandPL2)
angle_t pitch = P_BulletSlope(self); angle_t pitch = P_BulletSlope(self);
velz = FixedMul (GetDefaultByName("GoldWandFX2")->Speed, velz = FixedMul (GetDefaultByName("GoldWandFX2")->Speed,
finetangent[FINEANGLES/4-((signed)pitch>>ANGLETOFINESHIFT)]); finetangent[FINEANGLES/4-((signed)pitch>>ANGLETOFINESHIFT)]);
P_SpawnMissileAngle (self, PClass::FindClass("GoldWandFX2"), self->angle-(ANG45/8), velz); P_SpawnMissileAngle (self, PClass::FindActor("GoldWandFX2"), self->angle-(ANG45/8), velz);
P_SpawnMissileAngle (self, PClass::FindClass("GoldWandFX2"), self->angle+(ANG45/8), velz); P_SpawnMissileAngle (self, PClass::FindActor("GoldWandFX2"), self->angle+(ANG45/8), velz);
angle = self->angle-(ANG45/8); angle = self->angle-(ANG45/8);
for(i = 0; i < 5; i++) for(i = 0; i < 5; i++)
{ {
@ -204,9 +204,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireCrossbowPL1)
if (!weapon->DepleteAmmo (weapon->bAltFire)) if (!weapon->DepleteAmmo (weapon->bAltFire))
return 0; return 0;
} }
P_SpawnPlayerMissile (self, PClass::FindClass("CrossbowFX1")); P_SpawnPlayerMissile (self, PClass::FindActor("CrossbowFX1"));
P_SpawnPlayerMissile (self, PClass::FindClass("CrossbowFX3"), self->angle-(ANG45/10)); P_SpawnPlayerMissile (self, PClass::FindActor("CrossbowFX3"), self->angle-(ANG45/10));
P_SpawnPlayerMissile (self, PClass::FindClass("CrossbowFX3"), self->angle+(ANG45/10)); P_SpawnPlayerMissile (self, PClass::FindActor("CrossbowFX3"), self->angle+(ANG45/10));
return 0; return 0;
} }
@ -233,11 +233,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireCrossbowPL2)
if (!weapon->DepleteAmmo (weapon->bAltFire)) if (!weapon->DepleteAmmo (weapon->bAltFire))
return 0; return 0;
} }
P_SpawnPlayerMissile (self, PClass::FindClass("CrossbowFX2")); P_SpawnPlayerMissile (self, PClass::FindActor("CrossbowFX2"));
P_SpawnPlayerMissile (self, PClass::FindClass("CrossbowFX2"), self->angle-(ANG45/10)); P_SpawnPlayerMissile (self, PClass::FindActor("CrossbowFX2"), self->angle-(ANG45/10));
P_SpawnPlayerMissile (self, PClass::FindClass("CrossbowFX2"), self->angle+(ANG45/10)); P_SpawnPlayerMissile (self, PClass::FindActor("CrossbowFX2"), self->angle+(ANG45/10));
P_SpawnPlayerMissile (self, PClass::FindClass("CrossbowFX3"), self->angle-(ANG45/5)); P_SpawnPlayerMissile (self, PClass::FindActor("CrossbowFX3"), self->angle-(ANG45/5));
P_SpawnPlayerMissile (self, PClass::FindClass("CrossbowFX3"), self->angle+(ANG45/5)); P_SpawnPlayerMissile (self, PClass::FindActor("CrossbowFX3"), self->angle+(ANG45/5));
return 0; return 0;
} }
@ -448,7 +448,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMacePL1)
} }
player->psprites[ps_weapon].sx = ((pr_maceatk()&3)-2)*FRACUNIT; player->psprites[ps_weapon].sx = ((pr_maceatk()&3)-2)*FRACUNIT;
player->psprites[ps_weapon].sy = WEAPONTOP+(pr_maceatk()&3)*FRACUNIT; player->psprites[ps_weapon].sy = WEAPONTOP+(pr_maceatk()&3)*FRACUNIT;
ball = P_SpawnPlayerMissile (self, PClass::FindClass("MaceFX1"), ball = P_SpawnPlayerMissile (self, PClass::FindActor("MaceFX1"),
self->angle+(((pr_maceatk()&7)-4)<<24)); self->angle+(((pr_maceatk()&7)-4)<<24));
if (ball) if (ball)
{ {
@ -942,7 +942,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSkullRodPL1)
if (!weapon->DepleteAmmo (weapon->bAltFire)) if (!weapon->DepleteAmmo (weapon->bAltFire))
return 0; return 0;
} }
mo = P_SpawnPlayerMissile (self, PClass::FindClass("HornRodFX1")); mo = P_SpawnPlayerMissile (self, PClass::FindActor("HornRodFX1"));
// Randomize the first frame // Randomize the first frame
if (mo && pr_fsr1() > 128) if (mo && pr_fsr1() > 128)
{ {

View file

@ -84,7 +84,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_WizAtk3)
P_TraceBleed (damage, self->target, self); P_TraceBleed (damage, self->target, self);
return 0; return 0;
} }
const PClass *fx = PClass::FindClass("WizardFX1"); PClassActor *fx = PClass::FindActor("WizardFX1");
mo = P_SpawnMissile (self, self->target, fx); mo = P_SpawnMissile (self, self->target, fx);
if (mo != NULL) if (mo != NULL)
{ {

View file

@ -48,7 +48,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BatSpawn)
delta = self->args[1]; delta = self->args[1];
if (delta==0) delta=1; if (delta==0) delta=1;
angle = self->angle + (((pr_batspawn()%delta)-(delta>>1))<<24); angle = self->angle + (((pr_batspawn()%delta)-(delta>>1))<<24);
mo = P_SpawnMissileAngle (self, PClass::FindClass ("Bat"), angle, 0); mo = P_SpawnMissileAngle (self, PClass::FindActor("Bat"), angle, 0);
if (mo) if (mo)
{ {
mo->args[0] = pr_batspawn()&63; // floatbob index mo->args[0] = pr_batspawn()&63; // floatbob index

View file

@ -249,8 +249,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_CHolyAttack)
if (!weapon->DepleteAmmo (weapon->bAltFire)) if (!weapon->DepleteAmmo (weapon->bAltFire))
return 0; return 0;
} }
AActor * missile = P_SpawnPlayerMissile (self, 0,0,0, PClass::FindClass ("HolyMissile"), self->angle, &linetarget); AActor *missile = P_SpawnPlayerMissile (self, 0,0,0, PClass::FindActor("HolyMissile"), self->angle, &linetarget);
if (missile != NULL) missile->tracer = linetarget; if (missile != NULL)
{
missile->tracer = linetarget;
}
weapon->CHolyCount = 3; weapon->CHolyCount = 3;
S_Sound (self, CHAN_WEAPON, "HolySymbolFire", 1, ATTN_NORM); S_Sound (self, CHAN_WEAPON, "HolySymbolFire", 1, ATTN_NORM);

View file

@ -126,7 +126,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FHammerThrow)
if (!weapon->DepleteAmmo (weapon->bAltFire, false)) if (!weapon->DepleteAmmo (weapon->bAltFire, false))
return 0; return 0;
} }
mo = P_SpawnPlayerMissile (player->mo, PClass::FindClass ("HammerMissile")); mo = P_SpawnPlayerMissile (player->mo, PClass::FindActor("HammerMissile"));
if (mo) if (mo)
{ {
mo->special1 = 0; mo->special1 = 0;

View file

@ -30,7 +30,12 @@ IMPLEMENT_CLASS (AArtiHealingRadius)
bool AArtiHealingRadius::Use (bool pickup) bool AArtiHealingRadius::Use (bool pickup)
{ {
bool effective = false; bool effective = false;
int mode = Owner->GetClass()->Meta.GetMetaInt(APMETA_HealingRadius); FName mode;
if (Owner->IsKindOf(RUNTIME_CLASS(APlayerPawn)))
{
mode = static_cast<PClassPlayerPawn *>(Owner->GetClass())->HealingRadiusType;
}
for (int i = 0; i < MAXPLAYERS; ++i) for (int i = 0; i < MAXPLAYERS; ++i)
{ {

View file

@ -574,7 +574,7 @@ void ASorcBall3::CastSorcererSpell ()
ang1 = angle - ANGLE_45; ang1 = angle - ANGLE_45;
ang2 = angle + ANGLE_45; ang2 = angle + ANGLE_45;
const PClass *cls = PClass::FindClass("SorcFX3"); PClassActor *cls = PClass::FindActor("SorcFX3");
if (health < (SpawnHealth()/3)) if (health < (SpawnHealth()/3))
{ // Spawn 2 at a time { // Spawn 2 at a time
mo = P_SpawnMissileAngle(parent, cls, ang1, 4*FRACUNIT); mo = P_SpawnMissileAngle(parent, cls, ang1, 4*FRACUNIT);
@ -623,7 +623,7 @@ void ASorcBall1::CastSorcererSpell ()
ang1 = angle + ANGLE_1*70; ang1 = angle + ANGLE_1*70;
ang2 = angle - ANGLE_1*70; ang2 = angle - ANGLE_1*70;
const PClass *cls = PClass::FindClass("SorcFX1"); PClassActor *cls = PClass::FindActor("SorcFX1");
mo = P_SpawnMissileAngle (parent, cls, ang1, 0); mo = P_SpawnMissileAngle (parent, cls, ang1, 0);
if (mo) if (mo)
{ {
@ -670,7 +670,7 @@ void A_SorcOffense2(AActor *actor)
delta = (finesine[index])*SORCFX4_SPREAD_ANGLE; delta = (finesine[index])*SORCFX4_SPREAD_ANGLE;
delta = (delta>>FRACBITS)*ANGLE_1; delta = (delta>>FRACBITS)*ANGLE_1;
ang1 = actor->angle + delta; ang1 = actor->angle + delta;
mo = P_SpawnMissileAngle(parent, PClass::FindClass("SorcFX4"), ang1, 0); mo = P_SpawnMissileAngle(parent, PClass::FindActor("SorcFX4"), ang1, 0);
if (mo) if (mo)
{ {
mo->special2 = 35*5/2; // 5 seconds mo->special2 = 35*5/2; // 5 seconds

View file

@ -144,7 +144,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_IceGuyMissileExplode)
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
{ {
mo = P_SpawnMissileAngleZ (self, self->z+3*FRACUNIT, mo = P_SpawnMissileAngleZ (self, self->z+3*FRACUNIT,
PClass::FindClass("IceGuyFX2"), i*ANG45, (fixed_t)(-0.3*FRACUNIT)); PClass::FindActor("IceGuyFX2"), i*ANG45, (fixed_t)(-0.3*FRACUNIT));
if (mo) if (mo)
{ {
mo->target = self->target; mo->target = self->target;

View file

@ -164,8 +164,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_KoraxBonePop)
// Spawn 6 spirits equalangularly // Spawn 6 spirits equalangularly
for (i = 0; i < 6; ++i) for (i = 0; i < 6; ++i)
{ {
mo = P_SpawnMissileAngle (self, PClass::FindClass("KoraxSpirit"), ANGLE_60*i, 5*FRACUNIT); mo = P_SpawnMissileAngle (self, PClass::FindActor("KoraxSpirit"), ANGLE_60*i, 5*FRACUNIT);
if (mo) KSpiritInit (mo, self); if (mo)
{
KSpiritInit (mo, self);
}
} }
P_StartScript (self, NULL, 255, NULL, 0, 0, 0, 0, false, false); // Death script P_StartScript (self, NULL, 255, NULL, 0, 0, 0, 0, false, false); // Death script

View file

@ -215,10 +215,15 @@ DEFINE_ACTION_FUNCTION(AActor, A_LightningZap)
{ {
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
const PClass *lightning=PClass::FindClass((ENamedName) self->GetClass()->Meta.GetMetaInt (ACMETA_MissileName, NAME_LightningZap)); PClassActor *lightning = PClass::FindActor(self->GetClass()->MissileName);
AActor *mo; AActor *mo;
fixed_t deltaZ; fixed_t deltaZ;
if (lightning == NULL)
{
lightning = PClass::FindActor(NAME_LightningZap);
}
CALL_ACTION(A_LightningClip, self); CALL_ACTION(A_LightningClip, self);
self->health -= 8; self->health -= 8;
@ -338,10 +343,14 @@ DEFINE_ACTION_FUNCTION(AActor, A_ZapMimic)
DEFINE_ACTION_FUNCTION(AActor, A_LastZap) DEFINE_ACTION_FUNCTION(AActor, A_LastZap)
{ {
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
const PClass *lightning=PClass::FindClass((ENamedName) self->GetClass()->Meta.GetMetaInt (ACMETA_MissileName, NAME_LightningZap)); PClassActor *lightning = PClass::FindActor(self->GetClass()->MissileName);
AActor *mo; AActor *mo;
if (lightning == NULL)
{
lightning = PClass::FindActor(NAME_LightningZap);
}
mo = Spawn(lightning, self->x, self->y, self->z, ALLOW_REPLACE); mo = Spawn(lightning, self->x, self->y, self->z, ALLOW_REPLACE);
if (mo) if (mo)
{ {

View file

@ -31,7 +31,7 @@ IMPLEMENT_CLASS (AArtiDarkServant)
bool AArtiDarkServant::Use (bool pickup) bool AArtiDarkServant::Use (bool pickup)
{ {
AActor *mo = P_SpawnPlayerMissile (Owner, PClass::FindClass ("SummoningDoll")); AActor *mo = P_SpawnPlayerMissile (Owner, PClass::FindActor("SummoningDoll"));
if (mo) if (mo)
{ {
mo->target = Owner; mo->target = Owner;

View file

@ -301,7 +301,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurAtk2)
return 0; return 0;
} }
z = self->z + 40*FRACUNIT; z = self->z + 40*FRACUNIT;
const PClass *fx = PClass::FindClass("MinotaurFX1"); PClassActor *fx = PClass::FindActor("MinotaurFX1");
if (fx) if (fx)
{ {
mo = P_SpawnMissileZ (self, z, self->target, fx); mo = P_SpawnMissileZ (self, z, self->target, fx);

View file

@ -83,7 +83,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_NoBlocking)
// If the self has attached metadata for items to drop, drop those. // If the self has attached metadata for items to drop, drop those.
if (!self->IsKindOf (RUNTIME_CLASS (APlayerPawn))) // [GRB] if (!self->IsKindOf (RUNTIME_CLASS (APlayerPawn))) // [GRB]
{ {
FDropItem *di = self->GetDropItems(); DDropItem *di = self->GetDropItems();
if (di != NULL) if (di != NULL)
{ {
@ -92,7 +92,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_NoBlocking)
if (di->Name != NAME_None) if (di->Name != NAME_None)
{ {
const PClass *ti = PClass::FindClass(di->Name); const PClass *ti = PClass::FindClass(di->Name);
if (ti) P_DropItem (self, ti, di->amount, di->probability); if (ti) P_DropItem (self, ti, di->Amount, di->Probability);
} }
di = di->Next; di = di->Next;
} }

View file

@ -349,9 +349,9 @@ void APowerInvulnerable::InitEffect ()
{ {
Owner->effects &= ~FX_RESPAWNINVUL; Owner->effects &= ~FX_RESPAWNINVUL;
Owner->flags2 |= MF2_INVULNERABLE; Owner->flags2 |= MF2_INVULNERABLE;
if (Mode == NAME_None) if (Mode == NAME_None && Owner->IsKindOf(RUNTIME_CLASS(APlayerPawn)))
{ {
Mode = (ENamedName)RUNTIME_TYPE(Owner)->Meta.GetMetaInt(APMETA_InvulMode); Mode = static_cast<PClassPlayerPawn *>(Owner->GetClass())->InvulMode;
} }
if (Mode == NAME_Reflective) if (Mode == NAME_Reflective)
{ {
@ -1729,7 +1729,7 @@ void APowerMorph::InitEffect( )
player_t *realplayer = Owner->player; // Remember the identity of the player player_t *realplayer = Owner->player; // Remember the identity of the player
const PClass *morph_flash = PClass::FindClass (MorphFlash); const PClass *morph_flash = PClass::FindClass (MorphFlash);
const PClass *unmorph_flash = PClass::FindClass (UnMorphFlash); const PClass *unmorph_flash = PClass::FindClass (UnMorphFlash);
const PClass *player_class = PClass::FindClass (PlayerClass); PClassPlayerPawn *player_class = dyn_cast<PClassPlayerPawn>(PClass::FindClass (PlayerClass));
if (P_MorphPlayer(realplayer, realplayer, player_class, -1/*INDEFINITELY*/, MorphStyle, morph_flash, unmorph_flash)) if (P_MorphPlayer(realplayer, realplayer, player_class, -1/*INDEFINITELY*/, MorphStyle, morph_flash, unmorph_flash))
{ {
Owner = realplayer->mo; // Replace the new owner in our owner; safe because we are not attached to anything yet Owner = realplayer->mo; // Replace the new owner in our owner; safe because we are not attached to anything yet

View file

@ -154,7 +154,7 @@ void AFastProjectile::Effect()
{ {
//if (pr_smoke() < 128) // [RH] I think it looks better if it's consistent //if (pr_smoke() < 128) // [RH] I think it looks better if it's consistent
{ {
FName name = (ENamedName) this->GetClass()->Meta.GetMetaInt (ACMETA_MissileName, NAME_None); FName name = GetClass()->MissileName;
if (name != NAME_None) if (name != NAME_None)
{ {
fixed_t hitz = z-8*FRACUNIT; fixed_t hitz = z-8*FRACUNIT;

View file

@ -25,7 +25,7 @@ static FRandom pr_morphmonst ("MorphMonster");
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool P_MorphPlayer (player_t *activator, player_t *p, const PClass *spawntype, int duration, int style, const PClass *enter_flash, const PClass *exit_flash) bool P_MorphPlayer (player_t *activator, player_t *p, PClassPlayerPawn *spawntype, int duration, int style, const PClass *enter_flash, const PClass *exit_flash)
{ {
AInventory *item; AInventory *item;
APlayerPawn *morphed; APlayerPawn *morphed;
@ -129,7 +129,7 @@ bool P_MorphPlayer (player_t *activator, player_t *p, const PClass *spawntype, i
hxarmor->Slots[1] = 0; hxarmor->Slots[1] = 0;
hxarmor->Slots[2] = 0; hxarmor->Slots[2] = 0;
hxarmor->Slots[3] = 0; hxarmor->Slots[3] = 0;
hxarmor->Slots[4] = spawntype->Meta.GetMetaFixed (APMETA_Hexenarmor0); hxarmor->Slots[4] = spawntype->HexenArmor[0];
} }
else if (item->ItemFlags & IF_KEEPDEPLETED) else if (item->ItemFlags & IF_KEEPDEPLETED)
{ {
@ -157,9 +157,7 @@ bool P_MorphPlayer (player_t *activator, player_t *p, const PClass *spawntype, i
// and for the original DOOM status bar. // and for the original DOOM status bar.
if (p == &players[consoleplayer]) if (p == &players[consoleplayer])
{ {
const char *face = spawntype->Meta.GetMetaString (APMETA_Face); if (spawntype->Face.IsNotEmpty() && strcmp(spawntype->Face, "None") != 0)
if (face != NULL && strcmp(face, "None") != 0)
{ {
StatusBar->SetFace(&skins[p->MorphedPlayerClass]); StatusBar->SetFace(&skins[p->MorphedPlayerClass]);
} }
@ -285,8 +283,8 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag,
// and for the original DOOM status bar. // and for the original DOOM status bar.
if ((player == &players[consoleplayer])) if ((player == &players[consoleplayer]))
{ {
const char *face = pmo->GetClass()->Meta.GetMetaString (APMETA_Face); FString face = pmo->GetClass()->Face;
if (face != NULL && strcmp(face, "None") != 0) if (face.IsNotEmpty() && strcmp(face, "None") != 0)
{ {
// Assume root-level base skin to begin with // Assume root-level base skin to begin with
size_t skinindex = 0; size_t skinindex = 0;
@ -361,7 +359,7 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag,
AHexenArmor *hxarmor = mo->FindInventory<AHexenArmor>(); AHexenArmor *hxarmor = mo->FindInventory<AHexenArmor>();
if (hxarmor != NULL) if (hxarmor != NULL)
{ {
hxarmor->Slots[4] = mo->GetClass()->Meta.GetMetaFixed (APMETA_Hexenarmor0); hxarmor->Slots[4] = mo->GetClass()->HexenArmor[0];
} }
return true; return true;
} }
@ -558,7 +556,7 @@ int AMorphProjectile::DoSpecialDamage (AActor *target, int damage)
const PClass *unmorph_flash = PClass::FindClass (UnMorphFlash); const PClass *unmorph_flash = PClass::FindClass (UnMorphFlash);
if (target->player) if (target->player)
{ {
const PClass *player_class = PClass::FindClass (PlayerClass); PClassPlayerPawn *player_class = dyn_cast<PClassPlayerPawn>(PClass::FindClass(PlayerClass));
P_MorphPlayer (NULL, target->player, player_class, Duration, MorphStyle, morph_flash, unmorph_flash); P_MorphPlayer (NULL, target->player, player_class, Duration, MorphStyle, morph_flash, unmorph_flash);
} }
else else

View file

@ -33,7 +33,7 @@ class AActor;
class player_t; class player_t;
class AMorphedMonster; class AMorphedMonster;
bool P_MorphPlayer (player_t *activator, player_t *player, const PClass *morphclass, int duration = 0, int style = 0, bool P_MorphPlayer (player_t *activator, player_t *player, PClassPlayerPawn *morphclass, int duration = 0, int style = 0,
const PClass *enter_flash = NULL, const PClass *exit_flash = NULL); const PClass *enter_flash = NULL, const PClass *exit_flash = NULL);
bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag = 0, bool force = false); bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag = 0, bool force = false);
bool P_MorphMonster (AActor *actor, const PClass *morphclass, int duration = 0, int style = 0, bool P_MorphMonster (AActor *actor, const PClass *morphclass, int duration = 0, int style = 0,

View file

@ -20,6 +20,41 @@
static FRandom pr_restore ("RestorePos"); static FRandom pr_restore ("RestorePos");
IMPLEMENT_CLASS(PClassInventory)
PClassInventory::PClassInventory()
{
GiveQuest = 0;
AltHUDIcon.SetInvalid();
}
void PClassInventory::Derive(PClass *newclass)
{
assert(newclass->IsKindOf(RUNTIME_CLASS(PClassInventory)));
Super::Derive(newclass);
PClassInventory *newc = static_cast<PClassInventory *>(newclass);
newc->PickupMessage = PickupMessage;
newc->GiveQuest = GiveQuest;
newc->AltHUDIcon = AltHUDIcon;
}
IMPLEMENT_CLASS(PClassAmmo)
PClassAmmo::PClassAmmo()
{
DropAmount = 0;
}
void PClassAmmo::Derive(PClass *newclass)
{
assert(newclass->IsKindOf(RUNTIME_CLASS(PClassAmmo)));
Super::Derive(newclass);
PClassAmmo *newc = static_cast<PClassAmmo *>(newclass);
newc->DropAmount = DropAmount;
}
IMPLEMENT_CLASS (AAmmo) IMPLEMENT_CLASS (AAmmo)
//=========================================================================== //===========================================================================
@ -970,9 +1005,9 @@ void AInventory::DoPickupSpecial (AActor *toucher)
const char *AInventory::PickupMessage () const char *AInventory::PickupMessage ()
{ {
const char *message = GetClass()->Meta.GetMetaString (AIMETA_PickupMessage); FString message = GetClass()->PickupMessage;
return message != NULL? message : "You got a pickup"; return message.IsNotEmpty() ? message : "You got a pickup";
} }
//=========================================================================== //===========================================================================
@ -1169,8 +1204,8 @@ bool AInventory::DoRespawn ()
void AInventory::GiveQuest (AActor *toucher) void AInventory::GiveQuest (AActor *toucher)
{ {
int quest = GetClass()->Meta.GetMetaInt(AIMETA_GiveQuest); int quest = GetClass()->GiveQuest;
if (quest>0 && quest<31) if (quest > 0 && quest <= countof(QuestItemClasses))
{ {
toucher->GiveInventoryType (QuestItemClasses[quest-1]); toucher->GiveInventoryType (QuestItemClasses[quest-1]);
} }
@ -1394,6 +1429,35 @@ bool ACustomInventory::TryPickup (AActor *&toucher)
return useok; return useok;
} }
IMPLEMENT_CLASS(PClassHealth)
//===========================================================================
//
// PClassHealth Constructor
//
//===========================================================================
PClassHealth::PClassHealth()
{
LowHealth = 0;
}
//===========================================================================
//
// PClassHealth :: Derive
//
//===========================================================================
void PClassHealth::Derive(PClass *newclass)
{
assert(newclass->IsKindOf(RUNTIME_CLASS(PClassHealth)));
Super::Derive(newclass);
PClassHealth *newc = static_cast<PClassHealth *>(newclass);
newc->LowHealth = LowHealth;
newc->LowHealthMessage = LowHealthMessage;
}
IMPLEMENT_CLASS (AHealth) IMPLEMENT_CLASS (AHealth)
//=========================================================================== //===========================================================================
@ -1403,13 +1467,13 @@ IMPLEMENT_CLASS (AHealth)
//=========================================================================== //===========================================================================
const char *AHealth::PickupMessage () const char *AHealth::PickupMessage ()
{ {
int threshold = GetClass()->Meta.GetMetaInt(AIMETA_LowHealth, 0); int threshold = GetClass()->LowHealth;
if (PrevHealth < threshold) if (PrevHealth < threshold)
{ {
const char *message = GetClass()->Meta.GetMetaString (AIMETA_LowHealthMessage); FString message = GetClass()->LowHealthMessage;
if (message != NULL) if (message.IsNotEmpty())
{ {
return message; return message;
} }

View file

@ -10,6 +10,8 @@
class player_t; class player_t;
class FConfigFile; class FConfigFile;
class AWeapon; class AWeapon;
class PClassWeapon;
class PClassPlayerPawn;
class FWeaponSlot class FWeaponSlot
{ {
@ -19,13 +21,13 @@ public:
FWeaponSlot &operator= (const FWeaponSlot &other) { Weapons = other.Weapons; return *this; } FWeaponSlot &operator= (const FWeaponSlot &other) { Weapons = other.Weapons; return *this; }
void Clear() { Weapons.Clear(); } void Clear() { Weapons.Clear(); }
bool AddWeapon (const char *type); bool AddWeapon (const char *type);
bool AddWeapon (PClassActor *type); bool AddWeapon (PClassWeapon *type);
void AddWeaponList (const char *list, bool clear); void AddWeaponList (const char *list, bool clear);
AWeapon *PickWeapon (player_t *player); AWeapon *PickWeapon (player_t *player);
int Size () const { return (int)Weapons.Size(); } int Size () const { return (int)Weapons.Size(); }
int LocateWeapon (PClassActor *type); int LocateWeapon (PClassWeapon *type);
inline PClassActor *GetWeapon (int index) const inline PClassWeapon *GetWeapon (int index) const
{ {
if ((unsigned)index < Weapons.Size()) if ((unsigned)index < Weapons.Size())
{ {
@ -42,7 +44,7 @@ public:
private: private:
struct WeaponInfo struct WeaponInfo
{ {
PClassActor *Type; PClassWeapon *Type;
fixed_t Position; fixed_t Position;
}; };
void SetInitialPositions(); void SetInitialPositions();
@ -68,25 +70,25 @@ struct FWeaponSlots
AWeapon *PickPrevWeapon (player_t *player); AWeapon *PickPrevWeapon (player_t *player);
void Clear (); void Clear ();
bool LocateWeapon (PClassActor *type, int *const slot, int *const index); bool LocateWeapon (PClassWeapon *type, int *const slot, int *const index);
ESlotDef AddDefaultWeapon (int slot, PClassActor *type); ESlotDef AddDefaultWeapon (int slot, PClassWeapon *type);
void AddExtraWeapons(); void AddExtraWeapons();
void SetFromGameInfo(); void SetFromGameInfo();
void SetFromPlayer(PClassActor *type); void SetFromPlayer(PClassPlayerPawn *type);
void StandardSetup(PClassActor *type); void StandardSetup(PClassPlayerPawn *type);
void LocalSetup(PClassActor *type); void LocalSetup(PClassActor *type);
void SendDifferences(const FWeaponSlots &other); void SendDifferences(const FWeaponSlots &other);
int RestoreSlots (FConfigFile *config, const char *section); int RestoreSlots (FConfigFile *config, const char *section);
void PrintSettings(); void PrintSettings();
void AddSlot(int slot, PClassActor *type, bool feedback); void AddSlot(int slot, PClassWeapon *type, bool feedback);
void AddSlotDefault(int slot, PClassActor *type, bool feedback); void AddSlotDefault(int slot, PClassWeapon *type, bool feedback);
}; };
void P_PlaybackKeyConfWeapons(FWeaponSlots *slots); void P_PlaybackKeyConfWeapons(FWeaponSlots *slots);
void Net_WriteWeapon(PClassActor *type); void Net_WriteWeapon(PClassWeapon *type);
PClassActor *Net_ReadWeapon(BYTE **stream); PClassWeapon *Net_ReadWeapon(BYTE **stream);
void P_SetupWeapons_ntohton(); void P_SetupWeapons_ntohton();
void P_WriteDemoWeaponsChunk(BYTE **demo); void P_WriteDemoWeaponsChunk(BYTE **demo);
@ -98,17 +100,6 @@ void P_ReadDemoWeaponsChunk(BYTE **demo);
// A pickup is anything the player can pickup (i.e. weapons, ammo, powerups, etc) // A pickup is anything the player can pickup (i.e. weapons, ammo, powerups, etc)
enum
{
AIMETA_BASE = 0x71000,
AIMETA_PickupMessage, // string
AIMETA_GiveQuest, // optionally give one of the quest items.
AIMETA_DropAmount, // specifies the amount for a dropped ammo item
AIMETA_LowHealth,
AIMETA_LowHealthMessage,
AIMETA_PuzzFailMessage,
};
enum enum
{ {
IF_ACTIVATABLE = 1<<0, // can be activated IF_ACTIVATABLE = 1<<0, // can be activated
@ -134,9 +125,22 @@ enum
struct vissprite_t; struct vissprite_t;
class PClassInventory : public PClassActor
{
DECLARE_CLASS(PClassInventory, PClassActor)
protected:
virtual void Derive(PClass *newclass);
public:
PClassInventory();
FString PickupMessage;
int GiveQuest; // Optionally give one of the quest items.
FTextureID AltHUDIcon;
};
class AInventory : public AActor class AInventory : public AActor
{ {
DECLARE_CLASS (AInventory, AActor) DECLARE_CLASS_WITH_META(AInventory, AActor, PClassInventory)
HAS_OBJECT_POINTERS HAS_OBJECT_POINTERS
public: public:
virtual void Touch (AActor *toucher); virtual void Touch (AActor *toucher);
@ -172,7 +176,7 @@ public:
const PClass *SpawnPointClass; // For respawning like Heretic's mace const PClass *SpawnPointClass; // For respawning like Heretic's mace
DWORD ItemFlags; DWORD ItemFlags;
const PClass *PickupFlash; // actor to spawn as pickup flash PClassActor *PickupFlash; // actor to spawn as pickup flash
FSoundIDNoInit PickupSound; FSoundIDNoInit PickupSound;
@ -220,9 +224,20 @@ public:
}; };
// Ammo: Something a weapon needs to operate // Ammo: Something a weapon needs to operate
class PClassAmmo : public PClassInventory
{
DECLARE_CLASS(PClassAmmo, PClassInventory)
protected:
virtual void Derive(PClass *newclass);
public:
PClassAmmo();
int DropAmount; // Specifies the amount for a dropped ammo item.
};
class AAmmo : public AInventory class AAmmo : public AInventory
{ {
DECLARE_CLASS (AAmmo, AInventory) DECLARE_CLASS_WITH_META(AAmmo, AInventory, PClassAmmo)
public: public:
void Serialize (FArchive &arc); void Serialize (FArchive &arc);
AInventory *CreateCopy (AActor *other); AInventory *CreateCopy (AActor *other);
@ -234,27 +249,32 @@ public:
}; };
// A weapon is just that. // A weapon is just that.
enum class PClassWeapon : public PClassInventory
{ {
AWMETA_BASE = 0x72000, DECLARE_CLASS(PClassWeapon, PClassInventory);
AWMETA_SlotNumber, protected:
AWMETA_SlotPriority, virtual void Derive(PClass *newclass);
public:
PClassWeapon();
int SlotNumber;
fixed_t SlotPriority;
}; };
class AWeapon : public AInventory class AWeapon : public AInventory
{ {
DECLARE_CLASS (AWeapon, AInventory) DECLARE_CLASS_WITH_META(AWeapon, AInventory, PClassWeapon)
HAS_OBJECT_POINTERS HAS_OBJECT_POINTERS
public: public:
DWORD WeaponFlags; DWORD WeaponFlags;
PClassActor *AmmoType1, *AmmoType2; // Types of ammo used by this weapon PClassAmmo *AmmoType1, *AmmoType2; // Types of ammo used by this weapon
int AmmoGive1, AmmoGive2; // Amount of each ammo to get when picking up weapon int AmmoGive1, AmmoGive2; // Amount of each ammo to get when picking up weapon
int MinAmmo1, MinAmmo2; // Minimum ammo needed to switch to this weapon int MinAmmo1, MinAmmo2; // Minimum ammo needed to switch to this weapon
int AmmoUse1, AmmoUse2; // How much ammo to use with each shot int AmmoUse1, AmmoUse2; // How much ammo to use with each shot
int Kickback; int Kickback;
fixed_t YAdjust; // For viewing the weapon fullscreen fixed_t YAdjust; // For viewing the weapon fullscreen
FSoundIDNoInit UpSound, ReadySound; // Sounds when coming up and idle FSoundIDNoInit UpSound, ReadySound; // Sounds when coming up and idle
PClassActor *SisterWeaponType; // Another weapon to pick up with this one PClassWeapon *SisterWeaponType; // Another weapon to pick up with this one
PClassActor *ProjectileType; // Projectile used by primary attack PClassActor *ProjectileType; // Projectile used by primary attack
PClassActor *AltProjectileType; // Projectile used by alternate attack PClassActor *AltProjectileType; // Projectile used by alternate attack
int SelectionOrder; // Lower-numbered weapons get picked first int SelectionOrder; // Lower-numbered weapons get picked first
@ -302,7 +322,7 @@ public:
protected: protected:
AAmmo *AddAmmo (AActor *other, PClassActor *ammotype, int amount); AAmmo *AddAmmo (AActor *other, PClassActor *ammotype, int amount);
bool AddExistingAmmo (AAmmo *ammo, int amount); bool AddExistingAmmo (AAmmo *ammo, int amount);
AWeapon *AddWeapon (PClassActor *weapon); AWeapon *AddWeapon (PClassWeapon *weapon);
}; };
enum enum
@ -336,9 +356,21 @@ enum
#define S_LIGHTDONE 0 #define S_LIGHTDONE 0
// Health is some item that gives the player health when picked up. // Health is some item that gives the player health when picked up.
class PClassHealth : public PClassInventory
{
DECLARE_CLASS(PClassHealth, PClassInventory)
protected:
virtual void Derive(PClass *newclass);
public:
PClassHealth();
FString LowHealthMessage;
int LowHealth;
};
class AHealth : public AInventory class AHealth : public AInventory
{ {
DECLARE_CLASS (AHealth, AInventory) DECLARE_CLASS_WITH_META(AHealth, AInventory, PClassHealth)
int PrevHealth; int PrevHealth;
public: public:
@ -440,9 +472,18 @@ protected:
}; };
// PuzzleItems work in conjunction with the UsePuzzleItem special // PuzzleItems work in conjunction with the UsePuzzleItem special
class PClassPuzzleItem : public PClassInventory
{
DECLARE_CLASS(PClassPuzzleItem, PClassInventory);
protected:
virtual void Derive(PClass *newclass);
public:
FString PuzzFailMessage;
};
class APuzzleItem : public AInventory class APuzzleItem : public AInventory
{ {
DECLARE_CLASS (APuzzleItem, AInventory) DECLARE_CLASS_WITH_META(APuzzleItem, AInventory, PClassPuzzleItem)
public: public:
void Serialize (FArchive &arc); void Serialize (FArchive &arc);
bool ShouldStay (); bool ShouldStay ();

View file

@ -8,7 +8,16 @@
#include "doomstat.h" #include "doomstat.h"
#include "v_font.h" #include "v_font.h"
IMPLEMENT_CLASS (APuzzleItem) IMPLEMENT_CLASS(PClassPuzzleItem)
void PClassPuzzleItem::Derive(PClass *newclass)
{
Super::Derive(newclass);
assert(newclass->IsKindOf(RUNTIME_CLASS(PClassPuzzleItem)));
static_cast<PClassPuzzleItem *>(newclass)->PuzzFailMessage = PuzzFailMessage;
}
IMPLEMENT_CLASS(APuzzleItem)
void APuzzleItem::Serialize (FArchive &arc) void APuzzleItem::Serialize (FArchive &arc)
{ {
@ -36,9 +45,9 @@ bool APuzzleItem::Use (bool pickup)
S_Sound (Owner, CHAN_VOICE, "*puzzfail", 1, ATTN_IDLE); S_Sound (Owner, CHAN_VOICE, "*puzzfail", 1, ATTN_IDLE);
if (Owner != NULL && Owner->CheckLocalView (consoleplayer)) if (Owner != NULL && Owner->CheckLocalView (consoleplayer))
{ {
const char *message = GetClass()->Meta.GetMetaString (AIMETA_PuzzFailMessage); FString message = GetClass()->PuzzFailMessage;
if (message != NULL && *message=='$') message = GStrings[message + 1]; if (message.IsNotEmpty() && message[0] == '$') message = GStrings[&message[1]];
if (message == NULL) message = GStrings("TXT_USEPUZZLEFAILED"); if (message.IsEmpty()) message = GStrings("TXT_USEPUZZLEFAILED");
C_MidPrintBold (SmallFont, message); C_MidPrintBold (SmallFont, message);
} }
return false; return false;

View file

@ -28,9 +28,9 @@ class ARandomSpawner : public AActor
// random spawner's velocity (0...) instead of their own. // random spawner's velocity (0...) instead of their own.
void BeginPlay() void BeginPlay()
{ {
FDropItem *di; // di will be our drop item list iterator DDropItem *di; // di will be our drop item list iterator
FDropItem *drop; // while drop stays as the reference point. DDropItem *drop; // while drop stays as the reference point.
int n=0; int n = 0;
Super::BeginPlay(); Super::BeginPlay();
drop = di = GetDropItems(); drop = di = GetDropItems();
@ -40,8 +40,8 @@ class ARandomSpawner : public AActor
{ {
if (di->Name != NAME_None) if (di->Name != NAME_None)
{ {
if (di->amount < 0) di->amount = 1; // default value is -1, we need a positive value. if (di->Amount < 0) di->Amount = 1; // default value is -1, we need a positive value.
n += di->amount; // this is how we can weight the list. n += di->Amount; // this is how we can weight the list.
di = di->Next; di = di->Next;
} }
} }
@ -54,7 +54,7 @@ class ARandomSpawner : public AActor
{ {
if (di->Name != NAME_None) if (di->Name != NAME_None)
{ {
n -= di->amount; n -= di->Amount;
if ((di->Next != NULL) && (n > -1)) di = di->Next; else n = -1; if ((di->Next != NULL) && (n > -1)) di = di->Next; else n = -1;
} }
} }
@ -64,7 +64,7 @@ class ARandomSpawner : public AActor
Spawn("Unknown", x, y, z, NO_REPLACE); // Show that there's a problem. Spawn("Unknown", x, y, z, NO_REPLACE); // Show that there's a problem.
Destroy(); return; Destroy(); return;
} }
else if (pr_randomspawn() <= di->probability) // prob 255 = always spawn, prob 0 = never spawn. else if (pr_randomspawn() <= di->Probability) // prob 255 = always spawn, prob 0 = almost never spawn.
{ {
// Handle replacement here so as to get the proper speed and flags for missiles // Handle replacement here so as to get the proper speed and flags for missiles
PClassActor *cls; PClassActor *cls;

View file

@ -13,7 +13,7 @@ public:
virtual void PlayPickupSound (AActor *toucher); virtual void PlayPickupSound (AActor *toucher);
int PieceValue; int PieceValue;
PClassActor *WeaponClass; PClassWeapon *WeaponClass;
TObjPtr<AWeapon> FullWeapon; TObjPtr<AWeapon> FullWeapon;
}; };

View file

@ -30,11 +30,29 @@ FString WeaponSection;
TArray<FString> KeyConfWeapons; TArray<FString> KeyConfWeapons;
FWeaponSlots *PlayingKeyConf; FWeaponSlots *PlayingKeyConf;
TArray<PClassActor *> Weapons_ntoh; TArray<PClassWeapon *> Weapons_ntoh;
TMap<PClassActor *, int> Weapons_hton; TMap<PClassWeapon *, int> Weapons_hton;
static int STACK_ARGS ntoh_cmp(const void *a, const void *b); static int STACK_ARGS ntoh_cmp(const void *a, const void *b);
IMPLEMENT_CLASS(PClassWeapon)
PClassWeapon::PClassWeapon()
{
SlotNumber = -1;
SlotPriority = FIXED_MAX;
}
void PClassWeapon::Derive(PClass *newclass)
{
assert(newclass->IsKindOf(RUNTIME_CLASS(PClassWeapon)));
Super::Derive(newclass);
PClassWeapon *newc = static_cast<PClassWeapon *>(newclass);
newc->SlotNumber = SlotNumber;
newc->SlotPriority = SlotPriority;
}
//=========================================================================== //===========================================================================
// //
// AWeapon :: Serialize // AWeapon :: Serialize
@ -357,7 +375,7 @@ bool AWeapon::AddExistingAmmo (AAmmo *ammo, int amount)
// //
//=========================================================================== //===========================================================================
AWeapon *AWeapon::AddWeapon (PClassActor *weapontype) AWeapon *AWeapon::AddWeapon (PClassWeapon *weapontype)
{ {
AWeapon *weap; AWeapon *weap;
@ -620,13 +638,13 @@ IMPLEMENT_CLASS(AWeaponGiver)
bool AWeaponGiver::TryPickup(AActor *&toucher) bool AWeaponGiver::TryPickup(AActor *&toucher)
{ {
FDropItem *di = GetDropItems(); DDropItem *di = GetDropItems();
AWeapon *weap; AWeapon *weap;
if (di != NULL) if (di != NULL)
{ {
PClassActor *ti = PClass::FindActor(di->Name); PClassWeapon *ti = dyn_cast<PClassWeapon>(PClass::FindClass(di->Name));
if (ti != NULL && ti->IsDescendantOf(RUNTIME_CLASS(AWeapon))) if (ti != NULL)
{ {
if (master == NULL) if (master == NULL)
{ {
@ -662,10 +680,10 @@ bool AWeaponGiver::TryPickup(AActor *&toucher)
bool FWeaponSlot::AddWeapon(const char *type) bool FWeaponSlot::AddWeapon(const char *type)
{ {
return AddWeapon (PClass::FindActor (type)); return AddWeapon(static_cast<PClassWeapon *>(PClass::FindClass(type)));
} }
bool FWeaponSlot::AddWeapon(PClassActor *type) bool FWeaponSlot::AddWeapon(PClassWeapon *type)
{ {
unsigned int i; unsigned int i;
@ -726,7 +744,7 @@ void FWeaponSlot :: AddWeaponList(const char *list, bool clear)
// //
//=========================================================================== //===========================================================================
int FWeaponSlot::LocateWeapon(PClassActor *type) int FWeaponSlot::LocateWeapon(PClassWeapon *type)
{ {
unsigned int i; unsigned int i;
@ -842,7 +860,7 @@ void FWeaponSlot::Sort()
for (i = 1; i < (int)Weapons.Size(); ++i) for (i = 1; i < (int)Weapons.Size(); ++i)
{ {
fixed_t pos = Weapons[i].Position; fixed_t pos = Weapons[i].Position;
PClassActor *type = Weapons[i].Type; PClassWeapon *type = Weapons[i].Type;
for (j = i - 1; j >= 0 && Weapons[j].Position > pos; --j) for (j = i - 1; j >= 0 && Weapons[j].Position > pos; --j)
{ {
Weapons[j + 1] = Weapons[j]; Weapons[j + 1] = Weapons[j];
@ -891,7 +909,7 @@ void FWeaponSlots::Clear()
// //
//=========================================================================== //===========================================================================
ESlotDef FWeaponSlots::AddDefaultWeapon (int slot, PClassActor *type) ESlotDef FWeaponSlots::AddDefaultWeapon (int slot, PClassWeapon *type)
{ {
int currSlot, index; int currSlot, index;
@ -916,7 +934,7 @@ ESlotDef FWeaponSlots::AddDefaultWeapon (int slot, PClassActor *type)
// //
//=========================================================================== //===========================================================================
bool FWeaponSlots::LocateWeapon (PClassActor *type, int *const slot, int *const index) bool FWeaponSlots::LocateWeapon (PClassWeapon *type, int *const slot, int *const index)
{ {
int i, j; int i, j;
@ -1014,7 +1032,7 @@ AWeapon *FWeaponSlots::PickNextWeapon(player_t *player)
slot = 0; slot = 0;
} }
} }
PClassActor *type = Slots[slot].GetWeapon(index); PClassWeapon *type = Slots[slot].GetWeapon(index);
AWeapon *weap = static_cast<AWeapon *>(player->mo->FindInventory(type)); AWeapon *weap = static_cast<AWeapon *>(player->mo->FindInventory(type));
if (weap != NULL && weap->CheckAmmo(AWeapon::EitherFire, false)) if (weap != NULL && weap->CheckAmmo(AWeapon::EitherFire, false))
{ {
@ -1069,7 +1087,7 @@ AWeapon *FWeaponSlots::PickPrevWeapon (player_t *player)
} }
index = Slots[slot].Size() - 1; index = Slots[slot].Size() - 1;
} }
PClassActor *type = Slots[slot].GetWeapon(index); PClassWeapon *type = Slots[slot].GetWeapon(index);
AWeapon *weap = static_cast<AWeapon *>(player->mo->FindInventory(type)); AWeapon *weap = static_cast<AWeapon *>(player->mo->FindInventory(type));
if (weap != NULL && weap->CheckAmmo(AWeapon::EitherFire, false)) if (weap != NULL && weap->CheckAmmo(AWeapon::EitherFire, false))
{ {
@ -1109,17 +1127,16 @@ void FWeaponSlots::AddExtraWeapons()
{ {
continue; continue;
} }
PClassActor *acls = static_cast<PClassActor *>(cls); PClassWeapon *acls = static_cast<PClassWeapon *>(cls);
if ((acls->GameFilter == GAME_Any || (acls->GameFilter & gameinfo.gametype)) && if ((acls->GameFilter == GAME_Any || (acls->GameFilter & gameinfo.gametype)) &&
acls->Replacement == NULL && // Replaced weapons don't get slotted. acls->Replacement == NULL && // Replaced weapons don't get slotted.
!LocateWeapon(acls, NULL, NULL) // Don't duplicate it if it's already present. !LocateWeapon(acls, NULL, NULL) // Don't duplicate it if it's already present.
) )
{ {
int slot = acls->Meta.GetMetaInt(AWMETA_SlotNumber, -1); int slot = acls->SlotNumber;
if ((unsigned)slot < NUM_WEAPON_SLOTS) if ((unsigned)slot < NUM_WEAPON_SLOTS)
{ {
fixed_t position = acls->Meta.GetMetaFixed(AWMETA_SlotPriority, INT_MAX); FWeaponSlot::WeaponInfo info = { acls, acls->SlotPriority };
FWeaponSlot::WeaponInfo info = { acls, position };
Slots[slot].Weapons.Push(info); Slots[slot].Weapons.Push(info);
} }
} }
@ -1156,7 +1173,7 @@ void FWeaponSlots::SetFromGameInfo()
{ {
for (unsigned j = 0; j < gameinfo.DefaultWeaponSlots[i].Size(); i++) for (unsigned j = 0; j < gameinfo.DefaultWeaponSlots[i].Size(); i++)
{ {
PClassActor *cls = PClass::FindActor(gameinfo.DefaultWeaponSlots[i][j]); PClassWeapon *cls = dyn_cast<PClassWeapon>(PClass::FindClass(gameinfo.DefaultWeaponSlots[i][j]));
if (cls == NULL) if (cls == NULL)
{ {
Printf("Unknown weapon class '%s' found in default weapon slot assignments\n", Printf("Unknown weapon class '%s' found in default weapon slot assignments\n",
@ -1181,7 +1198,7 @@ void FWeaponSlots::SetFromGameInfo()
// //
//=========================================================================== //===========================================================================
void FWeaponSlots::StandardSetup(PClassActor *type) void FWeaponSlots::StandardSetup(PClassPlayerPawn *type)
{ {
SetFromPlayer(type); SetFromPlayer(type);
AddExtraWeapons(); AddExtraWeapons();
@ -1266,15 +1283,14 @@ void FWeaponSlots::SendDifferences(const FWeaponSlots &other)
// //
//=========================================================================== //===========================================================================
void FWeaponSlots::SetFromPlayer(PClassActor *type) void FWeaponSlots::SetFromPlayer(PClassPlayerPawn *type)
{ {
Clear(); Clear();
for (int i = 0; i < NUM_WEAPON_SLOTS; ++i) for (int i = 0; i < NUM_WEAPON_SLOTS; ++i)
{ {
const char *str = type->Meta.GetMetaString(APMETA_Slot0 + i); if (!type->Slot[i].IsEmpty())
if (str != NULL)
{ {
Slots[i].AddWeaponList(str, false); Slots[i].AddWeaponList(type->Slot[i], false);
} }
} }
} }
@ -1385,7 +1401,7 @@ CCMD (setslot)
Net_WriteByte(argv.argc()-2); Net_WriteByte(argv.argc()-2);
for (int i = 2; i < argv.argc(); i++) for (int i = 2; i < argv.argc(); i++)
{ {
Net_WriteWeapon(PClass::FindActor(argv[i])); Net_WriteWeapon(dyn_cast<PClassWeapon>(PClass::FindClass(argv[i])));
} }
} }
} }
@ -1396,7 +1412,7 @@ CCMD (setslot)
// //
//=========================================================================== //===========================================================================
void FWeaponSlots::AddSlot(int slot, PClassActor *type, bool feedback) void FWeaponSlots::AddSlot(int slot, PClassWeapon *type, bool feedback)
{ {
if (type != NULL && !Slots[slot].AddWeapon(type) && feedback) if (type != NULL && !Slots[slot].AddWeapon(type) && feedback)
{ {
@ -1414,19 +1430,26 @@ CCMD (addslot)
return; return;
} }
PClassWeapon *type= dyn_cast<PClassWeapon>(PClass::FindClass(argv[2]));
if (type == NULL)
{
Printf("%s is not a weapon\n", argv[2]);
return;
}
if (ParsingKeyConf) if (ParsingKeyConf)
{ {
KeyConfWeapons.Push(argv.args()); KeyConfWeapons.Push(argv.args());
} }
else if (PlayingKeyConf != NULL) else if (PlayingKeyConf != NULL)
{ {
PlayingKeyConf->AddSlot(int(slot), PClass::FindActor(argv[2]), false); PlayingKeyConf->AddSlot(int(slot), type, false);
} }
else else
{ {
Net_WriteByte(DEM_ADDSLOT); Net_WriteByte(DEM_ADDSLOT);
Net_WriteByte(slot); Net_WriteByte(slot);
Net_WriteWeapon(PClass::FindActor(argv[2])); Net_WriteWeapon(type);
} }
} }
@ -1449,7 +1472,7 @@ CCMD (weaponsection)
// CCMD addslotdefault // CCMD addslotdefault
// //
//=========================================================================== //===========================================================================
void FWeaponSlots::AddSlotDefault(int slot, PClassActor *type, bool feedback) void FWeaponSlots::AddSlotDefault(int slot, PClassWeapon *type, bool feedback)
{ {
if (type != NULL && type->IsDescendantOf(RUNTIME_CLASS(AWeapon))) if (type != NULL && type->IsDescendantOf(RUNTIME_CLASS(AWeapon)))
{ {
@ -1474,7 +1497,7 @@ void FWeaponSlots::AddSlotDefault(int slot, PClassActor *type, bool feedback)
CCMD (addslotdefault) CCMD (addslotdefault)
{ {
PClassActor *type; PClassWeapon *type;
unsigned int slot; unsigned int slot;
if (argv.argc() != 3 || (slot = atoi (argv[1])) >= NUM_WEAPON_SLOTS) if (argv.argc() != 3 || (slot = atoi (argv[1])) >= NUM_WEAPON_SLOTS)
@ -1483,8 +1506,8 @@ CCMD (addslotdefault)
return; return;
} }
type = PClass::FindActor(argv[2]); type = dyn_cast<PClassWeapon>(PClass::FindClass(argv[2]));
if (type == NULL || !type->IsDescendantOf (RUNTIME_CLASS(AWeapon))) if (type == NULL)
{ {
Printf ("%s is not a weapon\n", argv[2]); Printf ("%s is not a weapon\n", argv[2]);
return; return;
@ -1496,13 +1519,13 @@ CCMD (addslotdefault)
} }
else if (PlayingKeyConf != NULL) else if (PlayingKeyConf != NULL)
{ {
PlayingKeyConf->AddSlotDefault(int(slot), PClass::FindActor(argv[2]), false); PlayingKeyConf->AddSlotDefault(int(slot), type, false);
} }
else else
{ {
Net_WriteByte(DEM_ADDSLOTDEFAULT); Net_WriteByte(DEM_ADDSLOTDEFAULT);
Net_WriteByte(slot); Net_WriteByte(slot);
Net_WriteWeapon(PClass::FindActor(argv[2])); Net_WriteWeapon(type);
} }
} }
@ -1539,7 +1562,7 @@ void P_PlaybackKeyConfWeapons(FWeaponSlots *slots)
void P_SetupWeapons_ntohton() void P_SetupWeapons_ntohton()
{ {
unsigned int i; unsigned int i;
PClassActor *cls; PClassWeapon *cls;
Weapons_ntoh.Clear(); Weapons_ntoh.Clear();
Weapons_hton.Clear(); Weapons_hton.Clear();
@ -1552,7 +1575,7 @@ void P_SetupWeapons_ntohton()
if (cls->IsDescendantOf(RUNTIME_CLASS(AWeapon))) if (cls->IsDescendantOf(RUNTIME_CLASS(AWeapon)))
{ {
Weapons_ntoh.Push(static_cast<PClassActor *>(cls)); Weapons_ntoh.Push(static_cast<PClassWeapon *>(cls));
} }
} }
qsort(&Weapons_ntoh[1], Weapons_ntoh.Size() - 1, sizeof(Weapons_ntoh[0]), ntoh_cmp); qsort(&Weapons_ntoh[1], Weapons_ntoh.Size() - 1, sizeof(Weapons_ntoh[0]), ntoh_cmp);
@ -1578,8 +1601,8 @@ void P_SetupWeapons_ntohton()
static int STACK_ARGS ntoh_cmp(const void *a, const void *b) static int STACK_ARGS ntoh_cmp(const void *a, const void *b)
{ {
PClassActor *c1 = *(PClassActor **)a; PClassWeapon *c1 = *(PClassWeapon **)a;
PClassActor *c2 = *(PClassActor **)b; PClassWeapon *c2 = *(PClassWeapon **)b;
int g1 = c1->GameFilter == GAME_Any ? 1 : (c1->GameFilter & gameinfo.gametype) ? 0 : 2; int g1 = c1->GameFilter == GAME_Any ? 1 : (c1->GameFilter & gameinfo.gametype) ? 0 : 2;
int g2 = c2->GameFilter == GAME_Any ? 1 : (c2->GameFilter & gameinfo.gametype) ? 0 : 2; int g2 = c2->GameFilter == GAME_Any ? 1 : (c2->GameFilter & gameinfo.gametype) ? 0 : 2;
if (g1 != g2) if (g1 != g2)
@ -1619,7 +1642,7 @@ void P_WriteDemoWeaponsChunk(BYTE **demo)
void P_ReadDemoWeaponsChunk(BYTE **demo) void P_ReadDemoWeaponsChunk(BYTE **demo)
{ {
int count, i; int count, i;
PClassActor *type; PClassWeapon *type;
const char *s; const char *s;
count = ReadWord(demo); count = ReadWord(demo);
@ -1632,7 +1655,7 @@ void P_ReadDemoWeaponsChunk(BYTE **demo)
for (i = 1; i < count; ++i) for (i = 1; i < count; ++i)
{ {
s = ReadStringConst(demo); s = ReadStringConst(demo);
type = PClass::FindActor(s); type = dyn_cast<PClassWeapon>(PClass::FindClass(s));
// If a demo was recorded with a weapon that is no longer present, // If a demo was recorded with a weapon that is no longer present,
// should we report it? // should we report it?
Weapons_ntoh[i] = type; Weapons_ntoh[i] = type;
@ -1649,7 +1672,7 @@ void P_ReadDemoWeaponsChunk(BYTE **demo)
// //
//=========================================================================== //===========================================================================
void Net_WriteWeapon(PClassActor *type) void Net_WriteWeapon(PClassWeapon *type)
{ {
int index, *index_p; int index, *index_p;
@ -1681,7 +1704,7 @@ void Net_WriteWeapon(PClassActor *type)
// //
//=========================================================================== //===========================================================================
PClassActor *Net_ReadWeapon(BYTE **stream) PClassWeapon *Net_ReadWeapon(BYTE **stream)
{ {
int index; int index;

View file

@ -2176,7 +2176,7 @@ class CommandPlayerClass : public SBarInfoCommandFlowControl
bool foundClass = false; bool foundClass = false;
for(unsigned int c = 0;c < PlayerClasses.Size();c++) for(unsigned int c = 0;c < PlayerClasses.Size();c++)
{ {
if(stricmp(sc.String, PlayerClasses[c].Type->Meta.GetMetaString(APMETA_DisplayName)) == 0) if(stricmp(sc.String, PlayerClasses[c].Type->DisplayName) == 0)
{ {
foundClass = true; foundClass = true;
classes.Push(PlayerClasses[c].Type->ClassIndex); classes.Push(PlayerClasses[c].Type->ClassIndex);

View file

@ -104,16 +104,14 @@ static int statspace;
void AM_GetPosition(fixed_t & x, fixed_t & y); void AM_GetPosition(fixed_t & x, fixed_t & y);
FTextureID GetHUDIcon(const PClass *cls) FTextureID GetHUDIcon(PClassInventory *cls)
{ {
FTextureID tex; return cls->AltHUDIcon;
tex.texnum = cls->Meta.GetMetaInt(HUMETA_AltIcon, 0);
return tex;
} }
void SetHUDIcon(PClass *cls, FTextureID tex) void SetHUDIcon(PClassInventory *cls, FTextureID tex)
{ {
cls->Meta.SetMetaInt(HUMETA_AltIcon, tex.GetIndex()); cls->AltHUDIcon = tex;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -450,14 +448,14 @@ static int DrawKeys(player_t * CPlayer, int x, int y)
// Drawing Ammo // Drawing Ammo
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
static TArray<PClassActor *> orderedammos; static TArray<PClassAmmo *> orderedammos;
static void AddAmmoToList(AWeapon * weapdef) static void AddAmmoToList(AWeapon * weapdef)
{ {
for(int i=0; i<2;i++) for(int i=0; i<2;i++)
{ {
PClassActor * ti = i==0? weapdef->AmmoType1 : weapdef->AmmoType2; PClassAmmo * ti = i==0? weapdef->AmmoType1 : weapdef->AmmoType2;
if (ti) if (ti)
{ {
AAmmo * ammodef=(AAmmo*)GetDefaultByType(ti); AAmmo * ammodef=(AAmmo*)GetDefaultByType(ti);
@ -516,7 +514,7 @@ static int DrawAmmo(player_t *CPlayer, int x, int y)
for(i=orderedammos.Size()-1;i>=0;i--) for(i=orderedammos.Size()-1;i>=0;i--)
{ {
PClassActor * type = orderedammos[i]; PClassAmmo * type = orderedammos[i];
AAmmo * ammoitem = (AAmmo*)CPlayer->mo->FindInventory(type); AAmmo * ammoitem = (AAmmo*)CPlayer->mo->FindInventory(type);
AAmmo * inv = ammoitem? ammoitem : (AAmmo*)GetDefaultByType(orderedammos[i]); AAmmo * inv = ammoitem? ammoitem : (AAmmo*)GetDefaultByType(orderedammos[i]);
@ -605,16 +603,16 @@ static void DrawOneWeapon(player_t * CPlayer, int x, int & y, AWeapon * weapon)
} }
static void DrawWeapons(player_t * CPlayer, int x, int y) static void DrawWeapons(player_t *CPlayer, int x, int y)
{ {
int k,j; int k,j;
AInventory * inv; AInventory *inv;
// First draw all weapons in the inventory that are not assigned to a weapon slot // First draw all weapons in the inventory that are not assigned to a weapon slot
for(inv=CPlayer->mo->Inventory;inv;inv=inv->Inventory) for(inv = CPlayer->mo->Inventory; inv; inv = inv->Inventory)
{ {
if (inv->IsKindOf(RUNTIME_CLASS(AWeapon)) && if (inv->IsKindOf(RUNTIME_CLASS(AWeapon)) &&
!CPlayer->weapons.LocateWeapon(RUNTIME_TYPE(inv), NULL, NULL)) !CPlayer->weapons.LocateWeapon(static_cast<AWeapon*>(inv)->GetClass(), NULL, NULL))
{ {
DrawOneWeapon(CPlayer, x, y, static_cast<AWeapon*>(inv)); DrawOneWeapon(CPlayer, x, y, static_cast<AWeapon*>(inv));
} }
@ -931,7 +929,7 @@ void HUD_InitHud()
} }
else else
{ {
const PClass * ti = PClass::FindClass(sc.String); PClass *ti = PClass::FindClass(sc.String);
if (!ti) if (!ti)
{ {
Printf("Unknown item class '%s' in ALTHUDCF\n", sc.String); Printf("Unknown item class '%s' in ALTHUDCF\n", sc.String);
@ -950,9 +948,8 @@ void HUD_InitHud()
} }
else tex.SetInvalid(); else tex.SetInvalid();
if (ti) SetHUDIcon(const_cast<PClass*>(ti), tex); if (ti) SetHUDIcon(static_cast<PClassInventory*>(ti), tex);
} }
} }
} }
} }

View file

@ -29,18 +29,18 @@ DEFINE_ACTION_FUNCTION(AActor, A_CrusaderChoose)
{ {
A_FaceTarget (self); A_FaceTarget (self);
self->angle -= ANGLE_180/16; self->angle -= ANGLE_180/16;
P_SpawnMissileZAimed (self, self->z + 40*FRACUNIT, self->target, PClass::FindClass("FastFlameMissile")); P_SpawnMissileZAimed (self, self->z + 40*FRACUNIT, self->target, PClass::FindActor("FastFlameMissile"));
} }
else else
{ {
if (P_CheckMissileRange (self)) if (P_CheckMissileRange (self))
{ {
A_FaceTarget (self); A_FaceTarget (self);
P_SpawnMissileZAimed (self, self->z + 56*FRACUNIT, self->target, PClass::FindClass("CrusaderMissile")); P_SpawnMissileZAimed (self, self->z + 56*FRACUNIT, self->target, PClass::FindActor("CrusaderMissile"));
self->angle -= ANGLE_45/32; self->angle -= ANGLE_45/32;
P_SpawnMissileZAimed (self, self->z + 40*FRACUNIT, self->target, PClass::FindClass("CrusaderMissile")); P_SpawnMissileZAimed (self, self->z + 40*FRACUNIT, self->target, PClass::FindActor("CrusaderMissile"));
self->angle += ANGLE_45/16; self->angle += ANGLE_45/16;
P_SpawnMissileZAimed (self, self->z + 40*FRACUNIT, self->target, PClass::FindClass("CrusaderMissile")); P_SpawnMissileZAimed (self, self->z + 40*FRACUNIT, self->target, PClass::FindActor("CrusaderMissile"));
self->angle -= ANGLE_45/16; self->angle -= ANGLE_45/16;
self->reactiontime += 15; self->reactiontime += 15;
} }
@ -54,7 +54,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CrusaderSweepLeft)
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
self->angle += ANGLE_90/16; self->angle += ANGLE_90/16;
AActor *misl = P_SpawnMissileZAimed (self, self->z + 48*FRACUNIT, self->target, PClass::FindClass("FastFlameMissile")); AActor *misl = P_SpawnMissileZAimed (self, self->z + 48*FRACUNIT, self->target, PClass::FindActor("FastFlameMissile"));
if (misl != NULL) if (misl != NULL)
{ {
misl->velz += FRACUNIT; misl->velz += FRACUNIT;
@ -67,7 +67,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CrusaderSweepRight)
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
self->angle -= ANGLE_90/16; self->angle -= ANGLE_90/16;
AActor *misl = P_SpawnMissileZAimed (self, self->z + 48*FRACUNIT, self->target, PClass::FindClass("FastFlameMissile")); AActor *misl = P_SpawnMissileZAimed (self, self->z + 48*FRACUNIT, self->target, PClass::FindActor("FastFlameMissile"));
if (misl != NULL) if (misl != NULL)
{ {
misl->velz += FRACUNIT; misl->velz += FRACUNIT;

View file

@ -63,13 +63,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_InquisitorAttack)
self->z += 32*FRACBITS; self->z += 32*FRACBITS;
self->angle -= ANGLE_45/32; self->angle -= ANGLE_45/32;
proj = P_SpawnMissileZAimed (self, self->z, self->target, PClass::FindClass("InquisitorShot")); proj = P_SpawnMissileZAimed (self, self->z, self->target, PClass::FindActor("InquisitorShot"));
if (proj != NULL) if (proj != NULL)
{ {
proj->velz += 9*FRACUNIT; proj->velz += 9*FRACUNIT;
} }
self->angle += ANGLE_45/16; self->angle += ANGLE_45/16;
proj = P_SpawnMissileZAimed (self, self->z, self->target, PClass::FindClass("InquisitorShot")); proj = P_SpawnMissileZAimed (self, self->z, self->target, PClass::FindActor("InquisitorShot"));
if (proj != NULL) if (proj != NULL)
{ {
proj->velz += 16*FRACUNIT; proj->velz += 16*FRACUNIT;

View file

@ -53,7 +53,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SentinelAttack)
return 0; return 0;
} }
missile = P_SpawnMissileZAimed (self, self->z + 32*FRACUNIT, self->target, PClass::FindClass("SentinelFX2")); missile = P_SpawnMissileZAimed (self, self->z + 32*FRACUNIT, self->target, PClass::FindActor("SentinelFX2"));
if (missile != NULL && (missile->velx | missile->vely) != 0) if (missile != NULL && (missile->velx | missile->vely) != 0)
{ {

View file

@ -341,7 +341,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMiniMissile)
savedangle = self->angle; savedangle = self->angle;
self->angle += pr_minimissile.Random2() << (19 - player->accuracy * 5 / 100); self->angle += pr_minimissile.Random2() << (19 - player->accuracy * 5 / 100);
player->mo->PlayAttacking2 (); player->mo->PlayAttacking2 ();
P_SpawnPlayerMissile (self, PClass::FindClass("MiniMissile")); P_SpawnPlayerMissile (self, PClass::FindActor("MiniMissile"));
self->angle = savedangle; self->angle = savedangle;
return 0; return 0;
} }
@ -359,7 +359,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RocketInFlight)
AActor *trail; AActor *trail;
S_Sound (self, CHAN_VOICE, "misc/missileinflight", 1, ATTN_NORM); S_Sound (self, CHAN_VOICE, "misc/missileinflight", 1, ATTN_NORM);
P_SpawnPuff (self, PClass::FindClass("MiniMissilePuff"), self->x, self->y, self->z, self->angle - ANGLE_180, 2, PF_HITTHING); P_SpawnPuff (self, PClass::FindActor("MiniMissilePuff"), self->x, self->y, self->z, self->angle - ANGLE_180, 2, PF_HITTHING);
trail = Spawn("RocketTrail", self->x - self->velx, self->y - self->vely, self->z, ALLOW_REPLACE); trail = Spawn("RocketTrail", self->x - self->velx, self->y - self->vely, self->z, ALLOW_REPLACE);
if (trail != NULL) if (trail != NULL)
{ {
@ -409,7 +409,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireFlamer)
} }
self->angle += pr_flamethrower.Random2() << 18; self->angle += pr_flamethrower.Random2() << 18;
self = P_SpawnPlayerMissile (self, PClass::FindClass("FlameMissile")); self = P_SpawnPlayerMissile (self, PClass::FindActor("FlameMissile"));
if (self != NULL) if (self != NULL)
{ {
self->velz += 5*FRACUNIT; self->velz += 5*FRACUNIT;
@ -508,7 +508,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMauler2)
} }
self->player->mo->PlayAttacking2 (); self->player->mo->PlayAttacking2 ();
} }
P_SpawnPlayerMissile (self, PClass::FindClass("MaulerTorpedo")); P_SpawnPlayerMissile (self, PClass::FindActor("MaulerTorpedo"));
P_DamageMobj (self, self, NULL, 20, self->DamageType); P_DamageMobj (self, self, NULL, 20, self->DamageType);
P_ThrustMobj (self, self->angle + ANGLE_180, 0x7D000); P_ThrustMobj (self, self->angle + ANGLE_180, 0x7D000);
return 0; return 0;
@ -1012,7 +1012,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSigil2)
P_DamageMobj (self, self, NULL, 2*4, 0, DMG_NO_ARMOR); P_DamageMobj (self, self, NULL, 2*4, 0, DMG_NO_ARMOR);
S_Sound (self, CHAN_WEAPON, "weapons/sigilcharge", 1, ATTN_NORM); S_Sound (self, CHAN_WEAPON, "weapons/sigilcharge", 1, ATTN_NORM);
P_SpawnPlayerMissile (self, PClass::FindClass("SpectralLightningH1")); P_SpawnPlayerMissile (self, PClass::FindActor("SpectralLightningH1"));
return 0; return 0;
} }
@ -1073,7 +1073,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSigil4)
P_BulletSlope (self, &linetarget); P_BulletSlope (self, &linetarget);
if (linetarget != NULL) if (linetarget != NULL)
{ {
spot = P_SpawnPlayerMissile (self, 0,0,0, PClass::FindClass("SpectralLightningBigV1"), self->angle, &linetarget); spot = P_SpawnPlayerMissile (self, 0,0,0, PClass::FindActor("SpectralLightningBigV1"), self->angle, &linetarget);
if (spot != NULL) if (spot != NULL)
{ {
spot->tracer = linetarget; spot->tracer = linetarget;
@ -1081,7 +1081,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSigil4)
} }
else else
{ {
spot = P_SpawnPlayerMissile (self, PClass::FindClass("SpectralLightningBigV1")); spot = P_SpawnPlayerMissile (self, PClass::FindActor("SpectralLightningBigV1"));
if (spot != NULL) if (spot != NULL)
{ {
spot->velx += FixedMul (spot->Speed, finecosine[self->angle >> ANGLETOFINESHIFT]); spot->velx += FixedMul (spot->Speed, finecosine[self->angle >> ANGLETOFINESHIFT]);
@ -1109,7 +1109,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSigil5)
P_DamageMobj (self, self, NULL, 5*4, 0, DMG_NO_ARMOR); P_DamageMobj (self, self, NULL, 5*4, 0, DMG_NO_ARMOR);
S_Sound (self, CHAN_WEAPON, "weapons/sigilcharge", 1, ATTN_NORM); S_Sound (self, CHAN_WEAPON, "weapons/sigilcharge", 1, ATTN_NORM);
P_SpawnPlayerMissile (self, PClass::FindClass("SpectralLightningBigBall1")); P_SpawnPlayerMissile (self, PClass::FindActor("SpectralLightningBigBall1"));
return 0; return 0;
} }

View file

@ -107,7 +107,9 @@ int GetSpriteIndex(const char * spritename)
return (lastindex = (int)sprites.Push (temp)); return (lastindex = (int)sprites.Push (temp));
} }
IMPLEMENT_CLASS(PClassActor) IMPLEMENT_POINTY_CLASS(PClassActor)
DECLARE_POINTER(DropItems)
END_POINTERS
//========================================================================== //==========================================================================
// //
@ -173,6 +175,28 @@ PClassActor::PClassActor()
StateList = NULL; StateList = NULL;
DamageFactors = NULL; DamageFactors = NULL;
PainChances = NULL; PainChances = NULL;
Obituary = Obituary;
HitObituary = HitObituary;
DeathHeight = -1;
BurnHeight = -1;
GibHealth = INT_MIN;
WoundHealth = 6;
PoisonDamage = 0;
FastSpeed = FIXED_MIN;
RDFactor = FRACUNIT;
CameraHeight = FIXED_MIN;
BloodType = NAME_Blood;
BloodType2 = NAME_BloodSplatter;
BloodType3 = NAME_AxeBlood;
DropItems = NULL;
DontHurtShooter = false;
ExplosionDamage = 128;
ExplosionRadius = -1;
MissileHeight = 32*FRACUNIT;
MeleeDamage = 0;
} }
//========================================================================== //==========================================================================
@ -202,6 +226,45 @@ PClassActor::~PClassActor()
} }
} }
//==========================================================================
//
// PClassActor :: Derive
//
//==========================================================================
void PClassActor::Derive(PClass *newclass)
{
assert(newclass->IsKindOf(RUNTIME_CLASS(PClassActor)));
Super::Derive(newclass);
PClassActor *newa = static_cast<PClassActor *>(newclass);
newa->Obituary = Obituary;
newa->HitObituary = HitObituary;
newa->DeathHeight = DeathHeight;
newa->BurnHeight = BurnHeight;
newa->BloodColor = BloodColor;
newa->GibHealth = GibHealth;
newa->WoundHealth = WoundHealth;
newa->PoisonDamage = PoisonDamage;
newa->FastSpeed = FastSpeed;
newa->RDFactor = RDFactor;
newa->CameraHeight = CameraHeight;
newa->HowlSound = HowlSound;
newa->BloodType = BloodType;
newa->BloodType2 = BloodType2;
newa->BloodType3 = BloodType3;
newa->DropItems = DropItems;
newa->DontHurtShooter = DontHurtShooter;
newa->ExplosionRadius = ExplosionRadius;
newa->ExplosionDamage = ExplosionDamage;
newa->MeleeDamage = MeleeDamage;
newa->MeleeSound = MeleeSound;
newa->MissileName = MissileName;
newa->MissileHeight = MissileHeight;
}
//========================================================================== //==========================================================================
// //
// PClassActor :: PropagateMark // PClassActor :: PropagateMark

View file

@ -44,6 +44,7 @@
#include "dobject.h" #include "dobject.h"
#include "doomdef.h" #include "doomdef.h"
#include "vm.h" #include "vm.h"
#include "s_sound.h"
const BYTE SF_FULLBRIGHT = 0x40; const BYTE SF_FULLBRIGHT = 0x40;
@ -124,10 +125,14 @@ FArchive &operator<< (FArchive &arc, FState *&state);
typedef TMap<FName, fixed_t> DmgFactors; typedef TMap<FName, fixed_t> DmgFactors;
typedef TMap<FName, BYTE> PainChanceList; typedef TMap<FName, BYTE> PainChanceList;
class DDropItem;
class PClassActor : public PClass class PClassActor : public PClass
{ {
DECLARE_CLASS(PClassActor, PClass); DECLARE_CLASS(PClassActor, PClass);
HAS_OBJECT_POINTERS;
protected:
virtual void Derive(PClass *newclass);
public: public:
static void StaticInit (); static void StaticInit ();
static void StaticSetActorNums (); static void StaticSetActorNums ();
@ -163,6 +168,32 @@ public:
FStateLabels *StateList; FStateLabels *StateList;
DmgFactors *DamageFactors; DmgFactors *DamageFactors;
PainChanceList *PainChances; PainChanceList *PainChances;
FString Obituary; // Player was killed by this actor
FString HitObituary; // Player was killed by this actor in melee
fixed_t DeathHeight; // Height on normal death
fixed_t BurnHeight; // Height on burning death
PalEntry BloodColor; // Colorized blood
int GibHealth; // Negative health below which this monster dies an extreme death
int WoundHealth; // Health needed to enter wound state
int PoisonDamage; // Amount of poison damage
fixed_t FastSpeed; // Speed in fast mode
fixed_t RDFactor; // Radius damage factor
fixed_t CameraHeight; // Height of camera when used as such
FSoundID HowlSound; // Sound being played when electrocuted or poisoned
FName BloodType; // Blood replacement type
FName BloodType2; // Bloopsplatter replacement type
FName BloodType3; // AxeBlood replacement type
DDropItem *DropItems;
// Old Decorate compatibility stuff
bool DontHurtShooter;
int ExplosionRadius;
int ExplosionDamage;
int MeleeDamage;
FSoundID MeleeSound;
FName MissileName;
fixed_t MissileHeight;
}; };
inline PClassActor *PClass::FindActor(FName name) inline PClassActor *PClass::FindActor(FName name)

View file

@ -144,7 +144,7 @@ void cht_DoCheat (player_t *player, int cheat)
break; break;
case CHT_MORPH: case CHT_MORPH:
msg = cht_Morph (player, PClass::FindClass (gameinfo.gametype == GAME_Heretic ? NAME_ChickenPlayer : NAME_PigPlayer), true); msg = cht_Morph (player, static_cast<PClassPlayerPawn *>(PClass::FindClass (gameinfo.gametype == GAME_Heretic ? NAME_ChickenPlayer : NAME_PigPlayer)), true);
break; break;
case CHT_NOTARGET: case CHT_NOTARGET:
@ -521,13 +521,13 @@ void cht_DoCheat (player_t *player, int cheat)
Printf ("%s is a cheater: %s\n", player->userinfo.netname, msg); Printf ("%s is a cheater: %s\n", player->userinfo.netname, msg);
} }
const char *cht_Morph (player_t *player, const PClass *morphclass, bool quickundo) const char *cht_Morph (player_t *player, PClassPlayerPawn *morphclass, bool quickundo)
{ {
if (player->mo == NULL) if (player->mo == NULL)
{ {
return ""; return "";
} }
PClass *oldclass = player->mo->GetClass(); PClassPlayerPawn *oldclass = player->mo->GetClass();
// Set the standard morph style for the current game // Set the standard morph style for the current game
int style = MORPH_UNDOBYTOMEOFPOWER; int style = MORPH_UNDOBYTOMEOFPOWER;
@ -750,7 +750,7 @@ void cht_Give (player_t *player, const char *name, int amount)
// is in a weapon slot. // is in a weapon slot.
if (static_cast<PClassActor *>(type)->GameFilter == GAME_Any || if (static_cast<PClassActor *>(type)->GameFilter == GAME_Any ||
(static_cast<PClassActor *>(type)->GameFilter & gameinfo.gametype) || (static_cast<PClassActor *>(type)->GameFilter & gameinfo.gametype) ||
player->weapons.LocateWeapon(static_cast<PClassActor *>(type), NULL, NULL)) player->weapons.LocateWeapon(static_cast<PClassWeapon *>(type), NULL, NULL))
{ {
AWeapon *def = (AWeapon*)GetDefaultByType (type); AWeapon *def = (AWeapon*)GetDefaultByType (type);
if (!(def->WeaponFlags & WIF_CHEATNOTWEAPON)) if (!(def->WeaponFlags & WIF_CHEATNOTWEAPON))

View file

@ -29,11 +29,12 @@
// [RH] Functions that actually perform the cheating // [RH] Functions that actually perform the cheating
class player_t; class player_t;
class PClass; class PClassPlayerPawn;
void cht_DoCheat (player_t *player, int cheat); void cht_DoCheat (player_t *player, int cheat);
void cht_Give (player_t *player, const char *item, int amount=1); void cht_Give (player_t *player, const char *item, int amount=1);
void cht_Take (player_t *player, const char *item, int amount=1); void cht_Take (player_t *player, const char *item, int amount=1);
void cht_Suicide (player_t *player); void cht_Suicide (player_t *player);
const char *cht_Morph (player_t *player, const PClass *morphclass, bool quickundo); const char *cht_Morph (player_t *player, PClassPlayerPawn *morphclass, bool quickundo);
#endif #endif

View file

@ -1883,7 +1883,7 @@ static void SCClass (int option)
if (option == 3) if (option == 3)
playerclass = "Random"; playerclass = "Random";
else else
playerclass = PlayerClasses[option].Type->Meta.GetMetaString (APMETA_DisplayName); playerclass = PlayerClasses[option].Type->DisplayName;
if (EpiDef.numitems > 1) if (EpiDef.numitems > 1)
{ {
@ -2299,7 +2299,7 @@ static void M_PlayerSetupDrawer ()
x = SmallFont->StringWidth ("Class") + 8 + PSetupDef.x; x = SmallFont->StringWidth ("Class") + 8 + PSetupDef.x;
screen->DrawText (SmallFont, label, PSetupDef.x, PSetupDef.y + LINEHEIGHT*5+yo, "Class", DTA_Clean, true, TAG_DONE); screen->DrawText (SmallFont, label, PSetupDef.x, PSetupDef.y + LINEHEIGHT*5+yo, "Class", DTA_Clean, true, TAG_DONE);
screen->DrawText (SmallFont, value, x, PSetupDef.y + LINEHEIGHT*5+yo, screen->DrawText (SmallFont, value, x, PSetupDef.y + LINEHEIGHT*5+yo,
pclass == -1 ? "Random" : PlayerClasses[pclass].Type->Meta.GetMetaString (APMETA_DisplayName), pclass == -1 ? "Random" : PlayerClasses[pclass].Type->DisplayName,
DTA_Clean, true, TAG_DONE); DTA_Clean, true, TAG_DONE);
// Draw skin setting // Draw skin setting
@ -2567,8 +2567,7 @@ static void M_ChangeClass (int choice)
else else
type = (type < (int)PlayerClasses.Size () - 1) ? type + 1 : -1; type = (type < (int)PlayerClasses.Size () - 1) ? type + 1 : -1;
cvar_set ("playerclass", type < 0 ? "Random" : cvar_set ("playerclass", type < 0 ? "Random" : PlayerClasses[type].Type->DisplayName);
PlayerClasses[type].Type->Meta.GetMetaString (APMETA_DisplayName));
} }
static void M_ChangeSkin (int choice) static void M_ChangeSkin (int choice)
@ -3964,8 +3963,7 @@ void M_Init (void)
{ {
if (!(PlayerClasses[i].Flags & PCF_NOMENU)) if (!(PlayerClasses[i].Flags & PCF_NOMENU))
{ {
ClassMenuItems[n].name = ClassMenuItems[n].name = PlayerClasses[i].Type->DisplayName;
PlayerClasses[i].Type->Meta.GetMetaString (APMETA_DisplayName);
n++; n++;
} }
} }
@ -3979,8 +3977,7 @@ void M_Init (void)
{ {
if (n == 0) if (n == 0)
{ {
ClassMenuItems[0].name = ClassMenuItems[0].name = PlayerClasses[0].Type->DisplayName;
PlayerClasses[0].Type->Meta.GetMetaString (APMETA_DisplayName);
} }
ClassMenuDef.numitems = 1; ClassMenuDef.numitems = 1;
} }

View file

@ -3109,7 +3109,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
} }
else else
{ {
return actor->GetClass()->Meta.GetMetaFixed(AMETA_CameraHeight, actor->height/2); return actor->GetCameraHeight();
} }
} }
else return 0; else return 0;
@ -6358,7 +6358,7 @@ int DLevelScript::RunScript ()
{ {
int tag = STACK(7); int tag = STACK(7);
FName playerclass_name = FBehavior::StaticLookupString(STACK(6)); FName playerclass_name = FBehavior::StaticLookupString(STACK(6));
const PClass *playerclass = PClass::FindClass (playerclass_name); PClassPlayerPawn *playerclass = dyn_cast<PClassPlayerPawn>(PClass::FindClass (playerclass_name));
FName monsterclass_name = FBehavior::StaticLookupString(STACK(5)); FName monsterclass_name = FBehavior::StaticLookupString(STACK(5));
const PClass *monsterclass = PClass::FindClass (monsterclass_name); const PClass *monsterclass = PClass::FindClass (monsterclass_name);
int duration = STACK(4); int duration = STACK(4);

View file

@ -2877,8 +2877,13 @@ void ModifyDropAmount(AInventory *inv, int dropamount)
else if (inv->IsKindOf (RUNTIME_CLASS(AAmmo))) else if (inv->IsKindOf (RUNTIME_CLASS(AAmmo)))
{ {
// Half ammo when dropped by bad guys. // Half ammo when dropped by bad guys.
inv->Amount = inv->GetClass()->Meta.GetMetaInt (AIMETA_DropAmount, MAX(1, FixedMul(inv->Amount, dropammofactor))); int amount = static_cast<PClassAmmo *>(inv->GetClass())->DropAmount;
inv->ItemFlags|=flagmask; if (amount <= 0)
{
amount = FixedMul(inv->Amount, dropammofactor);
}
inv->Amount = amount;
inv->ItemFlags |= flagmask;
} }
else if (inv->IsKindOf (RUNTIME_CLASS(AWeapon))) else if (inv->IsKindOf (RUNTIME_CLASS(AWeapon)))
{ {

View file

@ -243,17 +243,13 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker)
{ {
message = GStrings("OB_MONTELEFRAG"); message = GStrings("OB_MONTELEFRAG");
} }
else if (mod == NAME_Melee) else if (mod == NAME_Melee && attacker->GetClass()->HitObituary.IsNotEmpty())
{ {
message = attacker->GetClass()->Meta.GetMetaString (AMETA_HitObituary); message = attacker->GetClass()->HitObituary;
if (message == NULL)
{
message = attacker->GetClass()->Meta.GetMetaString (AMETA_Obituary);
} }
} else if (attacker->GetClass()->Obituary.IsNotEmpty())
else
{ {
message = attacker->GetClass()->Meta.GetMetaString (AMETA_Obituary); message = attacker->GetClass()->Obituary;
} }
} }
} }
@ -274,13 +270,13 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker)
if (mod == NAME_Telefrag) message = GStrings("OB_MPTELEFRAG"); if (mod == NAME_Telefrag) message = GStrings("OB_MPTELEFRAG");
if (message == NULL) if (message == NULL)
{ {
if (inflictor != NULL) if (inflictor != NULL && inflictor->GetClass()->Obituary.IsNotEmpty())
{ {
message = inflictor->GetClass()->Meta.GetMetaString (AMETA_Obituary); message = inflictor->GetClass()->Obituary;
} }
if (message == NULL && attacker->player->ReadyWeapon != NULL) if (message == NULL && attacker->player->ReadyWeapon != NULL && attacker->player->ReadyWeapon->GetClass()->Obituary.IsNotEmpty())
{ {
message = attacker->player->ReadyWeapon->GetClass()->Meta.GetMetaString (AMETA_Obituary); message = attacker->player->ReadyWeapon->GetClass()->Obituary;
} }
if (message == NULL) if (message == NULL)
{ {
@ -320,12 +316,7 @@ EXTERN_CVAR (Int, fraglimit)
static int GibHealth(AActor *actor) static int GibHealth(AActor *actor)
{ {
return -abs( return -abs(actor->GetGibHealth());
actor->GetClass()->Meta.GetMetaInt (
AMETA_GibHealth,
gameinfo.gametype & GAME_DoomChex ?
-actor->SpawnHealth() :
-actor->SpawnHealth()/2));
} }
void AActor::Die (AActor *source, AActor *inflictor) void AActor::Die (AActor *source, AActor *inflictor)
@ -399,22 +390,22 @@ void AActor::Die (AActor *source, AActor *inflictor)
flags6 |= MF6_KILLED; flags6 |= MF6_KILLED;
// [RH] Allow the death height to be overridden using metadata. // [RH] Allow the death height to be overridden using metadata.
fixed_t metaheight = 0; fixed_t metaheight = -1;
if (DamageType == NAME_Fire) if (DamageType == NAME_Fire)
{ {
metaheight = GetClass()->Meta.GetMetaFixed (AMETA_BurnHeight); metaheight = GetClass()->BurnHeight;
} }
if (metaheight == 0) if (metaheight < 0)
{ {
metaheight = GetClass()->Meta.GetMetaFixed (AMETA_DeathHeight); metaheight = GetClass()->DeathHeight;
} }
if (metaheight != 0) if (metaheight < 0)
{ {
height = MAX<fixed_t> (metaheight, 0); height >>= 2;
} }
else else
{ {
height >>= 2; height = MAX<fixed_t> (metaheight, 0);
} }
// [RH] If the thing has a special, execute and remove it // [RH] If the thing has a special, execute and remove it
@ -1271,7 +1262,7 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
woundstate = target->FindState(NAME_Wound, mod); woundstate = target->FindState(NAME_Wound, mod);
if (woundstate != NULL) if (woundstate != NULL)
{ {
int woundhealth = RUNTIME_TYPE(target)->Meta.GetMetaInt (AMETA_WoundHealth, 6); int woundhealth = target->GetClass()->WoundHealth;
if (target->health <= woundhealth) if (target->health <= woundhealth)
{ {

View file

@ -103,7 +103,7 @@ enum EPuffFlags
PF_TEMPORARY = 4 PF_TEMPORARY = 4
}; };
AActor *P_SpawnPuff (AActor *source, const PClass *pufftype, fixed_t x, fixed_t y, fixed_t z, angle_t dir, int updown, int flags = 0); AActor *P_SpawnPuff (AActor *source, PClassActor *pufftype, fixed_t x, fixed_t y, fixed_t z, angle_t dir, int updown, int flags = 0);
void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, angle_t dir, int damage, AActor *originator); void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, angle_t dir, int damage, AActor *originator);
void P_BloodSplatter (fixed_t x, fixed_t y, fixed_t z, AActor *originator); void P_BloodSplatter (fixed_t x, fixed_t y, fixed_t z, AActor *originator);
void P_BloodSplatter2 (fixed_t x, fixed_t y, fixed_t z, AActor *originator); void P_BloodSplatter2 (fixed_t x, fixed_t y, fixed_t z, AActor *originator);
@ -114,15 +114,15 @@ void P_ExplodeMissile (AActor *missile, line_t *explodeline, AActor *target);
AActor *P_SpawnMissile (AActor* source, AActor* dest, const PClass *type, AActor* owner = NULL); AActor *P_SpawnMissile (AActor* source, AActor* dest, const PClass *type, AActor* owner = NULL);
AActor *P_SpawnMissileZ (AActor* source, fixed_t z, AActor* dest, const PClass *type); AActor *P_SpawnMissileZ (AActor* source, fixed_t z, AActor* dest, const PClass *type);
AActor *P_SpawnMissileXYZ (fixed_t x, fixed_t y, fixed_t z, AActor *source, AActor *dest, const PClass *type, bool checkspawn = true, AActor *owner = NULL); AActor *P_SpawnMissileXYZ (fixed_t x, fixed_t y, fixed_t z, AActor *source, AActor *dest, const PClass *type, bool checkspawn = true, AActor *owner = NULL);
AActor *P_SpawnMissileAngle (AActor *source, const PClass *type, angle_t angle, fixed_t velz); AActor *P_SpawnMissileAngle (AActor *source, PClassActor *type, angle_t angle, fixed_t velz);
AActor *P_SpawnMissileAngleSpeed (AActor *source, const PClass *type, angle_t angle, fixed_t velz, fixed_t speed); AActor *P_SpawnMissileAngleSpeed (AActor *source, PClassActor *type, angle_t angle, fixed_t velz, fixed_t speed);
AActor *P_SpawnMissileAngleZ (AActor *source, fixed_t z, const PClass *type, angle_t angle, fixed_t velz); AActor *P_SpawnMissileAngleZ (AActor *source, fixed_t z, PClassActor *type, angle_t angle, fixed_t velz);
AActor *P_SpawnMissileAngleZSpeed (AActor *source, fixed_t z, const PClass *type, angle_t angle, fixed_t velz, fixed_t speed, AActor *owner=NULL, bool checkspawn = true); AActor *P_SpawnMissileAngleZSpeed (AActor *source, fixed_t z, PClassActor *type, angle_t angle, fixed_t velz, fixed_t speed, AActor *owner=NULL, bool checkspawn = true);
AActor *P_SpawnMissileZAimed (AActor *source, fixed_t z, AActor *dest, const PClass *type); AActor *P_SpawnMissileZAimed (AActor *source, fixed_t z, AActor *dest, PClassActor *type);
AActor *P_SpawnPlayerMissile (AActor* source, const PClass *type); AActor *P_SpawnPlayerMissile (AActor* source, PClassActor *type);
AActor *P_SpawnPlayerMissile (AActor *source, const PClass *type, angle_t angle); AActor *P_SpawnPlayerMissile (AActor *source, PClassActor *type, angle_t angle);
AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z, const PClass *type, angle_t angle, AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z, PClassActor *type, angle_t angle,
AActor **pLineTarget = NULL, AActor **MissileActor = NULL, bool nofreeaim = false); AActor **pLineTarget = NULL, AActor **MissileActor = NULL, bool nofreeaim = false);
void P_CheckFakeFloorTriggers (AActor *mo, fixed_t oldz, bool oldz_has_viewheight=false); void P_CheckFakeFloorTriggers (AActor *mo, fixed_t oldz, bool oldz_has_viewheight=false);

View file

@ -3588,7 +3588,7 @@ void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *actor, a
{ {
if (bleedtrace.HitType == TRACE_HitWall) if (bleedtrace.HitType == TRACE_HitWall)
{ {
PalEntry bloodcolor = (PalEntry)actor->GetClass()->Meta.GetMetaInt(AMETA_BloodColor); PalEntry bloodcolor = actor->GetClass()->BloodColor;
if (bloodcolor != 0) if (bloodcolor != 0)
{ {
bloodcolor.r>>=1; // the full color is too bright for blood decals bloodcolor.r>>=1; // the full color is too bright for blood decals
@ -4325,7 +4325,7 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b
{ {
points = points * splashfactor; points = points * splashfactor;
} }
points *= thing->GetClass()->Meta.GetMetaFixed(AMETA_RDFactor, FRACUNIT)/(float)FRACUNIT; points *= thing->GetClass()->RDFactor/(float)FRACUNIT;
if (points > 0.f && P_CheckSight (thing, bombspot, 1)) if (points > 0.f && P_CheckSight (thing, bombspot, 1))
{ // OK to damage; target is in direct path { // OK to damage; target is in direct path
@ -4391,7 +4391,7 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b
int damage = Scale (bombdamage, bombdistance-dist, bombdistance); int damage = Scale (bombdamage, bombdistance-dist, bombdistance);
damage = (int)((float)damage * splashfactor); damage = (int)((float)damage * splashfactor);
damage = Scale(damage, thing->GetClass()->Meta.GetMetaFixed(AMETA_RDFactor, FRACUNIT), FRACUNIT); damage = Scale(damage, thing->GetClass()->RDFactor, FRACUNIT);
if (damage > 0) if (damage > 0)
{ {
P_DamageMobj (thing, bombspot, bombsource, damage, bombmod); P_DamageMobj (thing, bombspot, bombsource, damage, bombmod);
@ -4598,8 +4598,8 @@ void P_DoCrunch (AActor *thing, FChangePosition *cpos)
if ((!(thing->flags&MF_NOBLOOD)) && if ((!(thing->flags&MF_NOBLOOD)) &&
(!(thing->flags2&(MF2_INVULNERABLE|MF2_DORMANT)))) (!(thing->flags2&(MF2_INVULNERABLE|MF2_DORMANT))))
{ {
PalEntry bloodcolor = (PalEntry)thing->GetClass()->Meta.GetMetaInt(AMETA_BloodColor); PalEntry bloodcolor = thing->GetClass()->BloodColor;
const PClass *bloodcls = PClass::FindClass((ENamedName)thing->GetClass()->Meta.GetMetaInt(AMETA_BloodType, NAME_Blood)); PClassActor *bloodcls = PClass::FindActor(thing->GetClass()->BloodType);
P_TraceBleed (cpos->crushchange, thing); P_TraceBleed (cpos->crushchange, thing);
if (cl_bloodtype <= 1 && bloodcls != NULL) if (cl_bloodtype <= 1 && bloodcls != NULL)

View file

@ -1069,7 +1069,7 @@ bool AActor::Grind(bool items)
if (isgeneric) // Not a custom crush state, so colorize it appropriately. if (isgeneric) // Not a custom crush state, so colorize it appropriately.
{ {
S_Sound (this, CHAN_BODY, "misc/fallingsplat", 1, ATTN_IDLE); S_Sound (this, CHAN_BODY, "misc/fallingsplat", 1, ATTN_IDLE);
PalEntry bloodcolor = PalEntry(GetClass()->Meta.GetMetaInt(AMETA_BloodColor)); PalEntry bloodcolor = GetClass()->BloodColor;
if (bloodcolor!=0) Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a); if (bloodcolor!=0) Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a);
} }
return false; return false;
@ -1113,7 +1113,7 @@ bool AActor::Grind(bool items)
} }
S_Sound (this, CHAN_BODY, "misc/fallingsplat", 1, ATTN_IDLE); S_Sound (this, CHAN_BODY, "misc/fallingsplat", 1, ATTN_IDLE);
PalEntry bloodcolor = (PalEntry)this->GetClass()->Meta.GetMetaInt(AMETA_BloodColor); PalEntry bloodcolor = GetClass()->BloodColor;
if (bloodcolor!=0) gib->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a); if (bloodcolor!=0) gib->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a);
} }
if (flags & MF_ICECORPSE) if (flags & MF_ICECORPSE)
@ -2651,7 +2651,7 @@ int AActor::GetMissileDamage (int mask, int add)
void AActor::Howl () void AActor::Howl ()
{ {
int howl = GetClass()->Meta.GetMetaInt(AMETA_HowlSound); FSoundID howl = GetClass()->HowlSound;
if (!S_IsActorPlayingSomething(this, CHAN_BODY, howl)) if (!S_IsActorPlayingSomething(this, CHAN_BODY, howl))
{ {
S_Sound (this, CHAN_BODY, howl, 1, ATTN_NORM); S_Sound (this, CHAN_BODY, howl, 1, ATTN_NORM);
@ -3553,9 +3553,8 @@ AActor *AActor::StaticSpawn (PClassActor *type, fixed_t ix, fixed_t iy, fixed_t
actor->frame = st->GetFrame(); actor->frame = st->GetFrame();
actor->renderflags = (actor->renderflags & ~RF_FULLBRIGHT) | st->GetFullbright(); actor->renderflags = (actor->renderflags & ~RF_FULLBRIGHT) | st->GetFullbright();
actor->touching_sectorlist = NULL; // NULL head of sector list // phares 3/13/98 actor->touching_sectorlist = NULL; // NULL head of sector list // phares 3/13/98
if (G_SkillProperty(SKILLP_FastMonsters)) if (G_SkillProperty(SKILLP_FastMonsters) && actor->GetClass()->FastSpeed >= 0)
actor->Speed = actor->GetClass()->Meta.GetMetaFixed(AMETA_FastSpeed, actor->Speed); actor->Speed = actor->GetClass()->FastSpeed;
// set subsector and/or block links // set subsector and/or block links
actor->LinkToWorld (SpawningMapThing); actor->LinkToWorld (SpawningMapThing);
@ -4445,7 +4444,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
// P_SpawnPuff // P_SpawnPuff
// //
AActor *P_SpawnPuff (AActor *source, const PClass *pufftype, fixed_t x, fixed_t y, fixed_t z, angle_t dir, int updown, int flags) AActor *P_SpawnPuff (AActor *source, PClassActor *pufftype, fixed_t x, fixed_t y, fixed_t z, angle_t dir, int updown, int flags)
{ {
AActor *puff; AActor *puff;
@ -4507,8 +4506,8 @@ AActor *P_SpawnPuff (AActor *source, const PClass *pufftype, fixed_t x, fixed_t
void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, angle_t dir, int damage, AActor *originator) void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, angle_t dir, int damage, AActor *originator)
{ {
AActor *th; AActor *th;
PalEntry bloodcolor = (PalEntry)originator->GetClass()->Meta.GetMetaInt(AMETA_BloodColor); PalEntry bloodcolor = originator->GetClass()->BloodColor;
const PClass *bloodcls = PClass::FindClass((ENamedName)originator->GetClass()->Meta.GetMetaInt(AMETA_BloodType, NAME_Blood)); PClassActor *bloodcls = PClass::FindActor(originator->GetClass()->BloodType);
int bloodtype = cl_bloodtype; int bloodtype = cl_bloodtype;
@ -4569,15 +4568,15 @@ void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, angle_t dir, int damage, AAc
void P_BloodSplatter (fixed_t x, fixed_t y, fixed_t z, AActor *originator) void P_BloodSplatter (fixed_t x, fixed_t y, fixed_t z, AActor *originator)
{ {
PalEntry bloodcolor = (PalEntry)originator->GetClass()->Meta.GetMetaInt(AMETA_BloodColor); PalEntry bloodcolor = originator->GetClass()->BloodColor;
const PClass *bloodcls = PClass::FindClass((ENamedName)originator->GetClass()->Meta.GetMetaInt(AMETA_BloodType2, NAME_BloodSplatter)); PClassActor *bloodcls = PClass::FindActor(originator->GetClass()->BloodType2);
int bloodtype = cl_bloodtype; int bloodtype = cl_bloodtype;
if (bloodcls != NULL && !(GetDefaultByType(bloodcls)->flags4 & MF4_ALLOWPARTICLES)) if (bloodcls != NULL && !(GetDefaultByType(bloodcls)->flags4 & MF4_ALLOWPARTICLES))
bloodtype = 0; bloodtype = 0;
if (bloodcls!=NULL && bloodtype <= 1) if (bloodcls != NULL && bloodtype <= 1)
{ {
AActor *mo; AActor *mo;
@ -4607,8 +4606,8 @@ void P_BloodSplatter (fixed_t x, fixed_t y, fixed_t z, AActor *originator)
void P_BloodSplatter2 (fixed_t x, fixed_t y, fixed_t z, AActor *originator) void P_BloodSplatter2 (fixed_t x, fixed_t y, fixed_t z, AActor *originator)
{ {
PalEntry bloodcolor = (PalEntry)originator->GetClass()->Meta.GetMetaInt(AMETA_BloodColor); PalEntry bloodcolor = originator->GetClass()->BloodColor;
const PClass *bloodcls = PClass::FindClass((ENamedName)originator->GetClass()->Meta.GetMetaInt(AMETA_BloodType3, NAME_AxeBlood)); PClassActor *bloodcls = PClass::FindActor(originator->GetClass()->BloodType3);
int bloodtype = cl_bloodtype; int bloodtype = cl_bloodtype;
@ -4646,8 +4645,8 @@ void P_BloodSplatter2 (fixed_t x, fixed_t y, fixed_t z, AActor *originator)
void P_RipperBlood (AActor *mo, AActor *bleeder) void P_RipperBlood (AActor *mo, AActor *bleeder)
{ {
fixed_t x, y, z; fixed_t x, y, z;
PalEntry bloodcolor = (PalEntry)bleeder->GetClass()->Meta.GetMetaInt(AMETA_BloodColor); PalEntry bloodcolor = bleeder->GetClass()->BloodColor;
const PClass *bloodcls = PClass::FindClass((ENamedName)bleeder->GetClass()->Meta.GetMetaInt(AMETA_BloodType, NAME_Blood)); PClassActor *bloodcls = PClass::FindActor(bleeder->GetClass()->BloodType);
x = mo->x + (pr_ripperblood.Random2 () << 12); x = mo->x + (pr_ripperblood.Random2 () << 12);
y = mo->y + (pr_ripperblood.Random2 () << 12); y = mo->y + (pr_ripperblood.Random2 () << 12);
@ -5031,11 +5030,12 @@ void P_PlaySpawnSound(AActor *missile, AActor *spawner)
} }
} }
static fixed_t GetDefaultSpeed(const PClass *type) static fixed_t GetDefaultSpeed(PClassActor *type)
{ {
if (type == NULL) return 0; if (type == NULL)
else if (G_SkillProperty(SKILLP_FastMonsters)) return 0;
return type->Meta.GetMetaFixed(AMETA_FastSpeed, GetDefaultByType(type)->Speed); else if (G_SkillProperty(SKILLP_FastMonsters) && type->FastSpeed >= 0)
return type->FastSpeed;
else else
return GetDefaultByType(type)->Speed; return GetDefaultByType(type)->Speed;
} }
@ -5158,7 +5158,7 @@ AActor * P_OldSpawnMissile(AActor * source, AActor * owner, AActor * dest, const
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
AActor *P_SpawnMissileAngle (AActor *source, const PClass *type, AActor *P_SpawnMissileAngle (AActor *source, PClassActor *type,
angle_t angle, fixed_t velz) angle_t angle, fixed_t velz)
{ {
return P_SpawnMissileAngleZSpeed (source, source->z + 32*FRACUNIT, return P_SpawnMissileAngleZSpeed (source, source->z + 32*FRACUNIT,
@ -5166,13 +5166,13 @@ AActor *P_SpawnMissileAngle (AActor *source, const PClass *type,
} }
AActor *P_SpawnMissileAngleZ (AActor *source, fixed_t z, AActor *P_SpawnMissileAngleZ (AActor *source, fixed_t z,
const PClass *type, angle_t angle, fixed_t velz) PClassActor *type, angle_t angle, fixed_t velz)
{ {
return P_SpawnMissileAngleZSpeed (source, z, type, angle, velz, return P_SpawnMissileAngleZSpeed (source, z, type, angle, velz,
GetDefaultSpeed (type)); GetDefaultSpeed (type));
} }
AActor *P_SpawnMissileZAimed (AActor *source, fixed_t z, AActor *dest, const PClass *type) AActor *P_SpawnMissileZAimed (AActor *source, fixed_t z, AActor *dest, PClassActor *type)
{ {
angle_t an; angle_t an;
fixed_t dist; fixed_t dist;
@ -5201,7 +5201,7 @@ AActor *P_SpawnMissileZAimed (AActor *source, fixed_t z, AActor *dest, const PCl
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
AActor *P_SpawnMissileAngleSpeed (AActor *source, const PClass *type, AActor *P_SpawnMissileAngleSpeed (AActor *source, PClassActor *type,
angle_t angle, fixed_t velz, fixed_t speed) angle_t angle, fixed_t velz, fixed_t speed)
{ {
return P_SpawnMissileAngleZSpeed (source, source->z + 32*FRACUNIT, return P_SpawnMissileAngleZSpeed (source, source->z + 32*FRACUNIT,
@ -5209,7 +5209,7 @@ AActor *P_SpawnMissileAngleSpeed (AActor *source, const PClass *type,
} }
AActor *P_SpawnMissileAngleZSpeed (AActor *source, fixed_t z, AActor *P_SpawnMissileAngleZSpeed (AActor *source, fixed_t z,
const PClass *type, angle_t angle, fixed_t velz, fixed_t speed, AActor *owner, bool checkspawn) PClassActor *type, angle_t angle, fixed_t velz, fixed_t speed, AActor *owner, bool checkspawn)
{ {
AActor *mo; AActor *mo;
@ -5239,18 +5239,18 @@ AActor *P_SpawnMissileAngleZSpeed (AActor *source, fixed_t z,
================ ================
*/ */
AActor *P_SpawnPlayerMissile (AActor *source, const PClass *type) AActor *P_SpawnPlayerMissile (AActor *source, PClassActor *type)
{ {
return P_SpawnPlayerMissile (source, 0, 0, 0, type, source->angle); return P_SpawnPlayerMissile (source, 0, 0, 0, type, source->angle);
} }
AActor *P_SpawnPlayerMissile (AActor *source, const PClass *type, angle_t angle) AActor *P_SpawnPlayerMissile (AActor *source, PClassActor *type, angle_t angle)
{ {
return P_SpawnPlayerMissile (source, 0, 0, 0, type, angle); return P_SpawnPlayerMissile (source, 0, 0, 0, type, angle);
} }
AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z, AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z,
const PClass *type, angle_t angle, AActor **pLineTarget, AActor **pMissileActor, PClassActor *type, angle_t angle, AActor **pLineTarget, AActor **pMissileActor,
bool nofreeaim) bool nofreeaim)
{ {
static const int angdiff[3] = { -1<<26, 1<<26, 0 }; static const int angdiff[3] = { -1<<26, 1<<26, 0 };
@ -5451,7 +5451,7 @@ int AActor::DoSpecialDamage (AActor *target, int damage)
{ {
if (target->player) if (target->player)
{ {
int poisondamage = GetClass()->Meta.GetMetaInt(AMETA_PoisonDamage); int poisondamage = GetClass()->PoisonDamage;
if (poisondamage > 0) if (poisondamage > 0)
{ {
P_PoisonPlayer (target->player, this, this->target, poisondamage); P_PoisonPlayer (target->player, this, this->target, poisondamage);
@ -5512,8 +5512,7 @@ void AActor::Crash()
} }
if (crashstate == NULL) if (crashstate == NULL)
{ {
int gibhealth = -abs(GetClass()->Meta.GetMetaInt (AMETA_GibHealth, int gibhealth = GetGibHealth();
gameinfo.gametype & GAME_DoomChex ? -SpawnHealth() : -SpawnHealth()/2));
if (health < gibhealth) if (health < gibhealth)
{ // Extreme death { // Extreme death
@ -5538,7 +5537,7 @@ void AActor::SetIdle()
SetState(idle); SetState(idle);
} }
int AActor::SpawnHealth() int AActor::SpawnHealth() const
{ {
if (!(flags3 & MF3_ISMONSTER) || GetDefault()->health == 0) if (!(flags3 & MF3_ISMONSTER) || GetDefault()->health == 0)
{ {
@ -5556,15 +5555,32 @@ int AActor::SpawnHealth()
} }
} }
FDropItem *AActor::GetDropItems() int AActor::GetGibHealth() const
{ {
unsigned int index = GetClass()->Meta.GetMetaInt (ACMETA_DropItems) - 1; int gibhealth = GetClass()->GibHealth;
if (index >= 0 && index < DropItemList.Size()) if (gibhealth != INT_MIN)
{ {
return DropItemList[index]; return gibhealth;
} }
return NULL; else if (gameinfo.gametype & GAME_DoomChex)
{
return -SpawnHealth();
}
else
{
return -SpawnHealth()/2;
}
}
fixed_t AActor::GetCameraHeight() const
{
return GetClass()->CameraHeight == FIXED_MIN ? height / 2 : GetClass()->CameraHeight;
}
DDropItem *AActor::GetDropItems() const
{
return GetClass()->DropItems;
} }
fixed_t AActor::GetGravity() const fixed_t AActor::GetGravity() const
@ -5595,30 +5611,9 @@ const char *AActor::GetTag(const char *def) const
// DropItem handling // DropItem handling
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
FDropItemPtrArray DropItemList; IMPLEMENT_POINTY_CLASS(DDropItem)
DECLARE_POINTER(Next)
void FreeDropItemChain(FDropItem *chain) END_POINTERS
{
while (chain != NULL)
{
FDropItem *next = chain->Next;
delete chain;
chain = next;
}
}
FDropItemPtrArray::~FDropItemPtrArray()
{
for (unsigned int i = 0; i < Size(); ++i)
{
FreeDropItemChain ((*this)[i]);
}
}
int StoreDropItemChain(FDropItem *chain)
{
return DropItemList.Push (chain) + 1;
}
void PrintMiscActorInfo(AActor * query) void PrintMiscActorInfo(AActor * query)
{ {

View file

@ -104,32 +104,32 @@ void SetupPlayerClasses ()
if (gameinfo.gametype == GAME_Doom) if (gameinfo.gametype == GAME_Doom)
{ {
newclass.Type = PClass::FindClass (NAME_DoomPlayer); newclass.Type = static_cast<PClassPlayerPawn *>(PClass::FindClass(NAME_DoomPlayer));
PlayerClasses.Push (newclass); PlayerClasses.Push(newclass);
} }
else if (gameinfo.gametype == GAME_Heretic) else if (gameinfo.gametype == GAME_Heretic)
{ {
newclass.Type = PClass::FindClass (NAME_HereticPlayer); newclass.Type = static_cast<PClassPlayerPawn *>(PClass::FindClass(NAME_HereticPlayer));
PlayerClasses.Push (newclass); PlayerClasses.Push(newclass);
} }
else if (gameinfo.gametype == GAME_Hexen) else if (gameinfo.gametype == GAME_Hexen)
{ {
newclass.Type = PClass::FindClass (NAME_FighterPlayer); newclass.Type = static_cast<PClassPlayerPawn *>(PClass::FindClass(NAME_FighterPlayer));
PlayerClasses.Push (newclass); PlayerClasses.Push(newclass);
newclass.Type = PClass::FindClass (NAME_ClericPlayer); newclass.Type = static_cast<PClassPlayerPawn *>(PClass::FindClass(NAME_ClericPlayer));
PlayerClasses.Push (newclass); PlayerClasses.Push(newclass);
newclass.Type = PClass::FindClass (NAME_MagePlayer); newclass.Type = static_cast<PClassPlayerPawn *>(PClass::FindClass(NAME_MagePlayer));
PlayerClasses.Push (newclass); PlayerClasses.Push(newclass);
} }
else if (gameinfo.gametype == GAME_Strife) else if (gameinfo.gametype == GAME_Strife)
{ {
newclass.Type = PClass::FindClass (NAME_StrifePlayer); newclass.Type = static_cast<PClassPlayerPawn *>(PClass::FindClass(NAME_StrifePlayer));
PlayerClasses.Push (newclass); PlayerClasses.Push(newclass);
} }
else if (gameinfo.gametype == GAME_Chex) else if (gameinfo.gametype == GAME_Chex)
{ {
newclass.Type = PClass::FindClass (NAME_ChexPlayer); newclass.Type = static_cast<PClassPlayerPawn *>(PClass::FindClass(NAME_ChexPlayer));
PlayerClasses.Push (newclass); PlayerClasses.Push(newclass);
} }
} }
@ -145,17 +145,13 @@ CCMD (addplayerclass)
{ {
if (ParsingKeyConf && argv.argc () > 1) if (ParsingKeyConf && argv.argc () > 1)
{ {
const PClass *ti = PClass::FindClass (argv[1]); PClassPlayerPawn *ti = dyn_cast<PClassPlayerPawn>(PClass::FindClass(argv[1]));
if (!ti) if (ti == NULL)
{ {
Printf ("Unknown player class '%s'\n", argv[1]); Printf ("Unknown player class '%s'\n", argv[1]);
} }
else if (!ti->IsDescendantOf (RUNTIME_CLASS (APlayerPawn))) else if (ti->DisplayName.IsEmpty())
{
Printf ("Invalid player class '%s'\n", argv[1]);
}
else if (ti->Meta.GetMetaString (APMETA_DisplayName) == NULL)
{ {
Printf ("Missing displayname for player class '%s'\n", argv[1]); Printf ("Missing displayname for player class '%s'\n", argv[1]);
} }
@ -180,7 +176,6 @@ CCMD (addplayerclass)
arg++; arg++;
} }
PlayerClasses.Push (newclass); PlayerClasses.Push (newclass);
} }
} }
@ -190,8 +185,7 @@ CCMD (playerclasses)
{ {
for (unsigned int i = 0; i < PlayerClasses.Size (); i++) for (unsigned int i = 0; i < PlayerClasses.Size (); i++)
{ {
Printf ("% 3d %s\n", i, Printf("% 3d %s\n", i, PlayerClasses[i].Type->DisplayName.GetChars());
PlayerClasses[i].Type->Meta.GetMetaString (APMETA_DisplayName));
} }
} }
@ -396,6 +390,48 @@ int player_t::GetSpawnClass()
return static_cast<APlayerPawn*>(GetDefaultByType(type))->SpawnMask; return static_cast<APlayerPawn*>(GetDefaultByType(type))->SpawnMask;
} }
//===========================================================================
//
// PClassPlayerPawn
//
//===========================================================================
IMPLEMENT_CLASS(PClassPlayerPawn)
PClassPlayerPawn::PClassPlayerPawn()
{
for (int i = 0; i < countof(HexenArmor); ++i)
{
HexenArmor[i] = 0;
}
ColorRangeStart = 0;
ColorRangeEnd = 0;
}
void PClassPlayerPawn::Derive(PClass *newclass)
{
assert(newclass->IsKindOf(RUNTIME_CLASS(PClassPlayerPawn)));
Super::Derive(newclass);
PClassPlayerPawn *newp = static_cast<PClassPlayerPawn *>(newclass);
int i;
newp->DisplayName = DisplayName;
newp->SoundClass = SoundClass;
newp->Face = Face;
newp->InvulMode = InvulMode;
newp->HealingRadiusType = HealingRadiusType;
newp->ColorRangeStart = ColorRangeStart;
newp->ColorRangeEnd = ColorRangeEnd;
for (i = 0; i < countof(HexenArmor); ++i)
{
newp->HexenArmor[i] = HexenArmor[i];
}
for (i = 0; i < countof(Slot); ++i)
{
newp->Slot[i] = Slot[i];
}
}
//=========================================================================== //===========================================================================
// //
// APlayerPawn // APlayerPawn
@ -908,8 +944,8 @@ const char *APlayerPawn::GetSoundClass ()
} }
// [GRB] // [GRB]
const char *sclass = GetClass ()->Meta.GetMetaString (APMETA_SoundClass); PClassPlayerPawn *pclass = GetClass();
return sclass != NULL ? sclass : "player"; return pclass->SoundClass.IsNotEmpty() ? pclass->SoundClass : "player";
} }
//=========================================================================== //===========================================================================
@ -1026,18 +1062,14 @@ void APlayerPawn::GiveDefaultInventory ()
// HexenArmor must always be the first item in the inventory because // HexenArmor must always be the first item in the inventory because
// it provides player class based protection that should not affect // it provides player class based protection that should not affect
// any other protection item. // any other protection item.
fixed_t hx[5]; PClassPlayerPawn *myclass = GetClass();
for(int i=0;i<5;i++) GiveInventoryType(RUNTIME_CLASS(AHexenArmor));
{
hx[i] = GetClass()->Meta.GetMetaFixed(APMETA_Hexenarmor0+i);
}
GiveInventoryType (RUNTIME_CLASS(AHexenArmor));
AHexenArmor *harmor = FindInventory<AHexenArmor>(); AHexenArmor *harmor = FindInventory<AHexenArmor>();
harmor->Slots[4] = hx[0]; harmor->Slots[4] = myclass->HexenArmor[0];
harmor->SlotsIncrement[0] = hx[1]; for (int i = 0; i < 4; ++i)
harmor->SlotsIncrement[1] = hx[2]; {
harmor->SlotsIncrement[2] = hx[3]; harmor->SlotsIncrement[i] = myclass->HexenArmor[i + 1];
harmor->SlotsIncrement[3] = hx[4]; }
// BasicArmor must come right after that. It should not affect any // BasicArmor must come right after that. It should not affect any
// other protection item as well but needs to process the damage // other protection item as well but needs to process the damage
@ -1049,7 +1081,7 @@ void APlayerPawn::GiveDefaultInventory ()
AddInventory (barmor); AddInventory (barmor);
// Now add the items from the DECORATE definition // Now add the items from the DECORATE definition
FDropItem *di = GetDropItems(); DDropItem *di = GetDropItems();
while (di) while (di)
{ {
@ -1060,14 +1092,14 @@ void APlayerPawn::GiveDefaultInventory ()
if (item != NULL) if (item != NULL)
{ {
item->Amount = clamp<int>( item->Amount = clamp<int>(
item->Amount + (di->amount ? di->amount : ((AInventory *)item->GetDefault ())->Amount), item->Amount + (di->Amount ? di->Amount : ((AInventory *)item->GetDefault ())->Amount),
0, item->MaxAmount); 0, item->MaxAmount);
} }
else else
{ {
item = static_cast<AInventory *>(Spawn (ti, 0,0,0, NO_REPLACE)); item = static_cast<AInventory *>(Spawn (ti, 0,0,0, NO_REPLACE));
item->ItemFlags|=IF_IGNORESKILL; // no skill multiplicators here item->ItemFlags |= IF_IGNORESKILL; // no skill multiplicators here
item->Amount = di->amount; item->Amount = di->Amount;
if (item->IsKindOf (RUNTIME_CLASS (AWeapon))) if (item->IsKindOf (RUNTIME_CLASS (AWeapon)))
{ {
// To allow better control any weapon is emptied of // To allow better control any weapon is emptied of
@ -1341,7 +1373,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SkullPop)
// [GRB] Parameterized version // [GRB] Parameterized version
if (spawntype == NULL || !spawntype->IsDescendantOf(RUNTIME_CLASS(APlayerChunk))) if (spawntype == NULL || !spawntype->IsDescendantOf(RUNTIME_CLASS(APlayerChunk)))
{ {
spawntype = PClass::FindActor("BloodySkull"); spawntype = dyn_cast<PClassPlayerPawn>(PClass::FindClass("BloodySkull"));
if (spawntype == NULL) if (spawntype == NULL)
return 0; return 0;
} }

View file

@ -1064,7 +1064,7 @@ void R_SetupFrame (AActor *actor)
{ {
iview->nviewx = camera->x; iview->nviewx = camera->x;
iview->nviewy = camera->y; iview->nviewy = camera->y;
iview->nviewz = camera->player ? camera->player->viewz : camera->z + camera->GetClass()->Meta.GetMetaFixed(AMETA_CameraHeight); iview->nviewz = camera->player ? camera->player->viewz : camera->z + camera->GetCameraHeight();
viewsector = camera->Sector; viewsector = camera->Sector;
r_showviewer = false; r_showviewer = false;
} }

View file

@ -442,7 +442,7 @@ void R_InitSkins (void)
int lastlump; int lastlump;
int aliasid; int aliasid;
bool remove; bool remove;
const PClass *basetype, *transtype; PClassPlayerPawn *basetype, *transtype;
key[sizeof(key)-1] = 0; key[sizeof(key)-1] = 0;
i = PlayerClasses.Size () - 1; i = PlayerClasses.Size () - 1;
@ -527,11 +527,11 @@ void R_InitSkins (void)
else if (0 == stricmp (key, "game")) else if (0 == stricmp (key, "game"))
{ {
if (gameinfo.gametype == GAME_Heretic) if (gameinfo.gametype == GAME_Heretic)
basetype = PClass::FindClass (NAME_HereticPlayer); basetype = static_cast<PClassPlayerPawn *>(PClass::FindClass (NAME_HereticPlayer));
else if (gameinfo.gametype == GAME_Strife) else if (gameinfo.gametype == GAME_Strife)
basetype = PClass::FindClass (NAME_StrifePlayer); basetype = static_cast<PClassPlayerPawn *>(PClass::FindClass (NAME_StrifePlayer));
else else
basetype = PClass::FindClass (NAME_DoomPlayer); basetype = static_cast<PClassPlayerPawn *>(PClass::FindClass (NAME_DoomPlayer));
transtype = basetype; transtype = basetype;
@ -539,7 +539,7 @@ void R_InitSkins (void)
{ {
if (gameinfo.gametype & GAME_DoomChex) if (gameinfo.gametype & GAME_DoomChex)
{ {
transtype = PClass::FindClass (NAME_HereticPlayer); transtype = static_cast<PClassPlayerPawn *>(PClass::FindClass (NAME_HereticPlayer));
skins[i].othergame = true; skins[i].othergame = true;
} }
else if (gameinfo.gametype != GAME_Heretic) else if (gameinfo.gametype != GAME_Heretic)
@ -558,7 +558,7 @@ void R_InitSkins (void)
{ {
if (gameinfo.gametype == GAME_Heretic) if (gameinfo.gametype == GAME_Heretic)
{ {
transtype = PClass::FindClass (NAME_DoomPlayer); transtype = static_cast<PClassPlayerPawn *>(PClass::FindClass (NAME_DoomPlayer));
skins[i].othergame = true; skins[i].othergame = true;
} }
else if (!(gameinfo.gametype & GAME_DoomChex)) else if (!(gameinfo.gametype & GAME_DoomChex))
@ -634,12 +634,12 @@ void R_InitSkins (void)
{ {
if (gameinfo.gametype & GAME_DoomChex) if (gameinfo.gametype & GAME_DoomChex)
{ {
basetype = transtype = PClass::FindClass (NAME_DoomPlayer); basetype = transtype = static_cast<PClassPlayerPawn *>(PClass::FindClass (NAME_DoomPlayer));
} }
else if (gameinfo.gametype == GAME_Heretic) else if (gameinfo.gametype == GAME_Heretic)
{ {
basetype = PClass::FindClass (NAME_HereticPlayer); basetype = static_cast<PClassPlayerPawn *>(PClass::FindClass (NAME_HereticPlayer));
transtype = PClass::FindClass (NAME_DoomPlayer); transtype = static_cast<PClassPlayerPawn *>(PClass::FindClass (NAME_DoomPlayer));
skins[i].othergame = true; skins[i].othergame = true;
} }
else else
@ -650,17 +650,18 @@ void R_InitSkins (void)
if (!remove) if (!remove)
{ {
skins[i].range0start = transtype->Meta.GetMetaInt (APMETA_ColorRange) & 0xff; skins[i].range0start = transtype->ColorRangeStart;
skins[i].range0end = transtype->Meta.GetMetaInt (APMETA_ColorRange) >> 8; skins[i].range0end = transtype->ColorRangeEnd;
remove = true; remove = true;
for (j = 0; j < (int)PlayerClasses.Size (); j++) for (j = 0; j < (int)PlayerClasses.Size (); j++)
{ {
const PClass *type = PlayerClasses[j].Type; PClassPlayerPawn *type = PlayerClasses[j].Type;
if (type->IsDescendantOf (basetype) && if (type->IsDescendantOf (basetype) &&
GetDefaultByType (type)->SpawnState->sprite == GetDefaultByType (basetype)->SpawnState->sprite && GetDefaultByType (type)->SpawnState->sprite == GetDefaultByType (basetype)->SpawnState->sprite &&
type->Meta.GetMetaInt (APMETA_ColorRange) == basetype->Meta.GetMetaInt (APMETA_ColorRange)) type->ColorRangeStart == basetype->ColorRangeStart &&
type->ColorRangeEnd == basetype->ColorRangeEnd)
{ {
PlayerClasses[j].Skins.Push ((int)i); PlayerClasses[j].Skins.Push ((int)i);
remove = false; remove = false;
@ -871,9 +872,9 @@ void R_InitSprites ()
memset (skins, 0, sizeof(*skins) * numskins); memset (skins, 0, sizeof(*skins) * numskins);
for (i = 0; i < numskins; i++) for (i = 0; i < numskins; i++)
{ // Assume Doom skin by default { // Assume Doom skin by default
const PClass *type = PlayerClasses[0].Type; PClassPlayerPawn *type = PlayerClasses[0].Type;
skins[i].range0start = type->Meta.GetMetaInt (APMETA_ColorRange) & 255; skins[i].range0start = type->ColorRangeStart;
skins[i].range0end = type->Meta.GetMetaInt (APMETA_ColorRange) >> 8; skins[i].range0end = type->ColorRangeEnd;
skins[i].ScaleX = GetDefaultByType (type)->scaleX; skins[i].ScaleX = GetDefaultByType (type)->scaleX;
skins[i].ScaleY = GetDefaultByType (type)->scaleY; skins[i].ScaleY = GetDefaultByType (type)->scaleY;
} }
@ -886,11 +887,11 @@ void R_InitSprites ()
// [GRB] Each player class has its own base skin // [GRB] Each player class has its own base skin
for (i = 0; i < PlayerClasses.Size (); i++) for (i = 0; i < PlayerClasses.Size (); i++)
{ {
const PClass *basetype = PlayerClasses[i].Type; PClassPlayerPawn *basetype = PlayerClasses[i].Type;
const char *pclassface = basetype->Meta.GetMetaString (APMETA_Face); FString pclassface = basetype->Face;
strcpy (skins[i].name, "Base"); strcpy (skins[i].name, "Base");
if (pclassface == NULL || strcmp(pclassface, "None") == 0) if (pclassface.IsEmpty() || strcmp(pclassface, "None") == 0)
{ {
skins[i].face[0] = 'S'; skins[i].face[0] = 'S';
skins[i].face[1] = 'T'; skins[i].face[1] = 'T';
@ -901,8 +902,8 @@ void R_InitSprites ()
{ {
strcpy(skins[i].face, pclassface); strcpy(skins[i].face, pclassface);
} }
skins[i].range0start = basetype->Meta.GetMetaInt (APMETA_ColorRange) & 255; skins[i].range0start = basetype->ColorRangeStart;
skins[i].range0end = basetype->Meta.GetMetaInt (APMETA_ColorRange) >> 8; skins[i].range0end = basetype->ColorRangeEnd;
skins[i].ScaleX = GetDefaultByType (basetype)->scaleX; skins[i].ScaleX = GetDefaultByType (basetype)->scaleX;
skins[i].ScaleY = GetDefaultByType (basetype)->scaleY; skins[i].ScaleY = GetDefaultByType (basetype)->scaleY;
skins[i].sprite = GetDefaultByType (basetype)->SpawnState->sprite; skins[i].sprite = GetDefaultByType (basetype)->SpawnState->sprite;

View file

@ -7,7 +7,7 @@ class FBitmap;
struct FRemapTable; struct FRemapTable;
struct FCopyInfo; struct FCopyInfo;
class FScanner; class FScanner;
class PClass; class PClassInventory;
class FArchive; class FArchive;
// Texture IDs // Texture IDs
@ -18,7 +18,7 @@ class FTextureID
{ {
friend class FTextureManager; friend class FTextureManager;
friend FArchive &operator<< (FArchive &arc, FTextureID &tex); friend FArchive &operator<< (FArchive &arc, FTextureID &tex);
friend FTextureID GetHUDIcon(const PClass *cls); friend FTextureID GetHUDIcon(PClassInventory *cls);
friend void R_InitSpriteDefs (); friend void R_InitSpriteDefs ();
public: public:

View file

@ -256,7 +256,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
{ {
extra.DeathHeight = ((AActor*)(type->Defaults))->height; extra.DeathHeight = ((AActor*)(type->Defaults))->height;
} }
type->Meta.SetMetaFixed (AMETA_DeathHeight, extra.DeathHeight); type->DeathHeight = extra.DeathHeight;
} }
bag.statedef.SetStateLabel("Death", &type->OwnedStates[extra.DeathStart]); bag.statedef.SetStateLabel("Death", &type->OwnedStates[extra.DeathStart]);
} }
@ -294,7 +294,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
} }
if (extra.BurnHeight == 0) extra.BurnHeight = ((AActor*)(type->Defaults))->height; if (extra.BurnHeight == 0) extra.BurnHeight = ((AActor*)(type->Defaults))->height;
type->Meta.SetMetaFixed (AMETA_BurnHeight, extra.BurnHeight); type->BurnHeight = extra.BurnHeight;
bag.statedef.SetStateLabel("Burn", &type->OwnedStates[extra.FireDeathStart]); bag.statedef.SetStateLabel("Burn", &type->OwnedStates[extra.FireDeathStart]);
} }
@ -475,18 +475,18 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults,
else if (def == DEF_Projectile && sc.Compare ("ExplosionRadius")) else if (def == DEF_Projectile && sc.Compare ("ExplosionRadius"))
{ {
sc.MustGetNumber (); sc.MustGetNumber ();
bag.Info->Meta.SetMetaInt(ACMETA_ExplosionRadius, sc.Number); bag.Info->ExplosionRadius = sc.Number;
extra.bExplosive = true; extra.bExplosive = true;
} }
else if (def == DEF_Projectile && sc.Compare ("ExplosionDamage")) else if (def == DEF_Projectile && sc.Compare ("ExplosionDamage"))
{ {
sc.MustGetNumber (); sc.MustGetNumber ();
bag.Info->Meta.SetMetaInt(ACMETA_ExplosionDamage, sc.Number); bag.Info->ExplosionDamage = sc.Number;
extra.bExplosive = true; extra.bExplosive = true;
} }
else if (def == DEF_Projectile && sc.Compare ("DoNotHurtShooter")) else if (def == DEF_Projectile && sc.Compare ("DoNotHurtShooter"))
{ {
bag.Info->Meta.SetMetaInt(ACMETA_DontHurtShooter, true); bag.Info->DontHurtShooter = true;
} }
else if (def == DEF_Projectile && sc.Compare ("Damage")) else if (def == DEF_Projectile && sc.Compare ("Damage"))
{ {
@ -571,7 +571,7 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults,
else if (def == DEF_Pickup && sc.Compare ("PickupMessage")) else if (def == DEF_Pickup && sc.Compare ("PickupMessage"))
{ {
sc.MustGetString (); sc.MustGetString ();
bag.Info->Meta.SetMetaString(AIMETA_PickupMessage, sc.String); static_cast<PClassInventory *>(bag.Info)->PickupMessage = sc.String;
} }
else if (def == DEF_Pickup && sc.Compare ("Respawns")) else if (def == DEF_Pickup && sc.Compare ("Respawns"))
{ {

View file

@ -208,17 +208,7 @@ void FinishActor(const FScriptPosition &sc, PClassActor *info, Baggage &bag)
bag.statedef.MakeStateDefines(NULL); bag.statedef.MakeStateDefines(NULL);
if (bag.DropItemSet) if (bag.DropItemSet)
{ {
if (bag.DropItemList == NULL) info->DropItems = bag.DropItemList;
{
if (info->Meta.GetMetaInt (ACMETA_DropItems) != 0)
{
info->Meta.SetMetaInt (ACMETA_DropItems, 0);
}
}
else
{
info->Meta.SetMetaInt (ACMETA_DropItems, StoreDropItemChain(bag.DropItemList));
}
} }
if (info->IsDescendantOf (RUNTIME_CLASS(AInventory))) if (info->IsDescendantOf (RUNTIME_CLASS(AInventory)))
{ {

View file

@ -152,7 +152,7 @@ extern FStateExpressions StateParams;
// Extra info maintained while defining an actor. // Extra info maintained while defining an actor.
// //
//========================================================================== //==========================================================================
struct FDropItem; class DDropItem;
struct Baggage struct Baggage
{ {
@ -166,7 +166,7 @@ struct Baggage
int Lumpnum; int Lumpnum;
FStateDefinitions statedef; FStateDefinitions statedef;
FDropItem *DropItemList; DDropItem *DropItemList;
FScriptPosition ScriptPosition; FScriptPosition ScriptPosition;
}; };
@ -235,13 +235,6 @@ enum
{ {
ACMETA_BASE = 0x83000, ACMETA_BASE = 0x83000,
ACMETA_DropItems, // Int (index into DropItemList) ACMETA_DropItems, // Int (index into DropItemList)
ACMETA_ExplosionDamage,
ACMETA_ExplosionRadius,
ACMETA_DontHurtShooter,
ACMETA_MeleeSound,
ACMETA_MeleeDamage,
ACMETA_MissileName,
ACMETA_MissileHeight,
}; };

View file

@ -213,8 +213,8 @@ static void DoAttack (AActor *self, bool domelee, bool domissile,
DEFINE_ACTION_FUNCTION(AActor, A_MeleeAttack) DEFINE_ACTION_FUNCTION(AActor, A_MeleeAttack)
{ {
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
int MeleeDamage = self->GetClass()->Meta.GetMetaInt(ACMETA_MeleeDamage, 0); int MeleeDamage = self->GetClass()->MeleeDamage;
FSoundID MeleeSound = self->GetClass()->Meta.GetMetaInt(ACMETA_MeleeSound, 0); FSoundID MeleeSound = self->GetClass()->MeleeSound;
DoAttack(self, true, false, MeleeDamage, MeleeSound, NULL, 0); DoAttack(self, true, false, MeleeDamage, MeleeSound, NULL, 0);
return 0; return 0;
} }
@ -222,8 +222,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_MeleeAttack)
DEFINE_ACTION_FUNCTION(AActor, A_MissileAttack) DEFINE_ACTION_FUNCTION(AActor, A_MissileAttack)
{ {
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
const PClass *MissileType = PClass::FindClass(ENamedName(self->GetClass()->Meta.GetMetaInt(ACMETA_MissileName, NAME_None))); PClassActor *MissileType = PClass::FindActor(self->GetClass()->MissileName);
fixed_t MissileHeight = self->GetClass()->Meta.GetMetaFixed(ACMETA_MissileHeight, 32*FRACUNIT); fixed_t MissileHeight = self->GetClass()->MissileHeight;
DoAttack(self, false, true, 0, 0, MissileType, MissileHeight); DoAttack(self, false, true, 0, 0, MissileType, MissileHeight);
return 0; return 0;
} }
@ -231,10 +231,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_MissileAttack)
DEFINE_ACTION_FUNCTION(AActor, A_ComboAttack) DEFINE_ACTION_FUNCTION(AActor, A_ComboAttack)
{ {
PARAM_ACTION_PROLOGUE; PARAM_ACTION_PROLOGUE;
int MeleeDamage = self->GetClass()->Meta.GetMetaInt(ACMETA_MeleeDamage, 0); int MeleeDamage = self->GetClass()->MeleeDamage;
FSoundID MeleeSound = self->GetClass()->Meta.GetMetaInt(ACMETA_MeleeSound, 0); FSoundID MeleeSound = self->GetClass()->MeleeSound;
const PClass *MissileType = PClass::FindClass(ENamedName(self->GetClass()->Meta.GetMetaInt(ACMETA_MissileName, NAME_None))); PClassActor *MissileType = PClass::FindActor(self->GetClass()->MissileName);
fixed_t MissileHeight = self->GetClass()->Meta.GetMetaFixed(ACMETA_MissileHeight, 32*FRACUNIT); fixed_t MissileHeight = self->GetClass()->MissileHeight;
DoAttack(self, true, true, MeleeDamage, MeleeSound, MissileType, MissileHeight); DoAttack(self, true, true, MeleeDamage, MeleeSound, MissileType, MissileHeight);
return 0; return 0;
} }
@ -622,9 +622,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode)
if (damage < 0) // get parameters from metadata if (damage < 0) // get parameters from metadata
{ {
damage = self->GetClass()->Meta.GetMetaInt (ACMETA_ExplosionDamage, 128); damage = self->GetClass()->ExplosionDamage;
distance = self->GetClass()->Meta.GetMetaInt (ACMETA_ExplosionRadius, damage); distance = self->GetClass()->ExplosionRadius;
hurtSource = !self->GetClass()->Meta.GetMetaInt (ACMETA_DontHurtShooter); if (distance < 0)
{
distance = damage;
}
hurtSource = !self->GetClass()->DontHurtShooter;
alert = false; alert = false;
} }
else else

View file

@ -74,7 +74,7 @@
// Gets a class pointer and performs an error check for correct type // Gets a class pointer and performs an error check for correct type
// //
//========================================================================== //==========================================================================
static PClassActor *FindClassTentative(const char *name, const char *ancestor) static PClassActor *FindClassTentative(const char *name, PClass *ancestor)
{ {
// "" and "none" mean 'no class' // "" and "none" mean 'no class'
if (name == NULL || *name == 0 || !stricmp(name, "none")) if (name == NULL || *name == 0 || !stricmp(name, "none"))
@ -82,16 +82,26 @@ static PClassActor *FindClassTentative(const char *name, const char *ancestor)
return NULL; return NULL;
} }
PClass *anc = PClass::FindClass(ancestor); PClass *cls = ancestor->FindClassTentative(name);
assert(anc != NULL); // parent classes used here should always be natively defined assert(cls != NULL); // cls can not be NULL here
PClass *cls = anc->FindClassTentative(name); if (!cls->IsDescendantOf(ancestor))
assert (cls != NULL); // cls can not ne NULL here
if (!cls->IsDescendantOf(anc))
{ {
I_Error("%s does not inherit from %s\n", name, ancestor); I_Error("%s does not inherit from %s\n", name, ancestor);
} }
return static_cast<PClassActor *>(cls); return static_cast<PClassActor *>(cls);
} }
static AAmmo::MetaClass *FindClassTentativeAmmo(const char *name)
{
return static_cast<AAmmo::MetaClass *>(FindClassTentative(name, RUNTIME_CLASS(AAmmo)));
}
static AWeapon::MetaClass *FindClassTentativeWeapon(const char *name)
{
return static_cast<AWeapon::MetaClass *>(FindClassTentative(name, RUNTIME_CLASS(AWeapon)));
}
static APowerup::MetaClass *FindClassTentativePowerup(const char *name)
{
return static_cast<APowerup::MetaClass *>(FindClassTentative(name, RUNTIME_CLASS(APowerup)));
}
//=========================================================================== //===========================================================================
// //
@ -144,7 +154,7 @@ void HandleDeprecatedFlags(AActor *defaults, PClassActor *info, bool set, int in
case DEPF_PICKUPFLASH: case DEPF_PICKUPFLASH:
if (set) if (set)
{ {
static_cast<AInventory*>(defaults)->PickupFlash = FindClassTentative("PickupFlash", "Actor"); static_cast<AInventory*>(defaults)->PickupFlash = FindClassTentative("PickupFlash", RUNTIME_CLASS(AActor));
} }
else else
{ {
@ -293,10 +303,6 @@ DEFINE_PROPERTY(skip_super, 0, Actor)
} }
memcpy (defaults, GetDefault<AActor>(), sizeof(AActor)); memcpy (defaults, GetDefault<AActor>(), sizeof(AActor));
if (bag.DropItemList != NULL)
{
FreeDropItemChain (bag.DropItemList);
}
ResetBaggage (&bag, RUNTIME_CLASS(AActor)); ResetBaggage (&bag, RUNTIME_CLASS(AActor));
} }
@ -324,7 +330,8 @@ DEFINE_PROPERTY(health, I, Actor)
DEFINE_PROPERTY(gibhealth, I, Actor) DEFINE_PROPERTY(gibhealth, I, Actor)
{ {
PROP_INT_PARM(id, 0); PROP_INT_PARM(id, 0);
info->Meta.SetMetaInt (AMETA_GibHealth, id); assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
static_cast<PClassActor *>(info)->GibHealth = id;
} }
//========================================================================== //==========================================================================
@ -333,7 +340,8 @@ DEFINE_PROPERTY(gibhealth, I, Actor)
DEFINE_PROPERTY(woundhealth, I, Actor) DEFINE_PROPERTY(woundhealth, I, Actor)
{ {
PROP_INT_PARM(id, 0); PROP_INT_PARM(id, 0);
info->Meta.SetMetaInt (AMETA_WoundHealth, id); assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
static_cast<PClassActor *>(info)->WoundHealth = id;
} }
//========================================================================== //==========================================================================
@ -556,7 +564,8 @@ DEFINE_PROPERTY(activesound, S, Actor)
DEFINE_PROPERTY(howlsound, S, Actor) DEFINE_PROPERTY(howlsound, S, Actor)
{ {
PROP_STRING_PARM(str, 0); PROP_STRING_PARM(str, 0);
info->Meta.SetMetaInt (AMETA_HowlSound, S_FindSound(str)); assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
static_cast<PClassActor *>(info)->HowlSound = str;
} }
//========================================================================== //==========================================================================
@ -573,20 +582,20 @@ DEFINE_PROPERTY(dropitem, S_i_i, Actor)
bag.DropItemList = NULL; bag.DropItemList = NULL;
} }
FDropItem *di = new FDropItem; DDropItem *di = new DDropItem;
di->Name =type; di->Name = type;
di->probability=255; di->Probability = 255;
di->amount=-1; di->Amount = -1;
if (PROP_PARM_COUNT > 1) if (PROP_PARM_COUNT > 1)
{ {
PROP_INT_PARM(prob, 1); PROP_INT_PARM(prob, 1);
di->probability = prob; di->Probability = prob;
if (PROP_PARM_COUNT > 2) if (PROP_PARM_COUNT > 2)
{ {
PROP_INT_PARM(amt, 2); PROP_INT_PARM(amt, 2);
di->amount = amt; di->Amount = amt;
} }
} }
di->Next = bag.DropItemList; di->Next = bag.DropItemList;
@ -637,7 +646,8 @@ DEFINE_PROPERTY(alpha, F, Actor)
DEFINE_PROPERTY(obituary, S, Actor) DEFINE_PROPERTY(obituary, S, Actor)
{ {
PROP_STRING_PARM(str, 0); PROP_STRING_PARM(str, 0);
info->Meta.SetMetaString (AMETA_Obituary, str); assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
static_cast<PClassActor *>(info)->Obituary = str;
} }
//========================================================================== //==========================================================================
@ -646,7 +656,8 @@ DEFINE_PROPERTY(obituary, S, Actor)
DEFINE_PROPERTY(hitobituary, S, Actor) DEFINE_PROPERTY(hitobituary, S, Actor)
{ {
PROP_STRING_PARM(str, 0); PROP_STRING_PARM(str, 0);
info->Meta.SetMetaString (AMETA_HitObituary, str); assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
static_cast<PClassActor *>(info)->HitObituary = str;
} }
//========================================================================== //==========================================================================
@ -654,7 +665,8 @@ DEFINE_PROPERTY(hitobituary, S, Actor)
//========================================================================== //==========================================================================
DEFINE_PROPERTY(donthurtshooter, 0, Actor) DEFINE_PROPERTY(donthurtshooter, 0, Actor)
{ {
info->Meta.SetMetaInt (ACMETA_DontHurtShooter, true); assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
static_cast<PClassActor *>(info)->DontHurtShooter = true;
} }
//========================================================================== //==========================================================================
@ -663,7 +675,8 @@ DEFINE_PROPERTY(donthurtshooter, 0, Actor)
DEFINE_PROPERTY(explosionradius, I, Actor) DEFINE_PROPERTY(explosionradius, I, Actor)
{ {
PROP_INT_PARM(id, 0); PROP_INT_PARM(id, 0);
info->Meta.SetMetaInt (ACMETA_ExplosionRadius, id); assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
static_cast<PClassActor *>(info)->ExplosionRadius = id;
} }
//========================================================================== //==========================================================================
@ -672,7 +685,8 @@ DEFINE_PROPERTY(explosionradius, I, Actor)
DEFINE_PROPERTY(explosiondamage, I, Actor) DEFINE_PROPERTY(explosiondamage, I, Actor)
{ {
PROP_INT_PARM(id, 0); PROP_INT_PARM(id, 0);
info->Meta.SetMetaInt (ACMETA_ExplosionDamage, id); assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
static_cast<PClassActor *>(info)->ExplosionDamage = id;
} }
//========================================================================== //==========================================================================
@ -681,9 +695,8 @@ DEFINE_PROPERTY(explosiondamage, I, Actor)
DEFINE_PROPERTY(deathheight, F, Actor) DEFINE_PROPERTY(deathheight, F, Actor)
{ {
PROP_FIXED_PARM(h, 0); PROP_FIXED_PARM(h, 0);
// AActor::Die() uses a height of 0 to mean "cut the height to 1/4", assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
// so if a height of 0 is desired, store it as -1. static_cast<PClassActor *>(info)->DeathHeight = MAX(0, h);
info->Meta.SetMetaFixed (AMETA_DeathHeight, h <= 0 ? -1 : h);
} }
//========================================================================== //==========================================================================
@ -692,8 +705,8 @@ DEFINE_PROPERTY(deathheight, F, Actor)
DEFINE_PROPERTY(burnheight, F, Actor) DEFINE_PROPERTY(burnheight, F, Actor)
{ {
PROP_FIXED_PARM(h, 0); PROP_FIXED_PARM(h, 0);
// The note above for AMETA_DeathHeight also applies here. assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
info->Meta.SetMetaFixed (AMETA_BurnHeight, h <= 0 ? -1 : h); static_cast<PClassActor *>(info)->BurnHeight = MAX(0, h);
} }
//========================================================================== //==========================================================================
@ -720,7 +733,8 @@ DEFINE_PROPERTY(meleethreshold, F, Actor)
DEFINE_PROPERTY(meleedamage, I, Actor) DEFINE_PROPERTY(meleedamage, I, Actor)
{ {
PROP_INT_PARM(id, 0); PROP_INT_PARM(id, 0);
info->Meta.SetMetaInt (ACMETA_MeleeDamage, id); assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
static_cast<PClassActor *>(info)->MeleeDamage = id;
} }
//========================================================================== //==========================================================================
@ -738,7 +752,8 @@ DEFINE_PROPERTY(meleerange, F, Actor)
DEFINE_PROPERTY(meleesound, S, Actor) DEFINE_PROPERTY(meleesound, S, Actor)
{ {
PROP_STRING_PARM(str, 0); PROP_STRING_PARM(str, 0);
info->Meta.SetMetaInt (ACMETA_MeleeSound, S_FindSound(str)); assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
static_cast<PClassActor *>(info)->MeleeSound = str;
} }
//========================================================================== //==========================================================================
@ -747,7 +762,8 @@ DEFINE_PROPERTY(meleesound, S, Actor)
DEFINE_PROPERTY(missiletype, S, Actor) DEFINE_PROPERTY(missiletype, S, Actor)
{ {
PROP_STRING_PARM(str, 0); PROP_STRING_PARM(str, 0);
info->Meta.SetMetaInt (ACMETA_MissileName, FName(str)); assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
static_cast<PClassActor *>(info)->MissileName = str;
} }
//========================================================================== //==========================================================================
@ -756,7 +772,8 @@ DEFINE_PROPERTY(missiletype, S, Actor)
DEFINE_PROPERTY(missileheight, F, Actor) DEFINE_PROPERTY(missileheight, F, Actor)
{ {
PROP_FIXED_PARM(id, 0); PROP_FIXED_PARM(id, 0);
info->Meta.SetMetaFixed (ACMETA_MissileHeight, id); assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
static_cast<PClassActor *>(info)->MissileHeight = id;
} }
//========================================================================== //==========================================================================
@ -826,7 +843,8 @@ DEFINE_PROPERTY(bloodcolor, C, Actor)
PalEntry pe = color; PalEntry pe = color;
pe.a = CreateBloodTranslation(pe); pe.a = CreateBloodTranslation(pe);
info->Meta.SetMetaInt (AMETA_BloodColor, pe); assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
static_cast<PClassActor *>(info)->BloodColor = pe;
} }
@ -839,23 +857,26 @@ DEFINE_PROPERTY(bloodtype, Sss, Actor)
PROP_STRING_PARM(str1, 1) PROP_STRING_PARM(str1, 1)
PROP_STRING_PARM(str2, 2) PROP_STRING_PARM(str2, 2)
assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
PClassActor *ainfo = static_cast<PClassActor *>(info);
FName blood = str; FName blood = str;
// normal blood // normal blood
info->Meta.SetMetaInt (AMETA_BloodType, blood); ainfo->BloodType = blood;
if (PROP_PARM_COUNT > 1) if (PROP_PARM_COUNT > 1)
{ {
blood = str1; blood = str1;
} }
// blood splatter // blood splatter
info->Meta.SetMetaInt (AMETA_BloodType2, blood); ainfo->BloodType2 = blood;
if (PROP_PARM_COUNT > 2) if (PROP_PARM_COUNT > 2)
{ {
blood = str2; blood = str2;
} }
// axe blood // axe blood
info->Meta.SetMetaInt (AMETA_BloodType3, blood); ainfo->BloodType3 = blood;
} }
//========================================================================== //==========================================================================
@ -1000,7 +1021,8 @@ DEFINE_PROPERTY(maxdropoffheight, F, Actor)
DEFINE_PROPERTY(poisondamage, I, Actor) DEFINE_PROPERTY(poisondamage, I, Actor)
{ {
PROP_INT_PARM(i, 0); PROP_INT_PARM(i, 0);
info->Meta.SetMetaInt (AMETA_PoisonDamage, i); assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
static_cast<PClassActor *>(info)->PoisonDamage = i;
} }
//========================================================================== //==========================================================================
@ -1009,7 +1031,8 @@ DEFINE_PROPERTY(poisondamage, I, Actor)
DEFINE_PROPERTY(fastspeed, F, Actor) DEFINE_PROPERTY(fastspeed, F, Actor)
{ {
PROP_FIXED_PARM(i, 0); PROP_FIXED_PARM(i, 0);
info->Meta.SetMetaFixed (AMETA_FastSpeed, i); assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
static_cast<PClassActor *>(info)->FastSpeed = i;
} }
//========================================================================== //==========================================================================
@ -1018,7 +1041,8 @@ DEFINE_PROPERTY(fastspeed, F, Actor)
DEFINE_PROPERTY(radiusdamagefactor, F, Actor) DEFINE_PROPERTY(radiusdamagefactor, F, Actor)
{ {
PROP_FIXED_PARM(i, 0); PROP_FIXED_PARM(i, 0);
info->Meta.SetMetaFixed (AMETA_RDFactor, i); assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
static_cast<PClassActor *>(info)->RDFactor = i;
} }
//========================================================================== //==========================================================================
@ -1027,7 +1051,8 @@ DEFINE_PROPERTY(radiusdamagefactor, F, Actor)
DEFINE_PROPERTY(cameraheight, F, Actor) DEFINE_PROPERTY(cameraheight, F, Actor)
{ {
PROP_FIXED_PARM(i, 0); PROP_FIXED_PARM(i, 0);
info->Meta.SetMetaFixed (AMETA_CameraHeight, i); assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
static_cast<PClassActor *>(info)->CameraHeight = i;
} }
//========================================================================== //==========================================================================
@ -1135,7 +1160,8 @@ DEFINE_CLASS_PROPERTY(backpackmaxamount, I, Ammo)
DEFINE_CLASS_PROPERTY(dropamount, I, Ammo) DEFINE_CLASS_PROPERTY(dropamount, I, Ammo)
{ {
PROP_INT_PARM(i, 0); PROP_INT_PARM(i, 0);
info->Meta.SetMetaInt (AIMETA_DropAmount, i); assert(info->IsKindOf(RUNTIME_CLASS(PClassAmmo)));
static_cast<PClassAmmo *>(info)->DropAmount = i;
} }
//========================================================================== //==========================================================================
@ -1317,7 +1343,7 @@ DEFINE_CLASS_PROPERTY(defmaxamount, 0, Inventory)
DEFINE_CLASS_PROPERTY(pickupflash, S, Inventory) DEFINE_CLASS_PROPERTY(pickupflash, S, Inventory)
{ {
PROP_STRING_PARM(str, 0); PROP_STRING_PARM(str, 0);
defaults->PickupFlash = FindClassTentative(str, "Actor"); defaults->PickupFlash = FindClassTentative(str, RUNTIME_CLASS(AActor));
} }
//========================================================================== //==========================================================================
@ -1326,7 +1352,8 @@ DEFINE_CLASS_PROPERTY(pickupflash, S, Inventory)
DEFINE_CLASS_PROPERTY(pickupmessage, T, Inventory) DEFINE_CLASS_PROPERTY(pickupmessage, T, Inventory)
{ {
PROP_STRING_PARM(str, 0); PROP_STRING_PARM(str, 0);
info->Meta.SetMetaString(AIMETA_PickupMessage, str); assert(info->IsKindOf(RUNTIME_CLASS(PClassInventory)));
static_cast<PClassInventory *>(info)->PickupMessage = str;
} }
//========================================================================== //==========================================================================
@ -1369,7 +1396,8 @@ DEFINE_CLASS_PROPERTY(usesound, S, Inventory)
DEFINE_CLASS_PROPERTY(givequest, I, Inventory) DEFINE_CLASS_PROPERTY(givequest, I, Inventory)
{ {
PROP_INT_PARM(i, 0); PROP_INT_PARM(i, 0);
info->Meta.SetMetaInt(AIMETA_GiveQuest, i); assert(info->IsKindOf(RUNTIME_CLASS(PClassInventory)));
static_cast<PClassInventory *>(info)->GiveQuest = i;
} }
//========================================================================== //==========================================================================
@ -1379,8 +1407,9 @@ DEFINE_CLASS_PROPERTY(lowmessage, IT, Health)
{ {
PROP_INT_PARM(i, 0); PROP_INT_PARM(i, 0);
PROP_STRING_PARM(str, 1); PROP_STRING_PARM(str, 1);
info->Meta.SetMetaInt(AIMETA_LowHealth, i); assert(info->IsKindOf(RUNTIME_CLASS(PClassHealth)));
info->Meta.SetMetaString(AIMETA_LowHealthMessage, str); static_cast<PClassHealth *>(info)->LowHealth = i;
static_cast<PClassHealth *>(info)->LowHealthMessage = str;
} }
//========================================================================== //==========================================================================
@ -1407,7 +1436,8 @@ DEFINE_CLASS_PROPERTY(number, I, PuzzleItem)
DEFINE_CLASS_PROPERTY(failmessage, T, PuzzleItem) DEFINE_CLASS_PROPERTY(failmessage, T, PuzzleItem)
{ {
PROP_STRING_PARM(str, 0); PROP_STRING_PARM(str, 0);
info->Meta.SetMetaString(AIMETA_PuzzFailMessage, str); assert(info->IsKindOf(RUNTIME_CLASS(PClassPuzzleItem)));
static_cast<PClassPuzzleItem *>(info)->PuzzFailMessage = str;
} }
//========================================================================== //==========================================================================
@ -1444,7 +1474,7 @@ DEFINE_CLASS_PROPERTY(ammotype, S, Weapon)
{ {
PROP_STRING_PARM(str, 0); PROP_STRING_PARM(str, 0);
if (!stricmp(str, "none") || *str == 0) defaults->AmmoType1 = NULL; if (!stricmp(str, "none") || *str == 0) defaults->AmmoType1 = NULL;
else defaults->AmmoType1 = FindClassTentative(str, "Ammo"); else defaults->AmmoType1 = FindClassTentativeAmmo(str);
} }
//========================================================================== //==========================================================================
@ -1454,7 +1484,7 @@ DEFINE_CLASS_PROPERTY(ammotype1, S, Weapon)
{ {
PROP_STRING_PARM(str, 0); PROP_STRING_PARM(str, 0);
if (!stricmp(str, "none") || *str == 0) defaults->AmmoType1 = NULL; if (!stricmp(str, "none") || *str == 0) defaults->AmmoType1 = NULL;
else defaults->AmmoType1 = FindClassTentative(str, "Ammo"); else defaults->AmmoType1 = FindClassTentativeAmmo(str);
} }
//========================================================================== //==========================================================================
@ -1464,7 +1494,7 @@ DEFINE_CLASS_PROPERTY(ammotype2, S, Weapon)
{ {
PROP_STRING_PARM(str, 0); PROP_STRING_PARM(str, 0);
if (!stricmp(str, "none") || *str == 0) defaults->AmmoType1 = NULL; if (!stricmp(str, "none") || *str == 0) defaults->AmmoType1 = NULL;
else defaults->AmmoType2 = FindClassTentative(str, "Ammo"); else defaults->AmmoType2 = FindClassTentativeAmmo(str);
} }
//========================================================================== //==========================================================================
@ -1535,7 +1565,7 @@ DEFINE_CLASS_PROPERTY(selectionorder, I, Weapon)
DEFINE_CLASS_PROPERTY(sisterweapon, S, Weapon) DEFINE_CLASS_PROPERTY(sisterweapon, S, Weapon)
{ {
PROP_STRING_PARM(str, 0); PROP_STRING_PARM(str, 0);
defaults->SisterWeaponType = FindClassTentative(str, "Weapon"); defaults->SisterWeaponType = FindClassTentativeWeapon(str);
} }
//========================================================================== //==========================================================================
@ -1562,7 +1592,8 @@ DEFINE_CLASS_PROPERTY(yadjust, F, Weapon)
DEFINE_CLASS_PROPERTY(slotnumber, I, Weapon) DEFINE_CLASS_PROPERTY(slotnumber, I, Weapon)
{ {
PROP_INT_PARM(i, 0); PROP_INT_PARM(i, 0);
info->Meta.SetMetaInt(AWMETA_SlotNumber, i); assert(info->IsKindOf(RUNTIME_CLASS(PClassWeapon)));
static_cast<PClassWeapon *>(info)->SlotNumber = i;
} }
//========================================================================== //==========================================================================
@ -1571,7 +1602,8 @@ DEFINE_CLASS_PROPERTY(slotnumber, I, Weapon)
DEFINE_CLASS_PROPERTY(slotpriority, F, Weapon) DEFINE_CLASS_PROPERTY(slotpriority, F, Weapon)
{ {
PROP_FIXED_PARM(i, 0); PROP_FIXED_PARM(i, 0);
info->Meta.SetMetaFixed(AWMETA_SlotPriority, i); assert(info->IsKindOf(RUNTIME_CLASS(PClassWeapon)));
static_cast<PClassWeapon *>(info)->SlotPriority = i;
} }
//========================================================================== //==========================================================================
@ -1589,7 +1621,7 @@ DEFINE_CLASS_PROPERTY(number, I, WeaponPiece)
DEFINE_CLASS_PROPERTY(weapon, S, WeaponPiece) DEFINE_CLASS_PROPERTY(weapon, S, WeaponPiece)
{ {
PROP_STRING_PARM(str, 0); PROP_STRING_PARM(str, 0);
defaults->WeaponClass = FindClassTentative(str, "Weapon"); defaults->WeaponClass = FindClassTentativeWeapon(str);
} }
//========================================================================== //==========================================================================
@ -1777,7 +1809,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, type, S, PowerupGiver)
{ {
FString st; FString st;
st.Format("%s%s", strnicmp(str, "power", 5)? "Power" : "", str); st.Format("%s%s", strnicmp(str, "power", 5)? "Power" : "", str);
cls = FindClassTentative(st, "Powerup"); cls = FindClassTentativePowerup(st);
} }
defaults->PowerupType = cls; defaults->PowerupType = cls;
@ -1795,7 +1827,8 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, type, S, PowerupGiver)
DEFINE_CLASS_PROPERTY_PREFIX(player, displayname, S, PlayerPawn) DEFINE_CLASS_PROPERTY_PREFIX(player, displayname, S, PlayerPawn)
{ {
PROP_STRING_PARM(str, 0); PROP_STRING_PARM(str, 0);
info->Meta.SetMetaString (APMETA_DisplayName, str); assert(info->IsKindOf(RUNTIME_CLASS(PClassPlayerPawn)));
static_cast<PClassPlayerPawn *>(info)->DisplayName = str;
} }
//========================================================================== //==========================================================================
@ -1807,7 +1840,8 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, soundclass, S, PlayerPawn)
FString tmp = str; FString tmp = str;
tmp.ReplaceChars (' ', '_'); tmp.ReplaceChars (' ', '_');
info->Meta.SetMetaString (APMETA_SoundClass, tmp); assert(info->IsKindOf(RUNTIME_CLASS(PClassPlayerPawn)));
static_cast<PClassPlayerPawn *>(info)->SoundClass = tmp;
} }
//========================================================================== //==========================================================================
@ -1838,7 +1872,8 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, face, S, PlayerPawn)
tmp.GetChars(), info->TypeName.GetChars ()); tmp.GetChars(), info->TypeName.GetChars ());
} }
info->Meta.SetMetaString (APMETA_Face, tmp); assert(info->IsKindOf(RUNTIME_CLASS(PClassPlayerPawn)));
static_cast<PClassPlayerPawn *>(info)->Face = tmp;
} }
//========================================================================== //==========================================================================
@ -1852,7 +1887,9 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, colorrange, I_I, PlayerPawn)
if (start > end) if (start > end)
swap (start, end); swap (start, end);
info->Meta.SetMetaInt (APMETA_ColorRange, (start & 255) | ((end & 255) << 8)); assert(info->IsKindOf(RUNTIME_CLASS(PClassPlayerPawn)));
static_cast<PClassPlayerPawn *>(info)->ColorRangeStart = start;
static_cast<PClassPlayerPawn *>(info)->ColorRangeEnd = end;
} }
//========================================================================== //==========================================================================
@ -2036,15 +2073,15 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, startitem, S_i, PlayerPawn)
bag.DropItemList = NULL; bag.DropItemList = NULL;
} }
FDropItem * di=new FDropItem; DDropItem *di = new DDropItem;
di->Name = str; di->Name = str;
di->probability = 255; di->Probability = 255;
di->amount = 1; di->Amount = 1;
if (PROP_PARM_COUNT > 1) if (PROP_PARM_COUNT > 1)
{ {
PROP_INT_PARM(amt, 1); PROP_INT_PARM(amt, 1);
di->amount = amt; di->Amount = amt;
} }
di->Next = bag.DropItemList; di->Next = bag.DropItemList;
bag.DropItemList = di; bag.DropItemList = di;
@ -2056,7 +2093,8 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, startitem, S_i, PlayerPawn)
DEFINE_CLASS_PROPERTY_PREFIX(player, invulnerabilitymode, S, PlayerPawn) DEFINE_CLASS_PROPERTY_PREFIX(player, invulnerabilitymode, S, PlayerPawn)
{ {
PROP_STRING_PARM(str, 0); PROP_STRING_PARM(str, 0);
info->Meta.SetMetaInt (APMETA_InvulMode, (FName)str); assert(info->IsKindOf(RUNTIME_CLASS(PClassPlayerPawn)));
static_cast<PClassPlayerPawn *>(info)->InvulMode = str;
} }
//========================================================================== //==========================================================================
@ -2065,7 +2103,8 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, invulnerabilitymode, S, PlayerPawn)
DEFINE_CLASS_PROPERTY_PREFIX(player, healradiustype, S, PlayerPawn) DEFINE_CLASS_PROPERTY_PREFIX(player, healradiustype, S, PlayerPawn)
{ {
PROP_STRING_PARM(str, 0); PROP_STRING_PARM(str, 0);
info->Meta.SetMetaInt (APMETA_HealingRadius, (FName)str); assert(info->IsKindOf(RUNTIME_CLASS(PClassPlayerPawn)));
static_cast<PClassPlayerPawn *>(info)->HealingRadiusType = str;
} }
//========================================================================== //==========================================================================
@ -2073,10 +2112,11 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, healradiustype, S, PlayerPawn)
//========================================================================== //==========================================================================
DEFINE_CLASS_PROPERTY_PREFIX(player, hexenarmor, FFFFF, PlayerPawn) DEFINE_CLASS_PROPERTY_PREFIX(player, hexenarmor, FFFFF, PlayerPawn)
{ {
for (int i=0;i<5;i++) assert(info->IsKindOf(RUNTIME_CLASS(PClassPlayerPawn)));
for (int i = 0; i < 5; i++)
{ {
PROP_FIXED_PARM(val, i); PROP_FIXED_PARM(val, i);
info->Meta.SetMetaFixed (APMETA_Hexenarmor0+i, val); static_cast<PClassPlayerPawn *>(info)->HexenArmor[i] = val;
} }
} }
@ -2087,6 +2127,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, weaponslot, ISsssssssssssssssssssssssssssss
{ {
PROP_INT_PARM(slot, 0); PROP_INT_PARM(slot, 0);
assert(info->IsKindOf(RUNTIME_CLASS(PClassPlayerPawn)));
if (slot < 0 || slot > 9) if (slot < 0 || slot > 9)
{ {
I_Error("Slot must be between 0 and 9."); I_Error("Slot must be between 0 and 9.");
@ -2100,7 +2141,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, weaponslot, ISsssssssssssssssssssssssssssss
PROP_STRING_PARM(str, i); PROP_STRING_PARM(str, i);
weapons << ' ' << str; weapons << ' ' << str;
} }
info->Meta.SetMetaString(APMETA_Slot0 + slot, &weapons[1]); static_cast<PClassPlayerPawn *>(info)->Slot[slot] = &weapons[1];
} }
} }