mirror of
https://github.com/ZDoom/Raze.git
synced 2024-11-22 12:11:17 +00:00
- tabified the rest of Blood's code.
This commit is contained in:
parent
b7d095b943
commit
5061d5b37c
32 changed files with 18547 additions and 17165 deletions
|
@ -34,7 +34,7 @@ BEGIN_BLD_NS
|
|||
GAMEOPTIONS gGameOptions;
|
||||
|
||||
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;
|
||||
|
@ -42,216 +42,256 @@ MapRecord* gNextLevel;
|
|||
|
||||
char BloodIniFile[BMAX_PATH] = "BLOOD.INI";
|
||||
bool bINIOverride = false;
|
||||
IniFile *BloodINI;
|
||||
IniFile* BloodINI;
|
||||
|
||||
|
||||
void levelInitINI(const char *pzIni)
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void levelInitINI(const char* pzIni)
|
||||
{
|
||||
if (!fileSystem.FileExists(pzIni))
|
||||
I_Error("Initialization: %s does not exist", pzIni);
|
||||
BloodINI = new IniFile(pzIni);
|
||||
strncpy(BloodIniFile, pzIni, BMAX_PATH-1);
|
||||
I_Error("Initialization: %s does not exist", pzIni);
|
||||
BloodINI = new IniFile(pzIni);
|
||||
strncpy(BloodIniFile, pzIni, BMAX_PATH - 1);
|
||||
}
|
||||
|
||||
void CheckSectionAbend(const char *pzSection)
|
||||
void CheckSectionAbend(const char* pzSection)
|
||||
{
|
||||
if (!pzSection || !BloodINI->SectionExists(pzSection))
|
||||
I_Error("Section [%s] expected in BLOOD.INI", pzSection);
|
||||
if (!pzSection || !BloodINI->SectionExists(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))
|
||||
I_Error("Key %s expected in section [%s] of BLOOD.INI", pzKey, pzSection);
|
||||
if (!pzKey || !BloodINI->KeyExists(pzSection, pzKey))
|
||||
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)
|
||||
{
|
||||
char buffer[16];
|
||||
pLevelInfo->SetName(pIni->GetKeyString(pzSection, "Title", pLevelInfo->labelName));
|
||||
pLevelInfo->Author = pIni->GetKeyString(pzSection, "Author", "");
|
||||
pLevelInfo->music = pIni->GetKeyString(pzSection, "Song", ""); if (pLevelInfo->music.IsNotEmpty()) DefaultExtension(pLevelInfo->music, ".mid");
|
||||
pLevelInfo->cdSongId = pIni->GetKeyInt(pzSection, "Track", -1);
|
||||
*nextmap = pIni->GetKeyInt(pzSection, "EndingA", 0);
|
||||
*nextsecret = pIni->GetKeyInt(pzSection, "EndingB", 0);
|
||||
pLevelInfo->fog = pIni->GetKeyInt(pzSection, "Fog", -0);
|
||||
pLevelInfo->weather = pIni->GetKeyInt(pzSection, "Weather", -0);
|
||||
for (int i = 0; i < kMaxMessages; i++)
|
||||
{
|
||||
sprintf(buffer, "Message%d", i + 1);
|
||||
auto msg = pIni->GetKeyString(pzSection, buffer, "");
|
||||
pLevelInfo->AddMessage(i, msg);
|
||||
}
|
||||
char buffer[16];
|
||||
pLevelInfo->SetName(pIni->GetKeyString(pzSection, "Title", pLevelInfo->labelName));
|
||||
pLevelInfo->Author = pIni->GetKeyString(pzSection, "Author", "");
|
||||
pLevelInfo->music = pIni->GetKeyString(pzSection, "Song", ""); if (pLevelInfo->music.IsNotEmpty()) DefaultExtension(pLevelInfo->music, ".mid");
|
||||
pLevelInfo->cdSongId = pIni->GetKeyInt(pzSection, "Track", -1);
|
||||
*nextmap = pIni->GetKeyInt(pzSection, "EndingA", 0);
|
||||
*nextsecret = pIni->GetKeyInt(pzSection, "EndingB", 0);
|
||||
pLevelInfo->fog = pIni->GetKeyInt(pzSection, "Fog", -0);
|
||||
pLevelInfo->weather = pIni->GetKeyInt(pzSection, "Weather", -0);
|
||||
for (int i = 0; i < kMaxMessages; i++)
|
||||
{
|
||||
sprintf(buffer, "Message%d", i + 1);
|
||||
auto msg = pIni->GetKeyString(pzSection, buffer, "");
|
||||
pLevelInfo->AddMessage(i, msg);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static const char* DefFile(void)
|
||||
{
|
||||
int found = -1;
|
||||
if (userConfig.DefaultCon.IsEmpty() || userConfig.DefaultCon.CompareNoCase("blood.ini") == 0)
|
||||
{
|
||||
int numlumps = fileSystem.GetNumEntries();
|
||||
for (int i = numlumps - 1; i >= 0; i--)
|
||||
{
|
||||
int fileno = fileSystem.GetFileContainer(i);
|
||||
if (fileno != -1 && fileno <= fileSystem.GetMaxIwadNum()) continue;
|
||||
FString fn = fileSystem.GetFileFullName(i, false);
|
||||
FString ext = fn.Right(4);
|
||||
if (ext.CompareNoCase(".ini") == 0)
|
||||
{
|
||||
if (fileSystem.CheckNumForFullName(fn) != i) continue;
|
||||
if (found == -1)
|
||||
{
|
||||
IniFile inif(fn);
|
||||
for (int j = 1; j <= 6; j++)
|
||||
{
|
||||
FStringf key("Episode%d", j);
|
||||
if (inif.SectionExists(key))
|
||||
{
|
||||
found = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
found = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found >= 0) return fileSystem.GetFileFullName(found);
|
||||
// The command line parser stores this in the CON field.
|
||||
return userConfig.DefaultCon.IsNotEmpty() ? userConfig.DefaultCon.GetChars() : "blood.ini";
|
||||
int found = -1;
|
||||
if (userConfig.DefaultCon.IsEmpty() || userConfig.DefaultCon.CompareNoCase("blood.ini") == 0)
|
||||
{
|
||||
int numlumps = fileSystem.GetNumEntries();
|
||||
for (int i = numlumps - 1; i >= 0; i--)
|
||||
{
|
||||
int fileno = fileSystem.GetFileContainer(i);
|
||||
if (fileno != -1 && fileno <= fileSystem.GetMaxIwadNum()) continue;
|
||||
FString fn = fileSystem.GetFileFullName(i, false);
|
||||
FString ext = fn.Right(4);
|
||||
if (ext.CompareNoCase(".ini") == 0)
|
||||
{
|
||||
if (fileSystem.CheckNumForFullName(fn) != i) continue;
|
||||
if (found == -1)
|
||||
{
|
||||
IniFile inif(fn);
|
||||
for (int j = 1; j <= 6; j++)
|
||||
{
|
||||
FStringf key("Episode%d", j);
|
||||
if (inif.SectionExists(key))
|
||||
{
|
||||
found = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
found = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found >= 0) return fileSystem.GetFileFullName(found);
|
||||
// The command line parser stores this in the CON field.
|
||||
return userConfig.DefaultCon.IsNotEmpty() ? userConfig.DefaultCon.GetChars() : "blood.ini";
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static FString cleanPath(const char* pth)
|
||||
{
|
||||
FString path = pth;
|
||||
FixPathSeperator(path);
|
||||
if (fileSystem.FileExists(path)) return path;
|
||||
if (path.Len() > 3 && path[1] == ':' && isalpha(path[0]) && path[2] == '/')
|
||||
{
|
||||
path = path.Mid(3);
|
||||
if (fileSystem.FileExists(path)) return path;
|
||||
}
|
||||
// optionally strip the first path component to account for poor logic of the DOS EXE.
|
||||
auto pos = path.IndexOf("/");
|
||||
if (pos >= 0)
|
||||
{
|
||||
auto npath = path.Mid(pos + 1);
|
||||
if (fileSystem.FileExists(npath)) return npath;
|
||||
}
|
||||
return path;
|
||||
FString path = pth;
|
||||
FixPathSeperator(path);
|
||||
if (fileSystem.FileExists(path)) return path;
|
||||
if (path.Len() > 3 && path[1] == ':' && isalpha(path[0]) && path[2] == '/')
|
||||
{
|
||||
path = path.Mid(3);
|
||||
if (fileSystem.FileExists(path)) return path;
|
||||
}
|
||||
// optionally strip the first path component to account for poor logic of the DOS EXE.
|
||||
auto pos = path.IndexOf("/");
|
||||
if (pos >= 0)
|
||||
{
|
||||
auto npath = path.Mid(pos + 1);
|
||||
if (fileSystem.FileExists(npath)) return npath;
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void levelLoadDefaults(void)
|
||||
{
|
||||
char buffer[64];
|
||||
char buffer2[16];
|
||||
char buffer[64];
|
||||
char buffer2[16];
|
||||
|
||||
int cutALevel = 0;
|
||||
int cutALevel = 0;
|
||||
|
||||
levelInitINI(DefFile());
|
||||
int i;
|
||||
for (i = 1; i <= kMaxEpisodes; i++)
|
||||
{
|
||||
sprintf(buffer, "Episode%d", i);
|
||||
if (!BloodINI->SectionExists(buffer))
|
||||
break;
|
||||
auto cluster = MustFindCluster(i);
|
||||
auto volume = MustFindVolume(i);
|
||||
CutsceneDef &csB = cluster->outro;
|
||||
FString ep_str = BloodINI->GetKeyString(buffer, "Title", buffer);
|
||||
ep_str.StripRight();
|
||||
cluster->name = volume->name = FStringTable::MakeMacro(ep_str);
|
||||
if (i > 1) volume->flags |= VF_SHAREWARELOCK;
|
||||
if (BloodINI->GetKeyInt(buffer, "BloodBathOnly", 0)) volume->flags |= VF_HIDEFROMSP;
|
||||
levelInitINI(DefFile());
|
||||
int i;
|
||||
for (i = 1; i <= kMaxEpisodes; i++)
|
||||
{
|
||||
sprintf(buffer, "Episode%d", i);
|
||||
if (!BloodINI->SectionExists(buffer))
|
||||
break;
|
||||
auto cluster = MustFindCluster(i);
|
||||
auto volume = MustFindVolume(i);
|
||||
CutsceneDef& csB = cluster->outro;
|
||||
FString ep_str = BloodINI->GetKeyString(buffer, "Title", buffer);
|
||||
ep_str.StripRight();
|
||||
cluster->name = volume->name = FStringTable::MakeMacro(ep_str);
|
||||
if (i > 1) volume->flags |= VF_SHAREWARELOCK;
|
||||
if (BloodINI->GetKeyInt(buffer, "BloodBathOnly", 0)) volume->flags |= VF_HIDEFROMSP;
|
||||
|
||||
csB.video = cleanPath(BloodINI->GetKeyString(buffer, "CutSceneB", ""));
|
||||
int soundint = BloodINI->GetKeyInt(buffer, "CutWavB", -1);
|
||||
if (soundint > 0) csB.soundID = soundint + 0x40000000;
|
||||
else csB.soundName = cleanPath(BloodINI->GetKeyString(buffer, "CutWavB", ""));
|
||||
csB.video = cleanPath(BloodINI->GetKeyString(buffer, "CutSceneB", ""));
|
||||
int soundint = BloodINI->GetKeyInt(buffer, "CutWavB", -1);
|
||||
if (soundint > 0) csB.soundID = soundint + 0x40000000;
|
||||
else csB.soundName = cleanPath(BloodINI->GetKeyString(buffer, "CutWavB", ""));
|
||||
|
||||
//pEpisodeInfo->bloodbath = BloodINI->GetKeyInt(buffer, "BloodBathOnly", 0);
|
||||
cutALevel = BloodINI->GetKeyInt(buffer, "CutSceneALevel", 0);
|
||||
if (cutALevel < 1) cutALevel = 1;
|
||||
//pEpisodeInfo->bloodbath = BloodINI->GetKeyInt(buffer, "BloodBathOnly", 0);
|
||||
cutALevel = BloodINI->GetKeyInt(buffer, "CutSceneALevel", 0);
|
||||
if (cutALevel < 1) cutALevel = 1;
|
||||
|
||||
int nextmaps[kMaxLevels]{}, nextsecrets[kMaxLevels]{};
|
||||
for (int j = 1; j <= kMaxLevels; j++)
|
||||
{
|
||||
sprintf(buffer2, "Map%d", j);
|
||||
if (!BloodINI->KeyExists(buffer, buffer2))
|
||||
break;
|
||||
auto pLevelInfo = AllocateMap();
|
||||
const char *pMap = BloodINI->GetKeyString(buffer, buffer2, NULL);
|
||||
CheckSectionAbend(pMap);
|
||||
int nextmaps[kMaxLevels]{}, nextsecrets[kMaxLevels]{};
|
||||
for (int j = 1; j <= kMaxLevels; j++)
|
||||
{
|
||||
sprintf(buffer2, "Map%d", j);
|
||||
if (!BloodINI->KeyExists(buffer, buffer2))
|
||||
break;
|
||||
auto pLevelInfo = AllocateMap();
|
||||
const char* pMap = BloodINI->GetKeyString(buffer, buffer2, NULL);
|
||||
CheckSectionAbend(pMap);
|
||||
SetLevelNum(pLevelInfo, makelevelnum(i, j));
|
||||
pLevelInfo->cluster = i;
|
||||
pLevelInfo->labelName = pMap;
|
||||
pLevelInfo->cluster = i;
|
||||
pLevelInfo->labelName = pMap;
|
||||
if (j == 1) volume->startmap = pLevelInfo->labelName;
|
||||
pLevelInfo->fileName.Format("%s.map", pMap);
|
||||
levelLoadMapInfo(BloodINI, pLevelInfo, pMap, i, j, &nextmaps[j - 1], &nextsecrets[j - 1]);
|
||||
if (j == cutALevel)
|
||||
{
|
||||
CutsceneDef& csA = pLevelInfo->intro;
|
||||
csA.video = cleanPath(BloodINI->GetKeyString(buffer, "CutSceneA", ""));
|
||||
int soundfileint = BloodINI->GetKeyInt(buffer, "CutWavA", -1);
|
||||
if (soundfileint > 0) csA.soundID = soundfileint + 0x40000000;
|
||||
else csA.soundName = cleanPath(BloodINI->GetKeyString(buffer, "CutWavA", ""));
|
||||
}
|
||||
}
|
||||
// Now resolve the level links
|
||||
for (int j = 1; j <= kMaxLevels; j++)
|
||||
{
|
||||
auto map = FindMapByIndexOnly(i, j);
|
||||
if (map)
|
||||
{
|
||||
if (nextmaps[j - 1] > 0)
|
||||
{
|
||||
auto nmap = FindMapByIndexOnly(i, nextmaps[j - 1]);
|
||||
if (nmap) map->NextMap = nmap->labelName;
|
||||
else map->NextMap = "-";
|
||||
}
|
||||
else map->NextMap = "-";
|
||||
if (nextsecrets[j - 1] > 0)
|
||||
{
|
||||
auto nmap = FindMapByIndexOnly(i, nextsecrets[j - 1]);
|
||||
if (nmap) map->NextSecret = nmap->labelName;
|
||||
else map->NextSecret = "-";
|
||||
}
|
||||
else map->NextSecret = "-";
|
||||
}
|
||||
}
|
||||
}
|
||||
pLevelInfo->fileName.Format("%s.map", pMap);
|
||||
levelLoadMapInfo(BloodINI, pLevelInfo, pMap, i, j, &nextmaps[j - 1], &nextsecrets[j - 1]);
|
||||
if (j == cutALevel)
|
||||
{
|
||||
CutsceneDef& csA = pLevelInfo->intro;
|
||||
csA.video = cleanPath(BloodINI->GetKeyString(buffer, "CutSceneA", ""));
|
||||
int soundfileint = BloodINI->GetKeyInt(buffer, "CutWavA", -1);
|
||||
if (soundfileint > 0) csA.soundID = soundfileint + 0x40000000;
|
||||
else csA.soundName = cleanPath(BloodINI->GetKeyString(buffer, "CutWavA", ""));
|
||||
}
|
||||
}
|
||||
// Now resolve the level links
|
||||
for (int j = 1; j <= kMaxLevels; j++)
|
||||
{
|
||||
auto map = FindMapByIndexOnly(i, j);
|
||||
if (map)
|
||||
{
|
||||
if (nextmaps[j - 1] > 0)
|
||||
{
|
||||
auto nmap = FindMapByIndexOnly(i, nextmaps[j - 1]);
|
||||
if (nmap) map->NextMap = nmap->labelName;
|
||||
else map->NextMap = "-";
|
||||
}
|
||||
else map->NextMap = "-";
|
||||
if (nextsecrets[j - 1] > 0)
|
||||
{
|
||||
auto nmap = FindMapByIndexOnly(i, nextsecrets[j - 1]);
|
||||
if (nmap) map->NextSecret = nmap->labelName;
|
||||
else map->NextSecret = "-";
|
||||
}
|
||||
else map->NextSecret = "-";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void levelEndLevel(int secret)
|
||||
{
|
||||
gGameOptions.uGameFlags |= GF_AdvanceLevel;
|
||||
if (!secret) gNextLevel = FindNextMap(currentLevel);
|
||||
else gNextLevel = FindNextSecretMap(currentLevel);
|
||||
gGameOptions.uGameFlags |= GF_AdvanceLevel;
|
||||
if (!secret) gNextLevel = FindNextMap(currentLevel);
|
||||
else gNextLevel = FindNextSecretMap(currentLevel);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void levelTryPlayMusic()
|
||||
{
|
||||
FString buffer;
|
||||
if (mus_redbook && currentLevel->cdSongId > 0)
|
||||
buffer.Format("blood%02i.ogg", currentLevel->cdSongId);
|
||||
else
|
||||
{
|
||||
buffer = currentLevel->music;
|
||||
FString buffer;
|
||||
if (mus_redbook && currentLevel->cdSongId > 0)
|
||||
buffer.Format("blood%02i.ogg", currentLevel->cdSongId);
|
||||
else
|
||||
{
|
||||
buffer = currentLevel->music;
|
||||
if (Mus_Play(buffer, true)) return;
|
||||
if (buffer.IsNotEmpty()) DefaultExtension(buffer, ".mid");
|
||||
}
|
||||
if (!Mus_Play(buffer, true))
|
||||
{
|
||||
Mus_Play("", true);
|
||||
}
|
||||
if (buffer.IsNotEmpty()) DefaultExtension(buffer, ".mid");
|
||||
}
|
||||
if (!Mus_Play(buffer, true))
|
||||
{
|
||||
Mus_Play("", true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -46,22 +46,22 @@ enum EGameFlag
|
|||
};
|
||||
|
||||
struct GAMEOPTIONS {
|
||||
uint8_t nGameType;
|
||||
uint8_t nDifficulty;
|
||||
uint8_t nMonsterSettings;
|
||||
int uGameFlags;
|
||||
int uNetGameFlags;
|
||||
uint8_t nGameType;
|
||||
uint8_t nDifficulty;
|
||||
uint8_t nMonsterSettings;
|
||||
int uGameFlags;
|
||||
int uNetGameFlags;
|
||||
uint8_t nWeaponSettings;
|
||||
uint8_t nItemSettings;
|
||||
uint8_t nRespawnSettings;
|
||||
uint8_t nTeamSettings;
|
||||
int nMonsterRespawnTime;
|
||||
int nWeaponRespawnTime;
|
||||
int nItemRespawnTime;
|
||||
int nSpecialRespawnTime;
|
||||
int weaponsV10x;
|
||||
bool bFriendlyFire;
|
||||
bool bKeepKeysOnRespawn;
|
||||
int nMonsterRespawnTime;
|
||||
int nWeaponRespawnTime;
|
||||
int nItemRespawnTime;
|
||||
int nSpecialRespawnTime;
|
||||
int weaponsV10x;
|
||||
bool bFriendlyFire;
|
||||
bool bKeepKeysOnRespawn;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
@ -74,9 +74,9 @@ extern bool bINIOverride;
|
|||
extern MapRecord* gNextLevel;
|
||||
extern bool gGameStarted;
|
||||
|
||||
void levelInitINI(const char *pzIni);
|
||||
void CheckSectionAbend(const char *pzSection);
|
||||
void CheckKeyAbend(const char *pzSection, const char *pzKey);
|
||||
void levelInitINI(const char* pzIni);
|
||||
void CheckSectionAbend(const char* pzSection);
|
||||
void CheckKeyAbend(const char* pzSection, const char* pzKey);
|
||||
void levelLoadDefaults(void);
|
||||
// arg: 0 is normal exit, 1 is secret level
|
||||
void levelEndLevel(int arg);
|
||||
|
|
|
@ -39,7 +39,7 @@ BEGIN_BLD_NS
|
|||
void validateLinks();
|
||||
|
||||
// All AI states for assigning an index.
|
||||
static AISTATE* allAIStates[] =
|
||||
static AISTATE* const allAIStates[] =
|
||||
{
|
||||
nullptr,
|
||||
&genIdle,
|
||||
|
@ -391,6 +391,12 @@ static AISTATE* allAIStates[] =
|
|||
&zombieFTeslaRecoil,
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
FSerializer& Serialize(FSerializer& arc, const char* keyname, AISTATE*& w, AISTATE** def)
|
||||
{
|
||||
unsigned i = 0;
|
||||
|
@ -456,6 +462,12 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, DUDEEXTRA& w, DUDE
|
|||
return arc;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void DBloodActor::Serialize(FSerializer& arc)
|
||||
{
|
||||
Super::Serialize(arc);
|
||||
|
@ -464,9 +476,9 @@ void DBloodActor::Serialize(FSerializer& arc)
|
|||
("zvel", zvel)
|
||||
("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())
|
||||
{
|
||||
{
|
||||
arc("xsprite", xspr)
|
||||
("dudeslope", dudeSlope)
|
||||
("dudeextra", dudeExtra)
|
||||
|
@ -476,23 +488,29 @@ void DBloodActor::Serialize(FSerializer& arc)
|
|||
("owneractor", ownerActor);
|
||||
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
if (gModernMap)
|
||||
{
|
||||
if (gModernMap)
|
||||
{
|
||||
arc("spritemass", spriteMass)
|
||||
("prevmarker", prevmarker)
|
||||
.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
FSerializer& Serialize(FSerializer& arc, const char* keyname, XWALL& w, XWALL* def)
|
||||
{
|
||||
static XWALL nul;
|
||||
|
@ -520,6 +538,12 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, XWALL& w, XWALL* d
|
|||
return arc;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
FSerializer& Serialize(FSerializer& arc, const char* keyname, XSECTOR& w, XSECTOR* def)
|
||||
{
|
||||
static XSECTOR nul;
|
||||
|
@ -573,6 +597,12 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, XSECTOR& w, XSECTO
|
|||
return arc;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
FSerializer& Serialize(FSerializer& arc, const char* keyname, XSPRITE& w, XSPRITE* def)
|
||||
{
|
||||
static XSPRITE nul;
|
||||
|
@ -623,6 +653,12 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, XSPRITE& w, XSPRIT
|
|||
return arc;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
FSerializer& Serialize(FSerializer& arc, const char* keyname, GAMEOPTIONS& w, GAMEOPTIONS* def)
|
||||
{
|
||||
if (arc.BeginObject(keyname))
|
||||
|
@ -647,6 +683,12 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, GAMEOPTIONS& w, GA
|
|||
return arc;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void SerializeState(FSerializer& arc)
|
||||
{
|
||||
if (arc.isReading())
|
||||
|
@ -690,18 +732,24 @@ void SerializeView(FSerializer& arc);
|
|||
void SerializeNNExts(FSerializer& arc);
|
||||
void SerializeMirrors(FSerializer& arc);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void GameInterface::SerializeGameState(FSerializer& arc)
|
||||
{
|
||||
if (arc.isWriting())
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sndKillAllSounds();
|
||||
sfxKillAllSounds();
|
||||
ambKillAll();
|
||||
seqKillAll();
|
||||
}
|
||||
}
|
||||
SerializeState(arc);
|
||||
SerializeActor(arc);
|
||||
SerializePlayers(arc);
|
||||
|
|
|
@ -7,259 +7,257 @@
|
|||
// Keep it local so that the engine's sprite type is no longer limited by file format restrictions.
|
||||
struct spritetypedisk
|
||||
{
|
||||
int32_t x, y, z;
|
||||
uint16_t cstat;
|
||||
int16_t picnum;
|
||||
int8_t shade;
|
||||
uint8_t pal, clipdist, detail;
|
||||
uint8_t xrepeat, yrepeat;
|
||||
int8_t xoffset, yoffset;
|
||||
int16_t sectnum, statnum;
|
||||
int16_t ang, owner;
|
||||
int16_t index, yvel, inittype;
|
||||
int16_t type;
|
||||
int16_t hitag;
|
||||
int16_t extra;
|
||||
int32_t x, y, z;
|
||||
uint16_t cstat;
|
||||
int16_t picnum;
|
||||
int8_t shade;
|
||||
uint8_t pal, clipdist, detail;
|
||||
uint8_t xrepeat, yrepeat;
|
||||
int8_t xoffset, yoffset;
|
||||
int16_t sectnum, statnum;
|
||||
int16_t ang, owner;
|
||||
int16_t index, yvel, inittype;
|
||||
int16_t type;
|
||||
int16_t hitag;
|
||||
int16_t extra;
|
||||
};
|
||||
|
||||
struct sectortypedisk
|
||||
{
|
||||
int16_t wallptr, wallnum;
|
||||
int32_t ceilingz, floorz;
|
||||
uint16_t ceilingstat, floorstat;
|
||||
int16_t ceilingpicnum, ceilingheinum;
|
||||
int8_t ceilingshade;
|
||||
uint8_t ceilingpal, ceilingxpanning, ceilingypanning;
|
||||
int16_t floorpicnum, floorheinum;
|
||||
int8_t floorshade;
|
||||
uint8_t floorpal, floorxpanning, floorypanning;
|
||||
uint8_t visibility, fogpal;
|
||||
int16_t type;
|
||||
int16_t hitag;
|
||||
int16_t extra;
|
||||
int16_t wallptr, wallnum;
|
||||
int32_t ceilingz, floorz;
|
||||
uint16_t ceilingstat, floorstat;
|
||||
int16_t ceilingpicnum, ceilingheinum;
|
||||
int8_t ceilingshade;
|
||||
uint8_t ceilingpal, ceilingxpanning, ceilingypanning;
|
||||
int16_t floorpicnum, floorheinum;
|
||||
int8_t floorshade;
|
||||
uint8_t floorpal, floorxpanning, floorypanning;
|
||||
uint8_t visibility, fogpal;
|
||||
int16_t type;
|
||||
int16_t hitag;
|
||||
int16_t extra;
|
||||
};
|
||||
|
||||
struct walltypedisk
|
||||
{
|
||||
int32_t x, y;
|
||||
int16_t point2, nextwall, nextsector;
|
||||
uint16_t cstat;
|
||||
int16_t picnum, overpicnum;
|
||||
int8_t shade;
|
||||
uint8_t pal, xrepeat, yrepeat, xpanning, ypanning;
|
||||
int16_t type;
|
||||
int16_t hitag;
|
||||
int16_t extra;
|
||||
int32_t x, y;
|
||||
int16_t point2, nextwall, nextsector;
|
||||
uint16_t cstat;
|
||||
int16_t picnum, overpicnum;
|
||||
int8_t shade;
|
||||
uint8_t pal, xrepeat, yrepeat, xpanning, ypanning;
|
||||
int16_t type;
|
||||
int16_t hitag;
|
||||
int16_t extra;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
TArray<walltype> dbLoadMapWalls(const char* pPath);
|
||||
|
||||
class DBloodActor;
|
||||
struct AISTATE;
|
||||
|
||||
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
|
||||
TObjPtr<DBloodActor*> burnSource;
|
||||
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
|
||||
};
|
||||
};
|
||||
|
||||
int32_t targetX; // target x
|
||||
int32_t targetY; // target y
|
||||
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;
|
||||
TObjPtr<DBloodActor*> target; // target sprite
|
||||
TObjPtr<DBloodActor*> burnSource;
|
||||
|
||||
int16_t data1; // Data 1
|
||||
int16_t data2; // Data 2
|
||||
int16_t data3; // Data 3
|
||||
uint16_t txID; // TX ID
|
||||
uint16_t rxID; // RX ID
|
||||
uint16_t command; // Cmd
|
||||
uint16_t busyTime; // busyTime
|
||||
uint16_t waitTime; // waitTime
|
||||
uint16_t data4; // Data 4
|
||||
uint16_t goalAng; // Dude goal ang
|
||||
uint16_t burnTime;
|
||||
uint16_t height;
|
||||
uint16_t stateTimer; // ai timer
|
||||
int32_t targetX; // target x
|
||||
int32_t targetY; // target y
|
||||
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;
|
||||
|
||||
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
|
||||
int16_t data1; // Data 1
|
||||
int16_t data2; // Data 2
|
||||
int16_t data3; // Data 3
|
||||
uint16_t txID; // TX ID
|
||||
uint16_t rxID; // RX ID
|
||||
uint16_t command; // Cmd
|
||||
uint16_t busyTime; // busyTime
|
||||
uint16_t waitTime; // waitTime
|
||||
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 {
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
};
|
||||
};
|
||||
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
|
||||
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 {
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
|
@ -34,517 +34,559 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void sub_5A928(void)
|
||||
{
|
||||
for (int i = 0; i < buttonMap.NumButtons(); i++)
|
||||
buttonMap.ClearButton(i);
|
||||
for (int i = 0; i < buttonMap.NumButtons(); i++)
|
||||
buttonMap.ClearButton(i);
|
||||
}
|
||||
|
||||
const char *SetGodMode(bool god)
|
||||
const char* SetGodMode(bool god)
|
||||
{
|
||||
playerSetGodMode(gMe, god);
|
||||
bPlayerCheated = true;
|
||||
return gMe->godMode? GStrings("TXTB_GODMODE") : GStrings("TXTB_NOTGODMODE");
|
||||
playerSetGodMode(gMe, god);
|
||||
bPlayerCheated = true;
|
||||
return gMe->godMode ? GStrings("TXTB_GODMODE") : GStrings("TXTB_NOTGODMODE");
|
||||
}
|
||||
|
||||
const char *SetClipMode(bool noclip)
|
||||
const char* SetClipMode(bool noclip)
|
||||
{
|
||||
gNoClip = noclip;
|
||||
bPlayerCheated = true;
|
||||
return gNoClip? GStrings("TXTB_NOCLIP") : GStrings("TXTB_NOCLIPOFF");
|
||||
gNoClip = noclip;
|
||||
bPlayerCheated = true;
|
||||
return gNoClip ? GStrings("TXTB_NOCLIP") : GStrings("TXTB_NOCLIPOFF");
|
||||
}
|
||||
|
||||
void packStuff(PLAYER *pPlayer)
|
||||
void packStuff(PLAYER* pPlayer)
|
||||
{
|
||||
for (int i = 0; i < 5; i++)
|
||||
packAddItem(pPlayer, i);
|
||||
for (int i = 0; i < 5; i++)
|
||||
packAddItem(pPlayer, i);
|
||||
}
|
||||
|
||||
void packClear(PLAYER *pPlayer)
|
||||
void packClear(PLAYER* pPlayer)
|
||||
{
|
||||
pPlayer->packItemId = 0;
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
pPlayer->packSlots[i].isActive = 0;
|
||||
pPlayer->packSlots[i].curAmount = 0;
|
||||
}
|
||||
pPlayer->packItemId = 0;
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
pPlayer->packSlots[i].isActive = 0;
|
||||
pPlayer->packSlots[i].curAmount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SetAmmo(bool stat)
|
||||
{
|
||||
if (stat)
|
||||
{
|
||||
for (int i = 0; i < 12; i++)
|
||||
gMe->ammoCount[i] = gAmmoInfo[i].max;
|
||||
viewSetMessage(GStrings("TXTB_FULLAMMO"));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 12; i++)
|
||||
gMe->ammoCount[i] = 0;
|
||||
viewSetMessage(GStrings("TXTB_NOAMMO"));
|
||||
}
|
||||
if (stat)
|
||||
{
|
||||
for (int i = 0; i < 12; i++)
|
||||
gMe->ammoCount[i] = gAmmoInfo[i].max;
|
||||
viewSetMessage(GStrings("TXTB_FULLAMMO"));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 12; i++)
|
||||
gMe->ammoCount[i] = 0;
|
||||
viewSetMessage(GStrings("TXTB_NOAMMO"));
|
||||
}
|
||||
}
|
||||
|
||||
void SetWeapons(bool stat)
|
||||
{
|
||||
for (int i = 0; i < 14; i++)
|
||||
{
|
||||
gMe->hasWeapon[i] = stat;
|
||||
}
|
||||
SetAmmo(stat);
|
||||
if (stat)
|
||||
viewSetMessage(GStrings("TXTB_ALLWEAP"));
|
||||
else
|
||||
{
|
||||
if (!VanillaMode())
|
||||
{
|
||||
// Keep the pitchfork to avoid freeze
|
||||
gMe->hasWeapon[1] = 1;
|
||||
gMe->curWeapon = kWeapNone;
|
||||
gMe->nextWeapon = kWeapPitchFork;
|
||||
}
|
||||
viewSetMessage(GStrings("TXTB_NOWEAP"));
|
||||
}
|
||||
for (int i = 0; i < 14; i++)
|
||||
{
|
||||
gMe->hasWeapon[i] = stat;
|
||||
}
|
||||
SetAmmo(stat);
|
||||
if (stat)
|
||||
viewSetMessage(GStrings("TXTB_ALLWEAP"));
|
||||
else
|
||||
{
|
||||
if (!VanillaMode())
|
||||
{
|
||||
// Keep the pitchfork to avoid freeze
|
||||
gMe->hasWeapon[1] = 1;
|
||||
gMe->curWeapon = kWeapNone;
|
||||
gMe->nextWeapon = kWeapPitchFork;
|
||||
}
|
||||
viewSetMessage(GStrings("TXTB_NOWEAP"));
|
||||
}
|
||||
}
|
||||
|
||||
void SetToys(bool stat)
|
||||
{
|
||||
if (stat)
|
||||
{
|
||||
packStuff(gMe);
|
||||
viewSetMessage(GStrings("TXTB_FULLINV"));
|
||||
}
|
||||
else
|
||||
{
|
||||
packClear(gMe);
|
||||
viewSetMessage(GStrings("TXTB_NOINV"));
|
||||
}
|
||||
if (stat)
|
||||
{
|
||||
packStuff(gMe);
|
||||
viewSetMessage(GStrings("TXTB_FULLINV"));
|
||||
}
|
||||
else
|
||||
{
|
||||
packClear(gMe);
|
||||
viewSetMessage(GStrings("TXTB_NOINV"));
|
||||
}
|
||||
}
|
||||
|
||||
void SetArmor(bool stat)
|
||||
{
|
||||
int nAmount;
|
||||
if (stat)
|
||||
{
|
||||
viewSetMessage(GStrings("TXTB_FULLARM"));
|
||||
nAmount = 3200;
|
||||
}
|
||||
else
|
||||
{
|
||||
viewSetMessage(GStrings("TXTB_NOARM"));
|
||||
nAmount = 0;
|
||||
}
|
||||
for (int i = 0; i < 3; i++)
|
||||
gMe->armor[i] = nAmount;
|
||||
int nAmount;
|
||||
if (stat)
|
||||
{
|
||||
viewSetMessage(GStrings("TXTB_FULLARM"));
|
||||
nAmount = 3200;
|
||||
}
|
||||
else
|
||||
{
|
||||
viewSetMessage(GStrings("TXTB_NOARM"));
|
||||
nAmount = 0;
|
||||
}
|
||||
for (int i = 0; i < 3; i++)
|
||||
gMe->armor[i] = nAmount;
|
||||
}
|
||||
|
||||
void SetKeys(bool stat)
|
||||
{
|
||||
for (int i = 1; i <= 6; i++)
|
||||
gMe->hasKey[i] = stat;
|
||||
if (stat)
|
||||
viewSetMessage(GStrings("TXTB_ALLKEYS"));
|
||||
else
|
||||
viewSetMessage(GStrings("TXTB_NOKEYS"));
|
||||
for (int i = 1; i <= 6; i++)
|
||||
gMe->hasKey[i] = stat;
|
||||
if (stat)
|
||||
viewSetMessage(GStrings("TXTB_ALLKEYS"));
|
||||
else
|
||||
viewSetMessage(GStrings("TXTB_NOKEYS"));
|
||||
}
|
||||
|
||||
void SetInfiniteAmmo(bool stat)
|
||||
{
|
||||
gInfiniteAmmo = stat;
|
||||
if (gInfiniteAmmo)
|
||||
viewSetMessage(GStrings("TXTB_INFAMMO"));
|
||||
else
|
||||
viewSetMessage(GStrings("TXTB_LIMAMMO"));
|
||||
gInfiniteAmmo = stat;
|
||||
if (gInfiniteAmmo)
|
||||
viewSetMessage(GStrings("TXTB_INFAMMO"));
|
||||
else
|
||||
viewSetMessage(GStrings("TXTB_LIMAMMO"));
|
||||
}
|
||||
|
||||
void SetMap(bool stat)
|
||||
{
|
||||
gFullMap = stat;
|
||||
if (gFullMap)
|
||||
viewSetMessage(GStrings("TXTB_ALLMAP"));
|
||||
else
|
||||
viewSetMessage(GStrings("TXTB_NOALLMAP"));
|
||||
gFullMap = stat;
|
||||
if (gFullMap)
|
||||
viewSetMessage(GStrings("TXTB_ALLMAP"));
|
||||
else
|
||||
viewSetMessage(GStrings("TXTB_NOALLMAP"));
|
||||
}
|
||||
|
||||
void SetWooMode(bool stat)
|
||||
{
|
||||
if (stat)
|
||||
{
|
||||
if (!powerupCheck(gMe, kPwUpTwoGuns))
|
||||
powerupActivate(gMe, kPwUpTwoGuns);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (powerupCheck(gMe, kPwUpTwoGuns))
|
||||
{
|
||||
if (!VanillaMode())
|
||||
gMe->pwUpTime[kPwUpTwoGuns] = 0;
|
||||
powerupDeactivate(gMe, kPwUpTwoGuns);
|
||||
}
|
||||
}
|
||||
if (stat)
|
||||
{
|
||||
if (!powerupCheck(gMe, kPwUpTwoGuns))
|
||||
powerupActivate(gMe, kPwUpTwoGuns);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (powerupCheck(gMe, kPwUpTwoGuns))
|
||||
{
|
||||
if (!VanillaMode())
|
||||
gMe->pwUpTime[kPwUpTwoGuns] = 0;
|
||||
powerupDeactivate(gMe, kPwUpTwoGuns);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ToggleWooMode(void)
|
||||
{
|
||||
SetWooMode(!(powerupCheck(gMe, kPwUpTwoGuns) != 0));
|
||||
SetWooMode(!(powerupCheck(gMe, kPwUpTwoGuns) != 0));
|
||||
}
|
||||
|
||||
void ToggleBoots(void)
|
||||
{
|
||||
if (powerupCheck(gMe, kPwUpJumpBoots))
|
||||
{
|
||||
viewSetMessage(GStrings("TXTB_NOJBOOTS"));
|
||||
if (!VanillaMode())
|
||||
{
|
||||
gMe->pwUpTime[kPwUpJumpBoots] = 0;
|
||||
gMe->packSlots[4].curAmount = 0;
|
||||
}
|
||||
powerupDeactivate(gMe, kPwUpJumpBoots);
|
||||
}
|
||||
else
|
||||
{
|
||||
viewSetMessage(GStrings("TXTB_JBOOTS"));
|
||||
if (!VanillaMode())
|
||||
gMe->pwUpTime[kPwUpJumpBoots] = gPowerUpInfo[kPwUpJumpBoots].bonusTime;
|
||||
powerupActivate(gMe, kPwUpJumpBoots);
|
||||
}
|
||||
if (powerupCheck(gMe, kPwUpJumpBoots))
|
||||
{
|
||||
viewSetMessage(GStrings("TXTB_NOJBOOTS"));
|
||||
if (!VanillaMode())
|
||||
{
|
||||
gMe->pwUpTime[kPwUpJumpBoots] = 0;
|
||||
gMe->packSlots[4].curAmount = 0;
|
||||
}
|
||||
powerupDeactivate(gMe, kPwUpJumpBoots);
|
||||
}
|
||||
else
|
||||
{
|
||||
viewSetMessage(GStrings("TXTB_JBOOTS"));
|
||||
if (!VanillaMode())
|
||||
gMe->pwUpTime[kPwUpJumpBoots] = gPowerUpInfo[kPwUpJumpBoots].bonusTime;
|
||||
powerupActivate(gMe, kPwUpJumpBoots);
|
||||
}
|
||||
}
|
||||
|
||||
void ToggleInvisibility(void)
|
||||
{
|
||||
if (powerupCheck(gMe, kPwUpShadowCloak))
|
||||
{
|
||||
viewSetMessage(GStrings("TXTB_VISIBLE"));
|
||||
if (!VanillaMode())
|
||||
gMe->pwUpTime[kPwUpShadowCloak] = 0;
|
||||
powerupDeactivate(gMe, kPwUpShadowCloak);
|
||||
}
|
||||
else
|
||||
{
|
||||
viewSetMessage(GStrings("TXTB_INVISIBLE"));
|
||||
powerupActivate(gMe, kPwUpShadowCloak);
|
||||
}
|
||||
if (powerupCheck(gMe, kPwUpShadowCloak))
|
||||
{
|
||||
viewSetMessage(GStrings("TXTB_VISIBLE"));
|
||||
if (!VanillaMode())
|
||||
gMe->pwUpTime[kPwUpShadowCloak] = 0;
|
||||
powerupDeactivate(gMe, kPwUpShadowCloak);
|
||||
}
|
||||
else
|
||||
{
|
||||
viewSetMessage(GStrings("TXTB_INVISIBLE"));
|
||||
powerupActivate(gMe, kPwUpShadowCloak);
|
||||
}
|
||||
}
|
||||
|
||||
void ToggleInvulnerability(void)
|
||||
{
|
||||
if (powerupCheck(gMe, kPwUpDeathMask))
|
||||
{
|
||||
viewSetMessage(GStrings("TXTB_VULN"));
|
||||
if (!VanillaMode())
|
||||
gMe->pwUpTime[kPwUpDeathMask] = 0;
|
||||
powerupDeactivate(gMe, kPwUpDeathMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
viewSetMessage(GStrings("TXTB_INVULN"));
|
||||
powerupActivate(gMe, kPwUpDeathMask);
|
||||
}
|
||||
if (powerupCheck(gMe, kPwUpDeathMask))
|
||||
{
|
||||
viewSetMessage(GStrings("TXTB_VULN"));
|
||||
if (!VanillaMode())
|
||||
gMe->pwUpTime[kPwUpDeathMask] = 0;
|
||||
powerupDeactivate(gMe, kPwUpDeathMask);
|
||||
}
|
||||
else
|
||||
{
|
||||
viewSetMessage(GStrings("TXTB_INVULN"));
|
||||
powerupActivate(gMe, kPwUpDeathMask);
|
||||
}
|
||||
}
|
||||
|
||||
void ToggleDelirium(void)
|
||||
{
|
||||
if (powerupCheck(gMe, kPwUpDeliriumShroom))
|
||||
{
|
||||
viewSetMessage(GStrings("TXTB_NODELIR"));
|
||||
if (!VanillaMode())
|
||||
gMe->pwUpTime[kPwUpDeliriumShroom] = 0;
|
||||
powerupDeactivate(gMe, kPwUpDeliriumShroom);
|
||||
}
|
||||
else
|
||||
{
|
||||
viewSetMessage(GStrings("TXTB_DELIR"));
|
||||
powerupActivate(gMe, kPwUpDeliriumShroom);
|
||||
}
|
||||
if (powerupCheck(gMe, kPwUpDeliriumShroom))
|
||||
{
|
||||
viewSetMessage(GStrings("TXTB_NODELIR"));
|
||||
if (!VanillaMode())
|
||||
gMe->pwUpTime[kPwUpDeliriumShroom] = 0;
|
||||
powerupDeactivate(gMe, kPwUpDeliriumShroom);
|
||||
}
|
||||
else
|
||||
{
|
||||
viewSetMessage(GStrings("TXTB_DELIR"));
|
||||
powerupActivate(gMe, kPwUpDeliriumShroom);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
return -1;
|
||||
*nArg1 = pzArgs[0] - '0';
|
||||
int a1 = pzArgs[1] == ' ' ? 0 : pzArgs[1] - '0';
|
||||
*nArg2 = a1 * 10 + (pzArgs[2] - '0');
|
||||
return 2;
|
||||
if (!nArg1 || !nArg2 || strlen(pzArgs) < 3)
|
||||
return -1;
|
||||
*nArg1 = pzArgs[0] - '0';
|
||||
int a1 = pzArgs[1] == ' ' ? 0 : pzArgs[1] - '0';
|
||||
*nArg2 = a1 * 10 + (pzArgs[2] - '0');
|
||||
return 2;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
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.
|
||||
return nullptr;
|
||||
if (gGameOptions.nGameType != 0 || numplayers > 1) // sp only for now.
|
||||
return nullptr;
|
||||
|
||||
if (gamestate != GS_LEVEL || gMe->actor->xspr.health == 0) // must be alive and in a level to cheat.
|
||||
return nullptr;
|
||||
if (gamestate != GS_LEVEL || gMe->actor->xspr.health == 0) // must be alive and in a level to cheat.
|
||||
return nullptr;
|
||||
|
||||
bPlayerCheated = true;
|
||||
switch (cheat)
|
||||
{
|
||||
case CHT_GOD:
|
||||
return SetGodMode(!gMe->godMode);
|
||||
bPlayerCheated = true;
|
||||
switch (cheat)
|
||||
{
|
||||
case CHT_GOD:
|
||||
return SetGodMode(!gMe->godMode);
|
||||
|
||||
case CHT_GODOFF:
|
||||
return SetGodMode(false);
|
||||
case CHT_GODOFF:
|
||||
return SetGodMode(false);
|
||||
|
||||
case CHT_GODON:
|
||||
return SetGodMode(true);
|
||||
case CHT_GODON:
|
||||
return SetGodMode(true);
|
||||
|
||||
case CHT_NOCLIP:
|
||||
return SetClipMode(!gNoClip);
|
||||
case CHT_NOCLIP:
|
||||
return SetClipMode(!gNoClip);
|
||||
|
||||
case kCheatSpielberg:
|
||||
// demo record
|
||||
break;
|
||||
case kCheatSatchel:
|
||||
SetToys(true);
|
||||
break;
|
||||
case kCheatKevorkian:
|
||||
actDamageSprite(gMe->actor, gMe->actor, kDamageBullet, 8000);
|
||||
return GStrings("TXTB_KEVORKIAN");
|
||||
case kCheatSpielberg:
|
||||
// demo record
|
||||
break;
|
||||
case kCheatSatchel:
|
||||
SetToys(true);
|
||||
break;
|
||||
case kCheatKevorkian:
|
||||
actDamageSprite(gMe->actor, gMe->actor, kDamageBullet, 8000);
|
||||
return GStrings("TXTB_KEVORKIAN");
|
||||
|
||||
case kCheatMcGee:
|
||||
{
|
||||
if (!gMe->actor->xspr.burnTime)
|
||||
evPostActor(gMe->actor, 0, kCallbackFXFlameLick);
|
||||
actBurnSprite(gMe->actor, gMe->actor, 2400);
|
||||
return GStrings("TXTB_FIRED");
|
||||
}
|
||||
case kCheatEdmark:
|
||||
actDamageSprite(gMe->actor, gMe->actor, kDamageExplode, 8000);
|
||||
return GStrings("TXTB_THEDAYS");
|
||||
case kCheatMcGee:
|
||||
{
|
||||
if (!gMe->actor->xspr.burnTime)
|
||||
evPostActor(gMe->actor, 0, kCallbackFXFlameLick);
|
||||
actBurnSprite(gMe->actor, gMe->actor, 2400);
|
||||
return GStrings("TXTB_FIRED");
|
||||
}
|
||||
case kCheatEdmark:
|
||||
actDamageSprite(gMe->actor, gMe->actor, kDamageExplode, 8000);
|
||||
return GStrings("TXTB_THEDAYS");
|
||||
|
||||
case kCheatKrueger:
|
||||
{
|
||||
actHealDude(gMe->actor, 200, 200);
|
||||
gMe->armor[1] = VanillaMode() ? 200 : 3200;
|
||||
if (!gMe->actor->xspr.burnTime)
|
||||
evPostActor(gMe->actor, 0, kCallbackFXFlameLick);
|
||||
actBurnSprite(gMe->actor, gMe->actor, 2400);
|
||||
return GStrings("TXTB_RETARD");
|
||||
}
|
||||
case kCheatSterno:
|
||||
gMe->blindEffect = 250;
|
||||
break;
|
||||
case kCheat14: // quakeEffect (causing a little flickerEffect), not used by any cheat code (dead code)
|
||||
gMe->flickerEffect = 360;
|
||||
break;
|
||||
case kCheatSpork:
|
||||
actHealDude(gMe->actor, 200, 200);
|
||||
break;
|
||||
case kCheatClarice:
|
||||
for (int i = 0; i < 3; i++)
|
||||
gMe->armor[i] = 1600;
|
||||
return GStrings("TXTB_HALFARMOR");
|
||||
case kCheatFrankenstein:
|
||||
gMe->packSlots[0].curAmount = 100;
|
||||
break;
|
||||
case kCheatCheeseHead:
|
||||
gMe->packSlots[1].curAmount = 100;
|
||||
if (!VanillaMode())
|
||||
gMe->pwUpTime[kPwUpDivingSuit] = gPowerUpInfo[kPwUpDivingSuit].bonusTime;
|
||||
break;
|
||||
case kCheatTequila:
|
||||
ToggleWooMode();
|
||||
break;
|
||||
case kCheatFunkyShoes:
|
||||
ToggleBoots();
|
||||
break;
|
||||
case kCheatKeyMaster:
|
||||
SetKeys(true);
|
||||
break;
|
||||
case kCheatOneRing:
|
||||
ToggleInvisibility();
|
||||
break;
|
||||
case kCheatVoorhees:
|
||||
ToggleInvulnerability();
|
||||
break;
|
||||
case kCheatJoJo:
|
||||
ToggleDelirium();
|
||||
break;
|
||||
case kCheatLaraCroft:
|
||||
SetInfiniteAmmo(!gInfiniteAmmo);
|
||||
SetWeapons(gInfiniteAmmo);
|
||||
break;
|
||||
case kCheatHongKong:
|
||||
SetWeapons(true);
|
||||
SetInfiniteAmmo(true);
|
||||
break;
|
||||
case kCheatMontana:
|
||||
SetWeapons(true);
|
||||
SetToys(true);
|
||||
break;
|
||||
case kCheatBunz:
|
||||
SetWeapons(true);
|
||||
SetWooMode(true);
|
||||
break;
|
||||
case kCheatCousteau:
|
||||
actHealDude(gMe->actor, 200, 200);
|
||||
gMe->packSlots[1].curAmount = 100;
|
||||
if (!VanillaMode())
|
||||
gMe->pwUpTime[kPwUpDivingSuit] = gPowerUpInfo[kPwUpDivingSuit].bonusTime;
|
||||
break;
|
||||
case kCheatForkYou:
|
||||
SetInfiniteAmmo(false);
|
||||
SetMap(false);
|
||||
SetWeapons(false);
|
||||
SetAmmo(false);
|
||||
SetArmor(false);
|
||||
SetToys(false);
|
||||
SetKeys(false);
|
||||
SetWooMode(true);
|
||||
powerupActivate(gMe, kPwUpDeliriumShroom);
|
||||
gMe->actor->xspr.health = 16;
|
||||
gMe->hasWeapon[1] = 1;
|
||||
gMe->curWeapon = kWeapNone;
|
||||
gMe->nextWeapon = kWeapPitchFork;
|
||||
break;
|
||||
case kCheatKrueger:
|
||||
{
|
||||
actHealDude(gMe->actor, 200, 200);
|
||||
gMe->armor[1] = VanillaMode() ? 200 : 3200;
|
||||
if (!gMe->actor->xspr.burnTime)
|
||||
evPostActor(gMe->actor, 0, kCallbackFXFlameLick);
|
||||
actBurnSprite(gMe->actor, gMe->actor, 2400);
|
||||
return GStrings("TXTB_RETARD");
|
||||
}
|
||||
case kCheatSterno:
|
||||
gMe->blindEffect = 250;
|
||||
break;
|
||||
case kCheat14: // quakeEffect (causing a little flickerEffect), not used by any cheat code (dead code)
|
||||
gMe->flickerEffect = 360;
|
||||
break;
|
||||
case kCheatSpork:
|
||||
actHealDude(gMe->actor, 200, 200);
|
||||
break;
|
||||
case kCheatClarice:
|
||||
for (int i = 0; i < 3; i++)
|
||||
gMe->armor[i] = 1600;
|
||||
return GStrings("TXTB_HALFARMOR");
|
||||
case kCheatFrankenstein:
|
||||
gMe->packSlots[0].curAmount = 100;
|
||||
break;
|
||||
case kCheatCheeseHead:
|
||||
gMe->packSlots[1].curAmount = 100;
|
||||
if (!VanillaMode())
|
||||
gMe->pwUpTime[kPwUpDivingSuit] = gPowerUpInfo[kPwUpDivingSuit].bonusTime;
|
||||
break;
|
||||
case kCheatTequila:
|
||||
ToggleWooMode();
|
||||
break;
|
||||
case kCheatFunkyShoes:
|
||||
ToggleBoots();
|
||||
break;
|
||||
case kCheatKeyMaster:
|
||||
SetKeys(true);
|
||||
break;
|
||||
case kCheatOneRing:
|
||||
ToggleInvisibility();
|
||||
break;
|
||||
case kCheatVoorhees:
|
||||
ToggleInvulnerability();
|
||||
break;
|
||||
case kCheatJoJo:
|
||||
ToggleDelirium();
|
||||
break;
|
||||
case kCheatLaraCroft:
|
||||
SetInfiniteAmmo(!gInfiniteAmmo);
|
||||
SetWeapons(gInfiniteAmmo);
|
||||
break;
|
||||
case kCheatHongKong:
|
||||
SetWeapons(true);
|
||||
SetInfiniteAmmo(true);
|
||||
break;
|
||||
case kCheatMontana:
|
||||
SetWeapons(true);
|
||||
SetToys(true);
|
||||
break;
|
||||
case kCheatBunz:
|
||||
SetWeapons(true);
|
||||
SetWooMode(true);
|
||||
break;
|
||||
case kCheatCousteau:
|
||||
actHealDude(gMe->actor, 200, 200);
|
||||
gMe->packSlots[1].curAmount = 100;
|
||||
if (!VanillaMode())
|
||||
gMe->pwUpTime[kPwUpDivingSuit] = gPowerUpInfo[kPwUpDivingSuit].bonusTime;
|
||||
break;
|
||||
case kCheatForkYou:
|
||||
SetInfiniteAmmo(false);
|
||||
SetMap(false);
|
||||
SetWeapons(false);
|
||||
SetAmmo(false);
|
||||
SetArmor(false);
|
||||
SetToys(false);
|
||||
SetKeys(false);
|
||||
SetWooMode(true);
|
||||
powerupActivate(gMe, kPwUpDeliriumShroom);
|
||||
gMe->actor->xspr.health = 16;
|
||||
gMe->hasWeapon[1] = 1;
|
||||
gMe->curWeapon = kWeapNone;
|
||||
gMe->nextWeapon = kWeapPitchFork;
|
||||
break;
|
||||
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static bool cheatGoonies(cheatseq_t*)
|
||||
{
|
||||
SetMap(!gFullMap);
|
||||
return true;
|
||||
SetMap(!gFullMap);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cheatMario(cheatseq_t* c)
|
||||
{
|
||||
int nEpisode, nLevel;
|
||||
if (parseArgs((char*)c->Args, &nEpisode, &nLevel) == 2)
|
||||
int nEpisode, nLevel;
|
||||
if (parseArgs((char*)c->Args, &nEpisode, &nLevel) == 2)
|
||||
{
|
||||
auto map = FindMapByIndex(nEpisode, nLevel);
|
||||
if (map) DeferredStartGame(map, g_nextskill);
|
||||
}
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool cheatCalgon(cheatseq_t*)
|
||||
{
|
||||
levelEndLevel(0);
|
||||
return true;
|
||||
levelEndLevel(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static cheatseq_t s_CheatInfo[] = {
|
||||
{"MPKFA", nullptr, SendGenericCheat, 0, CHT_GOD },
|
||||
{"CAPINMYASS", nullptr, SendGenericCheat, 0, CHT_GODOFF },
|
||||
{"NOCAPINMYASS", nullptr, SendGenericCheat, 0, CHT_GODON },
|
||||
{"I WANNA BE LIKE KEVIN", nullptr, SendGenericCheat, 0, CHT_GODON },
|
||||
{"IDAHO", "give weapons" },
|
||||
{"GRISWOLD", "give armor" },
|
||||
{"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".)
|
||||
{"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)
|
||||
{"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)
|
||||
{"KEYMASTER", nullptr, SendGenericCheat, 0, kCheatKeyMaster }, // KEYMASTER (All keys)
|
||||
{"JOJO", nullptr, SendGenericCheat, 0, kCheatJoJo }, // JOJO (Drunk mode (same effect as getting bitten by red spider))
|
||||
{"SATCHEL", nullptr, SendGenericCheat, 0, kCheatSatchel }, // SATCHEL (Full inventory)
|
||||
{"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)
|
||||
{"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)
|
||||
{"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".)
|
||||
{"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)
|
||||
{"COUSTEAU", nullptr, SendGenericCheat, 0, kCheatCousteau }, // COUSTEAU (200% health and diving suit)
|
||||
{"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.)
|
||||
{"HONGKONG", nullptr, SendGenericCheat, 0, kCheatHongKong }, // HONGKONG (All weapons and infinite ammo)
|
||||
{"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))
|
||||
{"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)
|
||||
{"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 },
|
||||
{"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".)
|
||||
//{"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.)
|
||||
};
|
||||
{"MPKFA", nullptr, SendGenericCheat, 0, CHT_GOD },
|
||||
{"CAPINMYASS", nullptr, SendGenericCheat, 0, CHT_GODOFF },
|
||||
{"NOCAPINMYASS", nullptr, SendGenericCheat, 0, CHT_GODON },
|
||||
{"I WANNA BE LIKE KEVIN", nullptr, SendGenericCheat, 0, CHT_GODON },
|
||||
{"IDAHO", "give weapons" },
|
||||
{"GRISWOLD", "give armor" },
|
||||
{"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".)
|
||||
{"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)
|
||||
{"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)
|
||||
{"KEYMASTER", nullptr, SendGenericCheat, 0, kCheatKeyMaster }, // KEYMASTER (All keys)
|
||||
{"JOJO", nullptr, SendGenericCheat, 0, kCheatJoJo }, // JOJO (Drunk mode (same effect as getting bitten by red spider))
|
||||
{"SATCHEL", nullptr, SendGenericCheat, 0, kCheatSatchel }, // SATCHEL (Full inventory)
|
||||
{"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)
|
||||
{"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)
|
||||
{"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".)
|
||||
{"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)
|
||||
{"COUSTEAU", nullptr, SendGenericCheat, 0, kCheatCousteau }, // COUSTEAU (200% health and diving suit)
|
||||
{"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.)
|
||||
{"HONGKONG", nullptr, SendGenericCheat, 0, kCheatHongKong }, // HONGKONG (All weapons and infinite ammo)
|
||||
{"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))
|
||||
{"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)
|
||||
{"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 },
|
||||
{"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".)
|
||||
//{"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)
|
||||
{
|
||||
bPlayerCheated = 0;
|
||||
playerSetGodMode(gMe, 0);
|
||||
gNoClip = 0;
|
||||
packClear(gMe);
|
||||
gInfiniteAmmo = 0;
|
||||
gFullMap = 0;
|
||||
bPlayerCheated = 0;
|
||||
playerSetGodMode(gMe, 0);
|
||||
gNoClip = 0;
|
||||
packClear(gMe);
|
||||
gInfiniteAmmo = 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);
|
||||
if (skip) return;
|
||||
int type = ReadByte(stream);
|
||||
if (skip) return;
|
||||
|
||||
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");
|
||||
return;
|
||||
}
|
||||
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");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case GIVE_ALL:
|
||||
SetWeapons(true);
|
||||
SetAmmo(true);
|
||||
SetToys(true);
|
||||
SetArmor(true);
|
||||
SetKeys(true);
|
||||
bPlayerCheated = true;
|
||||
break;
|
||||
switch (type)
|
||||
{
|
||||
case GIVE_ALL:
|
||||
SetWeapons(true);
|
||||
SetAmmo(true);
|
||||
SetToys(true);
|
||||
SetArmor(true);
|
||||
SetKeys(true);
|
||||
bPlayerCheated = true;
|
||||
break;
|
||||
|
||||
case GIVE_HEALTH:
|
||||
actHealDude(gMe->actor, 200, 200);
|
||||
bPlayerCheated = true;
|
||||
break;
|
||||
case GIVE_HEALTH:
|
||||
actHealDude(gMe->actor, 200, 200);
|
||||
bPlayerCheated = true;
|
||||
break;
|
||||
|
||||
case GIVE_WEAPONS:
|
||||
SetWeapons(true);
|
||||
bPlayerCheated = true;
|
||||
break;
|
||||
case GIVE_WEAPONS:
|
||||
SetWeapons(true);
|
||||
bPlayerCheated = true;
|
||||
break;
|
||||
|
||||
case GIVE_AMMO:
|
||||
SetAmmo(true);
|
||||
bPlayerCheated = true;
|
||||
break;
|
||||
case GIVE_AMMO:
|
||||
SetAmmo(true);
|
||||
bPlayerCheated = true;
|
||||
break;
|
||||
|
||||
case GIVE_ARMOR:
|
||||
SetArmor(true);
|
||||
bPlayerCheated = true;
|
||||
break;
|
||||
case GIVE_ARMOR:
|
||||
SetArmor(true);
|
||||
bPlayerCheated = true;
|
||||
break;
|
||||
|
||||
case GIVE_KEYS:
|
||||
SetKeys(true);
|
||||
bPlayerCheated = true;
|
||||
break;
|
||||
case GIVE_KEYS:
|
||||
SetKeys(true);
|
||||
bPlayerCheated = true;
|
||||
break;
|
||||
|
||||
case GIVE_INVENTORY:
|
||||
SetToys(true);
|
||||
bPlayerCheated = true;
|
||||
break;
|
||||
case GIVE_INVENTORY:
|
||||
SetToys(true);
|
||||
bPlayerCheated = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void InitCheats()
|
||||
{
|
||||
SetCheats(s_CheatInfo, countof(s_CheatInfo));
|
||||
Net_SetCommandHandler(DEM_GIVE, cmd_Give);
|
||||
SetCheats(s_CheatInfo, countof(s_CheatInfo));
|
||||
Net_SetCommandHandler(DEM_GIVE, cmd_Give);
|
||||
}
|
||||
|
||||
END_BLD_NS
|
||||
|
|
|
@ -28,11 +28,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
BEGIN_BLD_NS
|
||||
|
||||
enum MESSAGE_PRIORITY {
|
||||
MESSAGE_PRIORITY_PICKUP = -10,
|
||||
MESSAGE_PRIORITY_NORMAL = 0,
|
||||
MESSAGE_PRIORITY_SECRET = 10,
|
||||
MESSAGE_PRIORITY_INI = 20,
|
||||
MESSAGE_PRIORITY_SYSTEM = 100
|
||||
MESSAGE_PRIORITY_PICKUP = -10,
|
||||
MESSAGE_PRIORITY_NORMAL = 0,
|
||||
MESSAGE_PRIORITY_SECRET = 10,
|
||||
MESSAGE_PRIORITY_INI = 20,
|
||||
MESSAGE_PRIORITY_SYSTEM = 100
|
||||
};
|
||||
|
||||
extern bool bPlayerCheated;
|
||||
|
|
|
@ -35,120 +35,126 @@ int mirrorcnt, mirrorsector, mirrorwall[4];
|
|||
|
||||
MIRROR mirror[16]; // only needed by Polymost.
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void InitMirrors(void)
|
||||
{
|
||||
r_rortexture = 4080;
|
||||
r_rortexturerange = 16;
|
||||
r_rortexture = 4080;
|
||||
r_rortexturerange = 16;
|
||||
|
||||
mirrorcnt = 0;
|
||||
tileDelete(504);
|
||||
portalClear();
|
||||
|
||||
mirrorcnt = 0;
|
||||
tileDelete(504);
|
||||
portalClear();
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
tileDelete(4080 + i);
|
||||
}
|
||||
for (int i = (int)wall.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
auto pWalli = &wall[i];
|
||||
if (mirrorcnt == 16)
|
||||
break;
|
||||
int nTile = 4080+mirrorcnt;
|
||||
if (pWalli->overpicnum == 504)
|
||||
{
|
||||
if (pWalli->extra > 0 && pWalli->type == kWallStack)
|
||||
{
|
||||
pWalli->overpicnum = nTile;
|
||||
for (int i = (int)wall.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
auto pWalli = &wall[i];
|
||||
if (mirrorcnt == 16)
|
||||
break;
|
||||
int nTile = 4080 + mirrorcnt;
|
||||
if (pWalli->overpicnum == 504)
|
||||
{
|
||||
if (pWalli->extra > 0 && pWalli->type == kWallStack)
|
||||
{
|
||||
pWalli->overpicnum = nTile;
|
||||
|
||||
mirror[mirrorcnt].wallnum = i;
|
||||
mirror[mirrorcnt].type = 0;
|
||||
pWalli->cstat |= CSTAT_WALL_1WAY;
|
||||
int tmp = pWalli->xw().data;
|
||||
int j;
|
||||
for (j = (int)wall.Size() - 1; j >= 0; j--)
|
||||
{
|
||||
if (j == i)
|
||||
continue;
|
||||
auto pWallj = &wall[j];
|
||||
if (pWallj->extra > 0 && pWallj->type == kWallStack)
|
||||
{
|
||||
if (tmp != pWallj->xw().data)
|
||||
continue;
|
||||
pWalli->hitag = j; // hitag is only used by Polymost, the new renderer uses external links.
|
||||
pWallj->hitag = i;
|
||||
mirror[mirrorcnt].link = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j < 0)
|
||||
{
|
||||
Printf(PRINT_HIGH, "wall[%d] has no matching wall link! (data=%d)\n", i, tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
mirrorcnt++;
|
||||
pWalli->portalflags = PORTAL_WALL_VIEW;
|
||||
pWalli->portalnum = j;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (pWalli->picnum == 504)
|
||||
{
|
||||
mirror[mirrorcnt].link = i;
|
||||
mirror[mirrorcnt].wallnum = i;
|
||||
pWalli->picnum = nTile;
|
||||
mirror[mirrorcnt].type = 0;
|
||||
pWalli->cstat |= CSTAT_WALL_1WAY;
|
||||
pWalli->portalflags = PORTAL_WALL_MIRROR;
|
||||
mirrorcnt++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
for (int i = (int)sector.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
if (mirrorcnt >= 15)
|
||||
break;
|
||||
mirror[mirrorcnt].wallnum = i;
|
||||
mirror[mirrorcnt].type = 0;
|
||||
pWalli->cstat |= CSTAT_WALL_1WAY;
|
||||
int tmp = pWalli->xw().data;
|
||||
int j;
|
||||
for (j = (int)wall.Size() - 1; j >= 0; j--)
|
||||
{
|
||||
if (j == i)
|
||||
continue;
|
||||
auto pWallj = &wall[j];
|
||||
if (pWallj->extra > 0 && pWallj->type == kWallStack)
|
||||
{
|
||||
if (tmp != pWallj->xw().data)
|
||||
continue;
|
||||
pWalli->hitag = j; // hitag is only used by Polymost, the new renderer uses external links.
|
||||
pWallj->hitag = i;
|
||||
mirror[mirrorcnt].link = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j < 0)
|
||||
{
|
||||
Printf(PRINT_HIGH, "wall[%d] has no matching wall link! (data=%d)\n", i, tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
mirrorcnt++;
|
||||
pWalli->portalflags = PORTAL_WALL_VIEW;
|
||||
pWalli->portalnum = j;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (pWalli->picnum == 504)
|
||||
{
|
||||
mirror[mirrorcnt].link = i;
|
||||
mirror[mirrorcnt].wallnum = i;
|
||||
pWalli->picnum = nTile;
|
||||
mirror[mirrorcnt].type = 0;
|
||||
pWalli->cstat |= CSTAT_WALL_1WAY;
|
||||
pWalli->portalflags = PORTAL_WALL_MIRROR;
|
||||
mirrorcnt++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
for (int i = (int)sector.Size() - 1; i >= 0; i--)
|
||||
{
|
||||
if (mirrorcnt >= 15)
|
||||
break;
|
||||
|
||||
auto secti = §or[i];
|
||||
if (secti->floorpicnum == 504)
|
||||
{
|
||||
auto link = barrier_cast<DBloodActor*>(secti->upperLink);
|
||||
if (link == nullptr)
|
||||
continue;
|
||||
auto link2 = link->GetOwner();
|
||||
if (link2 == nullptr)
|
||||
continue;
|
||||
auto secti = §or[i];
|
||||
if (secti->floorpicnum == 504)
|
||||
{
|
||||
auto link = barrier_cast<DBloodActor*>(secti->upperLink);
|
||||
if (link == nullptr)
|
||||
continue;
|
||||
auto link2 = link->GetOwner();
|
||||
if (link2 == nullptr)
|
||||
continue;
|
||||
|
||||
auto sectj = link2->spr.sector();
|
||||
int j = sectnum(sectj);
|
||||
if (sectj->ceilingpicnum != 504)
|
||||
I_Error("Lower link sector %d doesn't have mirror picnum\n", j);
|
||||
mirror[mirrorcnt].type = 2;
|
||||
mirror[mirrorcnt].dx = link2->spr.pos.X - link->spr.pos.X;
|
||||
mirror[mirrorcnt].dy = link2->spr.pos.Y - link->spr.pos.Y;
|
||||
mirror[mirrorcnt].dz = link2->spr.pos.Z - link->spr.pos.Z;
|
||||
mirror[mirrorcnt].wallnum = i;
|
||||
mirror[mirrorcnt].link = j;
|
||||
secti->floorpicnum = 4080 + mirrorcnt;
|
||||
secti->portalflags = PORTAL_SECTOR_FLOOR;
|
||||
secti->portalnum = portalAdd(PORTAL_SECTOR_FLOOR, j, mirror[mirrorcnt].dx, mirror[mirrorcnt].dy, mirror[mirrorcnt].dz);
|
||||
mirrorcnt++;
|
||||
mirror[mirrorcnt].type = 1;
|
||||
mirror[mirrorcnt].dx = link->spr.pos.X - link2->spr.pos.X;
|
||||
mirror[mirrorcnt].dy = link->spr.pos.Y - link2->spr.pos.Y;
|
||||
mirror[mirrorcnt].dz = link->spr.pos.Z - link2->spr.pos.Z;
|
||||
mirror[mirrorcnt].wallnum = j;
|
||||
mirror[mirrorcnt].link = i;
|
||||
sectj->ceilingpicnum = 4080 + mirrorcnt;
|
||||
sectj->portalflags = PORTAL_SECTOR_CEILING;
|
||||
sectj->portalnum = portalAdd(PORTAL_SECTOR_CEILING, i, mirror[mirrorcnt].dx, mirror[mirrorcnt].dy, mirror[mirrorcnt].dz);
|
||||
mirrorcnt++;
|
||||
}
|
||||
}
|
||||
mirrorsector = sector.Size();
|
||||
mergePortals();
|
||||
InitPolymostMirrorHack();
|
||||
auto sectj = link2->spr.sector();
|
||||
int j = sectnum(sectj);
|
||||
if (sectj->ceilingpicnum != 504)
|
||||
I_Error("Lower link sector %d doesn't have mirror picnum\n", j);
|
||||
mirror[mirrorcnt].type = 2;
|
||||
mirror[mirrorcnt].dx = link2->spr.pos.X - link->spr.pos.X;
|
||||
mirror[mirrorcnt].dy = link2->spr.pos.Y - link->spr.pos.Y;
|
||||
mirror[mirrorcnt].dz = link2->spr.pos.Z - link->spr.pos.Z;
|
||||
mirror[mirrorcnt].wallnum = i;
|
||||
mirror[mirrorcnt].link = j;
|
||||
secti->floorpicnum = 4080 + mirrorcnt;
|
||||
secti->portalflags = PORTAL_SECTOR_FLOOR;
|
||||
secti->portalnum = portalAdd(PORTAL_SECTOR_FLOOR, j, mirror[mirrorcnt].dx, mirror[mirrorcnt].dy, mirror[mirrorcnt].dz);
|
||||
mirrorcnt++;
|
||||
mirror[mirrorcnt].type = 1;
|
||||
mirror[mirrorcnt].dx = link->spr.pos.X - link2->spr.pos.X;
|
||||
mirror[mirrorcnt].dy = link->spr.pos.Y - link2->spr.pos.Y;
|
||||
mirror[mirrorcnt].dz = link->spr.pos.Z - link2->spr.pos.Z;
|
||||
mirror[mirrorcnt].wallnum = j;
|
||||
mirror[mirrorcnt].link = i;
|
||||
sectj->ceilingpicnum = 4080 + mirrorcnt;
|
||||
sectj->portalflags = PORTAL_SECTOR_CEILING;
|
||||
sectj->portalnum = portalAdd(PORTAL_SECTOR_CEILING, i, mirror[mirrorcnt].dx, mirror[mirrorcnt].dy, mirror[mirrorcnt].dz);
|
||||
mirrorcnt++;
|
||||
}
|
||||
}
|
||||
mirrorsector = sector.Size();
|
||||
mergePortals();
|
||||
InitPolymostMirrorHack();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -161,7 +167,7 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, MIRROR& w, MIRROR*
|
|||
{
|
||||
if (arc.BeginObject(keyname))
|
||||
{
|
||||
arc ("type", w.type)
|
||||
arc("type", w.type)
|
||||
("link", w.link)
|
||||
("dx", w.dx)
|
||||
("dy", w.dy)
|
||||
|
@ -172,12 +178,18 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, MIRROR& w, MIRROR*
|
|||
return arc;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void SerializeMirrors(FSerializer& arc)
|
||||
{
|
||||
if (arc.BeginObject("mirror"))
|
||||
{
|
||||
arc("mirrorcnt", mirrorcnt)
|
||||
.Array("mirror", mirror, countof(mirror))
|
||||
arc("mirrorcnt", mirrorcnt)
|
||||
.Array("mirror", mirror, countof(mirror))
|
||||
.EndObject();
|
||||
}
|
||||
|
||||
|
@ -193,8 +205,8 @@ void SerializeMirrors(FSerializer& arc)
|
|||
{
|
||||
tileDelete(4080 + i);
|
||||
}
|
||||
InitPolymostMirrorHack();
|
||||
}
|
||||
InitPolymostMirrorHack();
|
||||
}
|
||||
}
|
||||
|
||||
END_BLD_NS
|
||||
|
|
|
@ -32,24 +32,24 @@ unsigned int randSeed = 1;
|
|||
|
||||
unsigned int qrand(void)
|
||||
{
|
||||
if (randSeed&0x80000000)
|
||||
randSeed = ((randSeed<<1)^0x20000004)|0x1;
|
||||
else
|
||||
randSeed = randSeed<<1;
|
||||
return randSeed&0x7fff;
|
||||
if (randSeed & 0x80000000)
|
||||
randSeed = ((randSeed << 1) ^ 0x20000004) | 0x1;
|
||||
else
|
||||
randSeed = randSeed << 1;
|
||||
return randSeed & 0x7fff;
|
||||
}
|
||||
|
||||
int wRandSeed = 1;
|
||||
|
||||
int wrand(void)
|
||||
{
|
||||
wRandSeed = (wRandSeed*1103515245)+12345;
|
||||
return FixedToInt(wRandSeed)&0x7fff;
|
||||
wRandSeed = (wRandSeed * 1103515245) + 12345;
|
||||
return FixedToInt(wRandSeed) & 0x7fff;
|
||||
}
|
||||
|
||||
void wsrand(int seed)
|
||||
{
|
||||
wRandSeed = seed;
|
||||
wRandSeed = seed;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ int wrand(void);
|
|||
void wsrand(int);
|
||||
void FireInit(void);
|
||||
void FireProcess(void);
|
||||
void UpdateNetworkMenus(void);
|
||||
void UpdateNetworkMenus(void);
|
||||
void InitMirrors(void);
|
||||
void setPortalFlags(int mode);
|
||||
void processSpritesOnOtherSideOfPortal(int x, int y, int interpolation);
|
||||
|
@ -46,61 +46,61 @@ int qanimateoffs(int a1, int a2);
|
|||
|
||||
struct PLAYER;
|
||||
|
||||
bool checkFired6or7(PLAYER *pPlayer);
|
||||
bool checkFired6or7(PLAYER* pPlayer);
|
||||
void WeaponInit(void);
|
||||
void WeaponDraw(PLAYER *pPlayer, int a2, double a3, double a4, int a5);
|
||||
void WeaponRaise(PLAYER *pPlayer);
|
||||
void WeaponLower(PLAYER *pPlayer);
|
||||
int WeaponUpgrade(PLAYER *pPlayer, int newWeapon);
|
||||
void WeaponProcess(PLAYER *pPlayer);
|
||||
void WeaponDraw(PLAYER* pPlayer, int a2, double a3, double a4, int a5);
|
||||
void WeaponRaise(PLAYER* pPlayer);
|
||||
void WeaponLower(PLAYER* pPlayer);
|
||||
int WeaponUpgrade(PLAYER* pPlayer, int newWeapon);
|
||||
void WeaponProcess(PLAYER* pPlayer);
|
||||
void WeaponUpdateState(PLAYER* pPlayer);
|
||||
void teslaHit(DBloodActor *pMissile, int a2);
|
||||
void teslaHit(DBloodActor* pMissile, int a2);
|
||||
void WeaponPrecache();
|
||||
|
||||
struct ZONE {
|
||||
int x, y, z;
|
||||
int x, y, z;
|
||||
sectortype* sector;
|
||||
short ang;
|
||||
};
|
||||
extern ZONE gStartZone[8];
|
||||
|
||||
void warpInit(TArray<DBloodActor*>& actors);
|
||||
int CheckLink(DBloodActor *pSprite);
|
||||
int CheckLink(int *x, int *y, int *z, sectortype** pSector);
|
||||
int CheckLink(DBloodActor* pSprite);
|
||||
int CheckLink(int* x, int* y, int* z, sectortype** pSector);
|
||||
|
||||
int GetOctant(int x, int y);
|
||||
void RotateVector(int *dx, int *dy, int nAngle);
|
||||
void RotatePoint(int *x, int *y, int nAngle, int ox, int oy);
|
||||
void RotateVector(int* dx, int* dy, int nAngle);
|
||||
void RotatePoint(int* x, int* y, int nAngle, int ox, int oy);
|
||||
|
||||
#include "m_fixed.h"
|
||||
|
||||
inline int Sin(int ang)
|
||||
{
|
||||
return sintable[ang & 2047];
|
||||
return sintable[ang & 2047];
|
||||
}
|
||||
|
||||
inline int Cos(int ang)
|
||||
{
|
||||
return sintable[(ang + 512) & 2047];
|
||||
return sintable[(ang + 512) & 2047];
|
||||
}
|
||||
|
||||
enum SurfaceType {
|
||||
kSurfNone = 0,
|
||||
kSurfStone,
|
||||
kSurfMetal,
|
||||
kSurfWood,
|
||||
kSurfFlesh,
|
||||
kSurfWater,
|
||||
kSurfDirt,
|
||||
kSurfClay,
|
||||
kSurfSnow,
|
||||
kSurfIce,
|
||||
kSurfLeaves,
|
||||
kSurfCloth,
|
||||
kSurfPlant,
|
||||
kSurfGoo,
|
||||
kSurfLava,
|
||||
kSurfMax
|
||||
kSurfNone = 0,
|
||||
kSurfStone,
|
||||
kSurfMetal,
|
||||
kSurfWood,
|
||||
kSurfFlesh,
|
||||
kSurfWater,
|
||||
kSurfDirt,
|
||||
kSurfClay,
|
||||
kSurfSnow,
|
||||
kSurfIce,
|
||||
kSurfLeaves,
|
||||
kSurfCloth,
|
||||
kSurfPlant,
|
||||
kSurfGoo,
|
||||
kSurfLava,
|
||||
kSurfMax
|
||||
};
|
||||
|
||||
extern uint8_t surfType[MAXTILES];
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -42,222 +42,222 @@ BEGIN_BLD_NS
|
|||
|
||||
enum
|
||||
{
|
||||
// CONSTANTS
|
||||
// additional non-thing proximity, sight and physics sprites
|
||||
kMaxSuperXSprites = 512,
|
||||
kMaxTrackingConditions = 64,
|
||||
kMaxTracedObjects = 32, // per one tracking condition
|
||||
// CONSTANTS
|
||||
// additional non-thing proximity, sight and physics sprites
|
||||
kMaxSuperXSprites = 512,
|
||||
kMaxTrackingConditions = 64,
|
||||
kMaxTracedObjects = 32, // per one tracking condition
|
||||
|
||||
// additional physics attributes for debris sprites
|
||||
kPhysDebrisFloat = 0x0008, // *debris* slowly goes up and down from it's position
|
||||
kPhysDebrisFly = 0x0010, // *debris* affected by negative gravity (fly instead of falling)
|
||||
kPhysDebrisSwim = 0x0020, // *debris* can swim underwater (instead of drowning)
|
||||
kPhysDebrisTouch = 0x0040, // *debris* can be moved via touch
|
||||
kPhysDebrisVector = 0x0400, // *debris* can be affected by vector weapons
|
||||
kPhysDebrisExplode = 0x0800, // *debris* can be affected by explosions
|
||||
// additional physics attributes for debris sprites
|
||||
kPhysDebrisFloat = 0x0008, // *debris* slowly goes up and down from it's position
|
||||
kPhysDebrisFly = 0x0010, // *debris* affected by negative gravity (fly instead of falling)
|
||||
kPhysDebrisSwim = 0x0020, // *debris* can swim underwater (instead of drowning)
|
||||
kPhysDebrisTouch = 0x0040, // *debris* can be moved via touch
|
||||
kPhysDebrisVector = 0x0400, // *debris* can be affected by vector weapons
|
||||
kPhysDebrisExplode = 0x0800, // *debris* can be affected by explosions
|
||||
|
||||
// *modern types only hitag*
|
||||
kModernTypeFlag0 = 0x0000,
|
||||
kModernTypeFlag1 = 0x0001,
|
||||
kModernTypeFlag2 = 0x0002,
|
||||
kModernTypeFlag3 = 0x0003,
|
||||
kModernTypeFlag4 = 0x0004,
|
||||
kModernTypeFlag8 = 0x0008,
|
||||
kModernTypeFlag16 = 0x0010,
|
||||
// *modern types only hitag*
|
||||
kModernTypeFlag0 = 0x0000,
|
||||
kModernTypeFlag1 = 0x0001,
|
||||
kModernTypeFlag2 = 0x0002,
|
||||
kModernTypeFlag3 = 0x0003,
|
||||
kModernTypeFlag4 = 0x0004,
|
||||
kModernTypeFlag8 = 0x0008,
|
||||
kModernTypeFlag16 = 0x0010,
|
||||
|
||||
kMaxRandomizeRetries = 16,
|
||||
kPercFull = 100,
|
||||
kCondRange = 100,
|
||||
kMaxRandomizeRetries = 16,
|
||||
kPercFull = 100,
|
||||
kCondRange = 100,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kPatrolStateSize = 42,
|
||||
kPatrolAlarmSeeDist = 10000,
|
||||
kPatrolAlarmHearDist = 10000,
|
||||
kMaxPatrolVelocity = 500000,
|
||||
kMaxPatrolCrouchVelocity = (kMaxPatrolVelocity >> 1),
|
||||
kMaxPatrolSpotValue = 500,
|
||||
kMinPatrolTurnDelay = 8,
|
||||
kPatrolTurnDelayRange = 20,
|
||||
kPatrolStateSize = 42,
|
||||
kPatrolAlarmSeeDist = 10000,
|
||||
kPatrolAlarmHearDist = 10000,
|
||||
kMaxPatrolVelocity = 500000,
|
||||
kMaxPatrolCrouchVelocity = (kMaxPatrolVelocity >> 1),
|
||||
kMaxPatrolSpotValue = 500,
|
||||
kMinPatrolTurnDelay = 8,
|
||||
kPatrolTurnDelayRange = 20,
|
||||
|
||||
kDudeFlagStealth = 0x0001,
|
||||
kDudeFlagCrouch = 0x0002,
|
||||
kDudeFlagStealth = 0x0001,
|
||||
kDudeFlagCrouch = 0x0002,
|
||||
|
||||
kSlopeDist = 0x20,
|
||||
kEffectGenCallbackBase = 200,
|
||||
kTriggerSpriteScreen = 0x0001,
|
||||
kTriggerSpriteAim = 0x0002,
|
||||
kSlopeDist = 0x20,
|
||||
kEffectGenCallbackBase = 200,
|
||||
kTriggerSpriteScreen = 0x0001,
|
||||
kTriggerSpriteAim = 0x0002,
|
||||
|
||||
kMinAllowedPowerup = kPwUpFeatherFall,
|
||||
kMaxAllowedPowerup = kMaxPowerUps
|
||||
kMinAllowedPowerup = kPwUpFeatherFall,
|
||||
kMaxAllowedPowerup = kMaxPowerUps
|
||||
};
|
||||
|
||||
// modern statnums
|
||||
enum {
|
||||
kStatModernBase = 20,
|
||||
kStatModernDudeTargetChanger = kStatModernBase,
|
||||
kStatModernCondition = 21,
|
||||
kStatModernEventRedirector = 22,
|
||||
kStatModernPlayerLinker = 23,
|
||||
kStatModernBrokenDudeLeech = 24,
|
||||
kStatModernQavScene = 25,
|
||||
kStatModernWindGen = 26,
|
||||
kStatModernStealthRegion = 27,
|
||||
kStatModernTmp = 39,
|
||||
kStatModernMax = 40,
|
||||
kStatModernBase = 20,
|
||||
kStatModernDudeTargetChanger = kStatModernBase,
|
||||
kStatModernCondition = 21,
|
||||
kStatModernEventRedirector = 22,
|
||||
kStatModernPlayerLinker = 23,
|
||||
kStatModernBrokenDudeLeech = 24,
|
||||
kStatModernQavScene = 25,
|
||||
kStatModernWindGen = 26,
|
||||
kStatModernStealthRegion = 27,
|
||||
kStatModernTmp = 39,
|
||||
kStatModernMax = 40,
|
||||
};
|
||||
|
||||
// modern sprite types
|
||||
enum {
|
||||
kModernStealthRegion = 16,
|
||||
kModernCustomDudeSpawn = 24,
|
||||
kModernRandomTX = 25,
|
||||
kModernSequentialTX = 26,
|
||||
kModernSeqSpawner = 27,
|
||||
kModernObjPropertiesChanger = 28,
|
||||
kModernObjPicnumChanger = 29,
|
||||
kModernObjSizeChanger = 31,
|
||||
kModernDudeTargetChanger = 33,
|
||||
kModernSectorFXChanger = 34,
|
||||
kModernObjDataChanger = 35,
|
||||
kModernSpriteDamager = 36,
|
||||
kModernObjDataAccumulator = 37,
|
||||
kModernEffectSpawner = 38,
|
||||
kModernWindGenerator = 39,
|
||||
kModernRandom = 40,
|
||||
kModernRandom2 = 80,
|
||||
kItemShroomGrow = 129,
|
||||
kItemShroomShrink = 130,
|
||||
kItemModernMapLevel = 150, // once picked up, draws whole minimap
|
||||
kDudeModernCustom = kDudeVanillaMax,
|
||||
kDudeModernCustomBurning = 255,
|
||||
kModernThingTNTProx = 433, // detects only players
|
||||
kModernThingThrowableRock = 434, // does small damage if hits target
|
||||
kModernThingEnemyLifeLeech = 435, // the same as normal, except it aims in specified target only
|
||||
kModernPlayerControl = 500, /// WIP
|
||||
kModernCondition = 501, /// WIP, sends command only if specified conditions == true
|
||||
kModernConditionFalse = 502, /// WIP, sends command only if specified conditions != true
|
||||
kModernSlopeChanger = 504,
|
||||
kGenModernMissileUniversal = 704,
|
||||
kGenModernSound = 708,
|
||||
kModernStealthRegion = 16,
|
||||
kModernCustomDudeSpawn = 24,
|
||||
kModernRandomTX = 25,
|
||||
kModernSequentialTX = 26,
|
||||
kModernSeqSpawner = 27,
|
||||
kModernObjPropertiesChanger = 28,
|
||||
kModernObjPicnumChanger = 29,
|
||||
kModernObjSizeChanger = 31,
|
||||
kModernDudeTargetChanger = 33,
|
||||
kModernSectorFXChanger = 34,
|
||||
kModernObjDataChanger = 35,
|
||||
kModernSpriteDamager = 36,
|
||||
kModernObjDataAccumulator = 37,
|
||||
kModernEffectSpawner = 38,
|
||||
kModernWindGenerator = 39,
|
||||
kModernRandom = 40,
|
||||
kModernRandom2 = 80,
|
||||
kItemShroomGrow = 129,
|
||||
kItemShroomShrink = 130,
|
||||
kItemModernMapLevel = 150, // once picked up, draws whole minimap
|
||||
kDudeModernCustom = kDudeVanillaMax,
|
||||
kDudeModernCustomBurning = 255,
|
||||
kModernThingTNTProx = 433, // detects only players
|
||||
kModernThingThrowableRock = 434, // does small damage if hits target
|
||||
kModernThingEnemyLifeLeech = 435, // the same as normal, except it aims in specified target only
|
||||
kModernPlayerControl = 500, /// WIP
|
||||
kModernCondition = 501, /// WIP, sends command only if specified conditions == true
|
||||
kModernConditionFalse = 502, /// WIP, sends command only if specified conditions != true
|
||||
kModernSlopeChanger = 504,
|
||||
kGenModernMissileUniversal = 704,
|
||||
kGenModernSound = 708,
|
||||
};
|
||||
|
||||
// type of random
|
||||
enum {
|
||||
kRandomizeItem = 0,
|
||||
kRandomizeDude = 1,
|
||||
kRandomizeTX = 2,
|
||||
kRandomizeItem = 0,
|
||||
kRandomizeDude = 1,
|
||||
kRandomizeTX = 2,
|
||||
};
|
||||
|
||||
// type of object
|
||||
enum {
|
||||
OBJ_WALL = 0,
|
||||
OBJ_SPRITE = 3,
|
||||
OBJ_SECTOR = 6,
|
||||
OBJ_WALL = 0,
|
||||
OBJ_SPRITE = 3,
|
||||
OBJ_SECTOR = 6,
|
||||
};
|
||||
|
||||
enum {
|
||||
kCondGameBase = 0,
|
||||
kCondGameMax = 50,
|
||||
kCondMixedBase = 100,
|
||||
kCondMixedMax = 200,
|
||||
kCondWallBase = 200,
|
||||
kCondWallMax = 300,
|
||||
kCondSectorBase = 300,
|
||||
kCondSectorMax = 400,
|
||||
kCondPlayerBase = 400,
|
||||
kCondPlayerMax = 450,
|
||||
kCondDudeBase = 450,
|
||||
kCondDudeMax = 500,
|
||||
kCondSpriteBase = 500,
|
||||
kCondSpriteMax = 600,
|
||||
kCondGameBase = 0,
|
||||
kCondGameMax = 50,
|
||||
kCondMixedBase = 100,
|
||||
kCondMixedMax = 200,
|
||||
kCondWallBase = 200,
|
||||
kCondWallMax = 300,
|
||||
kCondSectorBase = 300,
|
||||
kCondSectorMax = 400,
|
||||
kCondPlayerBase = 400,
|
||||
kCondPlayerMax = 450,
|
||||
kCondDudeBase = 450,
|
||||
kCondDudeMax = 500,
|
||||
kCondSpriteBase = 500,
|
||||
kCondSpriteMax = 600,
|
||||
};
|
||||
|
||||
enum {
|
||||
kCondSerialSector = 100000,
|
||||
kCondSerialWall = 200000,
|
||||
kCondSerialSprite = 300000,
|
||||
kCondSerialMax = 400000,
|
||||
kCondSerialSector = 100000,
|
||||
kCondSerialWall = 200000,
|
||||
kCondSerialSprite = 300000,
|
||||
kCondSerialMax = 400000,
|
||||
};
|
||||
|
||||
enum {
|
||||
kPatrolMoveForward = 0,
|
||||
kPatrolMoveBackward = 1,
|
||||
kPatrolMoveForward = 0,
|
||||
kPatrolMoveBackward = 1,
|
||||
};
|
||||
|
||||
// - STRUCTS ------------------------------------------------------------------
|
||||
struct SPRITEMASS { // sprite mass info for getSpriteMassBySize();
|
||||
int seqId;
|
||||
int16_t picnum; // mainly needs for moving debris
|
||||
int16_t xrepeat;
|
||||
int16_t yrepeat;
|
||||
int16_t clipdist; // mass multiplier
|
||||
int mass;
|
||||
int16_t airVel; // mainly needs for moving debris
|
||||
int fraction; // mainly needs for moving debris
|
||||
int seqId;
|
||||
int16_t picnum; // mainly needs for moving debris
|
||||
int16_t xrepeat;
|
||||
int16_t yrepeat;
|
||||
int16_t clipdist; // mass multiplier
|
||||
int mass;
|
||||
int16_t airVel; // 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
|
||||
DBloodActor* initiator = nullptr; // index of sprite which triggered qav scene
|
||||
QAV* qavResrc = nullptr;
|
||||
short dummy = -1;
|
||||
DBloodActor* initiator = nullptr; // index of sprite which triggered qav scene
|
||||
QAV* qavResrc = nullptr;
|
||||
short dummy = -1;
|
||||
};
|
||||
|
||||
struct THINGINFO_EXTRA {
|
||||
bool allowThrow; // indicates if kDudeModernCustom can throw it
|
||||
bool allowThrow; // indicates if kDudeModernCustom can throw it
|
||||
};
|
||||
|
||||
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 {
|
||||
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 allowImpact; // allow to trigger object with Impact flag enabled with this missile
|
||||
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 allowImpact; // allow to trigger object with Impact flag enabled with this missile
|
||||
};
|
||||
|
||||
struct DUDEINFO_EXTRA {
|
||||
bool flying; // used by kModernDudeTargetChanger (ai fight)
|
||||
bool melee; // used by kModernDudeTargetChanger (ai fight)
|
||||
int idlgseqofs : 6; // used for patrol
|
||||
int mvegseqofs : 6; // used for patrol
|
||||
int idlwseqofs : 6; // used for patrol
|
||||
int mvewseqofs : 6; // used for patrol
|
||||
int idlcseqofs : 6; // used for patrol
|
||||
int mvecseqofs : 6; // used for patrol
|
||||
|
||||
bool flying; // used by kModernDudeTargetChanger (ai fight)
|
||||
bool melee; // used by kModernDudeTargetChanger (ai fight)
|
||||
int idlgseqofs : 6; // used for patrol
|
||||
int mvegseqofs : 6; // used for patrol
|
||||
int idlwseqofs : 6; // used for patrol
|
||||
int mvewseqofs : 6; // used for patrol
|
||||
int idlcseqofs : 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)
|
||||
QAVSCENE qavScene;
|
||||
QAVSCENE qavScene;
|
||||
};
|
||||
|
||||
struct OBJECTS_TO_TRACK {
|
||||
uint8_t cmd;
|
||||
EventObject obj;
|
||||
uint8_t cmd;
|
||||
EventObject obj;
|
||||
};
|
||||
|
||||
struct TRCONDITION {
|
||||
DBloodActor* actor;
|
||||
uint8_t length;
|
||||
OBJECTS_TO_TRACK obj[kMaxTracedObjects];
|
||||
DBloodActor* actor;
|
||||
uint8_t length;
|
||||
OBJECTS_TO_TRACK obj[kMaxTracedObjects];
|
||||
};
|
||||
|
||||
struct PATROL_FOUND_SOUNDS {
|
||||
|
||||
int snd;
|
||||
int max;
|
||||
int cur;
|
||||
int snd;
|
||||
int max;
|
||||
int cur;
|
||||
|
||||
};
|
||||
|
||||
struct CONDITION_TYPE_NAMES {
|
||||
|
||||
int rng1;
|
||||
int rng2;
|
||||
char name[32];
|
||||
int rng1;
|
||||
int rng2;
|
||||
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 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 modernTypeOperateSprite(DBloodActor*, 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 playerQavSceneReset(PLAYER* pPlayer);
|
||||
// ------------------------------------------------------------------------- //
|
||||
void callbackUniMissileBurst(DBloodActor*actor, sectortype* nSprite);
|
||||
void callbackUniMissileBurst(DBloodActor* actor, sectortype* nSprite);
|
||||
void callbackMakeMissileBlocking(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 aiPatrolTurn(DBloodActor* actor);
|
||||
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) {
|
||||
return (pAiState && pAiState->stateType >= kAiStatePatrolWaitL && pAiState->stateType <= kAiStatePatrolWaitW);
|
||||
return (pAiState && pAiState->stateType >= kAiStatePatrolWaitL && pAiState->stateType <= kAiStatePatrolWaitW);
|
||||
}
|
||||
|
||||
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) {
|
||||
return (pAiState && pAiState->stateType >= kAiStatePatrolTurnL && pAiState->stateType <= kAiStatePatrolTurnW);
|
||||
return (pAiState && pAiState->stateType >= kAiStatePatrolTurnL && pAiState->stateType <= kAiStatePatrolTurnW);
|
||||
}
|
||||
|
||||
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) {
|
||||
return (nAiStateType >= kAiStatePatrolBase && nAiStateType < kAiStatePatrolMax);
|
||||
return (nAiStateType >= kAiStatePatrolBase && nAiStateType < kAiStatePatrolMax);
|
||||
}
|
||||
// ------------------------------------------------------------------------- //
|
||||
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)
|
||||
{
|
||||
return (val > min && val < max);
|
||||
return (val > min && val < max);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -33,62 +33,62 @@ BEGIN_BLD_NS
|
|||
|
||||
void GameInterface::WarpToCoords(int x, int y, int z, int ang, int horz)
|
||||
{
|
||||
PLAYER *pPlayer = &gPlayer[myconnectindex];
|
||||
VIEW* pView = &gPrevView[myconnectindex];
|
||||
PLAYER* pPlayer = &gPlayer[myconnectindex];
|
||||
VIEW* pView = &gPrevView[myconnectindex];
|
||||
|
||||
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->zView = pView->viewz = gView->zView = z;
|
||||
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->zView = pView->viewz = gView->zView = z;
|
||||
|
||||
if (ang != INT_MIN)
|
||||
{
|
||||
pPlayer->angle.oang = pPlayer->angle.ang = pView->angle = gView->angle.ang = buildang(ang);
|
||||
}
|
||||
if (ang != INT_MIN)
|
||||
{
|
||||
pPlayer->angle.oang = pPlayer->angle.ang = pView->angle = gView->angle.ang = buildang(ang);
|
||||
}
|
||||
|
||||
if (horz != INT_MIN)
|
||||
{
|
||||
pPlayer->horizon.ohoriz = pPlayer->horizon.horiz = pView->horiz = gView->horizon.horiz = buildhoriz(horz);
|
||||
}
|
||||
if (horz != INT_MIN)
|
||||
{
|
||||
pPlayer->horizon.ohoriz = pPlayer->horizon.horiz = pView->horiz = gView->horizon.horiz = buildhoriz(horz);
|
||||
}
|
||||
}
|
||||
|
||||
void GameInterface::ToggleThirdPerson()
|
||||
{
|
||||
if (gamestate != GS_LEVEL) return;
|
||||
if (gViewPos > VIEWPOS_0)
|
||||
gViewPos = VIEWPOS_0;
|
||||
else
|
||||
gViewPos = VIEWPOS_1;
|
||||
if (gamestate != GS_LEVEL) return;
|
||||
if (gViewPos > VIEWPOS_0)
|
||||
gViewPos = VIEWPOS_0;
|
||||
else
|
||||
gViewPos = VIEWPOS_1;
|
||||
}
|
||||
|
||||
void GameInterface::SwitchCoopView()
|
||||
{
|
||||
if (gamestate != GS_LEVEL) return;
|
||||
if (gGameOptions.nGameType == 1)
|
||||
{
|
||||
gViewIndex = connectpoint2[gViewIndex];
|
||||
if (gViewIndex == -1)
|
||||
gViewIndex = connecthead;
|
||||
gView = &gPlayer[gViewIndex];
|
||||
}
|
||||
else if (gGameOptions.nGameType == 3)
|
||||
{
|
||||
int oldViewIndex = gViewIndex;
|
||||
do
|
||||
{
|
||||
gViewIndex = connectpoint2[gViewIndex];
|
||||
if (gViewIndex == -1)
|
||||
gViewIndex = connecthead;
|
||||
if (oldViewIndex == gViewIndex || gMe->teamId == gPlayer[gViewIndex].teamId)
|
||||
break;
|
||||
} while (oldViewIndex != gViewIndex);
|
||||
gView = &gPlayer[gViewIndex];
|
||||
}
|
||||
if (gamestate != GS_LEVEL) return;
|
||||
if (gGameOptions.nGameType == 1)
|
||||
{
|
||||
gViewIndex = connectpoint2[gViewIndex];
|
||||
if (gViewIndex == -1)
|
||||
gViewIndex = connecthead;
|
||||
gView = &gPlayer[gViewIndex];
|
||||
}
|
||||
else if (gGameOptions.nGameType == 3)
|
||||
{
|
||||
int oldViewIndex = gViewIndex;
|
||||
do
|
||||
{
|
||||
gViewIndex = connectpoint2[gViewIndex];
|
||||
if (gViewIndex == -1)
|
||||
gViewIndex = connecthead;
|
||||
if (oldViewIndex == gViewIndex || gMe->teamId == gPlayer[gViewIndex].teamId)
|
||||
break;
|
||||
} while (oldViewIndex != gViewIndex);
|
||||
gView = &gPlayer[gViewIndex];
|
||||
}
|
||||
}
|
||||
|
||||
void GameInterface::ToggleShowWeapon()
|
||||
{
|
||||
if (gamestate != GS_LEVEL) return;
|
||||
cl_showweapon = (cl_showweapon + 1) & 3;
|
||||
if (gamestate != GS_LEVEL) return;
|
||||
cl_showweapon = (cl_showweapon + 1) & 3;
|
||||
}
|
||||
|
||||
END_BLD_NS
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -36,166 +36,166 @@ BEGIN_BLD_NS
|
|||
// life modes of the player
|
||||
enum
|
||||
{
|
||||
kModeHuman = 0,
|
||||
kModeBeast = 1,
|
||||
kModeHumanShrink = 2,
|
||||
kModeHumanGrown = 3,
|
||||
kModeMax = 4,
|
||||
kModeHuman = 0,
|
||||
kModeBeast = 1,
|
||||
kModeHumanShrink = 2,
|
||||
kModeHumanGrown = 3,
|
||||
kModeMax = 4,
|
||||
};
|
||||
|
||||
// postures
|
||||
enum
|
||||
{
|
||||
kPostureStand = 0,
|
||||
kPostureSwim = 1,
|
||||
kPostureCrouch = 2,
|
||||
kPostureMax = 3,
|
||||
kPostureStand = 0,
|
||||
kPostureSwim = 1,
|
||||
kPostureCrouch = 2,
|
||||
kPostureMax = 3,
|
||||
};
|
||||
|
||||
struct PACKINFO
|
||||
{
|
||||
bool isActive; // is active (0/1)
|
||||
int curAmount = 0; // remaining percent
|
||||
bool isActive; // is active (0/1)
|
||||
int curAmount = 0; // remaining percent
|
||||
};
|
||||
|
||||
struct POSTURE
|
||||
{
|
||||
int frontAccel;
|
||||
int sideAccel;
|
||||
int backAccel;
|
||||
int pace[2];
|
||||
int bobV;
|
||||
int bobH;
|
||||
int swayV;
|
||||
int swayH;
|
||||
int eyeAboveZ;
|
||||
int weaponAboveZ;
|
||||
int xOffset;
|
||||
int zOffset;
|
||||
int normalJumpZ;
|
||||
int pwupJumpZ;
|
||||
int frontAccel;
|
||||
int sideAccel;
|
||||
int backAccel;
|
||||
int pace[2];
|
||||
int bobV;
|
||||
int bobH;
|
||||
int swayV;
|
||||
int swayH;
|
||||
int eyeAboveZ;
|
||||
int weaponAboveZ;
|
||||
int xOffset;
|
||||
int zOffset;
|
||||
int normalJumpZ;
|
||||
int pwupJumpZ;
|
||||
};
|
||||
|
||||
extern POSTURE gPostureDefaults[kModeMax][kPostureMax];
|
||||
|
||||
struct PLAYER
|
||||
{
|
||||
DBloodActor* actor;
|
||||
DUDEINFO* pDudeInfo;
|
||||
InputPacket input;
|
||||
PlayerHorizon horizon;
|
||||
PlayerAngle angle;
|
||||
uint8_t newWeapon;
|
||||
int used1; // something related to game checksum
|
||||
int weaponQav;
|
||||
int qavCallback;
|
||||
bool isRunning;
|
||||
int posture; // stand, crouch, swim
|
||||
int sceneQav; // by NoOne: used to keep qav id
|
||||
int bobPhase;
|
||||
int bobAmp;
|
||||
int bobHeight;
|
||||
int bobWidth;
|
||||
int swayPhase;
|
||||
int swayAmp;
|
||||
int swayHeight;
|
||||
int swayWidth;
|
||||
int nPlayer; // Connect id
|
||||
int lifeMode;
|
||||
int bloodlust; // ---> useless
|
||||
int zView;
|
||||
int zViewVel;
|
||||
int zWeapon;
|
||||
int zWeaponVel;
|
||||
int slope;
|
||||
bool isUnderwater;
|
||||
bool hasKey[8];
|
||||
int8_t hasFlag;
|
||||
TObjPtr<DBloodActor*> ctfFlagState[2];
|
||||
int damageControl[7];
|
||||
int8_t curWeapon;
|
||||
int8_t nextWeapon;
|
||||
int weaponTimer;
|
||||
int weaponState;
|
||||
int weaponAmmo; //rename
|
||||
bool hasWeapon[14];
|
||||
int weaponMode[14];
|
||||
int weaponOrder[2][14];
|
||||
//int at149[14];
|
||||
int ammoCount[12];
|
||||
bool qavLoop;
|
||||
int qavLastTick;
|
||||
int qavTimer;
|
||||
int fuseTime;
|
||||
int throwTime;
|
||||
int throwPower;
|
||||
Aim aim; // world
|
||||
//int at1c6;
|
||||
Aim relAim; // relative
|
||||
//int relAim;
|
||||
//int at1ce;
|
||||
//int at1d2;
|
||||
TObjPtr<DBloodActor*> aimTarget; // aim target sprite
|
||||
int aimTargetsCount;
|
||||
TObjPtr<DBloodActor*> aimTargets[16];
|
||||
int deathTime;
|
||||
int pwUpTime[kMaxPowerUps];
|
||||
int fragCount;
|
||||
int fragInfo[8];
|
||||
int teamId;
|
||||
TObjPtr<DBloodActor*> fragger;
|
||||
int underwaterTime;
|
||||
int bubbleTime;
|
||||
int restTime;
|
||||
int kickPower;
|
||||
int laughCount;
|
||||
bool godMode;
|
||||
bool fallScream;
|
||||
bool cantJump;
|
||||
int packItemTime; // pack timer
|
||||
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
|
||||
int armor[3]; // armor
|
||||
//int at342;
|
||||
//int at346;
|
||||
TObjPtr<DBloodActor*> voodooTarget;
|
||||
int voodooTargets; // --> useless
|
||||
int voodooVar1; // --> useless
|
||||
int vodooVar2; // --> useless
|
||||
int flickerEffect;
|
||||
int tiltEffect;
|
||||
int visibility;
|
||||
int painEffect;
|
||||
int blindEffect;
|
||||
int chokeEffect;
|
||||
int handTime;
|
||||
bool hand; // if true, there is hand start choking the player
|
||||
int pickupEffect;
|
||||
bool flashEffect; // if true, reduce pPlayer->visibility counter
|
||||
int quakeEffect;
|
||||
int player_par;
|
||||
int nWaterPal;
|
||||
POSTURE pPosture[kModeMax][kPostureMax];
|
||||
DBloodActor* actor;
|
||||
DUDEINFO* pDudeInfo;
|
||||
InputPacket input;
|
||||
PlayerHorizon horizon;
|
||||
PlayerAngle angle;
|
||||
uint8_t newWeapon;
|
||||
int used1; // something related to game checksum
|
||||
int weaponQav;
|
||||
int qavCallback;
|
||||
bool isRunning;
|
||||
int posture; // stand, crouch, swim
|
||||
int sceneQav; // by NoOne: used to keep qav id
|
||||
int bobPhase;
|
||||
int bobAmp;
|
||||
int bobHeight;
|
||||
int bobWidth;
|
||||
int swayPhase;
|
||||
int swayAmp;
|
||||
int swayHeight;
|
||||
int swayWidth;
|
||||
int nPlayer; // Connect id
|
||||
int lifeMode;
|
||||
int bloodlust; // ---> useless
|
||||
int zView;
|
||||
int zViewVel;
|
||||
int zWeapon;
|
||||
int zWeaponVel;
|
||||
int slope;
|
||||
bool isUnderwater;
|
||||
bool hasKey[8];
|
||||
int8_t hasFlag;
|
||||
TObjPtr<DBloodActor*> ctfFlagState[2];
|
||||
int damageControl[7];
|
||||
int8_t curWeapon;
|
||||
int8_t nextWeapon;
|
||||
int weaponTimer;
|
||||
int weaponState;
|
||||
int weaponAmmo; //rename
|
||||
bool hasWeapon[14];
|
||||
int weaponMode[14];
|
||||
int weaponOrder[2][14];
|
||||
//int at149[14];
|
||||
int ammoCount[12];
|
||||
bool qavLoop;
|
||||
int qavLastTick;
|
||||
int qavTimer;
|
||||
int fuseTime;
|
||||
int throwTime;
|
||||
int throwPower;
|
||||
Aim aim; // world
|
||||
//int at1c6;
|
||||
Aim relAim; // relative
|
||||
//int relAim;
|
||||
//int at1ce;
|
||||
//int at1d2;
|
||||
TObjPtr<DBloodActor*> aimTarget; // aim target sprite
|
||||
int aimTargetsCount;
|
||||
TObjPtr<DBloodActor*> aimTargets[16];
|
||||
int deathTime;
|
||||
int pwUpTime[kMaxPowerUps];
|
||||
int fragCount;
|
||||
int fragInfo[8];
|
||||
int teamId;
|
||||
TObjPtr<DBloodActor*> fragger;
|
||||
int underwaterTime;
|
||||
int bubbleTime;
|
||||
int restTime;
|
||||
int kickPower;
|
||||
int laughCount;
|
||||
bool godMode;
|
||||
bool fallScream;
|
||||
bool cantJump;
|
||||
int packItemTime; // pack timer
|
||||
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
|
||||
int armor[3]; // armor
|
||||
//int at342;
|
||||
//int at346;
|
||||
TObjPtr<DBloodActor*> voodooTarget;
|
||||
int voodooTargets; // --> useless
|
||||
int voodooVar1; // --> useless
|
||||
int vodooVar2; // --> useless
|
||||
int flickerEffect;
|
||||
int tiltEffect;
|
||||
int visibility;
|
||||
int painEffect;
|
||||
int blindEffect;
|
||||
int chokeEffect;
|
||||
int handTime;
|
||||
bool hand; // if true, there is hand start choking the player
|
||||
int pickupEffect;
|
||||
bool flashEffect; // if true, reduce pPlayer->visibility counter
|
||||
int quakeEffect;
|
||||
int player_par;
|
||||
int nWaterPal;
|
||||
POSTURE pPosture[kModeMax][kPostureMax];
|
||||
};
|
||||
|
||||
struct AMMOINFO
|
||||
{
|
||||
int max;
|
||||
int8_t vectorType;
|
||||
int max;
|
||||
int8_t vectorType;
|
||||
};
|
||||
|
||||
struct POWERUPINFO
|
||||
{
|
||||
int16_t picnum;
|
||||
bool pickupOnce;
|
||||
int bonusTime;
|
||||
int maxTime;
|
||||
int16_t picnum;
|
||||
bool pickupOnce;
|
||||
int bonusTime;
|
||||
int maxTime;
|
||||
};
|
||||
|
||||
void playerResetPosture(PLAYER* pPlayer);
|
||||
|
||||
extern PLAYER gPlayer[kMaxPlayers];
|
||||
extern PLAYER *gMe, *gView;
|
||||
extern PLAYER* gMe, * gView;
|
||||
|
||||
extern bool gBlueFlagDropped;
|
||||
extern bool gRedFlagDropped;
|
||||
|
@ -206,39 +206,39 @@ extern AMMOINFO gAmmoInfo[];
|
|||
extern POWERUPINFO gPowerUpInfo[kMaxPowerUps];
|
||||
|
||||
bool IsTargetTeammate(PLAYER* pSourcePlayer, DBloodActor* target);
|
||||
int powerupCheck(PLAYER *pPlayer, int nPowerUp);
|
||||
bool powerupActivate(PLAYER *pPlayer, int nPowerUp);
|
||||
void powerupDeactivate(PLAYER *pPlayer, int nPowerUp);
|
||||
void powerupSetState(PLAYER *pPlayer, int nPowerUp, bool bState);
|
||||
void powerupProcess(PLAYER *pPlayer);
|
||||
void powerupClear(PLAYER *pPlayer);
|
||||
int powerupCheck(PLAYER* pPlayer, int nPowerUp);
|
||||
bool powerupActivate(PLAYER* pPlayer, int nPowerUp);
|
||||
void powerupDeactivate(PLAYER* pPlayer, int nPowerUp);
|
||||
void powerupSetState(PLAYER* pPlayer, int nPowerUp, bool bState);
|
||||
void powerupProcess(PLAYER* pPlayer);
|
||||
void powerupClear(PLAYER* pPlayer);
|
||||
int packItemToPowerup(int nPack);
|
||||
int powerupToPackItem(int nPowerUp);
|
||||
bool packAddItem(PLAYER *pPlayer, unsigned int nPack);
|
||||
int packCheckItem(PLAYER *pPlayer, int nPack);
|
||||
bool packItemActive(PLAYER *pPlayer, int nPack);
|
||||
void packUseItem(PLAYER *pPlayer, int nPack);
|
||||
void packPrevItem(PLAYER *pPlayer);
|
||||
void packNextItem(PLAYER *pPlayer);
|
||||
bool playerSeqPlaying(PLAYER *pPlayer, int nSeq);
|
||||
void playerSetRace(PLAYER *pPlayer, int nLifeMode);
|
||||
void playerSetGodMode(PLAYER *pPlayer, bool bGodMode);
|
||||
void playerResetInertia(PLAYER *pPlayer);
|
||||
void playerCorrectInertia(PLAYER *pPlayer, vec3_t const *oldpos);
|
||||
bool packAddItem(PLAYER* pPlayer, unsigned int nPack);
|
||||
int packCheckItem(PLAYER* pPlayer, int nPack);
|
||||
bool packItemActive(PLAYER* pPlayer, int nPack);
|
||||
void packUseItem(PLAYER* pPlayer, int nPack);
|
||||
void packPrevItem(PLAYER* pPlayer);
|
||||
void packNextItem(PLAYER* pPlayer);
|
||||
bool playerSeqPlaying(PLAYER* pPlayer, int nSeq);
|
||||
void playerSetRace(PLAYER* pPlayer, int nLifeMode);
|
||||
void playerSetGodMode(PLAYER* pPlayer, bool bGodMode);
|
||||
void playerResetInertia(PLAYER* pPlayer);
|
||||
void playerCorrectInertia(PLAYER* pPlayer, vec3_t const* oldpos);
|
||||
void playerStart(int nPlayer, int bNewLevel = 0);
|
||||
void playerReset(PLAYER *pPlayer);
|
||||
void playerReset(PLAYER* pPlayer);
|
||||
void playerInit(int nPlayer, unsigned int a2);
|
||||
void CheckPickUp(PLAYER *pPlayer);
|
||||
void ProcessInput(PLAYER *pPlayer);
|
||||
void playerProcess(PLAYER *pPlayer);
|
||||
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);
|
||||
void playerFrag(PLAYER *pKiller, PLAYER *pVictim);
|
||||
int playerDamageArmor(PLAYER *pPlayer, DAMAGE_TYPE nType, int nDamage);
|
||||
int playerDamageSprite(DBloodActor* nSource, PLAYER *pPlayer, DAMAGE_TYPE nDamageType, int nDamage);
|
||||
int UseAmmo(PLAYER *pPlayer, int nAmmoType, int nDec);
|
||||
void voodooTarget(PLAYER *pPlayer);
|
||||
void playerLandingSound(PLAYER *pPlayer);
|
||||
void CheckPickUp(PLAYER* pPlayer);
|
||||
void ProcessInput(PLAYER* pPlayer);
|
||||
void playerProcess(PLAYER* pPlayer);
|
||||
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);
|
||||
void playerFrag(PLAYER* pKiller, PLAYER* pVictim);
|
||||
int playerDamageArmor(PLAYER* pPlayer, DAMAGE_TYPE nType, int nDamage);
|
||||
int playerDamageSprite(DBloodActor* nSource, PLAYER* pPlayer, DAMAGE_TYPE nDamageType, int nDamage);
|
||||
int UseAmmo(PLAYER* pPlayer, int nAmmoType, int nDec);
|
||||
void voodooTarget(PLAYER* pPlayer);
|
||||
void playerLandingSound(PLAYER* pPlayer);
|
||||
void PlayerSurvive(int, DBloodActor*);
|
||||
|
||||
END_BLD_NS
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -36,281 +36,309 @@ void fxPrecache();
|
|||
void gibPrecache();
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void tilePrecacheTile(int nTile, int nType, int palette)
|
||||
{
|
||||
int n = 1;
|
||||
switch (picanm[nTile].extra & 7)
|
||||
{
|
||||
case 0:
|
||||
n = 1;
|
||||
break;
|
||||
case 1:
|
||||
n = 5;
|
||||
break;
|
||||
case 2:
|
||||
n = 8;
|
||||
break;
|
||||
case 3:
|
||||
n = 2;
|
||||
break;
|
||||
}
|
||||
while (n--)
|
||||
{
|
||||
if (picanm[nTile].sf & PICANM_ANIMTYPE_MASK)
|
||||
{
|
||||
for (int frame = picanm[nTile].num; frame >= 0; frame--)
|
||||
{
|
||||
int tile;
|
||||
if ((picanm[nTile].sf & PICANM_ANIMTYPE_MASK) == PICANM_ANIMTYPE_BACK)
|
||||
tile = nTile - frame;
|
||||
else
|
||||
tile = nTile + frame;
|
||||
int n = 1;
|
||||
switch (picanm[nTile].extra & 7)
|
||||
{
|
||||
case 0:
|
||||
n = 1;
|
||||
break;
|
||||
case 1:
|
||||
n = 5;
|
||||
break;
|
||||
case 2:
|
||||
n = 8;
|
||||
break;
|
||||
case 3:
|
||||
n = 2;
|
||||
break;
|
||||
}
|
||||
while (n--)
|
||||
{
|
||||
if (picanm[nTile].sf & PICANM_ANIMTYPE_MASK)
|
||||
{
|
||||
for (int frame = picanm[nTile].num; frame >= 0; frame--)
|
||||
{
|
||||
int tile;
|
||||
if ((picanm[nTile].sf & PICANM_ANIMTYPE_MASK) == PICANM_ANIMTYPE_BACK)
|
||||
tile = nTile - frame;
|
||||
else
|
||||
tile = nTile + frame;
|
||||
|
||||
markTileForPrecache(tile, palette);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
markTileForPrecache(nTile, palette);
|
||||
}
|
||||
nTile += 1 + picanm[nTile].num;
|
||||
}
|
||||
markTileForPrecache(tile, palette);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
markTileForPrecache(nTile, palette);
|
||||
}
|
||||
nTile += 1 + picanm[nTile].num;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// To do: This needs to handle the sprite palettes as well to properly precache the needed content.
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void viewPrecacheTiles()
|
||||
{
|
||||
tilePrecacheTile(2173, 0, 0);
|
||||
tilePrecacheTile(2200, 0, 0);
|
||||
tilePrecacheTile(2201, 0, 0);
|
||||
tilePrecacheTile(2202, 0, 0);
|
||||
tilePrecacheTile(2207, 0, 0);
|
||||
tilePrecacheTile(2208, 0, 0);
|
||||
tilePrecacheTile(2209, 0, 0);
|
||||
tilePrecacheTile(2229, 0, 0);
|
||||
tilePrecacheTile(2260, 0, 0);
|
||||
tilePrecacheTile(2559, 0, 0);
|
||||
tilePrecacheTile(2169, 0, 0);
|
||||
tilePrecacheTile(2578, 0, 0);
|
||||
tilePrecacheTile(2586, 0, 0);
|
||||
tilePrecacheTile(2602, 0, 0);
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
tilePrecacheTile(2190 + i, 0, 0);
|
||||
tilePrecacheTile(2230 + i, 0, 0);
|
||||
tilePrecacheTile(2240 + i, 0, 0);
|
||||
tilePrecacheTile(2250 + i, 0, 0);
|
||||
tilePrecacheTile(kSBarNumberHealth + i, 0, 0);
|
||||
tilePrecacheTile(kSBarNumberAmmo + i, 0, 0);
|
||||
tilePrecacheTile(kSBarNumberInv + i, 0, 0);
|
||||
tilePrecacheTile(kSBarNumberArmor1 + i, 0, 0);
|
||||
tilePrecacheTile(kSBarNumberArmor2 + i, 0, 0);
|
||||
tilePrecacheTile(kSBarNumberArmor3 + i, 0, 0);
|
||||
}
|
||||
/*
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
tilePrecacheTile(gPackIcons[i], 0);
|
||||
tilePrecacheTile(gPackIcons2[i].nTile, 0);
|
||||
}
|
||||
*/
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
tilePrecacheTile(2220 + i, 0, 0);
|
||||
tilePrecacheTile(2552 + i, 0, 0);
|
||||
}
|
||||
tilePrecacheTile(2173, 0, 0);
|
||||
tilePrecacheTile(2200, 0, 0);
|
||||
tilePrecacheTile(2201, 0, 0);
|
||||
tilePrecacheTile(2202, 0, 0);
|
||||
tilePrecacheTile(2207, 0, 0);
|
||||
tilePrecacheTile(2208, 0, 0);
|
||||
tilePrecacheTile(2209, 0, 0);
|
||||
tilePrecacheTile(2229, 0, 0);
|
||||
tilePrecacheTile(2260, 0, 0);
|
||||
tilePrecacheTile(2559, 0, 0);
|
||||
tilePrecacheTile(2169, 0, 0);
|
||||
tilePrecacheTile(2578, 0, 0);
|
||||
tilePrecacheTile(2586, 0, 0);
|
||||
tilePrecacheTile(2602, 0, 0);
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
tilePrecacheTile(2190 + i, 0, 0);
|
||||
tilePrecacheTile(2230 + i, 0, 0);
|
||||
tilePrecacheTile(2240 + i, 0, 0);
|
||||
tilePrecacheTile(2250 + i, 0, 0);
|
||||
tilePrecacheTile(kSBarNumberHealth + i, 0, 0);
|
||||
tilePrecacheTile(kSBarNumberAmmo + i, 0, 0);
|
||||
tilePrecacheTile(kSBarNumberInv + i, 0, 0);
|
||||
tilePrecacheTile(kSBarNumberArmor1 + i, 0, 0);
|
||||
tilePrecacheTile(kSBarNumberArmor2 + i, 0, 0);
|
||||
tilePrecacheTile(kSBarNumberArmor3 + i, 0, 0);
|
||||
}
|
||||
/*
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
tilePrecacheTile(gPackIcons[i], 0);
|
||||
tilePrecacheTile(gPackIcons2[i].nTile, 0);
|
||||
}
|
||||
*/
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
tilePrecacheTile(2220 + i, 0, 0);
|
||||
tilePrecacheTile(2552 + i, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
void PrecacheDude(DBloodActor *actor)
|
||||
void PrecacheDude(DBloodActor* actor)
|
||||
{
|
||||
int palette = actor->spr.pal;
|
||||
DUDEINFO *pDudeInfo = getDudeInfo(actor->spr.type);
|
||||
seqPrecacheId(pDudeInfo->seqStartID , palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+5, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+1, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+2, palette);
|
||||
switch (actor->spr.type)
|
||||
{
|
||||
case kDudeCultistTommy:
|
||||
case kDudeCultistShotgun:
|
||||
case kDudeCultistTesla:
|
||||
case kDudeCultistTNT:
|
||||
seqPrecacheId(pDudeInfo->seqStartID+6 , palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+7 , palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+8 , palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+9 , palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+13, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+14, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+15, palette);
|
||||
break;
|
||||
case kDudeZombieButcher:
|
||||
case kDudeGillBeast:
|
||||
seqPrecacheId(pDudeInfo->seqStartID+6, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+7, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+8, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+9, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+10, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+11, palette);
|
||||
break;
|
||||
case kDudeGargoyleStatueFlesh:
|
||||
case kDudeGargoyleStatueStone:
|
||||
seqPrecacheId(pDudeInfo->seqStartID+6, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+6, palette); //???
|
||||
[[fallthrough]];
|
||||
case kDudeGargoyleFlesh:
|
||||
case kDudeGargoyleStone:
|
||||
seqPrecacheId(pDudeInfo->seqStartID+6, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+7, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+8, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+9, palette);
|
||||
break;
|
||||
case kDudePhantasm:
|
||||
case kDudeHellHound:
|
||||
case kDudeSpiderBrown:
|
||||
case kDudeSpiderRed:
|
||||
case kDudeSpiderBlack:
|
||||
case kDudeSpiderMother:
|
||||
case kDudeTchernobog:
|
||||
seqPrecacheId(pDudeInfo->seqStartID+6, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+7, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+8, palette);
|
||||
break;
|
||||
case kDudeCerberusTwoHead:
|
||||
seqPrecacheId(pDudeInfo->seqStartID+6, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+7, palette);
|
||||
[[fallthrough]];
|
||||
case kDudeHand:
|
||||
case kDudeBoneEel:
|
||||
case kDudeBat:
|
||||
case kDudeRat:
|
||||
seqPrecacheId(pDudeInfo->seqStartID+6, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+7, palette);
|
||||
break;
|
||||
case kDudeCultistBeast:
|
||||
seqPrecacheId(pDudeInfo->seqStartID+6, palette);
|
||||
break;
|
||||
case kDudeZombieAxeBuried:
|
||||
seqPrecacheId(pDudeInfo->seqStartID+12, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+9, palette);
|
||||
[[fallthrough]];
|
||||
case kDudeZombieAxeLaying:
|
||||
seqPrecacheId(pDudeInfo->seqStartID+10, palette);
|
||||
[[fallthrough]];
|
||||
case kDudeZombieAxeNormal:
|
||||
seqPrecacheId(pDudeInfo->seqStartID+6, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+7, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+8, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+11, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+13, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID+14, palette);
|
||||
break;
|
||||
}
|
||||
int palette = actor->spr.pal;
|
||||
DUDEINFO* pDudeInfo = getDudeInfo(actor->spr.type);
|
||||
seqPrecacheId(pDudeInfo->seqStartID, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 5, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 1, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 2, palette);
|
||||
switch (actor->spr.type)
|
||||
{
|
||||
case kDudeCultistTommy:
|
||||
case kDudeCultistShotgun:
|
||||
case kDudeCultistTesla:
|
||||
case kDudeCultistTNT:
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 6, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 7, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 8, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 9, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 13, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 14, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 15, palette);
|
||||
break;
|
||||
case kDudeZombieButcher:
|
||||
case kDudeGillBeast:
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 6, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 7, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 8, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 9, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 10, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 11, palette);
|
||||
break;
|
||||
case kDudeGargoyleStatueFlesh:
|
||||
case kDudeGargoyleStatueStone:
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 6, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 6, palette); //???
|
||||
[[fallthrough]];
|
||||
case kDudeGargoyleFlesh:
|
||||
case kDudeGargoyleStone:
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 6, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 7, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 8, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 9, palette);
|
||||
break;
|
||||
case kDudePhantasm:
|
||||
case kDudeHellHound:
|
||||
case kDudeSpiderBrown:
|
||||
case kDudeSpiderRed:
|
||||
case kDudeSpiderBlack:
|
||||
case kDudeSpiderMother:
|
||||
case kDudeTchernobog:
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 6, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 7, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 8, palette);
|
||||
break;
|
||||
case kDudeCerberusTwoHead:
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 6, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 7, palette);
|
||||
[[fallthrough]];
|
||||
case kDudeHand:
|
||||
case kDudeBoneEel:
|
||||
case kDudeBat:
|
||||
case kDudeRat:
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 6, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 7, palette);
|
||||
break;
|
||||
case kDudeCultistBeast:
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 6, palette);
|
||||
break;
|
||||
case kDudeZombieAxeBuried:
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 12, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 9, palette);
|
||||
[[fallthrough]];
|
||||
case kDudeZombieAxeLaying:
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 10, palette);
|
||||
[[fallthrough]];
|
||||
case kDudeZombieAxeNormal:
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 6, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 7, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 8, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 11, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 13, palette);
|
||||
seqPrecacheId(pDudeInfo->seqStartID + 14, palette);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void PrecacheThing(DBloodActor* actor)
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void PrecacheThing(DBloodActor* actor)
|
||||
{
|
||||
int palette = actor->spr.pal;
|
||||
switch (actor->spr.type) {
|
||||
case kThingGlassWindow: // worthless...
|
||||
case kThingFluorescent:
|
||||
seqPrecacheId(12, palette);
|
||||
break;
|
||||
case kThingSpiderWeb:
|
||||
seqPrecacheId(15, palette);
|
||||
break;
|
||||
case kThingMetalGrate:
|
||||
seqPrecacheId(21, palette);
|
||||
break;
|
||||
case kThingFlammableTree:
|
||||
seqPrecacheId(25, palette);
|
||||
seqPrecacheId(26, palette);
|
||||
break;
|
||||
case kTrapMachinegun:
|
||||
seqPrecacheId(38, palette);
|
||||
seqPrecacheId(40, palette);
|
||||
seqPrecacheId(28, palette);
|
||||
break;
|
||||
case kThingObjectGib:
|
||||
//case kThingObjectExplode: weird that only gib object is precached and this one is not
|
||||
break;
|
||||
}
|
||||
tilePrecacheTile(actor->spr.picnum, -1, palette);
|
||||
int palette = actor->spr.pal;
|
||||
switch (actor->spr.type) {
|
||||
case kThingGlassWindow: // worthless...
|
||||
case kThingFluorescent:
|
||||
seqPrecacheId(12, palette);
|
||||
break;
|
||||
case kThingSpiderWeb:
|
||||
seqPrecacheId(15, palette);
|
||||
break;
|
||||
case kThingMetalGrate:
|
||||
seqPrecacheId(21, palette);
|
||||
break;
|
||||
case kThingFlammableTree:
|
||||
seqPrecacheId(25, palette);
|
||||
seqPrecacheId(26, palette);
|
||||
break;
|
||||
case kTrapMachinegun:
|
||||
seqPrecacheId(38, palette);
|
||||
seqPrecacheId(40, palette);
|
||||
seqPrecacheId(28, palette);
|
||||
break;
|
||||
case kThingObjectGib:
|
||||
//case kThingObjectExplode: weird that only gib object is precached and this one is not
|
||||
break;
|
||||
}
|
||||
tilePrecacheTile(actor->spr.picnum, -1, palette);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void PreloadCache()
|
||||
{
|
||||
if (!r_precache) return;
|
||||
int skyTile = -1;
|
||||
// Fonts
|
||||
for(auto& sect: sector)
|
||||
{
|
||||
tilePrecacheTile(sect.floorpicnum, 0, sect.floorpal);
|
||||
tilePrecacheTile(sect.ceilingpicnum, 0, sect.ceilingpal);
|
||||
if ((sect.ceilingstat & CSTAT_SECTOR_SKY) != 0 && skyTile == -1)
|
||||
skyTile = sect.ceilingpicnum;
|
||||
}
|
||||
for(auto& wal : wall)
|
||||
{
|
||||
tilePrecacheTile(wal.picnum, 0, wal.pal);
|
||||
if (wal.overpicnum >= 0)
|
||||
tilePrecacheTile(wal.overpicnum, 0, wal.pal);
|
||||
}
|
||||
BloodSpriteIterator it;
|
||||
while (auto actor = it.Next())
|
||||
{
|
||||
switch (actor->spr.statnum)
|
||||
{
|
||||
case kStatDude:
|
||||
PrecacheDude(actor);
|
||||
break;
|
||||
case kStatThing:
|
||||
PrecacheThing(actor);
|
||||
break;
|
||||
default:
|
||||
tilePrecacheTile(actor->spr.picnum, -1, actor->spr.pal);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!r_precache) return;
|
||||
int skyTile = -1;
|
||||
// Fonts
|
||||
for (auto& sect : sector)
|
||||
{
|
||||
tilePrecacheTile(sect.floorpicnum, 0, sect.floorpal);
|
||||
tilePrecacheTile(sect.ceilingpicnum, 0, sect.ceilingpal);
|
||||
if ((sect.ceilingstat & CSTAT_SECTOR_SKY) != 0 && skyTile == -1)
|
||||
skyTile = sect.ceilingpicnum;
|
||||
}
|
||||
for (auto& wal : wall)
|
||||
{
|
||||
tilePrecacheTile(wal.picnum, 0, wal.pal);
|
||||
if (wal.overpicnum >= 0)
|
||||
tilePrecacheTile(wal.overpicnum, 0, wal.pal);
|
||||
}
|
||||
BloodSpriteIterator it;
|
||||
while (auto actor = it.Next())
|
||||
{
|
||||
switch (actor->spr.statnum)
|
||||
{
|
||||
case kStatDude:
|
||||
PrecacheDude(actor);
|
||||
break;
|
||||
case kStatThing:
|
||||
PrecacheThing(actor);
|
||||
break;
|
||||
default:
|
||||
tilePrecacheTile(actor->spr.picnum, -1, actor->spr.pal);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Precache common SEQs
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
seqPrecacheId(i, 0);
|
||||
}
|
||||
// Precache common SEQs
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
seqPrecacheId(i, 0);
|
||||
}
|
||||
|
||||
tilePrecacheTile(1147, -1, 0); // water drip
|
||||
tilePrecacheTile(1160, -1, 0); // blood drip
|
||||
tilePrecacheTile(1147, -1, 0); // water drip
|
||||
tilePrecacheTile(1160, -1, 0); // blood drip
|
||||
|
||||
// Player SEQs
|
||||
seqPrecacheId(dudeInfo[31].seqStartID+6, 0);
|
||||
seqPrecacheId(dudeInfo[31].seqStartID+7, 0);
|
||||
seqPrecacheId(dudeInfo[31].seqStartID+8, 0);
|
||||
seqPrecacheId(dudeInfo[31].seqStartID+9, 0);
|
||||
seqPrecacheId(dudeInfo[31].seqStartID+10, 0);
|
||||
seqPrecacheId(dudeInfo[31].seqStartID+14, 0);
|
||||
seqPrecacheId(dudeInfo[31].seqStartID+15, 0);
|
||||
seqPrecacheId(dudeInfo[31].seqStartID+12, 0);
|
||||
seqPrecacheId(dudeInfo[31].seqStartID+16, 0);
|
||||
seqPrecacheId(dudeInfo[31].seqStartID+17, 0);
|
||||
seqPrecacheId(dudeInfo[31].seqStartID+18, 0);
|
||||
// Player SEQs
|
||||
seqPrecacheId(dudeInfo[31].seqStartID + 6, 0);
|
||||
seqPrecacheId(dudeInfo[31].seqStartID + 7, 0);
|
||||
seqPrecacheId(dudeInfo[31].seqStartID + 8, 0);
|
||||
seqPrecacheId(dudeInfo[31].seqStartID + 9, 0);
|
||||
seqPrecacheId(dudeInfo[31].seqStartID + 10, 0);
|
||||
seqPrecacheId(dudeInfo[31].seqStartID + 14, 0);
|
||||
seqPrecacheId(dudeInfo[31].seqStartID + 15, 0);
|
||||
seqPrecacheId(dudeInfo[31].seqStartID + 12, 0);
|
||||
seqPrecacheId(dudeInfo[31].seqStartID + 16, 0);
|
||||
seqPrecacheId(dudeInfo[31].seqStartID + 17, 0);
|
||||
seqPrecacheId(dudeInfo[31].seqStartID + 18, 0);
|
||||
|
||||
if (skyTile > -1 && skyTile < kMaxTiles)
|
||||
{
|
||||
for (int i = 1; i < gSkyCount; i++)
|
||||
tilePrecacheTile(skyTile+i, 0, 0);
|
||||
}
|
||||
if (skyTile > -1 && skyTile < kMaxTiles)
|
||||
{
|
||||
for (int i = 1; i < gSkyCount; i++)
|
||||
tilePrecacheTile(skyTile + i, 0, 0);
|
||||
}
|
||||
|
||||
WeaponPrecache();
|
||||
viewPrecacheTiles();
|
||||
fxPrecache();
|
||||
gibPrecache();
|
||||
WeaponPrecache();
|
||||
viewPrecacheTiles();
|
||||
fxPrecache();
|
||||
gibPrecache();
|
||||
|
||||
I_GetEvent();
|
||||
precacheMarkedTiles();
|
||||
I_GetEvent();
|
||||
precacheMarkedTiles();
|
||||
}
|
||||
|
||||
END_BLD_NS
|
||||
|
|
|
@ -30,7 +30,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
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
|
||||
{
|
||||
QAVPrevTileFinder PrevTileFinder;
|
||||
bool loopable;
|
||||
TMap<int, TArray<int>> IgnoreData;
|
||||
QAVPrevTileFinder PrevTileFinder;
|
||||
bool loopable;
|
||||
TMap<int, TArray<int>> IgnoreData;
|
||||
|
||||
bool CanInterpFrameTile(const int nFrame, const int i)
|
||||
{
|
||||
// Check whether the current frame's tile is skippable.
|
||||
auto thisFrame = IgnoreData.CheckKey(nFrame);
|
||||
return thisFrame ? !thisFrame->Contains(i) : true;
|
||||
}
|
||||
bool CanInterpFrameTile(const int nFrame, const int i)
|
||||
{
|
||||
// Check whether the current frame's tile is skippable.
|
||||
auto thisFrame = IgnoreData.CheckKey(nFrame);
|
||||
return thisFrame ? !thisFrame->Contains(i) : true;
|
||||
}
|
||||
};
|
||||
|
||||
static TMap<FString, QAVPrevTileFinder> qavPrevTileFinders;
|
||||
|
@ -60,66 +60,78 @@ static TMap<int, QAVInterpProps> qavInterpProps;
|
|||
|
||||
static void qavInitTileFinderMap()
|
||||
{
|
||||
// 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* {
|
||||
return prevFrame->tiles[i].picnum == thisFrame->tiles[i].picnum ? &prevFrame->tiles[i] : nullptr;
|
||||
});
|
||||
// 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* {
|
||||
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.
|
||||
qavPrevTileFinders.Insert("index", [](FRAMEINFO* const thisFrame, FRAMEINFO* const prevFrame, const int i) -> TILE_FRAME* {
|
||||
return prevFrame->tiles[i].picnum > 0 ? &prevFrame->tiles[i] : nullptr;
|
||||
});
|
||||
// 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* {
|
||||
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.
|
||||
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)
|
||||
{
|
||||
return &prevFrame->tiles[j];
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
// 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* {
|
||||
for (int j = 0; j < 8; j++) if (thisFrame->tiles[i].x == prevFrame->tiles[j].x)
|
||||
{
|
||||
return &prevFrame->tiles[j];
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
|
||||
// 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* {
|
||||
for (int j = 0; j < 8; j++) if (thisFrame->tiles[i].y == prevFrame->tiles[j].y)
|
||||
{
|
||||
return &prevFrame->tiles[j];
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
// 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* {
|
||||
for (int j = 0; j < 8; j++) if (thisFrame->tiles[i].y == prevFrame->tiles[j].y)
|
||||
{
|
||||
return &prevFrame->tiles[j];
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static QAVPrevTileFinder qavGetInterpType(const FString& type)
|
||||
{
|
||||
if (!qavPrevTileFinders.CountUsed()) qavInitTileFinderMap();
|
||||
return *qavPrevTileFinders.CheckKey(type);
|
||||
if (!qavPrevTileFinders.CountUsed()) qavInitTileFinderMap();
|
||||
return *qavPrevTileFinders.CheckKey(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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (!to3dview)
|
||||
{
|
||||
if (!to3dview)
|
||||
{
|
||||
auto tex = tileGetTexture(picnum);
|
||||
double scale = z * (1. / 65536.);
|
||||
double angle = a * BAngToDegree;
|
||||
int renderstyle = (stat & RS_NOMASK)? STYLE_Normal : STYLE_Translucent;
|
||||
int pin = (stat & kQavOrientationLeft)? -1 : (stat & RS_ALIGN_R)? 1:0;
|
||||
int renderstyle = (stat & RS_NOMASK) ? STYLE_Normal : STYLE_Translucent;
|
||||
int pin = (stat & kQavOrientationLeft) ? -1 : (stat & RS_ALIGN_R) ? 1 : 0;
|
||||
auto translation = TRANSLATION(Translation_Remap, palnum);
|
||||
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);
|
||||
|
||||
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_FlipX, xflip, DTA_FlipY, yflip, TAG_DONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// there's some disagreements about flag values between QAV and the drawer. Shuffle these around.
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
// there's some disagreements about flag values between QAV and the drawer. Shuffle these around.
|
||||
if (stat & RS_YFLIP) stat |= RS_YFLIPHUD;
|
||||
stat &= ~RS_YFLIP;
|
||||
if (stat & 0x100) stat |= RS_XFLIPHUD;
|
||||
stat &= ~0x100;
|
||||
stat &= ~0x100;
|
||||
if ((stat & kQavOrientationLeft)) stat |= RS_ALIGN_L;
|
||||
stat &= ~kQavOrientationLeft;
|
||||
stat &= ~kQavOrientationLeft;
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
FRAMEINFO* const thisFrame = &frames[nFrame];
|
||||
auto const nFrame = clamp(ticks / ticksPerFrame, 0, nFrames - 1);
|
||||
FRAMEINFO* const thisFrame = &frames[nFrame];
|
||||
|
||||
auto const oFrame = clamp((nFrame == 0 && interpdata && interpdata->loopable ? nFrames : nFrame) - 1, 0, nFrames - 1);
|
||||
FRAMEINFO* const prevFrame = &frames[oFrame];
|
||||
auto const oFrame = clamp((nFrame == 0 && interpdata && interpdata->loopable ? nFrames : nFrame) - 1, 0, nFrames - 1);
|
||||
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++)
|
||||
{
|
||||
if (thisFrame->tiles[i].picnum > 0)
|
||||
{
|
||||
TILE_FRAME* const thisTile = &thisFrame->tiles[i];
|
||||
TILE_FRAME* const prevTile = interpolate && interpdata->CanInterpFrameTile(nFrame, i) ? interpdata->PrevTileFinder(thisFrame, prevFrame, i) : nullptr;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
if (thisFrame->tiles[i].picnum > 0)
|
||||
{
|
||||
TILE_FRAME* const thisTile = &thisFrame->tiles[i];
|
||||
TILE_FRAME* const prevTile = interpolate && interpdata->CanInterpFrameTile(nFrame, i) ? interpdata->PrevTileFinder(thisFrame, prevFrame, i) : nullptr;
|
||||
|
||||
double tileX = x;
|
||||
double tileY = y;
|
||||
double tileZ;
|
||||
double tileA;
|
||||
double tileAlpha;
|
||||
int tileShade;
|
||||
auto const tileStat = stat | thisTile->stat;
|
||||
double tileX = x;
|
||||
double tileY = y;
|
||||
double tileZ;
|
||||
double tileA;
|
||||
double tileAlpha;
|
||||
int tileShade;
|
||||
auto const tileStat = stat | thisTile->stat;
|
||||
|
||||
if (prevTile)
|
||||
{
|
||||
tileX += interpolatedvaluef(prevTile->x, thisTile->x, smoothratio);
|
||||
tileY += interpolatedvaluef(prevTile->y, thisTile->y, smoothratio);
|
||||
tileZ = interpolatedvaluef(prevTile->z, thisTile->z, smoothratio);
|
||||
tileA = interpolatedangle(buildang(prevTile->angle), buildang(thisTile->angle), smoothratio).asbuildf();
|
||||
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 thisAlpha = (tileStat & RS_TRANS1) ? glblend[0].def[!!(tileStat & RS_TRANS2)].alpha : 1.;
|
||||
tileAlpha = interpolatedvaluef(prevAlpha, thisAlpha, smoothratio);
|
||||
}
|
||||
else
|
||||
{
|
||||
tileX += thisTile->x;
|
||||
tileY += thisTile->y;
|
||||
tileZ = thisTile->z;
|
||||
tileA = thisTile->angle;
|
||||
tileShade = thisTile->shade + shade;
|
||||
tileAlpha = (tileStat & RS_TRANS1) ? glblend[0].def[!!(tileStat & RS_TRANS2)].alpha : 1.;
|
||||
}
|
||||
if (prevTile)
|
||||
{
|
||||
tileX += interpolatedvaluef(prevTile->x, thisTile->x, smoothratio);
|
||||
tileY += interpolatedvaluef(prevTile->y, thisTile->y, smoothratio);
|
||||
tileZ = interpolatedvaluef(prevTile->z, thisTile->z, smoothratio);
|
||||
tileA = interpolatedangle(buildang(prevTile->angle), buildang(thisTile->angle), smoothratio).asbuildf();
|
||||
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 thisAlpha = (tileStat & RS_TRANS1) ? glblend[0].def[!!(tileStat & RS_TRANS2)].alpha : 1.;
|
||||
tileAlpha = interpolatedvaluef(prevAlpha, thisAlpha, smoothratio);
|
||||
}
|
||||
else
|
||||
{
|
||||
tileX += thisTile->x;
|
||||
tileY += thisTile->y;
|
||||
tileZ = thisTile->z;
|
||||
tileA = thisTile->angle;
|
||||
tileShade = thisTile->shade + shade;
|
||||
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;
|
||||
assert(ticksPerFrame > 0);
|
||||
int frame;
|
||||
int ticks;
|
||||
if (start < 0)
|
||||
frame = (start + 1) / ticksPerFrame;
|
||||
else
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
auto pActor = pData ? pData->actor : nullptr;
|
||||
assert(ticksPerFrame > 0);
|
||||
int frame;
|
||||
int ticks;
|
||||
if (start < 0)
|
||||
frame = (start + 1) / ticksPerFrame;
|
||||
else
|
||||
frame = start / ticksPerFrame + 1;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
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) {
|
||||
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)
|
||||
{
|
||||
for (int i = 0; i < nFrames; i++)
|
||||
{
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
if (frames[i].tiles[j].picnum >= 0)
|
||||
tilePrecacheTile(frames[i].tiles[j].picnum, 0, palette);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < nFrames; i++)
|
||||
{
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
if (frames[i].tiles[j].picnum >= 0)
|
||||
tilePrecacheTile(frames[i].tiles[j].picnum, 0, palette);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void qavProcessTicker(QAV* const pQAV, int* duration, int* lastTick)
|
||||
{
|
||||
if (*duration > 0)
|
||||
{
|
||||
auto thisTick = I_GetTime(pQAV->ticrate);
|
||||
auto numTicks = thisTick - (*lastTick);
|
||||
if (numTicks)
|
||||
{
|
||||
*lastTick = thisTick;
|
||||
*duration -= pQAV->ticksPerFrame * numTicks;
|
||||
}
|
||||
}
|
||||
*duration = ClipLow(*duration, 0);
|
||||
if (*duration > 0)
|
||||
{
|
||||
auto thisTick = I_GetTime(pQAV->ticrate);
|
||||
auto numTicks = thisTick - (*lastTick);
|
||||
if (numTicks)
|
||||
{
|
||||
*lastTick = thisTick;
|
||||
*duration -= pQAV->ticksPerFrame * numTicks;
|
||||
}
|
||||
}
|
||||
*duration = ClipLow(*duration, 0);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void qavProcessTimer(PLAYER* const pPlayer, QAV* const pQAV, int* duration, double* smoothratio, bool const fixedduration, bool const ignoreWeaponTimer)
|
||||
{
|
||||
// Process if not paused.
|
||||
if (!paused)
|
||||
{
|
||||
// Process clock based on QAV's ticrate and last tick value.
|
||||
qavProcessTicker(pQAV, &pPlayer->qavTimer, &pPlayer->qavLastTick);
|
||||
// Process if not paused.
|
||||
if (!paused)
|
||||
{
|
||||
// Process clock based on QAV's ticrate and last tick value.
|
||||
qavProcessTicker(pQAV, &pPlayer->qavTimer, &pPlayer->qavLastTick);
|
||||
|
||||
if (pPlayer->weaponTimer == 0 && pPlayer->qavTimer == 0 && !ignoreWeaponTimer)
|
||||
{
|
||||
// Check if we're playing an idle QAV as per the ticker's weapon timer.
|
||||
*duration = fixedduration ? pQAV->duration - 1 : I_GetBuildTime() % pQAV->duration;
|
||||
*smoothratio = MaxSmoothRatio;
|
||||
}
|
||||
else if (pPlayer->qavTimer == 0)
|
||||
{
|
||||
// If qavTimer is 0, play the last frame uninterpolated. Sometimes the timer can be just ahead of weaponTimer.
|
||||
*duration = pQAV->duration - 1;
|
||||
*smoothratio = MaxSmoothRatio;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Apply normal values.
|
||||
*duration = pQAV->duration - pPlayer->qavTimer;
|
||||
*smoothratio = !cl_interpolate || cl_capfps ? MaxSmoothRatio : I_GetTimeFrac(pQAV->ticrate) * MaxSmoothRatio;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*smoothratio = MaxSmoothRatio;
|
||||
}
|
||||
if (pPlayer->weaponTimer == 0 && pPlayer->qavTimer == 0 && !ignoreWeaponTimer)
|
||||
{
|
||||
// Check if we're playing an idle QAV as per the ticker's weapon timer.
|
||||
*duration = fixedduration ? pQAV->duration - 1 : I_GetBuildTime() % pQAV->duration;
|
||||
*smoothratio = MaxSmoothRatio;
|
||||
}
|
||||
else if (pPlayer->qavTimer == 0)
|
||||
{
|
||||
// If qavTimer is 0, play the last frame uninterpolated. Sometimes the timer can be just ahead of weaponTimer.
|
||||
*duration = pQAV->duration - 1;
|
||||
*smoothratio = MaxSmoothRatio;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Apply normal values.
|
||||
*duration = pQAV->duration - pPlayer->qavTimer;
|
||||
*smoothratio = !cl_interpolate || cl_capfps ? MaxSmoothRatio : I_GetTimeFrac(pQAV->ticrate) * MaxSmoothRatio;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*smoothratio = MaxSmoothRatio;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// 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.
|
||||
// To avoid such unsafe operations this caches the read data separately.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
extern FMemArena seqcache; // Use the same storage as the SEQs.
|
||||
static TMap<int, QAV*> qavcache;
|
||||
QAV* getQAV(int res_id)
|
||||
{
|
||||
auto p = qavcache.CheckKey(res_id);
|
||||
if (p != nullptr) return *p;
|
||||
auto p = qavcache.CheckKey(res_id);
|
||||
if (p != nullptr) return *p;
|
||||
|
||||
int index = fileSystem.FindResource(res_id, "QAV");
|
||||
if (index < 0)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
auto fr = fileSystem.OpenFileReader(index);
|
||||
int index = fileSystem.FindResource(res_id, "QAV");
|
||||
if (index < 0)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
auto fr = fileSystem.OpenFileReader(index);
|
||||
|
||||
// Start reading QAV for nFrames, skipping padded data.
|
||||
for (int i = 0; i < 8; i++) fr.ReadUInt8();
|
||||
int nFrames = fr.ReadInt32();
|
||||
auto qavdata = (QAV*)seqcache.Alloc(sizeof(QAV) + ((nFrames - 1) * sizeof(FRAMEINFO)));
|
||||
// Start reading QAV for nFrames, skipping padded data.
|
||||
for (int i = 0; i < 8; i++) fr.ReadUInt8();
|
||||
int nFrames = fr.ReadInt32();
|
||||
auto qavdata = (QAV*)seqcache.Alloc(sizeof(QAV) + ((nFrames - 1) * sizeof(FRAMEINFO)));
|
||||
|
||||
// Write out QAV data.
|
||||
qavdata->nFrames = nFrames;
|
||||
qavdata->ticksPerFrame = fr.ReadInt32();
|
||||
qavdata->duration = fr.ReadInt32();
|
||||
qavdata->x = fr.ReadInt32();
|
||||
qavdata->y = fr.ReadInt32();
|
||||
/*qavdata->nSprite =*/ fr.ReadInt32();
|
||||
for (int i = 0; i < 4; i++) fr.ReadUInt8();
|
||||
// Write out QAV data.
|
||||
qavdata->nFrames = nFrames;
|
||||
qavdata->ticksPerFrame = fr.ReadInt32();
|
||||
qavdata->duration = fr.ReadInt32();
|
||||
qavdata->x = fr.ReadInt32();
|
||||
qavdata->y = fr.ReadInt32();
|
||||
/*qavdata->nSprite =*/ fr.ReadInt32();
|
||||
for (int i = 0; i < 4; i++) fr.ReadUInt8();
|
||||
|
||||
// Read FRAMEINFO data.
|
||||
for (int i = 0; i < qavdata->nFrames; i++)
|
||||
{
|
||||
qavdata->frames[i].nCallbackId = fr.ReadInt32();
|
||||
// Read FRAMEINFO data.
|
||||
for (int i = 0; i < qavdata->nFrames; i++)
|
||||
{
|
||||
qavdata->frames[i].nCallbackId = fr.ReadInt32();
|
||||
|
||||
// Read SOUNDINFO data.
|
||||
qavdata->frames[i].sound.sound = fr.ReadInt32();
|
||||
qavdata->frames[i].sound.priority = fr.ReadUInt8();
|
||||
qavdata->frames[i].sound.sndFlags = fr.ReadUInt8();
|
||||
qavdata->frames[i].sound.sndRange = fr.ReadUInt8();
|
||||
for (int j = 0; j < 1; j++) fr.ReadUInt8();
|
||||
// Read SOUNDINFO data.
|
||||
qavdata->frames[i].sound.sound = fr.ReadInt32();
|
||||
qavdata->frames[i].sound.priority = fr.ReadUInt8();
|
||||
qavdata->frames[i].sound.sndFlags = fr.ReadUInt8();
|
||||
qavdata->frames[i].sound.sndRange = fr.ReadUInt8();
|
||||
for (int j = 0; j < 1; j++) fr.ReadUInt8();
|
||||
|
||||
// Read TILE_FRAME data.
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
qavdata->frames[i].tiles[j].picnum = fr.ReadInt32();
|
||||
qavdata->frames[i].tiles[j].x = fr.ReadInt32();
|
||||
qavdata->frames[i].tiles[j].y = fr.ReadInt32();
|
||||
qavdata->frames[i].tiles[j].z = fr.ReadInt32();
|
||||
qavdata->frames[i].tiles[j].stat = fr.ReadInt32();
|
||||
qavdata->frames[i].tiles[j].shade = fr.ReadInt8();
|
||||
qavdata->frames[i].tiles[j].palnum = fr.ReadUInt8();
|
||||
qavdata->frames[i].tiles[j].angle = fr.ReadUInt16();
|
||||
}
|
||||
}
|
||||
// Read TILE_FRAME data.
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
qavdata->frames[i].tiles[j].picnum = fr.ReadInt32();
|
||||
qavdata->frames[i].tiles[j].x = fr.ReadInt32();
|
||||
qavdata->frames[i].tiles[j].y = fr.ReadInt32();
|
||||
qavdata->frames[i].tiles[j].z = fr.ReadInt32();
|
||||
qavdata->frames[i].tiles[j].stat = fr.ReadInt32();
|
||||
qavdata->frames[i].tiles[j].shade = fr.ReadInt8();
|
||||
qavdata->frames[i].tiles[j].palnum = fr.ReadUInt8();
|
||||
qavdata->frames[i].tiles[j].angle = fr.ReadUInt16();
|
||||
}
|
||||
}
|
||||
|
||||
// Write out additions.
|
||||
qavdata->res_id = res_id;
|
||||
qavdata->ticrate = 120. / qavdata->ticksPerFrame;
|
||||
// Write out additions.
|
||||
qavdata->res_id = res_id;
|
||||
qavdata->ticrate = 120. / qavdata->ticksPerFrame;
|
||||
|
||||
qavcache.Insert(res_id, qavdata);
|
||||
return qavdata;
|
||||
qavcache.Insert(res_id, qavdata);
|
||||
return qavdata;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -31,208 +31,208 @@ enum { kQavOrientationLeft = 4096 };
|
|||
|
||||
enum
|
||||
{
|
||||
kQAVNone = -1,
|
||||
kQAVNone = -1,
|
||||
|
||||
kQAVFORKUP = 0,
|
||||
kQAVFORKIDLE = 1,
|
||||
kQAVPFORK = 2,
|
||||
kQAVFORKDOWN = 3,
|
||||
kQAVFORKUP = 0,
|
||||
kQAVFORKIDLE = 1,
|
||||
kQAVPFORK = 2,
|
||||
kQAVFORKDOWN = 3,
|
||||
|
||||
kQAVLITEOPEN = 4,
|
||||
kQAVLITEFLAM = 5,
|
||||
kQAVLITEIDLE = 6,
|
||||
kQAVLITECLO2 = 7,
|
||||
kQAVLITEOPEN = 4,
|
||||
kQAVLITEFLAM = 5,
|
||||
kQAVLITEIDLE = 6,
|
||||
kQAVLITECLO2 = 7,
|
||||
|
||||
kQAVCANPREF = 8,
|
||||
kQAVCANIDLE = 9,
|
||||
kQAVCANFIRE = 10,
|
||||
kQAVCANDOWN = 11,
|
||||
kQAVCANFIRE2 = 12,
|
||||
kQAVCANDROP = 13,
|
||||
kQAVCANTHRO = 14,
|
||||
kQAVCANBOOM = 15,
|
||||
kQAVCANPREF = 8,
|
||||
kQAVCANIDLE = 9,
|
||||
kQAVCANFIRE = 10,
|
||||
kQAVCANDOWN = 11,
|
||||
kQAVCANFIRE2 = 12,
|
||||
kQAVCANDROP = 13,
|
||||
kQAVCANTHRO = 14,
|
||||
kQAVCANBOOM = 15,
|
||||
|
||||
kQAVBUNUP = 16,
|
||||
kQAVBUNDOWN = 17,
|
||||
kQAVBUNUP2 = 18,
|
||||
kQAVBUNDOWN2 = 19,
|
||||
kQAVBUNIDLE = 20,
|
||||
kQAVBUNFUSE = 21,
|
||||
kQAVBUNDROP = 22,
|
||||
kQAVBUNTHRO = 23,
|
||||
kQAVBUNUP = 16,
|
||||
kQAVBUNDOWN = 17,
|
||||
kQAVBUNUP2 = 18,
|
||||
kQAVBUNDOWN2 = 19,
|
||||
kQAVBUNIDLE = 20,
|
||||
kQAVBUNFUSE = 21,
|
||||
kQAVBUNDROP = 22,
|
||||
kQAVBUNTHRO = 23,
|
||||
|
||||
kQAVDYNEXPLO = 24,
|
||||
kQAVDYNEXPLO = 24,
|
||||
|
||||
kQAVPROXUP = 25,
|
||||
kQAVPROXDOWN = 26,
|
||||
kQAVPROXIDLE = 27,
|
||||
kQAVPROXDROP = 28,
|
||||
kQAVPROXTHRO = 29,
|
||||
kQAVPROXUP = 25,
|
||||
kQAVPROXDOWN = 26,
|
||||
kQAVPROXIDLE = 27,
|
||||
kQAVPROXDROP = 28,
|
||||
kQAVPROXTHRO = 29,
|
||||
|
||||
kQAVREMUP1 = 30,
|
||||
kQAVREMUP2 = 31,
|
||||
kQAVREMUP3 = 32,
|
||||
kQAVREMDOWN1 = 33,
|
||||
kQAVREMDOWN2 = 34,
|
||||
kQAVREMDOWN3 = 35,
|
||||
kQAVREMIDLE1 = 36,
|
||||
kQAVREMIDLE2 = 37,
|
||||
kQAVREMDROP = 38,
|
||||
kQAVREMTHRO = 39,
|
||||
kQAVREMFIRE = 40,
|
||||
kQAVREMUP1 = 30,
|
||||
kQAVREMUP2 = 31,
|
||||
kQAVREMUP3 = 32,
|
||||
kQAVREMDOWN1 = 33,
|
||||
kQAVREMDOWN2 = 34,
|
||||
kQAVREMDOWN3 = 35,
|
||||
kQAVREMIDLE1 = 36,
|
||||
kQAVREMIDLE2 = 37,
|
||||
kQAVREMDROP = 38,
|
||||
kQAVREMTHRO = 39,
|
||||
kQAVREMFIRE = 40,
|
||||
|
||||
kQAVFLARUP = 41,
|
||||
kQAVFLARIDLE = 42,
|
||||
kQAVFLARFIR2 = 43,
|
||||
kQAVFLARDOWN = 44,
|
||||
kQAVFLARUP = 41,
|
||||
kQAVFLARIDLE = 42,
|
||||
kQAVFLARFIR2 = 43,
|
||||
kQAVFLARDOWN = 44,
|
||||
|
||||
kQAVFLAR2UP = 45,
|
||||
kQAVFLAR2I = 46,
|
||||
kQAVFLAR2F = 47,
|
||||
kQAVFLAR2FIR = 48,
|
||||
kQAVFLAR2DWN = 49,
|
||||
kQAVFLAR2UP = 45,
|
||||
kQAVFLAR2I = 46,
|
||||
kQAVFLAR2F = 47,
|
||||
kQAVFLAR2FIR = 48,
|
||||
kQAVFLAR2DWN = 49,
|
||||
|
||||
kQAVSHOTUP = 50,
|
||||
kQAVSHOTI3 = 51,
|
||||
kQAVSHOTI2 = 52,
|
||||
kQAVSHOTI1 = 53,
|
||||
kQAVSHOTF1 = 54,
|
||||
kQAVSHOTF2 = 55,
|
||||
kQAVSHOTF3 = 56,
|
||||
kQAVSHOTL1 = 57,
|
||||
kQAVSHOTDOWN = 58,
|
||||
kQAVSHOTUP = 50,
|
||||
kQAVSHOTI3 = 51,
|
||||
kQAVSHOTI2 = 52,
|
||||
kQAVSHOTI1 = 53,
|
||||
kQAVSHOTF1 = 54,
|
||||
kQAVSHOTF2 = 55,
|
||||
kQAVSHOTF3 = 56,
|
||||
kQAVSHOTL1 = 57,
|
||||
kQAVSHOTDOWN = 58,
|
||||
|
||||
kQAV2SHOTUP = 59,
|
||||
kQAV2SHOTI = 60,
|
||||
kQAV2SHOTF2 = 61,
|
||||
kQAV2SHOTFIR = 62,
|
||||
kQAV2SHOTDWN = 63,
|
||||
kQAV2SHOTUP = 59,
|
||||
kQAV2SHOTI = 60,
|
||||
kQAV2SHOTF2 = 61,
|
||||
kQAV2SHOTFIR = 62,
|
||||
kQAV2SHOTDWN = 63,
|
||||
|
||||
kQAVTOMUP = 64,
|
||||
kQAVTOMIDLE = 65,
|
||||
kQAVTOMFIRE = 66,
|
||||
kQAVTOMSPRED = 67,
|
||||
kQAVTOMDOWN = 68,
|
||||
kQAVTOMUP = 64,
|
||||
kQAVTOMIDLE = 65,
|
||||
kQAVTOMFIRE = 66,
|
||||
kQAVTOMSPRED = 67,
|
||||
kQAVTOMDOWN = 68,
|
||||
|
||||
kQAV2TOMUP = 69,
|
||||
kQAV2TOMIDLE = 70,
|
||||
kQAV2TOMFIRE = 71,
|
||||
kQAV2TOMDOWN = 72,
|
||||
kQAV2TOMALT = 73,
|
||||
kQAV2TOMUP = 69,
|
||||
kQAV2TOMIDLE = 70,
|
||||
kQAV2TOMFIRE = 71,
|
||||
kQAV2TOMDOWN = 72,
|
||||
kQAV2TOMALT = 73,
|
||||
|
||||
kQAVSGUNUP = 74,
|
||||
kQAVSGUNIDL1 = 75,
|
||||
kQAVSGUNIDL2 = 76,
|
||||
kQAVSGUNFIR1 = 77,
|
||||
kQAVSGUNFIR4 = 78,
|
||||
kQAVSGUNPRE = 79,
|
||||
kQAVSGUNPOST = 80,
|
||||
kQAVSGUNDOWN = 81,
|
||||
kQAVSGUNUP = 74,
|
||||
kQAVSGUNIDL1 = 75,
|
||||
kQAVSGUNIDL2 = 76,
|
||||
kQAVSGUNFIR1 = 77,
|
||||
kQAVSGUNFIR4 = 78,
|
||||
kQAVSGUNPRE = 79,
|
||||
kQAVSGUNPOST = 80,
|
||||
kQAVSGUNDOWN = 81,
|
||||
|
||||
kQAV2SGUNUP = 82,
|
||||
kQAV2SGUNIDL = 83,
|
||||
kQAV2SGUNFIR = 84,
|
||||
kQAV2SGUNALT = 85,
|
||||
kQAV2SGUNPRE = 86,
|
||||
kQAV2SGUNPST = 87,
|
||||
kQAV2SGUNDWN = 88,
|
||||
kQAV2SGUNUP = 82,
|
||||
kQAV2SGUNIDL = 83,
|
||||
kQAV2SGUNFIR = 84,
|
||||
kQAV2SGUNALT = 85,
|
||||
kQAV2SGUNPRE = 86,
|
||||
kQAV2SGUNPST = 87,
|
||||
kQAV2SGUNDWN = 88,
|
||||
|
||||
kQAVNAPUP = 89,
|
||||
kQAVNAPIDLE = 90,
|
||||
kQAVNAPFIRE = 91,
|
||||
kQAVNAPDOWN = 92,
|
||||
kQAVNAPUP = 89,
|
||||
kQAVNAPIDLE = 90,
|
||||
kQAVNAPFIRE = 91,
|
||||
kQAVNAPDOWN = 92,
|
||||
|
||||
kQAVBSTUP = 93,
|
||||
kQAVBSTIDLE = 94,
|
||||
kQAVBSTATAK1 = 95,
|
||||
kQAVBSTATAK2 = 96,
|
||||
kQAVBSTATAK3 = 97,
|
||||
kQAVBSTATAK4 = 98,
|
||||
kQAVBSTDOWN = 99,
|
||||
kQAVBSTUP = 93,
|
||||
kQAVBSTIDLE = 94,
|
||||
kQAVBSTATAK1 = 95,
|
||||
kQAVBSTATAK2 = 96,
|
||||
kQAVBSTATAK3 = 97,
|
||||
kQAVBSTATAK4 = 98,
|
||||
kQAVBSTDOWN = 99,
|
||||
|
||||
kQAVVDUP = 100,
|
||||
kQAVVDIDLE1 = 101,
|
||||
kQAVVDIDLE2 = 102,
|
||||
kQAVVDFIRE1 = 103,
|
||||
kQAVVDFIRE2 = 104,
|
||||
kQAVVDFIRE3 = 105,
|
||||
kQAVVDFIRE4 = 106,
|
||||
kQAVVDFIRE5 = 107,
|
||||
kQAVVDFIRE6 = 108,
|
||||
kQAVVDDOWN = 109,
|
||||
kQAVVDSPEL1 = 110,
|
||||
kQAVVDUP = 100,
|
||||
kQAVVDIDLE1 = 101,
|
||||
kQAVVDIDLE2 = 102,
|
||||
kQAVVDFIRE1 = 103,
|
||||
kQAVVDFIRE2 = 104,
|
||||
kQAVVDFIRE3 = 105,
|
||||
kQAVVDFIRE4 = 106,
|
||||
kQAVVDFIRE5 = 107,
|
||||
kQAVVDFIRE6 = 108,
|
||||
kQAVVDDOWN = 109,
|
||||
kQAVVDSPEL1 = 110,
|
||||
|
||||
kQAVSTAFUP = 111,
|
||||
kQAVSTAFIDL1 = 112,
|
||||
kQAVSTAFIDL3 = 113,
|
||||
kQAVSTAFIRE1 = 114,
|
||||
kQAVSTAFIRE2 = 115,
|
||||
kQAVSTAFIRE4 = 116,
|
||||
kQAVSTAFPRE = 117,
|
||||
kQAVSTAFPOST = 118,
|
||||
kQAVSTAFDOWN = 119,
|
||||
kQAVSTAFUP = 111,
|
||||
kQAVSTAFIDL1 = 112,
|
||||
kQAVSTAFIDL3 = 113,
|
||||
kQAVSTAFIRE1 = 114,
|
||||
kQAVSTAFIRE2 = 115,
|
||||
kQAVSTAFIRE4 = 116,
|
||||
kQAVSTAFPRE = 117,
|
||||
kQAVSTAFPOST = 118,
|
||||
kQAVSTAFDOWN = 119,
|
||||
|
||||
kQAV2NAPUP = 120,
|
||||
kQAV2NAPIDLE = 121,
|
||||
kQAV2NAPFIRE = 122,
|
||||
kQAV2NAPFIR2 = 123,
|
||||
kQAV2NAPDOWN = 124,
|
||||
kQAV2NAPUP = 120,
|
||||
kQAV2NAPIDLE = 121,
|
||||
kQAV2NAPFIRE = 122,
|
||||
kQAV2NAPFIR2 = 123,
|
||||
kQAV2NAPDOWN = 124,
|
||||
|
||||
kQAVEnd = 125,
|
||||
kQAVEnd = 125,
|
||||
|
||||
kQAVBDRIP = 256,
|
||||
kQAVBDRIP = 256,
|
||||
};
|
||||
|
||||
// by NoOne: add sound flags
|
||||
enum
|
||||
{
|
||||
kFlagSoundKill = 0x01, // mute QAV sounds of same priority
|
||||
kFlagSoundKillAll = 0x02, // mute all QAV sounds
|
||||
kFlagSoundKill = 0x01, // mute QAV sounds of same priority
|
||||
kFlagSoundKillAll = 0x02, // mute all QAV sounds
|
||||
|
||||
};
|
||||
|
||||
struct TILE_FRAME
|
||||
{
|
||||
int picnum;
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
int stat;
|
||||
int8_t shade;
|
||||
int8_t palnum;
|
||||
uint16_t angle;
|
||||
int picnum;
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
int stat;
|
||||
int8_t shade;
|
||||
int8_t palnum;
|
||||
uint16_t angle;
|
||||
};
|
||||
|
||||
struct SOUNDINFO
|
||||
{
|
||||
int sound;
|
||||
uint8_t priority;
|
||||
uint8_t sndFlags; // (by NoOne) Various sound flags
|
||||
uint8_t sndRange; // (by NoOne) Random sound range
|
||||
uint8_t reserved[1];
|
||||
int sound;
|
||||
uint8_t priority;
|
||||
uint8_t sndFlags; // (by NoOne) Various sound flags
|
||||
uint8_t sndRange; // (by NoOne) Random sound range
|
||||
uint8_t reserved[1];
|
||||
};
|
||||
|
||||
struct FRAMEINFO
|
||||
{
|
||||
int nCallbackId; // 0
|
||||
SOUNDINFO sound; // 4
|
||||
TILE_FRAME tiles[8]; // 12
|
||||
int nCallbackId; // 0
|
||||
SOUNDINFO sound; // 4
|
||||
TILE_FRAME tiles[8]; // 12
|
||||
};
|
||||
|
||||
struct QAV
|
||||
{
|
||||
double ticrate; // 0
|
||||
int nFrames; // 8
|
||||
int ticksPerFrame; // C
|
||||
int duration; // 10
|
||||
int x; // 14
|
||||
int y; // 18
|
||||
uint16_t res_id;
|
||||
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(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 Precache(int palette = 0);
|
||||
double ticrate; // 0
|
||||
int nFrames; // 8
|
||||
int ticksPerFrame; // C
|
||||
int duration; // 10
|
||||
int x; // 14
|
||||
int y; // 18
|
||||
uint16_t res_id;
|
||||
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(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 Precache(int palette = 0);
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
auto const lump = fileSystem.FindResource(res_id, "QAV");
|
||||
return lump >= 0 && fileSystem.GetFileContainer(lump) < fileSystem.GetMaxIwadNum();
|
||||
auto const lump = fileSystem.FindResource(res_id, "QAV");
|
||||
return lump >= 0 && fileSystem.GetFileContainer(lump) < fileSystem.GetMaxIwadNum();
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -43,45 +43,57 @@ CVAR(Bool, hud_ctf_vanilla, false, CVAR_ARCHIVE)
|
|||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static void UpdateFrame(void)
|
||||
{
|
||||
auto tex = tileGetTexture(kBackTile);
|
||||
int width = twod->GetWidth();
|
||||
int height = twod->GetHeight();
|
||||
auto tex = tileGetTexture(kBackTile);
|
||||
int width = twod->GetWidth();
|
||||
int height = twod->GetHeight();
|
||||
|
||||
twod->AddFlatFill(0, 0, width, windowxy1.Y - 3, 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(windowxy2.X + 4, windowxy1.Y - 3, width, windowxy2.Y + 4, tex);
|
||||
twod->AddFlatFill(0, 0, width, windowxy1.Y - 3, 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(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, 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(windowxy1.X - 3, windowxy2.Y + 1, windowxy2.X + 1, windowxy2.Y + 4, tex, 0, 1, 0xff2a2a2a);
|
||||
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(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);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void UpdateStatusBar()
|
||||
{
|
||||
if (automapMode == am_off && hud_size <= Hud_Stbar)
|
||||
{
|
||||
UpdateFrame();
|
||||
}
|
||||
SummaryInfo sum;
|
||||
if (gGameOptions.nGameType == 3)
|
||||
{
|
||||
sum.kills = gView ? gView->fragCount : 0;
|
||||
sum.maxkills = -3;
|
||||
}
|
||||
else
|
||||
{
|
||||
sum.kills = gKillMgr.Kills;
|
||||
sum.maxkills = gKillMgr.TotalKills;
|
||||
}
|
||||
sum.secrets = gSecretMgr.Founds;
|
||||
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.time = Scale(PlayClock, 1000, 120);
|
||||
UpdateStatusBar(&sum);
|
||||
if (automapMode == am_off && hud_size <= Hud_Stbar)
|
||||
{
|
||||
UpdateFrame();
|
||||
}
|
||||
SummaryInfo sum;
|
||||
if (gGameOptions.nGameType == 3)
|
||||
{
|
||||
sum.kills = gView ? gView->fragCount : 0;
|
||||
sum.maxkills = -3;
|
||||
}
|
||||
else
|
||||
{
|
||||
sum.kills = gKillMgr.Kills;
|
||||
sum.maxkills = gKillMgr.TotalKills;
|
||||
}
|
||||
sum.secrets = gSecretMgr.Founds;
|
||||
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.time = Scale(PlayClock, 1000, 120);
|
||||
UpdateStatusBar(&sum);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -30,321 +30,355 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
BEGIN_BLD_NS
|
||||
|
||||
static const uint8_t flicker1[] = {
|
||||
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,
|
||||
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, 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,
|
||||
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
|
||||
};
|
||||
|
||||
static const uint8_t flicker2[] = {
|
||||
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,
|
||||
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
|
||||
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,
|
||||
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
|
||||
};
|
||||
|
||||
static const uint8_t flicker3[] = {
|
||||
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, 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
|
||||
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, 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
|
||||
};
|
||||
|
||||
static const uint8_t flicker4[] = {
|
||||
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,
|
||||
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, 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,
|
||||
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, 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
|
||||
};
|
||||
|
||||
static const uint8_t strobe[] = {
|
||||
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,
|
||||
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
|
||||
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,
|
||||
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)
|
||||
{
|
||||
b &= 2047;
|
||||
switch (a)
|
||||
{
|
||||
case 0:
|
||||
return c;
|
||||
case 1:
|
||||
return (b>>10)*c;
|
||||
case 2:
|
||||
return (abs(128-(b>>3))*c)>>7;
|
||||
case 3:
|
||||
return ((b>>3)*c)>>8;
|
||||
case 4:
|
||||
return ((255-(b>>3))*c)>>8;
|
||||
case 5:
|
||||
return (c+MulScale(c,Sin(b), 30))>>1;
|
||||
case 6:
|
||||
return flicker1[b>>5]*c;
|
||||
case 7:
|
||||
return (flicker2[b>>5]*c)>>2;
|
||||
case 8:
|
||||
return (flicker3[b>>5]*c)>>2;
|
||||
case 9:
|
||||
return (flicker4[b>>4]*c)>>2;
|
||||
case 10:
|
||||
return (strobe[b>>5]*c)>>6;
|
||||
case 11:
|
||||
if (b*4 > 2048)
|
||||
return 0;
|
||||
return (c-MulScale(c, Cos(b*4), 30))>>1;
|
||||
}
|
||||
return 0;
|
||||
b &= 2047;
|
||||
switch (a)
|
||||
{
|
||||
case 0:
|
||||
return c;
|
||||
case 1:
|
||||
return (b >> 10) * c;
|
||||
case 2:
|
||||
return (abs(128 - (b >> 3)) * c) >> 7;
|
||||
case 3:
|
||||
return ((b >> 3) * c) >> 8;
|
||||
case 4:
|
||||
return ((255 - (b >> 3)) * c) >> 8;
|
||||
case 5:
|
||||
return (c + MulScale(c, Sin(b), 30)) >> 1;
|
||||
case 6:
|
||||
return flicker1[b >> 5] * c;
|
||||
case 7:
|
||||
return (flicker2[b >> 5] * c) >> 2;
|
||||
case 8:
|
||||
return (flicker3[b >> 5] * c) >> 2;
|
||||
case 9:
|
||||
return (flicker4[b >> 4] * c) >> 2;
|
||||
case 10:
|
||||
return (strobe[b >> 5] * c) >> 6;
|
||||
case 11:
|
||||
if (b * 4 > 2048)
|
||||
return 0;
|
||||
return (c - MulScale(c, Cos(b * 4), 30)) >> 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// These can be fully regenerated after loading a savegame.
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
TArray<sectortype*> shadeList;
|
||||
TArray<sectortype*> panList;
|
||||
TArray<walltype*> wallPanList;
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void DoSectorLighting(void)
|
||||
{
|
||||
for (auto& pSector : shadeList)
|
||||
{
|
||||
XSECTOR* pXSector = &pSector->xs();
|
||||
if (pXSector->shade)
|
||||
{
|
||||
int v4 = pXSector->shade;
|
||||
if (pXSector->shadeFloor)
|
||||
{
|
||||
pSector->floorshade -= v4;
|
||||
if (pXSector->color)
|
||||
{
|
||||
int nTemp = pXSector->floorpal;
|
||||
pXSector->floorpal = pSector->floorpal;
|
||||
pSector->floorpal = nTemp;
|
||||
}
|
||||
}
|
||||
if (pXSector->shadeCeiling)
|
||||
{
|
||||
pSector->ceilingshade -= v4;
|
||||
if (pXSector->color)
|
||||
{
|
||||
int nTemp = pXSector->ceilpal;
|
||||
pXSector->ceilpal = pSector->ceilingpal;
|
||||
pSector->ceilingpal = nTemp;
|
||||
}
|
||||
}
|
||||
if (pXSector->shadeWalls)
|
||||
{
|
||||
for(auto& wal : wallsofsector(pSector))
|
||||
{
|
||||
wal.shade -= v4;
|
||||
if (pXSector->color)
|
||||
{
|
||||
wal.pal = pSector->floorpal;
|
||||
}
|
||||
}
|
||||
}
|
||||
pXSector->shade = 0;
|
||||
}
|
||||
if (pXSector->shadeAlways || pXSector->busy)
|
||||
{
|
||||
int t1 = pXSector->wave;
|
||||
int t2 = pXSector->amplitude;
|
||||
if (!pXSector->shadeAlways && pXSector->busy)
|
||||
{
|
||||
t2 = MulScale(t2, pXSector->busy, 16);
|
||||
}
|
||||
int v4 = GetWaveValue(t1, pXSector->phase*8+pXSector->freq*PlayClock, t2);
|
||||
if (pXSector->shadeFloor)
|
||||
{
|
||||
pSector->floorshade = ClipRange(pSector->floorshade+v4, -128, 127);
|
||||
if (pXSector->color && v4 != 0)
|
||||
{
|
||||
int nTemp = pXSector->floorpal;
|
||||
pXSector->floorpal = pSector->floorpal;
|
||||
pSector->floorpal = nTemp;
|
||||
}
|
||||
}
|
||||
if (pXSector->shadeCeiling)
|
||||
{
|
||||
pSector->ceilingshade = ClipRange(pSector->ceilingshade+v4, -128, 127);
|
||||
if (pXSector->color && v4 != 0)
|
||||
{
|
||||
int nTemp = pXSector->ceilpal;
|
||||
pXSector->ceilpal = pSector->ceilingpal;
|
||||
pSector->ceilingpal = nTemp;
|
||||
}
|
||||
}
|
||||
if (pXSector->shadeWalls)
|
||||
{
|
||||
for (auto& wal : wallsofsector(pSector))
|
||||
{
|
||||
wal.shade = ClipRange(wal.shade+v4, -128, 127);
|
||||
if (pXSector->color && v4 != 0)
|
||||
{
|
||||
wal.pal = pSector->floorpal;
|
||||
}
|
||||
}
|
||||
}
|
||||
pXSector->shade = v4;
|
||||
}
|
||||
}
|
||||
for (auto& pSector : shadeList)
|
||||
{
|
||||
XSECTOR* pXSector = &pSector->xs();
|
||||
if (pXSector->shade)
|
||||
{
|
||||
int v4 = pXSector->shade;
|
||||
if (pXSector->shadeFloor)
|
||||
{
|
||||
pSector->floorshade -= v4;
|
||||
if (pXSector->color)
|
||||
{
|
||||
int nTemp = pXSector->floorpal;
|
||||
pXSector->floorpal = pSector->floorpal;
|
||||
pSector->floorpal = nTemp;
|
||||
}
|
||||
}
|
||||
if (pXSector->shadeCeiling)
|
||||
{
|
||||
pSector->ceilingshade -= v4;
|
||||
if (pXSector->color)
|
||||
{
|
||||
int nTemp = pXSector->ceilpal;
|
||||
pXSector->ceilpal = pSector->ceilingpal;
|
||||
pSector->ceilingpal = nTemp;
|
||||
}
|
||||
}
|
||||
if (pXSector->shadeWalls)
|
||||
{
|
||||
for (auto& wal : wallsofsector(pSector))
|
||||
{
|
||||
wal.shade -= v4;
|
||||
if (pXSector->color)
|
||||
{
|
||||
wal.pal = pSector->floorpal;
|
||||
}
|
||||
}
|
||||
}
|
||||
pXSector->shade = 0;
|
||||
}
|
||||
if (pXSector->shadeAlways || pXSector->busy)
|
||||
{
|
||||
int t1 = pXSector->wave;
|
||||
int t2 = pXSector->amplitude;
|
||||
if (!pXSector->shadeAlways && pXSector->busy)
|
||||
{
|
||||
t2 = MulScale(t2, pXSector->busy, 16);
|
||||
}
|
||||
int v4 = GetWaveValue(t1, pXSector->phase * 8 + pXSector->freq * PlayClock, t2);
|
||||
if (pXSector->shadeFloor)
|
||||
{
|
||||
pSector->floorshade = ClipRange(pSector->floorshade + v4, -128, 127);
|
||||
if (pXSector->color && v4 != 0)
|
||||
{
|
||||
int nTemp = pXSector->floorpal;
|
||||
pXSector->floorpal = pSector->floorpal;
|
||||
pSector->floorpal = nTemp;
|
||||
}
|
||||
}
|
||||
if (pXSector->shadeCeiling)
|
||||
{
|
||||
pSector->ceilingshade = ClipRange(pSector->ceilingshade + v4, -128, 127);
|
||||
if (pXSector->color && v4 != 0)
|
||||
{
|
||||
int nTemp = pXSector->ceilpal;
|
||||
pXSector->ceilpal = pSector->ceilingpal;
|
||||
pSector->ceilingpal = nTemp;
|
||||
}
|
||||
}
|
||||
if (pXSector->shadeWalls)
|
||||
{
|
||||
for (auto& wal : wallsofsector(pSector))
|
||||
{
|
||||
wal.shade = ClipRange(wal.shade + v4, -128, 127);
|
||||
if (pXSector->color && v4 != 0)
|
||||
{
|
||||
wal.pal = pSector->floorpal;
|
||||
}
|
||||
}
|
||||
}
|
||||
pXSector->shade = v4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void UndoSectorLighting(void)
|
||||
{
|
||||
for (auto& sect: sector)
|
||||
{
|
||||
if (sect.hasX())
|
||||
{
|
||||
XSECTOR *pXSector = §.xs();
|
||||
if (pXSector->shade)
|
||||
{
|
||||
int v4 = pXSector->shade;
|
||||
if (pXSector->shadeFloor)
|
||||
{
|
||||
sect.floorshade -= v4;
|
||||
if (pXSector->color)
|
||||
{
|
||||
int nTemp = pXSector->floorpal;
|
||||
pXSector->floorpal = sect.floorpal;
|
||||
sect.floorpal = nTemp;
|
||||
}
|
||||
}
|
||||
if (pXSector->shadeCeiling)
|
||||
{
|
||||
sect.ceilingshade -= v4;
|
||||
if (pXSector->color)
|
||||
{
|
||||
int nTemp = pXSector->ceilpal;
|
||||
pXSector->ceilpal = sect.ceilingpal;
|
||||
sect.ceilingpal = nTemp;
|
||||
}
|
||||
}
|
||||
if (pXSector->shadeWalls)
|
||||
{
|
||||
for(auto& wal : wallsofsector(§))
|
||||
{
|
||||
wal.shade -= v4;
|
||||
if (pXSector->color)
|
||||
{
|
||||
wal.pal = sect.floorpal;
|
||||
}
|
||||
}
|
||||
}
|
||||
pXSector->shade = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto& sect : sector)
|
||||
{
|
||||
if (sect.hasX())
|
||||
{
|
||||
XSECTOR* pXSector = §.xs();
|
||||
if (pXSector->shade)
|
||||
{
|
||||
int v4 = pXSector->shade;
|
||||
if (pXSector->shadeFloor)
|
||||
{
|
||||
sect.floorshade -= v4;
|
||||
if (pXSector->color)
|
||||
{
|
||||
int nTemp = pXSector->floorpal;
|
||||
pXSector->floorpal = sect.floorpal;
|
||||
sect.floorpal = nTemp;
|
||||
}
|
||||
}
|
||||
if (pXSector->shadeCeiling)
|
||||
{
|
||||
sect.ceilingshade -= v4;
|
||||
if (pXSector->color)
|
||||
{
|
||||
int nTemp = pXSector->ceilpal;
|
||||
pXSector->ceilpal = sect.ceilingpal;
|
||||
sect.ceilingpal = nTemp;
|
||||
}
|
||||
}
|
||||
if (pXSector->shadeWalls)
|
||||
{
|
||||
for (auto& wal : wallsofsector(§))
|
||||
{
|
||||
wal.shade -= v4;
|
||||
if (pXSector->color)
|
||||
{
|
||||
wal.pal = sect.floorpal;
|
||||
}
|
||||
}
|
||||
}
|
||||
pXSector->shade = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void DoSectorPanning(void)
|
||||
{
|
||||
for(auto pSector : panList)
|
||||
{
|
||||
XSECTOR *pXSector = &pSector->xs();
|
||||
if (pXSector->panAlways || pXSector->busy)
|
||||
{
|
||||
int angle = pXSector->panAngle+1024;
|
||||
int speed = pXSector->panVel<<10;
|
||||
if (!pXSector->panAlways && (pXSector->busy&0xffff))
|
||||
speed = MulScale(speed, pXSector->busy, 16);
|
||||
for (auto pSector : panList)
|
||||
{
|
||||
XSECTOR* pXSector = &pSector->xs();
|
||||
if (pXSector->panAlways || pXSector->busy)
|
||||
{
|
||||
int angle = pXSector->panAngle + 1024;
|
||||
int speed = pXSector->panVel << 10;
|
||||
if (!pXSector->panAlways && (pXSector->busy & 0xffff))
|
||||
speed = MulScale(speed, pXSector->busy, 16);
|
||||
|
||||
if (pXSector->panFloor) // Floor
|
||||
{
|
||||
int nTile = pSector->floorpicnum;
|
||||
if (pSector->floorstat & CSTAT_SECTOR_ALIGN)
|
||||
angle -= 512;
|
||||
int xBits = tileWidth(nTile) >> int((pSector->floorstat & CSTAT_SECTOR_TEXHALF) != 0);
|
||||
int px = MulScale(speed << 2, Cos(angle), 30) / xBits;
|
||||
int yBits = tileHeight(nTile) >> int((pSector->floorstat & CSTAT_SECTOR_TEXHALF) != 0);
|
||||
int py = MulScale(speed << 2, Sin(angle), 30) / yBits;
|
||||
pSector->addfloorxpan(px * (1.f / 256));
|
||||
pSector->addfloorypan(-py * (1.f / 256));
|
||||
}
|
||||
if (pXSector->panCeiling) // Ceiling
|
||||
{
|
||||
int nTile = pSector->ceilingpicnum;
|
||||
if (pSector->ceilingstat & CSTAT_SECTOR_ALIGN)
|
||||
angle -= 512;
|
||||
int xBits = tileWidth(nTile) >> int((pSector->ceilingstat & CSTAT_SECTOR_TEXHALF) != 0);
|
||||
int px = MulScale(speed << 2, Cos(angle), 30) / xBits;
|
||||
int yBits = tileHeight(nTile) >> int((pSector->ceilingstat & CSTAT_SECTOR_TEXHALF) != 0);
|
||||
int py = MulScale(speed << 2, Sin(angle), 30) / yBits;
|
||||
pSector->addceilingxpan(px * (1.f / 256));
|
||||
pSector->addceilingypan(-py * (1.f / 256));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto pWall : wallPanList)
|
||||
{
|
||||
XWALL *pXWall = &pWall->xw();
|
||||
if (pXWall->panAlways || pXWall->busy)
|
||||
{
|
||||
int psx = pXWall->panXVel<<10;
|
||||
int psy = pXWall->panYVel<<10;
|
||||
if (!pXWall->panAlways && (pXWall->busy & 0xffff))
|
||||
{
|
||||
psx = MulScale(psx, pXWall->busy, 16);
|
||||
psy = MulScale(psy, pXWall->busy, 16);
|
||||
}
|
||||
int nTile = pWall->picnum;
|
||||
int px = (psx << 2) / tileWidth(nTile);
|
||||
int py = (psy << 2) / tileHeight(nTile);
|
||||
if (pXSector->panFloor) // Floor
|
||||
{
|
||||
int nTile = pSector->floorpicnum;
|
||||
if (pSector->floorstat & CSTAT_SECTOR_ALIGN)
|
||||
angle -= 512;
|
||||
int xBits = tileWidth(nTile) >> int((pSector->floorstat & CSTAT_SECTOR_TEXHALF) != 0);
|
||||
int px = MulScale(speed << 2, Cos(angle), 30) / xBits;
|
||||
int yBits = tileHeight(nTile) >> int((pSector->floorstat & CSTAT_SECTOR_TEXHALF) != 0);
|
||||
int py = MulScale(speed << 2, Sin(angle), 30) / yBits;
|
||||
pSector->addfloorxpan(px * (1.f / 256));
|
||||
pSector->addfloorypan(-py * (1.f / 256));
|
||||
}
|
||||
if (pXSector->panCeiling) // Ceiling
|
||||
{
|
||||
int nTile = pSector->ceilingpicnum;
|
||||
if (pSector->ceilingstat & CSTAT_SECTOR_ALIGN)
|
||||
angle -= 512;
|
||||
int xBits = tileWidth(nTile) >> int((pSector->ceilingstat & CSTAT_SECTOR_TEXHALF) != 0);
|
||||
int px = MulScale(speed << 2, Cos(angle), 30) / xBits;
|
||||
int yBits = tileHeight(nTile) >> int((pSector->ceilingstat & CSTAT_SECTOR_TEXHALF) != 0);
|
||||
int py = MulScale(speed << 2, Sin(angle), 30) / yBits;
|
||||
pSector->addceilingxpan(px * (1.f / 256));
|
||||
pSector->addceilingypan(-py * (1.f / 256));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto pWall : wallPanList)
|
||||
{
|
||||
XWALL* pXWall = &pWall->xw();
|
||||
if (pXWall->panAlways || pXWall->busy)
|
||||
{
|
||||
int psx = pXWall->panXVel << 10;
|
||||
int psy = pXWall->panYVel << 10;
|
||||
if (!pXWall->panAlways && (pXWall->busy & 0xffff))
|
||||
{
|
||||
psx = MulScale(psx, pXWall->busy, 16);
|
||||
psy = MulScale(psy, pXWall->busy, 16);
|
||||
}
|
||||
int nTile = pWall->picnum;
|
||||
int px = (psx << 2) / tileWidth(nTile);
|
||||
int py = (psy << 2) / tileHeight(nTile);
|
||||
|
||||
pWall->addxpan(px * (1.f / 256));
|
||||
pWall->addypan(py * (1.f / 256));
|
||||
}
|
||||
}
|
||||
pWall->addxpan(px * (1.f / 256));
|
||||
pWall->addypan(py * (1.f / 256));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void InitSectorFX(void)
|
||||
{
|
||||
shadeList.Clear();
|
||||
panList.Clear();
|
||||
wallPanList.Clear();
|
||||
for (auto& sect: sector)
|
||||
{
|
||||
if (sect.hasX())
|
||||
{
|
||||
XSECTOR *pXSector = §.xs();
|
||||
if (pXSector->amplitude)
|
||||
shadeList.Push(§);
|
||||
if (pXSector->panVel)
|
||||
{
|
||||
panList.Push(§);
|
||||
shadeList.Clear();
|
||||
panList.Clear();
|
||||
wallPanList.Clear();
|
||||
for (auto& sect : sector)
|
||||
{
|
||||
if (sect.hasX())
|
||||
{
|
||||
XSECTOR* pXSector = §.xs();
|
||||
if (pXSector->amplitude)
|
||||
shadeList.Push(§);
|
||||
if (pXSector->panVel)
|
||||
{
|
||||
panList.Push(§);
|
||||
|
||||
if (pXSector->panCeiling)
|
||||
{
|
||||
StartInterpolation(§, Interp_Sect_CeilingPanX);
|
||||
StartInterpolation(§, Interp_Sect_CeilingPanY);
|
||||
}
|
||||
if (pXSector->panFloor)
|
||||
{
|
||||
StartInterpolation(§, Interp_Sect_FloorPanX);
|
||||
StartInterpolation(§, Interp_Sect_FloorPanY);
|
||||
}
|
||||
if (pXSector->panCeiling)
|
||||
{
|
||||
StartInterpolation(§, Interp_Sect_CeilingPanX);
|
||||
StartInterpolation(§, Interp_Sect_CeilingPanY);
|
||||
}
|
||||
if (pXSector->panFloor)
|
||||
{
|
||||
StartInterpolation(§, Interp_Sect_FloorPanX);
|
||||
StartInterpolation(§, Interp_Sect_FloorPanY);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
for(auto& wal : wall)
|
||||
{
|
||||
if (wal.hasX())
|
||||
{
|
||||
XWALL *pXWall = &wal.xw();
|
||||
if (pXWall->panXVel || pXWall->panYVel)
|
||||
{
|
||||
wallPanList.Push(&wal);
|
||||
if (pXWall->panXVel) StartInterpolation(&wal, Interp_Wall_PanX);
|
||||
if (pXWall->panXVel) StartInterpolation(&wal, Interp_Wall_PanY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto& wal : wall)
|
||||
{
|
||||
if (wal.hasX())
|
||||
{
|
||||
XWALL* pXWall = &wal.xw();
|
||||
if (pXWall->panXVel || pXWall->panYVel)
|
||||
{
|
||||
wallPanList.Push(&wal);
|
||||
if (pXWall->panXVel) StartInterpolation(&wal, Interp_Wall_PanX);
|
||||
if (pXWall->panXVel) StartInterpolation(&wal, Interp_Wall_PanY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -351,7 +351,7 @@ void SEQINST::Update()
|
|||
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
|
||||
int surf = tileGetSurfType(actor->spr.sector()->floorpicnum);
|
||||
int surf = tileGetSurfType(actor->spr.sector()->floorpicnum);
|
||||
if (!surf) break;
|
||||
static int surfSfxMove[15][4] = {
|
||||
/* {snd1, snd2, gameVolume, myVolume} */
|
||||
|
@ -704,7 +704,7 @@ void seqProcess(int nTicks)
|
|||
{
|
||||
evKillActor(actor);
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -747,8 +747,8 @@ FSerializer& Serialize(FSerializer& arc, const char* keyname, SEQINST& w, SEQINS
|
|||
("timecounter", w.timeCounter)
|
||||
("frameindex", w.frameIndex)
|
||||
("target", w.target);
|
||||
|
||||
arc.EndObject();
|
||||
|
||||
arc.EndObject();
|
||||
}
|
||||
return arc;
|
||||
}
|
||||
|
|
|
@ -31,27 +31,27 @@ BEGIN_BLD_NS
|
|||
|
||||
class BloodSoundEngine : public RazeSoundEngine
|
||||
{
|
||||
// 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;
|
||||
TArray<uint8_t> ReadSound(int lumpnum) override;
|
||||
// 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;
|
||||
TArray<uint8_t> ReadSound(int lumpnum) override;
|
||||
|
||||
public:
|
||||
BloodSoundEngine()
|
||||
{
|
||||
S_Rolloff.RolloffType = ROLLOFF_Doom;
|
||||
S_Rolloff.MinDistance = 170; // these are the numbers I got when uncrunching the original sound code.
|
||||
S_Rolloff.MaxDistance = 850;
|
||||
}
|
||||
BloodSoundEngine()
|
||||
{
|
||||
S_Rolloff.RolloffType = ROLLOFF_Doom;
|
||||
S_Rolloff.MinDistance = 170; // these are the numbers I got when uncrunching the original sound code.
|
||||
S_Rolloff.MaxDistance = 850;
|
||||
}
|
||||
|
||||
void StopChannel(FSoundChan* chan) override
|
||||
{
|
||||
if (chan && chan->SysChannel != nullptr && !(chan->ChanFlags & CHANF_EVICTED) && chan->SourceType == SOURCE_Actor)
|
||||
{
|
||||
chan->Source = nullptr;
|
||||
chan->SourceType = SOURCE_Unattached;
|
||||
}
|
||||
SoundEngine::StopChannel(chan);
|
||||
}
|
||||
void StopChannel(FSoundChan* chan) override
|
||||
{
|
||||
if (chan && chan->SysChannel != nullptr && !(chan->ChanFlags & CHANF_EVICTED) && chan->SourceType == SOURCE_Actor)
|
||||
{
|
||||
chan->Source = nullptr;
|
||||
chan->SourceType = SOURCE_Unattached;
|
||||
}
|
||||
SoundEngine::StopChannel(chan);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -65,205 +65,240 @@ public:
|
|||
|
||||
TArray<uint8_t> BloodSoundEngine::ReadSound(int lumpnum)
|
||||
{
|
||||
auto wlump = fileSystem.OpenFileReader(lumpnum);
|
||||
return wlump.Read();
|
||||
auto wlump = fileSystem.OpenFileReader(lumpnum);
|
||||
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)
|
||||
{
|
||||
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 (pos != nullptr && type != SOURCE_None)
|
||||
{
|
||||
FVector3 camera;
|
||||
|
||||
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)
|
||||
{
|
||||
pos->X = pt[0];
|
||||
pos->Y = pt[1];
|
||||
pos->Z = pt[2];
|
||||
}
|
||||
else if (type == SOURCE_Actor)
|
||||
{
|
||||
assert(source != nullptr);
|
||||
auto actor = (DBloodActor*)source;
|
||||
if (vel) vel->Zero();
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
if (type == SOURCE_Unattached)
|
||||
{
|
||||
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 (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()
|
||||
{
|
||||
SoundListener listener;
|
||||
SoundListener listener;
|
||||
|
||||
if (gMe->actor)
|
||||
{
|
||||
listener.angle = -gMe->actor->spr.ang * float(BAngRadian); // Build uses a period of 2048.
|
||||
listener.velocity.Zero();
|
||||
listener.position = GetSoundPos(&gMe->actor->spr.pos);
|
||||
listener.valid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
listener.position.Zero();
|
||||
listener.valid = false;
|
||||
}
|
||||
listener.underwater = false;
|
||||
// This should probably use a real environment instead of the pitch hacking in S_PlaySound3D.
|
||||
// listenactor->waterlevel == 3;
|
||||
//assert(primaryLevel->Zones.Size() > listenactor->Sector->ZoneNumber);
|
||||
listener.Environment = 0;// primaryLevel->Zones[listenactor->Sector->ZoneNumber].Environment;
|
||||
if (gMe->actor)
|
||||
{
|
||||
listener.angle = -gMe->actor->spr.ang * float(BAngRadian); // Build uses a period of 2048.
|
||||
listener.velocity.Zero();
|
||||
listener.position = GetSoundPos(&gMe->actor->spr.pos);
|
||||
listener.valid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
listener.position.Zero();
|
||||
listener.valid = false;
|
||||
}
|
||||
listener.underwater = false;
|
||||
// This should probably use a real environment instead of the pitch hacking in S_PlaySound3D.
|
||||
// listenactor->waterlevel == 3;
|
||||
//assert(primaryLevel->Zones.Size() > listenactor->Sector->ZoneNumber);
|
||||
listener.Environment = 0;// primaryLevel->Zones[listenactor->Sector->ZoneNumber].Environment;
|
||||
|
||||
listener.ListenerObject = gMe;
|
||||
soundEngine->SetListener(listener);
|
||||
soundEngine->UpdateSounds(I_GetTime());
|
||||
listener.ListenerObject = gMe;
|
||||
soundEngine->SetListener(listener);
|
||||
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);
|
||||
if (pitch < 0) pitch = udata ? udata[0] : 0x10000;
|
||||
auto udata = soundEngine->GetUserData(soundId);
|
||||
if (pitch < 0) pitch = udata ? udata[0] : 0x10000;
|
||||
|
||||
if (relvol < 0) relvol = 0;
|
||||
else if (relvol == 0) relvol = udata && udata[2] ? udata[2] : 80;
|
||||
if (relvol > 255) relvol = 255;
|
||||
// Limit the attenuation. More than 2.0 is simply too much.
|
||||
attenuation = relvol > 0 ? clamp(80.f / relvol, 0.f, 2.f) : 1.f;
|
||||
return soundId;
|
||||
else if (relvol == 0) relvol = udata && udata[2] ? udata[2] : 80;
|
||||
if (relvol > 255) relvol = 255;
|
||||
// Limit the attenuation. More than 2.0 is simply too much.
|
||||
attenuation = relvol > 0 ? clamp(80.f / relvol, 0.f, 2.f) : 1.f;
|
||||
return soundId;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void sfxPlay3DSound(int x, int y, int z, int soundId, sectortype* pSector)
|
||||
{
|
||||
if (!SoundEnabled() || soundId < 0) return;
|
||||
auto sid = soundEngine->FindSoundByResID(soundId);
|
||||
if (sid == 0) return;
|
||||
if (!SoundEnabled() || soundId < 0) return;
|
||||
auto sid = soundEngine->FindSoundByResID(soundId);
|
||||
if (sid == 0) return;
|
||||
|
||||
vec3_t xyz = { x, y, z };
|
||||
auto svec = GetSoundPos(&xyz);
|
||||
vec3_t xyz = { x, y, z };
|
||||
auto svec = GetSoundPos(&xyz);
|
||||
|
||||
float attenuation;
|
||||
int pitch = -1;
|
||||
int relvol = 0;
|
||||
sid = getSfx(sid, attenuation, pitch, relvol);
|
||||
auto sfx = soundEngine->GetSfx(sid);
|
||||
EChanFlags flags = CHANF_OVERLAP;
|
||||
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);
|
||||
if (chan) chan->UserData = sectnum(pSector);
|
||||
float attenuation;
|
||||
int pitch = -1;
|
||||
int relvol = 0;
|
||||
sid = getSfx(sid, attenuation, pitch, relvol);
|
||||
auto sfx = soundEngine->GetSfx(sid);
|
||||
EChanFlags flags = CHANF_OVERLAP;
|
||||
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);
|
||||
if (chan) chan->UserData = sectnum(pSector);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void sfxPlay3DSoundCP(DBloodActor* pActor, int soundId, int playchannel, int playflags, int pitch, int volume)
|
||||
{
|
||||
if (!SoundEnabled() || soundId < 0 || !pActor) return;
|
||||
auto sid = soundEngine->FindSoundByResID(soundId);
|
||||
if (sid == 0) return;
|
||||
if (!SoundEnabled() || soundId < 0 || !pActor) return;
|
||||
auto sid = soundEngine->FindSoundByResID(soundId);
|
||||
if (sid == 0) return;
|
||||
|
||||
auto svec = GetSoundPos(&pActor->spr.pos);
|
||||
auto svec = GetSoundPos(&pActor->spr.pos);
|
||||
|
||||
float attenuation;
|
||||
sid = getSfx(sid, attenuation, pitch, volume);
|
||||
if (volume == -1) volume = 80;
|
||||
float attenuation;
|
||||
sid = getSfx(sid, attenuation, pitch, volume);
|
||||
if (volume == -1) volume = 80;
|
||||
|
||||
if (playchannel >= 0)
|
||||
{
|
||||
playchannel++; // This is to make 0 a valid channel value.
|
||||
if (soundEngine->EnumerateChannels([=](FSoundChan* chan) -> int
|
||||
{
|
||||
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 ((playflags & FX_ChannelMatch) != 0 && chan->EntChannel == playchannel)
|
||||
return true;
|
||||
if ((playflags & FX_SoundMatch) != 0 && chan->OrgID == sid)
|
||||
return true;
|
||||
soundEngine->StopChannel(chan);
|
||||
return -1;
|
||||
}
|
||||
return false;
|
||||
})) return;
|
||||
if (playchannel >= 0)
|
||||
{
|
||||
playchannel++; // This is to make 0 a valid channel value.
|
||||
if (soundEngine->EnumerateChannels([=](FSoundChan* chan) -> int
|
||||
{
|
||||
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 ((playflags & FX_ChannelMatch) != 0 && chan->EntChannel == playchannel)
|
||||
return true;
|
||||
if ((playflags & FX_SoundMatch) != 0 && chan->OrgID == sid)
|
||||
return true;
|
||||
soundEngine->StopChannel(chan);
|
||||
return -1;
|
||||
}
|
||||
return false;
|
||||
})) return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
auto sfx = soundEngine->GetSfx(sid);
|
||||
EChanFlags flags = playchannel == -1 ? CHANF_OVERLAP : CHANF_NONE;
|
||||
if (sfx && sfx->LoopStart >= 0)
|
||||
{
|
||||
flags |= CHANF_LOOP;
|
||||
flags &= ~CHANF_OVERLAP;
|
||||
}
|
||||
auto sfx = soundEngine->GetSfx(sid);
|
||||
EChanFlags flags = playchannel == -1 ? CHANF_OVERLAP : CHANF_NONE;
|
||||
if (sfx && sfx->LoopStart >= 0)
|
||||
{
|
||||
flags |= CHANF_LOOP;
|
||||
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)
|
||||
{
|
||||
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++;
|
||||
auto sid = soundEngine->FindSoundByResID(a3);
|
||||
soundEngine->EnumerateChannels([=](FSoundChan* channel)
|
||||
{
|
||||
if (channel->SourceType == SOURCE_Actor && channel->Source == pActor && (a2 < 0 || a2 == channel->EntChannel) && (a3 < 0 || sid == channel->OrgID))
|
||||
{
|
||||
soundEngine->StopChannel(channel);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
void sfxKill3DSound(DBloodActor* pActor, int a2, int a3)
|
||||
{
|
||||
if (!pActor)
|
||||
return;
|
||||
|
||||
if (a2 >= 0) a2++;
|
||||
auto sid = soundEngine->FindSoundByResID(a3);
|
||||
soundEngine->EnumerateChannels([=](FSoundChan* channel)
|
||||
{
|
||||
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)
|
||||
{
|
||||
soundEngine->EnumerateChannels([](FSoundChan* channel)
|
||||
{
|
||||
if (channel->SourceType == SOURCE_Actor || channel->SourceType == SOURCE_Unattached) soundEngine->StopChannel(channel);
|
||||
return false;
|
||||
});
|
||||
soundEngine->EnumerateChannels([](FSoundChan* channel)
|
||||
{
|
||||
if (channel->SourceType == SOURCE_Actor || channel->SourceType == SOURCE_Unattached) soundEngine->StopChannel(channel);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void sfxSetReverb(bool toggle)
|
||||
{
|
||||
if (toggle)
|
||||
{
|
||||
FX_SetReverb(128);
|
||||
FX_SetReverbDelay(10);
|
||||
}
|
||||
else
|
||||
FX_SetReverb(0);
|
||||
if (toggle)
|
||||
{
|
||||
FX_SetReverb(128);
|
||||
FX_SetReverbDelay(10);
|
||||
}
|
||||
else
|
||||
FX_SetReverb(0);
|
||||
}
|
||||
|
||||
void sfxSetReverb2(bool toggle)
|
||||
{
|
||||
if (toggle)
|
||||
{
|
||||
FX_SetReverb(128);
|
||||
FX_SetReverbDelay(20);
|
||||
}
|
||||
else
|
||||
FX_SetReverb(0);
|
||||
if (toggle)
|
||||
{
|
||||
FX_SetReverb(128);
|
||||
FX_SetReverbDelay(20);
|
||||
}
|
||||
else
|
||||
FX_SetReverb(0);
|
||||
}
|
||||
|
||||
END_BLD_NS
|
||||
|
|
|
@ -31,30 +31,30 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
BEGIN_BLD_NS
|
||||
|
||||
int soundRates[13] = {
|
||||
11025,
|
||||
11025,
|
||||
11025,
|
||||
11025,
|
||||
11025,
|
||||
22050,
|
||||
22050,
|
||||
22050,
|
||||
22050,
|
||||
44100,
|
||||
44100,
|
||||
44100,
|
||||
44100,
|
||||
11025,
|
||||
11025,
|
||||
11025,
|
||||
11025,
|
||||
11025,
|
||||
22050,
|
||||
22050,
|
||||
22050,
|
||||
22050,
|
||||
44100,
|
||||
44100,
|
||||
44100,
|
||||
44100,
|
||||
};
|
||||
|
||||
|
||||
void ByteSwapSFX(SFX* pSFX)
|
||||
{
|
||||
#if WORDS_BIGENDIAN
|
||||
pSFX->relVol = LittleLong(pSFX->relVol);
|
||||
pSFX->pitch = LittleLong(pSFX->pitch);
|
||||
pSFX->pitchRange = LittleLong(pSFX->pitchRange);
|
||||
pSFX->format = LittleLong(pSFX->format);
|
||||
pSFX->loopStart = LittleLong(pSFX->loopStart);
|
||||
pSFX->relVol = LittleLong(pSFX->relVol);
|
||||
pSFX->pitch = LittleLong(pSFX->pitch);
|
||||
pSFX->pitchRange = LittleLong(pSFX->pitchRange);
|
||||
pSFX->format = LittleLong(pSFX->format);
|
||||
pSFX->loopStart = LittleLong(pSFX->loopStart);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -69,137 +69,156 @@ void ByteSwapSFX(SFX* pSFX)
|
|||
|
||||
static void S_AddBloodSFX(int lumpnum)
|
||||
{
|
||||
auto sfxlump = fileSystem.ReadFile(lumpnum);
|
||||
SFX* sfx = (SFX*)sfxlump.GetMem();
|
||||
ByteSwapSFX(sfx);
|
||||
FStringf rawname("%s.raw", sfx->rawName);
|
||||
auto rawlump = fileSystem.FindFile(rawname);
|
||||
int sfxnum;
|
||||
auto sfxlump = fileSystem.ReadFile(lumpnum);
|
||||
SFX* sfx = (SFX*)sfxlump.GetMem();
|
||||
ByteSwapSFX(sfx);
|
||||
FStringf rawname("%s.raw", sfx->rawName);
|
||||
auto rawlump = fileSystem.FindFile(rawname);
|
||||
int sfxnum;
|
||||
|
||||
if (rawlump != -1)
|
||||
{
|
||||
auto& S_sfx = soundEngine->GetSounds();
|
||||
sfxnum = soundEngine->AddSoundLump(sfx->rawName, rawlump, 0, fileSystem.GetResourceId(lumpnum), 6);
|
||||
if (sfx->format < 5 || sfx->format > 12)
|
||||
{ // [0..4] + invalid formats
|
||||
S_sfx[sfxnum].RawRate = 11025;
|
||||
}
|
||||
else if (sfx->format < 9)
|
||||
{ // [5..8]
|
||||
S_sfx[sfxnum].RawRate = 22050;
|
||||
}
|
||||
else
|
||||
{ // [9..12]
|
||||
S_sfx[sfxnum].RawRate = 44100;
|
||||
}
|
||||
S_sfx[sfxnum].bLoadRAW = true;
|
||||
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].UserData.Resize(3);
|
||||
int* udata = (int*)S_sfx[sfxnum].UserData.Data();
|
||||
udata[0] = sfx->pitch;
|
||||
udata[1] = sfx->pitchRange;
|
||||
udata[2] = sfx->relVol;
|
||||
}
|
||||
if (rawlump != -1)
|
||||
{
|
||||
auto& S_sfx = soundEngine->GetSounds();
|
||||
sfxnum = soundEngine->AddSoundLump(sfx->rawName, rawlump, 0, fileSystem.GetResourceId(lumpnum), 6);
|
||||
if (sfx->format < 5 || sfx->format > 12)
|
||||
{ // [0..4] + invalid formats
|
||||
S_sfx[sfxnum].RawRate = 11025;
|
||||
}
|
||||
else if (sfx->format < 9)
|
||||
{ // [5..8]
|
||||
S_sfx[sfxnum].RawRate = 22050;
|
||||
}
|
||||
else
|
||||
{ // [9..12]
|
||||
S_sfx[sfxnum].RawRate = 44100;
|
||||
}
|
||||
S_sfx[sfxnum].bLoadRAW = true;
|
||||
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].UserData.Resize(3);
|
||||
int* udata = (int*)S_sfx[sfxnum].UserData.Data();
|
||||
udata[0] = sfx->pitch;
|
||||
udata[1] = sfx->pitchRange;
|
||||
udata[2] = sfx->relVol;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void sndInit(void)
|
||||
{
|
||||
soundEngine = new BloodSoundEngine;
|
||||
soundEngine->AddSoundLump("", 0, 0, -1, 6); // add a dummy entry at index #0
|
||||
for (int i = fileSystem.GetNumEntries() - 1; i >= 0; i--)
|
||||
{
|
||||
auto type = fileSystem.GetResourceType(i);
|
||||
if (!stricmp(type, "SFX"))
|
||||
{
|
||||
if (soundEngine->FindSoundByResID(fileSystem.GetResourceId(i)) == 0)
|
||||
S_AddBloodSFX(i);
|
||||
}
|
||||
else if (!stricmp(type, "WAV") || !stricmp(type, "OGG") || !stricmp(type, "FLAC") || !stricmp(type, "VOC"))
|
||||
{
|
||||
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->HashSounds();
|
||||
soundEngine = new BloodSoundEngine;
|
||||
soundEngine->AddSoundLump("", 0, 0, -1, 6); // add a dummy entry at index #0
|
||||
for (int i = fileSystem.GetNumEntries() - 1; i >= 0; i--)
|
||||
{
|
||||
auto type = fileSystem.GetResourceType(i);
|
||||
if (!stricmp(type, "SFX"))
|
||||
{
|
||||
if (soundEngine->FindSoundByResID(fileSystem.GetResourceId(i)) == 0)
|
||||
S_AddBloodSFX(i);
|
||||
}
|
||||
else if (!stricmp(type, "WAV") || !stricmp(type, "OGG") || !stricmp(type, "FLAC") || !stricmp(type, "VOC"))
|
||||
{
|
||||
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->HashSounds();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
int sndGetRate(int format)
|
||||
{
|
||||
if (format < 13)
|
||||
return soundRates[format];
|
||||
return 11025;
|
||||
if (format < 13)
|
||||
return soundRates[format];
|
||||
return 11025;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool sndCheckPlaying(unsigned int nSound)
|
||||
{
|
||||
auto snd = soundEngine->FindSoundByResID(nSound);
|
||||
return snd > 0 ? soundEngine->GetSoundPlayingInfo(SOURCE_Any, nullptr, snd) : false;
|
||||
auto snd = soundEngine->FindSoundByResID(nSound);
|
||||
return snd > 0 ? soundEngine->GetSoundPlayingInfo(SOURCE_Any, nullptr, snd) : false;
|
||||
}
|
||||
|
||||
void sndStopSample(unsigned int nSound)
|
||||
{
|
||||
auto snd = soundEngine->FindSoundByResID(nSound);
|
||||
auto snd = soundEngine->FindSoundByResID(nSound);
|
||||
|
||||
if (snd > 0)
|
||||
{
|
||||
soundEngine->StopSoundID(snd);
|
||||
}
|
||||
if (snd > 0)
|
||||
{
|
||||
soundEngine->StopSoundID(snd);
|
||||
}
|
||||
}
|
||||
|
||||
void sndStartSample(const char *pzSound, int nVolume, int nChannel)
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void sndStartSample(const char* pzSound, int nVolume, int nChannel)
|
||||
{
|
||||
if (!SoundEnabled())
|
||||
return;
|
||||
if (!strlen(pzSound))
|
||||
return;
|
||||
auto snd = soundEngine->FindSound(pzSound);
|
||||
if (snd > 0)
|
||||
{
|
||||
soundEngine->StartSound(SOURCE_None, nullptr, nullptr, nChannel + 1, 0, snd, nVolume / 255.f, ATTN_NONE);
|
||||
}
|
||||
if (!SoundEnabled())
|
||||
return;
|
||||
if (!strlen(pzSound))
|
||||
return;
|
||||
auto snd = soundEngine->FindSound(pzSound);
|
||||
if (snd > 0)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (!SoundEnabled())
|
||||
return;
|
||||
if (nChannel >= 7) nChannel = -1;
|
||||
auto snd = soundEngine->FindSoundByResID(nSound);
|
||||
if (snd > 0)
|
||||
{
|
||||
if (nVolume < 0)
|
||||
{
|
||||
auto udata = soundEngine->GetUserData(snd);
|
||||
if (udata) nVolume = min(Scale(udata[2], 255, 100), 255);
|
||||
else nVolume = 255;
|
||||
}
|
||||
if (bLoop) chanflags |= CHANF_LOOP;
|
||||
soundEngine->StopActorSounds(SOURCE_None, nullptr, nChannel + 1, nChannel + 1);
|
||||
soundEngine->StartSound(SOURCE_None, nullptr, nullptr, (nChannel + 1), chanflags, snd, nVolume / 255.f, ATTN_NONE);
|
||||
}
|
||||
if (!SoundEnabled())
|
||||
return;
|
||||
if (nChannel >= 7) nChannel = -1;
|
||||
auto snd = soundEngine->FindSoundByResID(nSound);
|
||||
if (snd > 0)
|
||||
{
|
||||
if (nVolume < 0)
|
||||
{
|
||||
auto udata = soundEngine->GetUserData(snd);
|
||||
if (udata) nVolume = min(Scale(udata[2], 255, 100), 255);
|
||||
else nVolume = 255;
|
||||
}
|
||||
if (bLoop) chanflags |= CHANF_LOOP;
|
||||
soundEngine->StopActorSounds(SOURCE_None, nullptr, nChannel + 1, nChannel + 1);
|
||||
soundEngine->StartSound(SOURCE_None, nullptr, nullptr, (nChannel + 1), chanflags, snd, nVolume / 255.f, ATTN_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
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;
|
||||
FixPathSeperator(name);
|
||||
return sndStartSample(name, nVolume, nChannel);
|
||||
FString name = pzFile;
|
||||
FixPathSeperator(name);
|
||||
return sndStartSample(name, nVolume, nChannel);
|
||||
}
|
||||
|
||||
void sndKillAllSounds(void)
|
||||
{
|
||||
soundEngine->StopSound(CHAN_AUTO);
|
||||
soundEngine->StopSound(CHAN_AUTO);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -30,30 +30,30 @@ BEGIN_BLD_NS
|
|||
|
||||
struct SFX
|
||||
{
|
||||
int relVol;
|
||||
int pitch;
|
||||
int pitchRange;
|
||||
int format;
|
||||
int loopStart;
|
||||
char rawName[9];
|
||||
int relVol;
|
||||
int pitch;
|
||||
int pitchRange;
|
||||
int format;
|
||||
int loopStart;
|
||||
char rawName[9];
|
||||
};
|
||||
|
||||
int sndGetRate(int format);
|
||||
bool sndCheckPlaying(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 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 sndProcess(void);
|
||||
void sndTerm(void);
|
||||
void sndInit(void);
|
||||
|
||||
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 sfxKill3DSound(DBloodActor *pSprite, int a2 = -1, int a3 = -1);
|
||||
void sfxKill3DSound(DBloodActor* pSprite, int a2 = -1, int a3 = -1);
|
||||
void sfxKillAllSounds(void);
|
||||
void sfxSetReverb(bool toggle);
|
||||
void sfxSetReverb2(bool toggle);
|
||||
|
@ -64,9 +64,9 @@ void ambInit(void);
|
|||
|
||||
enum EPlayFlags
|
||||
{
|
||||
FX_GlobalChannel = 1,
|
||||
FX_SoundMatch = 2,
|
||||
FX_ChannelMatch = 4,
|
||||
FX_GlobalChannel = 1,
|
||||
FX_SoundMatch = 2,
|
||||
FX_ChannelMatch = 4,
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -42,6 +42,12 @@ uint8_t surfType[kMaxTiles];
|
|||
int8_t tileShade[kMaxTiles];
|
||||
short voxelIndex[kMaxTiles];
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void GameInterface::LoadGameTextures()
|
||||
{
|
||||
auto hFile = fileSystem.OpenFileReader("SURFACE.DAT");
|
||||
|
@ -70,6 +76,12 @@ void GameInterface::LoadGameTextures()
|
|||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
int tileGetSurfType(int hit)
|
||||
{
|
||||
return surfType[hit];
|
||||
|
@ -90,6 +102,12 @@ int tileGetSurfType(CollisionBase& hit)
|
|||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void GameInterface::SetTileProps(int tile, int surf, int vox, int shade)
|
||||
{
|
||||
if (surf != INT_MAX) surfType[tile] = surf;
|
||||
|
|
|
@ -31,24 +31,24 @@ int OctantTable[8] = { 5, 6, 2, 1, 4, 7, 3, 0 };
|
|||
|
||||
int GetOctant(int x, int y)
|
||||
{
|
||||
int vc = abs(x)-abs(y);
|
||||
return OctantTable[7-(x<0)-(y<0)*2-(vc<0)*4];
|
||||
int vc = abs(x) - abs(y);
|
||||
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 oy = *dy;
|
||||
*dx = dmulscale30r(ox, Cos(nAngle), -oy, Sin(nAngle));
|
||||
*dy = dmulscale30r(ox, Sin(nAngle), oy, Cos(nAngle));
|
||||
int ox = *dx;
|
||||
int oy = *dy;
|
||||
*dx = dmulscale30r(ox, Cos(nAngle), -oy, Sin(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 dy = *y-oy;
|
||||
*x = ox+dmulscale30r(dx, Cos(nAngle), -dy, Sin(nAngle));
|
||||
*y = oy+dmulscale30r(dx, Sin(nAngle), dy, Cos(nAngle));
|
||||
int dx = *x - ox;
|
||||
int dy = *y - oy;
|
||||
*x = ox + dmulscale30r(dx, Cos(nAngle), -dy, Sin(nAngle));
|
||||
*y = oy + dmulscale30r(dx, Sin(nAngle), dy, Cos(nAngle));
|
||||
}
|
||||
|
||||
END_BLD_NS
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -32,26 +32,26 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
BEGIN_BLD_NS
|
||||
|
||||
enum BUSYID {
|
||||
BUSYID_0 = 0,
|
||||
BUSYID_1,
|
||||
BUSYID_2,
|
||||
BUSYID_3,
|
||||
BUSYID_4,
|
||||
BUSYID_5,
|
||||
BUSYID_6,
|
||||
BUSYID_7,
|
||||
BUSYID_0 = 0,
|
||||
BUSYID_1,
|
||||
BUSYID_2,
|
||||
BUSYID_3,
|
||||
BUSYID_4,
|
||||
BUSYID_5,
|
||||
BUSYID_6,
|
||||
BUSYID_7,
|
||||
};
|
||||
|
||||
struct BUSY {
|
||||
sectortype* sect;
|
||||
int delta;
|
||||
int busy;
|
||||
int/*BUSYID*/ type;
|
||||
sectortype* sect;
|
||||
int delta;
|
||||
int busy;
|
||||
int/*BUSYID*/ type;
|
||||
};
|
||||
|
||||
extern TArray<BUSY> gBusy;
|
||||
|
||||
void trTriggerSector(sectortype *pSector, int command);
|
||||
void trTriggerSector(sectortype* pSector, int command);
|
||||
void trMessageSector(sectortype* pSector, EVENT event);
|
||||
void trTriggerWall(walltype*, int command);
|
||||
void trMessageWall(walltype* pWall, EVENT& event);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -32,46 +32,46 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
BEGIN_BLD_NS
|
||||
|
||||
struct VIEW {
|
||||
int bobPhase;
|
||||
int Kills;
|
||||
int bobHeight; // bob height
|
||||
int bobWidth; // bob width
|
||||
int at10;
|
||||
int at14;
|
||||
int shakeBobY; // bob sway y
|
||||
int shakeBobX; // bob sway x
|
||||
fixedhoriz horiz; // horiz
|
||||
fixedhoriz horizoff; // horizoff
|
||||
int at2c;
|
||||
binangle angle; // angle
|
||||
int weaponZ; // weapon z
|
||||
int viewz; // view z
|
||||
int at3c;
|
||||
int at40;
|
||||
int at44;
|
||||
int at48; // posture
|
||||
double spin; // spin
|
||||
union {
|
||||
struct
|
||||
{
|
||||
int32_t x, y, z;
|
||||
};
|
||||
vec3_t pos;
|
||||
};
|
||||
int xvel; //xvel
|
||||
int yvel; //yvel
|
||||
int zvel; //zvel
|
||||
int sectnum; // sectnum
|
||||
unsigned int floordist; // floordist
|
||||
uint8_t at6e; // look center
|
||||
uint8_t at6f;
|
||||
uint8_t at70; // run
|
||||
uint8_t at71; // jump
|
||||
uint8_t at72; // underwater
|
||||
int16_t at73; // sprite flags
|
||||
SPRITEHIT at75;
|
||||
binangle look_ang;
|
||||
binangle rotscrnang;
|
||||
int bobPhase;
|
||||
int Kills;
|
||||
int bobHeight; // bob height
|
||||
int bobWidth; // bob width
|
||||
int at10;
|
||||
int at14;
|
||||
int shakeBobY; // bob sway y
|
||||
int shakeBobX; // bob sway x
|
||||
fixedhoriz horiz; // horiz
|
||||
fixedhoriz horizoff; // horizoff
|
||||
int at2c;
|
||||
binangle angle; // angle
|
||||
int weaponZ; // weapon z
|
||||
int viewz; // view z
|
||||
int at3c;
|
||||
int at40;
|
||||
int at44;
|
||||
int at48; // posture
|
||||
double spin; // spin
|
||||
union {
|
||||
struct
|
||||
{
|
||||
int32_t x, y, z;
|
||||
};
|
||||
vec3_t pos;
|
||||
};
|
||||
int xvel; //xvel
|
||||
int yvel; //yvel
|
||||
int zvel; //zvel
|
||||
int sectnum; // sectnum
|
||||
unsigned int floordist; // floordist
|
||||
uint8_t at6e; // look center
|
||||
uint8_t at6f;
|
||||
uint8_t at70; // run
|
||||
uint8_t at71; // jump
|
||||
uint8_t at72; // underwater
|
||||
int16_t at73; // sprite flags
|
||||
SPRITEHIT at75;
|
||||
binangle look_ang;
|
||||
binangle rotscrnang;
|
||||
};
|
||||
|
||||
extern VIEW gPrevView[kMaxPlayers];
|
||||
|
@ -80,55 +80,55 @@ extern VIEW predict, predictOld;
|
|||
extern bool gPrediction;
|
||||
|
||||
enum VIEW_EFFECT {
|
||||
kViewEffectShadow = 0,
|
||||
kViewEffectFlareHalo,
|
||||
kViewEffectCeilGlow,
|
||||
kViewEffectFloorGlow,
|
||||
kViewEffectTorchHigh,
|
||||
kViewEffectTorchLow,
|
||||
kViewEffectSmokeHigh,
|
||||
kViewEffectSmokeLow,
|
||||
kViewEffectFlame,
|
||||
kViewEffectSpear,
|
||||
kViewEffectTrail,
|
||||
kViewEffectPhase,
|
||||
kViewEffectShowWeapon,
|
||||
kViewEffectReflectiveBall,
|
||||
kViewEffectShoot,
|
||||
kViewEffectTesla,
|
||||
kViewEffectFlag,
|
||||
kViewEffectBigFlag,
|
||||
kViewEffectAtom,
|
||||
kViewEffectSpotProgress,
|
||||
kViewEffectShadow = 0,
|
||||
kViewEffectFlareHalo,
|
||||
kViewEffectCeilGlow,
|
||||
kViewEffectFloorGlow,
|
||||
kViewEffectTorchHigh,
|
||||
kViewEffectTorchLow,
|
||||
kViewEffectSmokeHigh,
|
||||
kViewEffectSmokeLow,
|
||||
kViewEffectFlame,
|
||||
kViewEffectSpear,
|
||||
kViewEffectTrail,
|
||||
kViewEffectPhase,
|
||||
kViewEffectShowWeapon,
|
||||
kViewEffectReflectiveBall,
|
||||
kViewEffectShoot,
|
||||
kViewEffectTesla,
|
||||
kViewEffectFlag,
|
||||
kViewEffectBigFlag,
|
||||
kViewEffectAtom,
|
||||
kViewEffectSpotProgress,
|
||||
};
|
||||
|
||||
enum VIEWPOS {
|
||||
VIEWPOS_0 = 0,
|
||||
VIEWPOS_1
|
||||
VIEWPOS_0 = 0,
|
||||
VIEWPOS_1
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kBackTile = 253,
|
||||
kBackTile = 253,
|
||||
|
||||
kCrosshairTile = 2319,
|
||||
kLoadScreen = 2049,
|
||||
kLoadScreenWideBack = 9216,
|
||||
kLoadScreenWideLeft = 9217,
|
||||
kLoadScreenWideRight = 9218,
|
||||
kLoadScreenWideMiddle = 9219,
|
||||
kCrosshairTile = 2319,
|
||||
kLoadScreen = 2049,
|
||||
kLoadScreenWideBack = 9216,
|
||||
kLoadScreenWideLeft = 9217,
|
||||
kLoadScreenWideRight = 9218,
|
||||
kLoadScreenWideMiddle = 9219,
|
||||
|
||||
kSBarNumberHealth = 9220,
|
||||
kSBarNumberAmmo = 9230,
|
||||
kSBarNumberInv = 9240,
|
||||
kSBarNumberArmor1 = 9250,
|
||||
kSBarNumberArmor2 = 9260,
|
||||
kSBarNumberArmor3 = 9270,
|
||||
kSBarNumberHealth = 9220,
|
||||
kSBarNumberAmmo = 9230,
|
||||
kSBarNumberInv = 9240,
|
||||
kSBarNumberArmor1 = 9250,
|
||||
kSBarNumberArmor2 = 9260,
|
||||
kSBarNumberArmor3 = 9270,
|
||||
};
|
||||
|
||||
enum { kFontNum = 5 };
|
||||
|
||||
extern FFont *gFont[kFontNum];
|
||||
extern FFont* gFont[kFontNum];
|
||||
extern VIEWPOS gViewPos;
|
||||
extern int gViewIndex;
|
||||
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 viewInitializePrediction(void);
|
||||
void viewUpdatePrediction(InputPacket *pInput);
|
||||
void viewUpdatePrediction(InputPacket* pInput);
|
||||
void viewCorrectPrediction(void);
|
||||
void viewBackupView(int nPlayer);
|
||||
void viewCorrectViewOffsets(int nPlayer, vec3_t const *oldpos);
|
||||
void viewCorrectViewOffsets(int nPlayer, vec3_t const* oldpos);
|
||||
void InitStatusBar(void);
|
||||
void UpdateStatusBar();
|
||||
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 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 UpdateDacs(int nPalette, bool bNoTint = false);
|
||||
void viewDrawScreen(bool sceneonly = false);
|
||||
void viewUpdateDelirium(void);
|
||||
void viewSetSystemMessage(const char* pMessage, ...);
|
||||
|
||||
inline void viewInterpolateSector(sectortype *pSector)
|
||||
inline void viewInterpolateSector(sectortype* pSector)
|
||||
{
|
||||
StartInterpolation(pSector, Interp_Sect_Floorz);
|
||||
StartInterpolation(pSector, Interp_Sect_Ceilingz);
|
||||
StartInterpolation(pSector, Interp_Sect_Floorheinum);
|
||||
StartInterpolation(pSector, Interp_Sect_Floorz);
|
||||
StartInterpolation(pSector, Interp_Sect_Ceilingz);
|
||||
StartInterpolation(pSector, Interp_Sect_Floorheinum);
|
||||
}
|
||||
|
||||
inline void viewInterpolateWall(walltype *pWall)
|
||||
inline void viewInterpolateWall(walltype* pWall)
|
||||
{
|
||||
StartInterpolation(pWall, Interp_Wall_X);
|
||||
StartInterpolation(pWall, Interp_Wall_Y);
|
||||
StartInterpolation(pWall, Interp_Wall_X);
|
||||
StartInterpolation(pWall, Interp_Wall_Y);
|
||||
}
|
||||
|
||||
inline void viewBackupSpriteLoc(DBloodActor* actor)
|
||||
{
|
||||
if (!actor->interpolated)
|
||||
{
|
||||
actor->spr.backuploc();
|
||||
actor->interpolated = true;
|
||||
}
|
||||
if (!actor->interpolated)
|
||||
{
|
||||
actor->spr.backuploc();
|
||||
actor->interpolated = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -30,268 +30,293 @@ BEGIN_BLD_NS
|
|||
|
||||
ZONE gStartZone[8];
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
ZONE gStartZoneTeam1[8];
|
||||
ZONE gStartZoneTeam2[8];
|
||||
bool gTeamsSpawnUsed = false;
|
||||
ZONE gStartZoneTeam1[8];
|
||||
ZONE gStartZoneTeam2[8];
|
||||
bool gTeamsSpawnUsed = false;
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void validateLinks()
|
||||
{
|
||||
int snum = 0;
|
||||
for (auto& sect: sector)
|
||||
{
|
||||
DCoreActor* upper = sect.upperLink;
|
||||
if (upper && !static_cast<DBloodActor*>(upper)->GetOwner())
|
||||
{
|
||||
Printf(PRINT_HIGH, "Unpartnered upper link in sector %d\n", snum);
|
||||
sect.upperLink = nullptr;
|
||||
}
|
||||
DCoreActor* lower = sect.lowerLink;
|
||||
if (lower && !static_cast<DBloodActor*>(lower)->GetOwner())
|
||||
{
|
||||
Printf(PRINT_HIGH, "Unpartnered lower link in sector %d\n", snum);
|
||||
sect.lowerLink = nullptr;
|
||||
}
|
||||
snum++;
|
||||
}
|
||||
int snum = 0;
|
||||
for (auto& sect : sector)
|
||||
{
|
||||
DCoreActor* upper = sect.upperLink;
|
||||
if (upper && !static_cast<DBloodActor*>(upper)->GetOwner())
|
||||
{
|
||||
Printf(PRINT_HIGH, "Unpartnered upper link in sector %d\n", snum);
|
||||
sect.upperLink = nullptr;
|
||||
}
|
||||
DCoreActor* lower = sect.lowerLink;
|
||||
if (lower && !static_cast<DBloodActor*>(lower)->GetOwner())
|
||||
{
|
||||
Printf(PRINT_HIGH, "Unpartnered lower link in sector %d\n", snum);
|
||||
sect.lowerLink = nullptr;
|
||||
}
|
||||
snum++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void warpInit(TArray<DBloodActor*>& actors)
|
||||
{
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
int team1 = 0; int team2 = 0; gTeamsSpawnUsed = false; // increment if team start positions specified.
|
||||
#endif
|
||||
#ifdef NOONE_EXTENSIONS
|
||||
int team1 = 0; int team2 = 0; gTeamsSpawnUsed = false; // increment if team start positions specified.
|
||||
#endif
|
||||
|
||||
for(auto actor : actors)
|
||||
{
|
||||
if (!actor->exists()) continue;
|
||||
if (actor->hasX()) {
|
||||
switch (actor->spr.type) {
|
||||
case kMarkerSPStart:
|
||||
if (gGameOptions.nGameType < 2 && actor->xspr.data1 >= 0 && actor->xspr.data1 < kMaxPlayers) {
|
||||
ZONE *pZone = &gStartZone[actor->xspr.data1];
|
||||
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;
|
||||
}
|
||||
DeleteSprite(actor);
|
||||
break;
|
||||
case kMarkerMPStart:
|
||||
if (actor->xspr.data1 >= 0 && actor->xspr.data2 < kMaxPlayers) {
|
||||
if (gGameOptions.nGameType >= 2) {
|
||||
// default if BB or teams without data2 specified
|
||||
ZONE* pZone = &gStartZone[actor->xspr.data1];
|
||||
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;
|
||||
|
||||
#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++;
|
||||
for (auto actor : actors)
|
||||
{
|
||||
if (!actor->exists()) continue;
|
||||
if (actor->hasX()) {
|
||||
switch (actor->spr.type) {
|
||||
case kMarkerSPStart:
|
||||
if (gGameOptions.nGameType < 2 && actor->xspr.data1 >= 0 && actor->xspr.data1 < kMaxPlayers) {
|
||||
ZONE* pZone = &gStartZone[actor->xspr.data1];
|
||||
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;
|
||||
}
|
||||
DeleteSprite(actor);
|
||||
break;
|
||||
case kMarkerMPStart:
|
||||
if (actor->xspr.data1 >= 0 && actor->xspr.data2 < kMaxPlayers) {
|
||||
if (gGameOptions.nGameType >= 2) {
|
||||
// default if BB or teams without data2 specified
|
||||
ZONE* pZone = &gStartZone[actor->xspr.data1];
|
||||
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;
|
||||
|
||||
} else if (actor->xspr.data2 == 2) {
|
||||
pZone = &gStartZoneTeam2[team2];
|
||||
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;
|
||||
team2++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#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++;
|
||||
|
||||
}
|
||||
DeleteSprite(actor);
|
||||
}
|
||||
break;
|
||||
case kMarkerUpLink:
|
||||
actor->spr.sector()->upperLink = actor;
|
||||
actor->spr.cstat |= CSTAT_SPRITE_INVISIBLE;
|
||||
actor->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL;
|
||||
break;
|
||||
case kMarkerLowLink:
|
||||
actor->spr.sector()->lowerLink = actor;
|
||||
actor->spr.cstat |= CSTAT_SPRITE_INVISIBLE;
|
||||
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
|
||||
}
|
||||
else if (actor->xspr.data2 == 2) {
|
||||
pZone = &gStartZoneTeam2[team2];
|
||||
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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
DeleteSprite(actor);
|
||||
}
|
||||
break;
|
||||
case kMarkerUpLink:
|
||||
actor->spr.sector()->upperLink = actor;
|
||||
actor->spr.cstat |= CSTAT_SPRITE_INVISIBLE;
|
||||
actor->spr.cstat &= ~CSTAT_SPRITE_BLOCK_ALL;
|
||||
break;
|
||||
case kMarkerLowLink:
|
||||
actor->spr.sector()->lowerLink = actor;
|
||||
actor->spr.cstat |= CSTAT_SPRITE_INVISIBLE;
|
||||
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)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
int CheckLink(DBloodActor *actor)
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
int CheckLink(DBloodActor* actor)
|
||||
{
|
||||
auto pSector = actor->spr.sector();
|
||||
auto aUpper = barrier_cast<DBloodActor*>(pSector->upperLink);
|
||||
auto aLower = barrier_cast<DBloodActor*>(pSector->lowerLink);
|
||||
if (aUpper)
|
||||
{
|
||||
int z;
|
||||
if (aUpper->spr.type == kMarkerUpLink)
|
||||
z = aUpper->spr.pos.Z;
|
||||
else
|
||||
z = getflorzofslopeptr(actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y);
|
||||
if (z <= actor->spr.pos.Z)
|
||||
{
|
||||
aLower = aUpper->GetOwner();
|
||||
assert(aLower);
|
||||
assert(aLower->spr.insector());
|
||||
ChangeActorSect(actor, aLower->spr.sector());
|
||||
actor->spr.pos.X += aLower->spr.pos.X - aUpper->spr.pos.X;
|
||||
actor->spr.pos.Y += aLower->spr.pos.Y - aUpper->spr.pos.Y;
|
||||
int z2;
|
||||
if (aLower->spr.type == kMarkerLowLink)
|
||||
z2 = aLower->spr.pos.Z;
|
||||
else
|
||||
z2 = getceilzofslopeptr(actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y);
|
||||
actor->spr.pos.Z += z2-z;
|
||||
actor->interpolated = false;
|
||||
return aUpper->spr.type;
|
||||
}
|
||||
}
|
||||
if (aLower)
|
||||
{
|
||||
int z;
|
||||
if (aLower->spr.type == kMarkerLowLink)
|
||||
z = aLower->spr.pos.Z;
|
||||
else
|
||||
z = getceilzofslopeptr(actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y);
|
||||
if (z >= actor->spr.pos.Z)
|
||||
{
|
||||
aUpper = aLower->GetOwner();
|
||||
assert(aUpper);
|
||||
assert(aUpper->spr.insector());
|
||||
ChangeActorSect(actor, aUpper->spr.sector());
|
||||
actor->spr.pos.X += aUpper->spr.pos.X - aLower->spr.pos.X;
|
||||
actor->spr.pos.Y += aUpper->spr.pos.Y - aLower->spr.pos.Y;
|
||||
int z2;
|
||||
if (aUpper->spr.type == kMarkerUpLink)
|
||||
z2 = aUpper->spr.pos.Z;
|
||||
else
|
||||
z2 = getflorzofslopeptr(actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y);
|
||||
actor->spr.pos.Z += z2-z;
|
||||
actor->interpolated = false;
|
||||
return aLower->spr.type;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
auto pSector = actor->spr.sector();
|
||||
auto aUpper = barrier_cast<DBloodActor*>(pSector->upperLink);
|
||||
auto aLower = barrier_cast<DBloodActor*>(pSector->lowerLink);
|
||||
if (aUpper)
|
||||
{
|
||||
int z;
|
||||
if (aUpper->spr.type == kMarkerUpLink)
|
||||
z = aUpper->spr.pos.Z;
|
||||
else
|
||||
z = getflorzofslopeptr(actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y);
|
||||
if (z <= actor->spr.pos.Z)
|
||||
{
|
||||
aLower = aUpper->GetOwner();
|
||||
assert(aLower);
|
||||
assert(aLower->spr.insector());
|
||||
ChangeActorSect(actor, aLower->spr.sector());
|
||||
actor->spr.pos.X += aLower->spr.pos.X - aUpper->spr.pos.X;
|
||||
actor->spr.pos.Y += aLower->spr.pos.Y - aUpper->spr.pos.Y;
|
||||
int z2;
|
||||
if (aLower->spr.type == kMarkerLowLink)
|
||||
z2 = aLower->spr.pos.Z;
|
||||
else
|
||||
z2 = getceilzofslopeptr(actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y);
|
||||
actor->spr.pos.Z += z2 - z;
|
||||
actor->interpolated = false;
|
||||
return aUpper->spr.type;
|
||||
}
|
||||
}
|
||||
if (aLower)
|
||||
{
|
||||
int z;
|
||||
if (aLower->spr.type == kMarkerLowLink)
|
||||
z = aLower->spr.pos.Z;
|
||||
else
|
||||
z = getceilzofslopeptr(actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y);
|
||||
if (z >= actor->spr.pos.Z)
|
||||
{
|
||||
aUpper = aLower->GetOwner();
|
||||
assert(aUpper);
|
||||
assert(aUpper->spr.insector());
|
||||
ChangeActorSect(actor, aUpper->spr.sector());
|
||||
actor->spr.pos.X += aUpper->spr.pos.X - aLower->spr.pos.X;
|
||||
actor->spr.pos.Y += aUpper->spr.pos.Y - aLower->spr.pos.Y;
|
||||
int z2;
|
||||
if (aUpper->spr.type == kMarkerUpLink)
|
||||
z2 = aUpper->spr.pos.Z;
|
||||
else
|
||||
z2 = getflorzofslopeptr(actor->spr.sector(), actor->spr.pos.X, actor->spr.pos.Y);
|
||||
actor->spr.pos.Z += z2 - z;
|
||||
actor->interpolated = false;
|
||||
return aLower->spr.type;
|
||||
}
|
||||
}
|
||||
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 aLower = barrier_cast<DBloodActor*>((*pSector)->lowerLink);
|
||||
if (aUpper)
|
||||
{
|
||||
int z1;
|
||||
if (aUpper->spr.type == kMarkerUpLink)
|
||||
z1 = aUpper->spr.pos.Z;
|
||||
else
|
||||
z1 = getflorzofslopeptr(*pSector, *x, *y);
|
||||
if (z1 <= *z)
|
||||
{
|
||||
aLower = aUpper->GetOwner();
|
||||
assert(aLower);
|
||||
assert(aLower->spr.insector());
|
||||
*pSector = aLower->spr.sector();
|
||||
*x += aLower->spr.pos.X - aUpper->spr.pos.X;
|
||||
*y += aLower->spr.pos.Y - aUpper->spr.pos.Y;
|
||||
int z2;
|
||||
if (aUpper->spr.type == kMarkerLowLink)
|
||||
z2 = aLower->spr.pos.Z;
|
||||
else
|
||||
z2 = getceilzofslopeptr(*pSector, *x, *y);
|
||||
*z += z2-z1;
|
||||
return aUpper->spr.type;
|
||||
}
|
||||
}
|
||||
if (aLower)
|
||||
{
|
||||
int z1;
|
||||
if (aLower->spr.type == kMarkerLowLink)
|
||||
z1 = aLower->spr.pos.Z;
|
||||
else
|
||||
z1 = getceilzofslopeptr(*pSector, *x, *y);
|
||||
if (z1 >= *z)
|
||||
{
|
||||
aUpper = aLower->GetOwner();
|
||||
assert(aUpper);
|
||||
*pSector = aUpper->spr.sector();
|
||||
*x += aUpper->spr.pos.X - aLower->spr.pos.X;
|
||||
*y += aUpper->spr.pos.Y - aLower->spr.pos.Y;
|
||||
int z2;
|
||||
if (aLower->spr.type == kMarkerUpLink)
|
||||
z2 = aUpper->spr.pos.Z;
|
||||
else
|
||||
z2 = getflorzofslopeptr(*pSector, *x, *y);
|
||||
*z += z2-z1;
|
||||
return aLower->spr.type;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
auto aUpper = barrier_cast<DBloodActor*>((*pSector)->upperLink);
|
||||
auto aLower = barrier_cast<DBloodActor*>((*pSector)->lowerLink);
|
||||
if (aUpper)
|
||||
{
|
||||
int z1;
|
||||
if (aUpper->spr.type == kMarkerUpLink)
|
||||
z1 = aUpper->spr.pos.Z;
|
||||
else
|
||||
z1 = getflorzofslopeptr(*pSector, *x, *y);
|
||||
if (z1 <= *z)
|
||||
{
|
||||
aLower = aUpper->GetOwner();
|
||||
assert(aLower);
|
||||
assert(aLower->spr.insector());
|
||||
*pSector = aLower->spr.sector();
|
||||
*x += aLower->spr.pos.X - aUpper->spr.pos.X;
|
||||
*y += aLower->spr.pos.Y - aUpper->spr.pos.Y;
|
||||
int z2;
|
||||
if (aUpper->spr.type == kMarkerLowLink)
|
||||
z2 = aLower->spr.pos.Z;
|
||||
else
|
||||
z2 = getceilzofslopeptr(*pSector, *x, *y);
|
||||
*z += z2 - z1;
|
||||
return aUpper->spr.type;
|
||||
}
|
||||
}
|
||||
if (aLower)
|
||||
{
|
||||
int z1;
|
||||
if (aLower->spr.type == kMarkerLowLink)
|
||||
z1 = aLower->spr.pos.Z;
|
||||
else
|
||||
z1 = getceilzofslopeptr(*pSector, *x, *y);
|
||||
if (z1 >= *z)
|
||||
{
|
||||
aUpper = aLower->GetOwner();
|
||||
assert(aUpper);
|
||||
*pSector = aUpper->spr.sector();
|
||||
*x += aUpper->spr.pos.X - aLower->spr.pos.X;
|
||||
*y += aUpper->spr.pos.Y - aLower->spr.pos.Y;
|
||||
int z2;
|
||||
if (aLower->spr.type == kMarkerUpLink)
|
||||
z2 = aUpper->spr.pos.Z;
|
||||
else
|
||||
z2 = getflorzofslopeptr(*pSector, *x, *y);
|
||||
*z += z2 - z1;
|
||||
return aLower->spr.type;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue