- implemented the remaining dynamic structures of dsdhacked

This commit is contained in:
Christoph Oelckers 2021-09-13 00:12:08 +02:00
parent 24d57b58c5
commit bdd02d9b2c

View file

@ -105,6 +105,8 @@ struct DEHSprName
char c[5];
};
static TArray<DEHSprName> OrgSprNames;
size_t OrgSprOrgSize;
static TMap<FState*, int> stateSprites;
struct StateMapper
{
@ -139,12 +141,75 @@ static PClassActor* FindInfoName(int index, bool mustexist = false)
}
if (!mustexist)
{
return static_cast<PClassActor*>(RUNTIME_CLASS(AActor)->CreateDerivedClass(name.GetChars(), (unsigned)sizeof(AActor)));
cls = static_cast<PClassActor*>(RUNTIME_CLASS(AActor)->CreateDerivedClass(name.GetChars(), (unsigned)sizeof(AActor)));
NewClassType(cls, -1); // This needs a VM type to work as intended.
return cls;
}
}
return nullptr;
}
static FSoundID DehFindSound(int index,bool mustexist = false)
{
if (index < 0) return NO_SOUND;
if (index < (int) SoundMap.Size()) return SoundMap[index];
FStringf name("~dsdhacked/#%d", index);
if (dsdhacked && !mustexist) return soundEngine->FindSoundTentative(name);
return NO_SOUND;
}
static void ReplaceSoundName(int index, const char* newname)
{
// This must physically replace the sound's lump name in the sound record.
auto snd = DehFindSound(index-1);
if (snd == NO_SOUND) return;
auto sfx = soundEngine->GetWritableSfx(snd);
FStringf dsname("ds%s", newname);
sfx->lumpnum = fileSystem.CheckNumForName(dsname, FileSys::ns_sounds);
sfx->bTentative = false;
sfx->bRandomHeader = false;
sfx->bLoadRAW = false;
sfx->b16bit = false;
sfx->bUsed = false;
sfx->UserData[0] = 0;
}
void RemapAllSprites()
{
TMap<FState*, int>::Iterator it(stateSprites);
TMap<FState*, int>::Pair *pair;
while (it.NextPair(pair))
{
int frameNum = 0; // Hmmm...
auto info = pair->Key;
int val = pair->Value;
unsigned int i;
if (val >= 0 && val < (int)OrgSprNames.Size())
{
for (i = 0; i < sprites.Size(); i++)
{
if (memcmp (OrgSprNames[val].c, sprites[i].name, 4) == 0)
{
info->sprite = (int)i;
break;
}
}
if (i == sprites.Size ())
{
Printf ("Frame %d: Sprite %d (%s) is undefined\n",
frameNum, val, OrgSprNames[val].c);
}
}
else
{
Printf ("Frame %d: Sprite %d out of range\n", frameNum, val);
}
}
stateSprites.Clear();
}
// bit flags for PatchThing (a .bex extension):
struct BitName
{
@ -202,11 +267,10 @@ struct MBFParamState
return argsused & (1 << i)? (int)args[i] : def;
}
int GetSoundArg(int i, int def = 0)
FSoundID GetSoundArg(int i, int def = 0)
{
int num = argsused & (1 << i) ? (int)args[i] : def;
if (num > 0 && num <= int(SoundMap.Size())) return SoundMap[num-1].index();
return 0;
return DehFindSound(num-1, true);
}
double GetFloatArg(int i, double def = 0)
@ -394,8 +458,8 @@ static int PatchPars (int);
static int PatchCodePtrs (int);
static int PatchMusic (int);
static int DoInclude (int);
static int PatchSpriteNames(int) { return 0; } // todo
static int PatchSoundNames(int) { return 0; } // todo
static int PatchSpriteNames(int);
static int PatchSoundNames(int);
static bool DoDehPatch();
static const struct {
@ -762,7 +826,7 @@ static void CreateFaceFunc(FunctionCallEmitter &emitters, int value1, int value2
static void CreateScratchFunc(FunctionCallEmitter &emitters, int value1, int value2, MBFParamState* state)
{ // A_CustomMeleeAttack
emitters.AddParameterIntConst(value1); // damage
emitters.AddParameterIntConst(value2 ? (int)SoundMap[value2 - 1].index() : 0); // hit sound
emitters.AddParameterIntConst(DehFindSound(value2 - 1, true).index()); // hit sound
emitters.AddParameterIntConst(0); // miss sound
emitters.AddParameterIntConst(NAME_None); // damage type
emitters.AddParameterIntConst(true); // bleed
@ -771,7 +835,7 @@ static void CreateScratchFunc(FunctionCallEmitter &emitters, int value1, int val
// misc1 = sound, misc2 = attenuation none (true) or normal (false)
static void CreatePlaySoundFunc(FunctionCallEmitter &emitters, int value1, int value2, MBFParamState* state)
{ // A_PlaySound
emitters.AddParameterIntConst(value1 ? (int)SoundMap[value1 - 1].index() : 0); // soundid
emitters.AddParameterIntConst(DehFindSound(value1 - 1, true).index()); // soundid
emitters.AddParameterIntConst(CHAN_BODY); // channel
emitters.AddParameterFloatConst(1); // volume
emitters.AddParameterIntConst(false); // looping
@ -840,7 +904,7 @@ static void CreateMonsterMeleeAttackFunc(FunctionCallEmitter &emitters, int valu
state->ValidateArgCount(4, "A_MonsterMeleeAttack");
emitters.AddParameterIntConst(state->GetIntArg(0, 3));
emitters.AddParameterIntConst(state->GetIntArg(1, 8));
emitters.AddParameterIntConst(state->GetSoundArg(2, 0));
emitters.AddParameterIntConst(state->GetSoundArg(2, 0).index());
emitters.AddParameterFloatConst(state->GetFloatArg(3));
}
@ -856,7 +920,7 @@ static void CreateHealChaseFunc(FunctionCallEmitter &emitters, int value1, int v
{
state->ValidateArgCount(2, "A_HealChase");
emitters.AddParameterPointerConst(state->GetStateArg(0));
emitters.AddParameterIntConst(state->GetSoundArg(1));
emitters.AddParameterIntConst(state->GetSoundArg(1).index());
}
static void CreateSeekTracerFunc(FunctionCallEmitter &emitters, int value1, int value2, MBFParamState* state)
@ -928,14 +992,14 @@ static void CreateWeaponMeleeAttackFunc(FunctionCallEmitter &emitters, int value
emitters.AddParameterIntConst(state->GetIntArg(0, 2));
emitters.AddParameterIntConst(state->GetIntArg(1, 10));
emitters.AddParameterFloatConst(state->GetFloatArg(2, 1));
emitters.AddParameterIntConst(state->GetSoundArg(3));
emitters.AddParameterIntConst(state->GetSoundArg(3).index());
emitters.AddParameterFloatConst(state->GetFloatArg(4));
}
static void CreateWeaponSoundFunc(FunctionCallEmitter &emitters, int value1, int value2, MBFParamState* state)
{
state->ValidateArgCount(2, "A_WeaponSound");
emitters.AddParameterIntConst(state->GetSoundArg(0));
emitters.AddParameterIntConst(state->GetSoundArg(0).index());
emitters.AddParameterIntConst(state->GetIntArg(1));
}
@ -1411,9 +1475,9 @@ static int PatchThing (int thingy)
}
else if (stricmp (Line1 + linelen - 6, " sound") == 0)
{
FSoundID snd = NO_SOUND;
FSoundID snd = DehFindSound(val - 1);
if (val == 0 || val >= SoundMap.Size())
if (snd == NO_SOUND) // This won't trigger for dsdhacked patches!
{
if (endptr == Line2)
{ // Sound was not a (valid) number,
@ -1422,10 +1486,6 @@ static int PatchThing (int thingy)
snd = S_FindSound(Line2);
}
}
else
{
snd = SoundMap[val-1];
}
if (!strnicmp (Line1, "Alert", 5))
info->SeeSound = snd;
@ -1817,28 +1877,7 @@ static int PatchFrame (int frameNum)
}
else if (keylen == 13 && stricmp (Line1, "Sprite number") == 0)
{
unsigned int i;
if (val < (int)OrgSprNames.Size())
{
for (i = 0; i < sprites.Size(); i++)
{
if (memcmp (OrgSprNames[val].c, sprites[i].name, 4) == 0)
{
info->sprite = (int)i;
break;
}
}
if (i == sprites.Size ())
{
Printf ("Frame %d: Sprite %d (%s) is undefined\n",
frameNum, val, OrgSprNames[val].c);
}
}
else
{
Printf ("Frame %d: Sprite %d out of range\n", frameNum, val);
}
stateSprites.Insert(info, val);
}
else if (keylen == 10 && stricmp (Line1, "Next frame") == 0)
{
@ -1940,7 +1979,7 @@ static int PatchSprite (int sprNum)
int result;
int offset = 0;
if ((unsigned)sprNum < OrgSprNames.Size())
if ((unsigned)sprNum < OrgSprOrgSize)
{
DPrintf (DMSG_SPAMMY, "Sprite %d\n", sprNum);
}
@ -1957,12 +1996,12 @@ static int PatchSprite (int sprNum)
else Printf (unknown_str, Line1, "Sprite", sprNum);
}
if (offset > 0 && sprNum != -1)
if (offset > 0 && sprNum != -1 && !dsdhacked)
{
// Calculate offset from beginning of sprite names.
offset = (offset - toff[dversion] - 22044) / 8;
if ((unsigned)offset < OrgSprNames.Size())
if ((unsigned)offset < OrgSprOrgSize)
{
sprNum = FindSprite (OrgSprNames[sprNum].c);
if (sprNum != -1)
@ -2609,6 +2648,7 @@ static int PatchPars (int dummy)
return result;
}
static int PatchCodePtrs (int dummy)
{
int result;
@ -2702,6 +2742,40 @@ static int PatchMusic (int dummy)
return result;
}
// This repplaces a sprite name in the current working data
static void ReplaceSpriteInData(const char* oldStr, const char* newStr)
{
if (strncmp ("PLAY", oldStr, 4) == 0)
{
strncpy (deh.PlayerSprite, newStr, 4);
}
// If this sprite is used by a pickup, then the DehackedPickup sprite map
// needs to be updated too.
for (size_t i = 0; i < countof(DehSpriteMappings); ++i)
{
if (strncmp (DehSpriteMappings[i].Sprite, oldStr, 4) == 0)
{
// Found a match, so change it.
strncpy (DehSpriteMappings[i].Sprite, newStr, 4);
// Now shift the map's entries around so that it stays sorted.
// This must be done because the map is scanned using a binary search.
while (i > 0 && strncmp (DehSpriteMappings[i-1].Sprite, newStr, 4) > 0)
{
std::swap (DehSpriteMappings[i-1], DehSpriteMappings[i]);
--i;
}
while ((size_t)i < countof(DehSpriteMappings)-1 &&
strncmp (DehSpriteMappings[i+1].Sprite, newStr, 4) < 0)
{
std::swap (DehSpriteMappings[i+1], DehSpriteMappings[i]);
++i;
}
break;
}
}
}
static int PatchText (int oldSize)
{
@ -2759,42 +2833,14 @@ static int PatchText (int oldSize)
if (i != -1)
{
strncpy (sprites[i].name, newStr, 4);
if (strncmp ("PLAY", oldStr, 4) == 0)
{
strncpy (deh.PlayerSprite, newStr, 4);
}
for (unsigned ii = 0; ii < OrgSprNames.Size(); ii++)
for (unsigned ii = 0; ii < OrgSprOrgSize; ii++)
{
if (!stricmp(OrgSprNames[ii].c, oldStr))
{
strcpy(OrgSprNames[ii].c, newStr);
}
}
// If this sprite is used by a pickup, then the DehackedPickup sprite map
// needs to be updated too.
for (i = 0; (size_t)i < countof(DehSpriteMappings); ++i)
{
if (strncmp (DehSpriteMappings[i].Sprite, oldStr, 4) == 0)
{
// Found a match, so change it.
strncpy (DehSpriteMappings[i].Sprite, newStr, 4);
// Now shift the map's entries around so that it stays sorted.
// This must be done because the map is scanned using a binary search.
while (i > 0 && strncmp (DehSpriteMappings[i-1].Sprite, newStr, 4) > 0)
{
std::swap (DehSpriteMappings[i-1], DehSpriteMappings[i]);
--i;
}
while ((size_t)i < countof(DehSpriteMappings)-1 &&
strncmp (DehSpriteMappings[i+1].Sprite, newStr, 4) < 0)
{
std::swap (DehSpriteMappings[i+1], DehSpriteMappings[i]);
++i;
}
break;
}
}
ReplaceSpriteInData(oldStr, newStr);
goto donewithtext;
}
}
@ -2875,6 +2921,57 @@ static int PatchStrings (int dummy)
return result;
}
static int PatchSoundNames (int dummy)
{
int result;
DPrintf (DMSG_SPAMMY, "[Sounds]\n");
while ((result = GetLine()) == 1)
{
FString newname = skipwhite (Line2);
ReplaceSoundName((int)strtoll(Line1, nullptr, 10), newname);
DPrintf (DMSG_SPAMMY, "Sound %d set to:\n%s\n", Line1, newname.GetChars());
}
return result;
}
static int PatchSpriteNames (int dummy)
{
int result;
DPrintf (DMSG_SPAMMY, "[Sprites]\n");
while ((result = GetLine()) == 1)
{
FString newname = skipwhite (Line2);
if (newname.Len() != 4)
{
Printf("Sprite name must be 4 characters long, got '%s'\n", newname.GetChars());
continue;
}
int64_t line1val = strtoll(Line1, nullptr, 10);
if (line1val >= OrgSprNames.Size())
{
unsigned osize = OrgSprNames.Size();
OrgSprNames.Resize(line1val + 1);
DEHSprName nulname{};
for (unsigned o = osize; o < OrgSprNames.Size(); o++)
{
OrgSprNames[o] = nulname;
}
int v = GetSpriteIndex(newname);
memcpy(OrgSprNames[line1val].c, sprites[v].name, 5);
}
DPrintf (DMSG_SPAMMY, "Sprite %d set to:\n%s\n", Line1, newname.GetChars());
}
return result;
}
static int DoInclude (int dummy)
{
char *data;
@ -3345,6 +3442,7 @@ static bool LoadDehSupp ()
if (sc.CheckString("}")) break;
sc.MustGetStringName(",");
}
OrgSprOrgSize = OrgSprNames.Size();
}
else if (sc.Compare("StateMap"))
{
@ -3557,7 +3655,8 @@ void FinishDehPatch ()
{
GetDefaultByType(cls)->flags8 |= MF8_RETARGETAFTERSLAM;
}
RemapAllSprites();
for (touchedIndex = 0; touchedIndex < TouchedActors.Size(); ++touchedIndex)
{
PClassActor *subclass;