diff --git a/src/gamedata/d_dehacked.cpp b/src/gamedata/d_dehacked.cpp index db87de3cdd..97f927475b 100644 --- a/src/gamedata/d_dehacked.cpp +++ b/src/gamedata/d_dehacked.cpp @@ -97,6 +97,7 @@ static TArray OrgHeights; // disappear, but that doesn't explain why frame patches specify an exact // state rather than a code pointer.) static TArray CodePConv; +static bool dsdhacked = false; // Sprite names in the order Doom originally had them. struct DEHSprName @@ -122,6 +123,28 @@ static TArray SoundMap; // Names of different actor types, in original Doom 2 order static TArray 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(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;