- dsdhacked: Allow dynamic creation of new actors

This commit is contained in:
Christoph Oelckers 2021-09-12 21:45:51 +02:00
parent b44741b8aa
commit 24d57b58c5

View file

@ -97,6 +97,7 @@ static TArray<int> OrgHeights;
// disappear, but that doesn't explain why frame patches specify an exact // disappear, but that doesn't explain why frame patches specify an exact
// state rather than a code pointer.) // state rather than a code pointer.)
static TArray<int> CodePConv; static TArray<int> CodePConv;
static bool dsdhacked = false;
// Sprite names in the order Doom originally had them. // Sprite names in the order Doom originally had them.
struct DEHSprName struct DEHSprName
@ -122,6 +123,28 @@ static TArray<FSoundID> SoundMap;
// Names of different actor types, in original Doom 2 order // Names of different actor types, in original Doom 2 order
static TArray<PClassActor *> InfoNames; static TArray<PClassActor *> InfoNames;
static PClassActor* FindInfoName(int index, bool mustexist = false)
{
if (index < 0) return nullptr;
if (index < (int)InfoNames.Size()) return InfoNames[index];
if (dsdhacked)
{
FStringf name("~Dsdhacked~%d", index);
auto cls = PClass::FindActor(name);
if (cls)
{
GetDefaultByType(cls)->flags8 |= MF8_RETARGETAFTERSLAM; // This flag is not a ZDoom default, but it must be a Dehacked default.
return cls;
}
if (!mustexist)
{
return static_cast<PClassActor*>(RUNTIME_CLASS(AActor)->CreateDerivedClass(name.GetChars(), (unsigned)sizeof(AActor)));
}
}
return nullptr;
}
// bit flags for PatchThing (a .bex extension): // bit flags for PatchThing (a .bex extension):
struct BitName struct BitName
{ {
@ -163,10 +186,8 @@ struct MBFParamState
PClassActor* GetTypeArg(int i) PClassActor* GetTypeArg(int i)
{ {
PClassActor* type = nullptr;
int num = (int)args[i]; int num = (int)args[i];
if (num > 0 && num < int(InfoNames.Size())) type = InfoNames[num-1]; // Dehacked is 1-based. return FindInfoName(num-1, true);
return type;
} }
FState* GetStateArg(int i) FState* GetStateArg(int i)
@ -341,7 +362,7 @@ FString PatchName;
static int PatchSize; static int PatchSize;
static char *Line1, *Line2; static char *Line1, *Line2;
static int dversion, pversion; static int dversion, pversion;
static bool including, includenotext, dsdhacked = false; static bool including, includenotext;
static int LumpFileNum; static int LumpFileNum;
static const char *unknown_str = "Unknown key %s encountered in %s %d.\n"; static const char *unknown_str = "Unknown key %s encountered in %s %d.\n";
@ -373,8 +394,8 @@ static int PatchPars (int);
static int PatchCodePtrs (int); static int PatchCodePtrs (int);
static int PatchMusic (int); static int PatchMusic (int);
static int DoInclude (int); static int DoInclude (int);
static int PatchSpriteNames (int); static int PatchSpriteNames(int) { return 0; } // todo
static int PatchSoundNames(int) {} // todo static int PatchSoundNames(int) { return 0; } // todo
static bool DoDehPatch(); static bool DoDehPatch();
static const struct { static const struct {
@ -710,11 +731,12 @@ static void CreateMushroomFunc(FunctionCallEmitter &emitters, int value1, int va
// misc1 = type (arg +0), misc2 = Z-pos (arg +2) // misc1 = type (arg +0), misc2 = Z-pos (arg +2)
static void CreateSpawnFunc(FunctionCallEmitter &emitters, int value1, int value2, MBFParamState* state) static void CreateSpawnFunc(FunctionCallEmitter &emitters, int value1, int value2, MBFParamState* state)
{ // A_SpawnItem { // A_SpawnItem
if (InfoNames[value1-1] == nullptr) auto p = FindInfoName(value1 - 1, true);
if (p == nullptr)
{ {
I_Error("No class found for dehackednum %d!\n", value1+1); I_Error("No class found for dehackednum %d!\n", value1+1);
} }
emitters.AddParameterPointerConst(InfoNames[value1-1]); // itemtype emitters.AddParameterPointerConst(p); // itemtype
emitters.AddParameterFloatConst(0); // distance emitters.AddParameterFloatConst(0); // distance
emitters.AddParameterFloatConst(value2); // height emitters.AddParameterFloatConst(value2); // height
emitters.AddParameterIntConst(0); // useammo emitters.AddParameterIntConst(0); // useammo
@ -1124,30 +1146,17 @@ static int PatchThing (int thingy)
type = NULL; type = NULL;
info = (AActor *)&dummy; info = (AActor *)&dummy;
ednum = &dummyed; ednum = &dummyed;
if (thingy > (int)InfoNames.Size() || thingy <= 0) auto thingytype = FindInfoName(thingy-1);
if (thingytype == nullptr)
{ {
Printf ("Thing %d out of range.\n", thingy); Printf ("Thing %d out of range or invalid.\n", thingy);
} }
else else
{ {
DPrintf (DMSG_SPAMMY, "Thing %d\n", thingy); DPrintf (DMSG_SPAMMY, "Thing %d\n", thingy);
if (thingy > 0)
{
type = InfoNames[thingy - 1];
if (type == NULL)
{
info = (AActor *)&dummy;
ednum = &dummyed;
// An error for the name has already been printed while loading DEHSUPP.
Printf ("Could not find thing %d\n", thingy);
}
else
{
info = GetDefaultByType (type); info = GetDefaultByType (type);
ednum = &type->ActorInfo()->DoomEdNum; ednum = &type->ActorInfo()->DoomEdNum;
} }
}
}
oldflags = info->flags; oldflags = info->flags;
@ -1280,13 +1289,13 @@ static int PatchThing (int thingy)
} }
else if (linelen == 12 && stricmp(Line1, "dropped item") == 0) else if (linelen == 12 && stricmp(Line1, "dropped item") == 0)
{ {
val--; // This is 1-based and 0 means 'no drop'. auto drop = FindInfoName(val - 1);
if ((unsigned)val < InfoNames.Size()) if (drop)
{ {
FDropItem* di = (FDropItem*)ClassDataAllocator.Alloc(sizeof(FDropItem)); FDropItem* di = (FDropItem*)ClassDataAllocator.Alloc(sizeof(FDropItem));
di->Next = nullptr; di->Next = nullptr;
di->Name = InfoNames[val]->TypeName.GetChars(); di->Name = drop->TypeName;
di->Probability = 255; di->Probability = 255;
di->Amount = -1; di->Amount = -1;
info->GetInfo()->DropItems = di; info->GetInfo()->DropItems = di;