- tabified the rest of Blood's code.

This commit is contained in:
Christoph Oelckers 2021-12-29 22:56:21 +01:00
parent b7d095b943
commit 5061d5b37c
32 changed files with 18547 additions and 17165 deletions

View file

@ -34,7 +34,7 @@ BEGIN_BLD_NS
GAMEOPTIONS gGameOptions; GAMEOPTIONS gGameOptions;
GAMEOPTIONS gSingleGameOptions = { GAMEOPTIONS gSingleGameOptions = {
0, 2, 0, 0, 0, 0, 0, 0, 2, 3600, 1800, 1800, 7200 0, 2, 0, 0, 0, 0, 0, 0, 2, 3600, 1800, 1800, 7200
}; };
int gSkill = 2; int gSkill = 2;
@ -42,216 +42,256 @@ MapRecord* gNextLevel;
char BloodIniFile[BMAX_PATH] = "BLOOD.INI"; char BloodIniFile[BMAX_PATH] = "BLOOD.INI";
bool bINIOverride = false; bool bINIOverride = false;
IniFile *BloodINI; IniFile* BloodINI;
void levelInitINI(const char *pzIni) //---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void levelInitINI(const char* pzIni)
{ {
if (!fileSystem.FileExists(pzIni)) if (!fileSystem.FileExists(pzIni))
I_Error("Initialization: %s does not exist", pzIni); I_Error("Initialization: %s does not exist", pzIni);
BloodINI = new IniFile(pzIni); BloodINI = new IniFile(pzIni);
strncpy(BloodIniFile, pzIni, BMAX_PATH-1); strncpy(BloodIniFile, pzIni, BMAX_PATH - 1);
} }
void CheckSectionAbend(const char *pzSection) void CheckSectionAbend(const char* pzSection)
{ {
if (!pzSection || !BloodINI->SectionExists(pzSection)) if (!pzSection || !BloodINI->SectionExists(pzSection))
I_Error("Section [%s] expected in BLOOD.INI", pzSection); I_Error("Section [%s] expected in BLOOD.INI", pzSection);
} }
void CheckKeyAbend(const char *pzSection, const char *pzKey) void CheckKeyAbend(const char* pzSection, const char* pzKey)
{ {
assert(pzSection != NULL); assert(pzSection != NULL);
if (!pzKey || !BloodINI->KeyExists(pzSection, pzKey)) if (!pzKey || !BloodINI->KeyExists(pzSection, pzKey))
I_Error("Key %s expected in section [%s] of BLOOD.INI", pzKey, pzSection); I_Error("Key %s expected in section [%s] of BLOOD.INI", pzKey, pzSection);
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void levelLoadMapInfo(IniFile* pIni, MapRecord* pLevelInfo, const char* pzSection, int epinum, int mapnum, int* nextmap, int* nextsecret) void levelLoadMapInfo(IniFile* pIni, MapRecord* pLevelInfo, const char* pzSection, int epinum, int mapnum, int* nextmap, int* nextsecret)
{ {
char buffer[16]; char buffer[16];
pLevelInfo->SetName(pIni->GetKeyString(pzSection, "Title", pLevelInfo->labelName)); pLevelInfo->SetName(pIni->GetKeyString(pzSection, "Title", pLevelInfo->labelName));
pLevelInfo->Author = pIni->GetKeyString(pzSection, "Author", ""); pLevelInfo->Author = pIni->GetKeyString(pzSection, "Author", "");
pLevelInfo->music = pIni->GetKeyString(pzSection, "Song", ""); if (pLevelInfo->music.IsNotEmpty()) DefaultExtension(pLevelInfo->music, ".mid"); pLevelInfo->music = pIni->GetKeyString(pzSection, "Song", ""); if (pLevelInfo->music.IsNotEmpty()) DefaultExtension(pLevelInfo->music, ".mid");
pLevelInfo->cdSongId = pIni->GetKeyInt(pzSection, "Track", -1); pLevelInfo->cdSongId = pIni->GetKeyInt(pzSection, "Track", -1);
*nextmap = pIni->GetKeyInt(pzSection, "EndingA", 0); *nextmap = pIni->GetKeyInt(pzSection, "EndingA", 0);
*nextsecret = pIni->GetKeyInt(pzSection, "EndingB", 0); *nextsecret = pIni->GetKeyInt(pzSection, "EndingB", 0);
pLevelInfo->fog = pIni->GetKeyInt(pzSection, "Fog", -0); pLevelInfo->fog = pIni->GetKeyInt(pzSection, "Fog", -0);
pLevelInfo->weather = pIni->GetKeyInt(pzSection, "Weather", -0); pLevelInfo->weather = pIni->GetKeyInt(pzSection, "Weather", -0);
for (int i = 0; i < kMaxMessages; i++) for (int i = 0; i < kMaxMessages; i++)
{ {
sprintf(buffer, "Message%d", i + 1); sprintf(buffer, "Message%d", i + 1);
auto msg = pIni->GetKeyString(pzSection, buffer, ""); auto msg = pIni->GetKeyString(pzSection, buffer, "");
pLevelInfo->AddMessage(i, msg); pLevelInfo->AddMessage(i, msg);
} }
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static const char* DefFile(void) static const char* DefFile(void)
{ {
int found = -1; int found = -1;
if (userConfig.DefaultCon.IsEmpty() || userConfig.DefaultCon.CompareNoCase("blood.ini") == 0) if (userConfig.DefaultCon.IsEmpty() || userConfig.DefaultCon.CompareNoCase("blood.ini") == 0)
{ {
int numlumps = fileSystem.GetNumEntries(); int numlumps = fileSystem.GetNumEntries();
for (int i = numlumps - 1; i >= 0; i--) for (int i = numlumps - 1; i >= 0; i--)
{ {
int fileno = fileSystem.GetFileContainer(i); int fileno = fileSystem.GetFileContainer(i);
if (fileno != -1 && fileno <= fileSystem.GetMaxIwadNum()) continue; if (fileno != -1 && fileno <= fileSystem.GetMaxIwadNum()) continue;
FString fn = fileSystem.GetFileFullName(i, false); FString fn = fileSystem.GetFileFullName(i, false);
FString ext = fn.Right(4); FString ext = fn.Right(4);
if (ext.CompareNoCase(".ini") == 0) if (ext.CompareNoCase(".ini") == 0)
{ {
if (fileSystem.CheckNumForFullName(fn) != i) continue; if (fileSystem.CheckNumForFullName(fn) != i) continue;
if (found == -1) if (found == -1)
{ {
IniFile inif(fn); IniFile inif(fn);
for (int j = 1; j <= 6; j++) for (int j = 1; j <= 6; j++)
{ {
FStringf key("Episode%d", j); FStringf key("Episode%d", j);
if (inif.SectionExists(key)) if (inif.SectionExists(key))
{ {
found = i; found = i;
break; break;
} }
} }
} }
else else
{ {
found = -1; found = -1;
break; break;
} }
} }
} }
} }
if (found >= 0) return fileSystem.GetFileFullName(found); if (found >= 0) return fileSystem.GetFileFullName(found);
// The command line parser stores this in the CON field. // The command line parser stores this in the CON field.
return userConfig.DefaultCon.IsNotEmpty() ? userConfig.DefaultCon.GetChars() : "blood.ini"; return userConfig.DefaultCon.IsNotEmpty() ? userConfig.DefaultCon.GetChars() : "blood.ini";
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static FString cleanPath(const char* pth) static FString cleanPath(const char* pth)
{ {
FString path = pth; FString path = pth;
FixPathSeperator(path); FixPathSeperator(path);
if (fileSystem.FileExists(path)) return path; if (fileSystem.FileExists(path)) return path;
if (path.Len() > 3 && path[1] == ':' && isalpha(path[0]) && path[2] == '/') if (path.Len() > 3 && path[1] == ':' && isalpha(path[0]) && path[2] == '/')
{ {
path = path.Mid(3); path = path.Mid(3);
if (fileSystem.FileExists(path)) return path; if (fileSystem.FileExists(path)) return path;
} }
// optionally strip the first path component to account for poor logic of the DOS EXE. // optionally strip the first path component to account for poor logic of the DOS EXE.
auto pos = path.IndexOf("/"); auto pos = path.IndexOf("/");
if (pos >= 0) if (pos >= 0)
{ {
auto npath = path.Mid(pos + 1); auto npath = path.Mid(pos + 1);
if (fileSystem.FileExists(npath)) return npath; if (fileSystem.FileExists(npath)) return npath;
} }
return path; return path;
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void levelLoadDefaults(void) void levelLoadDefaults(void)
{ {
char buffer[64]; char buffer[64];
char buffer2[16]; char buffer2[16];
int cutALevel = 0; int cutALevel = 0;
levelInitINI(DefFile()); levelInitINI(DefFile());
int i; int i;
for (i = 1; i <= kMaxEpisodes; i++) for (i = 1; i <= kMaxEpisodes; i++)
{ {
sprintf(buffer, "Episode%d", i); sprintf(buffer, "Episode%d", i);
if (!BloodINI->SectionExists(buffer)) if (!BloodINI->SectionExists(buffer))
break; break;
auto cluster = MustFindCluster(i); auto cluster = MustFindCluster(i);
auto volume = MustFindVolume(i); auto volume = MustFindVolume(i);
CutsceneDef &csB = cluster->outro; CutsceneDef& csB = cluster->outro;
FString ep_str = BloodINI->GetKeyString(buffer, "Title", buffer); FString ep_str = BloodINI->GetKeyString(buffer, "Title", buffer);
ep_str.StripRight(); ep_str.StripRight();
cluster->name = volume->name = FStringTable::MakeMacro(ep_str); cluster->name = volume->name = FStringTable::MakeMacro(ep_str);
if (i > 1) volume->flags |= VF_SHAREWARELOCK; if (i > 1) volume->flags |= VF_SHAREWARELOCK;
if (BloodINI->GetKeyInt(buffer, "BloodBathOnly", 0)) volume->flags |= VF_HIDEFROMSP; if (BloodINI->GetKeyInt(buffer, "BloodBathOnly", 0)) volume->flags |= VF_HIDEFROMSP;
csB.video = cleanPath(BloodINI->GetKeyString(buffer, "CutSceneB", "")); csB.video = cleanPath(BloodINI->GetKeyString(buffer, "CutSceneB", ""));
int soundint = BloodINI->GetKeyInt(buffer, "CutWavB", -1); int soundint = BloodINI->GetKeyInt(buffer, "CutWavB", -1);
if (soundint > 0) csB.soundID = soundint + 0x40000000; if (soundint > 0) csB.soundID = soundint + 0x40000000;
else csB.soundName = cleanPath(BloodINI->GetKeyString(buffer, "CutWavB", "")); else csB.soundName = cleanPath(BloodINI->GetKeyString(buffer, "CutWavB", ""));
//pEpisodeInfo->bloodbath = BloodINI->GetKeyInt(buffer, "BloodBathOnly", 0); //pEpisodeInfo->bloodbath = BloodINI->GetKeyInt(buffer, "BloodBathOnly", 0);
cutALevel = BloodINI->GetKeyInt(buffer, "CutSceneALevel", 0); cutALevel = BloodINI->GetKeyInt(buffer, "CutSceneALevel", 0);
if (cutALevel < 1) cutALevel = 1; if (cutALevel < 1) cutALevel = 1;
int nextmaps[kMaxLevels]{}, nextsecrets[kMaxLevels]{}; int nextmaps[kMaxLevels]{}, nextsecrets[kMaxLevels]{};
for (int j = 1; j <= kMaxLevels; j++) for (int j = 1; j <= kMaxLevels; j++)
{ {
sprintf(buffer2, "Map%d", j); sprintf(buffer2, "Map%d", j);
if (!BloodINI->KeyExists(buffer, buffer2)) if (!BloodINI->KeyExists(buffer, buffer2))
break; break;
auto pLevelInfo = AllocateMap(); auto pLevelInfo = AllocateMap();
const char *pMap = BloodINI->GetKeyString(buffer, buffer2, NULL); const char* pMap = BloodINI->GetKeyString(buffer, buffer2, NULL);
CheckSectionAbend(pMap); CheckSectionAbend(pMap);
SetLevelNum(pLevelInfo, makelevelnum(i, j)); SetLevelNum(pLevelInfo, makelevelnum(i, j));
pLevelInfo->cluster = i; pLevelInfo->cluster = i;
pLevelInfo->labelName = pMap; pLevelInfo->labelName = pMap;
if (j == 1) volume->startmap = pLevelInfo->labelName; if (j == 1) volume->startmap = pLevelInfo->labelName;
pLevelInfo->fileName.Format("%s.map", pMap); pLevelInfo->fileName.Format("%s.map", pMap);
levelLoadMapInfo(BloodINI, pLevelInfo, pMap, i, j, &nextmaps[j - 1], &nextsecrets[j - 1]); levelLoadMapInfo(BloodINI, pLevelInfo, pMap, i, j, &nextmaps[j - 1], &nextsecrets[j - 1]);
if (j == cutALevel) if (j == cutALevel)
{ {
CutsceneDef& csA = pLevelInfo->intro; CutsceneDef& csA = pLevelInfo->intro;
csA.video = cleanPath(BloodINI->GetKeyString(buffer, "CutSceneA", "")); csA.video = cleanPath(BloodINI->GetKeyString(buffer, "CutSceneA", ""));
int soundfileint = BloodINI->GetKeyInt(buffer, "CutWavA", -1); int soundfileint = BloodINI->GetKeyInt(buffer, "CutWavA", -1);
if (soundfileint > 0) csA.soundID = soundfileint + 0x40000000; if (soundfileint > 0) csA.soundID = soundfileint + 0x40000000;
else csA.soundName = cleanPath(BloodINI->GetKeyString(buffer, "CutWavA", "")); else csA.soundName = cleanPath(BloodINI->GetKeyString(buffer, "CutWavA", ""));
} }
} }
// Now resolve the level links // Now resolve the level links
for (int j = 1; j <= kMaxLevels; j++) for (int j = 1; j <= kMaxLevels; j++)
{ {
auto map = FindMapByIndexOnly(i, j); auto map = FindMapByIndexOnly(i, j);
if (map) if (map)
{ {
if (nextmaps[j - 1] > 0) if (nextmaps[j - 1] > 0)
{ {
auto nmap = FindMapByIndexOnly(i, nextmaps[j - 1]); auto nmap = FindMapByIndexOnly(i, nextmaps[j - 1]);
if (nmap) map->NextMap = nmap->labelName; if (nmap) map->NextMap = nmap->labelName;
else map->NextMap = "-"; else map->NextMap = "-";
} }
else map->NextMap = "-"; else map->NextMap = "-";
if (nextsecrets[j - 1] > 0) if (nextsecrets[j - 1] > 0)
{ {
auto nmap = FindMapByIndexOnly(i, nextsecrets[j - 1]); auto nmap = FindMapByIndexOnly(i, nextsecrets[j - 1]);
if (nmap) map->NextSecret = nmap->labelName; if (nmap) map->NextSecret = nmap->labelName;
else map->NextSecret = "-"; else map->NextSecret = "-";
} }
else map->NextSecret = "-"; else map->NextSecret = "-";
} }
} }
} }
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void levelEndLevel(int secret) void levelEndLevel(int secret)
{ {
gGameOptions.uGameFlags |= GF_AdvanceLevel; gGameOptions.uGameFlags |= GF_AdvanceLevel;
if (!secret) gNextLevel = FindNextMap(currentLevel); if (!secret) gNextLevel = FindNextMap(currentLevel);
else gNextLevel = FindNextSecretMap(currentLevel); else gNextLevel = FindNextSecretMap(currentLevel);
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void levelTryPlayMusic() void levelTryPlayMusic()
{ {
FString buffer; FString buffer;
if (mus_redbook && currentLevel->cdSongId > 0) if (mus_redbook && currentLevel->cdSongId > 0)
buffer.Format("blood%02i.ogg", currentLevel->cdSongId); buffer.Format("blood%02i.ogg", currentLevel->cdSongId);
else else
{ {
buffer = currentLevel->music; buffer = currentLevel->music;
if (Mus_Play(buffer, true)) return; if (Mus_Play(buffer, true)) return;
if (buffer.IsNotEmpty()) DefaultExtension(buffer, ".mid"); if (buffer.IsNotEmpty()) DefaultExtension(buffer, ".mid");
} }
if (!Mus_Play(buffer, true)) if (!Mus_Play(buffer, true))
{ {
Mus_Play("", true); Mus_Play("", true);
} }
} }

View file

@ -46,22 +46,22 @@ enum EGameFlag
}; };
struct GAMEOPTIONS { struct GAMEOPTIONS {
uint8_t nGameType; uint8_t nGameType;
uint8_t nDifficulty; uint8_t nDifficulty;
uint8_t nMonsterSettings; uint8_t nMonsterSettings;
int uGameFlags; int uGameFlags;
int uNetGameFlags; int uNetGameFlags;
uint8_t nWeaponSettings; uint8_t nWeaponSettings;
uint8_t nItemSettings; uint8_t nItemSettings;
uint8_t nRespawnSettings; uint8_t nRespawnSettings;
uint8_t nTeamSettings; uint8_t nTeamSettings;
int nMonsterRespawnTime; int nMonsterRespawnTime;
int nWeaponRespawnTime; int nWeaponRespawnTime;
int nItemRespawnTime; int nItemRespawnTime;
int nSpecialRespawnTime; int nSpecialRespawnTime;
int weaponsV10x; int weaponsV10x;
bool bFriendlyFire; bool bFriendlyFire;
bool bKeepKeysOnRespawn; bool bKeepKeysOnRespawn;
}; };
#pragma pack(pop) #pragma pack(pop)
@ -74,9 +74,9 @@ extern bool bINIOverride;
extern MapRecord* gNextLevel; extern MapRecord* gNextLevel;
extern bool gGameStarted; extern bool gGameStarted;
void levelInitINI(const char *pzIni); void levelInitINI(const char* pzIni);
void CheckSectionAbend(const char *pzSection); void CheckSectionAbend(const char* pzSection);
void CheckKeyAbend(const char *pzSection, const char *pzKey); void CheckKeyAbend(const char* pzSection, const char* pzKey);
void levelLoadDefaults(void); void levelLoadDefaults(void);
// arg: 0 is normal exit, 1 is secret level // arg: 0 is normal exit, 1 is secret level
void levelEndLevel(int arg); void levelEndLevel(int arg);

View file

@ -39,7 +39,7 @@ BEGIN_BLD_NS
void validateLinks(); void validateLinks();
// All AI states for assigning an index. // All AI states for assigning an index.
static AISTATE* allAIStates[] = static AISTATE* const allAIStates[] =
{ {
nullptr, nullptr,
&genIdle, &genIdle,
@ -391,6 +391,12 @@ static AISTATE* allAIStates[] =
&zombieFTeslaRecoil, &zombieFTeslaRecoil,
}; };
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
FSerializer& Serialize(FSerializer& arc, const char* keyname, AISTATE*& w, AISTATE** def) FSerializer& Serialize(FSerializer& arc, const char* keyname, AISTATE*& w, AISTATE** def)
{ {
unsigned i = 0; unsigned i = 0;
@ -456,6 +462,12 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, DUDEEXTRA& w, DUDE
return arc; return arc;
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void DBloodActor::Serialize(FSerializer& arc) void DBloodActor::Serialize(FSerializer& arc)
{ {
Super::Serialize(arc); Super::Serialize(arc);
@ -464,9 +476,9 @@ void DBloodActor::Serialize(FSerializer& arc)
("zvel", zvel) ("zvel", zvel)
("hasx", hasx); ("hasx", hasx);
// The rest is only relevant if the actor has an xsprite. // The rest is only relevant if the actor has an xsprite.
if (hasX()) if (hasX())
{ {
arc("xsprite", xspr) arc("xsprite", xspr)
("dudeslope", dudeSlope) ("dudeslope", dudeSlope)
("dudeextra", dudeExtra) ("dudeextra", dudeExtra)
@ -476,23 +488,29 @@ void DBloodActor::Serialize(FSerializer& arc)
("owneractor", ownerActor); ("owneractor", ownerActor);
#ifdef NOONE_EXTENSIONS #ifdef NOONE_EXTENSIONS
if (gModernMap) if (gModernMap)
{ {
arc("spritemass", spriteMass) arc("spritemass", spriteMass)
("prevmarker", prevmarker) ("prevmarker", prevmarker)
.Array("conditions", condition, 2); .Array("conditions", condition, 2);
// GenDudeExtra only contains valid info for kDudeModernCustom and kDudeModernCustomBurning so only save when needed as these are not small.
if (spr.type == kDudeModernCustom || spr.type == kDudeModernCustomBurning) // GenDudeExtra only contains valid info for kDudeModernCustom and kDudeModernCustomBurning so only save when needed as these are not small.
{ if (spr.type == kDudeModernCustom || spr.type == kDudeModernCustomBurning)
{
arc("gendudeextra", genDudeExtra); arc("gendudeextra", genDudeExtra);
}
} }
}
#endif #endif
} }
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
FSerializer& Serialize(FSerializer& arc, const char* keyname, XWALL& w, XWALL* def) FSerializer& Serialize(FSerializer& arc, const char* keyname, XWALL& w, XWALL* def)
{ {
static XWALL nul; static XWALL nul;
@ -520,6 +538,12 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, XWALL& w, XWALL* d
return arc; return arc;
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
FSerializer& Serialize(FSerializer& arc, const char* keyname, XSECTOR& w, XSECTOR* def) FSerializer& Serialize(FSerializer& arc, const char* keyname, XSECTOR& w, XSECTOR* def)
{ {
static XSECTOR nul; static XSECTOR nul;
@ -573,6 +597,12 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, XSECTOR& w, XSECTO
return arc; return arc;
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
FSerializer& Serialize(FSerializer& arc, const char* keyname, XSPRITE& w, XSPRITE* def) FSerializer& Serialize(FSerializer& arc, const char* keyname, XSPRITE& w, XSPRITE* def)
{ {
static XSPRITE nul; static XSPRITE nul;
@ -623,6 +653,12 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, XSPRITE& w, XSPRIT
return arc; return arc;
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
FSerializer& Serialize(FSerializer& arc, const char* keyname, GAMEOPTIONS& w, GAMEOPTIONS* def) FSerializer& Serialize(FSerializer& arc, const char* keyname, GAMEOPTIONS& w, GAMEOPTIONS* def)
{ {
if (arc.BeginObject(keyname)) if (arc.BeginObject(keyname))
@ -647,6 +683,12 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, GAMEOPTIONS& w, GA
return arc; return arc;
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void SerializeState(FSerializer& arc) void SerializeState(FSerializer& arc)
{ {
if (arc.isReading()) if (arc.isReading())
@ -690,18 +732,24 @@ void SerializeView(FSerializer& arc);
void SerializeNNExts(FSerializer& arc); void SerializeNNExts(FSerializer& arc);
void SerializeMirrors(FSerializer& arc); void SerializeMirrors(FSerializer& arc);
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void GameInterface::SerializeGameState(FSerializer& arc) void GameInterface::SerializeGameState(FSerializer& arc)
{ {
if (arc.isWriting()) if (arc.isWriting())
{ {
} }
else else
{ {
sndKillAllSounds(); sndKillAllSounds();
sfxKillAllSounds(); sfxKillAllSounds();
ambKillAll(); ambKillAll();
seqKillAll(); seqKillAll();
} }
SerializeState(arc); SerializeState(arc);
SerializeActor(arc); SerializeActor(arc);
SerializePlayers(arc); SerializePlayers(arc);

View file

@ -7,259 +7,257 @@
// Keep it local so that the engine's sprite type is no longer limited by file format restrictions. // Keep it local so that the engine's sprite type is no longer limited by file format restrictions.
struct spritetypedisk struct spritetypedisk
{ {
int32_t x, y, z; int32_t x, y, z;
uint16_t cstat; uint16_t cstat;
int16_t picnum; int16_t picnum;
int8_t shade; int8_t shade;
uint8_t pal, clipdist, detail; uint8_t pal, clipdist, detail;
uint8_t xrepeat, yrepeat; uint8_t xrepeat, yrepeat;
int8_t xoffset, yoffset; int8_t xoffset, yoffset;
int16_t sectnum, statnum; int16_t sectnum, statnum;
int16_t ang, owner; int16_t ang, owner;
int16_t index, yvel, inittype; int16_t index, yvel, inittype;
int16_t type; int16_t type;
int16_t hitag; int16_t hitag;
int16_t extra; int16_t extra;
}; };
struct sectortypedisk struct sectortypedisk
{ {
int16_t wallptr, wallnum; int16_t wallptr, wallnum;
int32_t ceilingz, floorz; int32_t ceilingz, floorz;
uint16_t ceilingstat, floorstat; uint16_t ceilingstat, floorstat;
int16_t ceilingpicnum, ceilingheinum; int16_t ceilingpicnum, ceilingheinum;
int8_t ceilingshade; int8_t ceilingshade;
uint8_t ceilingpal, ceilingxpanning, ceilingypanning; uint8_t ceilingpal, ceilingxpanning, ceilingypanning;
int16_t floorpicnum, floorheinum; int16_t floorpicnum, floorheinum;
int8_t floorshade; int8_t floorshade;
uint8_t floorpal, floorxpanning, floorypanning; uint8_t floorpal, floorxpanning, floorypanning;
uint8_t visibility, fogpal; uint8_t visibility, fogpal;
int16_t type; int16_t type;
int16_t hitag; int16_t hitag;
int16_t extra; int16_t extra;
}; };
struct walltypedisk struct walltypedisk
{ {
int32_t x, y; int32_t x, y;
int16_t point2, nextwall, nextsector; int16_t point2, nextwall, nextsector;
uint16_t cstat; uint16_t cstat;
int16_t picnum, overpicnum; int16_t picnum, overpicnum;
int8_t shade; int8_t shade;
uint8_t pal, xrepeat, yrepeat, xpanning, ypanning; uint8_t pal, xrepeat, yrepeat, xpanning, ypanning;
int16_t type; int16_t type;
int16_t hitag; int16_t hitag;
int16_t extra; int16_t extra;
}; };
#pragma pack(pop) #pragma pack(pop)
BEGIN_BLD_NS BEGIN_BLD_NS
TArray<walltype> dbLoadMapWalls(const char* pPath);
class DBloodActor; class DBloodActor;
struct AISTATE; struct AISTATE;
struct XSPRITE { struct XSPRITE {
AISTATE* aiState; // ai
union
{
uint32_t flags;
struct {
unsigned int state : 1; // State 0
unsigned int triggerOn : 1; // going ON
unsigned int triggerOff : 1; // going OFF
unsigned int restState : 1; // restState
unsigned int Interrutable : 1; // Interruptable
unsigned int Decoupled : 1; // Decoupled
unsigned int triggerOnce : 1; // 1-shot
unsigned int isTriggered : 1; // works in case if triggerOnce selected
unsigned int Push : 1; // Push
unsigned int Vector : 1; // Vector
unsigned int Impact : 1; // Impact
unsigned int Pickup : 1; // Pickup
unsigned int Touch : 1; // Touch
unsigned int Sight : 1; // Sight
unsigned int Proximity : 1; // Proximity
unsigned int lS : 1; // Single
unsigned int lB : 1; // Bloodbath
unsigned int lT : 1; // Launch Team
unsigned int lC : 1; // Coop
unsigned int DudeLockout : 1; // DudeLockout
unsigned int locked : 1; // Locked
unsigned int dudeDeaf : 1; // dudeDeaf
unsigned int dudeAmbush : 1; // dudeAmbush
unsigned int dudeGuard : 1; // dudeGuard
unsigned int dudeFlag4 : 1; // unused
unsigned int wave : 2; // Wave
unsigned int medium : 2; // medium
unsigned int respawn : 2; // Respawn option
unsigned int unused2 : 1; // (new) patrol state
};
};
TObjPtr<DBloodActor*> target; // target sprite AISTATE* aiState; // ai
TObjPtr<DBloodActor*> burnSource; union
{
uint32_t flags;
struct {
unsigned int state : 1; // State 0
unsigned int triggerOn : 1; // going ON
unsigned int triggerOff : 1; // going OFF
unsigned int restState : 1; // restState
unsigned int Interrutable : 1; // Interruptable
unsigned int Decoupled : 1; // Decoupled
unsigned int triggerOnce : 1; // 1-shot
unsigned int isTriggered : 1; // works in case if triggerOnce selected
unsigned int Push : 1; // Push
unsigned int Vector : 1; // Vector
unsigned int Impact : 1; // Impact
unsigned int Pickup : 1; // Pickup
unsigned int Touch : 1; // Touch
unsigned int Sight : 1; // Sight
unsigned int Proximity : 1; // Proximity
unsigned int lS : 1; // Single
unsigned int lB : 1; // Bloodbath
unsigned int lT : 1; // Launch Team
unsigned int lC : 1; // Coop
unsigned int DudeLockout : 1; // DudeLockout
unsigned int locked : 1; // Locked
unsigned int dudeDeaf : 1; // dudeDeaf
unsigned int dudeAmbush : 1; // dudeAmbush
unsigned int dudeGuard : 1; // dudeGuard
unsigned int dudeFlag4 : 1; // unused
unsigned int wave : 2; // Wave
unsigned int medium : 2; // medium
unsigned int respawn : 2; // Respawn option
unsigned int unused2 : 1; // (new) patrol state
};
};
int32_t targetX; // target x TObjPtr<DBloodActor*> target; // target sprite
int32_t targetY; // target y TObjPtr<DBloodActor*> burnSource;
int32_t targetZ; // target z
int32_t sysData1; // used to keep here various system data, so user can't change it in map editor
int32_t sysData2; //
int32_t scale; // used for scaling SEQ size on sprites
uint32_t physAttr; // currently used by additional physics sprites to keep its attributes.
uint32_t health;
uint32_t busy;
int16_t data1; // Data 1 int32_t targetX; // target x
int16_t data2; // Data 2 int32_t targetY; // target y
int16_t data3; // Data 3 int32_t targetZ; // target z
uint16_t txID; // TX ID int32_t sysData1; // used to keep here various system data, so user can't change it in map editor
uint16_t rxID; // RX ID int32_t sysData2; //
uint16_t command; // Cmd int32_t scale; // used for scaling SEQ size on sprites
uint16_t busyTime; // busyTime uint32_t physAttr; // currently used by additional physics sprites to keep its attributes.
uint16_t waitTime; // waitTime uint32_t health;
uint16_t data4; // Data 4 uint32_t busy;
uint16_t goalAng; // Dude goal ang
uint16_t burnTime;
uint16_t height;
uint16_t stateTimer; // ai timer
uint8_t respawnPending; // respawnPending int16_t data1; // Data 1
uint8_t dropMsg; // Drop Item int16_t data2; // Data 2
uint8_t key; // Key int16_t data3; // Data 3
uint8_t lSkill; // Launch 12345 uint16_t txID; // TX ID
uint8_t lockMsg; // Lock msg uint16_t rxID; // RX ID
int8_t dodgeDir; // Dude dodge direction uint16_t command; // Cmd
uint8_t unused1; // modern flags uint16_t busyTime; // busyTime
uint8_t unused3; // something about sight checks uint16_t waitTime; // waitTime
uint8_t unused4; // patrol turn delay uint16_t data4; // Data 4
uint16_t goalAng; // Dude goal ang
uint16_t burnTime;
uint16_t height;
uint16_t stateTimer; // ai timer
uint8_t respawnPending; // respawnPending
uint8_t dropMsg; // Drop Item
uint8_t key; // Key
uint8_t lSkill; // Launch 12345
uint8_t lockMsg; // Lock msg
int8_t dodgeDir; // Dude dodge direction
uint8_t unused1; // modern flags
uint8_t unused3; // something about sight checks
uint8_t unused4; // patrol turn delay
}; };
struct XSECTOR { struct XSECTOR {
union
{
uint64_t flags;
struct {
unsigned int state : 1; // State
unsigned int triggerOn : 1; // Send at ON
unsigned int triggerOff : 1; // Send at OFF
unsigned int restState : 1;
unsigned int interruptable : 1; // Interruptable
unsigned int reTriggerA : 1; // OFF->ON wait
unsigned int reTriggerB : 1; // ON->OFF wait
unsigned int shadeAlways : 1; // Lighting shadeAlways
unsigned int shadeFloor : 1; // Lighting floor
unsigned int shadeCeiling : 1; // Lighting ceiling
unsigned int shadeWalls : 1; // Lighting walls
unsigned int panAlways : 1; // Pan always
unsigned int panFloor : 1; // Pan floor
unsigned int panCeiling : 1; // Pan ceiling
unsigned int Drag : 1; // Pan drag
unsigned int Underwater : 1; // Underwater
unsigned int decoupled : 1; // Decoupled
unsigned int triggerOnce : 1; // 1-shot
unsigned int isTriggered : 1;
unsigned int Push : 1; // Push
unsigned int Vector : 1; // Vector
unsigned int Reserved : 1; // Reserved
unsigned int Enter : 1; // Enter
unsigned int Exit : 1; // Exit
unsigned int Wallpush : 1; // WallPush
unsigned int color : 1; // Color Lights
unsigned int stopOn : 1;
unsigned int stopOff : 1;
unsigned int Crush : 1; // Crush
unsigned int locked : 1; // Locked
unsigned int windAlways : 1; // Wind always
unsigned int dudeLockout : 1;
unsigned int bobAlways : 1; // Motion always
unsigned int bobFloor : 1; // Motion bob floor
unsigned int bobCeiling : 1; // Motion bob ceiling
unsigned int bobRotate : 1; // Motion rotate
unsigned int unused1 : 1; // (new) pause motion
};
};
DBloodActor* marker0;
DBloodActor* marker1;
DBloodActor* basePath;
DBloodActor* actordata;
uint32_t busy;
int32_t offCeilZ;
int32_t onCeilZ;
int32_t offFloorZ;
int32_t onFloorZ;
uint32_t windVel; // Wind vel (changed from 10 bit to use higher velocity values)
uint16_t data; // Data union
uint16_t txID; // TX ID {
uint16_t rxID; // RX ID uint64_t flags;
uint16_t busyTimeA; // OFF->ON busyTime struct {
uint16_t waitTimeA; // OFF->ON waitTime unsigned int state : 1; // State
uint16_t panAngle; // Motion angle unsigned int triggerOn : 1; // Send at ON
uint16_t busyTimeB; // ON->OFF busyTime unsigned int triggerOff : 1; // Send at OFF
uint16_t waitTimeB; // ON->OFF waitTime unsigned int restState : 1;
uint16_t windAng; // Wind ang unsigned int interruptable : 1; // Interruptable
uint16_t bobTheta; // Motion Theta unsigned int reTriggerA : 1; // OFF->ON wait
int16_t bobSpeed; // Motion speed unsigned int reTriggerB : 1; // ON->OFF wait
unsigned int shadeAlways : 1; // Lighting shadeAlways
unsigned int shadeFloor : 1; // Lighting floor
unsigned int shadeCeiling : 1; // Lighting ceiling
unsigned int shadeWalls : 1; // Lighting walls
unsigned int panAlways : 1; // Pan always
unsigned int panFloor : 1; // Pan floor
unsigned int panCeiling : 1; // Pan ceiling
unsigned int Drag : 1; // Pan drag
unsigned int Underwater : 1; // Underwater
unsigned int decoupled : 1; // Decoupled
unsigned int triggerOnce : 1; // 1-shot
unsigned int isTriggered : 1;
unsigned int Push : 1; // Push
unsigned int Vector : 1; // Vector
unsigned int Reserved : 1; // Reserved
unsigned int Enter : 1; // Enter
unsigned int Exit : 1; // Exit
unsigned int Wallpush : 1; // WallPush
unsigned int color : 1; // Color Lights
unsigned int stopOn : 1;
unsigned int stopOff : 1;
unsigned int Crush : 1; // Crush
unsigned int locked : 1; // Locked
unsigned int windAlways : 1; // Wind always
unsigned int dudeLockout : 1;
unsigned int bobAlways : 1; // Motion always
unsigned int bobFloor : 1; // Motion bob floor
unsigned int bobCeiling : 1; // Motion bob ceiling
unsigned int bobRotate : 1; // Motion rotate
unsigned int unused1 : 1; // (new) pause motion
uint8_t busyWaveA; // OFF->ON wave };
uint8_t busyWaveB; // ON->OFF wave };
uint8_t command; // Cmd DBloodActor* marker0;
int8_t amplitude; // Lighting amplitude DBloodActor* marker1;
uint8_t freq; // Lighting freq DBloodActor* basePath;
uint8_t phase; // Lighting phase DBloodActor* actordata;
uint8_t wave; // Lighting wave
int8_t shade; // Lighting value uint32_t busy;
uint8_t panVel; // Motion speed int32_t offCeilZ;
uint8_t Depth; // Depth int32_t onCeilZ;
uint8_t Key; // Key int32_t offFloorZ;
uint8_t ceilpal; // Ceil pal2 int32_t onFloorZ;
uint8_t damageType; // DamageType uint32_t windVel; // Wind vel (changed from 10 bit to use higher velocity values)
uint8_t floorpal; // Floor pal2
uint8_t bobZRange; // Motion Z range uint16_t data; // Data
uint16_t txID; // TX ID
uint16_t rxID; // RX ID
uint16_t busyTimeA; // OFF->ON busyTime
uint16_t waitTimeA; // OFF->ON waitTime
uint16_t panAngle; // Motion angle
uint16_t busyTimeB; // ON->OFF busyTime
uint16_t waitTimeB; // ON->OFF waitTime
uint16_t windAng; // Wind ang
uint16_t bobTheta; // Motion Theta
int16_t bobSpeed; // Motion speed
uint8_t busyWaveA; // OFF->ON wave
uint8_t busyWaveB; // ON->OFF wave
uint8_t command; // Cmd
int8_t amplitude; // Lighting amplitude
uint8_t freq; // Lighting freq
uint8_t phase; // Lighting phase
uint8_t wave; // Lighting wave
int8_t shade; // Lighting value
uint8_t panVel; // Motion speed
uint8_t Depth; // Depth
uint8_t Key; // Key
uint8_t ceilpal; // Ceil pal2
uint8_t damageType; // DamageType
uint8_t floorpal; // Floor pal2
uint8_t bobZRange; // Motion Z range
}; };
struct XWALL { struct XWALL {
union
{
uint32_t flags;
struct {
unsigned int state : 1; // State
unsigned int triggerOn : 1; // going ON
unsigned int triggerOff : 1; // going OFF
unsigned int restState : 1; // restState
unsigned int interruptable : 1; // Interruptable
unsigned int panAlways : 1; // panAlways
unsigned int decoupled : 1; // Decoupled
unsigned int triggerOnce : 1; // 1-shot
unsigned int isTriggered : 1;
unsigned int triggerPush : 1; // Push
unsigned int triggerVector : 1; // Vector
unsigned int triggerTouch : 1; // by NoOne: renamed from Reserved to Touch as it works with Touch now.
unsigned int locked : 1; // Locked
unsigned int dudeLockout : 1; // DudeLockout
};
};
uint32_t busy;
int16_t data; // Data union
uint16_t txID; // TX ID {
uint16_t rxID; // RX ID uint32_t flags;
uint16_t busyTime; // busyTime struct {
uint16_t waitTime; // waitTime unsigned int state : 1; // State
unsigned int triggerOn : 1; // going ON
uint8_t command; // Cmd unsigned int triggerOff : 1; // going OFF
int8_t panXVel; // panX unsigned int restState : 1; // restState
int8_t panYVel; // panY unsigned int interruptable : 1; // Interruptable
uint8_t key; // Key unsigned int panAlways : 1; // panAlways
unsigned int decoupled : 1; // Decoupled
unsigned int triggerOnce : 1; // 1-shot
unsigned int isTriggered : 1;
unsigned int triggerPush : 1; // Push
unsigned int triggerVector : 1; // Vector
unsigned int triggerTouch : 1; // by NoOne: renamed from Reserved to Touch as it works with Touch now.
unsigned int locked : 1; // Locked
unsigned int dudeLockout : 1; // DudeLockout
};
};
uint32_t busy;
int16_t data; // Data
uint16_t txID; // TX ID
uint16_t rxID; // RX ID
uint16_t busyTime; // busyTime
uint16_t waitTime; // waitTime
uint8_t command; // Cmd
int8_t panXVel; // panX
int8_t panYVel; // panY
uint8_t key; // Key
}; };
END_BLD_NS END_BLD_NS

View file

@ -34,517 +34,559 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void sub_5A928(void) void sub_5A928(void)
{ {
for (int i = 0; i < buttonMap.NumButtons(); i++) for (int i = 0; i < buttonMap.NumButtons(); i++)
buttonMap.ClearButton(i); buttonMap.ClearButton(i);
} }
const char *SetGodMode(bool god) const char* SetGodMode(bool god)
{ {
playerSetGodMode(gMe, god); playerSetGodMode(gMe, god);
bPlayerCheated = true; bPlayerCheated = true;
return gMe->godMode? GStrings("TXTB_GODMODE") : GStrings("TXTB_NOTGODMODE"); return gMe->godMode ? GStrings("TXTB_GODMODE") : GStrings("TXTB_NOTGODMODE");
} }
const char *SetClipMode(bool noclip) const char* SetClipMode(bool noclip)
{ {
gNoClip = noclip; gNoClip = noclip;
bPlayerCheated = true; bPlayerCheated = true;
return gNoClip? GStrings("TXTB_NOCLIP") : GStrings("TXTB_NOCLIPOFF"); return gNoClip ? GStrings("TXTB_NOCLIP") : GStrings("TXTB_NOCLIPOFF");
} }
void packStuff(PLAYER *pPlayer) void packStuff(PLAYER* pPlayer)
{ {
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
packAddItem(pPlayer, i); packAddItem(pPlayer, i);
} }
void packClear(PLAYER *pPlayer) void packClear(PLAYER* pPlayer)
{ {
pPlayer->packItemId = 0; pPlayer->packItemId = 0;
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
{ {
pPlayer->packSlots[i].isActive = 0; pPlayer->packSlots[i].isActive = 0;
pPlayer->packSlots[i].curAmount = 0; pPlayer->packSlots[i].curAmount = 0;
} }
} }
void SetAmmo(bool stat) void SetAmmo(bool stat)
{ {
if (stat) if (stat)
{ {
for (int i = 0; i < 12; i++) for (int i = 0; i < 12; i++)
gMe->ammoCount[i] = gAmmoInfo[i].max; gMe->ammoCount[i] = gAmmoInfo[i].max;
viewSetMessage(GStrings("TXTB_FULLAMMO")); viewSetMessage(GStrings("TXTB_FULLAMMO"));
} }
else else
{ {
for (int i = 0; i < 12; i++) for (int i = 0; i < 12; i++)
gMe->ammoCount[i] = 0; gMe->ammoCount[i] = 0;
viewSetMessage(GStrings("TXTB_NOAMMO")); viewSetMessage(GStrings("TXTB_NOAMMO"));
} }
} }
void SetWeapons(bool stat) void SetWeapons(bool stat)
{ {
for (int i = 0; i < 14; i++) for (int i = 0; i < 14; i++)
{ {
gMe->hasWeapon[i] = stat; gMe->hasWeapon[i] = stat;
} }
SetAmmo(stat); SetAmmo(stat);
if (stat) if (stat)
viewSetMessage(GStrings("TXTB_ALLWEAP")); viewSetMessage(GStrings("TXTB_ALLWEAP"));
else else
{ {
if (!VanillaMode()) if (!VanillaMode())
{ {
// Keep the pitchfork to avoid freeze // Keep the pitchfork to avoid freeze
gMe->hasWeapon[1] = 1; gMe->hasWeapon[1] = 1;
gMe->curWeapon = kWeapNone; gMe->curWeapon = kWeapNone;
gMe->nextWeapon = kWeapPitchFork; gMe->nextWeapon = kWeapPitchFork;
} }
viewSetMessage(GStrings("TXTB_NOWEAP")); viewSetMessage(GStrings("TXTB_NOWEAP"));
} }
} }
void SetToys(bool stat) void SetToys(bool stat)
{ {
if (stat) if (stat)
{ {
packStuff(gMe); packStuff(gMe);
viewSetMessage(GStrings("TXTB_FULLINV")); viewSetMessage(GStrings("TXTB_FULLINV"));
} }
else else
{ {
packClear(gMe); packClear(gMe);
viewSetMessage(GStrings("TXTB_NOINV")); viewSetMessage(GStrings("TXTB_NOINV"));
} }
} }
void SetArmor(bool stat) void SetArmor(bool stat)
{ {
int nAmount; int nAmount;
if (stat) if (stat)
{ {
viewSetMessage(GStrings("TXTB_FULLARM")); viewSetMessage(GStrings("TXTB_FULLARM"));
nAmount = 3200; nAmount = 3200;
} }
else else
{ {
viewSetMessage(GStrings("TXTB_NOARM")); viewSetMessage(GStrings("TXTB_NOARM"));
nAmount = 0; nAmount = 0;
} }
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
gMe->armor[i] = nAmount; gMe->armor[i] = nAmount;
} }
void SetKeys(bool stat) void SetKeys(bool stat)
{ {
for (int i = 1; i <= 6; i++) for (int i = 1; i <= 6; i++)
gMe->hasKey[i] = stat; gMe->hasKey[i] = stat;
if (stat) if (stat)
viewSetMessage(GStrings("TXTB_ALLKEYS")); viewSetMessage(GStrings("TXTB_ALLKEYS"));
else else
viewSetMessage(GStrings("TXTB_NOKEYS")); viewSetMessage(GStrings("TXTB_NOKEYS"));
} }
void SetInfiniteAmmo(bool stat) void SetInfiniteAmmo(bool stat)
{ {
gInfiniteAmmo = stat; gInfiniteAmmo = stat;
if (gInfiniteAmmo) if (gInfiniteAmmo)
viewSetMessage(GStrings("TXTB_INFAMMO")); viewSetMessage(GStrings("TXTB_INFAMMO"));
else else
viewSetMessage(GStrings("TXTB_LIMAMMO")); viewSetMessage(GStrings("TXTB_LIMAMMO"));
} }
void SetMap(bool stat) void SetMap(bool stat)
{ {
gFullMap = stat; gFullMap = stat;
if (gFullMap) if (gFullMap)
viewSetMessage(GStrings("TXTB_ALLMAP")); viewSetMessage(GStrings("TXTB_ALLMAP"));
else else
viewSetMessage(GStrings("TXTB_NOALLMAP")); viewSetMessage(GStrings("TXTB_NOALLMAP"));
} }
void SetWooMode(bool stat) void SetWooMode(bool stat)
{ {
if (stat) if (stat)
{ {
if (!powerupCheck(gMe, kPwUpTwoGuns)) if (!powerupCheck(gMe, kPwUpTwoGuns))
powerupActivate(gMe, kPwUpTwoGuns); powerupActivate(gMe, kPwUpTwoGuns);
} }
else else
{ {
if (powerupCheck(gMe, kPwUpTwoGuns)) if (powerupCheck(gMe, kPwUpTwoGuns))
{ {
if (!VanillaMode()) if (!VanillaMode())
gMe->pwUpTime[kPwUpTwoGuns] = 0; gMe->pwUpTime[kPwUpTwoGuns] = 0;
powerupDeactivate(gMe, kPwUpTwoGuns); powerupDeactivate(gMe, kPwUpTwoGuns);
} }
} }
} }
void ToggleWooMode(void) void ToggleWooMode(void)
{ {
SetWooMode(!(powerupCheck(gMe, kPwUpTwoGuns) != 0)); SetWooMode(!(powerupCheck(gMe, kPwUpTwoGuns) != 0));
} }
void ToggleBoots(void) void ToggleBoots(void)
{ {
if (powerupCheck(gMe, kPwUpJumpBoots)) if (powerupCheck(gMe, kPwUpJumpBoots))
{ {
viewSetMessage(GStrings("TXTB_NOJBOOTS")); viewSetMessage(GStrings("TXTB_NOJBOOTS"));
if (!VanillaMode()) if (!VanillaMode())
{ {
gMe->pwUpTime[kPwUpJumpBoots] = 0; gMe->pwUpTime[kPwUpJumpBoots] = 0;
gMe->packSlots[4].curAmount = 0; gMe->packSlots[4].curAmount = 0;
} }
powerupDeactivate(gMe, kPwUpJumpBoots); powerupDeactivate(gMe, kPwUpJumpBoots);
} }
else else
{ {
viewSetMessage(GStrings("TXTB_JBOOTS")); viewSetMessage(GStrings("TXTB_JBOOTS"));
if (!VanillaMode()) if (!VanillaMode())
gMe->pwUpTime[kPwUpJumpBoots] = gPowerUpInfo[kPwUpJumpBoots].bonusTime; gMe->pwUpTime[kPwUpJumpBoots] = gPowerUpInfo[kPwUpJumpBoots].bonusTime;
powerupActivate(gMe, kPwUpJumpBoots); powerupActivate(gMe, kPwUpJumpBoots);
} }
} }
void ToggleInvisibility(void) void ToggleInvisibility(void)
{ {
if (powerupCheck(gMe, kPwUpShadowCloak)) if (powerupCheck(gMe, kPwUpShadowCloak))
{ {
viewSetMessage(GStrings("TXTB_VISIBLE")); viewSetMessage(GStrings("TXTB_VISIBLE"));
if (!VanillaMode()) if (!VanillaMode())
gMe->pwUpTime[kPwUpShadowCloak] = 0; gMe->pwUpTime[kPwUpShadowCloak] = 0;
powerupDeactivate(gMe, kPwUpShadowCloak); powerupDeactivate(gMe, kPwUpShadowCloak);
} }
else else
{ {
viewSetMessage(GStrings("TXTB_INVISIBLE")); viewSetMessage(GStrings("TXTB_INVISIBLE"));
powerupActivate(gMe, kPwUpShadowCloak); powerupActivate(gMe, kPwUpShadowCloak);
} }
} }
void ToggleInvulnerability(void) void ToggleInvulnerability(void)
{ {
if (powerupCheck(gMe, kPwUpDeathMask)) if (powerupCheck(gMe, kPwUpDeathMask))
{ {
viewSetMessage(GStrings("TXTB_VULN")); viewSetMessage(GStrings("TXTB_VULN"));
if (!VanillaMode()) if (!VanillaMode())
gMe->pwUpTime[kPwUpDeathMask] = 0; gMe->pwUpTime[kPwUpDeathMask] = 0;
powerupDeactivate(gMe, kPwUpDeathMask); powerupDeactivate(gMe, kPwUpDeathMask);
} }
else else
{ {
viewSetMessage(GStrings("TXTB_INVULN")); viewSetMessage(GStrings("TXTB_INVULN"));
powerupActivate(gMe, kPwUpDeathMask); powerupActivate(gMe, kPwUpDeathMask);
} }
} }
void ToggleDelirium(void) void ToggleDelirium(void)
{ {
if (powerupCheck(gMe, kPwUpDeliriumShroom)) if (powerupCheck(gMe, kPwUpDeliriumShroom))
{ {
viewSetMessage(GStrings("TXTB_NODELIR")); viewSetMessage(GStrings("TXTB_NODELIR"));
if (!VanillaMode()) if (!VanillaMode())
gMe->pwUpTime[kPwUpDeliriumShroom] = 0; gMe->pwUpTime[kPwUpDeliriumShroom] = 0;
powerupDeactivate(gMe, kPwUpDeliriumShroom); powerupDeactivate(gMe, kPwUpDeliriumShroom);
} }
else else
{ {
viewSetMessage(GStrings("TXTB_DELIR")); viewSetMessage(GStrings("TXTB_DELIR"));
powerupActivate(gMe, kPwUpDeliriumShroom); powerupActivate(gMe, kPwUpDeliriumShroom);
} }
} }
bool bPlayerCheated = false; bool bPlayerCheated = false;
static int parseArgs(char *pzArgs, int *nArg1, int *nArg2) //---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static int parseArgs(char* pzArgs, int* nArg1, int* nArg2)
{ {
if (!nArg1 || !nArg2 || strlen(pzArgs) < 3) if (!nArg1 || !nArg2 || strlen(pzArgs) < 3)
return -1; return -1;
*nArg1 = pzArgs[0] - '0'; *nArg1 = pzArgs[0] - '0';
int a1 = pzArgs[1] == ' ' ? 0 : pzArgs[1] - '0'; int a1 = pzArgs[1] == ' ' ? 0 : pzArgs[1] - '0';
*nArg2 = a1 * 10 + (pzArgs[2] - '0'); *nArg2 = a1 * 10 + (pzArgs[2] - '0');
return 2; return 2;
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
const char* GameInterface::GenericCheat(int player, int cheat) const char* GameInterface::GenericCheat(int player, int cheat)
{ {
// message processing is not perfect because many cheats output multiple messages. // message processing is not perfect because many cheats output multiple messages.
if (gGameOptions.nGameType != 0 || numplayers > 1) // sp only for now. if (gGameOptions.nGameType != 0 || numplayers > 1) // sp only for now.
return nullptr; return nullptr;
if (gamestate != GS_LEVEL || gMe->actor->xspr.health == 0) // must be alive and in a level to cheat. if (gamestate != GS_LEVEL || gMe->actor->xspr.health == 0) // must be alive and in a level to cheat.
return nullptr; return nullptr;
bPlayerCheated = true; bPlayerCheated = true;
switch (cheat) switch (cheat)
{ {
case CHT_GOD: case CHT_GOD:
return SetGodMode(!gMe->godMode); return SetGodMode(!gMe->godMode);
case CHT_GODOFF: case CHT_GODOFF:
return SetGodMode(false); return SetGodMode(false);
case CHT_GODON: case CHT_GODON:
return SetGodMode(true); return SetGodMode(true);
case CHT_NOCLIP: case CHT_NOCLIP:
return SetClipMode(!gNoClip); return SetClipMode(!gNoClip);
case kCheatSpielberg: case kCheatSpielberg:
// demo record // demo record
break; break;
case kCheatSatchel: case kCheatSatchel:
SetToys(true); SetToys(true);
break; break;
case kCheatKevorkian: case kCheatKevorkian:
actDamageSprite(gMe->actor, gMe->actor, kDamageBullet, 8000); actDamageSprite(gMe->actor, gMe->actor, kDamageBullet, 8000);
return GStrings("TXTB_KEVORKIAN"); return GStrings("TXTB_KEVORKIAN");
case kCheatMcGee: case kCheatMcGee:
{ {
if (!gMe->actor->xspr.burnTime) if (!gMe->actor->xspr.burnTime)
evPostActor(gMe->actor, 0, kCallbackFXFlameLick); evPostActor(gMe->actor, 0, kCallbackFXFlameLick);
actBurnSprite(gMe->actor, gMe->actor, 2400); actBurnSprite(gMe->actor, gMe->actor, 2400);
return GStrings("TXTB_FIRED"); return GStrings("TXTB_FIRED");
} }
case kCheatEdmark: case kCheatEdmark:
actDamageSprite(gMe->actor, gMe->actor, kDamageExplode, 8000); actDamageSprite(gMe->actor, gMe->actor, kDamageExplode, 8000);
return GStrings("TXTB_THEDAYS"); return GStrings("TXTB_THEDAYS");
case kCheatKrueger: case kCheatKrueger:
{ {
actHealDude(gMe->actor, 200, 200); actHealDude(gMe->actor, 200, 200);
gMe->armor[1] = VanillaMode() ? 200 : 3200; gMe->armor[1] = VanillaMode() ? 200 : 3200;
if (!gMe->actor->xspr.burnTime) if (!gMe->actor->xspr.burnTime)
evPostActor(gMe->actor, 0, kCallbackFXFlameLick); evPostActor(gMe->actor, 0, kCallbackFXFlameLick);
actBurnSprite(gMe->actor, gMe->actor, 2400); actBurnSprite(gMe->actor, gMe->actor, 2400);
return GStrings("TXTB_RETARD"); return GStrings("TXTB_RETARD");
} }
case kCheatSterno: case kCheatSterno:
gMe->blindEffect = 250; gMe->blindEffect = 250;
break; break;
case kCheat14: // quakeEffect (causing a little flickerEffect), not used by any cheat code (dead code) case kCheat14: // quakeEffect (causing a little flickerEffect), not used by any cheat code (dead code)
gMe->flickerEffect = 360; gMe->flickerEffect = 360;
break; break;
case kCheatSpork: case kCheatSpork:
actHealDude(gMe->actor, 200, 200); actHealDude(gMe->actor, 200, 200);
break; break;
case kCheatClarice: case kCheatClarice:
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
gMe->armor[i] = 1600; gMe->armor[i] = 1600;
return GStrings("TXTB_HALFARMOR"); return GStrings("TXTB_HALFARMOR");
case kCheatFrankenstein: case kCheatFrankenstein:
gMe->packSlots[0].curAmount = 100; gMe->packSlots[0].curAmount = 100;
break; break;
case kCheatCheeseHead: case kCheatCheeseHead:
gMe->packSlots[1].curAmount = 100; gMe->packSlots[1].curAmount = 100;
if (!VanillaMode()) if (!VanillaMode())
gMe->pwUpTime[kPwUpDivingSuit] = gPowerUpInfo[kPwUpDivingSuit].bonusTime; gMe->pwUpTime[kPwUpDivingSuit] = gPowerUpInfo[kPwUpDivingSuit].bonusTime;
break; break;
case kCheatTequila: case kCheatTequila:
ToggleWooMode(); ToggleWooMode();
break; break;
case kCheatFunkyShoes: case kCheatFunkyShoes:
ToggleBoots(); ToggleBoots();
break; break;
case kCheatKeyMaster: case kCheatKeyMaster:
SetKeys(true); SetKeys(true);
break; break;
case kCheatOneRing: case kCheatOneRing:
ToggleInvisibility(); ToggleInvisibility();
break; break;
case kCheatVoorhees: case kCheatVoorhees:
ToggleInvulnerability(); ToggleInvulnerability();
break; break;
case kCheatJoJo: case kCheatJoJo:
ToggleDelirium(); ToggleDelirium();
break; break;
case kCheatLaraCroft: case kCheatLaraCroft:
SetInfiniteAmmo(!gInfiniteAmmo); SetInfiniteAmmo(!gInfiniteAmmo);
SetWeapons(gInfiniteAmmo); SetWeapons(gInfiniteAmmo);
break; break;
case kCheatHongKong: case kCheatHongKong:
SetWeapons(true); SetWeapons(true);
SetInfiniteAmmo(true); SetInfiniteAmmo(true);
break; break;
case kCheatMontana: case kCheatMontana:
SetWeapons(true); SetWeapons(true);
SetToys(true); SetToys(true);
break; break;
case kCheatBunz: case kCheatBunz:
SetWeapons(true); SetWeapons(true);
SetWooMode(true); SetWooMode(true);
break; break;
case kCheatCousteau: case kCheatCousteau:
actHealDude(gMe->actor, 200, 200); actHealDude(gMe->actor, 200, 200);
gMe->packSlots[1].curAmount = 100; gMe->packSlots[1].curAmount = 100;
if (!VanillaMode()) if (!VanillaMode())
gMe->pwUpTime[kPwUpDivingSuit] = gPowerUpInfo[kPwUpDivingSuit].bonusTime; gMe->pwUpTime[kPwUpDivingSuit] = gPowerUpInfo[kPwUpDivingSuit].bonusTime;
break; break;
case kCheatForkYou: case kCheatForkYou:
SetInfiniteAmmo(false); SetInfiniteAmmo(false);
SetMap(false); SetMap(false);
SetWeapons(false); SetWeapons(false);
SetAmmo(false); SetAmmo(false);
SetArmor(false); SetArmor(false);
SetToys(false); SetToys(false);
SetKeys(false); SetKeys(false);
SetWooMode(true); SetWooMode(true);
powerupActivate(gMe, kPwUpDeliriumShroom); powerupActivate(gMe, kPwUpDeliriumShroom);
gMe->actor->xspr.health = 16; gMe->actor->xspr.health = 16;
gMe->hasWeapon[1] = 1; gMe->hasWeapon[1] = 1;
gMe->curWeapon = kWeapNone; gMe->curWeapon = kWeapNone;
gMe->nextWeapon = kWeapPitchFork; gMe->nextWeapon = kWeapPitchFork;
break; break;
default: default:
return nullptr; return nullptr;
} }
return nullptr; return nullptr;
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static bool cheatGoonies(cheatseq_t*) static bool cheatGoonies(cheatseq_t*)
{ {
SetMap(!gFullMap); SetMap(!gFullMap);
return true; return true;
} }
static bool cheatMario(cheatseq_t* c) static bool cheatMario(cheatseq_t* c)
{ {
int nEpisode, nLevel; int nEpisode, nLevel;
if (parseArgs((char*)c->Args, &nEpisode, &nLevel) == 2) if (parseArgs((char*)c->Args, &nEpisode, &nLevel) == 2)
{ {
auto map = FindMapByIndex(nEpisode, nLevel); auto map = FindMapByIndex(nEpisode, nLevel);
if (map) DeferredStartGame(map, g_nextskill); if (map) DeferredStartGame(map, g_nextskill);
} }
return true; return true;
} }
static bool cheatCalgon(cheatseq_t*) static bool cheatCalgon(cheatseq_t*)
{ {
levelEndLevel(0); levelEndLevel(0);
return true; return true;
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static cheatseq_t s_CheatInfo[] = { static cheatseq_t s_CheatInfo[] = {
{"MPKFA", nullptr, SendGenericCheat, 0, CHT_GOD }, {"MPKFA", nullptr, SendGenericCheat, 0, CHT_GOD },
{"CAPINMYASS", nullptr, SendGenericCheat, 0, CHT_GODOFF }, {"CAPINMYASS", nullptr, SendGenericCheat, 0, CHT_GODOFF },
{"NOCAPINMYASS", nullptr, SendGenericCheat, 0, CHT_GODON }, {"NOCAPINMYASS", nullptr, SendGenericCheat, 0, CHT_GODON },
{"I WANNA BE LIKE KEVIN", nullptr, SendGenericCheat, 0, CHT_GODON }, {"I WANNA BE LIKE KEVIN", nullptr, SendGenericCheat, 0, CHT_GODON },
{"IDAHO", "give weapons" }, {"IDAHO", "give weapons" },
{"GRISWOLD", "give armor" }, {"GRISWOLD", "give armor" },
{"MONTANA", nullptr, SendGenericCheat, 0, kCheatMontana }, // MONTANA (All weapons, full ammo and all items) {"MONTANA", nullptr, SendGenericCheat, 0, kCheatMontana }, // MONTANA (All weapons, full ammo and all items)
{"EDMARK", nullptr, SendGenericCheat, 0, kCheatEdmark }, // EDMARK (Does a lot of fire damage to you (if you have 200HP and 200 fire armor then you can survive). Displays the message "THOSE WERE THE DAYS".) {"EDMARK", nullptr, SendGenericCheat, 0, kCheatEdmark }, // EDMARK (Does a lot of fire damage to you (if you have 200HP and 200 fire armor then you can survive). Displays the message "THOSE WERE THE DAYS".)
{"TEQUILA", nullptr, SendGenericCheat, 0, kCheatTequila }, // TEQUILA (Guns akimbo power-up) {"TEQUILA", nullptr, SendGenericCheat, 0, kCheatTequila }, // TEQUILA (Guns akimbo power-up)
{"BUNZ", nullptr, SendGenericCheat, 0, kCheatBunz }, // BUNZ (All weapons, full ammo, and guns akimbo power-up) {"BUNZ", nullptr, SendGenericCheat, 0, kCheatBunz }, // BUNZ (All weapons, full ammo, and guns akimbo power-up)
{"FUNKY SHOES", nullptr, SendGenericCheat, 0, kCheatFunkyShoes }, // FUNKY SHOES (Gives jump boots item and activates it) {"FUNKY SHOES", nullptr, SendGenericCheat, 0, kCheatFunkyShoes }, // FUNKY SHOES (Gives jump boots item and activates it)
{"GATEKEEPER", nullptr, SendGenericCheat, 0, kCheatGateKeeper }, // GATEKEEPER (Sets the you cheated flag to true, at the end of the level you will see that you have cheated) {"GATEKEEPER", nullptr, SendGenericCheat, 0, kCheatGateKeeper }, // GATEKEEPER (Sets the you cheated flag to true, at the end of the level you will see that you have cheated)
{"KEYMASTER", nullptr, SendGenericCheat, 0, kCheatKeyMaster }, // KEYMASTER (All keys) {"KEYMASTER", nullptr, SendGenericCheat, 0, kCheatKeyMaster }, // KEYMASTER (All keys)
{"JOJO", nullptr, SendGenericCheat, 0, kCheatJoJo }, // JOJO (Drunk mode (same effect as getting bitten by red spider)) {"JOJO", nullptr, SendGenericCheat, 0, kCheatJoJo }, // JOJO (Drunk mode (same effect as getting bitten by red spider))
{"SATCHEL", nullptr, SendGenericCheat, 0, kCheatSatchel }, // SATCHEL (Full inventory) {"SATCHEL", nullptr, SendGenericCheat, 0, kCheatSatchel }, // SATCHEL (Full inventory)
{"SPORK", nullptr, SendGenericCheat, 0, kCheatSpork }, // SPORK (200% health (same effect as getting life seed)) {"SPORK", nullptr, SendGenericCheat, 0, kCheatSpork }, // SPORK (200% health (same effect as getting life seed))
{"ONERING", nullptr, SendGenericCheat, 0, kCheatOneRing }, // ONERING (Cloak of invisibility power-up) {"ONERING", nullptr, SendGenericCheat, 0, kCheatOneRing }, // ONERING (Cloak of invisibility power-up)
{"MARIO###", nullptr, cheatMario }, // MARIO (Warp to level E M, e.g.: MARIO 1 3 will take you to Phantom Express) {"MARIO###", nullptr, cheatMario }, // MARIO (Warp to level E M, e.g.: MARIO 1 3 will take you to Phantom Express)
{"CALGON", nullptr, cheatCalgon }, // CALGON (Jumps to next level) {"CALGON", nullptr, cheatCalgon }, // CALGON (Jumps to next level)
{"KEVORKIAN", nullptr, SendGenericCheat, 0, kCheatKevorkian }, // KEVORKIAN (Does a lot of physical damage to you (if you have 200HP and 200 fire armor then you can survive). Displays the message "KEVORKIAN APPROVES".) {"KEVORKIAN", nullptr, SendGenericCheat, 0, kCheatKevorkian }, // KEVORKIAN (Does a lot of physical damage to you (if you have 200HP and 200 fire armor then you can survive). Displays the message "KEVORKIAN APPROVES".)
{"MCGEE", nullptr, SendGenericCheat, 0, kCheatMcGee }, // MCGEE (Sets you on fire. Displays the message "YOU'RE FIRED".) {"MCGEE", nullptr, SendGenericCheat, 0, kCheatMcGee }, // MCGEE (Sets you on fire. Displays the message "YOU'RE FIRED".)
{"KRUEGER", nullptr, SendGenericCheat, 0, kCheatKrueger }, // KRUEGER (200% health, but sets you on fire. Displays the message "FLAME RETARDANT".) {"KRUEGER", nullptr, SendGenericCheat, 0, kCheatKrueger }, // KRUEGER (200% health, but sets you on fire. Displays the message "FLAME RETARDANT".)
{"CHEESEHEAD", nullptr, SendGenericCheat, 0, kCheatCheeseHead }, // CHEESEHEAD (100% diving suit) {"CHEESEHEAD", nullptr, SendGenericCheat, 0, kCheatCheeseHead }, // CHEESEHEAD (100% diving suit)
{"COUSTEAU", nullptr, SendGenericCheat, 0, kCheatCousteau }, // COUSTEAU (200% health and diving suit) {"COUSTEAU", nullptr, SendGenericCheat, 0, kCheatCousteau }, // COUSTEAU (200% health and diving suit)
{"VOORHEES", nullptr, SendGenericCheat, 0, kCheatVoorhees }, // VOORHEES (Death mask power-up) {"VOORHEES", nullptr, SendGenericCheat, 0, kCheatVoorhees }, // VOORHEES (Death mask power-up)
{"LARA CROFT", nullptr, SendGenericCheat, 0, kCheatLaraCroft }, // LARA CROFT (All weapons and infinite ammo. Displays the message "LARA RULES". Typing it the second time will lose all weapons and ammo.) {"LARA CROFT", nullptr, SendGenericCheat, 0, kCheatLaraCroft }, // LARA CROFT (All weapons and infinite ammo. Displays the message "LARA RULES". Typing it the second time will lose all weapons and ammo.)
{"HONGKONG", nullptr, SendGenericCheat, 0, kCheatHongKong }, // HONGKONG (All weapons and infinite ammo) {"HONGKONG", nullptr, SendGenericCheat, 0, kCheatHongKong }, // HONGKONG (All weapons and infinite ammo)
{"FRANKENSTEIN", nullptr, SendGenericCheat, 0, kCheatFrankenstein }, // FRANKENSTEIN (100% med-kit) {"FRANKENSTEIN", nullptr, SendGenericCheat, 0, kCheatFrankenstein }, // FRANKENSTEIN (100% med-kit)
{"STERNO", nullptr, SendGenericCheat, 0, kCheatSterno }, // STERNO (Temporary blindness (same effect as getting bitten by green spider)) {"STERNO", nullptr, SendGenericCheat, 0, kCheatSterno }, // STERNO (Temporary blindness (same effect as getting bitten by green spider))
{"CLARICE", nullptr, SendGenericCheat, 0, kCheatClarice }, // CLARICE (Gives 100% body armor, 100% fire armor, 100% spirit armor) {"CLARICE", nullptr, SendGenericCheat, 0, kCheatClarice }, // CLARICE (Gives 100% body armor, 100% fire armor, 100% spirit armor)
{"FORK YOU", nullptr, SendGenericCheat, 0, kCheatForkYou }, // FORK YOU (Drunk mode, 1HP, no armor, no weapons, no ammo, no items, no keys, no map, guns akimbo power-up) {"FORK YOU", nullptr, SendGenericCheat, 0, kCheatForkYou }, // FORK YOU (Drunk mode, 1HP, no armor, no weapons, no ammo, no items, no keys, no map, guns akimbo power-up)
{"LIEBERMAN", nullptr, SendGenericCheat, 0, kCheatLieberMan }, // LIEBERMAN (Sets the you cheated flag to true, at the end of the level you will see that you have cheated) {"LIEBERMAN", nullptr, SendGenericCheat, 0, kCheatLieberMan }, // LIEBERMAN (Sets the you cheated flag to true, at the end of the level you will see that you have cheated)
{"EVA GALLI", nullptr, SendGenericCheat, 0, CHT_NOCLIP }, {"EVA GALLI", nullptr, SendGenericCheat, 0, CHT_NOCLIP },
{"RATE", "toggle r_showfps", nullptr, 1 }, // RATE (Display frame rate (doesn't count as a cheat)) {"RATE", "toggle r_showfps", nullptr, 1 }, // RATE (Display frame rate (doesn't count as a cheat))
{"GOONIES", nullptr, cheatGoonies, 0 }, // GOONIES (Enable full map. Displays the message "YOU HAVE THE MAP".) {"GOONIES", nullptr, cheatGoonies, 0 }, // GOONIES (Enable full map. Displays the message "YOU HAVE THE MAP".)
//{"SPIELBERG", nullptr, doCheat<kCheatSpielberg, 1 }, // SPIELBERG (Disables all cheats. If number values corresponding to a level and episode number are entered after the cheat word (i.e. "spielberg 1 3" for Phantom Express), you will be spawned to said level and the game will begin recording a demo from your actions.) //{"SPIELBERG", nullptr, doCheat<kCheatSpielberg, 1 }, // SPIELBERG (Disables all cheats. If number values corresponding to a level and episode number are entered after the cheat word (i.e. "spielberg 1 3" for Phantom Express), you will be spawned to said level and the game will begin recording a demo from your actions.)
}; };
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void cheatReset(void) void cheatReset(void)
{ {
bPlayerCheated = 0; bPlayerCheated = 0;
playerSetGodMode(gMe, 0); playerSetGodMode(gMe, 0);
gNoClip = 0; gNoClip = 0;
packClear(gMe); packClear(gMe);
gInfiniteAmmo = 0; gInfiniteAmmo = 0;
gFullMap = 0; gFullMap = 0;
} }
static void cmd_Give(int player, uint8_t **stream, bool skip) //---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void cmd_Give(int player, uint8_t** stream, bool skip)
{ {
int type = ReadByte(stream); int type = ReadByte(stream);
if (skip) return; if (skip) return;
if (numplayers != 1 || gamestate != GS_LEVEL || gMe->actor->xspr.health == 0) if (numplayers != 1 || gamestate != GS_LEVEL || gMe->actor->xspr.health == 0)
{ {
Printf("give: Cannot give while dead or not in a single-player game.\n"); Printf("give: Cannot give while dead or not in a single-player game.\n");
return; return;
} }
switch (type) switch (type)
{ {
case GIVE_ALL: case GIVE_ALL:
SetWeapons(true); SetWeapons(true);
SetAmmo(true); SetAmmo(true);
SetToys(true); SetToys(true);
SetArmor(true); SetArmor(true);
SetKeys(true); SetKeys(true);
bPlayerCheated = true; bPlayerCheated = true;
break; break;
case GIVE_HEALTH: case GIVE_HEALTH:
actHealDude(gMe->actor, 200, 200); actHealDude(gMe->actor, 200, 200);
bPlayerCheated = true; bPlayerCheated = true;
break; break;
case GIVE_WEAPONS: case GIVE_WEAPONS:
SetWeapons(true); SetWeapons(true);
bPlayerCheated = true; bPlayerCheated = true;
break; break;
case GIVE_AMMO: case GIVE_AMMO:
SetAmmo(true); SetAmmo(true);
bPlayerCheated = true; bPlayerCheated = true;
break; break;
case GIVE_ARMOR: case GIVE_ARMOR:
SetArmor(true); SetArmor(true);
bPlayerCheated = true; bPlayerCheated = true;
break; break;
case GIVE_KEYS: case GIVE_KEYS:
SetKeys(true); SetKeys(true);
bPlayerCheated = true; bPlayerCheated = true;
break; break;
case GIVE_INVENTORY: case GIVE_INVENTORY:
SetToys(true); SetToys(true);
bPlayerCheated = true; bPlayerCheated = true;
break; break;
default: default:
break; break;
} }
} }
void InitCheats() void InitCheats()
{ {
SetCheats(s_CheatInfo, countof(s_CheatInfo)); SetCheats(s_CheatInfo, countof(s_CheatInfo));
Net_SetCommandHandler(DEM_GIVE, cmd_Give); Net_SetCommandHandler(DEM_GIVE, cmd_Give);
} }
END_BLD_NS END_BLD_NS

View file

@ -28,11 +28,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
enum MESSAGE_PRIORITY { enum MESSAGE_PRIORITY {
MESSAGE_PRIORITY_PICKUP = -10, MESSAGE_PRIORITY_PICKUP = -10,
MESSAGE_PRIORITY_NORMAL = 0, MESSAGE_PRIORITY_NORMAL = 0,
MESSAGE_PRIORITY_SECRET = 10, MESSAGE_PRIORITY_SECRET = 10,
MESSAGE_PRIORITY_INI = 20, MESSAGE_PRIORITY_INI = 20,
MESSAGE_PRIORITY_SYSTEM = 100 MESSAGE_PRIORITY_SYSTEM = 100
}; };
extern bool bPlayerCheated; extern bool bPlayerCheated;

View file

@ -35,120 +35,126 @@ int mirrorcnt, mirrorsector, mirrorwall[4];
MIRROR mirror[16]; // only needed by Polymost. MIRROR mirror[16]; // only needed by Polymost.
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void InitMirrors(void) void InitMirrors(void)
{ {
r_rortexture = 4080; r_rortexture = 4080;
r_rortexturerange = 16; r_rortexturerange = 16;
mirrorcnt = 0;
tileDelete(504);
portalClear();
mirrorcnt = 0;
tileDelete(504);
portalClear();
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
tileDelete(4080 + i); tileDelete(4080 + i);
} }
for (int i = (int)wall.Size() - 1; i >= 0; i--) for (int i = (int)wall.Size() - 1; i >= 0; i--)
{ {
auto pWalli = &wall[i]; auto pWalli = &wall[i];
if (mirrorcnt == 16) if (mirrorcnt == 16)
break; break;
int nTile = 4080+mirrorcnt; int nTile = 4080 + mirrorcnt;
if (pWalli->overpicnum == 504) if (pWalli->overpicnum == 504)
{ {
if (pWalli->extra > 0 && pWalli->type == kWallStack) if (pWalli->extra > 0 && pWalli->type == kWallStack)
{ {
pWalli->overpicnum = nTile; pWalli->overpicnum = nTile;
mirror[mirrorcnt].wallnum = i; mirror[mirrorcnt].wallnum = i;
mirror[mirrorcnt].type = 0; mirror[mirrorcnt].type = 0;
pWalli->cstat |= CSTAT_WALL_1WAY; pWalli->cstat |= CSTAT_WALL_1WAY;
int tmp = pWalli->xw().data; int tmp = pWalli->xw().data;
int j; int j;
for (j = (int)wall.Size() - 1; j >= 0; j--) for (j = (int)wall.Size() - 1; j >= 0; j--)
{ {
if (j == i) if (j == i)
continue; continue;
auto pWallj = &wall[j]; auto pWallj = &wall[j];
if (pWallj->extra > 0 && pWallj->type == kWallStack) if (pWallj->extra > 0 && pWallj->type == kWallStack)
{ {
if (tmp != pWallj->xw().data) if (tmp != pWallj->xw().data)
continue; continue;
pWalli->hitag = j; // hitag is only used by Polymost, the new renderer uses external links. pWalli->hitag = j; // hitag is only used by Polymost, the new renderer uses external links.
pWallj->hitag = i; pWallj->hitag = i;
mirror[mirrorcnt].link = j; mirror[mirrorcnt].link = j;
break; break;
} }
} }
if (j < 0) if (j < 0)
{ {
Printf(PRINT_HIGH, "wall[%d] has no matching wall link! (data=%d)\n", i, tmp); Printf(PRINT_HIGH, "wall[%d] has no matching wall link! (data=%d)\n", i, tmp);
} }
else else
{ {
mirrorcnt++; mirrorcnt++;
pWalli->portalflags = PORTAL_WALL_VIEW; pWalli->portalflags = PORTAL_WALL_VIEW;
pWalli->portalnum = j; pWalli->portalnum = j;
} }
} }
continue; continue;
} }
if (pWalli->picnum == 504) if (pWalli->picnum == 504)
{ {
mirror[mirrorcnt].link = i; mirror[mirrorcnt].link = i;
mirror[mirrorcnt].wallnum = i; mirror[mirrorcnt].wallnum = i;
pWalli->picnum = nTile; pWalli->picnum = nTile;
mirror[mirrorcnt].type = 0; mirror[mirrorcnt].type = 0;
pWalli->cstat |= CSTAT_WALL_1WAY; pWalli->cstat |= CSTAT_WALL_1WAY;
pWalli->portalflags = PORTAL_WALL_MIRROR; pWalli->portalflags = PORTAL_WALL_MIRROR;
mirrorcnt++; mirrorcnt++;
continue; continue;
} }
} }
for (int i = (int)sector.Size() - 1; i >= 0; i--) for (int i = (int)sector.Size() - 1; i >= 0; i--)
{ {
if (mirrorcnt >= 15) if (mirrorcnt >= 15)
break; break;
auto secti = &sector[i]; auto secti = &sector[i];
if (secti->floorpicnum == 504) if (secti->floorpicnum == 504)
{ {
auto link = barrier_cast<DBloodActor*>(secti->upperLink); auto link = barrier_cast<DBloodActor*>(secti->upperLink);
if (link == nullptr) if (link == nullptr)
continue; continue;
auto link2 = link->GetOwner(); auto link2 = link->GetOwner();
if (link2 == nullptr) if (link2 == nullptr)
continue; continue;
auto sectj = link2->spr.sector(); auto sectj = link2->spr.sector();
int j = sectnum(sectj); int j = sectnum(sectj);
if (sectj->ceilingpicnum != 504) if (sectj->ceilingpicnum != 504)
I_Error("Lower link sector %d doesn't have mirror picnum\n", j); I_Error("Lower link sector %d doesn't have mirror picnum\n", j);
mirror[mirrorcnt].type = 2; mirror[mirrorcnt].type = 2;
mirror[mirrorcnt].dx = link2->spr.pos.X - link->spr.pos.X; mirror[mirrorcnt].dx = link2->spr.pos.X - link->spr.pos.X;
mirror[mirrorcnt].dy = link2->spr.pos.Y - link->spr.pos.Y; mirror[mirrorcnt].dy = link2->spr.pos.Y - link->spr.pos.Y;
mirror[mirrorcnt].dz = link2->spr.pos.Z - link->spr.pos.Z; mirror[mirrorcnt].dz = link2->spr.pos.Z - link->spr.pos.Z;
mirror[mirrorcnt].wallnum = i; mirror[mirrorcnt].wallnum = i;
mirror[mirrorcnt].link = j; mirror[mirrorcnt].link = j;
secti->floorpicnum = 4080 + mirrorcnt; secti->floorpicnum = 4080 + mirrorcnt;
secti->portalflags = PORTAL_SECTOR_FLOOR; secti->portalflags = PORTAL_SECTOR_FLOOR;
secti->portalnum = portalAdd(PORTAL_SECTOR_FLOOR, j, mirror[mirrorcnt].dx, mirror[mirrorcnt].dy, mirror[mirrorcnt].dz); secti->portalnum = portalAdd(PORTAL_SECTOR_FLOOR, j, mirror[mirrorcnt].dx, mirror[mirrorcnt].dy, mirror[mirrorcnt].dz);
mirrorcnt++; mirrorcnt++;
mirror[mirrorcnt].type = 1; mirror[mirrorcnt].type = 1;
mirror[mirrorcnt].dx = link->spr.pos.X - link2->spr.pos.X; mirror[mirrorcnt].dx = link->spr.pos.X - link2->spr.pos.X;
mirror[mirrorcnt].dy = link->spr.pos.Y - link2->spr.pos.Y; mirror[mirrorcnt].dy = link->spr.pos.Y - link2->spr.pos.Y;
mirror[mirrorcnt].dz = link->spr.pos.Z - link2->spr.pos.Z; mirror[mirrorcnt].dz = link->spr.pos.Z - link2->spr.pos.Z;
mirror[mirrorcnt].wallnum = j; mirror[mirrorcnt].wallnum = j;
mirror[mirrorcnt].link = i; mirror[mirrorcnt].link = i;
sectj->ceilingpicnum = 4080 + mirrorcnt; sectj->ceilingpicnum = 4080 + mirrorcnt;
sectj->portalflags = PORTAL_SECTOR_CEILING; sectj->portalflags = PORTAL_SECTOR_CEILING;
sectj->portalnum = portalAdd(PORTAL_SECTOR_CEILING, i, mirror[mirrorcnt].dx, mirror[mirrorcnt].dy, mirror[mirrorcnt].dz); sectj->portalnum = portalAdd(PORTAL_SECTOR_CEILING, i, mirror[mirrorcnt].dx, mirror[mirrorcnt].dy, mirror[mirrorcnt].dz);
mirrorcnt++; mirrorcnt++;
} }
} }
mirrorsector = sector.Size(); mirrorsector = sector.Size();
mergePortals(); mergePortals();
InitPolymostMirrorHack(); InitPolymostMirrorHack();
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -161,7 +167,7 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, MIRROR& w, MIRROR*
{ {
if (arc.BeginObject(keyname)) if (arc.BeginObject(keyname))
{ {
arc ("type", w.type) arc("type", w.type)
("link", w.link) ("link", w.link)
("dx", w.dx) ("dx", w.dx)
("dy", w.dy) ("dy", w.dy)
@ -172,12 +178,18 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, MIRROR& w, MIRROR*
return arc; return arc;
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void SerializeMirrors(FSerializer& arc) void SerializeMirrors(FSerializer& arc)
{ {
if (arc.BeginObject("mirror")) if (arc.BeginObject("mirror"))
{ {
arc("mirrorcnt", mirrorcnt) arc("mirrorcnt", mirrorcnt)
.Array("mirror", mirror, countof(mirror)) .Array("mirror", mirror, countof(mirror))
.EndObject(); .EndObject();
} }
@ -193,8 +205,8 @@ void SerializeMirrors(FSerializer& arc)
{ {
tileDelete(4080 + i); tileDelete(4080 + i);
} }
InitPolymostMirrorHack(); InitPolymostMirrorHack();
} }
} }
END_BLD_NS END_BLD_NS

View file

@ -32,24 +32,24 @@ unsigned int randSeed = 1;
unsigned int qrand(void) unsigned int qrand(void)
{ {
if (randSeed&0x80000000) if (randSeed & 0x80000000)
randSeed = ((randSeed<<1)^0x20000004)|0x1; randSeed = ((randSeed << 1) ^ 0x20000004) | 0x1;
else else
randSeed = randSeed<<1; randSeed = randSeed << 1;
return randSeed&0x7fff; return randSeed & 0x7fff;
} }
int wRandSeed = 1; int wRandSeed = 1;
int wrand(void) int wrand(void)
{ {
wRandSeed = (wRandSeed*1103515245)+12345; wRandSeed = (wRandSeed * 1103515245) + 12345;
return FixedToInt(wRandSeed)&0x7fff; return FixedToInt(wRandSeed) & 0x7fff;
} }
void wsrand(int seed) void wsrand(int seed)
{ {
wRandSeed = seed; wRandSeed = seed;
} }

View file

@ -37,7 +37,7 @@ int wrand(void);
void wsrand(int); void wsrand(int);
void FireInit(void); void FireInit(void);
void FireProcess(void); void FireProcess(void);
void UpdateNetworkMenus(void); void UpdateNetworkMenus(void);
void InitMirrors(void); void InitMirrors(void);
void setPortalFlags(int mode); void setPortalFlags(int mode);
void processSpritesOnOtherSideOfPortal(int x, int y, int interpolation); void processSpritesOnOtherSideOfPortal(int x, int y, int interpolation);
@ -46,61 +46,61 @@ int qanimateoffs(int a1, int a2);
struct PLAYER; struct PLAYER;
bool checkFired6or7(PLAYER *pPlayer); bool checkFired6or7(PLAYER* pPlayer);
void WeaponInit(void); void WeaponInit(void);
void WeaponDraw(PLAYER *pPlayer, int a2, double a3, double a4, int a5); void WeaponDraw(PLAYER* pPlayer, int a2, double a3, double a4, int a5);
void WeaponRaise(PLAYER *pPlayer); void WeaponRaise(PLAYER* pPlayer);
void WeaponLower(PLAYER *pPlayer); void WeaponLower(PLAYER* pPlayer);
int WeaponUpgrade(PLAYER *pPlayer, int newWeapon); int WeaponUpgrade(PLAYER* pPlayer, int newWeapon);
void WeaponProcess(PLAYER *pPlayer); void WeaponProcess(PLAYER* pPlayer);
void WeaponUpdateState(PLAYER* pPlayer); void WeaponUpdateState(PLAYER* pPlayer);
void teslaHit(DBloodActor *pMissile, int a2); void teslaHit(DBloodActor* pMissile, int a2);
void WeaponPrecache(); void WeaponPrecache();
struct ZONE { struct ZONE {
int x, y, z; int x, y, z;
sectortype* sector; sectortype* sector;
short ang; short ang;
}; };
extern ZONE gStartZone[8]; extern ZONE gStartZone[8];
void warpInit(TArray<DBloodActor*>& actors); void warpInit(TArray<DBloodActor*>& actors);
int CheckLink(DBloodActor *pSprite); int CheckLink(DBloodActor* pSprite);
int CheckLink(int *x, int *y, int *z, sectortype** pSector); int CheckLink(int* x, int* y, int* z, sectortype** pSector);
int GetOctant(int x, int y); int GetOctant(int x, int y);
void RotateVector(int *dx, int *dy, int nAngle); void RotateVector(int* dx, int* dy, int nAngle);
void RotatePoint(int *x, int *y, int nAngle, int ox, int oy); void RotatePoint(int* x, int* y, int nAngle, int ox, int oy);
#include "m_fixed.h" #include "m_fixed.h"
inline int Sin(int ang) inline int Sin(int ang)
{ {
return sintable[ang & 2047]; return sintable[ang & 2047];
} }
inline int Cos(int ang) inline int Cos(int ang)
{ {
return sintable[(ang + 512) & 2047]; return sintable[(ang + 512) & 2047];
} }
enum SurfaceType { enum SurfaceType {
kSurfNone = 0, kSurfNone = 0,
kSurfStone, kSurfStone,
kSurfMetal, kSurfMetal,
kSurfWood, kSurfWood,
kSurfFlesh, kSurfFlesh,
kSurfWater, kSurfWater,
kSurfDirt, kSurfDirt,
kSurfClay, kSurfClay,
kSurfSnow, kSurfSnow,
kSurfIce, kSurfIce,
kSurfLeaves, kSurfLeaves,
kSurfCloth, kSurfCloth,
kSurfPlant, kSurfPlant,
kSurfGoo, kSurfGoo,
kSurfLava, kSurfLava,
kSurfMax kSurfMax
}; };
extern uint8_t surfType[MAXTILES]; extern uint8_t surfType[MAXTILES];

File diff suppressed because it is too large Load diff

View file

@ -42,222 +42,222 @@ BEGIN_BLD_NS
enum enum
{ {
// CONSTANTS // CONSTANTS
// additional non-thing proximity, sight and physics sprites // additional non-thing proximity, sight and physics sprites
kMaxSuperXSprites = 512, kMaxSuperXSprites = 512,
kMaxTrackingConditions = 64, kMaxTrackingConditions = 64,
kMaxTracedObjects = 32, // per one tracking condition kMaxTracedObjects = 32, // per one tracking condition
// additional physics attributes for debris sprites // additional physics attributes for debris sprites
kPhysDebrisFloat = 0x0008, // *debris* slowly goes up and down from it's position kPhysDebrisFloat = 0x0008, // *debris* slowly goes up and down from it's position
kPhysDebrisFly = 0x0010, // *debris* affected by negative gravity (fly instead of falling) kPhysDebrisFly = 0x0010, // *debris* affected by negative gravity (fly instead of falling)
kPhysDebrisSwim = 0x0020, // *debris* can swim underwater (instead of drowning) kPhysDebrisSwim = 0x0020, // *debris* can swim underwater (instead of drowning)
kPhysDebrisTouch = 0x0040, // *debris* can be moved via touch kPhysDebrisTouch = 0x0040, // *debris* can be moved via touch
kPhysDebrisVector = 0x0400, // *debris* can be affected by vector weapons kPhysDebrisVector = 0x0400, // *debris* can be affected by vector weapons
kPhysDebrisExplode = 0x0800, // *debris* can be affected by explosions kPhysDebrisExplode = 0x0800, // *debris* can be affected by explosions
// *modern types only hitag* // *modern types only hitag*
kModernTypeFlag0 = 0x0000, kModernTypeFlag0 = 0x0000,
kModernTypeFlag1 = 0x0001, kModernTypeFlag1 = 0x0001,
kModernTypeFlag2 = 0x0002, kModernTypeFlag2 = 0x0002,
kModernTypeFlag3 = 0x0003, kModernTypeFlag3 = 0x0003,
kModernTypeFlag4 = 0x0004, kModernTypeFlag4 = 0x0004,
kModernTypeFlag8 = 0x0008, kModernTypeFlag8 = 0x0008,
kModernTypeFlag16 = 0x0010, kModernTypeFlag16 = 0x0010,
kMaxRandomizeRetries = 16, kMaxRandomizeRetries = 16,
kPercFull = 100, kPercFull = 100,
kCondRange = 100, kCondRange = 100,
}; };
enum enum
{ {
kPatrolStateSize = 42, kPatrolStateSize = 42,
kPatrolAlarmSeeDist = 10000, kPatrolAlarmSeeDist = 10000,
kPatrolAlarmHearDist = 10000, kPatrolAlarmHearDist = 10000,
kMaxPatrolVelocity = 500000, kMaxPatrolVelocity = 500000,
kMaxPatrolCrouchVelocity = (kMaxPatrolVelocity >> 1), kMaxPatrolCrouchVelocity = (kMaxPatrolVelocity >> 1),
kMaxPatrolSpotValue = 500, kMaxPatrolSpotValue = 500,
kMinPatrolTurnDelay = 8, kMinPatrolTurnDelay = 8,
kPatrolTurnDelayRange = 20, kPatrolTurnDelayRange = 20,
kDudeFlagStealth = 0x0001, kDudeFlagStealth = 0x0001,
kDudeFlagCrouch = 0x0002, kDudeFlagCrouch = 0x0002,
kSlopeDist = 0x20, kSlopeDist = 0x20,
kEffectGenCallbackBase = 200, kEffectGenCallbackBase = 200,
kTriggerSpriteScreen = 0x0001, kTriggerSpriteScreen = 0x0001,
kTriggerSpriteAim = 0x0002, kTriggerSpriteAim = 0x0002,
kMinAllowedPowerup = kPwUpFeatherFall, kMinAllowedPowerup = kPwUpFeatherFall,
kMaxAllowedPowerup = kMaxPowerUps kMaxAllowedPowerup = kMaxPowerUps
}; };
// modern statnums // modern statnums
enum { enum {
kStatModernBase = 20, kStatModernBase = 20,
kStatModernDudeTargetChanger = kStatModernBase, kStatModernDudeTargetChanger = kStatModernBase,
kStatModernCondition = 21, kStatModernCondition = 21,
kStatModernEventRedirector = 22, kStatModernEventRedirector = 22,
kStatModernPlayerLinker = 23, kStatModernPlayerLinker = 23,
kStatModernBrokenDudeLeech = 24, kStatModernBrokenDudeLeech = 24,
kStatModernQavScene = 25, kStatModernQavScene = 25,
kStatModernWindGen = 26, kStatModernWindGen = 26,
kStatModernStealthRegion = 27, kStatModernStealthRegion = 27,
kStatModernTmp = 39, kStatModernTmp = 39,
kStatModernMax = 40, kStatModernMax = 40,
}; };
// modern sprite types // modern sprite types
enum { enum {
kModernStealthRegion = 16, kModernStealthRegion = 16,
kModernCustomDudeSpawn = 24, kModernCustomDudeSpawn = 24,
kModernRandomTX = 25, kModernRandomTX = 25,
kModernSequentialTX = 26, kModernSequentialTX = 26,
kModernSeqSpawner = 27, kModernSeqSpawner = 27,
kModernObjPropertiesChanger = 28, kModernObjPropertiesChanger = 28,
kModernObjPicnumChanger = 29, kModernObjPicnumChanger = 29,
kModernObjSizeChanger = 31, kModernObjSizeChanger = 31,
kModernDudeTargetChanger = 33, kModernDudeTargetChanger = 33,
kModernSectorFXChanger = 34, kModernSectorFXChanger = 34,
kModernObjDataChanger = 35, kModernObjDataChanger = 35,
kModernSpriteDamager = 36, kModernSpriteDamager = 36,
kModernObjDataAccumulator = 37, kModernObjDataAccumulator = 37,
kModernEffectSpawner = 38, kModernEffectSpawner = 38,
kModernWindGenerator = 39, kModernWindGenerator = 39,
kModernRandom = 40, kModernRandom = 40,
kModernRandom2 = 80, kModernRandom2 = 80,
kItemShroomGrow = 129, kItemShroomGrow = 129,
kItemShroomShrink = 130, kItemShroomShrink = 130,
kItemModernMapLevel = 150, // once picked up, draws whole minimap kItemModernMapLevel = 150, // once picked up, draws whole minimap
kDudeModernCustom = kDudeVanillaMax, kDudeModernCustom = kDudeVanillaMax,
kDudeModernCustomBurning = 255, kDudeModernCustomBurning = 255,
kModernThingTNTProx = 433, // detects only players kModernThingTNTProx = 433, // detects only players
kModernThingThrowableRock = 434, // does small damage if hits target kModernThingThrowableRock = 434, // does small damage if hits target
kModernThingEnemyLifeLeech = 435, // the same as normal, except it aims in specified target only kModernThingEnemyLifeLeech = 435, // the same as normal, except it aims in specified target only
kModernPlayerControl = 500, /// WIP kModernPlayerControl = 500, /// WIP
kModernCondition = 501, /// WIP, sends command only if specified conditions == true kModernCondition = 501, /// WIP, sends command only if specified conditions == true
kModernConditionFalse = 502, /// WIP, sends command only if specified conditions != true kModernConditionFalse = 502, /// WIP, sends command only if specified conditions != true
kModernSlopeChanger = 504, kModernSlopeChanger = 504,
kGenModernMissileUniversal = 704, kGenModernMissileUniversal = 704,
kGenModernSound = 708, kGenModernSound = 708,
}; };
// type of random // type of random
enum { enum {
kRandomizeItem = 0, kRandomizeItem = 0,
kRandomizeDude = 1, kRandomizeDude = 1,
kRandomizeTX = 2, kRandomizeTX = 2,
}; };
// type of object // type of object
enum { enum {
OBJ_WALL = 0, OBJ_WALL = 0,
OBJ_SPRITE = 3, OBJ_SPRITE = 3,
OBJ_SECTOR = 6, OBJ_SECTOR = 6,
}; };
enum { enum {
kCondGameBase = 0, kCondGameBase = 0,
kCondGameMax = 50, kCondGameMax = 50,
kCondMixedBase = 100, kCondMixedBase = 100,
kCondMixedMax = 200, kCondMixedMax = 200,
kCondWallBase = 200, kCondWallBase = 200,
kCondWallMax = 300, kCondWallMax = 300,
kCondSectorBase = 300, kCondSectorBase = 300,
kCondSectorMax = 400, kCondSectorMax = 400,
kCondPlayerBase = 400, kCondPlayerBase = 400,
kCondPlayerMax = 450, kCondPlayerMax = 450,
kCondDudeBase = 450, kCondDudeBase = 450,
kCondDudeMax = 500, kCondDudeMax = 500,
kCondSpriteBase = 500, kCondSpriteBase = 500,
kCondSpriteMax = 600, kCondSpriteMax = 600,
}; };
enum { enum {
kCondSerialSector = 100000, kCondSerialSector = 100000,
kCondSerialWall = 200000, kCondSerialWall = 200000,
kCondSerialSprite = 300000, kCondSerialSprite = 300000,
kCondSerialMax = 400000, kCondSerialMax = 400000,
}; };
enum { enum {
kPatrolMoveForward = 0, kPatrolMoveForward = 0,
kPatrolMoveBackward = 1, kPatrolMoveBackward = 1,
}; };
// - STRUCTS ------------------------------------------------------------------ // - STRUCTS ------------------------------------------------------------------
struct SPRITEMASS { // sprite mass info for getSpriteMassBySize(); struct SPRITEMASS { // sprite mass info for getSpriteMassBySize();
int seqId; int seqId;
int16_t picnum; // mainly needs for moving debris int16_t picnum; // mainly needs for moving debris
int16_t xrepeat; int16_t xrepeat;
int16_t yrepeat; int16_t yrepeat;
int16_t clipdist; // mass multiplier int16_t clipdist; // mass multiplier
int mass; int mass;
int16_t airVel; // mainly needs for moving debris int16_t airVel; // mainly needs for moving debris
int fraction; // mainly needs for moving debris int fraction; // mainly needs for moving debris
}; };
struct QAVSCENE { // this one stores qavs anims that can be played by trigger struct QAVSCENE { // this one stores qavs anims that can be played by trigger
DBloodActor* initiator = nullptr; // index of sprite which triggered qav scene DBloodActor* initiator = nullptr; // index of sprite which triggered qav scene
QAV* qavResrc = nullptr; QAV* qavResrc = nullptr;
short dummy = -1; short dummy = -1;
}; };
struct THINGINFO_EXTRA { struct THINGINFO_EXTRA {
bool allowThrow; // indicates if kDudeModernCustom can throw it bool allowThrow; // indicates if kDudeModernCustom can throw it
}; };
struct VECTORINFO_EXTRA { struct VECTORINFO_EXTRA {
int fireSound[2]; // predefined fire sounds. used by kDudeModernCustom, but can be used for something else. int fireSound[2]; // predefined fire sounds. used by kDudeModernCustom, but can be used for something else.
}; };
struct MISSILEINFO_EXTRA { struct MISSILEINFO_EXTRA {
int fireSound[2]; // predefined fire sounds. used by kDudeModernCustom, but can be used for something else. int fireSound[2]; // predefined fire sounds. used by kDudeModernCustom, but can be used for something else.
bool dmgType[kDamageMax]; // list of damages types missile can use bool dmgType[kDamageMax]; // list of damages types missile can use
bool allowImpact; // allow to trigger object with Impact flag enabled with this missile bool allowImpact; // allow to trigger object with Impact flag enabled with this missile
}; };
struct DUDEINFO_EXTRA { struct DUDEINFO_EXTRA {
bool flying; // used by kModernDudeTargetChanger (ai fight) bool flying; // used by kModernDudeTargetChanger (ai fight)
bool melee; // used by kModernDudeTargetChanger (ai fight) bool melee; // used by kModernDudeTargetChanger (ai fight)
int idlgseqofs : 6; // used for patrol int idlgseqofs : 6; // used for patrol
int mvegseqofs : 6; // used for patrol int mvegseqofs : 6; // used for patrol
int idlwseqofs : 6; // used for patrol int idlwseqofs : 6; // used for patrol
int mvewseqofs : 6; // used for patrol int mvewseqofs : 6; // used for patrol
int idlcseqofs : 6; // used for patrol int idlcseqofs : 6; // used for patrol
int mvecseqofs : 6; // used for patrol int mvecseqofs : 6; // used for patrol
}; };
struct TRPLAYERCTRL { // this one for controlling the player using triggers (movement speed, jumps and other stuff) struct TRPLAYERCTRL { // this one for controlling the player using triggers (movement speed, jumps and other stuff)
QAVSCENE qavScene; QAVSCENE qavScene;
}; };
struct OBJECTS_TO_TRACK { struct OBJECTS_TO_TRACK {
uint8_t cmd; uint8_t cmd;
EventObject obj; EventObject obj;
}; };
struct TRCONDITION { struct TRCONDITION {
DBloodActor* actor; DBloodActor* actor;
uint8_t length; uint8_t length;
OBJECTS_TO_TRACK obj[kMaxTracedObjects]; OBJECTS_TO_TRACK obj[kMaxTracedObjects];
}; };
struct PATROL_FOUND_SOUNDS { struct PATROL_FOUND_SOUNDS {
int snd; int snd;
int max; int max;
int cur; int cur;
}; };
struct CONDITION_TYPE_NAMES { struct CONDITION_TYPE_NAMES {
int rng1; int rng1;
int rng2; int rng2;
char name[32]; char name[32];
}; };
@ -331,7 +331,7 @@ void seqTxSendCmdAll(DBloodActor* pXSource, DBloodActor* nIndex, COMMAND_ID cmd,
void trPlayerCtrlLink(DBloodActor* pXSource, PLAYER* pPlayer, bool checkCondition); void trPlayerCtrlLink(DBloodActor* pXSource, PLAYER* pPlayer, bool checkCondition);
void trPlayerCtrlStopScene(PLAYER* pPlayer); void trPlayerCtrlStopScene(PLAYER* pPlayer);
// ------------------------------------------------------------------------- // // ------------------------------------------------------------------------- //
void modernTypeTrigger(int type, sectortype*sect, walltype* wal, DBloodActor* actor, EVENT& event); void modernTypeTrigger(int type, sectortype* sect, walltype* wal, DBloodActor* actor, EVENT& event);
bool modernTypeOperateSector(sectortype* pSector, const EVENT& event); bool modernTypeOperateSector(sectortype* pSector, const EVENT& event);
bool modernTypeOperateSprite(DBloodActor*, EVENT& event); bool modernTypeOperateSprite(DBloodActor*, EVENT& event);
bool modernTypeOperateWall(walltype* pWall, const EVENT& event); bool modernTypeOperateWall(walltype* pWall, const EVENT& event);
@ -348,7 +348,7 @@ void playerQavScenePlay(PLAYER* pPlayer);
void playerQavSceneDraw(PLAYER* pPlayer, int a2, double a3, double a4, int a5); void playerQavSceneDraw(PLAYER* pPlayer, int a2, double a3, double a4, int a5);
void playerQavSceneReset(PLAYER* pPlayer); void playerQavSceneReset(PLAYER* pPlayer);
// ------------------------------------------------------------------------- // // ------------------------------------------------------------------------- //
void callbackUniMissileBurst(DBloodActor*actor, sectortype* nSprite); void callbackUniMissileBurst(DBloodActor* actor, sectortype* nSprite);
void callbackMakeMissileBlocking(DBloodActor* actor, sectortype* nSprite); void callbackMakeMissileBlocking(DBloodActor* actor, sectortype* nSprite);
void callbackGenDudeUpdate(DBloodActor* actor, sectortype* nSprite); void callbackGenDudeUpdate(DBloodActor* actor, sectortype* nSprite);
// ------------------------------------------------------------------------- // // ------------------------------------------------------------------------- //
@ -387,27 +387,27 @@ void aiPatrolFlagsMgr(DBloodActor* sourceactor, DBloodActor* destactor, bool cop
void aiPatrolRandGoalAng(DBloodActor* actor); void aiPatrolRandGoalAng(DBloodActor* actor);
void aiPatrolTurn(DBloodActor* actor); void aiPatrolTurn(DBloodActor* actor);
inline int aiPatrolGetVelocity(int speed, int value) { inline int aiPatrolGetVelocity(int speed, int value) {
return (value > 0) ? ClipRange((speed / 3) + (2500 * value), 0, 0x47956) : speed; return (value > 0) ? ClipRange((speed / 3) + (2500 * value), 0, 0x47956) : speed;
} }
inline bool aiPatrolWaiting(AISTATE* pAiState) { inline bool aiPatrolWaiting(AISTATE* pAiState) {
return (pAiState && pAiState->stateType >= kAiStatePatrolWaitL && pAiState->stateType <= kAiStatePatrolWaitW); return (pAiState && pAiState->stateType >= kAiStatePatrolWaitL && pAiState->stateType <= kAiStatePatrolWaitW);
} }
inline bool aiPatrolMoving(AISTATE* pAiState) { inline bool aiPatrolMoving(AISTATE* pAiState) {
return (pAiState && pAiState->stateType >= kAiStatePatrolMoveL && pAiState->stateType <= kAiStatePatrolMoveW); return (pAiState && pAiState->stateType >= kAiStatePatrolMoveL && pAiState->stateType <= kAiStatePatrolMoveW);
} }
inline bool aiPatrolTurning(AISTATE* pAiState) { inline bool aiPatrolTurning(AISTATE* pAiState) {
return (pAiState && pAiState->stateType >= kAiStatePatrolTurnL && pAiState->stateType <= kAiStatePatrolTurnW); return (pAiState && pAiState->stateType >= kAiStatePatrolTurnL && pAiState->stateType <= kAiStatePatrolTurnW);
} }
inline bool aiInPatrolState(AISTATE* pAiState) { inline bool aiInPatrolState(AISTATE* pAiState) {
return (pAiState && pAiState->stateType >= kAiStatePatrolBase && pAiState->stateType < kAiStatePatrolMax); return (pAiState && pAiState->stateType >= kAiStatePatrolBase && pAiState->stateType < kAiStatePatrolMax);
} }
inline bool aiInPatrolState(int nAiStateType) { inline bool aiInPatrolState(int nAiStateType) {
return (nAiStateType >= kAiStatePatrolBase && nAiStateType < kAiStatePatrolMax); return (nAiStateType >= kAiStatePatrolBase && nAiStateType < kAiStatePatrolMax);
} }
// ------------------------------------------------------------------------- // // ------------------------------------------------------------------------- //
bool readyForCrit(DBloodActor* pHunter, DBloodActor* pVictim); bool readyForCrit(DBloodActor* pHunter, DBloodActor* pVictim);
@ -416,7 +416,7 @@ void clampSprite(DBloodActor* actor, int which = 3);
inline bool valueIsBetween(int val, int min, int max) inline bool valueIsBetween(int val, int min, int max)
{ {
return (val > min && val < max); return (val > min && val < max);
} }

View file

@ -33,62 +33,62 @@ BEGIN_BLD_NS
void GameInterface::WarpToCoords(int x, int y, int z, int ang, int horz) void GameInterface::WarpToCoords(int x, int y, int z, int ang, int horz)
{ {
PLAYER *pPlayer = &gPlayer[myconnectindex]; PLAYER* pPlayer = &gPlayer[myconnectindex];
VIEW* pView = &gPrevView[myconnectindex]; VIEW* pView = &gPrevView[myconnectindex];
pPlayer->actor->spr.pos.X = pView->x = gView->actor->spr.pos.X = x; pPlayer->actor->spr.pos.X = pView->x = gView->actor->spr.pos.X = x;
pPlayer->actor->spr.pos.Y = pView->y = gView->actor->spr.pos.Y = y; pPlayer->actor->spr.pos.Y = pView->y = gView->actor->spr.pos.Y = y;
pPlayer->zView = pView->viewz = gView->zView = z; pPlayer->zView = pView->viewz = gView->zView = z;
if (ang != INT_MIN) if (ang != INT_MIN)
{ {
pPlayer->angle.oang = pPlayer->angle.ang = pView->angle = gView->angle.ang = buildang(ang); pPlayer->angle.oang = pPlayer->angle.ang = pView->angle = gView->angle.ang = buildang(ang);
} }
if (horz != INT_MIN) if (horz != INT_MIN)
{ {
pPlayer->horizon.ohoriz = pPlayer->horizon.horiz = pView->horiz = gView->horizon.horiz = buildhoriz(horz); pPlayer->horizon.ohoriz = pPlayer->horizon.horiz = pView->horiz = gView->horizon.horiz = buildhoriz(horz);
} }
} }
void GameInterface::ToggleThirdPerson() void GameInterface::ToggleThirdPerson()
{ {
if (gamestate != GS_LEVEL) return; if (gamestate != GS_LEVEL) return;
if (gViewPos > VIEWPOS_0) if (gViewPos > VIEWPOS_0)
gViewPos = VIEWPOS_0; gViewPos = VIEWPOS_0;
else else
gViewPos = VIEWPOS_1; gViewPos = VIEWPOS_1;
} }
void GameInterface::SwitchCoopView() void GameInterface::SwitchCoopView()
{ {
if (gamestate != GS_LEVEL) return; if (gamestate != GS_LEVEL) return;
if (gGameOptions.nGameType == 1) if (gGameOptions.nGameType == 1)
{ {
gViewIndex = connectpoint2[gViewIndex]; gViewIndex = connectpoint2[gViewIndex];
if (gViewIndex == -1) if (gViewIndex == -1)
gViewIndex = connecthead; gViewIndex = connecthead;
gView = &gPlayer[gViewIndex]; gView = &gPlayer[gViewIndex];
} }
else if (gGameOptions.nGameType == 3) else if (gGameOptions.nGameType == 3)
{ {
int oldViewIndex = gViewIndex; int oldViewIndex = gViewIndex;
do do
{ {
gViewIndex = connectpoint2[gViewIndex]; gViewIndex = connectpoint2[gViewIndex];
if (gViewIndex == -1) if (gViewIndex == -1)
gViewIndex = connecthead; gViewIndex = connecthead;
if (oldViewIndex == gViewIndex || gMe->teamId == gPlayer[gViewIndex].teamId) if (oldViewIndex == gViewIndex || gMe->teamId == gPlayer[gViewIndex].teamId)
break; break;
} while (oldViewIndex != gViewIndex); } while (oldViewIndex != gViewIndex);
gView = &gPlayer[gViewIndex]; gView = &gPlayer[gViewIndex];
} }
} }
void GameInterface::ToggleShowWeapon() void GameInterface::ToggleShowWeapon()
{ {
if (gamestate != GS_LEVEL) return; if (gamestate != GS_LEVEL) return;
cl_showweapon = (cl_showweapon + 1) & 3; cl_showweapon = (cl_showweapon + 1) & 3;
} }
END_BLD_NS END_BLD_NS

File diff suppressed because it is too large Load diff

View file

@ -36,166 +36,166 @@ BEGIN_BLD_NS
// life modes of the player // life modes of the player
enum enum
{ {
kModeHuman = 0, kModeHuman = 0,
kModeBeast = 1, kModeBeast = 1,
kModeHumanShrink = 2, kModeHumanShrink = 2,
kModeHumanGrown = 3, kModeHumanGrown = 3,
kModeMax = 4, kModeMax = 4,
}; };
// postures // postures
enum enum
{ {
kPostureStand = 0, kPostureStand = 0,
kPostureSwim = 1, kPostureSwim = 1,
kPostureCrouch = 2, kPostureCrouch = 2,
kPostureMax = 3, kPostureMax = 3,
}; };
struct PACKINFO struct PACKINFO
{ {
bool isActive; // is active (0/1) bool isActive; // is active (0/1)
int curAmount = 0; // remaining percent int curAmount = 0; // remaining percent
}; };
struct POSTURE struct POSTURE
{ {
int frontAccel; int frontAccel;
int sideAccel; int sideAccel;
int backAccel; int backAccel;
int pace[2]; int pace[2];
int bobV; int bobV;
int bobH; int bobH;
int swayV; int swayV;
int swayH; int swayH;
int eyeAboveZ; int eyeAboveZ;
int weaponAboveZ; int weaponAboveZ;
int xOffset; int xOffset;
int zOffset; int zOffset;
int normalJumpZ; int normalJumpZ;
int pwupJumpZ; int pwupJumpZ;
}; };
extern POSTURE gPostureDefaults[kModeMax][kPostureMax]; extern POSTURE gPostureDefaults[kModeMax][kPostureMax];
struct PLAYER struct PLAYER
{ {
DBloodActor* actor; DBloodActor* actor;
DUDEINFO* pDudeInfo; DUDEINFO* pDudeInfo;
InputPacket input; InputPacket input;
PlayerHorizon horizon; PlayerHorizon horizon;
PlayerAngle angle; PlayerAngle angle;
uint8_t newWeapon; uint8_t newWeapon;
int used1; // something related to game checksum int used1; // something related to game checksum
int weaponQav; int weaponQav;
int qavCallback; int qavCallback;
bool isRunning; bool isRunning;
int posture; // stand, crouch, swim int posture; // stand, crouch, swim
int sceneQav; // by NoOne: used to keep qav id int sceneQav; // by NoOne: used to keep qav id
int bobPhase; int bobPhase;
int bobAmp; int bobAmp;
int bobHeight; int bobHeight;
int bobWidth; int bobWidth;
int swayPhase; int swayPhase;
int swayAmp; int swayAmp;
int swayHeight; int swayHeight;
int swayWidth; int swayWidth;
int nPlayer; // Connect id int nPlayer; // Connect id
int lifeMode; int lifeMode;
int bloodlust; // ---> useless int bloodlust; // ---> useless
int zView; int zView;
int zViewVel; int zViewVel;
int zWeapon; int zWeapon;
int zWeaponVel; int zWeaponVel;
int slope; int slope;
bool isUnderwater; bool isUnderwater;
bool hasKey[8]; bool hasKey[8];
int8_t hasFlag; int8_t hasFlag;
TObjPtr<DBloodActor*> ctfFlagState[2]; TObjPtr<DBloodActor*> ctfFlagState[2];
int damageControl[7]; int damageControl[7];
int8_t curWeapon; int8_t curWeapon;
int8_t nextWeapon; int8_t nextWeapon;
int weaponTimer; int weaponTimer;
int weaponState; int weaponState;
int weaponAmmo; //rename int weaponAmmo; //rename
bool hasWeapon[14]; bool hasWeapon[14];
int weaponMode[14]; int weaponMode[14];
int weaponOrder[2][14]; int weaponOrder[2][14];
//int at149[14]; //int at149[14];
int ammoCount[12]; int ammoCount[12];
bool qavLoop; bool qavLoop;
int qavLastTick; int qavLastTick;
int qavTimer; int qavTimer;
int fuseTime; int fuseTime;
int throwTime; int throwTime;
int throwPower; int throwPower;
Aim aim; // world Aim aim; // world
//int at1c6; //int at1c6;
Aim relAim; // relative Aim relAim; // relative
//int relAim; //int relAim;
//int at1ce; //int at1ce;
//int at1d2; //int at1d2;
TObjPtr<DBloodActor*> aimTarget; // aim target sprite TObjPtr<DBloodActor*> aimTarget; // aim target sprite
int aimTargetsCount; int aimTargetsCount;
TObjPtr<DBloodActor*> aimTargets[16]; TObjPtr<DBloodActor*> aimTargets[16];
int deathTime; int deathTime;
int pwUpTime[kMaxPowerUps]; int pwUpTime[kMaxPowerUps];
int fragCount; int fragCount;
int fragInfo[8]; int fragInfo[8];
int teamId; int teamId;
TObjPtr<DBloodActor*> fragger; TObjPtr<DBloodActor*> fragger;
int underwaterTime; int underwaterTime;
int bubbleTime; int bubbleTime;
int restTime; int restTime;
int kickPower; int kickPower;
int laughCount; int laughCount;
bool godMode; bool godMode;
bool fallScream; bool fallScream;
bool cantJump; bool cantJump;
int packItemTime; // pack timer int packItemTime; // pack timer
int packItemId; // pack id 1: diving suit, 2: crystal ball, 3: beast vision 4: jump boots int packItemId; // pack id 1: diving suit, 2: crystal ball, 3: beast vision 4: jump boots
PACKINFO packSlots[5]; // at325 [1]: diving suit, [2]: crystal ball, [3]: beast vision [4]: jump boots PACKINFO packSlots[5]; // at325 [1]: diving suit, [2]: crystal ball, [3]: beast vision [4]: jump boots
int armor[3]; // armor int armor[3]; // armor
//int at342; //int at342;
//int at346; //int at346;
TObjPtr<DBloodActor*> voodooTarget; TObjPtr<DBloodActor*> voodooTarget;
int voodooTargets; // --> useless int voodooTargets; // --> useless
int voodooVar1; // --> useless int voodooVar1; // --> useless
int vodooVar2; // --> useless int vodooVar2; // --> useless
int flickerEffect; int flickerEffect;
int tiltEffect; int tiltEffect;
int visibility; int visibility;
int painEffect; int painEffect;
int blindEffect; int blindEffect;
int chokeEffect; int chokeEffect;
int handTime; int handTime;
bool hand; // if true, there is hand start choking the player bool hand; // if true, there is hand start choking the player
int pickupEffect; int pickupEffect;
bool flashEffect; // if true, reduce pPlayer->visibility counter bool flashEffect; // if true, reduce pPlayer->visibility counter
int quakeEffect; int quakeEffect;
int player_par; int player_par;
int nWaterPal; int nWaterPal;
POSTURE pPosture[kModeMax][kPostureMax]; POSTURE pPosture[kModeMax][kPostureMax];
}; };
struct AMMOINFO struct AMMOINFO
{ {
int max; int max;
int8_t vectorType; int8_t vectorType;
}; };
struct POWERUPINFO struct POWERUPINFO
{ {
int16_t picnum; int16_t picnum;
bool pickupOnce; bool pickupOnce;
int bonusTime; int bonusTime;
int maxTime; int maxTime;
}; };
void playerResetPosture(PLAYER* pPlayer); void playerResetPosture(PLAYER* pPlayer);
extern PLAYER gPlayer[kMaxPlayers]; extern PLAYER gPlayer[kMaxPlayers];
extern PLAYER *gMe, *gView; extern PLAYER* gMe, * gView;
extern bool gBlueFlagDropped; extern bool gBlueFlagDropped;
extern bool gRedFlagDropped; extern bool gRedFlagDropped;
@ -206,39 +206,39 @@ extern AMMOINFO gAmmoInfo[];
extern POWERUPINFO gPowerUpInfo[kMaxPowerUps]; extern POWERUPINFO gPowerUpInfo[kMaxPowerUps];
bool IsTargetTeammate(PLAYER* pSourcePlayer, DBloodActor* target); bool IsTargetTeammate(PLAYER* pSourcePlayer, DBloodActor* target);
int powerupCheck(PLAYER *pPlayer, int nPowerUp); int powerupCheck(PLAYER* pPlayer, int nPowerUp);
bool powerupActivate(PLAYER *pPlayer, int nPowerUp); bool powerupActivate(PLAYER* pPlayer, int nPowerUp);
void powerupDeactivate(PLAYER *pPlayer, int nPowerUp); void powerupDeactivate(PLAYER* pPlayer, int nPowerUp);
void powerupSetState(PLAYER *pPlayer, int nPowerUp, bool bState); void powerupSetState(PLAYER* pPlayer, int nPowerUp, bool bState);
void powerupProcess(PLAYER *pPlayer); void powerupProcess(PLAYER* pPlayer);
void powerupClear(PLAYER *pPlayer); void powerupClear(PLAYER* pPlayer);
int packItemToPowerup(int nPack); int packItemToPowerup(int nPack);
int powerupToPackItem(int nPowerUp); int powerupToPackItem(int nPowerUp);
bool packAddItem(PLAYER *pPlayer, unsigned int nPack); bool packAddItem(PLAYER* pPlayer, unsigned int nPack);
int packCheckItem(PLAYER *pPlayer, int nPack); int packCheckItem(PLAYER* pPlayer, int nPack);
bool packItemActive(PLAYER *pPlayer, int nPack); bool packItemActive(PLAYER* pPlayer, int nPack);
void packUseItem(PLAYER *pPlayer, int nPack); void packUseItem(PLAYER* pPlayer, int nPack);
void packPrevItem(PLAYER *pPlayer); void packPrevItem(PLAYER* pPlayer);
void packNextItem(PLAYER *pPlayer); void packNextItem(PLAYER* pPlayer);
bool playerSeqPlaying(PLAYER *pPlayer, int nSeq); bool playerSeqPlaying(PLAYER* pPlayer, int nSeq);
void playerSetRace(PLAYER *pPlayer, int nLifeMode); void playerSetRace(PLAYER* pPlayer, int nLifeMode);
void playerSetGodMode(PLAYER *pPlayer, bool bGodMode); void playerSetGodMode(PLAYER* pPlayer, bool bGodMode);
void playerResetInertia(PLAYER *pPlayer); void playerResetInertia(PLAYER* pPlayer);
void playerCorrectInertia(PLAYER *pPlayer, vec3_t const *oldpos); void playerCorrectInertia(PLAYER* pPlayer, vec3_t const* oldpos);
void playerStart(int nPlayer, int bNewLevel = 0); void playerStart(int nPlayer, int bNewLevel = 0);
void playerReset(PLAYER *pPlayer); void playerReset(PLAYER* pPlayer);
void playerInit(int nPlayer, unsigned int a2); void playerInit(int nPlayer, unsigned int a2);
void CheckPickUp(PLAYER *pPlayer); void CheckPickUp(PLAYER* pPlayer);
void ProcessInput(PLAYER *pPlayer); void ProcessInput(PLAYER* pPlayer);
void playerProcess(PLAYER *pPlayer); void playerProcess(PLAYER* pPlayer);
DBloodActor *playerFireMissile(PLAYER *pPlayer, int a2, int a3, int a4, int a5, int a6); DBloodActor* playerFireMissile(PLAYER* pPlayer, int a2, int a3, int a4, int a5, int a6);
DBloodActor *playerFireThing(PLAYER *pPlayer, int a2, int a3, int thingType, int a5); DBloodActor* playerFireThing(PLAYER* pPlayer, int a2, int a3, int thingType, int a5);
void playerFrag(PLAYER *pKiller, PLAYER *pVictim); void playerFrag(PLAYER* pKiller, PLAYER* pVictim);
int playerDamageArmor(PLAYER *pPlayer, DAMAGE_TYPE nType, int nDamage); int playerDamageArmor(PLAYER* pPlayer, DAMAGE_TYPE nType, int nDamage);
int playerDamageSprite(DBloodActor* nSource, PLAYER *pPlayer, DAMAGE_TYPE nDamageType, int nDamage); int playerDamageSprite(DBloodActor* nSource, PLAYER* pPlayer, DAMAGE_TYPE nDamageType, int nDamage);
int UseAmmo(PLAYER *pPlayer, int nAmmoType, int nDec); int UseAmmo(PLAYER* pPlayer, int nAmmoType, int nDec);
void voodooTarget(PLAYER *pPlayer); void voodooTarget(PLAYER* pPlayer);
void playerLandingSound(PLAYER *pPlayer); void playerLandingSound(PLAYER* pPlayer);
void PlayerSurvive(int, DBloodActor*); void PlayerSurvive(int, DBloodActor*);
END_BLD_NS END_BLD_NS

File diff suppressed because it is too large Load diff

View file

@ -36,281 +36,309 @@ void fxPrecache();
void gibPrecache(); void gibPrecache();
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void tilePrecacheTile(int nTile, int nType, int palette) void tilePrecacheTile(int nTile, int nType, int palette)
{ {
int n = 1; int n = 1;
switch (picanm[nTile].extra & 7) switch (picanm[nTile].extra & 7)
{ {
case 0: case 0:
n = 1; n = 1;
break; break;
case 1: case 1:
n = 5; n = 5;
break; break;
case 2: case 2:
n = 8; n = 8;
break; break;
case 3: case 3:
n = 2; n = 2;
break; break;
} }
while (n--) while (n--)
{ {
if (picanm[nTile].sf & PICANM_ANIMTYPE_MASK) if (picanm[nTile].sf & PICANM_ANIMTYPE_MASK)
{ {
for (int frame = picanm[nTile].num; frame >= 0; frame--) for (int frame = picanm[nTile].num; frame >= 0; frame--)
{ {
int tile; int tile;
if ((picanm[nTile].sf & PICANM_ANIMTYPE_MASK) == PICANM_ANIMTYPE_BACK) if ((picanm[nTile].sf & PICANM_ANIMTYPE_MASK) == PICANM_ANIMTYPE_BACK)
tile = nTile - frame; tile = nTile - frame;
else else
tile = nTile + frame; tile = nTile + frame;
markTileForPrecache(tile, palette); markTileForPrecache(tile, palette);
} }
} }
else else
{ {
markTileForPrecache(nTile, palette); markTileForPrecache(nTile, palette);
} }
nTile += 1 + picanm[nTile].num; nTile += 1 + picanm[nTile].num;
} }
} }
// To do: This needs to handle the sprite palettes as well to properly precache the needed content. // To do: This needs to handle the sprite palettes as well to properly precache the needed content.
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void viewPrecacheTiles() void viewPrecacheTiles()
{ {
tilePrecacheTile(2173, 0, 0); tilePrecacheTile(2173, 0, 0);
tilePrecacheTile(2200, 0, 0); tilePrecacheTile(2200, 0, 0);
tilePrecacheTile(2201, 0, 0); tilePrecacheTile(2201, 0, 0);
tilePrecacheTile(2202, 0, 0); tilePrecacheTile(2202, 0, 0);
tilePrecacheTile(2207, 0, 0); tilePrecacheTile(2207, 0, 0);
tilePrecacheTile(2208, 0, 0); tilePrecacheTile(2208, 0, 0);
tilePrecacheTile(2209, 0, 0); tilePrecacheTile(2209, 0, 0);
tilePrecacheTile(2229, 0, 0); tilePrecacheTile(2229, 0, 0);
tilePrecacheTile(2260, 0, 0); tilePrecacheTile(2260, 0, 0);
tilePrecacheTile(2559, 0, 0); tilePrecacheTile(2559, 0, 0);
tilePrecacheTile(2169, 0, 0); tilePrecacheTile(2169, 0, 0);
tilePrecacheTile(2578, 0, 0); tilePrecacheTile(2578, 0, 0);
tilePrecacheTile(2586, 0, 0); tilePrecacheTile(2586, 0, 0);
tilePrecacheTile(2602, 0, 0); tilePrecacheTile(2602, 0, 0);
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
tilePrecacheTile(2190 + i, 0, 0); tilePrecacheTile(2190 + i, 0, 0);
tilePrecacheTile(2230 + i, 0, 0); tilePrecacheTile(2230 + i, 0, 0);
tilePrecacheTile(2240 + i, 0, 0); tilePrecacheTile(2240 + i, 0, 0);
tilePrecacheTile(2250 + i, 0, 0); tilePrecacheTile(2250 + i, 0, 0);
tilePrecacheTile(kSBarNumberHealth + i, 0, 0); tilePrecacheTile(kSBarNumberHealth + i, 0, 0);
tilePrecacheTile(kSBarNumberAmmo + i, 0, 0); tilePrecacheTile(kSBarNumberAmmo + i, 0, 0);
tilePrecacheTile(kSBarNumberInv + i, 0, 0); tilePrecacheTile(kSBarNumberInv + i, 0, 0);
tilePrecacheTile(kSBarNumberArmor1 + i, 0, 0); tilePrecacheTile(kSBarNumberArmor1 + i, 0, 0);
tilePrecacheTile(kSBarNumberArmor2 + i, 0, 0); tilePrecacheTile(kSBarNumberArmor2 + i, 0, 0);
tilePrecacheTile(kSBarNumberArmor3 + i, 0, 0); tilePrecacheTile(kSBarNumberArmor3 + i, 0, 0);
} }
/* /*
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
{ {
tilePrecacheTile(gPackIcons[i], 0); tilePrecacheTile(gPackIcons[i], 0);
tilePrecacheTile(gPackIcons2[i].nTile, 0); tilePrecacheTile(gPackIcons2[i].nTile, 0);
} }
*/ */
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
{ {
tilePrecacheTile(2220 + i, 0, 0); tilePrecacheTile(2220 + i, 0, 0);
tilePrecacheTile(2552 + i, 0, 0); tilePrecacheTile(2552 + i, 0, 0);
} }
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void PrecacheDude(DBloodActor* actor)
void PrecacheDude(DBloodActor *actor)
{ {
int palette = actor->spr.pal; int palette = actor->spr.pal;
DUDEINFO *pDudeInfo = getDudeInfo(actor->spr.type); DUDEINFO* pDudeInfo = getDudeInfo(actor->spr.type);
seqPrecacheId(pDudeInfo->seqStartID , palette); seqPrecacheId(pDudeInfo->seqStartID, palette);
seqPrecacheId(pDudeInfo->seqStartID+5, palette); seqPrecacheId(pDudeInfo->seqStartID + 5, palette);
seqPrecacheId(pDudeInfo->seqStartID+1, palette); seqPrecacheId(pDudeInfo->seqStartID + 1, palette);
seqPrecacheId(pDudeInfo->seqStartID+2, palette); seqPrecacheId(pDudeInfo->seqStartID + 2, palette);
switch (actor->spr.type) switch (actor->spr.type)
{ {
case kDudeCultistTommy: case kDudeCultistTommy:
case kDudeCultistShotgun: case kDudeCultistShotgun:
case kDudeCultistTesla: case kDudeCultistTesla:
case kDudeCultistTNT: case kDudeCultistTNT:
seqPrecacheId(pDudeInfo->seqStartID+6 , palette); seqPrecacheId(pDudeInfo->seqStartID + 6, palette);
seqPrecacheId(pDudeInfo->seqStartID+7 , palette); seqPrecacheId(pDudeInfo->seqStartID + 7, palette);
seqPrecacheId(pDudeInfo->seqStartID+8 , palette); seqPrecacheId(pDudeInfo->seqStartID + 8, palette);
seqPrecacheId(pDudeInfo->seqStartID+9 , palette); seqPrecacheId(pDudeInfo->seqStartID + 9, palette);
seqPrecacheId(pDudeInfo->seqStartID+13, palette); seqPrecacheId(pDudeInfo->seqStartID + 13, palette);
seqPrecacheId(pDudeInfo->seqStartID+14, palette); seqPrecacheId(pDudeInfo->seqStartID + 14, palette);
seqPrecacheId(pDudeInfo->seqStartID+15, palette); seqPrecacheId(pDudeInfo->seqStartID + 15, palette);
break; break;
case kDudeZombieButcher: case kDudeZombieButcher:
case kDudeGillBeast: case kDudeGillBeast:
seqPrecacheId(pDudeInfo->seqStartID+6, palette); seqPrecacheId(pDudeInfo->seqStartID + 6, palette);
seqPrecacheId(pDudeInfo->seqStartID+7, palette); seqPrecacheId(pDudeInfo->seqStartID + 7, palette);
seqPrecacheId(pDudeInfo->seqStartID+8, palette); seqPrecacheId(pDudeInfo->seqStartID + 8, palette);
seqPrecacheId(pDudeInfo->seqStartID+9, palette); seqPrecacheId(pDudeInfo->seqStartID + 9, palette);
seqPrecacheId(pDudeInfo->seqStartID+10, palette); seqPrecacheId(pDudeInfo->seqStartID + 10, palette);
seqPrecacheId(pDudeInfo->seqStartID+11, palette); seqPrecacheId(pDudeInfo->seqStartID + 11, palette);
break; break;
case kDudeGargoyleStatueFlesh: case kDudeGargoyleStatueFlesh:
case kDudeGargoyleStatueStone: case kDudeGargoyleStatueStone:
seqPrecacheId(pDudeInfo->seqStartID+6, palette); seqPrecacheId(pDudeInfo->seqStartID + 6, palette);
seqPrecacheId(pDudeInfo->seqStartID+6, palette); //??? seqPrecacheId(pDudeInfo->seqStartID + 6, palette); //???
[[fallthrough]]; [[fallthrough]];
case kDudeGargoyleFlesh: case kDudeGargoyleFlesh:
case kDudeGargoyleStone: case kDudeGargoyleStone:
seqPrecacheId(pDudeInfo->seqStartID+6, palette); seqPrecacheId(pDudeInfo->seqStartID + 6, palette);
seqPrecacheId(pDudeInfo->seqStartID+7, palette); seqPrecacheId(pDudeInfo->seqStartID + 7, palette);
seqPrecacheId(pDudeInfo->seqStartID+8, palette); seqPrecacheId(pDudeInfo->seqStartID + 8, palette);
seqPrecacheId(pDudeInfo->seqStartID+9, palette); seqPrecacheId(pDudeInfo->seqStartID + 9, palette);
break; break;
case kDudePhantasm: case kDudePhantasm:
case kDudeHellHound: case kDudeHellHound:
case kDudeSpiderBrown: case kDudeSpiderBrown:
case kDudeSpiderRed: case kDudeSpiderRed:
case kDudeSpiderBlack: case kDudeSpiderBlack:
case kDudeSpiderMother: case kDudeSpiderMother:
case kDudeTchernobog: case kDudeTchernobog:
seqPrecacheId(pDudeInfo->seqStartID+6, palette); seqPrecacheId(pDudeInfo->seqStartID + 6, palette);
seqPrecacheId(pDudeInfo->seqStartID+7, palette); seqPrecacheId(pDudeInfo->seqStartID + 7, palette);
seqPrecacheId(pDudeInfo->seqStartID+8, palette); seqPrecacheId(pDudeInfo->seqStartID + 8, palette);
break; break;
case kDudeCerberusTwoHead: case kDudeCerberusTwoHead:
seqPrecacheId(pDudeInfo->seqStartID+6, palette); seqPrecacheId(pDudeInfo->seqStartID + 6, palette);
seqPrecacheId(pDudeInfo->seqStartID+7, palette); seqPrecacheId(pDudeInfo->seqStartID + 7, palette);
[[fallthrough]]; [[fallthrough]];
case kDudeHand: case kDudeHand:
case kDudeBoneEel: case kDudeBoneEel:
case kDudeBat: case kDudeBat:
case kDudeRat: case kDudeRat:
seqPrecacheId(pDudeInfo->seqStartID+6, palette); seqPrecacheId(pDudeInfo->seqStartID + 6, palette);
seqPrecacheId(pDudeInfo->seqStartID+7, palette); seqPrecacheId(pDudeInfo->seqStartID + 7, palette);
break; break;
case kDudeCultistBeast: case kDudeCultistBeast:
seqPrecacheId(pDudeInfo->seqStartID+6, palette); seqPrecacheId(pDudeInfo->seqStartID + 6, palette);
break; break;
case kDudeZombieAxeBuried: case kDudeZombieAxeBuried:
seqPrecacheId(pDudeInfo->seqStartID+12, palette); seqPrecacheId(pDudeInfo->seqStartID + 12, palette);
seqPrecacheId(pDudeInfo->seqStartID+9, palette); seqPrecacheId(pDudeInfo->seqStartID + 9, palette);
[[fallthrough]]; [[fallthrough]];
case kDudeZombieAxeLaying: case kDudeZombieAxeLaying:
seqPrecacheId(pDudeInfo->seqStartID+10, palette); seqPrecacheId(pDudeInfo->seqStartID + 10, palette);
[[fallthrough]]; [[fallthrough]];
case kDudeZombieAxeNormal: case kDudeZombieAxeNormal:
seqPrecacheId(pDudeInfo->seqStartID+6, palette); seqPrecacheId(pDudeInfo->seqStartID + 6, palette);
seqPrecacheId(pDudeInfo->seqStartID+7, palette); seqPrecacheId(pDudeInfo->seqStartID + 7, palette);
seqPrecacheId(pDudeInfo->seqStartID+8, palette); seqPrecacheId(pDudeInfo->seqStartID + 8, palette);
seqPrecacheId(pDudeInfo->seqStartID+11, palette); seqPrecacheId(pDudeInfo->seqStartID + 11, palette);
seqPrecacheId(pDudeInfo->seqStartID+13, palette); seqPrecacheId(pDudeInfo->seqStartID + 13, palette);
seqPrecacheId(pDudeInfo->seqStartID+14, palette); seqPrecacheId(pDudeInfo->seqStartID + 14, palette);
break; break;
} }
} }
void PrecacheThing(DBloodActor* actor) //---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void PrecacheThing(DBloodActor* actor)
{ {
int palette = actor->spr.pal; int palette = actor->spr.pal;
switch (actor->spr.type) { switch (actor->spr.type) {
case kThingGlassWindow: // worthless... case kThingGlassWindow: // worthless...
case kThingFluorescent: case kThingFluorescent:
seqPrecacheId(12, palette); seqPrecacheId(12, palette);
break; break;
case kThingSpiderWeb: case kThingSpiderWeb:
seqPrecacheId(15, palette); seqPrecacheId(15, palette);
break; break;
case kThingMetalGrate: case kThingMetalGrate:
seqPrecacheId(21, palette); seqPrecacheId(21, palette);
break; break;
case kThingFlammableTree: case kThingFlammableTree:
seqPrecacheId(25, palette); seqPrecacheId(25, palette);
seqPrecacheId(26, palette); seqPrecacheId(26, palette);
break; break;
case kTrapMachinegun: case kTrapMachinegun:
seqPrecacheId(38, palette); seqPrecacheId(38, palette);
seqPrecacheId(40, palette); seqPrecacheId(40, palette);
seqPrecacheId(28, palette); seqPrecacheId(28, palette);
break; break;
case kThingObjectGib: case kThingObjectGib:
//case kThingObjectExplode: weird that only gib object is precached and this one is not //case kThingObjectExplode: weird that only gib object is precached and this one is not
break; break;
} }
tilePrecacheTile(actor->spr.picnum, -1, palette); tilePrecacheTile(actor->spr.picnum, -1, palette);
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void PreloadCache() void PreloadCache()
{ {
if (!r_precache) return; if (!r_precache) return;
int skyTile = -1; int skyTile = -1;
// Fonts // Fonts
for(auto& sect: sector) for (auto& sect : sector)
{ {
tilePrecacheTile(sect.floorpicnum, 0, sect.floorpal); tilePrecacheTile(sect.floorpicnum, 0, sect.floorpal);
tilePrecacheTile(sect.ceilingpicnum, 0, sect.ceilingpal); tilePrecacheTile(sect.ceilingpicnum, 0, sect.ceilingpal);
if ((sect.ceilingstat & CSTAT_SECTOR_SKY) != 0 && skyTile == -1) if ((sect.ceilingstat & CSTAT_SECTOR_SKY) != 0 && skyTile == -1)
skyTile = sect.ceilingpicnum; skyTile = sect.ceilingpicnum;
} }
for(auto& wal : wall) for (auto& wal : wall)
{ {
tilePrecacheTile(wal.picnum, 0, wal.pal); tilePrecacheTile(wal.picnum, 0, wal.pal);
if (wal.overpicnum >= 0) if (wal.overpicnum >= 0)
tilePrecacheTile(wal.overpicnum, 0, wal.pal); tilePrecacheTile(wal.overpicnum, 0, wal.pal);
} }
BloodSpriteIterator it; BloodSpriteIterator it;
while (auto actor = it.Next()) while (auto actor = it.Next())
{ {
switch (actor->spr.statnum) switch (actor->spr.statnum)
{ {
case kStatDude: case kStatDude:
PrecacheDude(actor); PrecacheDude(actor);
break; break;
case kStatThing: case kStatThing:
PrecacheThing(actor); PrecacheThing(actor);
break; break;
default: default:
tilePrecacheTile(actor->spr.picnum, -1, actor->spr.pal); tilePrecacheTile(actor->spr.picnum, -1, actor->spr.pal);
break; break;
} }
} }
// Precache common SEQs // Precache common SEQs
for (int i = 0; i < 100; i++) for (int i = 0; i < 100; i++)
{ {
seqPrecacheId(i, 0); seqPrecacheId(i, 0);
} }
tilePrecacheTile(1147, -1, 0); // water drip tilePrecacheTile(1147, -1, 0); // water drip
tilePrecacheTile(1160, -1, 0); // blood drip tilePrecacheTile(1160, -1, 0); // blood drip
// Player SEQs // Player SEQs
seqPrecacheId(dudeInfo[31].seqStartID+6, 0); seqPrecacheId(dudeInfo[31].seqStartID + 6, 0);
seqPrecacheId(dudeInfo[31].seqStartID+7, 0); seqPrecacheId(dudeInfo[31].seqStartID + 7, 0);
seqPrecacheId(dudeInfo[31].seqStartID+8, 0); seqPrecacheId(dudeInfo[31].seqStartID + 8, 0);
seqPrecacheId(dudeInfo[31].seqStartID+9, 0); seqPrecacheId(dudeInfo[31].seqStartID + 9, 0);
seqPrecacheId(dudeInfo[31].seqStartID+10, 0); seqPrecacheId(dudeInfo[31].seqStartID + 10, 0);
seqPrecacheId(dudeInfo[31].seqStartID+14, 0); seqPrecacheId(dudeInfo[31].seqStartID + 14, 0);
seqPrecacheId(dudeInfo[31].seqStartID+15, 0); seqPrecacheId(dudeInfo[31].seqStartID + 15, 0);
seqPrecacheId(dudeInfo[31].seqStartID+12, 0); seqPrecacheId(dudeInfo[31].seqStartID + 12, 0);
seqPrecacheId(dudeInfo[31].seqStartID+16, 0); seqPrecacheId(dudeInfo[31].seqStartID + 16, 0);
seqPrecacheId(dudeInfo[31].seqStartID+17, 0); seqPrecacheId(dudeInfo[31].seqStartID + 17, 0);
seqPrecacheId(dudeInfo[31].seqStartID+18, 0); seqPrecacheId(dudeInfo[31].seqStartID + 18, 0);
if (skyTile > -1 && skyTile < kMaxTiles) if (skyTile > -1 && skyTile < kMaxTiles)
{ {
for (int i = 1; i < gSkyCount; i++) for (int i = 1; i < gSkyCount; i++)
tilePrecacheTile(skyTile+i, 0, 0); tilePrecacheTile(skyTile + i, 0, 0);
} }
WeaponPrecache(); WeaponPrecache();
viewPrecacheTiles(); viewPrecacheTiles();
fxPrecache(); fxPrecache();
gibPrecache(); gibPrecache();
I_GetEvent(); I_GetEvent();
precacheMarkedTiles(); precacheMarkedTiles();
} }
END_BLD_NS END_BLD_NS

View file

@ -30,7 +30,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
extern void (*qavClientCallback[])(int, void *); extern void (*qavClientCallback[])(int, void*);
//========================================================================== //==========================================================================
@ -39,20 +39,20 @@ extern void (*qavClientCallback[])(int, void *);
// //
//========================================================================== //==========================================================================
using QAVPrevTileFinder = TILE_FRAME* (*)(FRAMEINFO* const thisFrame, FRAMEINFO* const prevFrame, const int i); using QAVPrevTileFinder = TILE_FRAME * (*)(FRAMEINFO* const thisFrame, FRAMEINFO* const prevFrame, const int i);
struct QAVInterpProps struct QAVInterpProps
{ {
QAVPrevTileFinder PrevTileFinder; QAVPrevTileFinder PrevTileFinder;
bool loopable; bool loopable;
TMap<int, TArray<int>> IgnoreData; TMap<int, TArray<int>> IgnoreData;
bool CanInterpFrameTile(const int nFrame, const int i) bool CanInterpFrameTile(const int nFrame, const int i)
{ {
// Check whether the current frame's tile is skippable. // Check whether the current frame's tile is skippable.
auto thisFrame = IgnoreData.CheckKey(nFrame); auto thisFrame = IgnoreData.CheckKey(nFrame);
return thisFrame ? !thisFrame->Contains(i) : true; return thisFrame ? !thisFrame->Contains(i) : true;
} }
}; };
static TMap<FString, QAVPrevTileFinder> qavPrevTileFinders; static TMap<FString, QAVPrevTileFinder> qavPrevTileFinders;
@ -60,66 +60,78 @@ static TMap<int, QAVInterpProps> qavInterpProps;
static void qavInitTileFinderMap() static void qavInitTileFinderMap()
{ {
// Interpolate between frames if the picnums match. This is safest but could miss interpolations between suitable picnums. // Interpolate between frames if the picnums match. This is safest but could miss interpolations between suitable picnums.
qavPrevTileFinders.Insert("picnum", [](FRAMEINFO* const thisFrame, FRAMEINFO* const prevFrame, const int i) -> TILE_FRAME* { qavPrevTileFinders.Insert("picnum", [](FRAMEINFO* const thisFrame, FRAMEINFO* const prevFrame, const int i) -> TILE_FRAME* {
return prevFrame->tiles[i].picnum == thisFrame->tiles[i].picnum ? &prevFrame->tiles[i] : nullptr; return prevFrame->tiles[i].picnum == thisFrame->tiles[i].picnum ? &prevFrame->tiles[i] : nullptr;
}); });
// Interpolate between frames if the picnum is valid. This can be problematic if tile indices change between frames. // Interpolate between frames if the picnum is valid. This can be problematic if tile indices change between frames.
qavPrevTileFinders.Insert("index", [](FRAMEINFO* const thisFrame, FRAMEINFO* const prevFrame, const int i) -> TILE_FRAME* { qavPrevTileFinders.Insert("index", [](FRAMEINFO* const thisFrame, FRAMEINFO* const prevFrame, const int i) -> TILE_FRAME* {
return prevFrame->tiles[i].picnum > 0 ? &prevFrame->tiles[i] : nullptr; return prevFrame->tiles[i].picnum > 0 ? &prevFrame->tiles[i] : nullptr;
}); });
// Find previous frame by iterating all previous frame's tiles and return on first matched x coordinate. // Find previous frame by iterating all previous frame's tiles and return on first matched x coordinate.
qavPrevTileFinders.Insert("x", [](FRAMEINFO* const thisFrame, FRAMEINFO* const prevFrame, const int i) -> TILE_FRAME* { qavPrevTileFinders.Insert("x", [](FRAMEINFO* const thisFrame, FRAMEINFO* const prevFrame, const int i) -> TILE_FRAME* {
for (int j = 0; j < 8; j++) if (thisFrame->tiles[i].x == prevFrame->tiles[j].x) for (int j = 0; j < 8; j++) if (thisFrame->tiles[i].x == prevFrame->tiles[j].x)
{ {
return &prevFrame->tiles[j]; return &prevFrame->tiles[j];
} }
return nullptr; return nullptr;
}); });
// Find previous frame by iterating all previous frame's tiles and return on first matched y coordinate. // Find previous frame by iterating all previous frame's tiles and return on first matched y coordinate.
qavPrevTileFinders.Insert("y", [](FRAMEINFO* const thisFrame, FRAMEINFO* const prevFrame, const int i) -> TILE_FRAME* { qavPrevTileFinders.Insert("y", [](FRAMEINFO* const thisFrame, FRAMEINFO* const prevFrame, const int i) -> TILE_FRAME* {
for (int j = 0; j < 8; j++) if (thisFrame->tiles[i].y == prevFrame->tiles[j].y) for (int j = 0; j < 8; j++) if (thisFrame->tiles[i].y == prevFrame->tiles[j].y)
{ {
return &prevFrame->tiles[j]; return &prevFrame->tiles[j];
} }
return nullptr; return nullptr;
}); });
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static QAVPrevTileFinder qavGetInterpType(const FString& type) static QAVPrevTileFinder qavGetInterpType(const FString& type)
{ {
if (!qavPrevTileFinders.CountUsed()) qavInitTileFinderMap(); if (!qavPrevTileFinders.CountUsed()) qavInitTileFinderMap();
return *qavPrevTileFinders.CheckKey(type); return *qavPrevTileFinders.CheckKey(type);
} }
bool GameInterface::IsQAVInterpTypeValid(const FString& type) bool GameInterface::IsQAVInterpTypeValid(const FString& type)
{ {
return qavGetInterpType(type) != nullptr; return qavGetInterpType(type) != nullptr;
} }
void GameInterface::AddQAVInterpProps(const int res_id, const FString& interptype, const bool loopable, const TMap<int, TArray<int>>&& ignoredata) void GameInterface::AddQAVInterpProps(const int res_id, const FString& interptype, const bool loopable, const TMap<int, TArray<int>>&& ignoredata)
{ {
qavInterpProps.Insert(res_id, { qavGetInterpType(interptype), loopable, std::move(ignoredata) }); qavInterpProps.Insert(res_id, { qavGetInterpType(interptype), loopable, std::move(ignoredata) });
} }
void GameInterface::RemoveQAVInterpProps(const int res_id) void GameInterface::RemoveQAVInterpProps(const int res_id)
{ {
qavInterpProps.Remove(res_id); qavInterpProps.Remove(res_id);
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void DrawFrame(double x, double y, double z, double a, double alpha, int picnum, int stat, int shade, int palnum, bool to3dview) void DrawFrame(double x, double y, double z, double a, double alpha, int picnum, int stat, int shade, int palnum, bool to3dview)
{ {
if (!to3dview) if (!to3dview)
{ {
auto tex = tileGetTexture(picnum); auto tex = tileGetTexture(picnum);
double scale = z * (1. / 65536.); double scale = z * (1. / 65536.);
double angle = a * BAngToDegree; double angle = a * BAngToDegree;
int renderstyle = (stat & RS_NOMASK)? STYLE_Normal : STYLE_Translucent; int renderstyle = (stat & RS_NOMASK) ? STYLE_Normal : STYLE_Translucent;
int pin = (stat & kQavOrientationLeft)? -1 : (stat & RS_ALIGN_R)? 1:0; int pin = (stat & kQavOrientationLeft) ? -1 : (stat & RS_ALIGN_R) ? 1 : 0;
auto translation = TRANSLATION(Translation_Remap, palnum); auto translation = TRANSLATION(Translation_Remap, palnum);
bool topleft = !!(stat & RS_TOPLEFT); bool topleft = !!(stat & RS_TOPLEFT);
@ -128,258 +140,294 @@ void DrawFrame(double x, double y, double z, double a, double alpha, int picnum,
auto color = shadeToLight(shade); auto color = shadeToLight(shade);
DrawTexture(twod, tex, x, y, DTA_ScaleX, scale, DTA_ScaleY, scale, DTA_Rotate, angle, DTA_LegacyRenderStyle, renderstyle, DTA_Alpha, alpha, DTA_Pin, pin, DTA_TranslationIndex, translation, DrawTexture(twod, tex, x, y, DTA_ScaleX, scale, DTA_ScaleY, scale, DTA_Rotate, angle, DTA_LegacyRenderStyle, renderstyle, DTA_Alpha, alpha, DTA_Pin, pin, DTA_TranslationIndex, translation,
DTA_TopLeft, topleft, DTA_CenterOffsetRel, topleft? 0:2, DTA_FullscreenScale, FSMode_Fit320x200, DTA_FlipOffsets, true, DTA_Color, color, DTA_TopLeft, topleft, DTA_CenterOffsetRel, topleft ? 0 : 2, DTA_FullscreenScale, FSMode_Fit320x200, DTA_FlipOffsets, true, DTA_Color, color,
DTA_FlipX, xflip, DTA_FlipY, yflip, TAG_DONE); DTA_FlipX, xflip, DTA_FlipY, yflip, TAG_DONE);
} }
else else
{ {
// there's some disagreements about flag values between QAV and the drawer. Shuffle these around. // there's some disagreements about flag values between QAV and the drawer. Shuffle these around.
if (stat & RS_YFLIP) stat |= RS_YFLIPHUD; if (stat & RS_YFLIP) stat |= RS_YFLIPHUD;
stat &= ~RS_YFLIP; stat &= ~RS_YFLIP;
if (stat & 0x100) stat |= RS_XFLIPHUD; if (stat & 0x100) stat |= RS_XFLIPHUD;
stat &= ~0x100; stat &= ~0x100;
if ((stat & kQavOrientationLeft)) stat |= RS_ALIGN_L; if ((stat & kQavOrientationLeft)) stat |= RS_ALIGN_L;
stat &= ~kQavOrientationLeft; stat &= ~kQavOrientationLeft;
hud_drawsprite(x, y, z, a, picnum, shade, palnum, stat, alpha); hud_drawsprite(x, y, z, a, picnum, shade, palnum, stat, alpha);
} }
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void QAV::Draw(double x, double y, int ticks, int stat, int shade, int palnum, bool to3dview, double const smoothratio) void QAV::Draw(double x, double y, int ticks, int stat, int shade, int palnum, bool to3dview, double const smoothratio)
{ {
assert(ticksPerFrame > 0); assert(ticksPerFrame > 0);
auto const interpdata = qavInterpProps.CheckKey(res_id); auto const interpdata = qavInterpProps.CheckKey(res_id);
auto const nFrame = clamp(ticks / ticksPerFrame, 0, nFrames - 1); auto const nFrame = clamp(ticks / ticksPerFrame, 0, nFrames - 1);
FRAMEINFO* const thisFrame = &frames[nFrame]; FRAMEINFO* const thisFrame = &frames[nFrame];
auto const oFrame = clamp((nFrame == 0 && interpdata && interpdata->loopable ? nFrames : nFrame) - 1, 0, nFrames - 1); auto const oFrame = clamp((nFrame == 0 && interpdata && interpdata->loopable ? nFrames : nFrame) - 1, 0, nFrames - 1);
FRAMEINFO* const prevFrame = &frames[oFrame]; FRAMEINFO* const prevFrame = &frames[oFrame];
bool const interpolate = interpdata && cl_hudinterpolation && cl_bloodqavinterp && (nFrames > 1) && (nFrame != oFrame) && (smoothratio != MaxSmoothRatio); bool const interpolate = interpdata && cl_hudinterpolation && cl_bloodqavinterp && (nFrames > 1) && (nFrame != oFrame) && (smoothratio != MaxSmoothRatio);
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
if (thisFrame->tiles[i].picnum > 0) if (thisFrame->tiles[i].picnum > 0)
{ {
TILE_FRAME* const thisTile = &thisFrame->tiles[i]; TILE_FRAME* const thisTile = &thisFrame->tiles[i];
TILE_FRAME* const prevTile = interpolate && interpdata->CanInterpFrameTile(nFrame, i) ? interpdata->PrevTileFinder(thisFrame, prevFrame, i) : nullptr; TILE_FRAME* const prevTile = interpolate && interpdata->CanInterpFrameTile(nFrame, i) ? interpdata->PrevTileFinder(thisFrame, prevFrame, i) : nullptr;
double tileX = x; double tileX = x;
double tileY = y; double tileY = y;
double tileZ; double tileZ;
double tileA; double tileA;
double tileAlpha; double tileAlpha;
int tileShade; int tileShade;
auto const tileStat = stat | thisTile->stat; auto const tileStat = stat | thisTile->stat;
if (prevTile) if (prevTile)
{ {
tileX += interpolatedvaluef(prevTile->x, thisTile->x, smoothratio); tileX += interpolatedvaluef(prevTile->x, thisTile->x, smoothratio);
tileY += interpolatedvaluef(prevTile->y, thisTile->y, smoothratio); tileY += interpolatedvaluef(prevTile->y, thisTile->y, smoothratio);
tileZ = interpolatedvaluef(prevTile->z, thisTile->z, smoothratio); tileZ = interpolatedvaluef(prevTile->z, thisTile->z, smoothratio);
tileA = interpolatedangle(buildang(prevTile->angle), buildang(thisTile->angle), smoothratio).asbuildf(); tileA = interpolatedangle(buildang(prevTile->angle), buildang(thisTile->angle), smoothratio).asbuildf();
tileShade = interpolatedvalue(prevTile->shade, thisTile->shade, smoothratio) + shade; tileShade = interpolatedvalue(prevTile->shade, thisTile->shade, smoothratio) + shade;
auto prevAlpha = ((stat | prevTile->stat) & RS_TRANS1) ? glblend[0].def[!!((stat | prevTile->stat) & RS_TRANS2)].alpha : 1.; auto prevAlpha = ((stat | prevTile->stat) & RS_TRANS1) ? glblend[0].def[!!((stat | prevTile->stat) & RS_TRANS2)].alpha : 1.;
auto thisAlpha = (tileStat & RS_TRANS1) ? glblend[0].def[!!(tileStat & RS_TRANS2)].alpha : 1.; auto thisAlpha = (tileStat & RS_TRANS1) ? glblend[0].def[!!(tileStat & RS_TRANS2)].alpha : 1.;
tileAlpha = interpolatedvaluef(prevAlpha, thisAlpha, smoothratio); tileAlpha = interpolatedvaluef(prevAlpha, thisAlpha, smoothratio);
} }
else else
{ {
tileX += thisTile->x; tileX += thisTile->x;
tileY += thisTile->y; tileY += thisTile->y;
tileZ = thisTile->z; tileZ = thisTile->z;
tileA = thisTile->angle; tileA = thisTile->angle;
tileShade = thisTile->shade + shade; tileShade = thisTile->shade + shade;
tileAlpha = (tileStat & RS_TRANS1) ? glblend[0].def[!!(tileStat & RS_TRANS2)].alpha : 1.; tileAlpha = (tileStat & RS_TRANS1) ? glblend[0].def[!!(tileStat & RS_TRANS2)].alpha : 1.;
} }
DrawFrame(tileX, tileY, tileZ, tileA, tileAlpha, thisTile->picnum, tileStat, tileShade, (palnum <= 0 ? thisTile->palnum : palnum), to3dview); DrawFrame(tileX, tileY, tileZ, tileA, tileAlpha, thisTile->picnum, tileStat, tileShade, (palnum <= 0 ? thisTile->palnum : palnum), to3dview);
} }
} }
} }
void QAV::Play(int start, int end, int nCallback, PLAYER *pData) //---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void QAV::Play(int start, int end, int nCallback, PLAYER* pData)
{ {
auto pActor = pData ? pData->actor : nullptr; auto pActor = pData ? pData->actor : nullptr;
assert(ticksPerFrame > 0); assert(ticksPerFrame > 0);
int frame; int frame;
int ticks; int ticks;
if (start < 0) if (start < 0)
frame = (start + 1) / ticksPerFrame; frame = (start + 1) / ticksPerFrame;
else else
frame = start / ticksPerFrame + 1; frame = start / ticksPerFrame + 1;
for (ticks = ticksPerFrame * frame; ticks <= end; frame++, ticks += ticksPerFrame)
{
if (frame >= 0 && frame < nFrames)
{
FRAMEINFO *pFrame = &frames[frame];
SOUNDINFO *pSound = &pFrame->sound;
// by NoOne: handle Sound kill flags
if (!VanillaMode() && pSound->sndFlags > 0 && pSound->sndFlags <= kFlagSoundKillAll) {
for (int i = 0; i < nFrames; i++) {
FRAMEINFO* pFrame2 = &frames[i];
SOUNDINFO* pSound2 = &pFrame2->sound;
if (pSound2->sound != 0) {
if (pSound->sndFlags != kFlagSoundKillAll && pSound2->priority != pSound->priority) continue;
else if (pActor) {
// We need stop all sounds in a range
for (int a = 0; a <= pSound2->sndRange; a++)
sfxKill3DSound(pActor, -1, pSound2->sound + a);
} else {
sndKillAllSounds();
}
}
}
}
if (pSound->sound > 0) { for (ticks = ticksPerFrame * frame; ticks <= end; frame++, ticks += ticksPerFrame)
int sound = pSound->sound; {
if (frame >= 0 && frame < nFrames)
// by NoOne: add random rage sound feature {
if (pSound->sndRange > 0 && !VanillaMode()) FRAMEINFO* pFrame = &frames[frame];
sound += Random((pSound->sndRange == 1) ? 2 : pSound->sndRange); SOUNDINFO* pSound = &pFrame->sound;
if (pActor == nullptr) sndStartSample(sound, -1, -1, 0); // by NoOne: handle Sound kill flags
else sfxPlay3DSound(pActor, sound, 16+pSound->priority, 6); if (!VanillaMode() && pSound->sndFlags > 0 && pSound->sndFlags <= kFlagSoundKillAll) {
} for (int i = 0; i < nFrames; i++) {
FRAMEINFO* pFrame2 = &frames[i];
if (pFrame->nCallbackId > 0 && nCallback != -1) { SOUNDINFO* pSound2 = &pFrame2->sound;
qavClientCallback[nCallback](pFrame->nCallbackId, pData); if (pSound2->sound != 0) {
} if (pSound->sndFlags != kFlagSoundKillAll && pSound2->priority != pSound->priority) continue;
} else if (pActor) {
} // We need stop all sounds in a range
for (int a = 0; a <= pSound2->sndRange; a++)
sfxKill3DSound(pActor, -1, pSound2->sound + a);
}
else {
sndKillAllSounds();
}
}
}
}
if (pSound->sound > 0) {
int sound = pSound->sound;
// by NoOne: add random rage sound feature
if (pSound->sndRange > 0 && !VanillaMode())
sound += Random((pSound->sndRange == 1) ? 2 : pSound->sndRange);
if (pActor == nullptr) sndStartSample(sound, -1, -1, 0);
else sfxPlay3DSound(pActor, sound, 16 + pSound->priority, 6);
}
if (pFrame->nCallbackId > 0 && nCallback != -1) {
qavClientCallback[nCallback](pFrame->nCallbackId, pData);
}
}
}
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void QAV::Precache(int palette) void QAV::Precache(int palette)
{ {
for (int i = 0; i < nFrames; i++) for (int i = 0; i < nFrames; i++)
{ {
for (int j = 0; j < 8; j++) for (int j = 0; j < 8; j++)
{ {
if (frames[i].tiles[j].picnum >= 0) if (frames[i].tiles[j].picnum >= 0)
tilePrecacheTile(frames[i].tiles[j].picnum, 0, palette); tilePrecacheTile(frames[i].tiles[j].picnum, 0, palette);
} }
} }
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void qavProcessTicker(QAV* const pQAV, int* duration, int* lastTick) void qavProcessTicker(QAV* const pQAV, int* duration, int* lastTick)
{ {
if (*duration > 0) if (*duration > 0)
{ {
auto thisTick = I_GetTime(pQAV->ticrate); auto thisTick = I_GetTime(pQAV->ticrate);
auto numTicks = thisTick - (*lastTick); auto numTicks = thisTick - (*lastTick);
if (numTicks) if (numTicks)
{ {
*lastTick = thisTick; *lastTick = thisTick;
*duration -= pQAV->ticksPerFrame * numTicks; *duration -= pQAV->ticksPerFrame * numTicks;
} }
} }
*duration = ClipLow(*duration, 0); *duration = ClipLow(*duration, 0);
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void qavProcessTimer(PLAYER* const pPlayer, QAV* const pQAV, int* duration, double* smoothratio, bool const fixedduration, bool const ignoreWeaponTimer) void qavProcessTimer(PLAYER* const pPlayer, QAV* const pQAV, int* duration, double* smoothratio, bool const fixedduration, bool const ignoreWeaponTimer)
{ {
// Process if not paused. // Process if not paused.
if (!paused) if (!paused)
{ {
// Process clock based on QAV's ticrate and last tick value. // Process clock based on QAV's ticrate and last tick value.
qavProcessTicker(pQAV, &pPlayer->qavTimer, &pPlayer->qavLastTick); qavProcessTicker(pQAV, &pPlayer->qavTimer, &pPlayer->qavLastTick);
if (pPlayer->weaponTimer == 0 && pPlayer->qavTimer == 0 && !ignoreWeaponTimer) if (pPlayer->weaponTimer == 0 && pPlayer->qavTimer == 0 && !ignoreWeaponTimer)
{ {
// Check if we're playing an idle QAV as per the ticker's weapon timer. // Check if we're playing an idle QAV as per the ticker's weapon timer.
*duration = fixedduration ? pQAV->duration - 1 : I_GetBuildTime() % pQAV->duration; *duration = fixedduration ? pQAV->duration - 1 : I_GetBuildTime() % pQAV->duration;
*smoothratio = MaxSmoothRatio; *smoothratio = MaxSmoothRatio;
} }
else if (pPlayer->qavTimer == 0) else if (pPlayer->qavTimer == 0)
{ {
// If qavTimer is 0, play the last frame uninterpolated. Sometimes the timer can be just ahead of weaponTimer. // If qavTimer is 0, play the last frame uninterpolated. Sometimes the timer can be just ahead of weaponTimer.
*duration = pQAV->duration - 1; *duration = pQAV->duration - 1;
*smoothratio = MaxSmoothRatio; *smoothratio = MaxSmoothRatio;
} }
else else
{ {
// Apply normal values. // Apply normal values.
*duration = pQAV->duration - pPlayer->qavTimer; *duration = pQAV->duration - pPlayer->qavTimer;
*smoothratio = !cl_interpolate || cl_capfps ? MaxSmoothRatio : I_GetTimeFrac(pQAV->ticrate) * MaxSmoothRatio; *smoothratio = !cl_interpolate || cl_capfps ? MaxSmoothRatio : I_GetTimeFrac(pQAV->ticrate) * MaxSmoothRatio;
} }
} }
else else
{ {
*smoothratio = MaxSmoothRatio; *smoothratio = MaxSmoothRatio;
} }
} }
//---------------------------------------------------------------------------
//
// This is to eliminate a huge design issue in NBlood that was apparently copied verbatim from the DOS-Version. // This is to eliminate a huge design issue in NBlood that was apparently copied verbatim from the DOS-Version.
// Sequences were cached in the resource and directly returned from there in writable form, with byte swapping directly performed in the cache on Big Endian systems. // Sequences were cached in the resource and directly returned from there in writable form, with byte swapping directly performed in the cache on Big Endian systems.
// To avoid such unsafe operations this caches the read data separately. // To avoid such unsafe operations this caches the read data separately.
//
//---------------------------------------------------------------------------
extern FMemArena seqcache; // Use the same storage as the SEQs. extern FMemArena seqcache; // Use the same storage as the SEQs.
static TMap<int, QAV*> qavcache; static TMap<int, QAV*> qavcache;
QAV* getQAV(int res_id) QAV* getQAV(int res_id)
{ {
auto p = qavcache.CheckKey(res_id); auto p = qavcache.CheckKey(res_id);
if (p != nullptr) return *p; if (p != nullptr) return *p;
int index = fileSystem.FindResource(res_id, "QAV"); int index = fileSystem.FindResource(res_id, "QAV");
if (index < 0) if (index < 0)
{ {
return nullptr; return nullptr;
} }
auto fr = fileSystem.OpenFileReader(index); auto fr = fileSystem.OpenFileReader(index);
// Start reading QAV for nFrames, skipping padded data. // Start reading QAV for nFrames, skipping padded data.
for (int i = 0; i < 8; i++) fr.ReadUInt8(); for (int i = 0; i < 8; i++) fr.ReadUInt8();
int nFrames = fr.ReadInt32(); int nFrames = fr.ReadInt32();
auto qavdata = (QAV*)seqcache.Alloc(sizeof(QAV) + ((nFrames - 1) * sizeof(FRAMEINFO))); auto qavdata = (QAV*)seqcache.Alloc(sizeof(QAV) + ((nFrames - 1) * sizeof(FRAMEINFO)));
// Write out QAV data. // Write out QAV data.
qavdata->nFrames = nFrames; qavdata->nFrames = nFrames;
qavdata->ticksPerFrame = fr.ReadInt32(); qavdata->ticksPerFrame = fr.ReadInt32();
qavdata->duration = fr.ReadInt32(); qavdata->duration = fr.ReadInt32();
qavdata->x = fr.ReadInt32(); qavdata->x = fr.ReadInt32();
qavdata->y = fr.ReadInt32(); qavdata->y = fr.ReadInt32();
/*qavdata->nSprite =*/ fr.ReadInt32(); /*qavdata->nSprite =*/ fr.ReadInt32();
for (int i = 0; i < 4; i++) fr.ReadUInt8(); for (int i = 0; i < 4; i++) fr.ReadUInt8();
// Read FRAMEINFO data. // Read FRAMEINFO data.
for (int i = 0; i < qavdata->nFrames; i++) for (int i = 0; i < qavdata->nFrames; i++)
{ {
qavdata->frames[i].nCallbackId = fr.ReadInt32(); qavdata->frames[i].nCallbackId = fr.ReadInt32();
// Read SOUNDINFO data. // Read SOUNDINFO data.
qavdata->frames[i].sound.sound = fr.ReadInt32(); qavdata->frames[i].sound.sound = fr.ReadInt32();
qavdata->frames[i].sound.priority = fr.ReadUInt8(); qavdata->frames[i].sound.priority = fr.ReadUInt8();
qavdata->frames[i].sound.sndFlags = fr.ReadUInt8(); qavdata->frames[i].sound.sndFlags = fr.ReadUInt8();
qavdata->frames[i].sound.sndRange = fr.ReadUInt8(); qavdata->frames[i].sound.sndRange = fr.ReadUInt8();
for (int j = 0; j < 1; j++) fr.ReadUInt8(); for (int j = 0; j < 1; j++) fr.ReadUInt8();
// Read TILE_FRAME data. // Read TILE_FRAME data.
for (int j = 0; j < 8; j++) for (int j = 0; j < 8; j++)
{ {
qavdata->frames[i].tiles[j].picnum = fr.ReadInt32(); qavdata->frames[i].tiles[j].picnum = fr.ReadInt32();
qavdata->frames[i].tiles[j].x = fr.ReadInt32(); qavdata->frames[i].tiles[j].x = fr.ReadInt32();
qavdata->frames[i].tiles[j].y = fr.ReadInt32(); qavdata->frames[i].tiles[j].y = fr.ReadInt32();
qavdata->frames[i].tiles[j].z = fr.ReadInt32(); qavdata->frames[i].tiles[j].z = fr.ReadInt32();
qavdata->frames[i].tiles[j].stat = fr.ReadInt32(); qavdata->frames[i].tiles[j].stat = fr.ReadInt32();
qavdata->frames[i].tiles[j].shade = fr.ReadInt8(); qavdata->frames[i].tiles[j].shade = fr.ReadInt8();
qavdata->frames[i].tiles[j].palnum = fr.ReadUInt8(); qavdata->frames[i].tiles[j].palnum = fr.ReadUInt8();
qavdata->frames[i].tiles[j].angle = fr.ReadUInt16(); qavdata->frames[i].tiles[j].angle = fr.ReadUInt16();
} }
} }
// Write out additions. // Write out additions.
qavdata->res_id = res_id; qavdata->res_id = res_id;
qavdata->ticrate = 120. / qavdata->ticksPerFrame; qavdata->ticrate = 120. / qavdata->ticksPerFrame;
qavcache.Insert(res_id, qavdata); qavcache.Insert(res_id, qavdata);
return qavdata; return qavdata;
} }

View file

@ -31,208 +31,208 @@ enum { kQavOrientationLeft = 4096 };
enum enum
{ {
kQAVNone = -1, kQAVNone = -1,
kQAVFORKUP = 0, kQAVFORKUP = 0,
kQAVFORKIDLE = 1, kQAVFORKIDLE = 1,
kQAVPFORK = 2, kQAVPFORK = 2,
kQAVFORKDOWN = 3, kQAVFORKDOWN = 3,
kQAVLITEOPEN = 4, kQAVLITEOPEN = 4,
kQAVLITEFLAM = 5, kQAVLITEFLAM = 5,
kQAVLITEIDLE = 6, kQAVLITEIDLE = 6,
kQAVLITECLO2 = 7, kQAVLITECLO2 = 7,
kQAVCANPREF = 8, kQAVCANPREF = 8,
kQAVCANIDLE = 9, kQAVCANIDLE = 9,
kQAVCANFIRE = 10, kQAVCANFIRE = 10,
kQAVCANDOWN = 11, kQAVCANDOWN = 11,
kQAVCANFIRE2 = 12, kQAVCANFIRE2 = 12,
kQAVCANDROP = 13, kQAVCANDROP = 13,
kQAVCANTHRO = 14, kQAVCANTHRO = 14,
kQAVCANBOOM = 15, kQAVCANBOOM = 15,
kQAVBUNUP = 16, kQAVBUNUP = 16,
kQAVBUNDOWN = 17, kQAVBUNDOWN = 17,
kQAVBUNUP2 = 18, kQAVBUNUP2 = 18,
kQAVBUNDOWN2 = 19, kQAVBUNDOWN2 = 19,
kQAVBUNIDLE = 20, kQAVBUNIDLE = 20,
kQAVBUNFUSE = 21, kQAVBUNFUSE = 21,
kQAVBUNDROP = 22, kQAVBUNDROP = 22,
kQAVBUNTHRO = 23, kQAVBUNTHRO = 23,
kQAVDYNEXPLO = 24, kQAVDYNEXPLO = 24,
kQAVPROXUP = 25, kQAVPROXUP = 25,
kQAVPROXDOWN = 26, kQAVPROXDOWN = 26,
kQAVPROXIDLE = 27, kQAVPROXIDLE = 27,
kQAVPROXDROP = 28, kQAVPROXDROP = 28,
kQAVPROXTHRO = 29, kQAVPROXTHRO = 29,
kQAVREMUP1 = 30, kQAVREMUP1 = 30,
kQAVREMUP2 = 31, kQAVREMUP2 = 31,
kQAVREMUP3 = 32, kQAVREMUP3 = 32,
kQAVREMDOWN1 = 33, kQAVREMDOWN1 = 33,
kQAVREMDOWN2 = 34, kQAVREMDOWN2 = 34,
kQAVREMDOWN3 = 35, kQAVREMDOWN3 = 35,
kQAVREMIDLE1 = 36, kQAVREMIDLE1 = 36,
kQAVREMIDLE2 = 37, kQAVREMIDLE2 = 37,
kQAVREMDROP = 38, kQAVREMDROP = 38,
kQAVREMTHRO = 39, kQAVREMTHRO = 39,
kQAVREMFIRE = 40, kQAVREMFIRE = 40,
kQAVFLARUP = 41, kQAVFLARUP = 41,
kQAVFLARIDLE = 42, kQAVFLARIDLE = 42,
kQAVFLARFIR2 = 43, kQAVFLARFIR2 = 43,
kQAVFLARDOWN = 44, kQAVFLARDOWN = 44,
kQAVFLAR2UP = 45, kQAVFLAR2UP = 45,
kQAVFLAR2I = 46, kQAVFLAR2I = 46,
kQAVFLAR2F = 47, kQAVFLAR2F = 47,
kQAVFLAR2FIR = 48, kQAVFLAR2FIR = 48,
kQAVFLAR2DWN = 49, kQAVFLAR2DWN = 49,
kQAVSHOTUP = 50, kQAVSHOTUP = 50,
kQAVSHOTI3 = 51, kQAVSHOTI3 = 51,
kQAVSHOTI2 = 52, kQAVSHOTI2 = 52,
kQAVSHOTI1 = 53, kQAVSHOTI1 = 53,
kQAVSHOTF1 = 54, kQAVSHOTF1 = 54,
kQAVSHOTF2 = 55, kQAVSHOTF2 = 55,
kQAVSHOTF3 = 56, kQAVSHOTF3 = 56,
kQAVSHOTL1 = 57, kQAVSHOTL1 = 57,
kQAVSHOTDOWN = 58, kQAVSHOTDOWN = 58,
kQAV2SHOTUP = 59, kQAV2SHOTUP = 59,
kQAV2SHOTI = 60, kQAV2SHOTI = 60,
kQAV2SHOTF2 = 61, kQAV2SHOTF2 = 61,
kQAV2SHOTFIR = 62, kQAV2SHOTFIR = 62,
kQAV2SHOTDWN = 63, kQAV2SHOTDWN = 63,
kQAVTOMUP = 64, kQAVTOMUP = 64,
kQAVTOMIDLE = 65, kQAVTOMIDLE = 65,
kQAVTOMFIRE = 66, kQAVTOMFIRE = 66,
kQAVTOMSPRED = 67, kQAVTOMSPRED = 67,
kQAVTOMDOWN = 68, kQAVTOMDOWN = 68,
kQAV2TOMUP = 69, kQAV2TOMUP = 69,
kQAV2TOMIDLE = 70, kQAV2TOMIDLE = 70,
kQAV2TOMFIRE = 71, kQAV2TOMFIRE = 71,
kQAV2TOMDOWN = 72, kQAV2TOMDOWN = 72,
kQAV2TOMALT = 73, kQAV2TOMALT = 73,
kQAVSGUNUP = 74, kQAVSGUNUP = 74,
kQAVSGUNIDL1 = 75, kQAVSGUNIDL1 = 75,
kQAVSGUNIDL2 = 76, kQAVSGUNIDL2 = 76,
kQAVSGUNFIR1 = 77, kQAVSGUNFIR1 = 77,
kQAVSGUNFIR4 = 78, kQAVSGUNFIR4 = 78,
kQAVSGUNPRE = 79, kQAVSGUNPRE = 79,
kQAVSGUNPOST = 80, kQAVSGUNPOST = 80,
kQAVSGUNDOWN = 81, kQAVSGUNDOWN = 81,
kQAV2SGUNUP = 82, kQAV2SGUNUP = 82,
kQAV2SGUNIDL = 83, kQAV2SGUNIDL = 83,
kQAV2SGUNFIR = 84, kQAV2SGUNFIR = 84,
kQAV2SGUNALT = 85, kQAV2SGUNALT = 85,
kQAV2SGUNPRE = 86, kQAV2SGUNPRE = 86,
kQAV2SGUNPST = 87, kQAV2SGUNPST = 87,
kQAV2SGUNDWN = 88, kQAV2SGUNDWN = 88,
kQAVNAPUP = 89, kQAVNAPUP = 89,
kQAVNAPIDLE = 90, kQAVNAPIDLE = 90,
kQAVNAPFIRE = 91, kQAVNAPFIRE = 91,
kQAVNAPDOWN = 92, kQAVNAPDOWN = 92,
kQAVBSTUP = 93, kQAVBSTUP = 93,
kQAVBSTIDLE = 94, kQAVBSTIDLE = 94,
kQAVBSTATAK1 = 95, kQAVBSTATAK1 = 95,
kQAVBSTATAK2 = 96, kQAVBSTATAK2 = 96,
kQAVBSTATAK3 = 97, kQAVBSTATAK3 = 97,
kQAVBSTATAK4 = 98, kQAVBSTATAK4 = 98,
kQAVBSTDOWN = 99, kQAVBSTDOWN = 99,
kQAVVDUP = 100, kQAVVDUP = 100,
kQAVVDIDLE1 = 101, kQAVVDIDLE1 = 101,
kQAVVDIDLE2 = 102, kQAVVDIDLE2 = 102,
kQAVVDFIRE1 = 103, kQAVVDFIRE1 = 103,
kQAVVDFIRE2 = 104, kQAVVDFIRE2 = 104,
kQAVVDFIRE3 = 105, kQAVVDFIRE3 = 105,
kQAVVDFIRE4 = 106, kQAVVDFIRE4 = 106,
kQAVVDFIRE5 = 107, kQAVVDFIRE5 = 107,
kQAVVDFIRE6 = 108, kQAVVDFIRE6 = 108,
kQAVVDDOWN = 109, kQAVVDDOWN = 109,
kQAVVDSPEL1 = 110, kQAVVDSPEL1 = 110,
kQAVSTAFUP = 111, kQAVSTAFUP = 111,
kQAVSTAFIDL1 = 112, kQAVSTAFIDL1 = 112,
kQAVSTAFIDL3 = 113, kQAVSTAFIDL3 = 113,
kQAVSTAFIRE1 = 114, kQAVSTAFIRE1 = 114,
kQAVSTAFIRE2 = 115, kQAVSTAFIRE2 = 115,
kQAVSTAFIRE4 = 116, kQAVSTAFIRE4 = 116,
kQAVSTAFPRE = 117, kQAVSTAFPRE = 117,
kQAVSTAFPOST = 118, kQAVSTAFPOST = 118,
kQAVSTAFDOWN = 119, kQAVSTAFDOWN = 119,
kQAV2NAPUP = 120, kQAV2NAPUP = 120,
kQAV2NAPIDLE = 121, kQAV2NAPIDLE = 121,
kQAV2NAPFIRE = 122, kQAV2NAPFIRE = 122,
kQAV2NAPFIR2 = 123, kQAV2NAPFIR2 = 123,
kQAV2NAPDOWN = 124, kQAV2NAPDOWN = 124,
kQAVEnd = 125, kQAVEnd = 125,
kQAVBDRIP = 256, kQAVBDRIP = 256,
}; };
// by NoOne: add sound flags // by NoOne: add sound flags
enum enum
{ {
kFlagSoundKill = 0x01, // mute QAV sounds of same priority kFlagSoundKill = 0x01, // mute QAV sounds of same priority
kFlagSoundKillAll = 0x02, // mute all QAV sounds kFlagSoundKillAll = 0x02, // mute all QAV sounds
}; };
struct TILE_FRAME struct TILE_FRAME
{ {
int picnum; int picnum;
int x; int x;
int y; int y;
int z; int z;
int stat; int stat;
int8_t shade; int8_t shade;
int8_t palnum; int8_t palnum;
uint16_t angle; uint16_t angle;
}; };
struct SOUNDINFO struct SOUNDINFO
{ {
int sound; int sound;
uint8_t priority; uint8_t priority;
uint8_t sndFlags; // (by NoOne) Various sound flags uint8_t sndFlags; // (by NoOne) Various sound flags
uint8_t sndRange; // (by NoOne) Random sound range uint8_t sndRange; // (by NoOne) Random sound range
uint8_t reserved[1]; uint8_t reserved[1];
}; };
struct FRAMEINFO struct FRAMEINFO
{ {
int nCallbackId; // 0 int nCallbackId; // 0
SOUNDINFO sound; // 4 SOUNDINFO sound; // 4
TILE_FRAME tiles[8]; // 12 TILE_FRAME tiles[8]; // 12
}; };
struct QAV struct QAV
{ {
double ticrate; // 0 double ticrate; // 0
int nFrames; // 8 int nFrames; // 8
int ticksPerFrame; // C int ticksPerFrame; // C
int duration; // 10 int duration; // 10
int x; // 14 int x; // 14
int y; // 18 int y; // 18
uint16_t res_id; uint16_t res_id;
FRAMEINFO frames[1]; // 24 FRAMEINFO frames[1]; // 24
void Draw(double x, double y, int ticks, int stat, int shade, int palnum, bool to3dview, double const smoothratio = 65536); void Draw(double x, double y, int ticks, int stat, int shade, int palnum, bool to3dview, double const smoothratio = 65536);
void Draw(int ticks, int stat, int shade, int palnum, bool to3dview, double const smoothratio = 65536) { Draw(x, y, ticks, stat, shade, palnum, to3dview, smoothratio); } void Draw(int ticks, int stat, int shade, int palnum, bool to3dview, double const smoothratio = 65536) { Draw(x, y, ticks, stat, shade, palnum, to3dview, smoothratio); }
void Play(int, int, int, PLAYER *); void Play(int, int, int, PLAYER*);
void Precache(int palette = 0); void Precache(int palette = 0);
}; };
QAV* getQAV(int res_id); QAV* getQAV(int res_id);
@ -241,13 +241,13 @@ void qavProcessTimer(PLAYER* const pPlayer, QAV* const pQAV, int* duration, doub
inline bool qavIsOriginal(const int res_id) inline bool qavIsOriginal(const int res_id)
{ {
auto const lump = fileSystem.FindResource(res_id, "QAV"); auto const lump = fileSystem.FindResource(res_id, "QAV");
return lump >= 0 && fileSystem.GetFileContainer(lump) < fileSystem.GetMaxIwadNum(); return lump >= 0 && fileSystem.GetFileContainer(lump) < fileSystem.GetMaxIwadNum();
} }
inline int qavGetCorrectID(const int res_id) inline int qavGetCorrectID(const int res_id)
{ {
return cl_bloodweapinterp && qavIsOriginal(res_id) && fileSystem.FindResource(res_id + 10000, "QAV") != -1 ? res_id + 10000 : res_id; return cl_bloodweapinterp && qavIsOriginal(res_id) && fileSystem.FindResource(res_id + 10000, "QAV") != -1 ? res_id + 10000 : res_id;
} }
END_BLD_NS END_BLD_NS

View file

@ -43,45 +43,57 @@ CVAR(Bool, hud_ctf_vanilla, false, CVAR_ARCHIVE)
BEGIN_BLD_NS BEGIN_BLD_NS
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void UpdateFrame(void) static void UpdateFrame(void)
{ {
auto tex = tileGetTexture(kBackTile); auto tex = tileGetTexture(kBackTile);
int width = twod->GetWidth(); int width = twod->GetWidth();
int height = twod->GetHeight(); int height = twod->GetHeight();
twod->AddFlatFill(0, 0, width, windowxy1.Y - 3, tex); twod->AddFlatFill(0, 0, width, windowxy1.Y - 3, tex);
twod->AddFlatFill(0, windowxy2.Y + 4, width, height, tex); twod->AddFlatFill(0, windowxy2.Y + 4, width, height, tex);
twod->AddFlatFill(0, windowxy1.Y - 3, windowxy1.X - 3, windowxy2.Y + 4, tex); twod->AddFlatFill(0, windowxy1.Y - 3, windowxy1.X - 3, windowxy2.Y + 4, tex);
twod->AddFlatFill(windowxy2.X + 4, windowxy1.Y - 3, width, windowxy2.Y + 4, tex); twod->AddFlatFill(windowxy2.X + 4, windowxy1.Y - 3, width, windowxy2.Y + 4, tex);
twod->AddFlatFill(windowxy1.X - 3, windowxy1.Y - 3, windowxy1.X, windowxy2.Y + 1, tex, 0, 1, 0xff545454); twod->AddFlatFill(windowxy1.X - 3, windowxy1.Y - 3, windowxy1.X, windowxy2.Y + 1, tex, 0, 1, 0xff545454);
twod->AddFlatFill(windowxy1.X, windowxy1.Y - 3, windowxy2.X + 4, windowxy1.Y, tex, 0, 1, 0xff545454); twod->AddFlatFill(windowxy1.X, windowxy1.Y - 3, windowxy2.X + 4, windowxy1.Y, tex, 0, 1, 0xff545454);
twod->AddFlatFill(windowxy2.X + 1, windowxy1.Y, windowxy2.X + 4, windowxy2.Y + 4, tex, 0, 1, 0xff2a2a2a); twod->AddFlatFill(windowxy2.X + 1, windowxy1.Y, windowxy2.X + 4, windowxy2.Y + 4, tex, 0, 1, 0xff2a2a2a);
twod->AddFlatFill(windowxy1.X - 3, windowxy2.Y + 1, windowxy2.X + 1, windowxy2.Y + 4, tex, 0, 1, 0xff2a2a2a); twod->AddFlatFill(windowxy1.X - 3, windowxy2.Y + 1, windowxy2.X + 1, windowxy2.Y + 4, tex, 0, 1, 0xff2a2a2a);
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void UpdateStatusBar() void UpdateStatusBar()
{ {
if (automapMode == am_off && hud_size <= Hud_Stbar) if (automapMode == am_off && hud_size <= Hud_Stbar)
{ {
UpdateFrame(); UpdateFrame();
} }
SummaryInfo sum; SummaryInfo sum;
if (gGameOptions.nGameType == 3) if (gGameOptions.nGameType == 3)
{ {
sum.kills = gView ? gView->fragCount : 0; sum.kills = gView ? gView->fragCount : 0;
sum.maxkills = -3; sum.maxkills = -3;
} }
else else
{ {
sum.kills = gKillMgr.Kills; sum.kills = gKillMgr.Kills;
sum.maxkills = gKillMgr.TotalKills; sum.maxkills = gKillMgr.TotalKills;
} }
sum.secrets = gSecretMgr.Founds; sum.secrets = gSecretMgr.Founds;
sum.supersecrets = gSecretMgr.Super; sum.supersecrets = gSecretMgr.Super;
sum.maxsecrets = max(gSecretMgr.Founds, gSecretMgr.Total); // If we found more than there are, increase the total. Some levels have a bugged counter. sum.maxsecrets = max(gSecretMgr.Founds, gSecretMgr.Total); // If we found more than there are, increase the total. Some levels have a bugged counter.
sum.time = Scale(PlayClock, 1000, 120); sum.time = Scale(PlayClock, 1000, 120);
UpdateStatusBar(&sum); UpdateStatusBar(&sum);
} }

View file

@ -30,321 +30,355 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
static const uint8_t flicker1[] = { static const uint8_t flicker1[] = {
0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0,
1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1,
0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1,
0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1
}; };
static const uint8_t flicker2[] = { static const uint8_t flicker2[] = {
1, 2, 4, 2, 3, 4, 3, 2, 0, 0, 1, 2, 4, 3, 2, 0, 1, 2, 4, 2, 3, 4, 3, 2, 0, 0, 1, 2, 4, 3, 2, 0,
2, 1, 0, 1, 0, 2, 3, 4, 3, 2, 1, 1, 2, 0, 0, 1, 2, 1, 0, 1, 0, 2, 3, 4, 3, 2, 1, 1, 2, 0, 0, 1,
1, 2, 3, 4, 4, 3, 2, 1, 2, 3, 4, 4, 2, 1, 0, 1, 1, 2, 3, 4, 4, 3, 2, 1, 2, 3, 4, 4, 2, 1, 0, 1,
0, 0, 0, 0, 1, 2, 3, 4, 3, 2, 1, 2, 3, 4, 3, 2 0, 0, 0, 0, 1, 2, 3, 4, 3, 2, 1, 2, 3, 4, 3, 2
}; };
static const uint8_t flicker3[] = { static const uint8_t flicker3[] = {
4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 4, 2, 4, 3, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 4, 2, 4, 3, 4, 4,
4, 4, 2, 1, 3, 3, 3, 4, 3, 4, 4, 4, 4, 4, 2, 4, 4, 4, 2, 1, 3, 3, 3, 4, 3, 4, 4, 4, 4, 4, 2, 4,
4, 4, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 1, 0, 1, 4, 4, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 1, 0, 1,
0, 1, 0, 1, 0, 2, 3, 4, 4, 4, 4, 4, 4, 4, 3, 4 0, 1, 0, 1, 0, 2, 3, 4, 4, 4, 4, 4, 4, 4, 3, 4
}; };
static const uint8_t flicker4[] = { static const uint8_t flicker4[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4, 0, 0, 3, 0, 1, 0, 1, 0, 4, 4, 4, 4, 4, 2, 0, 4, 0, 0, 3, 0, 1, 0, 1, 0, 4, 4, 4, 4, 4, 2, 0,
0, 0, 0, 4, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 4, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 1,
0, 0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 2, 1, 4, 3, 2, 0, 0, 0, 0, 0, 2, 1, 2, 1, 2, 1, 2, 1, 4, 3, 2,
0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0, 0, 0 ,0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0, 0, 0 ,0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0, 0, 0 ,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0, 0, 0 ,0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0, 0, 0 ,0, 0 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0 ,0 ,0, 0, 0 ,0, 0
}; };
static const uint8_t strobe[] = { static const uint8_t strobe[] = {
64, 64, 64, 48, 36, 27, 20, 15, 11, 9, 6, 5, 4, 3, 2, 2, 64, 64, 64, 48, 36, 27, 20, 15, 11, 9, 6, 5, 4, 3, 2, 2,
1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}; };
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
int GetWaveValue(int a, int b, int c) int GetWaveValue(int a, int b, int c)
{ {
b &= 2047; b &= 2047;
switch (a) switch (a)
{ {
case 0: case 0:
return c; return c;
case 1: case 1:
return (b>>10)*c; return (b >> 10) * c;
case 2: case 2:
return (abs(128-(b>>3))*c)>>7; return (abs(128 - (b >> 3)) * c) >> 7;
case 3: case 3:
return ((b>>3)*c)>>8; return ((b >> 3) * c) >> 8;
case 4: case 4:
return ((255-(b>>3))*c)>>8; return ((255 - (b >> 3)) * c) >> 8;
case 5: case 5:
return (c+MulScale(c,Sin(b), 30))>>1; return (c + MulScale(c, Sin(b), 30)) >> 1;
case 6: case 6:
return flicker1[b>>5]*c; return flicker1[b >> 5] * c;
case 7: case 7:
return (flicker2[b>>5]*c)>>2; return (flicker2[b >> 5] * c) >> 2;
case 8: case 8:
return (flicker3[b>>5]*c)>>2; return (flicker3[b >> 5] * c) >> 2;
case 9: case 9:
return (flicker4[b>>4]*c)>>2; return (flicker4[b >> 4] * c) >> 2;
case 10: case 10:
return (strobe[b>>5]*c)>>6; return (strobe[b >> 5] * c) >> 6;
case 11: case 11:
if (b*4 > 2048) if (b * 4 > 2048)
return 0; return 0;
return (c-MulScale(c, Cos(b*4), 30))>>1; return (c - MulScale(c, Cos(b * 4), 30)) >> 1;
} }
return 0; return 0;
} }
//---------------------------------------------------------------------------
//
// These can be fully regenerated after loading a savegame. // These can be fully regenerated after loading a savegame.
//
//---------------------------------------------------------------------------
TArray<sectortype*> shadeList; TArray<sectortype*> shadeList;
TArray<sectortype*> panList; TArray<sectortype*> panList;
TArray<walltype*> wallPanList; TArray<walltype*> wallPanList;
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void DoSectorLighting(void) void DoSectorLighting(void)
{ {
for (auto& pSector : shadeList) for (auto& pSector : shadeList)
{ {
XSECTOR* pXSector = &pSector->xs(); XSECTOR* pXSector = &pSector->xs();
if (pXSector->shade) if (pXSector->shade)
{ {
int v4 = pXSector->shade; int v4 = pXSector->shade;
if (pXSector->shadeFloor) if (pXSector->shadeFloor)
{ {
pSector->floorshade -= v4; pSector->floorshade -= v4;
if (pXSector->color) if (pXSector->color)
{ {
int nTemp = pXSector->floorpal; int nTemp = pXSector->floorpal;
pXSector->floorpal = pSector->floorpal; pXSector->floorpal = pSector->floorpal;
pSector->floorpal = nTemp; pSector->floorpal = nTemp;
} }
} }
if (pXSector->shadeCeiling) if (pXSector->shadeCeiling)
{ {
pSector->ceilingshade -= v4; pSector->ceilingshade -= v4;
if (pXSector->color) if (pXSector->color)
{ {
int nTemp = pXSector->ceilpal; int nTemp = pXSector->ceilpal;
pXSector->ceilpal = pSector->ceilingpal; pXSector->ceilpal = pSector->ceilingpal;
pSector->ceilingpal = nTemp; pSector->ceilingpal = nTemp;
} }
} }
if (pXSector->shadeWalls) if (pXSector->shadeWalls)
{ {
for(auto& wal : wallsofsector(pSector)) for (auto& wal : wallsofsector(pSector))
{ {
wal.shade -= v4; wal.shade -= v4;
if (pXSector->color) if (pXSector->color)
{ {
wal.pal = pSector->floorpal; wal.pal = pSector->floorpal;
} }
} }
} }
pXSector->shade = 0; pXSector->shade = 0;
} }
if (pXSector->shadeAlways || pXSector->busy) if (pXSector->shadeAlways || pXSector->busy)
{ {
int t1 = pXSector->wave; int t1 = pXSector->wave;
int t2 = pXSector->amplitude; int t2 = pXSector->amplitude;
if (!pXSector->shadeAlways && pXSector->busy) if (!pXSector->shadeAlways && pXSector->busy)
{ {
t2 = MulScale(t2, pXSector->busy, 16); t2 = MulScale(t2, pXSector->busy, 16);
} }
int v4 = GetWaveValue(t1, pXSector->phase*8+pXSector->freq*PlayClock, t2); int v4 = GetWaveValue(t1, pXSector->phase * 8 + pXSector->freq * PlayClock, t2);
if (pXSector->shadeFloor) if (pXSector->shadeFloor)
{ {
pSector->floorshade = ClipRange(pSector->floorshade+v4, -128, 127); pSector->floorshade = ClipRange(pSector->floorshade + v4, -128, 127);
if (pXSector->color && v4 != 0) if (pXSector->color && v4 != 0)
{ {
int nTemp = pXSector->floorpal; int nTemp = pXSector->floorpal;
pXSector->floorpal = pSector->floorpal; pXSector->floorpal = pSector->floorpal;
pSector->floorpal = nTemp; pSector->floorpal = nTemp;
} }
} }
if (pXSector->shadeCeiling) if (pXSector->shadeCeiling)
{ {
pSector->ceilingshade = ClipRange(pSector->ceilingshade+v4, -128, 127); pSector->ceilingshade = ClipRange(pSector->ceilingshade + v4, -128, 127);
if (pXSector->color && v4 != 0) if (pXSector->color && v4 != 0)
{ {
int nTemp = pXSector->ceilpal; int nTemp = pXSector->ceilpal;
pXSector->ceilpal = pSector->ceilingpal; pXSector->ceilpal = pSector->ceilingpal;
pSector->ceilingpal = nTemp; pSector->ceilingpal = nTemp;
} }
} }
if (pXSector->shadeWalls) if (pXSector->shadeWalls)
{ {
for (auto& wal : wallsofsector(pSector)) for (auto& wal : wallsofsector(pSector))
{ {
wal.shade = ClipRange(wal.shade+v4, -128, 127); wal.shade = ClipRange(wal.shade + v4, -128, 127);
if (pXSector->color && v4 != 0) if (pXSector->color && v4 != 0)
{ {
wal.pal = pSector->floorpal; wal.pal = pSector->floorpal;
} }
} }
} }
pXSector->shade = v4; pXSector->shade = v4;
} }
} }
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void UndoSectorLighting(void) void UndoSectorLighting(void)
{ {
for (auto& sect: sector) for (auto& sect : sector)
{ {
if (sect.hasX()) if (sect.hasX())
{ {
XSECTOR *pXSector = &sect.xs(); XSECTOR* pXSector = &sect.xs();
if (pXSector->shade) if (pXSector->shade)
{ {
int v4 = pXSector->shade; int v4 = pXSector->shade;
if (pXSector->shadeFloor) if (pXSector->shadeFloor)
{ {
sect.floorshade -= v4; sect.floorshade -= v4;
if (pXSector->color) if (pXSector->color)
{ {
int nTemp = pXSector->floorpal; int nTemp = pXSector->floorpal;
pXSector->floorpal = sect.floorpal; pXSector->floorpal = sect.floorpal;
sect.floorpal = nTemp; sect.floorpal = nTemp;
} }
} }
if (pXSector->shadeCeiling) if (pXSector->shadeCeiling)
{ {
sect.ceilingshade -= v4; sect.ceilingshade -= v4;
if (pXSector->color) if (pXSector->color)
{ {
int nTemp = pXSector->ceilpal; int nTemp = pXSector->ceilpal;
pXSector->ceilpal = sect.ceilingpal; pXSector->ceilpal = sect.ceilingpal;
sect.ceilingpal = nTemp; sect.ceilingpal = nTemp;
} }
} }
if (pXSector->shadeWalls) if (pXSector->shadeWalls)
{ {
for(auto& wal : wallsofsector(&sect)) for (auto& wal : wallsofsector(&sect))
{ {
wal.shade -= v4; wal.shade -= v4;
if (pXSector->color) if (pXSector->color)
{ {
wal.pal = sect.floorpal; wal.pal = sect.floorpal;
} }
} }
} }
pXSector->shade = 0; pXSector->shade = 0;
} }
} }
} }
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void DoSectorPanning(void) void DoSectorPanning(void)
{ {
for(auto pSector : panList) for (auto pSector : panList)
{ {
XSECTOR *pXSector = &pSector->xs(); XSECTOR* pXSector = &pSector->xs();
if (pXSector->panAlways || pXSector->busy) if (pXSector->panAlways || pXSector->busy)
{ {
int angle = pXSector->panAngle+1024; int angle = pXSector->panAngle + 1024;
int speed = pXSector->panVel<<10; int speed = pXSector->panVel << 10;
if (!pXSector->panAlways && (pXSector->busy&0xffff)) if (!pXSector->panAlways && (pXSector->busy & 0xffff))
speed = MulScale(speed, pXSector->busy, 16); speed = MulScale(speed, pXSector->busy, 16);
if (pXSector->panFloor) // Floor if (pXSector->panFloor) // Floor
{ {
int nTile = pSector->floorpicnum; int nTile = pSector->floorpicnum;
if (pSector->floorstat & CSTAT_SECTOR_ALIGN) if (pSector->floorstat & CSTAT_SECTOR_ALIGN)
angle -= 512; angle -= 512;
int xBits = tileWidth(nTile) >> int((pSector->floorstat & CSTAT_SECTOR_TEXHALF) != 0); int xBits = tileWidth(nTile) >> int((pSector->floorstat & CSTAT_SECTOR_TEXHALF) != 0);
int px = MulScale(speed << 2, Cos(angle), 30) / xBits; int px = MulScale(speed << 2, Cos(angle), 30) / xBits;
int yBits = tileHeight(nTile) >> int((pSector->floorstat & CSTAT_SECTOR_TEXHALF) != 0); int yBits = tileHeight(nTile) >> int((pSector->floorstat & CSTAT_SECTOR_TEXHALF) != 0);
int py = MulScale(speed << 2, Sin(angle), 30) / yBits; int py = MulScale(speed << 2, Sin(angle), 30) / yBits;
pSector->addfloorxpan(px * (1.f / 256)); pSector->addfloorxpan(px * (1.f / 256));
pSector->addfloorypan(-py * (1.f / 256)); pSector->addfloorypan(-py * (1.f / 256));
} }
if (pXSector->panCeiling) // Ceiling if (pXSector->panCeiling) // Ceiling
{ {
int nTile = pSector->ceilingpicnum; int nTile = pSector->ceilingpicnum;
if (pSector->ceilingstat & CSTAT_SECTOR_ALIGN) if (pSector->ceilingstat & CSTAT_SECTOR_ALIGN)
angle -= 512; angle -= 512;
int xBits = tileWidth(nTile) >> int((pSector->ceilingstat & CSTAT_SECTOR_TEXHALF) != 0); int xBits = tileWidth(nTile) >> int((pSector->ceilingstat & CSTAT_SECTOR_TEXHALF) != 0);
int px = MulScale(speed << 2, Cos(angle), 30) / xBits; int px = MulScale(speed << 2, Cos(angle), 30) / xBits;
int yBits = tileHeight(nTile) >> int((pSector->ceilingstat & CSTAT_SECTOR_TEXHALF) != 0); int yBits = tileHeight(nTile) >> int((pSector->ceilingstat & CSTAT_SECTOR_TEXHALF) != 0);
int py = MulScale(speed << 2, Sin(angle), 30) / yBits; int py = MulScale(speed << 2, Sin(angle), 30) / yBits;
pSector->addceilingxpan(px * (1.f / 256)); pSector->addceilingxpan(px * (1.f / 256));
pSector->addceilingypan(-py * (1.f / 256)); pSector->addceilingypan(-py * (1.f / 256));
} }
} }
} }
for (auto pWall : wallPanList) for (auto pWall : wallPanList)
{ {
XWALL *pXWall = &pWall->xw(); XWALL* pXWall = &pWall->xw();
if (pXWall->panAlways || pXWall->busy) if (pXWall->panAlways || pXWall->busy)
{ {
int psx = pXWall->panXVel<<10; int psx = pXWall->panXVel << 10;
int psy = pXWall->panYVel<<10; int psy = pXWall->panYVel << 10;
if (!pXWall->panAlways && (pXWall->busy & 0xffff)) if (!pXWall->panAlways && (pXWall->busy & 0xffff))
{ {
psx = MulScale(psx, pXWall->busy, 16); psx = MulScale(psx, pXWall->busy, 16);
psy = MulScale(psy, pXWall->busy, 16); psy = MulScale(psy, pXWall->busy, 16);
} }
int nTile = pWall->picnum; int nTile = pWall->picnum;
int px = (psx << 2) / tileWidth(nTile); int px = (psx << 2) / tileWidth(nTile);
int py = (psy << 2) / tileHeight(nTile); int py = (psy << 2) / tileHeight(nTile);
pWall->addxpan(px * (1.f / 256)); pWall->addxpan(px * (1.f / 256));
pWall->addypan(py * (1.f / 256)); pWall->addypan(py * (1.f / 256));
} }
} }
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void InitSectorFX(void) void InitSectorFX(void)
{ {
shadeList.Clear(); shadeList.Clear();
panList.Clear(); panList.Clear();
wallPanList.Clear(); wallPanList.Clear();
for (auto& sect: sector) for (auto& sect : sector)
{ {
if (sect.hasX()) if (sect.hasX())
{ {
XSECTOR *pXSector = &sect.xs(); XSECTOR* pXSector = &sect.xs();
if (pXSector->amplitude) if (pXSector->amplitude)
shadeList.Push(&sect); shadeList.Push(&sect);
if (pXSector->panVel) if (pXSector->panVel)
{ {
panList.Push(&sect); panList.Push(&sect);
if (pXSector->panCeiling) if (pXSector->panCeiling)
{ {
StartInterpolation(&sect, Interp_Sect_CeilingPanX); StartInterpolation(&sect, Interp_Sect_CeilingPanX);
StartInterpolation(&sect, Interp_Sect_CeilingPanY); StartInterpolation(&sect, Interp_Sect_CeilingPanY);
} }
if (pXSector->panFloor) if (pXSector->panFloor)
{ {
StartInterpolation(&sect, Interp_Sect_FloorPanX); StartInterpolation(&sect, Interp_Sect_FloorPanX);
StartInterpolation(&sect, Interp_Sect_FloorPanY); StartInterpolation(&sect, Interp_Sect_FloorPanY);
} }
} }
} }
} }
for(auto& wal : wall) for (auto& wal : wall)
{ {
if (wal.hasX()) if (wal.hasX())
{ {
XWALL *pXWall = &wal.xw(); XWALL* pXWall = &wal.xw();
if (pXWall->panXVel || pXWall->panYVel) if (pXWall->panXVel || pXWall->panYVel)
{ {
wallPanList.Push(&wal); wallPanList.Push(&wal);
if (pXWall->panXVel) StartInterpolation(&wal, Interp_Wall_PanX); if (pXWall->panXVel) StartInterpolation(&wal, Interp_Wall_PanX);
if (pXWall->panXVel) StartInterpolation(&wal, Interp_Wall_PanY); if (pXWall->panXVel) StartInterpolation(&wal, Interp_Wall_PanY);
} }
} }
} }
} }

View file

@ -351,7 +351,7 @@ void SEQINST::Update()
if (!VanillaMode() && pSequence->frames[frameIndex].surfaceSound && actor->zvel == 0 && actor->xvel != 0) { if (!VanillaMode() && pSequence->frames[frameIndex].surfaceSound && actor->zvel == 0 && actor->xvel != 0) {
if (actor->spr.sector()->upperLink) break; // don't play surface sound for stacked sectors if (actor->spr.sector()->upperLink) break; // don't play surface sound for stacked sectors
int surf = tileGetSurfType(actor->spr.sector()->floorpicnum); int surf = tileGetSurfType(actor->spr.sector()->floorpicnum);
if (!surf) break; if (!surf) break;
static int surfSfxMove[15][4] = { static int surfSfxMove[15][4] = {
/* {snd1, snd2, gameVolume, myVolume} */ /* {snd1, snd2, gameVolume, myVolume} */
@ -704,7 +704,7 @@ void seqProcess(int nTicks)
{ {
evKillActor(actor); evKillActor(actor);
if ((actor->spr.hitag & kAttrRespawn) != 0 && (actor->spr.inittype >= kDudeBase && actor->spr.inittype < kDudeMax)) if ((actor->spr.hitag & kAttrRespawn) != 0 && (actor->spr.inittype >= kDudeBase && actor->spr.inittype < kDudeMax))
evPostActor(actor, gGameOptions.nMonsterRespawnTime, kCallbackRespawn); evPostActor(actor, gGameOptions.nMonsterRespawnTime, kCallbackRespawn);
else DeleteSprite(actor); // safe to not use actPostSprite here else DeleteSprite(actor); // safe to not use actPostSprite here
} }
} }
@ -747,8 +747,8 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, SEQINST& w, SEQINS
("timecounter", w.timeCounter) ("timecounter", w.timeCounter)
("frameindex", w.frameIndex) ("frameindex", w.frameIndex)
("target", w.target); ("target", w.target);
arc.EndObject(); arc.EndObject();
} }
return arc; return arc;
} }

View file

@ -31,27 +31,27 @@ BEGIN_BLD_NS
class BloodSoundEngine : public RazeSoundEngine class BloodSoundEngine : public RazeSoundEngine
{ {
// client specific parts of the sound engine go in this class. // client specific parts of the sound engine go in this class.
void CalcPosVel(int type, const void* source, const float pt[3], int channum, int chanflags, FSoundID chanSound, FVector3* pos, FVector3* vel, FSoundChan *channel) override; void CalcPosVel(int type, const void* source, const float pt[3], int channum, int chanflags, FSoundID chanSound, FVector3* pos, FVector3* vel, FSoundChan* channel) override;
TArray<uint8_t> ReadSound(int lumpnum) override; TArray<uint8_t> ReadSound(int lumpnum) override;
public: public:
BloodSoundEngine() BloodSoundEngine()
{ {
S_Rolloff.RolloffType = ROLLOFF_Doom; S_Rolloff.RolloffType = ROLLOFF_Doom;
S_Rolloff.MinDistance = 170; // these are the numbers I got when uncrunching the original sound code. S_Rolloff.MinDistance = 170; // these are the numbers I got when uncrunching the original sound code.
S_Rolloff.MaxDistance = 850; S_Rolloff.MaxDistance = 850;
} }
void StopChannel(FSoundChan* chan) override void StopChannel(FSoundChan* chan) override
{ {
if (chan && chan->SysChannel != nullptr && !(chan->ChanFlags & CHANF_EVICTED) && chan->SourceType == SOURCE_Actor) if (chan && chan->SysChannel != nullptr && !(chan->ChanFlags & CHANF_EVICTED) && chan->SourceType == SOURCE_Actor)
{ {
chan->Source = nullptr; chan->Source = nullptr;
chan->SourceType = SOURCE_Unattached; chan->SourceType = SOURCE_Unattached;
} }
SoundEngine::StopChannel(chan); SoundEngine::StopChannel(chan);
} }
@ -65,205 +65,240 @@ public:
TArray<uint8_t> BloodSoundEngine::ReadSound(int lumpnum) TArray<uint8_t> BloodSoundEngine::ReadSound(int lumpnum)
{ {
auto wlump = fileSystem.OpenFileReader(lumpnum); auto wlump = fileSystem.OpenFileReader(lumpnum);
return wlump.Read(); return wlump.Read();
} }
void BloodSoundEngine::CalcPosVel(int type, const void* source, const float pt[3], int channum, int chanflags, FSoundID chanSound, FVector3* pos, FVector3* vel, FSoundChan *) void BloodSoundEngine::CalcPosVel(int type, const void* source, const float pt[3], int channum, int chanflags, FSoundID chanSound, FVector3* pos, FVector3* vel, FSoundChan*)
{ {
if (pos != nullptr && type != SOURCE_None) if (pos != nullptr && type != SOURCE_None)
{ {
FVector3 camera; FVector3 camera;
if (gMe && gMe->actor) camera = GetSoundPos(&gMe->actor->spr.pos);
else camera = { 0, 0, 0 }; // don't crash if there is no player.
if (vel) vel->Zero(); if (gMe && gMe->actor) camera = GetSoundPos(&gMe->actor->spr.pos);
else camera = { 0, 0, 0 }; // don't crash if there is no player.
if (type == SOURCE_Unattached) if (vel) vel->Zero();
{
pos->X = pt[0];
pos->Y = pt[1];
pos->Z = pt[2];
}
else if (type == SOURCE_Actor)
{
assert(source != nullptr);
auto actor = (DBloodActor*)source;
// Engine expects velocity in units per second, not units per tic. if (type == SOURCE_Unattached)
if (vel) *vel = { actor->xvel * (30 / 65536.f), actor->zvel * (-30 / 65536.f), actor->yvel * (-30 / 65536.f) }; {
*pos = GetSoundPos(&actor->spr.pos); pos->X = pt[0];
} pos->Y = pt[1];
else if (type == SOURCE_Ambient) pos->Z = pt[2];
{ }
*pos = camera; // just to be safe. Ambient sounds are in the world but unpositioned else if (type == SOURCE_Actor)
} {
if ((chanflags & CHANF_LISTENERZ)) assert(source != nullptr);
{ auto actor = (DBloodActor*)source;
pos->Y = camera.Y;
} // Engine expects velocity in units per second, not units per tic.
} if (vel) *vel = { actor->xvel * (30 / 65536.f), actor->zvel * (-30 / 65536.f), actor->yvel * (-30 / 65536.f) };
*pos = GetSoundPos(&actor->spr.pos);
}
else if (type == SOURCE_Ambient)
{
*pos = camera; // just to be safe. Ambient sounds are in the world but unpositioned
}
if ((chanflags & CHANF_LISTENERZ))
{
pos->Y = camera.Y;
}
}
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void GameInterface::UpdateSounds() void GameInterface::UpdateSounds()
{ {
SoundListener listener; SoundListener listener;
if (gMe->actor) if (gMe->actor)
{ {
listener.angle = -gMe->actor->spr.ang * float(BAngRadian); // Build uses a period of 2048. listener.angle = -gMe->actor->spr.ang * float(BAngRadian); // Build uses a period of 2048.
listener.velocity.Zero(); listener.velocity.Zero();
listener.position = GetSoundPos(&gMe->actor->spr.pos); listener.position = GetSoundPos(&gMe->actor->spr.pos);
listener.valid = true; listener.valid = true;
} }
else else
{ {
listener.position.Zero(); listener.position.Zero();
listener.valid = false; listener.valid = false;
} }
listener.underwater = false; listener.underwater = false;
// This should probably use a real environment instead of the pitch hacking in S_PlaySound3D. // This should probably use a real environment instead of the pitch hacking in S_PlaySound3D.
// listenactor->waterlevel == 3; // listenactor->waterlevel == 3;
//assert(primaryLevel->Zones.Size() > listenactor->Sector->ZoneNumber); //assert(primaryLevel->Zones.Size() > listenactor->Sector->ZoneNumber);
listener.Environment = 0;// primaryLevel->Zones[listenactor->Sector->ZoneNumber].Environment; listener.Environment = 0;// primaryLevel->Zones[listenactor->Sector->ZoneNumber].Environment;
listener.ListenerObject = gMe; listener.ListenerObject = gMe;
soundEngine->SetListener(listener); soundEngine->SetListener(listener);
soundEngine->UpdateSounds(I_GetTime()); soundEngine->UpdateSounds(I_GetTime());
} }
FSoundID getSfx(FSoundID soundId, float &attenuation, int &pitch, int &relvol) //---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
FSoundID getSfx(FSoundID soundId, float& attenuation, int& pitch, int& relvol)
{ {
auto udata = soundEngine->GetUserData(soundId); auto udata = soundEngine->GetUserData(soundId);
if (pitch < 0) pitch = udata ? udata[0] : 0x10000; if (pitch < 0) pitch = udata ? udata[0] : 0x10000;
if (relvol < 0) relvol = 0; if (relvol < 0) relvol = 0;
else if (relvol == 0) relvol = udata && udata[2] ? udata[2] : 80; else if (relvol == 0) relvol = udata && udata[2] ? udata[2] : 80;
if (relvol > 255) relvol = 255; if (relvol > 255) relvol = 255;
// Limit the attenuation. More than 2.0 is simply too much. // Limit the attenuation. More than 2.0 is simply too much.
attenuation = relvol > 0 ? clamp(80.f / relvol, 0.f, 2.f) : 1.f; attenuation = relvol > 0 ? clamp(80.f / relvol, 0.f, 2.f) : 1.f;
return soundId; return soundId;
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void sfxPlay3DSound(int x, int y, int z, int soundId, sectortype* pSector) void sfxPlay3DSound(int x, int y, int z, int soundId, sectortype* pSector)
{ {
if (!SoundEnabled() || soundId < 0) return; if (!SoundEnabled() || soundId < 0) return;
auto sid = soundEngine->FindSoundByResID(soundId); auto sid = soundEngine->FindSoundByResID(soundId);
if (sid == 0) return; if (sid == 0) return;
vec3_t xyz = { x, y, z }; vec3_t xyz = { x, y, z };
auto svec = GetSoundPos(&xyz); auto svec = GetSoundPos(&xyz);
float attenuation; float attenuation;
int pitch = -1; int pitch = -1;
int relvol = 0; int relvol = 0;
sid = getSfx(sid, attenuation, pitch, relvol); sid = getSfx(sid, attenuation, pitch, relvol);
auto sfx = soundEngine->GetSfx(sid); auto sfx = soundEngine->GetSfx(sid);
EChanFlags flags = CHANF_OVERLAP; EChanFlags flags = CHANF_OVERLAP;
if (sfx && sfx->LoopStart >= 0) flags |= CHANF_LOOP; if (sfx && sfx->LoopStart >= 0) flags |= CHANF_LOOP;
auto chan = soundEngine->StartSound(SOURCE_Unattached, nullptr, &svec, -1, flags, sid, (0.8f / 80.f) * relvol, attenuation, nullptr, pitch / 65536.f); auto chan = soundEngine->StartSound(SOURCE_Unattached, nullptr, &svec, -1, flags, sid, (0.8f / 80.f) * relvol, attenuation, nullptr, pitch / 65536.f);
if (chan) chan->UserData = sectnum(pSector); if (chan) chan->UserData = sectnum(pSector);
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void sfxPlay3DSoundCP(DBloodActor* pActor, int soundId, int playchannel, int playflags, int pitch, int volume) void sfxPlay3DSoundCP(DBloodActor* pActor, int soundId, int playchannel, int playflags, int pitch, int volume)
{ {
if (!SoundEnabled() || soundId < 0 || !pActor) return; if (!SoundEnabled() || soundId < 0 || !pActor) return;
auto sid = soundEngine->FindSoundByResID(soundId); auto sid = soundEngine->FindSoundByResID(soundId);
if (sid == 0) return; if (sid == 0) return;
auto svec = GetSoundPos(&pActor->spr.pos); auto svec = GetSoundPos(&pActor->spr.pos);
float attenuation; float attenuation;
sid = getSfx(sid, attenuation, pitch, volume); sid = getSfx(sid, attenuation, pitch, volume);
if (volume == -1) volume = 80; if (volume == -1) volume = 80;
if (playchannel >= 0) if (playchannel >= 0)
{ {
playchannel++; // This is to make 0 a valid channel value. playchannel++; // This is to make 0 a valid channel value.
if (soundEngine->EnumerateChannels([=](FSoundChan* chan) -> int if (soundEngine->EnumerateChannels([=](FSoundChan* chan) -> int
{ {
if (chan->SourceType != SOURCE_Actor) return false; // other source types are not our business. if (chan->SourceType != SOURCE_Actor) return false; // other source types are not our business.
if (chan->EntChannel == playchannel && (chan->Source == pActor || (playflags & FX_GlobalChannel) != 0)) if (chan->EntChannel == playchannel && (chan->Source == pActor || (playflags & FX_GlobalChannel) != 0))
{ {
if ((playflags & FX_ChannelMatch) != 0 && chan->EntChannel == playchannel) if ((playflags & FX_ChannelMatch) != 0 && chan->EntChannel == playchannel)
return true; return true;
if ((playflags & FX_SoundMatch) != 0 && chan->OrgID == sid) if ((playflags & FX_SoundMatch) != 0 && chan->OrgID == sid)
return true; return true;
soundEngine->StopChannel(chan); soundEngine->StopChannel(chan);
return -1; return -1;
} }
return false; return false;
})) return; })) return;
} }
auto sfx = soundEngine->GetSfx(sid); auto sfx = soundEngine->GetSfx(sid);
EChanFlags flags = playchannel == -1 ? CHANF_OVERLAP : CHANF_NONE; EChanFlags flags = playchannel == -1 ? CHANF_OVERLAP : CHANF_NONE;
if (sfx && sfx->LoopStart >= 0) if (sfx && sfx->LoopStart >= 0)
{ {
flags |= CHANF_LOOP; flags |= CHANF_LOOP;
flags &= ~CHANF_OVERLAP; flags &= ~CHANF_OVERLAP;
} }
soundEngine->StartSound(SOURCE_Actor, pActor, &svec, playchannel, flags, sid, volume * (0.8f / 80.f), attenuation, nullptr, pitch / 65536.f); soundEngine->StartSound(SOURCE_Actor, pActor, &svec, playchannel, flags, sid, volume * (0.8f / 80.f), attenuation, nullptr, pitch / 65536.f);
} }
void sfxPlay3DSound(DBloodActor* pActor, int soundId, int a3, int a4) void sfxPlay3DSound(DBloodActor* pActor, int soundId, int a3, int a4)
{ {
sfxPlay3DSoundCP(pActor, soundId, a3, a4, -1); sfxPlay3DSoundCP(pActor, soundId, a3, a4, -1);
} }
void sfxKill3DSound(DBloodActor *pActor, int a2, int a3) //---------------------------------------------------------------------------
{ //
if (!pActor) //
return; //
//---------------------------------------------------------------------------
if (a2 >= 0) a2++; void sfxKill3DSound(DBloodActor* pActor, int a2, int a3)
auto sid = soundEngine->FindSoundByResID(a3); {
soundEngine->EnumerateChannels([=](FSoundChan* channel) if (!pActor)
{ return;
if (channel->SourceType == SOURCE_Actor && channel->Source == pActor && (a2 < 0 || a2 == channel->EntChannel) && (a3 < 0 || sid == channel->OrgID))
{ if (a2 >= 0) a2++;
soundEngine->StopChannel(channel); auto sid = soundEngine->FindSoundByResID(a3);
} soundEngine->EnumerateChannels([=](FSoundChan* channel)
return false; {
}); if (channel->SourceType == SOURCE_Actor && channel->Source == pActor && (a2 < 0 || a2 == channel->EntChannel) && (a3 < 0 || sid == channel->OrgID))
{
soundEngine->StopChannel(channel);
}
return false;
});
} }
void sfxKillAllSounds(void) void sfxKillAllSounds(void)
{ {
soundEngine->EnumerateChannels([](FSoundChan* channel) soundEngine->EnumerateChannels([](FSoundChan* channel)
{ {
if (channel->SourceType == SOURCE_Actor || channel->SourceType == SOURCE_Unattached) soundEngine->StopChannel(channel); if (channel->SourceType == SOURCE_Actor || channel->SourceType == SOURCE_Unattached) soundEngine->StopChannel(channel);
return false; return false;
}); });
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void sfxSetReverb(bool toggle) void sfxSetReverb(bool toggle)
{ {
if (toggle) if (toggle)
{ {
FX_SetReverb(128); FX_SetReverb(128);
FX_SetReverbDelay(10); FX_SetReverbDelay(10);
} }
else else
FX_SetReverb(0); FX_SetReverb(0);
} }
void sfxSetReverb2(bool toggle) void sfxSetReverb2(bool toggle)
{ {
if (toggle) if (toggle)
{ {
FX_SetReverb(128); FX_SetReverb(128);
FX_SetReverbDelay(20); FX_SetReverbDelay(20);
} }
else else
FX_SetReverb(0); FX_SetReverb(0);
} }
END_BLD_NS END_BLD_NS

View file

@ -31,30 +31,30 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
int soundRates[13] = { int soundRates[13] = {
11025, 11025,
11025, 11025,
11025, 11025,
11025, 11025,
11025, 11025,
22050, 22050,
22050, 22050,
22050, 22050,
22050, 22050,
44100, 44100,
44100, 44100,
44100, 44100,
44100, 44100,
}; };
void ByteSwapSFX(SFX* pSFX) void ByteSwapSFX(SFX* pSFX)
{ {
#if WORDS_BIGENDIAN #if WORDS_BIGENDIAN
pSFX->relVol = LittleLong(pSFX->relVol); pSFX->relVol = LittleLong(pSFX->relVol);
pSFX->pitch = LittleLong(pSFX->pitch); pSFX->pitch = LittleLong(pSFX->pitch);
pSFX->pitchRange = LittleLong(pSFX->pitchRange); pSFX->pitchRange = LittleLong(pSFX->pitchRange);
pSFX->format = LittleLong(pSFX->format); pSFX->format = LittleLong(pSFX->format);
pSFX->loopStart = LittleLong(pSFX->loopStart); pSFX->loopStart = LittleLong(pSFX->loopStart);
#endif #endif
} }
@ -69,137 +69,156 @@ void ByteSwapSFX(SFX* pSFX)
static void S_AddBloodSFX(int lumpnum) static void S_AddBloodSFX(int lumpnum)
{ {
auto sfxlump = fileSystem.ReadFile(lumpnum); auto sfxlump = fileSystem.ReadFile(lumpnum);
SFX* sfx = (SFX*)sfxlump.GetMem(); SFX* sfx = (SFX*)sfxlump.GetMem();
ByteSwapSFX(sfx); ByteSwapSFX(sfx);
FStringf rawname("%s.raw", sfx->rawName); FStringf rawname("%s.raw", sfx->rawName);
auto rawlump = fileSystem.FindFile(rawname); auto rawlump = fileSystem.FindFile(rawname);
int sfxnum; int sfxnum;
if (rawlump != -1) if (rawlump != -1)
{ {
auto& S_sfx = soundEngine->GetSounds(); auto& S_sfx = soundEngine->GetSounds();
sfxnum = soundEngine->AddSoundLump(sfx->rawName, rawlump, 0, fileSystem.GetResourceId(lumpnum), 6); sfxnum = soundEngine->AddSoundLump(sfx->rawName, rawlump, 0, fileSystem.GetResourceId(lumpnum), 6);
if (sfx->format < 5 || sfx->format > 12) if (sfx->format < 5 || sfx->format > 12)
{ // [0..4] + invalid formats { // [0..4] + invalid formats
S_sfx[sfxnum].RawRate = 11025; S_sfx[sfxnum].RawRate = 11025;
} }
else if (sfx->format < 9) else if (sfx->format < 9)
{ // [5..8] { // [5..8]
S_sfx[sfxnum].RawRate = 22050; S_sfx[sfxnum].RawRate = 22050;
} }
else else
{ // [9..12] { // [9..12]
S_sfx[sfxnum].RawRate = 44100; S_sfx[sfxnum].RawRate = 44100;
} }
S_sfx[sfxnum].bLoadRAW = true; S_sfx[sfxnum].bLoadRAW = true;
S_sfx[sfxnum].LoopStart = LittleLong(sfx->loopStart); S_sfx[sfxnum].LoopStart = LittleLong(sfx->loopStart);
//S_sfx[sfxnum].Volume = sfx->relVol / 255.f; This cannot be done because this volume setting is optional. //S_sfx[sfxnum].Volume = sfx->relVol / 255.f; This cannot be done because this volume setting is optional.
S_sfx[sfxnum].UserData.Resize(3); S_sfx[sfxnum].UserData.Resize(3);
int* udata = (int*)S_sfx[sfxnum].UserData.Data(); int* udata = (int*)S_sfx[sfxnum].UserData.Data();
udata[0] = sfx->pitch; udata[0] = sfx->pitch;
udata[1] = sfx->pitchRange; udata[1] = sfx->pitchRange;
udata[2] = sfx->relVol; udata[2] = sfx->relVol;
} }
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void sndInit(void) void sndInit(void)
{ {
soundEngine = new BloodSoundEngine; soundEngine = new BloodSoundEngine;
soundEngine->AddSoundLump("", 0, 0, -1, 6); // add a dummy entry at index #0 soundEngine->AddSoundLump("", 0, 0, -1, 6); // add a dummy entry at index #0
for (int i = fileSystem.GetNumEntries() - 1; i >= 0; i--) for (int i = fileSystem.GetNumEntries() - 1; i >= 0; i--)
{ {
auto type = fileSystem.GetResourceType(i); auto type = fileSystem.GetResourceType(i);
if (!stricmp(type, "SFX")) if (!stricmp(type, "SFX"))
{ {
if (soundEngine->FindSoundByResID(fileSystem.GetResourceId(i)) == 0) if (soundEngine->FindSoundByResID(fileSystem.GetResourceId(i)) == 0)
S_AddBloodSFX(i); S_AddBloodSFX(i);
} }
else if (!stricmp(type, "WAV") || !stricmp(type, "OGG") || !stricmp(type, "FLAC") || !stricmp(type, "VOC")) else if (!stricmp(type, "WAV") || !stricmp(type, "OGG") || !stricmp(type, "FLAC") || !stricmp(type, "VOC"))
{ {
if (fileSystem.GetFileNamespace(i) != ns_music) if (fileSystem.GetFileNamespace(i) != ns_music)
soundEngine->AddSoundLump(fileSystem.GetFileFullName(i), i, 0, fileSystem.GetResourceId(i)| 0x40000000, 6); // mark the resource ID as special. soundEngine->AddSoundLump(fileSystem.GetFileFullName(i), i, 0, fileSystem.GetResourceId(i) | 0x40000000, 6); // mark the resource ID as special.
} }
} }
soundEngine->HashSounds(); soundEngine->HashSounds();
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
int sndGetRate(int format) int sndGetRate(int format)
{ {
if (format < 13) if (format < 13)
return soundRates[format]; return soundRates[format];
return 11025; return 11025;
} }
bool sndCheckPlaying(unsigned int nSound) bool sndCheckPlaying(unsigned int nSound)
{ {
auto snd = soundEngine->FindSoundByResID(nSound); auto snd = soundEngine->FindSoundByResID(nSound);
return snd > 0 ? soundEngine->GetSoundPlayingInfo(SOURCE_Any, nullptr, snd) : false; return snd > 0 ? soundEngine->GetSoundPlayingInfo(SOURCE_Any, nullptr, snd) : false;
} }
void sndStopSample(unsigned int nSound) void sndStopSample(unsigned int nSound)
{ {
auto snd = soundEngine->FindSoundByResID(nSound); auto snd = soundEngine->FindSoundByResID(nSound);
if (snd > 0) if (snd > 0)
{ {
soundEngine->StopSoundID(snd); soundEngine->StopSoundID(snd);
} }
} }
void sndStartSample(const char *pzSound, int nVolume, int nChannel) //---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void sndStartSample(const char* pzSound, int nVolume, int nChannel)
{ {
if (!SoundEnabled()) if (!SoundEnabled())
return; return;
if (!strlen(pzSound)) if (!strlen(pzSound))
return; return;
auto snd = soundEngine->FindSound(pzSound); auto snd = soundEngine->FindSound(pzSound);
if (snd > 0) if (snd > 0)
{ {
soundEngine->StartSound(SOURCE_None, nullptr, nullptr, nChannel + 1, 0, snd, nVolume / 255.f, ATTN_NONE); soundEngine->StartSound(SOURCE_None, nullptr, nullptr, nChannel + 1, 0, snd, nVolume / 255.f, ATTN_NONE);
} }
} }
void sndStartSample(unsigned int nSound, int nVolume, int nChannel, bool bLoop, EChanFlags chanflags) void sndStartSample(unsigned int nSound, int nVolume, int nChannel, bool bLoop, EChanFlags chanflags)
{ {
if (!SoundEnabled()) if (!SoundEnabled())
return; return;
if (nChannel >= 7) nChannel = -1; if (nChannel >= 7) nChannel = -1;
auto snd = soundEngine->FindSoundByResID(nSound); auto snd = soundEngine->FindSoundByResID(nSound);
if (snd > 0) if (snd > 0)
{ {
if (nVolume < 0) if (nVolume < 0)
{ {
auto udata = soundEngine->GetUserData(snd); auto udata = soundEngine->GetUserData(snd);
if (udata) nVolume = min(Scale(udata[2], 255, 100), 255); if (udata) nVolume = min(Scale(udata[2], 255, 100), 255);
else nVolume = 255; else nVolume = 255;
} }
if (bLoop) chanflags |= CHANF_LOOP; if (bLoop) chanflags |= CHANF_LOOP;
soundEngine->StopActorSounds(SOURCE_None, nullptr, nChannel + 1, nChannel + 1); soundEngine->StopActorSounds(SOURCE_None, nullptr, nChannel + 1, nChannel + 1);
soundEngine->StartSound(SOURCE_None, nullptr, nullptr, (nChannel + 1), chanflags, snd, nVolume / 255.f, ATTN_NONE); soundEngine->StartSound(SOURCE_None, nullptr, nullptr, (nChannel + 1), chanflags, snd, nVolume / 255.f, ATTN_NONE);
} }
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void sndStartWavID(unsigned int nSound, int nVolume, int nChannel) void sndStartWavID(unsigned int nSound, int nVolume, int nChannel)
{ {
return sndStartSample(nSound | 0x40000000, nVolume, nChannel); return sndStartSample(nSound | 0x40000000, nVolume, nChannel);
} }
void sndStartWavDisk(const char *pzFile, int nVolume, int nChannel) void sndStartWavDisk(const char* pzFile, int nVolume, int nChannel)
{ {
FString name = pzFile; FString name = pzFile;
FixPathSeperator(name); FixPathSeperator(name);
return sndStartSample(name, nVolume, nChannel); return sndStartSample(name, nVolume, nChannel);
} }
void sndKillAllSounds(void) void sndKillAllSounds(void)
{ {
soundEngine->StopSound(CHAN_AUTO); soundEngine->StopSound(CHAN_AUTO);
} }

View file

@ -30,30 +30,30 @@ BEGIN_BLD_NS
struct SFX struct SFX
{ {
int relVol; int relVol;
int pitch; int pitch;
int pitchRange; int pitchRange;
int format; int format;
int loopStart; int loopStart;
char rawName[9]; char rawName[9];
}; };
int sndGetRate(int format); int sndGetRate(int format);
bool sndCheckPlaying(unsigned int nSound); bool sndCheckPlaying(unsigned int nSound);
void sndStopSample(unsigned int nSound); void sndStopSample(unsigned int nSound);
void sndStartSample(const char *pzSound, int nVolume, int nChannel = -1); void sndStartSample(const char* pzSound, int nVolume, int nChannel = -1);
void sndStartSample(unsigned int nSound, int nVolume, int nChannel = -1, bool bLoop = false, EChanFlags soundflags = CHANF_NONE); void sndStartSample(unsigned int nSound, int nVolume, int nChannel = -1, bool bLoop = false, EChanFlags soundflags = CHANF_NONE);
void sndStartWavID(unsigned int nSound, int nVolume, int nChannel = -1); void sndStartWavID(unsigned int nSound, int nVolume, int nChannel = -1);
void sndStartWavDisk(const char *pzFile, int nVolume, int nChannel = -1); void sndStartWavDisk(const char* pzFile, int nVolume, int nChannel = -1);
void sndKillAllSounds(void); void sndKillAllSounds(void);
void sndProcess(void); void sndProcess(void);
void sndTerm(void); void sndTerm(void);
void sndInit(void); void sndInit(void);
void sfxPlay3DSound(int x, int y, int z, int soundId, sectortype* pSector); void sfxPlay3DSound(int x, int y, int z, int soundId, sectortype* pSector);
void sfxPlay3DSound(DBloodActor *pSprite, int soundId, int a3 = -1, int a4 = 0); void sfxPlay3DSound(DBloodActor* pSprite, int soundId, int a3 = -1, int a4 = 0);
void sfxPlay3DSoundCP(DBloodActor* pSprite, int soundId, int a3 = -1, int a4 = 0, int pitch = 0, int volume = 0); void sfxPlay3DSoundCP(DBloodActor* pSprite, int soundId, int a3 = -1, int a4 = 0, int pitch = 0, int volume = 0);
void sfxKill3DSound(DBloodActor *pSprite, int a2 = -1, int a3 = -1); void sfxKill3DSound(DBloodActor* pSprite, int a2 = -1, int a3 = -1);
void sfxKillAllSounds(void); void sfxKillAllSounds(void);
void sfxSetReverb(bool toggle); void sfxSetReverb(bool toggle);
void sfxSetReverb2(bool toggle); void sfxSetReverb2(bool toggle);
@ -64,9 +64,9 @@ void ambInit(void);
enum EPlayFlags enum EPlayFlags
{ {
FX_GlobalChannel = 1, FX_GlobalChannel = 1,
FX_SoundMatch = 2, FX_SoundMatch = 2,
FX_ChannelMatch = 4, FX_ChannelMatch = 4,
}; };

View file

@ -42,6 +42,12 @@ uint8_t surfType[kMaxTiles];
int8_t tileShade[kMaxTiles]; int8_t tileShade[kMaxTiles];
short voxelIndex[kMaxTiles]; short voxelIndex[kMaxTiles];
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void GameInterface::LoadGameTextures() void GameInterface::LoadGameTextures()
{ {
auto hFile = fileSystem.OpenFileReader("SURFACE.DAT"); auto hFile = fileSystem.OpenFileReader("SURFACE.DAT");
@ -70,6 +76,12 @@ void GameInterface::LoadGameTextures()
} }
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
int tileGetSurfType(int hit) int tileGetSurfType(int hit)
{ {
return surfType[hit]; return surfType[hit];
@ -90,6 +102,12 @@ int tileGetSurfType(CollisionBase& hit)
} }
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void GameInterface::SetTileProps(int tile, int surf, int vox, int shade) void GameInterface::SetTileProps(int tile, int surf, int vox, int shade)
{ {
if (surf != INT_MAX) surfType[tile] = surf; if (surf != INT_MAX) surfType[tile] = surf;

View file

@ -31,24 +31,24 @@ int OctantTable[8] = { 5, 6, 2, 1, 4, 7, 3, 0 };
int GetOctant(int x, int y) int GetOctant(int x, int y)
{ {
int vc = abs(x)-abs(y); int vc = abs(x) - abs(y);
return OctantTable[7-(x<0)-(y<0)*2-(vc<0)*4]; return OctantTable[7 - (x < 0) - (y < 0) * 2 - (vc < 0) * 4];
} }
void RotateVector(int *dx, int *dy, int nAngle) void RotateVector(int* dx, int* dy, int nAngle)
{ {
int ox = *dx; int ox = *dx;
int oy = *dy; int oy = *dy;
*dx = dmulscale30r(ox, Cos(nAngle), -oy, Sin(nAngle)); *dx = dmulscale30r(ox, Cos(nAngle), -oy, Sin(nAngle));
*dy = dmulscale30r(ox, Sin(nAngle), oy, Cos(nAngle)); *dy = dmulscale30r(ox, Sin(nAngle), oy, Cos(nAngle));
} }
void RotatePoint(int *x, int *y, int nAngle, int ox, int oy) void RotatePoint(int* x, int* y, int nAngle, int ox, int oy)
{ {
int dx = *x-ox; int dx = *x - ox;
int dy = *y-oy; int dy = *y - oy;
*x = ox+dmulscale30r(dx, Cos(nAngle), -dy, Sin(nAngle)); *x = ox + dmulscale30r(dx, Cos(nAngle), -dy, Sin(nAngle));
*y = oy+dmulscale30r(dx, Sin(nAngle), dy, Cos(nAngle)); *y = oy + dmulscale30r(dx, Sin(nAngle), dy, Cos(nAngle));
} }
END_BLD_NS END_BLD_NS

File diff suppressed because it is too large Load diff

View file

@ -32,26 +32,26 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
enum BUSYID { enum BUSYID {
BUSYID_0 = 0, BUSYID_0 = 0,
BUSYID_1, BUSYID_1,
BUSYID_2, BUSYID_2,
BUSYID_3, BUSYID_3,
BUSYID_4, BUSYID_4,
BUSYID_5, BUSYID_5,
BUSYID_6, BUSYID_6,
BUSYID_7, BUSYID_7,
}; };
struct BUSY { struct BUSY {
sectortype* sect; sectortype* sect;
int delta; int delta;
int busy; int busy;
int/*BUSYID*/ type; int/*BUSYID*/ type;
}; };
extern TArray<BUSY> gBusy; extern TArray<BUSY> gBusy;
void trTriggerSector(sectortype *pSector, int command); void trTriggerSector(sectortype* pSector, int command);
void trMessageSector(sectortype* pSector, EVENT event); void trMessageSector(sectortype* pSector, EVENT event);
void trTriggerWall(walltype*, int command); void trTriggerWall(walltype*, int command);
void trMessageWall(walltype* pWall, EVENT& event); void trMessageWall(walltype* pWall, EVENT& event);

File diff suppressed because it is too large Load diff

View file

@ -32,46 +32,46 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_BLD_NS BEGIN_BLD_NS
struct VIEW { struct VIEW {
int bobPhase; int bobPhase;
int Kills; int Kills;
int bobHeight; // bob height int bobHeight; // bob height
int bobWidth; // bob width int bobWidth; // bob width
int at10; int at10;
int at14; int at14;
int shakeBobY; // bob sway y int shakeBobY; // bob sway y
int shakeBobX; // bob sway x int shakeBobX; // bob sway x
fixedhoriz horiz; // horiz fixedhoriz horiz; // horiz
fixedhoriz horizoff; // horizoff fixedhoriz horizoff; // horizoff
int at2c; int at2c;
binangle angle; // angle binangle angle; // angle
int weaponZ; // weapon z int weaponZ; // weapon z
int viewz; // view z int viewz; // view z
int at3c; int at3c;
int at40; int at40;
int at44; int at44;
int at48; // posture int at48; // posture
double spin; // spin double spin; // spin
union { union {
struct struct
{ {
int32_t x, y, z; int32_t x, y, z;
}; };
vec3_t pos; vec3_t pos;
}; };
int xvel; //xvel int xvel; //xvel
int yvel; //yvel int yvel; //yvel
int zvel; //zvel int zvel; //zvel
int sectnum; // sectnum int sectnum; // sectnum
unsigned int floordist; // floordist unsigned int floordist; // floordist
uint8_t at6e; // look center uint8_t at6e; // look center
uint8_t at6f; uint8_t at6f;
uint8_t at70; // run uint8_t at70; // run
uint8_t at71; // jump uint8_t at71; // jump
uint8_t at72; // underwater uint8_t at72; // underwater
int16_t at73; // sprite flags int16_t at73; // sprite flags
SPRITEHIT at75; SPRITEHIT at75;
binangle look_ang; binangle look_ang;
binangle rotscrnang; binangle rotscrnang;
}; };
extern VIEW gPrevView[kMaxPlayers]; extern VIEW gPrevView[kMaxPlayers];
@ -80,55 +80,55 @@ extern VIEW predict, predictOld;
extern bool gPrediction; extern bool gPrediction;
enum VIEW_EFFECT { enum VIEW_EFFECT {
kViewEffectShadow = 0, kViewEffectShadow = 0,
kViewEffectFlareHalo, kViewEffectFlareHalo,
kViewEffectCeilGlow, kViewEffectCeilGlow,
kViewEffectFloorGlow, kViewEffectFloorGlow,
kViewEffectTorchHigh, kViewEffectTorchHigh,
kViewEffectTorchLow, kViewEffectTorchLow,
kViewEffectSmokeHigh, kViewEffectSmokeHigh,
kViewEffectSmokeLow, kViewEffectSmokeLow,
kViewEffectFlame, kViewEffectFlame,
kViewEffectSpear, kViewEffectSpear,
kViewEffectTrail, kViewEffectTrail,
kViewEffectPhase, kViewEffectPhase,
kViewEffectShowWeapon, kViewEffectShowWeapon,
kViewEffectReflectiveBall, kViewEffectReflectiveBall,
kViewEffectShoot, kViewEffectShoot,
kViewEffectTesla, kViewEffectTesla,
kViewEffectFlag, kViewEffectFlag,
kViewEffectBigFlag, kViewEffectBigFlag,
kViewEffectAtom, kViewEffectAtom,
kViewEffectSpotProgress, kViewEffectSpotProgress,
}; };
enum VIEWPOS { enum VIEWPOS {
VIEWPOS_0 = 0, VIEWPOS_0 = 0,
VIEWPOS_1 VIEWPOS_1
}; };
enum enum
{ {
kBackTile = 253, kBackTile = 253,
kCrosshairTile = 2319, kCrosshairTile = 2319,
kLoadScreen = 2049, kLoadScreen = 2049,
kLoadScreenWideBack = 9216, kLoadScreenWideBack = 9216,
kLoadScreenWideLeft = 9217, kLoadScreenWideLeft = 9217,
kLoadScreenWideRight = 9218, kLoadScreenWideRight = 9218,
kLoadScreenWideMiddle = 9219, kLoadScreenWideMiddle = 9219,
kSBarNumberHealth = 9220, kSBarNumberHealth = 9220,
kSBarNumberAmmo = 9230, kSBarNumberAmmo = 9230,
kSBarNumberInv = 9240, kSBarNumberInv = 9240,
kSBarNumberArmor1 = 9250, kSBarNumberArmor1 = 9250,
kSBarNumberArmor2 = 9260, kSBarNumberArmor2 = 9260,
kSBarNumberArmor3 = 9270, kSBarNumberArmor3 = 9270,
}; };
enum { kFontNum = 5 }; enum { kFontNum = 5 };
extern FFont *gFont[kFontNum]; extern FFont* gFont[kFontNum];
extern VIEWPOS gViewPos; extern VIEWPOS gViewPos;
extern int gViewIndex; extern int gViewIndex;
extern int gScreenTilt; extern int gScreenTilt;
@ -140,44 +140,44 @@ extern double gInterpolate;
void hudDraw(PLAYER* gView, sectortype* pSector, double bobx, double boby, double zDelta, int basepal, double smoothratio); void hudDraw(PLAYER* gView, sectortype* pSector, double bobx, double boby, double zDelta, int basepal, double smoothratio);
void viewInitializePrediction(void); void viewInitializePrediction(void);
void viewUpdatePrediction(InputPacket *pInput); void viewUpdatePrediction(InputPacket* pInput);
void viewCorrectPrediction(void); void viewCorrectPrediction(void);
void viewBackupView(int nPlayer); void viewBackupView(int nPlayer);
void viewCorrectViewOffsets(int nPlayer, vec3_t const *oldpos); void viewCorrectViewOffsets(int nPlayer, vec3_t const* oldpos);
void InitStatusBar(void); void InitStatusBar(void);
void UpdateStatusBar(); void UpdateStatusBar();
void viewInit(void); void viewInit(void);
void viewprocessSprites(tspritetype* tsprite, int& spritesortcnt, int32_t cX, int32_t cY, int32_t cZ, int32_t cA, int32_t smooth); void viewprocessSprites(tspritetype* tsprite, int& spritesortcnt, int32_t cX, int32_t cY, int32_t cZ, int32_t cA, int32_t smooth);
void viewSetMessage(const char *pMessage, const int pal = 0, const MESSAGE_PRIORITY priority = MESSAGE_PRIORITY_NORMAL); void viewSetMessage(const char* pMessage, const int pal = 0, const MESSAGE_PRIORITY priority = MESSAGE_PRIORITY_NORMAL);
void viewSetErrorMessage(const char *pMessage); void viewSetErrorMessage(const char* pMessage);
void DoLensEffect(void); void DoLensEffect(void);
void UpdateDacs(int nPalette, bool bNoTint = false); void UpdateDacs(int nPalette, bool bNoTint = false);
void viewDrawScreen(bool sceneonly = false); void viewDrawScreen(bool sceneonly = false);
void viewUpdateDelirium(void); void viewUpdateDelirium(void);
void viewSetSystemMessage(const char* pMessage, ...); void viewSetSystemMessage(const char* pMessage, ...);
inline void viewInterpolateSector(sectortype *pSector) inline void viewInterpolateSector(sectortype* pSector)
{ {
StartInterpolation(pSector, Interp_Sect_Floorz); StartInterpolation(pSector, Interp_Sect_Floorz);
StartInterpolation(pSector, Interp_Sect_Ceilingz); StartInterpolation(pSector, Interp_Sect_Ceilingz);
StartInterpolation(pSector, Interp_Sect_Floorheinum); StartInterpolation(pSector, Interp_Sect_Floorheinum);
} }
inline void viewInterpolateWall(walltype *pWall) inline void viewInterpolateWall(walltype* pWall)
{ {
StartInterpolation(pWall, Interp_Wall_X); StartInterpolation(pWall, Interp_Wall_X);
StartInterpolation(pWall, Interp_Wall_Y); StartInterpolation(pWall, Interp_Wall_Y);
} }
inline void viewBackupSpriteLoc(DBloodActor* actor) inline void viewBackupSpriteLoc(DBloodActor* actor)
{ {
if (!actor->interpolated) if (!actor->interpolated)
{ {
actor->spr.backuploc(); actor->spr.backuploc();
actor->interpolated = true; actor->interpolated = true;
} }
} }

View file

@ -30,268 +30,293 @@ BEGIN_BLD_NS
ZONE gStartZone[8]; ZONE gStartZone[8];
#ifdef NOONE_EXTENSIONS #ifdef NOONE_EXTENSIONS
ZONE gStartZoneTeam1[8]; ZONE gStartZoneTeam1[8];
ZONE gStartZoneTeam2[8]; ZONE gStartZoneTeam2[8];
bool gTeamsSpawnUsed = false; bool gTeamsSpawnUsed = false;
#endif #endif
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void validateLinks() void validateLinks()
{ {
int snum = 0; int snum = 0;
for (auto& sect: sector) for (auto& sect : sector)
{ {
DCoreActor* upper = sect.upperLink; DCoreActor* upper = sect.upperLink;
if (upper && !static_cast<DBloodActor*>(upper)->GetOwner()) if (upper && !static_cast<DBloodActor*>(upper)->GetOwner())
{ {
Printf(PRINT_HIGH, "Unpartnered upper link in sector %d\n", snum); Printf(PRINT_HIGH, "Unpartnered upper link in sector %d\n", snum);
sect.upperLink = nullptr; sect.upperLink = nullptr;
} }
DCoreActor* lower = sect.lowerLink; DCoreActor* lower = sect.lowerLink;
if (lower && !static_cast<DBloodActor*>(lower)->GetOwner()) if (lower && !static_cast<DBloodActor*>(lower)->GetOwner())
{ {
Printf(PRINT_HIGH, "Unpartnered lower link in sector %d\n", snum); Printf(PRINT_HIGH, "Unpartnered lower link in sector %d\n", snum);
sect.lowerLink = nullptr; sect.lowerLink = nullptr;
} }
snum++; snum++;
} }
} }
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void warpInit(TArray<DBloodActor*>& actors) void warpInit(TArray<DBloodActor*>& actors)
{ {
#ifdef NOONE_EXTENSIONS #ifdef NOONE_EXTENSIONS
int team1 = 0; int team2 = 0; gTeamsSpawnUsed = false; // increment if team start positions specified. int team1 = 0; int team2 = 0; gTeamsSpawnUsed = false; // increment if team start positions specified.
#endif #endif
for(auto actor : actors) for (auto actor : actors)
{ {
if (!actor->exists()) continue; if (!actor->exists()) continue;
if (actor->hasX()) { if (actor->hasX()) {
switch (actor->spr.type) { switch (actor->spr.type) {
case kMarkerSPStart: case kMarkerSPStart:
if (gGameOptions.nGameType < 2 && actor->xspr.data1 >= 0 && actor->xspr.data1 < kMaxPlayers) { if (gGameOptions.nGameType < 2 && actor->xspr.data1 >= 0 && actor->xspr.data1 < kMaxPlayers) {
ZONE *pZone = &gStartZone[actor->xspr.data1]; ZONE* pZone = &gStartZone[actor->xspr.data1];
pZone->x = actor->spr.pos.X; pZone->x = actor->spr.pos.X;
pZone->y = actor->spr.pos.Y; pZone->y = actor->spr.pos.Y;
pZone->z = actor->spr.pos.Z; pZone->z = actor->spr.pos.Z;
pZone->sector = actor->spr.sector(); pZone->sector = actor->spr.sector();
pZone->ang = actor->spr.ang; pZone->ang = actor->spr.ang;
} }
DeleteSprite(actor); DeleteSprite(actor);
break; break;
case kMarkerMPStart: case kMarkerMPStart:
if (actor->xspr.data1 >= 0 && actor->xspr.data2 < kMaxPlayers) { if (actor->xspr.data1 >= 0 && actor->xspr.data2 < kMaxPlayers) {
if (gGameOptions.nGameType >= 2) { if (gGameOptions.nGameType >= 2) {
// default if BB or teams without data2 specified // default if BB or teams without data2 specified
ZONE* pZone = &gStartZone[actor->xspr.data1]; ZONE* pZone = &gStartZone[actor->xspr.data1];
pZone->x = actor->spr.pos.X; pZone->x = actor->spr.pos.X;
pZone->y = actor->spr.pos.Y; pZone->y = actor->spr.pos.Y;
pZone->z = actor->spr.pos.Z; pZone->z = actor->spr.pos.Z;
pZone->sector = actor->spr.sector(); pZone->sector = actor->spr.sector();
pZone->ang = actor->spr.ang; pZone->ang = actor->spr.ang;
#ifdef NOONE_EXTENSIONS
// fill player spawn position according team of player in TEAMS mode.
if (gModernMap && gGameOptions.nGameType == 3) {
if (actor->xspr.data2 == 1) {
pZone = &gStartZoneTeam1[team1];
pZone->x = actor->spr.pos.X;
pZone->y = actor->spr.pos.Y;
pZone->z = actor->spr.pos.Z;
pZone->sector = actor->spr.sector();
pZone->ang = actor->spr.ang;
team1++;
} else if (actor->xspr.data2 == 2) { #ifdef NOONE_EXTENSIONS
pZone = &gStartZoneTeam2[team2]; // fill player spawn position according team of player in TEAMS mode.
pZone->x = actor->spr.pos.X; if (gModernMap && gGameOptions.nGameType == 3) {
pZone->y = actor->spr.pos.Y; if (actor->xspr.data2 == 1) {
pZone->z = actor->spr.pos.Z; pZone = &gStartZoneTeam1[team1];
pZone->sector = actor->spr.sector(); pZone->x = actor->spr.pos.X;
pZone->ang = actor->spr.ang; pZone->y = actor->spr.pos.Y;
team2++; pZone->z = actor->spr.pos.Z;
} pZone->sector = actor->spr.sector();
} pZone->ang = actor->spr.ang;
#endif team1++;
} }
DeleteSprite(actor); else if (actor->xspr.data2 == 2) {
} pZone = &gStartZoneTeam2[team2];
break; pZone->x = actor->spr.pos.X;
case kMarkerUpLink: pZone->y = actor->spr.pos.Y;
actor->spr.sector()->upperLink = actor; pZone->z = actor->spr.pos.Z;
actor->spr.cstat |= CSTAT_SPRITE_INVISIBLE; pZone->sector = actor->spr.sector();
actor->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL; pZone->ang = actor->spr.ang;
break; team2++;
case kMarkerLowLink: }
actor->spr.sector()->lowerLink = actor; }
actor->spr.cstat |= CSTAT_SPRITE_INVISIBLE; #endif
actor->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL;
break;
case kMarkerUpWater:
case kMarkerUpStack:
case kMarkerUpGoo:
actor->spr.sector()->upperLink = actor;
actor->spr.cstat |= CSTAT_SPRITE_INVISIBLE;
actor->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL;
actor->spr.pos.Z = getflorzofslopeptr(actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y);
break;
case kMarkerLowWater:
case kMarkerLowStack:
case kMarkerLowGoo:
actor->spr.sector()->lowerLink = actor;
actor->spr.cstat |= CSTAT_SPRITE_INVISIBLE;
actor->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL;
actor->spr.pos.Z = getceilzofslopeptr(actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y);
break;
}
}
}
#ifdef NOONE_EXTENSIONS
// check if there is enough start positions for teams, if any used
if (team1 > 0 || team2 > 0) {
gTeamsSpawnUsed = true;
if (team1 < kMaxPlayers / 2 || team2 < kMaxPlayers / 2) {
viewSetSystemMessage("At least 4 spawn positions for each team is recommended.");
viewSetSystemMessage("Team A positions: %d, Team B positions: %d.", team1, team2);
}
}
#endif
for(auto& sect: sector) }
{ DeleteSprite(actor);
auto actor = barrier_cast<DBloodActor*>(sect.upperLink); }
if (actor && actor->hasX()) break;
{ case kMarkerUpLink:
int nLink = actor->xspr.data1; actor->spr.sector()->upperLink = actor;
for(auto& isect: sector) actor->spr.cstat |= CSTAT_SPRITE_INVISIBLE;
{ actor->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL;
auto actor2 = barrier_cast<DBloodActor*>(isect.lowerLink); break;
if (actor2 && actor2->hasX()) case kMarkerLowLink:
{ actor->spr.sector()->lowerLink = actor;
if (actor2->xspr.data1 == nLink) actor->spr.cstat |= CSTAT_SPRITE_INVISIBLE;
{ actor->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL;
actor->SetOwner(actor2); break;
actor2->SetOwner(actor); case kMarkerUpWater:
} case kMarkerUpStack:
} case kMarkerUpGoo:
} actor->spr.sector()->upperLink = actor;
} actor->spr.cstat |= CSTAT_SPRITE_INVISIBLE;
} actor->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL;
actor->spr.pos.Z = getflorzofslopeptr(actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y);
break;
case kMarkerLowWater:
case kMarkerLowStack:
case kMarkerLowGoo:
actor->spr.sector()->lowerLink = actor;
actor->spr.cstat |= CSTAT_SPRITE_INVISIBLE;
actor->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL;
actor->spr.pos.Z = getceilzofslopeptr(actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y);
break;
}
}
}
#ifdef NOONE_EXTENSIONS
// check if there is enough start positions for teams, if any used
if (team1 > 0 || team2 > 0) {
gTeamsSpawnUsed = true;
if (team1 < kMaxPlayers / 2 || team2 < kMaxPlayers / 2) {
viewSetSystemMessage("At least 4 spawn positions for each team is recommended.");
viewSetSystemMessage("Team A positions: %d, Team B positions: %d.", team1, team2);
}
}
#endif
for (auto& sect : sector)
{
auto actor = barrier_cast<DBloodActor*>(sect.upperLink);
if (actor && actor->hasX())
{
int nLink = actor->xspr.data1;
for (auto& isect : sector)
{
auto actor2 = barrier_cast<DBloodActor*>(isect.lowerLink);
if (actor2 && actor2->hasX())
{
if (actor2->xspr.data1 == nLink)
{
actor->SetOwner(actor2);
actor2->SetOwner(actor);
}
}
}
}
}
validateLinks(); validateLinks();
} }
int CheckLink(DBloodActor *actor) //---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
int CheckLink(DBloodActor* actor)
{ {
auto pSector = actor->spr.sector(); auto pSector = actor->spr.sector();
auto aUpper = barrier_cast<DBloodActor*>(pSector->upperLink); auto aUpper = barrier_cast<DBloodActor*>(pSector->upperLink);
auto aLower = barrier_cast<DBloodActor*>(pSector->lowerLink); auto aLower = barrier_cast<DBloodActor*>(pSector->lowerLink);
if (aUpper) if (aUpper)
{ {
int z; int z;
if (aUpper->spr.type == kMarkerUpLink) if (aUpper->spr.type == kMarkerUpLink)
z = aUpper->spr.pos.Z; z = aUpper->spr.pos.Z;
else else
z = getflorzofslopeptr(actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y); z = getflorzofslopeptr(actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y);
if (z <= actor->spr.pos.Z) if (z <= actor->spr.pos.Z)
{ {
aLower = aUpper->GetOwner(); aLower = aUpper->GetOwner();
assert(aLower); assert(aLower);
assert(aLower->spr.insector()); assert(aLower->spr.insector());
ChangeActorSect(actor, aLower->spr.sector()); ChangeActorSect(actor, aLower->spr.sector());
actor->spr.pos.X += aLower->spr.pos.X - aUpper->spr.pos.X; actor->spr.pos.X += aLower->spr.pos.X - aUpper->spr.pos.X;
actor->spr.pos.Y += aLower->spr.pos.Y - aUpper->spr.pos.Y; actor->spr.pos.Y += aLower->spr.pos.Y - aUpper->spr.pos.Y;
int z2; int z2;
if (aLower->spr.type == kMarkerLowLink) if (aLower->spr.type == kMarkerLowLink)
z2 = aLower->spr.pos.Z; z2 = aLower->spr.pos.Z;
else else
z2 = getceilzofslopeptr(actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y); z2 = getceilzofslopeptr(actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y);
actor->spr.pos.Z += z2-z; actor->spr.pos.Z += z2 - z;
actor->interpolated = false; actor->interpolated = false;
return aUpper->spr.type; return aUpper->spr.type;
} }
} }
if (aLower) if (aLower)
{ {
int z; int z;
if (aLower->spr.type == kMarkerLowLink) if (aLower->spr.type == kMarkerLowLink)
z = aLower->spr.pos.Z; z = aLower->spr.pos.Z;
else else
z = getceilzofslopeptr(actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y); z = getceilzofslopeptr(actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y);
if (z >= actor->spr.pos.Z) if (z >= actor->spr.pos.Z)
{ {
aUpper = aLower->GetOwner(); aUpper = aLower->GetOwner();
assert(aUpper); assert(aUpper);
assert(aUpper->spr.insector()); assert(aUpper->spr.insector());
ChangeActorSect(actor, aUpper->spr.sector()); ChangeActorSect(actor, aUpper->spr.sector());
actor->spr.pos.X += aUpper->spr.pos.X - aLower->spr.pos.X; actor->spr.pos.X += aUpper->spr.pos.X - aLower->spr.pos.X;
actor->spr.pos.Y += aUpper->spr.pos.Y - aLower->spr.pos.Y; actor->spr.pos.Y += aUpper->spr.pos.Y - aLower->spr.pos.Y;
int z2; int z2;
if (aUpper->spr.type == kMarkerUpLink) if (aUpper->spr.type == kMarkerUpLink)
z2 = aUpper->spr.pos.Z; z2 = aUpper->spr.pos.Z;
else else
z2 = getflorzofslopeptr(actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y); z2 = getflorzofslopeptr(actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y);
actor->spr.pos.Z += z2-z; actor->spr.pos.Z += z2 - z;
actor->interpolated = false; actor->interpolated = false;
return aLower->spr.type; return aLower->spr.type;
} }
} }
return 0; return 0;
} }
int CheckLink(int *x, int *y, int *z, sectortype** pSector) //---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
int CheckLink(int* x, int* y, int* z, sectortype** pSector)
{ {
auto aUpper = barrier_cast<DBloodActor*>((*pSector)->upperLink); auto aUpper = barrier_cast<DBloodActor*>((*pSector)->upperLink);
auto aLower = barrier_cast<DBloodActor*>((*pSector)->lowerLink); auto aLower = barrier_cast<DBloodActor*>((*pSector)->lowerLink);
if (aUpper) if (aUpper)
{ {
int z1; int z1;
if (aUpper->spr.type == kMarkerUpLink) if (aUpper->spr.type == kMarkerUpLink)
z1 = aUpper->spr.pos.Z; z1 = aUpper->spr.pos.Z;
else else
z1 = getflorzofslopeptr(*pSector, *x, *y); z1 = getflorzofslopeptr(*pSector, *x, *y);
if (z1 <= *z) if (z1 <= *z)
{ {
aLower = aUpper->GetOwner(); aLower = aUpper->GetOwner();
assert(aLower); assert(aLower);
assert(aLower->spr.insector()); assert(aLower->spr.insector());
*pSector = aLower->spr.sector(); *pSector = aLower->spr.sector();
*x += aLower->spr.pos.X - aUpper->spr.pos.X; *x += aLower->spr.pos.X - aUpper->spr.pos.X;
*y += aLower->spr.pos.Y - aUpper->spr.pos.Y; *y += aLower->spr.pos.Y - aUpper->spr.pos.Y;
int z2; int z2;
if (aUpper->spr.type == kMarkerLowLink) if (aUpper->spr.type == kMarkerLowLink)
z2 = aLower->spr.pos.Z; z2 = aLower->spr.pos.Z;
else else
z2 = getceilzofslopeptr(*pSector, *x, *y); z2 = getceilzofslopeptr(*pSector, *x, *y);
*z += z2-z1; *z += z2 - z1;
return aUpper->spr.type; return aUpper->spr.type;
} }
} }
if (aLower) if (aLower)
{ {
int z1; int z1;
if (aLower->spr.type == kMarkerLowLink) if (aLower->spr.type == kMarkerLowLink)
z1 = aLower->spr.pos.Z; z1 = aLower->spr.pos.Z;
else else
z1 = getceilzofslopeptr(*pSector, *x, *y); z1 = getceilzofslopeptr(*pSector, *x, *y);
if (z1 >= *z) if (z1 >= *z)
{ {
aUpper = aLower->GetOwner(); aUpper = aLower->GetOwner();
assert(aUpper); assert(aUpper);
*pSector = aUpper->spr.sector(); *pSector = aUpper->spr.sector();
*x += aUpper->spr.pos.X - aLower->spr.pos.X; *x += aUpper->spr.pos.X - aLower->spr.pos.X;
*y += aUpper->spr.pos.Y - aLower->spr.pos.Y; *y += aUpper->spr.pos.Y - aLower->spr.pos.Y;
int z2; int z2;
if (aLower->spr.type == kMarkerUpLink) if (aLower->spr.type == kMarkerUpLink)
z2 = aUpper->spr.pos.Z; z2 = aUpper->spr.pos.Z;
else else
z2 = getflorzofslopeptr(*pSector, *x, *y); z2 = getflorzofslopeptr(*pSector, *x, *y);
*z += z2-z1; *z += z2 - z1;
return aLower->spr.type; return aLower->spr.type;
} }
} }
return 0; return 0;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

File diff suppressed because it is too large Load diff