- 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
// state rather than a code pointer.)
static TArray<int> CodePConv;
static bool dsdhacked = false;
// Sprite names in the order Doom originally had them.
struct DEHSprName
@ -122,6 +123,28 @@ static TArray<FSoundID> SoundMap;
// Names of different actor types, in original Doom 2 order
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):
struct BitName
{
@ -163,10 +186,8 @@ struct MBFParamState
PClassActor* GetTypeArg(int i)
{
PClassActor* type = nullptr;
int num = (int)args[i];
if (num > 0 && num < int(InfoNames.Size())) type = InfoNames[num-1]; // Dehacked is 1-based.
return type;
return FindInfoName(num-1, true);
}
FState* GetStateArg(int i)
@ -341,7 +362,7 @@ FString PatchName;
static int PatchSize;
static char *Line1, *Line2;
static int dversion, pversion;
static bool including, includenotext, dsdhacked = false;
static bool including, includenotext;
static int LumpFileNum;
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 PatchMusic (int);
static int DoInclude (int);
static int PatchSpriteNames (int);
static int PatchSoundNames(int) {} // todo
static int PatchSpriteNames(int) { return 0; } // todo
static int PatchSoundNames(int) { return 0; } // todo
static bool DoDehPatch();
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)
static void CreateSpawnFunc(FunctionCallEmitter &emitters, int value1, int value2, MBFParamState* state)
{ // 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);
}
emitters.AddParameterPointerConst(InfoNames[value1-1]); // itemtype
emitters.AddParameterPointerConst(p); // itemtype
emitters.AddParameterFloatConst(0); // distance
emitters.AddParameterFloatConst(value2); // height
emitters.AddParameterIntConst(0); // useammo
@ -1124,29 +1146,16 @@ static int PatchThing (int thingy)
type = NULL;
info = (AActor *)&dummy;
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
{
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);
ednum = &type->ActorInfo()->DoomEdNum;
}
}
info = GetDefaultByType (type);
ednum = &type->ActorInfo()->DoomEdNum;
}
oldflags = info->flags;
@ -1280,13 +1289,13 @@ static int PatchThing (int thingy)
}
else if (linelen == 12 && stricmp(Line1, "dropped item") == 0)
{
val--; // This is 1-based and 0 means 'no drop'.
if ((unsigned)val < InfoNames.Size())
auto drop = FindInfoName(val - 1);
if (drop)
{
FDropItem* di = (FDropItem*)ClassDataAllocator.Alloc(sizeof(FDropItem));
di->Next = nullptr;
di->Name = InfoNames[val]->TypeName.GetChars();
di->Name = drop->TypeName;
di->Probability = 255;
di->Amount = -1;
info->GetInfo()->DropItems = di;