- 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 FStrifeDialogueNode;
enum
{
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 *>
class DDropItem : public DObject
{
DECLARE_CLASS(DDropItem, DObject)
HAS_OBJECT_POINTERS
public:
~FDropItemPtrArray();
DDropItem *Next;
FName Name;
int Probability;
int Amount;
};
extern FDropItemPtrArray DropItemList;
void FreeDropItemChain(FDropItem *chain);
int StoreDropItemChain(FDropItem *chain);
// Map Object definition.
class AActor : public DThinker
@ -556,7 +525,7 @@ public:
return (AActor *)(RUNTIME_TYPE(this)->Defaults);
}
FDropItem *GetDropItems();
DDropItem *GetDropItems() const;
// Return true if the monster should use a missile attack, false for melee
bool SuggestMissileAttack (fixed_t dist);
@ -702,7 +671,11 @@ public:
void Crash();
// 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.
bool CountsAsKill() const

View file

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

View file

@ -2099,7 +2099,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
case DEM_SUMMONFRIEND2:
case DEM_SUMMONFOE2:
{
const PClass *typeinfo;
PClassActor *typeinfo;
int angle = 0;
SWORD tid = 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);
}
typeinfo = PClass::FindClass (s);
if (typeinfo != NULL && typeinfo->IsKindOf(RUNTIME_CLASS(PClassActor)))
typeinfo = PClass::FindActor(s);
if (typeinfo != NULL)
{
AActor *source = players[player].mo;
if (source != NULL)
@ -2318,7 +2318,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
case DEM_MORPHEX:
{
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)
{
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)
{
PClassActor *wpn = Net_ReadWeapon(stream);
PClassWeapon *wpn = Net_ReadWeapon(stream);
players[player].weapons.AddSlot(slot, wpn, player == consoleplayer);
}
}
@ -2392,7 +2392,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
case DEM_ADDSLOT:
{
int slot = ReadByte(stream);
PClassActor *wpn = Net_ReadWeapon(stream);
PClassWeapon *wpn = Net_ReadWeapon(stream);
players[player].weapons.AddSlot(slot, wpn, player == consoleplayer);
}
break;
@ -2400,7 +2400,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
case DEM_ADDSLOTDEFAULT:
{
int slot = ReadByte(stream);
PClassActor *wpn = Net_ReadWeapon(stream);
PClassWeapon *wpn = Net_ReadWeapon(stream);
players[player].weapons.AddSlotDefault(slot, wpn, player == consoleplayer);
}
break;

View file

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

View file

@ -44,38 +44,30 @@
//Added by MC:
#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 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
{
DECLARE_CLASS (APlayerPawn, AActor)
DECLARE_CLASS_WITH_META(APlayerPawn, AActor, PClassPlayerPawn)
HAS_OBJECT_POINTERS
public:
virtual void Serialize (FArchive &arc);
@ -431,7 +423,7 @@ public:
bool CheckSkin (int skin);
const PClass *Type;
PClassPlayerPawn *Type;
DWORD Flags;
TArray<int> Skins;
};

View file

@ -60,134 +60,6 @@ ClassReg DObject::RegistrationInfo =
};
_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)
{
// This is by no means speed-optimized. But it's an informational console

View file

@ -80,56 +80,6 @@ class DPillar;
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_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
@ -140,6 +90,12 @@ enum
{
CLASSREG_PClass,
CLASSREG_PClassActor,
CLASSREG_PClassInventory,
CLASSREG_PClassAmmo,
CLASSREG_PClassHealth,
CLASSREG_PClassPuzzleItem,
CLASSREG_PClassWeapon,
CLASSREG_PClassPlayerPawn
};
struct ClassReg
@ -149,8 +105,8 @@ struct ClassReg
ClassReg *ParentType;
const size_t *Pointers;
void (*ConstructNative)(void *);
unsigned int SizeOf:31;
unsigned int MetaClassNum:1;
unsigned int SizeOf:29;
unsigned int MetaClassNum:3;
PClass *RegisterClass();
};
@ -159,7 +115,7 @@ enum EInPlace { EC_InPlace };
#define DECLARE_ABSTRACT_CLASS(cls,parent) \
public: \
virtual PClass *StaticType() const { return RegistrationInfo.MyClass; } \
virtual PClass *StaticType() const; \
static ClassReg RegistrationInfo, * const RegistrationInfoPtr; \
private: \
typedef parent Super; \
@ -205,7 +161,8 @@ protected: \
create, \
sizeof(cls), \
cls::MetaClassNum }; \
_DECLARE_TI(cls)
_DECLARE_TI(cls) \
PClass *cls::StaticType() const { return RegistrationInfo.MyClass; }
#define _IMP_CREATE_OBJ(cls) \
void cls::InPlaceConstructor(void *mem) { new((EInPlace *)mem) cls; }

View file

@ -38,6 +38,8 @@
#include "templates.h"
#include "autosegs.h"
#include "v_text.h"
#include "a_pickups.h"
#include "d_player.h"
IMPLEMENT_POINTY_CLASS(PClass)
DECLARE_POINTER(ParentClass)
@ -121,6 +123,7 @@ PClass::PClass()
Defaults = NULL;
bRuntimeClass = false;
ClassIndex = ~0;
ConstructNative = NULL;
}
PClass::~PClass()
@ -135,6 +138,18 @@ PClass::~PClass()
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.
// Or this may be a recursive call for a previously created class.
if (MyClass != NULL)
@ -145,30 +160,35 @@ PClass *ClassReg::RegisterClass()
// Add type to list
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");
}
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;
PClass::m_Types.Push(cls);
cls->TypeName = FName(Name+1);
if (ParentType != NULL)
{
cls->ParentClass = ParentType->RegisterClass();
}
cls->Size = SizeOf;
cls->Pointers = Pointers;
cls->ConstructNative = ConstructNative;
cls->InsertIntoHash();
if (ParentType != NULL)
{
cls->ParentClass = ParentType->RegisterClass();
}
return cls;
}
@ -231,7 +251,7 @@ PClass *PClass::FindClass (FName zaname)
}
// Create a new object that this class represents
DObject *PClass::CreateNew () const
DObject *PClass::CreateNew() const
{
BYTE *mem = (BYTE *)M_Malloc (Size);
assert (mem != NULL);
@ -247,6 +267,23 @@ DObject *PClass::CreateNew () const
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
PClass *PClass::CreateDerivedClass (FName name, unsigned int size)
{
@ -275,34 +312,16 @@ PClass *PClass::CreateDerivedClass (FName name, unsigned int size)
}
type->TypeName = name;
type->ParentClass = this;
type->Size = size;
type->Pointers = NULL;
type->ConstructNative = ConstructNative;
type->bRuntimeClass = true;
Derive(type);
if (!notnew)
{
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();
}
// If this class has an actor info, then any classes derived from it
// also need an actor info.
// If this class is for an actor, push it onto the RuntimeActors stack.
if (type->IsKindOf(RUNTIME_CLASS(PClassActor)))
{
m_RuntimeActors.Push(static_cast<PClassActor *>(type));
@ -351,17 +370,13 @@ PClass *PClass::FindClassTentative (FName name)
break;
}
}
PClass *type = new PClassActor;
PClass *type = static_cast<PClass *>(GetClass()->CreateNew());
DPrintf("Creating placeholder class %s : %s\n", name.GetChars(), TypeName.GetChars());
type->TypeName = name;
type->ParentClass = this;
type->Size = -1;
type->Pointers = NULL;
type->ConstructNative = NULL;
type->ClassIndex = m_Types.Push (type);
type->Defaults = NULL;
type->FlatPointers = NULL;
type->bRuntimeClass = true;
type->InsertIntoHash();
return type;

View file

@ -153,6 +153,8 @@ class PClass : public DObject
{
DECLARE_CLASS(PClass, DObject);
HAS_OBJECT_POINTERS;
protected:
virtual void Derive(PClass *newclass);
public:
static void StaticInit ();
static void StaticShutdown ();
@ -164,7 +166,6 @@ public:
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
PClass *HashNext;
FMetaTable Meta;
BYTE *Defaults;
bool bRuntimeClass; // class was defined at run-time, not compile-time
unsigned short ClassIndex;

View file

@ -180,8 +180,8 @@ static void SpawnFly(AActor *self, const PClass *spawntype, FSoundID sound)
FName SpawnName;
FDropItem *di; // di will be our drop item list iterator
FDropItem *drop; // while drop stays as the reference point.
DDropItem *di; // di will be our drop item list iterator
DDropItem *drop; // while drop stays as the reference point.
int n = 0;
// 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->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;
@ -210,7 +210,7 @@ static void SpawnFly(AActor *self, const PClass *spawntype, FSoundID sound)
{
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))
{

View file

@ -390,7 +390,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMissile)
if (!weapon->DepleteAmmo (weapon->bAltFire))
return 0;
}
P_SpawnPlayerMissile (self, PClass::FindClass("Rocket"));
P_SpawnPlayerMissile (self, PClass::FindActor("Rocket"));
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;
}
@ -537,7 +537,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireBFG)
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;
}
@ -619,7 +619,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BFGsound)
DEFINE_ACTION_FUNCTION(AActor, A_FireOldBFG)
{
PARAM_ACTION_PROLOGUE;
const PClass * plasma[] = {PClass::FindClass("PlasmaBall1"), PClass::FindClass("PlasmaBall2")};
PClassActor *plasma[] = { PClass::FindActor("PlasmaBall1"), PClass::FindActor("PlasmaBall2") };
AActor * mo = NULL;
player_t *player;

View file

@ -65,7 +65,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_Tracer)
return 0;
// 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,
self->y - self->vely, self->z, ALLOW_REPLACE);

View file

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

View file

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

View file

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

View file

@ -48,7 +48,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_BatSpawn)
delta = self->args[1];
if (delta==0) delta=1;
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)
{
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))
return 0;
}
AActor * missile = P_SpawnPlayerMissile (self, 0,0,0, PClass::FindClass ("HolyMissile"), self->angle, &linetarget);
if (missile != NULL) missile->tracer = linetarget;
AActor *missile = P_SpawnPlayerMissile (self, 0,0,0, PClass::FindActor("HolyMissile"), self->angle, &linetarget);
if (missile != NULL)
{
missile->tracer = linetarget;
}
weapon->CHolyCount = 3;
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))
return 0;
}
mo = P_SpawnPlayerMissile (player->mo, PClass::FindClass ("HammerMissile"));
mo = P_SpawnPlayerMissile (player->mo, PClass::FindActor("HammerMissile"));
if (mo)
{
mo->special1 = 0;

View file

@ -30,7 +30,12 @@ IMPLEMENT_CLASS (AArtiHealingRadius)
bool AArtiHealingRadius::Use (bool pickup)
{
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)
{

View file

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

View file

@ -164,8 +164,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_KoraxBonePop)
// Spawn 6 spirits equalangularly
for (i = 0; i < 6; ++i)
{
mo = P_SpawnMissileAngle (self, PClass::FindClass("KoraxSpirit"), ANGLE_60*i, 5*FRACUNIT);
if (mo) KSpiritInit (mo, self);
mo = P_SpawnMissileAngle (self, PClass::FindActor("KoraxSpirit"), ANGLE_60*i, 5*FRACUNIT);
if (mo)
{
KSpiritInit (mo, self);
}
}
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;
const PClass *lightning=PClass::FindClass((ENamedName) self->GetClass()->Meta.GetMetaInt (ACMETA_MissileName, NAME_LightningZap));
PClassActor *lightning = PClass::FindActor(self->GetClass()->MissileName);
AActor *mo;
fixed_t deltaZ;
if (lightning == NULL)
{
lightning = PClass::FindActor(NAME_LightningZap);
}
CALL_ACTION(A_LightningClip, self);
self->health -= 8;
@ -338,10 +343,14 @@ DEFINE_ACTION_FUNCTION(AActor, A_ZapMimic)
DEFINE_ACTION_FUNCTION(AActor, A_LastZap)
{
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;
if (lightning == NULL)
{
lightning = PClass::FindActor(NAME_LightningZap);
}
mo = Spawn(lightning, self->x, self->y, self->z, ALLOW_REPLACE);
if (mo)
{

View file

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

View file

@ -301,7 +301,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MinotaurAtk2)
return 0;
}
z = self->z + 40*FRACUNIT;
const PClass *fx = PClass::FindClass("MinotaurFX1");
PClassActor *fx = PClass::FindActor("MinotaurFX1");
if (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 (!self->IsKindOf (RUNTIME_CLASS (APlayerPawn))) // [GRB]
{
FDropItem *di = self->GetDropItems();
DDropItem *di = self->GetDropItems();
if (di != NULL)
{
@ -92,7 +92,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_NoBlocking)
if (di->Name != NAME_None)
{
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;
}

View file

@ -349,9 +349,9 @@ void APowerInvulnerable::InitEffect ()
{
Owner->effects &= ~FX_RESPAWNINVUL;
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)
{
@ -1729,7 +1729,7 @@ void APowerMorph::InitEffect( )
player_t *realplayer = Owner->player; // Remember the identity of the player
const PClass *morph_flash = PClass::FindClass (MorphFlash);
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))
{
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
{
FName name = (ENamedName) this->GetClass()->Meta.GetMetaInt (ACMETA_MissileName, NAME_None);
FName name = GetClass()->MissileName;
if (name != NAME_None)
{
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;
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[2] = 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)
{
@ -157,9 +157,7 @@ bool P_MorphPlayer (player_t *activator, player_t *p, const PClass *spawntype, i
// and for the original DOOM status bar.
if (p == &players[consoleplayer])
{
const char *face = spawntype->Meta.GetMetaString (APMETA_Face);
if (face != NULL && strcmp(face, "None") != 0)
if (spawntype->Face.IsNotEmpty() && strcmp(spawntype->Face, "None") != 0)
{
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.
if ((player == &players[consoleplayer]))
{
const char *face = pmo->GetClass()->Meta.GetMetaString (APMETA_Face);
if (face != NULL && strcmp(face, "None") != 0)
FString face = pmo->GetClass()->Face;
if (face.IsNotEmpty() && strcmp(face, "None") != 0)
{
// Assume root-level base skin to begin with
size_t skinindex = 0;
@ -361,7 +359,7 @@ bool P_UndoPlayerMorph (player_t *activator, player_t *player, int unmorphflag,
AHexenArmor *hxarmor = mo->FindInventory<AHexenArmor>();
if (hxarmor != NULL)
{
hxarmor->Slots[4] = mo->GetClass()->Meta.GetMetaFixed (APMETA_Hexenarmor0);
hxarmor->Slots[4] = mo->GetClass()->HexenArmor[0];
}
return true;
}
@ -558,7 +556,7 @@ int AMorphProjectile::DoSpecialDamage (AActor *target, int damage)
const PClass *unmorph_flash = PClass::FindClass (UnMorphFlash);
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);
}
else

View file

@ -33,7 +33,7 @@ class AActor;
class player_t;
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);
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,

View file

@ -20,6 +20,41 @@
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)
//===========================================================================
@ -970,9 +1005,9 @@ void AInventory::DoPickupSpecial (AActor *toucher)
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)
{
int quest = GetClass()->Meta.GetMetaInt(AIMETA_GiveQuest);
if (quest>0 && quest<31)
int quest = GetClass()->GiveQuest;
if (quest > 0 && quest <= countof(QuestItemClasses))
{
toucher->GiveInventoryType (QuestItemClasses[quest-1]);
}
@ -1394,6 +1429,35 @@ bool ACustomInventory::TryPickup (AActor *&toucher)
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)
//===========================================================================
@ -1403,13 +1467,13 @@ IMPLEMENT_CLASS (AHealth)
//===========================================================================
const char *AHealth::PickupMessage ()
{
int threshold = GetClass()->Meta.GetMetaInt(AIMETA_LowHealth, 0);
int threshold = GetClass()->LowHealth;
if (PrevHealth < threshold)
{
const char *message = GetClass()->Meta.GetMetaString (AIMETA_LowHealthMessage);
FString message = GetClass()->LowHealthMessage;
if (message != NULL)
if (message.IsNotEmpty())
{
return message;
}

View file

@ -10,6 +10,8 @@
class player_t;
class FConfigFile;
class AWeapon;
class PClassWeapon;
class PClassPlayerPawn;
class FWeaponSlot
{
@ -19,13 +21,13 @@ public:
FWeaponSlot &operator= (const FWeaponSlot &other) { Weapons = other.Weapons; return *this; }
void Clear() { Weapons.Clear(); }
bool AddWeapon (const char *type);
bool AddWeapon (PClassActor *type);
bool AddWeapon (PClassWeapon *type);
void AddWeaponList (const char *list, bool clear);
AWeapon *PickWeapon (player_t *player);
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())
{
@ -42,7 +44,7 @@ public:
private:
struct WeaponInfo
{
PClassActor *Type;
PClassWeapon *Type;
fixed_t Position;
};
void SetInitialPositions();
@ -68,25 +70,25 @@ struct FWeaponSlots
AWeapon *PickPrevWeapon (player_t *player);
void Clear ();
bool LocateWeapon (PClassActor *type, int *const slot, int *const index);
ESlotDef AddDefaultWeapon (int slot, PClassActor *type);
bool LocateWeapon (PClassWeapon *type, int *const slot, int *const index);
ESlotDef AddDefaultWeapon (int slot, PClassWeapon *type);
void AddExtraWeapons();
void SetFromGameInfo();
void SetFromPlayer(PClassActor *type);
void StandardSetup(PClassActor *type);
void SetFromPlayer(PClassPlayerPawn *type);
void StandardSetup(PClassPlayerPawn *type);
void LocalSetup(PClassActor *type);
void SendDifferences(const FWeaponSlots &other);
int RestoreSlots (FConfigFile *config, const char *section);
void PrintSettings();
void AddSlot(int slot, PClassActor *type, bool feedback);
void AddSlotDefault(int slot, PClassActor *type, bool feedback);
void AddSlot(int slot, PClassWeapon *type, bool feedback);
void AddSlotDefault(int slot, PClassWeapon *type, bool feedback);
};
void P_PlaybackKeyConfWeapons(FWeaponSlots *slots);
void Net_WriteWeapon(PClassActor *type);
PClassActor *Net_ReadWeapon(BYTE **stream);
void Net_WriteWeapon(PClassWeapon *type);
PClassWeapon *Net_ReadWeapon(BYTE **stream);
void P_SetupWeapons_ntohton();
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)
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
{
IF_ACTIVATABLE = 1<<0, // can be activated
@ -134,9 +125,22 @@ enum
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
{
DECLARE_CLASS (AInventory, AActor)
DECLARE_CLASS_WITH_META(AInventory, AActor, PClassInventory)
HAS_OBJECT_POINTERS
public:
virtual void Touch (AActor *toucher);
@ -172,7 +176,7 @@ public:
const PClass *SpawnPointClass; // For respawning like Heretic's mace
DWORD ItemFlags;
const PClass *PickupFlash; // actor to spawn as pickup flash
PClassActor *PickupFlash; // actor to spawn as pickup flash
FSoundIDNoInit PickupSound;
@ -220,9 +224,20 @@ public:
};
// 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
{
DECLARE_CLASS (AAmmo, AInventory)
DECLARE_CLASS_WITH_META(AAmmo, AInventory, PClassAmmo)
public:
void Serialize (FArchive &arc);
AInventory *CreateCopy (AActor *other);
@ -234,27 +249,32 @@ public:
};
// A weapon is just that.
enum
class PClassWeapon : public PClassInventory
{
AWMETA_BASE = 0x72000,
AWMETA_SlotNumber,
AWMETA_SlotPriority,
DECLARE_CLASS(PClassWeapon, PClassInventory);
protected:
virtual void Derive(PClass *newclass);
public:
PClassWeapon();
int SlotNumber;
fixed_t SlotPriority;
};
class AWeapon : public AInventory
{
DECLARE_CLASS (AWeapon, AInventory)
DECLARE_CLASS_WITH_META(AWeapon, AInventory, PClassWeapon)
HAS_OBJECT_POINTERS
public:
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 MinAmmo1, MinAmmo2; // Minimum ammo needed to switch to this weapon
int AmmoUse1, AmmoUse2; // How much ammo to use with each shot
int Kickback;
fixed_t YAdjust; // For viewing the weapon fullscreen
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 *AltProjectileType; // Projectile used by alternate attack
int SelectionOrder; // Lower-numbered weapons get picked first
@ -302,7 +322,7 @@ public:
protected:
AAmmo *AddAmmo (AActor *other, PClassActor *ammotype, int amount);
bool AddExistingAmmo (AAmmo *ammo, int amount);
AWeapon *AddWeapon (PClassActor *weapon);
AWeapon *AddWeapon (PClassWeapon *weapon);
};
enum
@ -336,9 +356,21 @@ enum
#define S_LIGHTDONE 0
// 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
{
DECLARE_CLASS (AHealth, AInventory)
DECLARE_CLASS_WITH_META(AHealth, AInventory, PClassHealth)
int PrevHealth;
public:
@ -440,9 +472,18 @@ protected:
};
// 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
{
DECLARE_CLASS (APuzzleItem, AInventory)
DECLARE_CLASS_WITH_META(APuzzleItem, AInventory, PClassPuzzleItem)
public:
void Serialize (FArchive &arc);
bool ShouldStay ();

View file

@ -8,7 +8,16 @@
#include "doomstat.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)
{
@ -36,9 +45,9 @@ bool APuzzleItem::Use (bool pickup)
S_Sound (Owner, CHAN_VOICE, "*puzzfail", 1, ATTN_IDLE);
if (Owner != NULL && Owner->CheckLocalView (consoleplayer))
{
const char *message = GetClass()->Meta.GetMetaString (AIMETA_PuzzFailMessage);
if (message != NULL && *message=='$') message = GStrings[message + 1];
if (message == NULL) message = GStrings("TXT_USEPUZZLEFAILED");
FString message = GetClass()->PuzzFailMessage;
if (message.IsNotEmpty() && message[0] == '$') message = GStrings[&message[1]];
if (message.IsEmpty()) message = GStrings("TXT_USEPUZZLEFAILED");
C_MidPrintBold (SmallFont, message);
}
return false;

View file

@ -28,9 +28,9 @@ class ARandomSpawner : public AActor
// random spawner's velocity (0...) instead of their own.
void BeginPlay()
{
FDropItem *di; // di will be our drop item list iterator
FDropItem *drop; // while drop stays as the reference point.
int n=0;
DDropItem *di; // di will be our drop item list iterator
DDropItem *drop; // while drop stays as the reference point.
int n = 0;
Super::BeginPlay();
drop = di = GetDropItems();
@ -40,8 +40,8 @@ class ARandomSpawner : public AActor
{
if (di->Name != NAME_None)
{
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.
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.
di = di->Next;
}
}
@ -54,7 +54,7 @@ class ARandomSpawner : public AActor
{
if (di->Name != NAME_None)
{
n -= di->amount;
n -= di->Amount;
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.
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
PClassActor *cls;

View file

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

View file

@ -30,11 +30,29 @@ FString WeaponSection;
TArray<FString> KeyConfWeapons;
FWeaponSlots *PlayingKeyConf;
TArray<PClassActor *> Weapons_ntoh;
TMap<PClassActor *, int> Weapons_hton;
TArray<PClassWeapon *> Weapons_ntoh;
TMap<PClassWeapon *, int> Weapons_hton;
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
@ -357,7 +375,7 @@ bool AWeapon::AddExistingAmmo (AAmmo *ammo, int amount)
//
//===========================================================================
AWeapon *AWeapon::AddWeapon (PClassActor *weapontype)
AWeapon *AWeapon::AddWeapon (PClassWeapon *weapontype)
{
AWeapon *weap;
@ -620,13 +638,13 @@ IMPLEMENT_CLASS(AWeaponGiver)
bool AWeaponGiver::TryPickup(AActor *&toucher)
{
FDropItem *di = GetDropItems();
DDropItem *di = GetDropItems();
AWeapon *weap;
if (di != NULL)
{
PClassActor *ti = PClass::FindActor(di->Name);
if (ti != NULL && ti->IsDescendantOf(RUNTIME_CLASS(AWeapon)))
PClassWeapon *ti = dyn_cast<PClassWeapon>(PClass::FindClass(di->Name));
if (ti != NULL)
{
if (master == NULL)
{
@ -662,10 +680,10 @@ bool AWeaponGiver::TryPickup(AActor *&toucher)
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;
@ -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;
@ -842,7 +860,7 @@ void FWeaponSlot::Sort()
for (i = 1; i < (int)Weapons.Size(); ++i)
{
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)
{
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;
@ -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;
@ -1014,7 +1032,7 @@ AWeapon *FWeaponSlots::PickNextWeapon(player_t *player)
slot = 0;
}
}
PClassActor *type = Slots[slot].GetWeapon(index);
PClassWeapon *type = Slots[slot].GetWeapon(index);
AWeapon *weap = static_cast<AWeapon *>(player->mo->FindInventory(type));
if (weap != NULL && weap->CheckAmmo(AWeapon::EitherFire, false))
{
@ -1069,7 +1087,7 @@ AWeapon *FWeaponSlots::PickPrevWeapon (player_t *player)
}
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));
if (weap != NULL && weap->CheckAmmo(AWeapon::EitherFire, false))
{
@ -1109,17 +1127,16 @@ void FWeaponSlots::AddExtraWeapons()
{
continue;
}
PClassActor *acls = static_cast<PClassActor *>(cls);
PClassWeapon *acls = static_cast<PClassWeapon *>(cls);
if ((acls->GameFilter == GAME_Any || (acls->GameFilter & gameinfo.gametype)) &&
acls->Replacement == NULL && // Replaced weapons don't get slotted.
!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)
{
fixed_t position = acls->Meta.GetMetaFixed(AWMETA_SlotPriority, INT_MAX);
FWeaponSlot::WeaponInfo info = { acls, position };
FWeaponSlot::WeaponInfo info = { acls, acls->SlotPriority };
Slots[slot].Weapons.Push(info);
}
}
@ -1156,7 +1173,7 @@ void FWeaponSlots::SetFromGameInfo()
{
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)
{
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);
AddExtraWeapons();
@ -1266,15 +1283,14 @@ void FWeaponSlots::SendDifferences(const FWeaponSlots &other)
//
//===========================================================================
void FWeaponSlots::SetFromPlayer(PClassActor *type)
void FWeaponSlots::SetFromPlayer(PClassPlayerPawn *type)
{
Clear();
for (int i = 0; i < NUM_WEAPON_SLOTS; ++i)
{
const char *str = type->Meta.GetMetaString(APMETA_Slot0 + i);
if (str != NULL)
if (!type->Slot[i].IsEmpty())
{
Slots[i].AddWeaponList(str, false);
Slots[i].AddWeaponList(type->Slot[i], false);
}
}
}
@ -1385,7 +1401,7 @@ CCMD (setslot)
Net_WriteByte(argv.argc()-2);
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)
{
@ -1414,19 +1430,26 @@ CCMD (addslot)
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)
{
KeyConfWeapons.Push(argv.args());
}
else if (PlayingKeyConf != NULL)
{
PlayingKeyConf->AddSlot(int(slot), PClass::FindActor(argv[2]), false);
PlayingKeyConf->AddSlot(int(slot), type, false);
}
else
{
Net_WriteByte(DEM_ADDSLOT);
Net_WriteByte(slot);
Net_WriteWeapon(PClass::FindActor(argv[2]));
Net_WriteWeapon(type);
}
}
@ -1449,7 +1472,7 @@ CCMD (weaponsection)
// 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)))
{
@ -1474,7 +1497,7 @@ void FWeaponSlots::AddSlotDefault(int slot, PClassActor *type, bool feedback)
CCMD (addslotdefault)
{
PClassActor *type;
PClassWeapon *type;
unsigned int slot;
if (argv.argc() != 3 || (slot = atoi (argv[1])) >= NUM_WEAPON_SLOTS)
@ -1483,8 +1506,8 @@ CCMD (addslotdefault)
return;
}
type = PClass::FindActor(argv[2]);
if (type == NULL || !type->IsDescendantOf (RUNTIME_CLASS(AWeapon)))
type = dyn_cast<PClassWeapon>(PClass::FindClass(argv[2]));
if (type == NULL)
{
Printf ("%s is not a weapon\n", argv[2]);
return;
@ -1496,13 +1519,13 @@ CCMD (addslotdefault)
}
else if (PlayingKeyConf != NULL)
{
PlayingKeyConf->AddSlotDefault(int(slot), PClass::FindActor(argv[2]), false);
PlayingKeyConf->AddSlotDefault(int(slot), type, false);
}
else
{
Net_WriteByte(DEM_ADDSLOTDEFAULT);
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()
{
unsigned int i;
PClassActor *cls;
PClassWeapon *cls;
Weapons_ntoh.Clear();
Weapons_hton.Clear();
@ -1552,7 +1575,7 @@ void P_SetupWeapons_ntohton()
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);
@ -1578,8 +1601,8 @@ void P_SetupWeapons_ntohton()
static int STACK_ARGS ntoh_cmp(const void *a, const void *b)
{
PClassActor *c1 = *(PClassActor **)a;
PClassActor *c2 = *(PClassActor **)b;
PClassWeapon *c1 = *(PClassWeapon **)a;
PClassWeapon *c2 = *(PClassWeapon **)b;
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;
if (g1 != g2)
@ -1619,7 +1642,7 @@ void P_WriteDemoWeaponsChunk(BYTE **demo)
void P_ReadDemoWeaponsChunk(BYTE **demo)
{
int count, i;
PClassActor *type;
PClassWeapon *type;
const char *s;
count = ReadWord(demo);
@ -1632,7 +1655,7 @@ void P_ReadDemoWeaponsChunk(BYTE **demo)
for (i = 1; i < count; ++i)
{
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,
// should we report it?
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;
@ -1681,7 +1704,7 @@ void Net_WriteWeapon(PClassActor *type)
//
//===========================================================================
PClassActor *Net_ReadWeapon(BYTE **stream)
PClassWeapon *Net_ReadWeapon(BYTE **stream)
{
int index;

View file

@ -2176,7 +2176,7 @@ class CommandPlayerClass : public SBarInfoCommandFlowControl
bool foundClass = false;
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;
classes.Push(PlayerClasses[c].Type->ClassIndex);

View file

@ -104,16 +104,14 @@ static int statspace;
void AM_GetPosition(fixed_t & x, fixed_t & y);
FTextureID GetHUDIcon(const PClass *cls)
FTextureID GetHUDIcon(PClassInventory *cls)
{
FTextureID tex;
tex.texnum = cls->Meta.GetMetaInt(HUMETA_AltIcon, 0);
return tex;
return cls->AltHUDIcon;
}
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
//
//---------------------------------------------------------------------------
static TArray<PClassActor *> orderedammos;
static TArray<PClassAmmo *> orderedammos;
static void AddAmmoToList(AWeapon * weapdef)
{
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)
{
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--)
{
PClassActor * type = orderedammos[i];
PClassAmmo * type = orderedammos[i];
AAmmo * ammoitem = (AAmmo*)CPlayer->mo->FindInventory(type);
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;
AInventory * inv;
AInventory *inv;
// 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)) &&
!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));
}
@ -931,7 +929,7 @@ void HUD_InitHud()
}
else
{
const PClass * ti = PClass::FindClass(sc.String);
PClass *ti = PClass::FindClass(sc.String);
if (!ti)
{
Printf("Unknown item class '%s' in ALTHUDCF\n", sc.String);
@ -950,9 +948,8 @@ void HUD_InitHud()
}
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);
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
{
if (P_CheckMissileRange (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;
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;
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->reactiontime += 15;
}
@ -54,7 +54,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CrusaderSweepLeft)
PARAM_ACTION_PROLOGUE;
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)
{
misl->velz += FRACUNIT;
@ -67,7 +67,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_CrusaderSweepRight)
PARAM_ACTION_PROLOGUE;
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)
{
misl->velz += FRACUNIT;

View file

@ -63,13 +63,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_InquisitorAttack)
self->z += 32*FRACBITS;
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)
{
proj->velz += 9*FRACUNIT;
}
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)
{
proj->velz += 16*FRACUNIT;

View file

@ -53,7 +53,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SentinelAttack)
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)
{

View file

@ -341,7 +341,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMiniMissile)
savedangle = self->angle;
self->angle += pr_minimissile.Random2() << (19 - player->accuracy * 5 / 100);
player->mo->PlayAttacking2 ();
P_SpawnPlayerMissile (self, PClass::FindClass("MiniMissile"));
P_SpawnPlayerMissile (self, PClass::FindActor("MiniMissile"));
self->angle = savedangle;
return 0;
}
@ -359,7 +359,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_RocketInFlight)
AActor *trail;
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);
if (trail != NULL)
{
@ -409,7 +409,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireFlamer)
}
self->angle += pr_flamethrower.Random2() << 18;
self = P_SpawnPlayerMissile (self, PClass::FindClass("FlameMissile"));
self = P_SpawnPlayerMissile (self, PClass::FindActor("FlameMissile"));
if (self != NULL)
{
self->velz += 5*FRACUNIT;
@ -508,7 +508,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireMauler2)
}
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_ThrustMobj (self, self->angle + ANGLE_180, 0x7D000);
return 0;
@ -1012,7 +1012,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSigil2)
P_DamageMobj (self, self, NULL, 2*4, 0, DMG_NO_ARMOR);
S_Sound (self, CHAN_WEAPON, "weapons/sigilcharge", 1, ATTN_NORM);
P_SpawnPlayerMissile (self, PClass::FindClass("SpectralLightningH1"));
P_SpawnPlayerMissile (self, PClass::FindActor("SpectralLightningH1"));
return 0;
}
@ -1073,7 +1073,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSigil4)
P_BulletSlope (self, &linetarget);
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)
{
spot->tracer = linetarget;
@ -1081,7 +1081,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireSigil4)
}
else
{
spot = P_SpawnPlayerMissile (self, PClass::FindClass("SpectralLightningBigV1"));
spot = P_SpawnPlayerMissile (self, PClass::FindActor("SpectralLightningBigV1"));
if (spot != NULL)
{
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);
S_Sound (self, CHAN_WEAPON, "weapons/sigilcharge", 1, ATTN_NORM);
P_SpawnPlayerMissile (self, PClass::FindClass("SpectralLightningBigBall1"));
P_SpawnPlayerMissile (self, PClass::FindActor("SpectralLightningBigBall1"));
return 0;
}

View file

@ -107,7 +107,9 @@ int GetSpriteIndex(const char * spritename)
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;
DamageFactors = 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

View file

@ -44,6 +44,7 @@
#include "dobject.h"
#include "doomdef.h"
#include "vm.h"
#include "s_sound.h"
const BYTE SF_FULLBRIGHT = 0x40;
@ -124,10 +125,14 @@ FArchive &operator<< (FArchive &arc, FState *&state);
typedef TMap<FName, fixed_t> DmgFactors;
typedef TMap<FName, BYTE> PainChanceList;
class DDropItem;
class PClassActor : public PClass
{
DECLARE_CLASS(PClassActor, PClass);
HAS_OBJECT_POINTERS;
protected:
virtual void Derive(PClass *newclass);
public:
static void StaticInit ();
static void StaticSetActorNums ();
@ -163,6 +168,32 @@ public:
FStateLabels *StateList;
DmgFactors *DamageFactors;
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)

View file

@ -144,7 +144,7 @@ void cht_DoCheat (player_t *player, int cheat)
break;
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;
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);
}
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)
{
return "";
}
PClass *oldclass = player->mo->GetClass();
PClassPlayerPawn *oldclass = player->mo->GetClass();
// Set the standard morph style for the current game
int style = MORPH_UNDOBYTOMEOFPOWER;
@ -750,7 +750,7 @@ void cht_Give (player_t *player, const char *name, int amount)
// is in a weapon slot.
if (static_cast<PClassActor *>(type)->GameFilter == GAME_Any ||
(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);
if (!(def->WeaponFlags & WIF_CHEATNOTWEAPON))

View file

@ -29,11 +29,12 @@
// [RH] Functions that actually perform the cheating
class player_t;
class PClass;
class PClassPlayerPawn;
void cht_DoCheat (player_t *player, int cheat);
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_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

View file

@ -1883,7 +1883,7 @@ static void SCClass (int option)
if (option == 3)
playerclass = "Random";
else
playerclass = PlayerClasses[option].Type->Meta.GetMetaString (APMETA_DisplayName);
playerclass = PlayerClasses[option].Type->DisplayName;
if (EpiDef.numitems > 1)
{
@ -2299,7 +2299,7 @@ static void M_PlayerSetupDrawer ()
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, 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);
// Draw skin setting
@ -2567,8 +2567,7 @@ static void M_ChangeClass (int choice)
else
type = (type < (int)PlayerClasses.Size () - 1) ? type + 1 : -1;
cvar_set ("playerclass", type < 0 ? "Random" :
PlayerClasses[type].Type->Meta.GetMetaString (APMETA_DisplayName));
cvar_set ("playerclass", type < 0 ? "Random" : PlayerClasses[type].Type->DisplayName);
}
static void M_ChangeSkin (int choice)
@ -3964,8 +3963,7 @@ void M_Init (void)
{
if (!(PlayerClasses[i].Flags & PCF_NOMENU))
{
ClassMenuItems[n].name =
PlayerClasses[i].Type->Meta.GetMetaString (APMETA_DisplayName);
ClassMenuItems[n].name = PlayerClasses[i].Type->DisplayName;
n++;
}
}
@ -3979,8 +3977,7 @@ void M_Init (void)
{
if (n == 0)
{
ClassMenuItems[0].name =
PlayerClasses[0].Type->Meta.GetMetaString (APMETA_DisplayName);
ClassMenuItems[0].name = PlayerClasses[0].Type->DisplayName;
}
ClassMenuDef.numitems = 1;
}

View file

@ -3109,7 +3109,7 @@ int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
}
else
{
return actor->GetClass()->Meta.GetMetaFixed(AMETA_CameraHeight, actor->height/2);
return actor->GetCameraHeight();
}
}
else return 0;
@ -6358,7 +6358,7 @@ int DLevelScript::RunScript ()
{
int tag = STACK(7);
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));
const PClass *monsterclass = PClass::FindClass (monsterclass_name);
int duration = STACK(4);

View file

@ -2877,8 +2877,13 @@ void ModifyDropAmount(AInventory *inv, int dropamount)
else if (inv->IsKindOf (RUNTIME_CLASS(AAmmo)))
{
// Half ammo when dropped by bad guys.
inv->Amount = inv->GetClass()->Meta.GetMetaInt (AIMETA_DropAmount, MAX(1, FixedMul(inv->Amount, dropammofactor)));
inv->ItemFlags|=flagmask;
int amount = static_cast<PClassAmmo *>(inv->GetClass())->DropAmount;
if (amount <= 0)
{
amount = FixedMul(inv->Amount, dropammofactor);
}
inv->Amount = amount;
inv->ItemFlags |= flagmask;
}
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");
}
else if (mod == NAME_Melee)
else if (mod == NAME_Melee && attacker->GetClass()->HitObituary.IsNotEmpty())
{
message = attacker->GetClass()->Meta.GetMetaString (AMETA_HitObituary);
if (message == NULL)
{
message = attacker->GetClass()->Meta.GetMetaString (AMETA_Obituary);
message = attacker->GetClass()->HitObituary;
}
}
else
else if (attacker->GetClass()->Obituary.IsNotEmpty())
{
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 (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)
{
@ -320,12 +316,7 @@ EXTERN_CVAR (Int, fraglimit)
static int GibHealth(AActor *actor)
{
return -abs(
actor->GetClass()->Meta.GetMetaInt (
AMETA_GibHealth,
gameinfo.gametype & GAME_DoomChex ?
-actor->SpawnHealth() :
-actor->SpawnHealth()/2));
return -abs(actor->GetGibHealth());
}
void AActor::Die (AActor *source, AActor *inflictor)
@ -399,22 +390,22 @@ void AActor::Die (AActor *source, AActor *inflictor)
flags6 |= MF6_KILLED;
// [RH] Allow the death height to be overridden using metadata.
fixed_t metaheight = 0;
fixed_t metaheight = -1;
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
{
height >>= 2;
height = MAX<fixed_t> (metaheight, 0);
}
// [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);
if (woundstate != NULL)
{
int woundhealth = RUNTIME_TYPE(target)->Meta.GetMetaInt (AMETA_WoundHealth, 6);
int woundhealth = target->GetClass()->WoundHealth;
if (target->health <= woundhealth)
{

View file

@ -103,7 +103,7 @@ enum EPuffFlags
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_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);
@ -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_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_SpawnMissileAngle (AActor *source, const PClass *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_SpawnMissileAngleZ (AActor *source, fixed_t z, const PClass *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_SpawnMissileZAimed (AActor *source, fixed_t z, AActor *dest, const PClass *type);
AActor *P_SpawnMissileAngle (AActor *source, PClassActor *type, angle_t angle, fixed_t velz);
AActor *P_SpawnMissileAngleSpeed (AActor *source, PClassActor *type, angle_t angle, fixed_t velz, fixed_t speed);
AActor *P_SpawnMissileAngleZ (AActor *source, fixed_t z, PClassActor *type, angle_t angle, fixed_t velz);
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, PClassActor *type);
AActor *P_SpawnPlayerMissile (AActor* source, const PClass *type);
AActor *P_SpawnPlayerMissile (AActor *source, const PClass *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, PClassActor *type);
AActor *P_SpawnPlayerMissile (AActor *source, PClassActor *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);
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)
{
PalEntry bloodcolor = (PalEntry)actor->GetClass()->Meta.GetMetaInt(AMETA_BloodColor);
PalEntry bloodcolor = actor->GetClass()->BloodColor;
if (bloodcolor != 0)
{
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 *= thing->GetClass()->Meta.GetMetaFixed(AMETA_RDFactor, FRACUNIT)/(float)FRACUNIT;
points *= thing->GetClass()->RDFactor/(float)FRACUNIT;
if (points > 0.f && P_CheckSight (thing, bombspot, 1))
{ // 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);
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)
{
P_DamageMobj (thing, bombspot, bombsource, damage, bombmod);
@ -4598,8 +4598,8 @@ void P_DoCrunch (AActor *thing, FChangePosition *cpos)
if ((!(thing->flags&MF_NOBLOOD)) &&
(!(thing->flags2&(MF2_INVULNERABLE|MF2_DORMANT))))
{
PalEntry bloodcolor = (PalEntry)thing->GetClass()->Meta.GetMetaInt(AMETA_BloodColor);
const PClass *bloodcls = PClass::FindClass((ENamedName)thing->GetClass()->Meta.GetMetaInt(AMETA_BloodType, NAME_Blood));
PalEntry bloodcolor = thing->GetClass()->BloodColor;
PClassActor *bloodcls = PClass::FindActor(thing->GetClass()->BloodType);
P_TraceBleed (cpos->crushchange, thing);
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.
{
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);
}
return false;
@ -1113,7 +1113,7 @@ bool AActor::Grind(bool items)
}
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 (flags & MF_ICECORPSE)
@ -2651,7 +2651,7 @@ int AActor::GetMissileDamage (int mask, int add)
void AActor::Howl ()
{
int howl = GetClass()->Meta.GetMetaInt(AMETA_HowlSound);
FSoundID howl = GetClass()->HowlSound;
if (!S_IsActorPlayingSomething(this, CHAN_BODY, howl))
{
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->renderflags = (actor->renderflags & ~RF_FULLBRIGHT) | st->GetFullbright();
actor->touching_sectorlist = NULL; // NULL head of sector list // phares 3/13/98
if (G_SkillProperty(SKILLP_FastMonsters))
actor->Speed = actor->GetClass()->Meta.GetMetaFixed(AMETA_FastSpeed, actor->Speed);
if (G_SkillProperty(SKILLP_FastMonsters) && actor->GetClass()->FastSpeed >= 0)
actor->Speed = actor->GetClass()->FastSpeed;
// set subsector and/or block links
actor->LinkToWorld (SpawningMapThing);
@ -4445,7 +4444,7 @@ AActor *P_SpawnMapThing (FMapThing *mthing, int position)
// 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;
@ -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)
{
AActor *th;
PalEntry bloodcolor = (PalEntry)originator->GetClass()->Meta.GetMetaInt(AMETA_BloodColor);
const PClass *bloodcls = PClass::FindClass((ENamedName)originator->GetClass()->Meta.GetMetaInt(AMETA_BloodType, NAME_Blood));
PalEntry bloodcolor = originator->GetClass()->BloodColor;
PClassActor *bloodcls = PClass::FindActor(originator->GetClass()->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)
{
PalEntry bloodcolor = (PalEntry)originator->GetClass()->Meta.GetMetaInt(AMETA_BloodColor);
const PClass *bloodcls = PClass::FindClass((ENamedName)originator->GetClass()->Meta.GetMetaInt(AMETA_BloodType2, NAME_BloodSplatter));
PalEntry bloodcolor = originator->GetClass()->BloodColor;
PClassActor *bloodcls = PClass::FindActor(originator->GetClass()->BloodType2);
int bloodtype = cl_bloodtype;
if (bloodcls != NULL && !(GetDefaultByType(bloodcls)->flags4 & MF4_ALLOWPARTICLES))
bloodtype = 0;
if (bloodcls!=NULL && bloodtype <= 1)
if (bloodcls != NULL && bloodtype <= 1)
{
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)
{
PalEntry bloodcolor = (PalEntry)originator->GetClass()->Meta.GetMetaInt(AMETA_BloodColor);
const PClass *bloodcls = PClass::FindClass((ENamedName)originator->GetClass()->Meta.GetMetaInt(AMETA_BloodType3, NAME_AxeBlood));
PalEntry bloodcolor = originator->GetClass()->BloodColor;
PClassActor *bloodcls = PClass::FindActor(originator->GetClass()->BloodType3);
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)
{
fixed_t x, y, z;
PalEntry bloodcolor = (PalEntry)bleeder->GetClass()->Meta.GetMetaInt(AMETA_BloodColor);
const PClass *bloodcls = PClass::FindClass((ENamedName)bleeder->GetClass()->Meta.GetMetaInt(AMETA_BloodType, NAME_Blood));
PalEntry bloodcolor = bleeder->GetClass()->BloodColor;
PClassActor *bloodcls = PClass::FindActor(bleeder->GetClass()->BloodType);
x = mo->x + (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;
else if (G_SkillProperty(SKILLP_FastMonsters))
return type->Meta.GetMetaFixed(AMETA_FastSpeed, GetDefaultByType(type)->Speed);
if (type == NULL)
return 0;
else if (G_SkillProperty(SKILLP_FastMonsters) && type->FastSpeed >= 0)
return type->FastSpeed;
else
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)
{
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,
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,
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;
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)
{
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,
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;
@ -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);
}
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);
}
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)
{
static const int angdiff[3] = { -1<<26, 1<<26, 0 };
@ -5451,7 +5451,7 @@ int AActor::DoSpecialDamage (AActor *target, int damage)
{
if (target->player)
{
int poisondamage = GetClass()->Meta.GetMetaInt(AMETA_PoisonDamage);
int poisondamage = GetClass()->PoisonDamage;
if (poisondamage > 0)
{
P_PoisonPlayer (target->player, this, this->target, poisondamage);
@ -5512,8 +5512,7 @@ void AActor::Crash()
}
if (crashstate == NULL)
{
int gibhealth = -abs(GetClass()->Meta.GetMetaInt (AMETA_GibHealth,
gameinfo.gametype & GAME_DoomChex ? -SpawnHealth() : -SpawnHealth()/2));
int gibhealth = GetGibHealth();
if (health < gibhealth)
{ // Extreme death
@ -5538,7 +5537,7 @@ void AActor::SetIdle()
SetState(idle);
}
int AActor::SpawnHealth()
int AActor::SpawnHealth() const
{
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
@ -5595,30 +5611,9 @@ const char *AActor::GetTag(const char *def) const
// DropItem handling
//
//----------------------------------------------------------------------------
FDropItemPtrArray DropItemList;
void FreeDropItemChain(FDropItem *chain)
{
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;
}
IMPLEMENT_POINTY_CLASS(DDropItem)
DECLARE_POINTER(Next)
END_POINTERS
void PrintMiscActorInfo(AActor * query)
{

View file

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

View file

@ -1064,7 +1064,7 @@ void R_SetupFrame (AActor *actor)
{
iview->nviewx = camera->x;
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;
r_showviewer = false;
}

View file

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

View file

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

View file

@ -256,7 +256,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
{
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]);
}
@ -294,7 +294,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
}
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]);
}
@ -475,18 +475,18 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults,
else if (def == DEF_Projectile && sc.Compare ("ExplosionRadius"))
{
sc.MustGetNumber ();
bag.Info->Meta.SetMetaInt(ACMETA_ExplosionRadius, sc.Number);
bag.Info->ExplosionRadius = sc.Number;
extra.bExplosive = true;
}
else if (def == DEF_Projectile && sc.Compare ("ExplosionDamage"))
{
sc.MustGetNumber ();
bag.Info->Meta.SetMetaInt(ACMETA_ExplosionDamage, sc.Number);
bag.Info->ExplosionDamage = sc.Number;
extra.bExplosive = true;
}
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"))
{
@ -571,7 +571,7 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults,
else if (def == DEF_Pickup && sc.Compare ("PickupMessage"))
{
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"))
{

View file

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

View file

@ -152,7 +152,7 @@ extern FStateExpressions StateParams;
// Extra info maintained while defining an actor.
//
//==========================================================================
struct FDropItem;
class DDropItem;
struct Baggage
{
@ -166,7 +166,7 @@ struct Baggage
int Lumpnum;
FStateDefinitions statedef;
FDropItem *DropItemList;
DDropItem *DropItemList;
FScriptPosition ScriptPosition;
};
@ -235,13 +235,6 @@ enum
{
ACMETA_BASE = 0x83000,
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)
{
PARAM_ACTION_PROLOGUE;
int MeleeDamage = self->GetClass()->Meta.GetMetaInt(ACMETA_MeleeDamage, 0);
FSoundID MeleeSound = self->GetClass()->Meta.GetMetaInt(ACMETA_MeleeSound, 0);
int MeleeDamage = self->GetClass()->MeleeDamage;
FSoundID MeleeSound = self->GetClass()->MeleeSound;
DoAttack(self, true, false, MeleeDamage, MeleeSound, NULL, 0);
return 0;
}
@ -222,8 +222,8 @@ DEFINE_ACTION_FUNCTION(AActor, A_MeleeAttack)
DEFINE_ACTION_FUNCTION(AActor, A_MissileAttack)
{
PARAM_ACTION_PROLOGUE;
const PClass *MissileType = PClass::FindClass(ENamedName(self->GetClass()->Meta.GetMetaInt(ACMETA_MissileName, NAME_None)));
fixed_t MissileHeight = self->GetClass()->Meta.GetMetaFixed(ACMETA_MissileHeight, 32*FRACUNIT);
PClassActor *MissileType = PClass::FindActor(self->GetClass()->MissileName);
fixed_t MissileHeight = self->GetClass()->MissileHeight;
DoAttack(self, false, true, 0, 0, MissileType, MissileHeight);
return 0;
}
@ -231,10 +231,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_MissileAttack)
DEFINE_ACTION_FUNCTION(AActor, A_ComboAttack)
{
PARAM_ACTION_PROLOGUE;
int MeleeDamage = self->GetClass()->Meta.GetMetaInt(ACMETA_MeleeDamage, 0);
FSoundID MeleeSound = self->GetClass()->Meta.GetMetaInt(ACMETA_MeleeSound, 0);
const PClass *MissileType = PClass::FindClass(ENamedName(self->GetClass()->Meta.GetMetaInt(ACMETA_MissileName, NAME_None)));
fixed_t MissileHeight = self->GetClass()->Meta.GetMetaFixed(ACMETA_MissileHeight, 32*FRACUNIT);
int MeleeDamage = self->GetClass()->MeleeDamage;
FSoundID MeleeSound = self->GetClass()->MeleeSound;
PClassActor *MissileType = PClass::FindActor(self->GetClass()->MissileName);
fixed_t MissileHeight = self->GetClass()->MissileHeight;
DoAttack(self, true, true, MeleeDamage, MeleeSound, MissileType, MissileHeight);
return 0;
}
@ -622,9 +622,13 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode)
if (damage < 0) // get parameters from metadata
{
damage = self->GetClass()->Meta.GetMetaInt (ACMETA_ExplosionDamage, 128);
distance = self->GetClass()->Meta.GetMetaInt (ACMETA_ExplosionRadius, damage);
hurtSource = !self->GetClass()->Meta.GetMetaInt (ACMETA_DontHurtShooter);
damage = self->GetClass()->ExplosionDamage;
distance = self->GetClass()->ExplosionRadius;
if (distance < 0)
{
distance = damage;
}
hurtSource = !self->GetClass()->DontHurtShooter;
alert = false;
}
else

View file

@ -74,7 +74,7 @@
// 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'
if (name == NULL || *name == 0 || !stricmp(name, "none"))
@ -82,16 +82,26 @@ static PClassActor *FindClassTentative(const char *name, const char *ancestor)
return NULL;
}
PClass *anc = PClass::FindClass(ancestor);
assert(anc != NULL); // parent classes used here should always be natively defined
PClass *cls = anc->FindClassTentative(name);
assert (cls != NULL); // cls can not ne NULL here
if (!cls->IsDescendantOf(anc))
PClass *cls = ancestor->FindClassTentative(name);
assert(cls != NULL); // cls can not be NULL here
if (!cls->IsDescendantOf(ancestor))
{
I_Error("%s does not inherit from %s\n", name, ancestor);
}
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:
if (set)
{
static_cast<AInventory*>(defaults)->PickupFlash = FindClassTentative("PickupFlash", "Actor");
static_cast<AInventory*>(defaults)->PickupFlash = FindClassTentative("PickupFlash", RUNTIME_CLASS(AActor));
}
else
{
@ -293,10 +303,6 @@ DEFINE_PROPERTY(skip_super, 0, Actor)
}
memcpy (defaults, GetDefault<AActor>(), sizeof(AActor));
if (bag.DropItemList != NULL)
{
FreeDropItemChain (bag.DropItemList);
}
ResetBaggage (&bag, RUNTIME_CLASS(AActor));
}
@ -324,7 +330,8 @@ DEFINE_PROPERTY(health, I, Actor)
DEFINE_PROPERTY(gibhealth, I, Actor)
{
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)
{
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)
{
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;
}
FDropItem *di = new FDropItem;
DDropItem *di = new DDropItem;
di->Name =type;
di->probability=255;
di->amount=-1;
di->Name = type;
di->Probability = 255;
di->Amount = -1;
if (PROP_PARM_COUNT > 1)
{
PROP_INT_PARM(prob, 1);
di->probability = prob;
di->Probability = prob;
if (PROP_PARM_COUNT > 2)
{
PROP_INT_PARM(amt, 2);
di->amount = amt;
di->Amount = amt;
}
}
di->Next = bag.DropItemList;
@ -637,7 +646,8 @@ DEFINE_PROPERTY(alpha, F, Actor)
DEFINE_PROPERTY(obituary, S, Actor)
{
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)
{
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)
{
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)
{
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)
{
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)
{
PROP_FIXED_PARM(h, 0);
// AActor::Die() uses a height of 0 to mean "cut the height to 1/4",
// so if a height of 0 is desired, store it as -1.
info->Meta.SetMetaFixed (AMETA_DeathHeight, h <= 0 ? -1 : h);
assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
static_cast<PClassActor *>(info)->DeathHeight = MAX(0, h);
}
//==========================================================================
@ -692,8 +705,8 @@ DEFINE_PROPERTY(deathheight, F, Actor)
DEFINE_PROPERTY(burnheight, F, Actor)
{
PROP_FIXED_PARM(h, 0);
// The note above for AMETA_DeathHeight also applies here.
info->Meta.SetMetaFixed (AMETA_BurnHeight, h <= 0 ? -1 : h);
assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
static_cast<PClassActor *>(info)->BurnHeight = MAX(0, h);
}
//==========================================================================
@ -720,7 +733,8 @@ DEFINE_PROPERTY(meleethreshold, F, Actor)
DEFINE_PROPERTY(meleedamage, I, Actor)
{
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)
{
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)
{
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)
{
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;
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(str2, 2)
assert(info->IsKindOf(RUNTIME_CLASS(PClassActor)));
PClassActor *ainfo = static_cast<PClassActor *>(info);
FName blood = str;
// normal blood
info->Meta.SetMetaInt (AMETA_BloodType, blood);
ainfo->BloodType = blood;
if (PROP_PARM_COUNT > 1)
{
blood = str1;
}
// blood splatter
info->Meta.SetMetaInt (AMETA_BloodType2, blood);
ainfo->BloodType2 = blood;
if (PROP_PARM_COUNT > 2)
{
blood = str2;
}
// 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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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)
{
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_STRING_PARM(str, 1);
info->Meta.SetMetaInt(AIMETA_LowHealth, i);
info->Meta.SetMetaString(AIMETA_LowHealthMessage, str);
assert(info->IsKindOf(RUNTIME_CLASS(PClassHealth)));
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)
{
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);
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);
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);
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)
{
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)
{
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)
{
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)
{
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;
st.Format("%s%s", strnicmp(str, "power", 5)? "Power" : "", str);
cls = FindClassTentative(st, "Powerup");
cls = FindClassTentativePowerup(st);
}
defaults->PowerupType = cls;
@ -1795,7 +1827,8 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, type, S, PowerupGiver)
DEFINE_CLASS_PROPERTY_PREFIX(player, displayname, S, PlayerPawn)
{
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;
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 ());
}
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)
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;
}
FDropItem * di=new FDropItem;
DDropItem *di = new DDropItem;
di->Name = str;
di->probability = 255;
di->amount = 1;
di->Probability = 255;
di->Amount = 1;
if (PROP_PARM_COUNT > 1)
{
PROP_INT_PARM(amt, 1);
di->amount = amt;
di->Amount = amt;
}
di->Next = bag.DropItemList;
bag.DropItemList = di;
@ -2056,7 +2093,8 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, startitem, S_i, PlayerPawn)
DEFINE_CLASS_PROPERTY_PREFIX(player, invulnerabilitymode, S, PlayerPawn)
{
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)
{
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)
{
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);
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);
assert(info->IsKindOf(RUNTIME_CLASS(PClassPlayerPawn)));
if (slot < 0 || slot > 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);
weapons << ' ' << str;
}
info->Meta.SetMetaString(APMETA_Slot0 + slot, &weapons[1]);
static_cast<PClassPlayerPawn *>(info)->Slot[slot] = &weapons[1];
}
}