- tabified the rest of Blood's code.

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

View file

@ -34,7 +34,7 @@ BEGIN_BLD_NS
GAMEOPTIONS gGameOptions;
GAMEOPTIONS 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);
}
}

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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 = &sector[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 = &sector[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

View file

@ -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;
}

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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);
}

View file

@ -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 = &sect.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(&sect))
{
wal.shade -= v4;
if (pXSector->color)
{
wal.pal = sect.floorpal;
}
}
}
pXSector->shade = 0;
}
}
}
for (auto& sect : sector)
{
if (sect.hasX())
{
XSECTOR* pXSector = &sect.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(&sect))
{
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 = &sect.xs();
if (pXSector->amplitude)
shadeList.Push(&sect);
if (pXSector->panVel)
{
panList.Push(&sect);
shadeList.Clear();
panList.Clear();
wallPanList.Clear();
for (auto& sect : sector)
{
if (sect.hasX())
{
XSECTOR* pXSector = &sect.xs();
if (pXSector->amplitude)
shadeList.Push(&sect);
if (pXSector->panVel)
{
panList.Push(&sect);
if (pXSector->panCeiling)
{
StartInterpolation(&sect, Interp_Sect_CeilingPanX);
StartInterpolation(&sect, Interp_Sect_CeilingPanY);
}
if (pXSector->panFloor)
{
StartInterpolation(&sect, Interp_Sect_FloorPanX);
StartInterpolation(&sect, Interp_Sect_FloorPanY);
}
if (pXSector->panCeiling)
{
StartInterpolation(&sect, Interp_Sect_CeilingPanX);
StartInterpolation(&sect, Interp_Sect_CeilingPanY);
}
if (pXSector->panFloor)
{
StartInterpolation(&sect, Interp_Sect_FloorPanX);
StartInterpolation(&sect, 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);
}
}
}
}

View file

@ -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;
}

View file

@ -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

View file

@ -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);
}

View file

@ -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,
};

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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;
}
}

View file

@ -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