mirror of
https://github.com/ZDoom/raze-gles.git
synced 2025-01-11 18:50:46 +00:00
Merge branch 'powerslave'
This commit is contained in:
commit
f576774e69
148 changed files with 45663 additions and 305 deletions
|
@ -414,6 +414,7 @@ add_subdirectory( source/duke3d )
|
|||
add_subdirectory( source/blood )
|
||||
add_subdirectory( source/rr )
|
||||
add_subdirectory( source/sw )
|
||||
add_subdirectory( source/exhumed )
|
||||
|
||||
if( NOT CMAKE_CROSSCOMPILING )
|
||||
export(TARGETS ${CROSS_EXPORTS} FILE "${CMAKE_BINARY_DIR}/ImportExecutables.cmake" )
|
||||
|
|
22
README.md
Normal file
22
README.md
Normal file
|
@ -0,0 +1,22 @@
|
|||
# PCExhumed
|
||||
A port of the PC version of Exhumed based on EDuke32
|
||||
|
||||
## Installing
|
||||
1. Extract PCExhumed to a new directory
|
||||
2. Copy the following files from the PC retail version of Exhumed or PowerSlave (Exhumed preferred). Beta, demo or pre-release versions not supported.
|
||||
|
||||
STUFF.DAT
|
||||
DEMO.VCR
|
||||
BOOK.MOV
|
||||
|
||||
CD audio tracks are not yet working.
|
||||
The intro movie is not yet working with audio.
|
||||
Demo playback is not yet working.
|
||||
|
||||
3. Launch PCExhumed
|
||||
|
||||
## Building PCExhumed
|
||||
See: https://wiki.eduke32.com/wiki/Main_Page
|
||||
|
||||
## Acknowledgments:
|
||||
See AUTHORS.md
|
|
@ -226,15 +226,15 @@ find_package( FluidSynth )
|
|||
|
||||
# SSE only matters on 32-bit targets. We check compiler flags to know if we can do it.
|
||||
if( CMAKE_SIZEOF_VOID_P MATCHES "4" AND NOT CMAKE_OSX_ARCHITECTURES MATCHES ppc )
|
||||
CHECK_CXX_COMPILER_FLAG( "-msse2 -mfpmath=sse" CAN_DO_MFPMATH )
|
||||
CHECK_CXX_COMPILER_FLAG( -arch:SSE2 CAN_DO_ARCHSSE2 )
|
||||
if( CAN_DO_MFPMATH )
|
||||
set( SSE1_ENABLE "-msse -mfpmath=sse" )
|
||||
set( SSE2_ENABLE "-msse2 -mfpmath=sse" )
|
||||
elseif( CAN_DO_ARCHSSE2 )
|
||||
set( SSE1_ENABLE -arch:SSE )
|
||||
set( SSE2_ENABLE -arch:SSE2 )
|
||||
endif()
|
||||
CHECK_CXX_COMPILER_FLAG( "-msse2 -mfpmath=sse" CAN_DO_MFPMATH )
|
||||
CHECK_CXX_COMPILER_FLAG( -arch:SSE2 CAN_DO_ARCHSSE2 )
|
||||
if( CAN_DO_MFPMATH )
|
||||
set( SSE1_ENABLE "-msse -mfpmath=sse" )
|
||||
set( SSE2_ENABLE "-msse2 -mfpmath=sse" )
|
||||
elseif( CAN_DO_ARCHSSE2 )
|
||||
set( SSE1_ENABLE -arch:SSE )
|
||||
set( SSE2_ENABLE -arch:SSE2 )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if( X64 )
|
||||
|
@ -859,7 +859,7 @@ if( UNIX )
|
|||
endif()
|
||||
endif()
|
||||
|
||||
target_link_libraries( ${PROJECT_NAME} ${PROJECT_LIBRARIES} gdtoa lzma duke3d blood rr sw zmusic )
|
||||
target_link_libraries( ${PROJECT_NAME} ${PROJECT_LIBRARIES} gdtoa lzma duke3d blood rr sw exhumed zmusic )
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
|
@ -993,6 +993,8 @@ source_group("Code\\Menu" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/commo
|
|||
source_group("Code\\Rendering" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/.+")
|
||||
source_group("Code\\Rendering\\GL_Load" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/gl_load/.+")
|
||||
source_group("Code\\Rendering\\GL\\System" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/gl/system.+")
|
||||
source_group("Platform" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/platform/.+")
|
||||
source_group("Platform\\Win32" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/platform/win32/.+")
|
||||
source_group("Utility\\Smackerdec" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/smackerdec/.+")
|
||||
source_group("Utility\\Smackerdec\\Headers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/libsmackerdec/include/.+")
|
||||
source_group("Utility\\Smackerdec\\Sources" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/libsmackerdec/src/.+")
|
||||
|
|
|
@ -125,7 +125,7 @@ struct GameInterface
|
|||
virtual void DrawMenuCaption(const DVector2& origin, const char* text) {}
|
||||
virtual bool SaveGame(FSaveGameNode*) { return false; }
|
||||
virtual bool LoadGame(FSaveGameNode*) { return false; }
|
||||
virtual void DoPrintMessage(int prio, const char*) = 0;
|
||||
virtual void DoPrintMessage(int prio, const char*) {}
|
||||
void PrintMessage(int prio, const char*fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
|
|
@ -766,10 +766,8 @@ static FORCE_INLINE void clipmove_tweak_pos(const vec3_t *pos, int32_t gx, int32
|
|||
{
|
||||
int32_t daz;
|
||||
|
||||
if (enginecompatibility_mode == ENGINECOMPATIBILITY_19950829)
|
||||
return;
|
||||
|
||||
if (rintersect(pos->x, pos->y, 0, gx, gy, 0, x1, y1, x2, y2, daxptr, dayptr, &daz) == -1)
|
||||
if (enginecompatibility_mode == ENGINECOMPATIBILITY_19950829 ||
|
||||
rintersect(pos->x, pos->y, 0, gx, gy, 0, x1, y1, x2, y2, daxptr, dayptr, &daz) == -1)
|
||||
{
|
||||
*daxptr = pos->x;
|
||||
*dayptr = pos->y;
|
||||
|
@ -785,7 +783,7 @@ int32_t getceilzofslope_old(int32_t sectnum, int32_t dax, int32_t day)
|
|||
dx = wall[wall[j].point2].x-wall[j].x;
|
||||
dy = wall[wall[j].point2].y-wall[j].y;
|
||||
i = (ksqrtasm_old(dx*dx+dy*dy)); if (i == 0) return(sector[sectnum].ceilingz);
|
||||
i = divscale20(sector[sectnum].ceilingheinum,i);
|
||||
i = divscale15(sector[sectnum].ceilingheinum,i);
|
||||
dx *= i; dy *= i;
|
||||
return(sector[sectnum].ceilingz+dmulscale23(dx,day-wall[j].y,-dy,dax-wall[j].x));
|
||||
}
|
||||
|
@ -799,7 +797,7 @@ int32_t getflorzofslope_old(int32_t sectnum, int32_t dax, int32_t day)
|
|||
dx = wall[wall[j].point2].x-wall[j].x;
|
||||
dy = wall[wall[j].point2].y-wall[j].y;
|
||||
i = (ksqrtasm_old(dx*dx+dy*dy)); if (i == 0) return sector[sectnum].floorz;
|
||||
i = divscale20(sector[sectnum].floorheinum,i);
|
||||
i = divscale15(sector[sectnum].floorheinum,i);
|
||||
dx *= i; dy *= i;
|
||||
return(sector[sectnum].floorz+dmulscale23(dx,day-wall[j].y,-dy,dax-wall[j].x));
|
||||
}
|
||||
|
@ -1442,7 +1440,7 @@ int32_t clipmove(vec3_t * const pos, int16_t * const sectnum, int32_t xvect, int
|
|||
if (templl > 0)
|
||||
{
|
||||
int64_t const templl2 = compat_maybe_truncate_to_int32((int64_t)(goal.x-vec.x)*clipr.x + (int64_t)(goal.y-vec.y)*clipr.y);
|
||||
int32_t const i = enginecompatibility_mode == ENGINECOMPATIBILITY_19950829 || ((llabs(templl2)>>11) < templl) ?
|
||||
int32_t const i = (enginecompatibility_mode == ENGINECOMPATIBILITY_19950829 || (llabs(templl2)>>11) < templl) ?
|
||||
divscale64(templl2, templl, 20) : 0;
|
||||
|
||||
goal = { mulscale20(clipr.x, i)+vec.x, mulscale20(clipr.y, i)+vec.y };
|
||||
|
|
|
@ -10428,7 +10428,7 @@ int32_t cansee_old(int32_t xs, int32_t ys, int32_t zs, int16_t sectnums, int32_t
|
|||
int32_t cansee(int32_t x1, int32_t y1, int32_t z1, int16_t sect1, int32_t x2, int32_t y2, int32_t z2, int16_t sect2)
|
||||
{
|
||||
if (enginecompatibility_mode == ENGINECOMPATIBILITY_19950829)
|
||||
return cansee_old(x1, y1, z2, sect1, x2, y2, z2, sect2);
|
||||
return cansee_old(x1, y1, z1, sect1, x2, y2, z2, sect2);
|
||||
int32_t dacnt, danum;
|
||||
const int32_t x21 = x2-x1, y21 = y2-y1, z21 = z2-z1;
|
||||
|
||||
|
|
|
@ -56,12 +56,14 @@ enum GameFunction_t
|
|||
gamefunc_Shrink_Screen,
|
||||
gamefunc_Enlarge_Screen,
|
||||
gamefunc_Center_View,
|
||||
gamefunc_Look_Straight = gamefunc_Center_View,
|
||||
gamefunc_Holster_Weapon,
|
||||
gamefunc_Show_Opponents_Weapon,
|
||||
gamefunc_Map_Follow_Mode,
|
||||
gamefunc_See_Coop_View,
|
||||
gamefunc_See_Co_Op_View = gamefunc_See_Coop_View,
|
||||
gamefunc_Mouse_Aiming,
|
||||
gamefunc_Mouseview = gamefunc_Mouse_Aiming,
|
||||
gamefunc_Toggle_Crosshair,
|
||||
gamefunc_Steroids,
|
||||
gamefunc_Quick_Kick,
|
||||
|
@ -83,10 +85,14 @@ enum GameFunction_t
|
|||
gamefunc_Flash_Bomb,
|
||||
gamefunc_Caltrops,
|
||||
|
||||
gamefunc_Zoom_In, // Map controls should not pollute the global button namespace.
|
||||
gamefunc_Zoom_Out,
|
||||
|
||||
NUMGAMEFUNCTIONS
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Actions
|
||||
struct FButtonStatus
|
||||
{
|
||||
|
|
|
@ -1051,7 +1051,7 @@ void C_Ticker()
|
|||
|
||||
lasttic = consoletic;
|
||||
NotifyStrings.Tick();
|
||||
if (GUICapture & 1)
|
||||
if (ConsoleState == c_down)
|
||||
{
|
||||
D_ProcessEvents();
|
||||
}
|
||||
|
|
|
@ -265,6 +265,10 @@ namespace ShadowWarrior
|
|||
{
|
||||
::GameInterface* CreateInterface();
|
||||
}
|
||||
namespace Powerslave
|
||||
{
|
||||
::GameInterface* CreateInterface();
|
||||
}
|
||||
|
||||
void CheckFrontend(int flags)
|
||||
{
|
||||
|
@ -280,6 +284,10 @@ void CheckFrontend(int flags)
|
|||
{
|
||||
gi = ShadowWarrior::CreateInterface();
|
||||
}
|
||||
else if (flags & GAMEFLAG_PSEXHUMED)
|
||||
{
|
||||
gi = Powerslave::CreateInterface();
|
||||
}
|
||||
else
|
||||
{
|
||||
gi = Duke::CreateInterface();
|
||||
|
@ -639,12 +647,19 @@ FStringCVar* const CombatMacros[] = { &combatmacro0, &combatmacro1, &combatmacro
|
|||
void CONFIG_ReadCombatMacros()
|
||||
{
|
||||
FScanner sc;
|
||||
sc.Open("engine/combatmacros.txt");
|
||||
for (auto s : CombatMacros)
|
||||
try
|
||||
{
|
||||
sc.MustGetToken(TK_StringConst);
|
||||
if (strlen(*s) == 0)
|
||||
*s = sc.String;
|
||||
sc.Open("engine/combatmacros.txt");
|
||||
for (auto s : CombatMacros)
|
||||
{
|
||||
sc.MustGetToken(TK_StringConst);
|
||||
if (strlen(*s) == 0)
|
||||
*s = sc.String;
|
||||
}
|
||||
}
|
||||
catch (const std::runtime_error &)
|
||||
{
|
||||
// We do not want this to error out. Just ignore if it fails.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -105,7 +105,10 @@ enum
|
|||
GAMEFLAG_RRRA = 0x00000200,
|
||||
GAMEFLAG_BLOOD = 0x00000400,
|
||||
GAMEFLAG_SW = 0x00000800,
|
||||
GAMEFLAG_STANDALONE = 0x00001000,
|
||||
GAMEFLAG_POWERSLAVE = 0x00001000,
|
||||
GAMEFLAG_EXHUMED = 0x00002000,
|
||||
GAMEFLAG_PSEXHUMED = 0x00003000, // the two games really are the same, except for the name and the publisher.
|
||||
GAMEFLAG_STANDALONE = 0x00004000,
|
||||
GAMEFLAGMASK = 0x00000FFF, // flags allowed from grpinfo
|
||||
|
||||
};
|
||||
|
|
|
@ -192,7 +192,7 @@ public:
|
|||
|
||||
void ClearKeysDown(void)
|
||||
{
|
||||
KB_LastScan = 0;
|
||||
ClearLastScanCode();
|
||||
ClearAllKeyStatus();
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ void RegisterDukeMenus();
|
|||
void RegisterRedneckMenus();
|
||||
void RegisterBloodMenus();
|
||||
void RegisterSWMenus();
|
||||
void RegisterPSMenus();
|
||||
void RegisterLoadsaveMenus();
|
||||
void RegisterOptionMenus();
|
||||
void RegisterJoystickMenus();
|
||||
|
@ -387,8 +388,6 @@ void M_StartControlPanel (bool makeSound)
|
|||
BackbuttonTime = 0;
|
||||
BackbuttonAlpha = 0;
|
||||
DrawBackground = -1;
|
||||
DMenu::MenuTime = -1;
|
||||
M_Ticker(); // This needs to be called once here to make sure that the menu actually has ticked before it gets drawn for the first time.
|
||||
}
|
||||
|
||||
void Menu_Open(int playerid)
|
||||
|
@ -412,6 +411,8 @@ void M_ActivateMenu(DMenu *menu)
|
|||
transition.StartTransition(DMenu::CurrentMenu, menu, MA_Advance);
|
||||
}
|
||||
DMenu::CurrentMenu = menu;
|
||||
DMenu::MenuTime = -1;
|
||||
M_Ticker(); // This needs to be called once here to make sure that the menu actually has ticked before it gets drawn for the first time.
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -428,7 +429,7 @@ bool M_SetMenu(FName menu, int param, FName caller)
|
|||
GameStartupInfo.Episode = GameStartupInfo.Skill = 0;
|
||||
menu = NAME_StartGame;
|
||||
#endif
|
||||
if (DrawBackground == -1)
|
||||
if (DrawBackground == -1)
|
||||
{
|
||||
if (menu == NAME_MainMenu) DrawBackground = 1;
|
||||
else DrawBackground = 0;
|
||||
|
@ -473,6 +474,7 @@ bool M_SetMenu(FName menu, int param, FName caller)
|
|||
{
|
||||
case NAME_StartGame:
|
||||
M_ClearMenus(); // must be done before starting the level.
|
||||
if (caller == NAME_MainMenu) GameStartupInfo.Episode = param;
|
||||
STAT_StartNewGame(gVolumeNames[GameStartupInfo.Episode], GameStartupInfo.Skill);
|
||||
gi->StartGame(GameStartupInfo);
|
||||
return false;
|
||||
|
@ -837,7 +839,7 @@ void M_Ticker (void)
|
|||
if (DMenu::MenuTime & 3) return;
|
||||
if (DMenu::CurrentMenu != NULL && menuactive != MENU_Off)
|
||||
{
|
||||
D_ProcessEvents(); // The main loop is blocked when the menu is open and cannot dispatch the events.
|
||||
if (DMenu::MenuTime != 0) D_ProcessEvents(); // The main loop is blocked when the menu is open and cannot dispatch the events.
|
||||
if (transition.previous) transition.previous->Ticker();
|
||||
if (DMenu::CurrentMenu == nullptr) return; // In case one of the sub-screens has closed the menu.
|
||||
DMenu::CurrentMenu->Ticker();
|
||||
|
@ -894,6 +896,7 @@ void M_Drawer (void)
|
|||
}
|
||||
if (!going)
|
||||
{
|
||||
assert(DMenu::CurrentMenu);
|
||||
DMenu::CurrentMenu->origin = { 0,0 };
|
||||
// else if (DrawBackground) Menu_DrawBackground(origin);
|
||||
DMenu::CurrentMenu->Drawer();
|
||||
|
@ -925,8 +928,8 @@ void M_ClearMenus (bool final)
|
|||
menuactive = MENU_Off;
|
||||
if (!final)
|
||||
{
|
||||
mouseGrabInput(true);
|
||||
gi->MenuClosed();
|
||||
mouseGrabInput(true);
|
||||
gi->MenuClosed();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -979,6 +982,7 @@ void M_Init (void)
|
|||
RegisterRedneckMenus();
|
||||
RegisterBloodMenus();
|
||||
RegisterSWMenus();
|
||||
RegisterPSMenus();
|
||||
RegisterLoadsaveMenus();
|
||||
RegisterOptionMenus();
|
||||
RegisterJoystickMenus();
|
||||
|
|
|
@ -152,6 +152,7 @@ static const gamefilter games[] = {
|
|||
{ "RedneckRides", GAMEFLAG_RRRA},
|
||||
{ "Blood", GAMEFLAG_BLOOD},
|
||||
{ "ShadowWarrior", GAMEFLAG_SW},
|
||||
{ "Exhumed", GAMEFLAG_POWERSLAVE|GAMEFLAG_EXHUMED},
|
||||
};
|
||||
|
||||
// for other parts that need to filter by game name.
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
#define BEGIN_SW_NS namespace ShadowWarrior {
|
||||
#define END_SW_NS }
|
||||
|
||||
#define BEGIN_PS_NS namespace Powerslave {
|
||||
#define END_PS_NS }
|
||||
|
||||
#else
|
||||
|
||||
#define BEGIN_DUKE_NS
|
||||
|
@ -28,5 +31,8 @@
|
|||
#define BEGIN_SW_NS
|
||||
#define END_SW_NS
|
||||
|
||||
#define BEGIN_PS_NS
|
||||
#define END_PS_NS
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -664,6 +664,8 @@ static TArray<GrpInfo> ParseGrpInfo(const char *fn, FileReader &fr, TMap<FString
|
|||
FlagMap.Insert("GAMEFLAG_RRRA", GAMEFLAG_RRRA);
|
||||
FlagMap.Insert("GAMEFLAG_BLOOD", GAMEFLAG_BLOOD);
|
||||
FlagMap.Insert("GAMEFLAG_SW", GAMEFLAG_SW);
|
||||
FlagMap.Insert("GAMEFLAG_POWERSLAVE", GAMEFLAG_POWERSLAVE);
|
||||
FlagMap.Insert("GAMEFLAG_EXHUMED", GAMEFLAG_EXHUMED);
|
||||
|
||||
FScanner sc;
|
||||
auto mem = fr.Read();
|
||||
|
@ -1124,6 +1126,9 @@ const char* G_DefaultDefFile(void)
|
|||
if (g_gameType & GAMEFLAG_SW)
|
||||
return "sw.def";
|
||||
|
||||
if (g_gameType & GAMEFLAG_PSEXHUMED)
|
||||
return "exhumed.def";
|
||||
|
||||
if (g_gameType & GAMEFLAG_NAM)
|
||||
return fileSystem.FindFile("nam.def") ? "nam.def" : "napalm.def";
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ enum EChanFlag
|
|||
CHANF_VIRTUAL = 2048, // internal: Channel is currently virtual
|
||||
CHANF_NOSTOP = 4096, // only for A_PlaySound. Does not start if channel is playing something.
|
||||
CHANF_OVERLAP = 8192, // [MK] Does not stop any sounds in the channel and instead plays over them.
|
||||
CHANF_ENDED = 16384, // Helper to detect broken ChannelEnded implementations.
|
||||
};
|
||||
|
||||
typedef TFlags<EChanFlag> EChanFlags;
|
||||
|
|
|
@ -1702,7 +1702,9 @@ void OpenALSoundRenderer::StopChannel(FISoundChannel *chan)
|
|||
|
||||
ALuint source = GET_PTRID(chan->SysChannel);
|
||||
// Release first, so it can be properly marked as evicted if it's being killed
|
||||
chan->ChanFlags |= CHANF_ENDED;
|
||||
soundEngine->ChannelEnded(chan);
|
||||
assert(!(chan->ChanFlags & CHANF_ENDED));
|
||||
|
||||
ALint state = AL_INITIAL;
|
||||
alGetSourcei(source, AL_SOURCE_STATE, &state);
|
||||
|
@ -1726,7 +1728,9 @@ void OpenALSoundRenderer::ForceStopChannel(FISoundChannel *chan)
|
|||
ALuint source = GET_PTRID(chan->SysChannel);
|
||||
if(!source) return;
|
||||
|
||||
chan->ChanFlags |= CHANF_ENDED;
|
||||
soundEngine->ChannelEnded(chan);
|
||||
assert(!(chan->ChanFlags & CHANF_ENDED));
|
||||
FreeSource(source);
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ int sfx_empty = -1;
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void SoundEngine::Init(TArray<uint8_t> &curve)
|
||||
void SoundEngine::Init(TArray<uint8_t> &curve, int factor)
|
||||
{
|
||||
StopAllChannels();
|
||||
// Free all channels for use.
|
||||
|
@ -72,6 +72,7 @@ void SoundEngine::Init(TArray<uint8_t> &curve)
|
|||
ReturnChannel(Channels);
|
||||
}
|
||||
S_SoundCurve = std::move(curve);
|
||||
SndCurveFactor = (uint8_t)factor;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -605,6 +606,7 @@ FSoundChan *SoundEngine::StartSound(int type, const void *source,
|
|||
}
|
||||
if (chan != NULL)
|
||||
{
|
||||
assert(!(chan->ChanFlags & CHANF_FORGETTABLE));
|
||||
chan->SoundID = sound_id;
|
||||
chan->OrgID = FSoundID(org_id);
|
||||
chan->EntChannel = channel;
|
||||
|
@ -1332,7 +1334,7 @@ float SoundEngine::GetRolloff(const FRolloffInfo* rolloff, float distance)
|
|||
|
||||
if (rolloff->RolloffType == ROLLOFF_Custom && S_SoundCurve.Size() > 0)
|
||||
{
|
||||
return S_SoundCurve[int(S_SoundCurve.Size() * (1.f - volume))] / 127.f;
|
||||
return S_SoundCurve[int(S_SoundCurve.Size() * (1.f - volume))] / (float)SndCurveFactor;
|
||||
}
|
||||
return (powf(10.f, volume) - 1.f) / 9.f;
|
||||
}
|
||||
|
@ -1347,7 +1349,7 @@ void SoundEngine::ChannelEnded(FISoundChannel *ichan)
|
|||
{
|
||||
FSoundChan *schan = static_cast<FSoundChan*>(ichan);
|
||||
bool evicted;
|
||||
|
||||
schan->ChanFlags &= ~CHANF_ENDED;
|
||||
if (schan != NULL)
|
||||
{
|
||||
// If the sound was stopped with GSnd->StopSound(), then we know
|
||||
|
@ -1764,7 +1766,7 @@ FString SoundEngine::NoiseDebug()
|
|||
int ch = 0;
|
||||
|
||||
FStringf out("*** SOUND DEBUG INFO ***\nListener: %3.2f %2.3f %2.3f\n"
|
||||
"x y z vol dist chan pri flags aud pos name\n", listener.X, listener.Y, listener.Z);
|
||||
"x y z vol dist chan pri flags aud pos name\n", listener.X, listener.Y, listener.Z);
|
||||
|
||||
if (Channels == nullptr)
|
||||
{
|
||||
|
@ -1782,16 +1784,17 @@ FString SoundEngine::NoiseDebug()
|
|||
CalcPosVel(chan, &origin, nullptr);
|
||||
out.AppendFormat(TEXTCOLOR_GOLD "%5.0f | %5.0f | %5.0f | %5.0f ", origin.X, origin.Z, origin.Y, (origin - listener).Length());
|
||||
}
|
||||
out.AppendFormat("%-.2g %-4d %-4d %s3%sZ%sU%sM%sN%sA%sL%sE%sV" TEXTCOLOR_GOLD " %-5.4f %-4u %d: %s\n", chan->Volume, chan->EntChannel, chan->Priority,
|
||||
(chan->ChanFlags & CHANF_IS3D) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK,
|
||||
(chan->ChanFlags & CHANF_LISTENERZ) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK,
|
||||
(chan->ChanFlags & CHANF_UI) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK,
|
||||
(chan->ChanFlags & CHANF_MAYBE_LOCAL) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK,
|
||||
(chan->ChanFlags & CHANF_NOPAUSE) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK,
|
||||
(chan->ChanFlags & CHANF_AREA) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK,
|
||||
(chan->ChanFlags & CHANF_LOOP) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK,
|
||||
(chan->ChanFlags & CHANF_EVICTED) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK,
|
||||
(chan->ChanFlags & CHANF_VIRTUAL) ? TEXTCOLOR_GREEN : TEXTCOLOR_BLACK,
|
||||
out.AppendFormat("%-.2g %-4d %-4d %sF%s3%sZ%sU%sM%sN%sA%sL%sE%sV" TEXTCOLOR_GOLD " %-5.4f %-4u %d: %s\n", chan->Volume, chan->EntChannel, chan->Priority,
|
||||
(chan->ChanFlags & CHANF_FORGETTABLE) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
|
||||
(chan->ChanFlags & CHANF_IS3D) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
|
||||
(chan->ChanFlags & CHANF_LISTENERZ) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
|
||||
(chan->ChanFlags & CHANF_UI) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
|
||||
(chan->ChanFlags & CHANF_MAYBE_LOCAL) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
|
||||
(chan->ChanFlags & CHANF_NOPAUSE) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
|
||||
(chan->ChanFlags & CHANF_AREA) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
|
||||
(chan->ChanFlags & CHANF_LOOP) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
|
||||
(chan->ChanFlags & CHANF_EVICTED) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
|
||||
(chan->ChanFlags & CHANF_VIRTUAL) ? TEXTCOLOR_GREEN : TEXTCOLOR_DARKRED,
|
||||
GSnd->GetAudibility(chan), GSnd->GetPosition(chan), ((int)chan->OrgID)-1, S_sfx[chan->SoundID].name.GetChars());
|
||||
ch++;
|
||||
}
|
||||
|
|
|
@ -217,6 +217,8 @@ enum // This cannot be remain as this, but for now it has to suffice.
|
|||
SOURCE_Ambient, // Sound is coming from a blood ambient definition.
|
||||
SOURCE_Unattached, // Sound is not attached to any particular emitter.
|
||||
SOURCE_Player, // SW player sound (player in SW maintains its own position separately from the sprite so needs to be special.)
|
||||
SOURCE_Swirly, // Special stuff for Exhumed. (local sound with custom panning)
|
||||
SOURCE_EXBoss, // Another special case for Exhumed.
|
||||
};
|
||||
|
||||
|
||||
|
@ -234,6 +236,7 @@ class SoundEngine
|
|||
{
|
||||
protected:
|
||||
bool SoundPaused = false; // whether sound is paused
|
||||
uint8_t SndCurveFactor = 127;
|
||||
int RestartEvictionsAt = 0; // do not restart evicted channels before this time
|
||||
SoundListener listener{};
|
||||
|
||||
|
@ -284,7 +287,7 @@ public:
|
|||
// Sets channels, SFX and music volume,
|
||||
// allocates channel buffer, sets S_sfx lookup.
|
||||
//
|
||||
void Init(TArray<uint8_t> &sndcurve);
|
||||
void Init(TArray<uint8_t> &sndcurve, int factor = 127);
|
||||
void InitData();
|
||||
void Clear();
|
||||
void Shutdown();
|
||||
|
|
|
@ -379,9 +379,10 @@ FTexture* BuildTiles::ValidateCustomTile(int tilenum, int type)
|
|||
else if (type == FTexture::Restorable)
|
||||
{
|
||||
// This is for modifying an existing tile.
|
||||
// It only gets used for the crosshair and two specific effects:
|
||||
// It only gets used for the crosshair and a few specific effects:
|
||||
// A) the fire in Blood.
|
||||
// B) the pin display in Redneck Rampage's bowling lanes.
|
||||
// C) Exhumed's menu plus one special effect tile.
|
||||
// All of these effects should probably be redone without actual texture hacking...
|
||||
if (tile->GetWidth() == 0 || tile->GetHeight() == 0) return nullptr; // The base must have a size for this to work.
|
||||
// todo: invalidate hardware textures for tile.
|
||||
|
|
|
@ -588,7 +588,7 @@ inline uint8_t* tileData(int num)
|
|||
return tex->GetWritableBuffer();
|
||||
}
|
||||
|
||||
// Some hacks to allow accessing the no lpnger existing arrays as if they still were arrays to avoid changing hundreds of lines of code.
|
||||
// Some hacks to allow accessing the no longer existing arrays as if they still were arrays to avoid changing hundreds of lines of code.
|
||||
struct TileSiz
|
||||
{
|
||||
const vec2_16_t &operator[](size_t index)
|
||||
|
|
|
@ -44,6 +44,7 @@ void I_FatalError(const char* fmt, ...) ATTRIBUTE((format(printf, 1, 2)));
|
|||
// lots of potential for merge conflicts.
|
||||
|
||||
int PrintString (int iprintlevel, const char *outline);
|
||||
int VPrintf(int printlevel, const char* format, va_list parms);
|
||||
int Printf (int printlevel, const char *format, ...) ATTRIBUTE((format(printf,2,3)));
|
||||
int Printf (const char *format, ...) ATTRIBUTE((format(printf,1,2)));
|
||||
int DPrintf (int level, const char *format, ...) ATTRIBUTE((format(printf,2,3)));
|
||||
|
|
|
@ -64,16 +64,19 @@ const char *GetVersionString();
|
|||
#define SAVESIG_BLD GAMENAME ".Blood"
|
||||
#define SAVESIG_RR GAMENAME ".Redneck"
|
||||
#define SAVESIG_SW GAMENAME ".ShadowWarrior"
|
||||
#define SAVESIG_PS GAMENAME ".Exhumed"
|
||||
|
||||
#define MINSAVEVER_DN3D 1
|
||||
#define MINSAVEVER_BLD 1
|
||||
#define MINSAVEVER_RR 1
|
||||
#define MINSAVEVER_SW 1
|
||||
#define MINSAVEVER_PS 1
|
||||
|
||||
#define SAVEVER_DN3D 1
|
||||
#define SAVEVER_BLD 1
|
||||
#define SAVEVER_RR 1
|
||||
#define SAVEVER_SW 1
|
||||
#define SAVEVER_PS 1
|
||||
|
||||
#if defined(__APPLE__) || defined(_WIN32)
|
||||
#define GAME_DIR GAMENAME
|
||||
|
|
114
source/exhumed/CMakeLists.txt
Normal file
114
source/exhumed/CMakeLists.txt
Normal file
|
@ -0,0 +1,114 @@
|
|||
cmake_minimum_required( VERSION 3.1.0 )
|
||||
|
||||
if (MSVC)
|
||||
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /J" )
|
||||
endif()
|
||||
|
||||
include_directories( "${CMAKE_CURRENT_SOURCE_DIR}/../../build/include" )
|
||||
|
||||
if (WIN32)
|
||||
include_directories( "${ZLIB_INCLUDE_DIR}" "${ZMUSIC_INCLUDE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/../../platform/windows/include" "${CMAKE_CURRENT_SOURCE_DIR}/../../platform/windows/include/vpx" "${CMAKE_CURRENT_SOURCE_DIR}/../../platform/windows/include/sdl2" )
|
||||
else ()
|
||||
include_directories( "${ZLIB_INCLUDE_DIR}" "${ZMUSIC_INCLUDE_DIR}" "${BZIP2_INCLUDE_DIR}" "${LZMA_INCLUDE_DIR}" "${JPEG_INCLUDE_DIR}" "${GDTOA_INCLUDE_DIR}")
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../build/include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../libsmackerdec/include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../common
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../common/utility
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../common/console
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../common/textures
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../common/fonts
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../common/2d
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../common/music
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../common/input
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../platform )
|
||||
|
||||
|
||||
|
||||
#set( NOT_COMPILED_SOURCE_FILES
|
||||
# src/gamestructures.cpp
|
||||
#)
|
||||
|
||||
#set_source_files_properties( ${NOT_COMPILED_SOURCE_FILES} PROPERTIES HEADER_FILE_ONLY TRUE )
|
||||
|
||||
set( PCH_SOURCES
|
||||
src/aistuff.cpp
|
||||
src/anims.cpp
|
||||
src/anubis.cpp
|
||||
src/bubbles.cpp
|
||||
src/bullet.cpp
|
||||
src/cd.cpp
|
||||
src/enginesubs.cpp
|
||||
src/exhumed.cpp
|
||||
src/fish.cpp
|
||||
src/grenade.cpp
|
||||
src/gun.cpp
|
||||
src/init.cpp
|
||||
src/input.cpp
|
||||
src/items.cpp
|
||||
src/lavadude.cpp
|
||||
src/light.cpp
|
||||
src/lighting.cpp
|
||||
src/lion.cpp
|
||||
src/main.cpp
|
||||
src/map.cpp
|
||||
src/menu.cpp
|
||||
src/mono.cpp
|
||||
src/move.cpp
|
||||
src/movie.cpp
|
||||
src/mummy.cpp
|
||||
src/network.cpp
|
||||
src/object.cpp
|
||||
src/osdcmds.cpp
|
||||
src/paul.cpp
|
||||
src/player.cpp
|
||||
src/queen.cpp
|
||||
src/ra.cpp
|
||||
src/random.cpp
|
||||
src/rat.cpp
|
||||
src/record.cpp
|
||||
src/rex.cpp
|
||||
src/roach.cpp
|
||||
src/runlist.cpp
|
||||
src/save.cpp
|
||||
src/scorp.cpp
|
||||
src/sequence.cpp
|
||||
src/serial.cpp
|
||||
src/set.cpp
|
||||
src/snake.cpp
|
||||
src/sound.cpp
|
||||
src/spider.cpp
|
||||
src/status.cpp
|
||||
src/stream.cpp
|
||||
src/switch.cpp
|
||||
src/text2.cpp
|
||||
src/timer.cpp
|
||||
src/trigdat.cpp
|
||||
src/view.cpp
|
||||
src/wasp.cpp
|
||||
src/d_menu.cpp
|
||||
)
|
||||
|
||||
if( MSVC )
|
||||
enable_precompiled_headers( ../g_pch.h PCH_SOURCES )
|
||||
# The original Build code was written with unsigned chars and unfortunately they still haven't been eliminated entirely.
|
||||
# All other code should stay with signed chars. What a mess... :(
|
||||
#set_source_files_properties( ${PCH_SOURCES} PROPERTIES COMPILE_FLAGS "/J" )
|
||||
else()
|
||||
# Temporary solution for compilers other than MSVC
|
||||
set_source_files_properties( ${PCH_SOURCES} PROPERTIES COMPILE_FLAGS "-include g_pch.h" )
|
||||
endif()
|
||||
|
||||
file( GLOB HEADER_FILES
|
||||
src/*.h
|
||||
)
|
||||
add_library( exhumed STATIC
|
||||
${HEADER_FILES}
|
||||
${PCH_SOURCES}
|
||||
#${NOT_COMPILED_SOURCE_FILES}
|
||||
)
|
||||
|
||||
|
71
source/exhumed/src/aistuff.cpp
Normal file
71
source/exhumed/src/aistuff.cpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "aistuff.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
|
||||
extern int localclock;
|
||||
|
||||
int TimeSlot[KMaxTimeSlots];
|
||||
|
||||
|
||||
void InitTimeSlot()
|
||||
{
|
||||
for (int i = 0; i < KMaxTimeSlots; i++) {
|
||||
TimeSlot[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int GrabTimeSlot(int UNUSED(nVal))
|
||||
{
|
||||
return -1;
|
||||
|
||||
// BJD - below code found in an early Powerslave release. Doesn't seem to do anything and is missing in later releases.
|
||||
#if 0
|
||||
int ebx = -1;
|
||||
int esi;
|
||||
|
||||
for (int i = 0; i < nVal; i++)
|
||||
{
|
||||
int nSlot = (localclock + i) & 0xF;
|
||||
|
||||
if (ebx >= 0)
|
||||
{
|
||||
if (esi <= TimeSlot[nSlot]) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
esi = TimeSlot[nSlot];
|
||||
ebx = i;
|
||||
}
|
||||
|
||||
esi = localclock;
|
||||
|
||||
int edx = ebx;
|
||||
|
||||
while (edx < 16)
|
||||
{
|
||||
TimeSlot[(edx + esi) & 0xF]++;
|
||||
edx += nVal;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
END_PS_NS
|
51
source/exhumed/src/aistuff.h
Normal file
51
source/exhumed/src/aistuff.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __aistuff_h__
|
||||
#define __aistuff_h__
|
||||
|
||||
#include "compat.h"
|
||||
#include "anubis.h"
|
||||
#include "bubbles.h"
|
||||
#include "mummy.h"
|
||||
#include "rex.h"
|
||||
#include "roach.h"
|
||||
#include "scorp.h"
|
||||
#include "spider.h"
|
||||
#include "lion.h"
|
||||
#include "set.h"
|
||||
#include "queen.h"
|
||||
#include "wasp.h"
|
||||
#include "rat.h"
|
||||
#include "gun.h"
|
||||
#include "grenade.h"
|
||||
#include "snake.h"
|
||||
#include "fish.h"
|
||||
#include "lavadude.h"
|
||||
#include "bullet.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
#define KMaxTimeSlots 16
|
||||
|
||||
void InitTimeSlot();
|
||||
int GrabTimeSlot(int nVal);
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
348
source/exhumed/src/anims.cpp
Normal file
348
source/exhumed/src/anims.cpp
Normal file
|
@ -0,0 +1,348 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "engine.h"
|
||||
#include "anims.h"
|
||||
#include "sequence.h"
|
||||
#include "runlist.h"
|
||||
#include "exhumed.h"
|
||||
#include "sound.h"
|
||||
#include "random.h"
|
||||
#include "init.h"
|
||||
#include <assert.h>
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
#define kMaxAnims 400
|
||||
|
||||
short nMagicSeq = -1;
|
||||
short nPreMagicSeq = -1;
|
||||
short nSavePointSeq = -1;
|
||||
short nAnimsFree = 0;
|
||||
|
||||
short AnimRunRec[kMaxAnims];
|
||||
short AnimsFree[kMaxAnims];
|
||||
Anim AnimList[kMaxAnims];
|
||||
uint8_t AnimFlags[kMaxAnims];
|
||||
|
||||
static SavegameHelper sgh("anims",
|
||||
SV(nMagicSeq),
|
||||
SV(nPreMagicSeq),
|
||||
SV(nSavePointSeq),
|
||||
SV(nAnimsFree),
|
||||
SA(AnimRunRec),
|
||||
SA(AnimsFree),
|
||||
SA(AnimList),
|
||||
SA(AnimFlags),
|
||||
nullptr);
|
||||
|
||||
void InitAnims()
|
||||
{
|
||||
for (int i = 0; i < kMaxAnims; i++) {
|
||||
AnimsFree[i] = i;
|
||||
}
|
||||
|
||||
nAnimsFree = kMaxAnims;
|
||||
|
||||
nMagicSeq = SeqOffsets[kSeqItems] + 21;
|
||||
nPreMagicSeq = SeqOffsets[kSeqMagic2];
|
||||
nSavePointSeq = SeqOffsets[kSeqItems] + 12;
|
||||
}
|
||||
|
||||
void DestroyAnim(int nAnim)
|
||||
{
|
||||
short nSprite = AnimList[nAnim].nSprite;
|
||||
|
||||
if (nSprite >= 0)
|
||||
{
|
||||
StopSpriteSound(nSprite);
|
||||
runlist_SubRunRec(AnimRunRec[nAnim]);
|
||||
runlist_DoSubRunRec(sprite[nSprite].extra);
|
||||
runlist_FreeRun(sprite[nSprite].lotag - 1);
|
||||
}
|
||||
|
||||
AnimsFree[nAnimsFree] = nAnim;
|
||||
nAnimsFree++;
|
||||
}
|
||||
|
||||
int BuildAnim(int nSprite, int val, int val2, int x, int y, int z, int nSector, int nRepeat, int nFlag)
|
||||
{
|
||||
if (!nAnimsFree) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
nAnimsFree--;
|
||||
|
||||
short nAnim = AnimsFree[nAnimsFree];
|
||||
|
||||
if (nSprite == -1) {
|
||||
nSprite = insertsprite(nSector, 500);
|
||||
}
|
||||
|
||||
sprite[nSprite].x = x;
|
||||
sprite[nSprite].y = y;
|
||||
sprite[nSprite].z = z;
|
||||
sprite[nSprite].cstat = 0;
|
||||
|
||||
if (nFlag & 4)
|
||||
{
|
||||
sprite[nSprite].pal = 4;
|
||||
sprite[nSprite].shade = -64;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite[nSprite].pal = 0;
|
||||
sprite[nSprite].shade = -12;
|
||||
}
|
||||
|
||||
sprite[nSprite].clipdist = 10;
|
||||
sprite[nSprite].xrepeat = nRepeat;
|
||||
sprite[nSprite].yrepeat = nRepeat;
|
||||
sprite[nSprite].picnum = 1;
|
||||
sprite[nSprite].ang = 0;
|
||||
sprite[nSprite].xoffset = 0;
|
||||
sprite[nSprite].yoffset = 0;
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].zvel = 0;
|
||||
|
||||
// CHECKME - where is hitag set otherwise?
|
||||
if (sprite[nSprite].statnum < 900) {
|
||||
sprite[nSprite].hitag = -1;
|
||||
}
|
||||
|
||||
sprite[nSprite].lotag = runlist_HeadRun() + 1;
|
||||
sprite[nSprite].owner = -1;
|
||||
sprite[nSprite].extra = runlist_AddRunRec(sprite[nSprite].lotag - 1, nAnim | 0x100000);
|
||||
|
||||
AnimRunRec[nAnim] = runlist_AddRunRec(NewRun, nAnim | 0x100000);
|
||||
AnimList[nAnim].nSprite = nSprite;
|
||||
AnimFlags[nAnim] = nFlag;
|
||||
AnimList[nAnim].field_2 = 0;
|
||||
AnimList[nAnim].nSeq = SeqOffsets[val] + val2;
|
||||
AnimList[nAnim].field_4 = 256;
|
||||
|
||||
if (nFlag & 0x80) {
|
||||
sprite[nSprite].cstat |= 0x2; // set transluscence
|
||||
}
|
||||
|
||||
return nAnim;
|
||||
}
|
||||
|
||||
short GetAnimSprite(short nAnim)
|
||||
{
|
||||
return AnimList[nAnim].nSprite;
|
||||
}
|
||||
|
||||
void FuncAnim(int a, int, int nRun)
|
||||
{
|
||||
short nAnim = RunData[nRun].nVal;
|
||||
assert(nAnim >= 0 && nAnim < kMaxAnims);
|
||||
|
||||
short nSprite = AnimList[nAnim].nSprite;
|
||||
short nSeq = AnimList[nAnim].nSeq;
|
||||
|
||||
assert(nSprite != -1);
|
||||
|
||||
int nMessage = a & 0x7F0000;
|
||||
|
||||
switch (nMessage)
|
||||
{
|
||||
case 0x20000:
|
||||
{
|
||||
short var_1C = AnimList[nAnim].field_2;
|
||||
|
||||
if (!(sprite[nSprite].cstat & 0x8000))
|
||||
{
|
||||
seq_MoveSequence(nSprite, nSeq, var_1C);
|
||||
}
|
||||
|
||||
if (sprite[nSprite].statnum == kStatIgnited)
|
||||
{
|
||||
short nSpriteB = sprite[nSprite].hitag;
|
||||
if (nSpriteB > -1)
|
||||
{
|
||||
sprite[nSprite].x = sprite[nSpriteB].x;
|
||||
sprite[nSprite].y = sprite[nSpriteB].y;
|
||||
sprite[nSprite].z = sprite[nSpriteB].z;
|
||||
|
||||
if (sprite[nSpriteB].sectnum != sprite[nSprite].sectnum)
|
||||
{
|
||||
if (sprite[nSpriteB].sectnum < 0 || sprite[nSpriteB].sectnum >= kMaxSectors)
|
||||
{
|
||||
DestroyAnim(nAnim);
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
mychangespritesect(nSprite, sprite[nSpriteB].sectnum);
|
||||
}
|
||||
}
|
||||
|
||||
if (!var_1C)
|
||||
{
|
||||
if (sprite[nSpriteB].cstat != 0x8000)
|
||||
{
|
||||
short hitag2 = sprite[nSpriteB].hitag;
|
||||
sprite[nSpriteB].hitag--;
|
||||
|
||||
if (hitag2 >= 15)
|
||||
{
|
||||
runlist_DamageEnemy(nSpriteB, -1, (sprite[nSpriteB].hitag - 14) * 2);
|
||||
|
||||
if (sprite[nSpriteB].shade < 100)
|
||||
{
|
||||
sprite[nSpriteB].pal = 0;
|
||||
sprite[nSpriteB].shade++;
|
||||
}
|
||||
|
||||
if (!(sprite[nSpriteB].cstat & 101))
|
||||
{
|
||||
DestroyAnim(nAnim);
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite[nSpriteB].hitag = 1;
|
||||
DestroyAnim(nAnim);
|
||||
mydeletesprite(nSprite);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite[nSpriteB].hitag = 1;
|
||||
DestroyAnim(nAnim);
|
||||
mydeletesprite(nSprite);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AnimList[nAnim].field_2++;
|
||||
if (AnimList[nAnim].field_2 >= SeqSize[nSeq])
|
||||
{
|
||||
if (AnimFlags[nAnim] & 0x10)
|
||||
{
|
||||
AnimList[nAnim].field_2 = 0;
|
||||
}
|
||||
else if (nSeq == nPreMagicSeq)
|
||||
{
|
||||
AnimList[nAnim].field_2 = 0;
|
||||
AnimList[nAnim].nSeq = nMagicSeq;
|
||||
short nAnimSprite = AnimList[nAnim].nSprite;
|
||||
AnimFlags[nAnim] |= 0x10;
|
||||
sprite[nAnimSprite].cstat |= 2;
|
||||
}
|
||||
else if (nSeq == nSavePointSeq)
|
||||
{
|
||||
AnimList[nAnim].field_2 = 0;
|
||||
AnimList[nAnim].nSeq++;
|
||||
AnimFlags[nAnim] |= 0x10;
|
||||
}
|
||||
else
|
||||
{
|
||||
DestroyAnim(nAnim);
|
||||
mydeletesprite(nSprite);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x90000:
|
||||
{
|
||||
seq_PlotSequence(a & 0xFFFF, nSeq, AnimList[nAnim].field_2, 0x101);
|
||||
tsprite[a & 0xFFFF].owner = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
case 0xA0000:
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
Printf("unknown msg %x for anim\n", a & 0x7F0000);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BuildExplosion(short nSprite)
|
||||
{
|
||||
short nSector = sprite[nSprite].sectnum;
|
||||
|
||||
int edx = 36;
|
||||
|
||||
if (SectFlag[nSector] & kSectUnderwater)
|
||||
{
|
||||
edx = 75;
|
||||
}
|
||||
else if (sprite[nSprite].z == sector[nSector].floorz)
|
||||
{
|
||||
edx = 34;
|
||||
}
|
||||
|
||||
BuildAnim(-1, edx, 0, sprite[nSprite].x, sprite[nSprite].y, sprite[nSprite].z, sprite[nSprite].sectnum, sprite[nSprite].xrepeat, 4);
|
||||
}
|
||||
|
||||
int BuildSplash(int nSprite, int nSector)
|
||||
{
|
||||
int nRepeat, nSound;
|
||||
|
||||
if (sprite[nSprite].statnum != 200)
|
||||
{
|
||||
nRepeat = sprite[nSprite].xrepeat + (RandomWord() % sprite[nSprite].xrepeat);
|
||||
nSound = kSound0;
|
||||
}
|
||||
else
|
||||
{
|
||||
nRepeat = 20;
|
||||
nSound = kSound1;
|
||||
}
|
||||
|
||||
int bIsLava = SectFlag[nSector] & kSectLava;
|
||||
|
||||
int edx, nFlag;
|
||||
|
||||
if (bIsLava)
|
||||
{
|
||||
edx = 43;
|
||||
nFlag = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
edx = 35;
|
||||
nFlag = 0;
|
||||
}
|
||||
|
||||
int nAnim = BuildAnim(-1, edx, 0, sprite[nSprite].x, sprite[nSprite].y, sector[nSector].floorz, nSector, nRepeat, nFlag);
|
||||
|
||||
if (!bIsLava)
|
||||
{
|
||||
D3PlayFX(StaticSound[nSound] | 0xa00, AnimList[nAnim].nSprite);
|
||||
}
|
||||
|
||||
return AnimList[nAnim].nSprite;
|
||||
}
|
||||
END_PS_NS
|
48
source/exhumed/src/anims.h
Normal file
48
source/exhumed/src/anims.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __anims_h__
|
||||
#define __anims_h__
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
struct Anim
|
||||
{
|
||||
short nSeq;
|
||||
short field_2;
|
||||
short field_4;
|
||||
short nSprite;
|
||||
};
|
||||
|
||||
extern Anim AnimList[];
|
||||
extern uint8_t AnimFlags[];
|
||||
|
||||
void InitAnims();
|
||||
void DestroyAnim(int nAnim);
|
||||
int BuildAnim(int nSprite, int val, int val2, int x, int y, int z, int nSector, int nRepeat, int nFlag);
|
||||
short GetAnimSprite(short nAnim);
|
||||
|
||||
void FuncAnim(int, int, int);
|
||||
void BuildExplosion(short nSprite);
|
||||
int BuildSplash(int nSprite, int nSector);
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
502
source/exhumed/src/anubis.cpp
Normal file
502
source/exhumed/src/anubis.cpp
Normal file
|
@ -0,0 +1,502 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "exhumed.h"
|
||||
#include "anubis.h"
|
||||
#include "engine.h"
|
||||
#include "runlist.h"
|
||||
#include "sequence.h"
|
||||
#include "move.h"
|
||||
#include "bullet.h"
|
||||
#include "random.h"
|
||||
#include "items.h"
|
||||
#include "object.h"
|
||||
#include "sound.h"
|
||||
#include "trigdat.h"
|
||||
#include <assert.h>
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
#define kMaxAnubis 80
|
||||
|
||||
struct Anubis
|
||||
{
|
||||
short nHealth;
|
||||
short nFrame;
|
||||
short nAction;
|
||||
short nSprite;
|
||||
short nTarget;
|
||||
short f;
|
||||
short g;
|
||||
short h;
|
||||
};
|
||||
|
||||
Anubis AnubisList[kMaxAnubis];
|
||||
|
||||
short AnubisSprite = -1;
|
||||
short AnubisCount = -1;
|
||||
|
||||
static actionSeq ActionSeq[] = {
|
||||
{ 0, 0 },
|
||||
{ 8, 0 },
|
||||
{ 16, 0 },
|
||||
{ 24, 0 },
|
||||
{ 32, 0 },
|
||||
{ -1, 0 },
|
||||
{ 46, 1 },
|
||||
{ 46, 1 },
|
||||
{ 47, 1 },
|
||||
{ 49, 1 },
|
||||
{ 49, 1 },
|
||||
{ 40, 1 },
|
||||
{ 42, 1 },
|
||||
{ 41, 1 },
|
||||
{ 43, 1 },
|
||||
};
|
||||
|
||||
short nAnubisDrum = 0;
|
||||
|
||||
static SavegameHelper sgh("anubis",
|
||||
SA(AnubisList),
|
||||
SV(AnubisSprite),
|
||||
SV(AnubisCount),
|
||||
SV(nAnubisDrum),
|
||||
nullptr);
|
||||
|
||||
|
||||
void InitAnubis()
|
||||
{
|
||||
AnubisCount = kMaxAnubis;
|
||||
AnubisSprite = 1;
|
||||
nAnubisDrum = 1;
|
||||
}
|
||||
|
||||
int BuildAnubis(int nSprite, int x, int y, int z, int nSector, int nAngle, uint8_t bIsDrummer)
|
||||
{
|
||||
AnubisCount--;
|
||||
short nAnubis = AnubisCount;
|
||||
|
||||
if (nAnubis < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nSprite == -1)
|
||||
{
|
||||
nSprite = insertsprite(nSector, 101);
|
||||
}
|
||||
else
|
||||
{
|
||||
changespritestat(nSprite, 101);
|
||||
|
||||
x = sprite[nSprite].x;
|
||||
y = sprite[nSprite].y;
|
||||
z = sector[sprite[nSprite].sectnum].floorz;
|
||||
nAngle = sprite[nSprite].ang;
|
||||
}
|
||||
|
||||
assert(nSprite >=0 && nSprite < kMaxSprites);
|
||||
|
||||
sprite[nSprite].x = x;
|
||||
sprite[nSprite].y = y;
|
||||
sprite[nSprite].z = z;
|
||||
sprite[nSprite].cstat = 0x101;
|
||||
sprite[nSprite].xoffset = 0;
|
||||
sprite[nSprite].shade = -12;
|
||||
sprite[nSprite].yoffset = 0;
|
||||
sprite[nSprite].picnum = 1;
|
||||
sprite[nSprite].pal = sector[sprite[nSprite].sectnum].ceilingpal;
|
||||
sprite[nSprite].clipdist = 60;
|
||||
sprite[nSprite].ang = nAngle;
|
||||
sprite[nSprite].xrepeat = 40;
|
||||
sprite[nSprite].yrepeat = 40;
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].zvel = 0;
|
||||
sprite[nSprite].hitag = 0;
|
||||
sprite[nSprite].lotag = runlist_HeadRun() + 1;
|
||||
sprite[nSprite].extra = -1;
|
||||
|
||||
// GrabTimeSlot(3);
|
||||
|
||||
if (bIsDrummer)
|
||||
{
|
||||
AnubisList[nAnubis].nAction = nAnubisDrum + 6;
|
||||
nAnubisDrum++;
|
||||
|
||||
if (nAnubisDrum >= 5) {
|
||||
nAnubisDrum = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AnubisList[nAnubis].nAction = 0;
|
||||
}
|
||||
|
||||
AnubisList[nAnubis].nHealth = 540;
|
||||
AnubisList[nAnubis].nFrame = 0;
|
||||
AnubisList[nAnubis].nSprite = nSprite;
|
||||
AnubisList[nAnubis].nTarget = -1;
|
||||
AnubisList[nAnubis].g = 0;
|
||||
|
||||
sprite[nSprite].owner = runlist_AddRunRec(sprite[nSprite].lotag - 1, nAnubis | 0x90000);
|
||||
|
||||
runlist_AddRunRec(NewRun, nAnubis | 0x90000);
|
||||
nCreaturesLeft++;
|
||||
|
||||
return nAnubis | 0x90000;
|
||||
}
|
||||
|
||||
void FuncAnubis(int a, int nDamage, int nRun)
|
||||
{
|
||||
short nAnubis = RunData[nRun].nVal;
|
||||
int var_14 = 0;
|
||||
|
||||
assert(nAnubis >= 0 && nAnubis < kMaxAnubis);
|
||||
|
||||
short nSprite = AnubisList[nAnubis].nSprite;
|
||||
short nAction = AnubisList[nAnubis].nAction;
|
||||
|
||||
int nMessage = a & 0x7F0000;
|
||||
|
||||
switch (nMessage)
|
||||
{
|
||||
case 0x20000:
|
||||
{
|
||||
if (nAction < 11) {
|
||||
Gravity(nSprite);
|
||||
}
|
||||
|
||||
short nSeq = SeqOffsets[kSeqAnubis] + ActionSeq[nAction].a;
|
||||
|
||||
seq_MoveSequence(nSprite, nSeq, AnubisList[nAnubis].nFrame);
|
||||
|
||||
sprite[nSprite].picnum = seq_GetSeqPicnum2(nSeq, AnubisList[nAnubis].nFrame);
|
||||
|
||||
AnubisList[nAnubis].nFrame++;
|
||||
if (AnubisList[nAnubis].nFrame >= SeqSize[nSeq])
|
||||
{
|
||||
AnubisList[nAnubis].nFrame = 0;
|
||||
var_14 = 1;
|
||||
}
|
||||
|
||||
short nTarget = AnubisList[nAnubis].nTarget;
|
||||
|
||||
short nFrame = SeqBase[nSeq] + AnubisList[nAnubis].nFrame;
|
||||
short nFlag = FrameFlag[nFrame];
|
||||
|
||||
int c = 0;
|
||||
|
||||
if (nAction > 0 && nAction < 11) {
|
||||
c = MoveCreatureWithCaution(nSprite);
|
||||
}
|
||||
|
||||
switch (nAction)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
if ((nAnubis & 0x1F) == (totalmoves & 0x1F))
|
||||
{
|
||||
if (nTarget < 0) {
|
||||
nTarget = FindPlayer(nSprite, 100);
|
||||
}
|
||||
|
||||
if (nTarget >= 0)
|
||||
{
|
||||
D3PlayFX(StaticSound[kSound8], nSprite);
|
||||
AnubisList[nAnubis].nAction = 1;
|
||||
AnubisList[nAnubis].nFrame = 0;
|
||||
AnubisList[nAnubis].nTarget = nTarget;
|
||||
|
||||
sprite[nSprite].xvel = Cos(sprite[nSprite].ang) >> 2;
|
||||
sprite[nSprite].yvel = Sin(sprite[nSprite].ang) >> 2;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
if ((nAnubis & 0x1F) == (totalmoves & 0x1F))
|
||||
{
|
||||
PlotCourseToSprite(nSprite, nTarget);
|
||||
|
||||
sprite[nSprite].xvel = Cos(sprite[nSprite].ang & 0xFFF8) >> 2;
|
||||
sprite[nSprite].yvel = Sin(sprite[nSprite].ang & 0xFFF8) >> 2;
|
||||
}
|
||||
|
||||
switch (c & 0xC000)
|
||||
{
|
||||
case 0xC000:
|
||||
{
|
||||
if ((c & 0x3FFF) == nTarget)
|
||||
{
|
||||
int nAng = getangle(sprite[nTarget].x - sprite[nSprite].x, sprite[nTarget].y - sprite[nSprite].y);
|
||||
int nAngDiff = AngleDiff(sprite[nSprite].ang, nAng);
|
||||
|
||||
if (nAngDiff < 64)
|
||||
{
|
||||
AnubisList[nAnubis].nAction = 2;
|
||||
AnubisList[nAnubis].nFrame = 0;
|
||||
}
|
||||
break; // only break if condition met
|
||||
}
|
||||
// else we fall through to 0x8000
|
||||
fallthrough__;
|
||||
}
|
||||
case 0x8000:
|
||||
{
|
||||
sprite[nSprite].ang = (sprite[nSprite].ang + 256) & kAngleMask;
|
||||
sprite[nSprite].xvel = Cos(sprite[nSprite].ang) >> 2;
|
||||
sprite[nSprite].yvel = Sin(sprite[nSprite].ang) >> 2;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
if (AnubisList[nAnubis].g)
|
||||
{
|
||||
AnubisList[nAnubis].g--;
|
||||
}
|
||||
else
|
||||
{
|
||||
AnubisList[nAnubis].g = 60;
|
||||
|
||||
if (cansee(sprite[nSprite].x, sprite[nSprite].y, sprite[nSprite].z - GetSpriteHeight(nSprite), sprite[nSprite].sectnum,
|
||||
sprite[nTarget].x, sprite[nTarget].y, sprite[nTarget].z - GetSpriteHeight(nTarget), sprite[nTarget].sectnum))
|
||||
{
|
||||
AnubisList[nAnubis].nAction = 3;
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].ang = GetMyAngle(sprite[nTarget].x - sprite[nSprite].x, sprite[nTarget].y - sprite[nSprite].y);
|
||||
AnubisList[nAnubis].nFrame = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
if (nTarget == -1)
|
||||
{
|
||||
AnubisList[nAnubis].nAction = 0;
|
||||
AnubisList[nAnubis].g = 50;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PlotCourseToSprite(nSprite, nTarget) >= 768)
|
||||
{
|
||||
AnubisList[nAnubis].nAction = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nFlag & 0x80)
|
||||
{
|
||||
runlist_DamageEnemy(nTarget, nSprite, 7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
if (var_14)
|
||||
{
|
||||
AnubisList[nAnubis].nAction = 1;
|
||||
|
||||
sprite[nSprite].xvel = Cos(sprite[nSprite].ang) >> 2;
|
||||
sprite[nSprite].yvel = Sin(sprite[nSprite].ang) >> 2;
|
||||
AnubisList[nAnubis].nFrame = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// loc_25718:
|
||||
if (nFlag & 0x80)
|
||||
{
|
||||
BuildBullet(nSprite, 8, 0, 0, -1, sprite[nSprite].ang, nTarget + 10000, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
case 4:
|
||||
case 5:
|
||||
{
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
|
||||
if (var_14)
|
||||
{
|
||||
AnubisList[nAnubis].nAction = 1;
|
||||
AnubisList[nAnubis].nFrame = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
{
|
||||
if (var_14)
|
||||
{
|
||||
AnubisList[nAnubis].nAction = (RandomSize(3) % 5) + 6;
|
||||
AnubisList[nAnubis].nFrame = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
case 11:
|
||||
case 12:
|
||||
{
|
||||
if (var_14)
|
||||
{
|
||||
AnubisList[nAnubis].nAction = nAction + 2;
|
||||
AnubisList[nAnubis].nFrame = 0;
|
||||
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
case 13:
|
||||
case 14:
|
||||
{
|
||||
sprite[nSprite].cstat &= 0xFEFE;
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
// loc_2564C:
|
||||
if (nAction && nTarget != -1)
|
||||
{
|
||||
if (!(sprite[nTarget].cstat & 0x101))
|
||||
{
|
||||
AnubisList[nAnubis].nAction = 0;
|
||||
AnubisList[nAnubis].nFrame = 0;
|
||||
AnubisList[nAnubis].g = 100;
|
||||
AnubisList[nAnubis].nTarget = -1;
|
||||
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x90000:
|
||||
{
|
||||
seq_PlotSequence(a & 0xFFFF, SeqOffsets[kSeqAnubis] + ActionSeq[nAction].a, AnubisList[nAnubis].nFrame, ActionSeq[nAction].b);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xA0000: // fall through to next case
|
||||
{
|
||||
if (nAction >= 11) {
|
||||
return;
|
||||
}
|
||||
|
||||
nDamage = runlist_CheckRadialDamage(nSprite);
|
||||
fallthrough__;
|
||||
}
|
||||
case 0x80000:
|
||||
{
|
||||
if (nDamage)
|
||||
{
|
||||
if (AnubisList[nAnubis].nHealth <= 0)
|
||||
return;
|
||||
|
||||
AnubisList[nAnubis].nHealth -= nDamage;
|
||||
|
||||
if (AnubisList[nAnubis].nHealth > 0)
|
||||
{
|
||||
short nTarget = a & 0xFFFF;
|
||||
|
||||
// loc_258D6:
|
||||
if (nTarget < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sprite[nTarget].statnum == 100 || sprite[nTarget].statnum < 199)
|
||||
{
|
||||
if (!RandomSize(5)) {
|
||||
AnubisList[nAnubis].nTarget = nTarget;
|
||||
}
|
||||
}
|
||||
|
||||
if (RandomSize(1))
|
||||
{
|
||||
if (nAction >= 6 && nAction <= 10)
|
||||
{
|
||||
int nThisSprite = insertsprite(sprite[nSprite].sectnum, 98);
|
||||
|
||||
sprite[nThisSprite].x = sprite[nSprite].x;
|
||||
sprite[nThisSprite].y = sprite[nSprite].y;
|
||||
sprite[nThisSprite].z = sector[sprite[nThisSprite].sectnum].floorz;
|
||||
sprite[nThisSprite].xrepeat = 40;
|
||||
sprite[nThisSprite].yrepeat = 40;
|
||||
sprite[nThisSprite].shade = -64;
|
||||
|
||||
BuildObject(nThisSprite, 2, 0);
|
||||
}
|
||||
|
||||
AnubisList[nAnubis].nAction = 4;
|
||||
AnubisList[nAnubis].nFrame = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// loc_259B5:
|
||||
D3PlayFX(StaticSound[kSound39], nSprite);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// he ded.
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].zvel = 0;
|
||||
sprite[nSprite].z = sector[sprite[nSprite].sectnum].floorz;
|
||||
sprite[nSprite].cstat &= 0xFEFE;
|
||||
|
||||
AnubisList[nAnubis].nHealth = 0;
|
||||
|
||||
nCreaturesLeft--;
|
||||
|
||||
if (nAction < 11)
|
||||
{
|
||||
DropMagic(nSprite);
|
||||
AnubisList[nAnubis].nAction = (nMessage == 0xA0000) + 11;
|
||||
AnubisList[nAnubis].nFrame = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
default:
|
||||
{
|
||||
Printf("unknown msg %d for Anubis\n", a & 0x7F0000);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
END_PS_NS
|
33
source/exhumed/src/anubis.h
Normal file
33
source/exhumed/src/anubis.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __anubis_h__
|
||||
#define __anubis_h__
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
void InitAnubis();
|
||||
int BuildAnubis(int nSprite, int x, int y, int z, int nSector, int nAngle, uint8_t bIsDrummer);
|
||||
|
||||
void FuncAnubis(int a, int b, int c);
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
252
source/exhumed/src/bubbles.cpp
Normal file
252
source/exhumed/src/bubbles.cpp
Normal file
|
@ -0,0 +1,252 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "bubbles.h"
|
||||
#include "runlist.h"
|
||||
#include "exhumed.h"
|
||||
#include "random.h"
|
||||
#include "engine.h"
|
||||
#include "sequence.h"
|
||||
#include "move.h"
|
||||
#include "init.h"
|
||||
#include "runlist.h"
|
||||
#include "init.h"
|
||||
#include "anims.h"
|
||||
#include <assert.h>
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
|
||||
#define kMaxBubbles 200
|
||||
#define kMaxMachines 125
|
||||
|
||||
struct Bubble
|
||||
{
|
||||
short _0;
|
||||
short _2;
|
||||
short nSprite;
|
||||
short _6;
|
||||
};
|
||||
|
||||
struct machine
|
||||
{
|
||||
short _0;
|
||||
short nSprite;
|
||||
short _4;
|
||||
};
|
||||
|
||||
short BubbleCount = 0;
|
||||
|
||||
short nFreeCount;
|
||||
short nMachineCount;
|
||||
|
||||
uint8_t nBubblesFree[kMaxBubbles];
|
||||
machine Machine[kMaxMachines];
|
||||
Bubble BubbleList[kMaxBubbles];
|
||||
|
||||
static SavegameHelper sgh("bubbles",
|
||||
SV(BubbleCount),
|
||||
SV(nFreeCount),
|
||||
SV(nMachineCount),
|
||||
SA(nBubblesFree),
|
||||
SA(Machine),
|
||||
SA(BubbleList),
|
||||
nullptr);
|
||||
|
||||
void InitBubbles()
|
||||
{
|
||||
BubbleCount = 0;
|
||||
nMachineCount = 0;
|
||||
|
||||
for (int i = 0; i < kMaxBubbles; i++) {
|
||||
nBubblesFree[i] = i;
|
||||
}
|
||||
|
||||
nFreeCount = kMaxBubbles;
|
||||
}
|
||||
|
||||
void DestroyBubble(short nBubble)
|
||||
{
|
||||
short nSprite = BubbleList[nBubble].nSprite;
|
||||
|
||||
runlist_DoSubRunRec(sprite[nSprite].lotag - 1);
|
||||
runlist_DoSubRunRec(sprite[nSprite].owner);
|
||||
runlist_SubRunRec(BubbleList[nBubble]._6);
|
||||
|
||||
mydeletesprite(nSprite);
|
||||
|
||||
nBubblesFree[nFreeCount] = nBubble;
|
||||
|
||||
nFreeCount++;
|
||||
}
|
||||
|
||||
short GetBubbleSprite(short nBubble)
|
||||
{
|
||||
return BubbleList[nBubble].nSprite;
|
||||
}
|
||||
|
||||
int BuildBubble(int x, int y, int z, short nSector)
|
||||
{
|
||||
int nSize = RandomSize(3);
|
||||
if (nSize > 4) {
|
||||
nSize -= 4;
|
||||
}
|
||||
|
||||
if (nFreeCount <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
nFreeCount--;
|
||||
|
||||
uint8_t nBubble = nBubblesFree[nFreeCount];
|
||||
|
||||
int nSprite = insertsprite(nSector, 402);
|
||||
assert(nSprite >= 0 && nSprite < kMaxSprites);
|
||||
|
||||
sprite[nSprite].x = x;
|
||||
sprite[nSprite].y = y;
|
||||
sprite[nSprite].z = z;
|
||||
sprite[nSprite].cstat = 0;
|
||||
sprite[nSprite].shade = -32;
|
||||
sprite[nSprite].pal = 0;
|
||||
sprite[nSprite].clipdist = 5;
|
||||
sprite[nSprite].xrepeat = 40;
|
||||
sprite[nSprite].yrepeat = 40;
|
||||
sprite[nSprite].xoffset = 0;
|
||||
sprite[nSprite].yoffset = 0;
|
||||
sprite[nSprite].picnum = 1;
|
||||
sprite[nSprite].ang = inita;
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].zvel = -1200;
|
||||
sprite[nSprite].hitag = -1;
|
||||
sprite[nSprite].extra = -1;
|
||||
sprite[nSprite].lotag = runlist_HeadRun() + 1;
|
||||
|
||||
// GrabTimeSlot(3);
|
||||
|
||||
BubbleList[nBubble].nSprite = nSprite;
|
||||
BubbleList[nBubble]._0 = 0;
|
||||
BubbleList[nBubble]._2 = SeqOffsets[kSeqBubble] + nSize;
|
||||
|
||||
sprite[nSprite].owner = runlist_AddRunRec(sprite[nSprite].lotag - 1, nBubble | 0x140000);
|
||||
|
||||
BubbleList[nBubble]._6 = runlist_AddRunRec(NewRun, nBubble | 0x140000);
|
||||
return nBubble | 0x140000;
|
||||
}
|
||||
|
||||
void FuncBubble(int a, int UNUSED(b), int nRun)
|
||||
{
|
||||
short nBubble = RunData[nRun].nVal;
|
||||
assert(nBubble >= 0 && nBubble < kMaxBubbles);
|
||||
|
||||
short nSprite = BubbleList[nBubble].nSprite;
|
||||
short dx = BubbleList[nBubble]._2;
|
||||
|
||||
int nMessage = a & 0x7F0000;
|
||||
|
||||
switch (nMessage)
|
||||
{
|
||||
case 0x20000:
|
||||
{
|
||||
seq_MoveSequence(nSprite, dx, BubbleList[nBubble]._0);
|
||||
|
||||
BubbleList[nBubble]._0++;
|
||||
|
||||
if (BubbleList[nBubble]._0 >= SeqSize[dx]) {
|
||||
BubbleList[nBubble]._0 = 0;
|
||||
}
|
||||
|
||||
sprite[nSprite].z += sprite[nSprite].zvel;
|
||||
|
||||
short nSector = sprite[nSprite].sectnum;
|
||||
|
||||
if (sprite[nSprite].z <= sector[nSector].ceilingz)
|
||||
{
|
||||
short nSectAbove = SectAbove[nSector];
|
||||
|
||||
if (sprite[nSprite].hitag > -1 && nSectAbove != -1) {
|
||||
BuildAnim(-1, 70, 0, sprite[nSprite].x, sprite[nSprite].y, sector[nSectAbove].floorz, nSectAbove, 64, 0);
|
||||
}
|
||||
|
||||
DestroyBubble(nBubble);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x90000:
|
||||
{
|
||||
seq_PlotSequence(a & 0xFFFF, dx, BubbleList[nBubble]._0, 1);
|
||||
tsprite[a & 0xFFFF].owner = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x80000:
|
||||
case 0xA0000:
|
||||
return;
|
||||
|
||||
default:
|
||||
Printf("unknown msg %d for Bubble\n", nMessage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void DoBubbleMachines()
|
||||
{
|
||||
for (int i = 0; i < nMachineCount; i++)
|
||||
{
|
||||
Machine[i]._0--;
|
||||
|
||||
if (Machine[i]._0 <= 0)
|
||||
{
|
||||
Machine[i]._0 = (RandomWord() % Machine[i]._4) + 30;
|
||||
|
||||
int nSprite = Machine[i].nSprite;
|
||||
BuildBubble(sprite[nSprite].x, sprite[nSprite].y, sprite[nSprite].z, sprite[nSprite].sectnum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BuildBubbleMachine(int nSprite)
|
||||
{
|
||||
if (nMachineCount >= kMaxMachines) {
|
||||
I_Error("too many bubble machines in level %d\n", levelnew);
|
||||
}
|
||||
|
||||
Machine[nMachineCount]._4 = 75;
|
||||
Machine[nMachineCount].nSprite = nSprite;
|
||||
Machine[nMachineCount]._0 = Machine[nMachineCount]._4;
|
||||
nMachineCount++;
|
||||
|
||||
sprite[nSprite].cstat = 0x8000u;
|
||||
}
|
||||
|
||||
void DoBubbles(int nPlayer)
|
||||
{
|
||||
int x, y, z;
|
||||
short nSector;
|
||||
|
||||
WheresMyMouth(nPlayer, &x, &y, &z, &nSector);
|
||||
|
||||
int nBubble = BuildBubble(x, y, z, nSector);
|
||||
int nSprite = GetBubbleSprite(nBubble);
|
||||
|
||||
sprite[nSprite].hitag = nPlayer;
|
||||
}
|
||||
END_PS_NS
|
34
source/exhumed/src/bubbles.h
Normal file
34
source/exhumed/src/bubbles.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __bubbles_h__
|
||||
#define __bubbles_h__
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
void InitBubbles();
|
||||
|
||||
void BuildBubbleMachine(int nSprite);
|
||||
void DoBubbleMachines();
|
||||
|
||||
void DoBubbles(int nPlayer);
|
||||
void FuncBubble(int, int, int);
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
869
source/exhumed/src/bullet.cpp
Normal file
869
source/exhumed/src/bullet.cpp
Normal file
|
@ -0,0 +1,869 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "engine.h"
|
||||
#include "bullet.h"
|
||||
#include "runlist.h"
|
||||
#include "anims.h"
|
||||
#include "sequence.h"
|
||||
#include "exhumed.h"
|
||||
#include "sound.h"
|
||||
#include "init.h"
|
||||
#include "move.h"
|
||||
#include "player.h"
|
||||
#include "trigdat.h"
|
||||
#include "random.h"
|
||||
#include "gun.h"
|
||||
#include "names.h"
|
||||
#include "lighting.h"
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#ifndef __WATCOMC__
|
||||
//#include <cmath>
|
||||
#else
|
||||
//#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
#define kMaxBullets 500
|
||||
|
||||
short BulletFree[kMaxBullets];
|
||||
|
||||
// 32 bytes
|
||||
struct Bullet
|
||||
{
|
||||
short nSeq; // 0
|
||||
short field_2; // 2
|
||||
short nSprite; // 4
|
||||
short field_6;
|
||||
short field_8;
|
||||
short nType;
|
||||
short field_C;
|
||||
short field_E;
|
||||
uint16_t field_10;
|
||||
uint8_t field_12;
|
||||
uint8_t field_13;
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
};
|
||||
|
||||
Bullet BulletList[kMaxBullets];
|
||||
short nBulletEnemy[kMaxBullets];
|
||||
int nBulletsFree;
|
||||
int lasthitz, lasthitx, lasthity;
|
||||
short lasthitsect, lasthitsprite, lasthitwall;
|
||||
|
||||
int nBulletCount = 0;
|
||||
short nRadialBullet = 0;
|
||||
|
||||
static SavegameHelper sgh("bullet",
|
||||
SV(BulletFree),
|
||||
SA(BulletList),
|
||||
SA(nBulletEnemy),
|
||||
SV(nBulletsFree),
|
||||
SV(lasthitz),
|
||||
SV(lasthitx),
|
||||
SV(lasthity),
|
||||
SV(lasthitsect),
|
||||
SV(lasthitsprite),
|
||||
SV(lasthitwall),
|
||||
SV(nBulletCount),
|
||||
SV(nRadialBullet),
|
||||
nullptr);
|
||||
|
||||
|
||||
bulletInfo BulletInfo[] = {
|
||||
{ 25, 1, 20, -1, -1, 13, 0, 0, -1, 0 },
|
||||
{ 25, -1, 65000, -1, 31, 73, 0, 0, -1, 0 },
|
||||
{ 15, -1, 60000, -1, 31, 73, 0, 0, -1, 0 },
|
||||
{ 5, 15, 2000, -1, 14, 38, 4, 5, 3, 0 },
|
||||
{ 250, 100, 2000, -1, 33, 34, 4, 20, -1, 0 },
|
||||
{ 200, -1, 2000, -1, 20, 23, 4, 10, -1, 0 },
|
||||
{ 200, -1, 60000, 68, 68, -1, -1, 0, -1, 0 },
|
||||
{ 300, 1, 0, -1, -1, -1, 0, 50, -1, 0 },
|
||||
{ 18, -1, 2000, -1, 18, 29, 4, 0, -1, 0 },
|
||||
{ 20, -1, 2000, 37, 11, 30, 4, 0, -1, 0 },
|
||||
{ 25, -1, 3000, -1, 44, 36, 4, 15, 90, 0 },
|
||||
{ 30, -1, 1000, -1, 52, 53, 4, 20, 48, 0 },
|
||||
{ 20, -1, 3500, -1, 54, 55, 4, 30, -1, 0 },
|
||||
{ 10, -1, 5000, -1, 57, 76, 4, 0, -1, 0 },
|
||||
{ 40, -1, 1500, -1, 63, 38, 4, 10, 40, 0 },
|
||||
{ 20, -1, 2000, -1, 60, 12, 0, 0, -1, 0 },
|
||||
{ 5, -1, 60000, -1, 31, 76, 0, 0, -1, 0 }
|
||||
};
|
||||
|
||||
|
||||
void InitBullets()
|
||||
{
|
||||
nBulletCount = 0;
|
||||
|
||||
for (int i = 0; i < kMaxBullets; i++) {
|
||||
BulletFree[i] = i;
|
||||
}
|
||||
|
||||
nBulletsFree = kMaxBullets;
|
||||
|
||||
memset(nBulletEnemy, -1, sizeof(nBulletEnemy));
|
||||
}
|
||||
|
||||
short GrabBullet()
|
||||
{
|
||||
nBulletsFree--;
|
||||
return BulletFree[nBulletsFree];
|
||||
}
|
||||
|
||||
void DestroyBullet(short nBullet)
|
||||
{
|
||||
short nSprite = BulletList[nBullet].nSprite;
|
||||
|
||||
runlist_DoSubRunRec(BulletList[nBullet].field_6);
|
||||
runlist_DoSubRunRec(sprite[nSprite].lotag - 1);
|
||||
runlist_SubRunRec(BulletList[nBullet].field_8);
|
||||
|
||||
StopSpriteSound(nSprite);
|
||||
|
||||
mydeletesprite(nSprite);
|
||||
|
||||
BulletFree[nBulletsFree] = nBullet;
|
||||
nBulletsFree++;
|
||||
}
|
||||
|
||||
void IgniteSprite(int nSprite)
|
||||
{
|
||||
sprite[nSprite].hitag += 2;
|
||||
|
||||
int nAnim = BuildAnim(-1, 38, 0, sprite[nSprite].x, sprite[nSprite].y, sprite[nSprite].z, sprite[nSprite].sectnum, 40, 20);//276);
|
||||
short nAnimSprite = GetAnimSprite(nAnim);
|
||||
|
||||
sprite[nAnimSprite].hitag = nSprite;
|
||||
changespritestat(nAnimSprite, kStatIgnited);
|
||||
|
||||
short yRepeat = (tilesiz[sprite[nAnimSprite].picnum].y * 32) / nFlameHeight;
|
||||
if (yRepeat < 1)
|
||||
yRepeat = 1;
|
||||
|
||||
sprite[nAnimSprite].yrepeat = (uint8_t)yRepeat;
|
||||
}
|
||||
|
||||
void BulletHitsSprite(Bullet *pBullet, short nBulletSprite, short nHitSprite, int x, int y, int z, int nSector)
|
||||
{
|
||||
assert(nSector >= 0 && nSector < kMaxSectors);
|
||||
|
||||
bulletInfo *pBulletInfo = &BulletInfo[pBullet->nType];
|
||||
|
||||
short nStat = sprite[nHitSprite].statnum;
|
||||
|
||||
switch (pBullet->nType)
|
||||
{
|
||||
case 3:
|
||||
{
|
||||
if (nStat > 107 || nStat == 98) {
|
||||
return;
|
||||
}
|
||||
|
||||
sprite[nHitSprite].hitag++;
|
||||
|
||||
if (sprite[nHitSprite].hitag == 15) {
|
||||
IgniteSprite(nHitSprite);
|
||||
}
|
||||
|
||||
if (!RandomSize(2)) {
|
||||
BuildAnim(-1, pBulletInfo->field_C, 0, x, y, z, nSector, 40, pBulletInfo->nFlags);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
case 14:
|
||||
{
|
||||
if (nStat > 107 || nStat == 98) {
|
||||
return;
|
||||
}
|
||||
// else - fall through to below cases
|
||||
fallthrough__;
|
||||
}
|
||||
case 1:
|
||||
case 2:
|
||||
case 8:
|
||||
case 9:
|
||||
case 12:
|
||||
case 13:
|
||||
case 15:
|
||||
case 16:
|
||||
{
|
||||
// loc_29E59
|
||||
if (!nStat || nStat > 98) {
|
||||
break;
|
||||
}
|
||||
|
||||
short nSprite = pBullet->nSprite;
|
||||
spritetype *pSprite = &sprite[nSprite];
|
||||
spritetype *pHitSprite = &sprite[nHitSprite];
|
||||
|
||||
if (nStat != 98)
|
||||
{
|
||||
int xVel = pHitSprite->xvel;
|
||||
int yVel = pHitSprite->yvel;
|
||||
|
||||
pHitSprite->xvel = Cos(pSprite->ang) >> 2;
|
||||
pHitSprite->yvel = Sin(pSprite->ang) >> 2;
|
||||
|
||||
MoveCreature(nHitSprite);
|
||||
|
||||
pHitSprite->xvel = xVel;
|
||||
pHitSprite->yvel = yVel;
|
||||
}
|
||||
else
|
||||
{
|
||||
short nAngle = pSprite->ang - (RandomSize(9) - 256);
|
||||
|
||||
pHitSprite->xvel = Cos(nAngle) << 1;
|
||||
pHitSprite->yvel = Sin(nAngle) << 1;
|
||||
pHitSprite->zvel = (-(RandomSize(3) + 1)) << 8;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// BHS_switchBreak:
|
||||
short nDamage = pBulletInfo->nDamage;
|
||||
|
||||
if (pBullet->field_13 > 1) {
|
||||
nDamage *= 2;
|
||||
}
|
||||
|
||||
runlist_DamageEnemy(nHitSprite, nBulletSprite, nDamage);
|
||||
|
||||
if (nStat <= 90 || nStat >= 199)
|
||||
{
|
||||
BuildAnim(-1, pBulletInfo->field_C, 0, x, y, z, nSector, 40, pBulletInfo->nFlags);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (nStat)
|
||||
{
|
||||
case 97:
|
||||
break;
|
||||
case 0:
|
||||
case 98:
|
||||
case 102:
|
||||
case 141:
|
||||
case 152:
|
||||
BuildAnim(-1, 12, 0, x, y, z, nSector, 40, 0);
|
||||
break;
|
||||
default:
|
||||
BuildAnim(-1, 39, 0, x, y, z, nSector, 40, 0);
|
||||
if (pBullet->nType > 2)
|
||||
{
|
||||
BuildAnim(-1, pBulletInfo->field_C, 0, x, y, z, nSector, 40, pBulletInfo->nFlags);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BackUpBullet(int *x, int *y, short nAngle)
|
||||
{
|
||||
*x -= Cos(nAngle) >> 11;
|
||||
*y -= Sin(nAngle) >> 11;
|
||||
}
|
||||
|
||||
int MoveBullet(short nBullet)
|
||||
{
|
||||
short hitsect = -1;
|
||||
short hitwall = -1;
|
||||
short hitsprite = -1;
|
||||
|
||||
Bullet *pBullet = &BulletList[nBullet];
|
||||
short nType = pBullet->nType;
|
||||
bulletInfo *pBulletInfo = &BulletInfo[nType];
|
||||
|
||||
short nSprite = BulletList[nBullet].nSprite;
|
||||
spritetype *pSprite = &sprite[nSprite];
|
||||
|
||||
int x = pSprite->x;
|
||||
int y = pSprite->y;
|
||||
int z = pSprite->z; // ebx
|
||||
short nSectFlag = SectFlag[pSprite->sectnum];
|
||||
|
||||
int x2, y2, z2;
|
||||
|
||||
int nVal;
|
||||
|
||||
if (pBullet->field_10 < 30000)
|
||||
{
|
||||
short nEnemySprite = nBulletEnemy[nBullet];
|
||||
if (nEnemySprite > -1)
|
||||
{
|
||||
if (!(sprite[nEnemySprite].cstat & 0x101))
|
||||
nBulletEnemy[nBullet] = -1;
|
||||
else
|
||||
{
|
||||
nVal = AngleChase(nSprite, nEnemySprite, pBullet->field_10, 0, 16);
|
||||
goto MOVEEND;
|
||||
}
|
||||
}
|
||||
if (nType == 3)
|
||||
{
|
||||
if (pBullet->field_E < 8)
|
||||
{
|
||||
pSprite->xrepeat -= 1;
|
||||
pSprite->yrepeat += 8;
|
||||
|
||||
pBullet->z -= 200;
|
||||
|
||||
if (pSprite->shade < 90) {
|
||||
pSprite->shade += 35;
|
||||
}
|
||||
|
||||
if (pBullet->field_E == 3)
|
||||
{
|
||||
pBullet->nSeq = 45;
|
||||
pBullet->field_2 = 0;
|
||||
pSprite->xrepeat = 40;
|
||||
pSprite->yrepeat = 40;
|
||||
pSprite->shade = 0;
|
||||
pSprite->z += 512;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pSprite->xrepeat += 4;
|
||||
pSprite->yrepeat += 4;
|
||||
}
|
||||
}
|
||||
|
||||
// loc_2A1DD
|
||||
nVal = movesprite(nSprite, pBullet->x, pBullet->y, pBullet->z, pSprite->clipdist >> 1, pSprite->clipdist >> 1, CLIPMASK1);
|
||||
|
||||
MOVEEND:
|
||||
if (nVal)
|
||||
{
|
||||
x2 = pSprite->x;
|
||||
y2 = pSprite->y;
|
||||
z2 = pSprite->z;
|
||||
hitsect = pSprite->sectnum;
|
||||
|
||||
if (nVal & 0x30000)
|
||||
{
|
||||
hitwall = nVal & 0x3FFF;
|
||||
goto HITWALL;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (nVal & 0xc000)
|
||||
{
|
||||
case 0x8000:
|
||||
hitwall = nVal & 0x3FFF;
|
||||
goto HITWALL;
|
||||
case 0xc000:
|
||||
hitsprite = nVal & 0x3FFF;
|
||||
goto HITSPRITE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sprite[nSprite].sectnum may have changed since we set nSectFlag ?
|
||||
short nFlagVal = nSectFlag ^ SectFlag[pSprite->sectnum];
|
||||
if (nFlagVal & kSectUnderwater)
|
||||
{
|
||||
DestroyBullet(nBullet);
|
||||
nVal = 1;
|
||||
}
|
||||
|
||||
if (nVal == 0 && nType != 15 && nType != 3)
|
||||
{
|
||||
AddFlash(sprite[nSprite].sectnum, sprite[nSprite].x, sprite[nSprite].y, sprite[nSprite].z, 0);
|
||||
|
||||
if (sprite[nSprite].pal != 5) {
|
||||
sprite[nSprite].pal = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
nVal = 1;
|
||||
|
||||
if (nBulletEnemy[nBullet] > -1)
|
||||
{
|
||||
hitsprite = nBulletEnemy[nBullet];
|
||||
x2 = sprite[hitsprite].x;
|
||||
y2 = sprite[hitsprite].y;
|
||||
z2 = sprite[hitsprite].z - (GetSpriteHeight(hitsprite) >> 1);
|
||||
hitsect = sprite[hitsprite].sectnum;
|
||||
}
|
||||
else
|
||||
{
|
||||
vec3_t startPos = { x, y, z };
|
||||
hitdata_t hitData;
|
||||
int dz;
|
||||
if (bVanilla)
|
||||
dz = -Sin(pBullet->field_C) * 8;
|
||||
else
|
||||
dz = -pBullet->field_C * 512;
|
||||
hitscan(&startPos, pSprite->sectnum, Cos(pSprite->ang), Sin(pSprite->ang), dz, &hitData, CLIPMASK1);
|
||||
x2 = hitData.pos.x;
|
||||
y2 = hitData.pos.y;
|
||||
z2 = hitData.pos.z;
|
||||
hitsprite = hitData.sprite;
|
||||
hitsect = hitData.sect;
|
||||
hitwall = hitData.wall;
|
||||
}
|
||||
|
||||
lasthitx = x2;
|
||||
lasthity = y2;
|
||||
lasthitz = z2;
|
||||
lasthitsect = hitsect;
|
||||
lasthitwall = hitwall;
|
||||
lasthitsprite = hitsprite;
|
||||
|
||||
if (hitsprite > -1)
|
||||
{
|
||||
HITSPRITE:
|
||||
if (pSprite->pal == 5 && sprite[hitsprite].statnum == 100)
|
||||
{
|
||||
short nPlayer = GetPlayerFromSprite(hitsprite);
|
||||
if (!PlayerList[nPlayer].bIsMummified)
|
||||
{
|
||||
PlayerList[nPlayer].bIsMummified = kTrue;
|
||||
SetNewWeapon(nPlayer, kWeaponMummified);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// assert(hitsect <= kMaxSectors);
|
||||
|
||||
BulletHitsSprite(pBullet, pSprite->owner, hitsprite, x2, y2, z2, hitsect);
|
||||
}
|
||||
}
|
||||
else if (hitwall > -1)
|
||||
{
|
||||
HITWALL:
|
||||
if (wall[hitwall].picnum == kEnergy1)
|
||||
{
|
||||
short nSector = wall[hitwall].nextsector;
|
||||
if (nSector > -1)
|
||||
{
|
||||
short nDamage = BulletInfo[pBullet->nType].nDamage;
|
||||
if (pBullet->field_13 > 1) {
|
||||
nDamage *= 2;
|
||||
}
|
||||
|
||||
short nNormal = GetWallNormal(hitwall) & kAngleMask;
|
||||
|
||||
runlist_DamageEnemy(sector[nSector].extra, nNormal, nDamage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// loc_2A4F5:?
|
||||
if (hitsprite < 0 && hitwall < 0)
|
||||
{
|
||||
if ((SectBelow[hitsect] >= 0 && (SectFlag[SectBelow[hitsect]] & kSectUnderwater)) || SectDepth[hitsect])
|
||||
{
|
||||
pSprite->x = x2;
|
||||
pSprite->y = y2;
|
||||
pSprite->z = z2;
|
||||
BuildSplash(nSprite, hitsect);
|
||||
}
|
||||
else
|
||||
{
|
||||
BuildAnim(-1, pBulletInfo->field_C, 0, x2, y2, z2, hitsect, 40, pBulletInfo->nFlags);
|
||||
}
|
||||
}
|
||||
else if (hitwall >= 0)
|
||||
{
|
||||
BackUpBullet(&x2, &y2, pSprite->ang);
|
||||
|
||||
if (nType != 3 || RandomSize(2) == 0)
|
||||
{
|
||||
int zOffset = RandomSize(8) << 3;
|
||||
|
||||
if (!RandomBit()) {
|
||||
zOffset = -zOffset;
|
||||
}
|
||||
|
||||
// draws bullet puff on walls when they're shot
|
||||
BuildAnim(-1, pBulletInfo->field_C, 0, x2, y2, z2 + zOffset, hitsect, 40, pBulletInfo->nFlags);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pSprite->x = x2;
|
||||
pSprite->y = y2;
|
||||
pSprite->z = z2;
|
||||
|
||||
mychangespritesect(nSprite, hitsect);
|
||||
}
|
||||
|
||||
// loc_2A639:
|
||||
if (BulletInfo[nType].field_10)
|
||||
{
|
||||
nRadialBullet = nType;
|
||||
|
||||
runlist_RadialDamageEnemy(nSprite, pBulletInfo->nDamage, pBulletInfo->field_10);
|
||||
|
||||
nRadialBullet = -1;
|
||||
|
||||
AddFlash(pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, 128);
|
||||
}
|
||||
|
||||
DestroyBullet(nBullet);
|
||||
}
|
||||
|
||||
return nVal;
|
||||
}
|
||||
|
||||
void SetBulletEnemy(short nBullet, short nEnemy)
|
||||
{
|
||||
if (nBullet >= 0) {
|
||||
nBulletEnemy[nBullet] = nEnemy;
|
||||
}
|
||||
}
|
||||
|
||||
int BuildBullet(short nSprite, int nType, int UNUSED(ebx), int UNUSED(ecx), int val1, int nAngle, int val2, int val3)
|
||||
{
|
||||
Bullet sBullet;
|
||||
bulletInfo *pBulletInfo = &BulletInfo[nType];
|
||||
|
||||
if (pBulletInfo->field_4 > 30000)
|
||||
{
|
||||
if (val2 >= 10000)
|
||||
{
|
||||
val2 -= 10000;
|
||||
|
||||
short nTargetSprite = val2;
|
||||
spritetype *pTargetSprite = &sprite[nTargetSprite];
|
||||
|
||||
// assert(sprite[nTargetSprite].sectnum <= kMaxSectors);
|
||||
|
||||
if (pTargetSprite->cstat & 0x101)
|
||||
{
|
||||
sBullet.nType = nType;
|
||||
sBullet.field_13 = val3;
|
||||
|
||||
sBullet.nSprite = insertsprite(sprite[nSprite].sectnum, 200);
|
||||
sprite[sBullet.nSprite].ang = nAngle;
|
||||
|
||||
int nHeight = GetSpriteHeight(nTargetSprite);
|
||||
|
||||
assert(sprite[nTargetSprite].sectnum >= 0 && sprite[nTargetSprite].sectnum < kMaxSectors);
|
||||
|
||||
BulletHitsSprite(&sBullet, nSprite, nTargetSprite, pTargetSprite->x, pTargetSprite->y, pTargetSprite->z - (nHeight >> 1), pTargetSprite->sectnum);
|
||||
mydeletesprite(sBullet.nSprite);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
val2 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!nBulletsFree) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
short nSector;
|
||||
|
||||
if (sprite[nSprite].statnum == 100)
|
||||
{
|
||||
nSector = nPlayerViewSect[GetPlayerFromSprite(nSprite)];
|
||||
}
|
||||
else
|
||||
{
|
||||
nSector = sprite[nSprite].sectnum;
|
||||
}
|
||||
|
||||
short nBulletSprite = insertsprite(nSector, 200);
|
||||
int nHeight = GetSpriteHeight(nSprite);
|
||||
nHeight = nHeight - (nHeight >> 2);
|
||||
|
||||
if (val1 == -1) {
|
||||
val1 = -nHeight;
|
||||
}
|
||||
|
||||
sprite[nBulletSprite].x = sprite[nSprite].x;
|
||||
sprite[nBulletSprite].y = sprite[nSprite].y;
|
||||
sprite[nBulletSprite].z = sprite[nSprite].z;
|
||||
|
||||
// why is this done here???
|
||||
assert(nBulletSprite >= 0 && nBulletSprite < kMaxSprites);
|
||||
|
||||
short nBullet = GrabBullet();
|
||||
Bullet *pBullet = &BulletList[nBullet];
|
||||
|
||||
nBulletEnemy[nBullet] = -1;
|
||||
|
||||
sprite[nBulletSprite].cstat = 0;
|
||||
sprite[nBulletSprite].shade = -64;
|
||||
|
||||
if (pBulletInfo->nFlags & 4) {
|
||||
sprite[nBulletSprite].pal = 4;
|
||||
}
|
||||
else {
|
||||
sprite[nBulletSprite].pal = 0;
|
||||
}
|
||||
|
||||
sprite[nBulletSprite].clipdist = 25;
|
||||
|
||||
short nRepeat = pBulletInfo->xyRepeat;
|
||||
if (nRepeat < 0) {
|
||||
nRepeat = 30;
|
||||
}
|
||||
|
||||
sprite[nBulletSprite].xrepeat = nRepeat;
|
||||
sprite[nBulletSprite].yrepeat = nRepeat;
|
||||
sprite[nBulletSprite].xoffset = 0;
|
||||
sprite[nBulletSprite].yoffset = 0;
|
||||
sprite[nBulletSprite].ang = nAngle;
|
||||
sprite[nBulletSprite].xvel = 0;
|
||||
sprite[nBulletSprite].yvel = 0;
|
||||
sprite[nBulletSprite].zvel = 0;
|
||||
sprite[nBulletSprite].owner = nSprite;
|
||||
sprite[nBulletSprite].lotag = runlist_HeadRun() + 1;
|
||||
sprite[nBulletSprite].extra = -1;
|
||||
sprite[nBulletSprite].hitag = 0;
|
||||
|
||||
// GrabTimeSlot(3);
|
||||
|
||||
pBullet->field_10 = 0;
|
||||
pBullet->field_E = pBulletInfo->field_2;
|
||||
pBullet->field_2 = 0;
|
||||
|
||||
short nSeq;
|
||||
|
||||
if (pBulletInfo->field_8 != -1)
|
||||
{
|
||||
pBullet->field_12 = 0;
|
||||
nSeq = pBulletInfo->field_8;
|
||||
}
|
||||
else
|
||||
{
|
||||
pBullet->field_12 = 1;
|
||||
nSeq = pBulletInfo->nSeq;
|
||||
}
|
||||
|
||||
pBullet->nSeq = nSeq;
|
||||
|
||||
sprite[nBulletSprite].picnum = seq_GetSeqPicnum(nSeq, 0, 0);
|
||||
|
||||
if (nSeq == kSeqBullet) {
|
||||
sprite[nBulletSprite].cstat |= 0x8000;
|
||||
}
|
||||
|
||||
pBullet->field_C = val2;
|
||||
pBullet->nType = nType;
|
||||
pBullet->nSprite = nBulletSprite;
|
||||
pBullet->field_6 = runlist_AddRunRec(sprite[nBulletSprite].lotag - 1, nBullet | 0xB0000);
|
||||
pBullet->field_8 = runlist_AddRunRec(NewRun, nBullet | 0xB0000);
|
||||
pBullet->field_13 = val3;
|
||||
sprite[nBulletSprite].z += val1;
|
||||
|
||||
int var_18;
|
||||
|
||||
nSector = sprite[nBulletSprite].sectnum;
|
||||
|
||||
while (sprite[nBulletSprite].z < sector[nSector].ceilingz)
|
||||
{
|
||||
if (SectAbove[nSector] == -1)
|
||||
{
|
||||
sprite[nBulletSprite].z = sector[nSector].ceilingz;
|
||||
break;
|
||||
}
|
||||
|
||||
nSector = SectAbove[nSector];
|
||||
mychangespritesect(nBulletSprite, nSector);
|
||||
}
|
||||
|
||||
if (val2 < 10000)
|
||||
{
|
||||
var_18 = ((-Sin(val2)) * pBulletInfo->field_4) >> 11;
|
||||
}
|
||||
else
|
||||
{
|
||||
val2 -= 10000;
|
||||
|
||||
short nTargetSprite = val2;
|
||||
|
||||
if ((unsigned int)pBulletInfo->field_4 > 30000)
|
||||
{
|
||||
nBulletEnemy[nBullet] = nTargetSprite;
|
||||
}
|
||||
else
|
||||
{
|
||||
nHeight = GetSpriteHeight(nTargetSprite);
|
||||
|
||||
if (sprite[nTargetSprite].statnum == 100)
|
||||
{
|
||||
nHeight -= nHeight >> 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
nHeight -= nHeight >> 1;
|
||||
}
|
||||
|
||||
int var_20 = sprite[nTargetSprite].z - nHeight;
|
||||
|
||||
int x, y;
|
||||
|
||||
if (nSprite != -1 && sprite[nSprite].statnum != 100)
|
||||
{
|
||||
x = sprite[nTargetSprite].x;
|
||||
y = sprite[nTargetSprite].y;
|
||||
|
||||
if (sprite[nTargetSprite].statnum != 100)
|
||||
{
|
||||
x += (sprite[nTargetSprite].xvel * 20) >> 6;
|
||||
y += (sprite[nTargetSprite].yvel * 20) >> 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
int nPlayer = GetPlayerFromSprite(nTargetSprite);
|
||||
if (nPlayer > -1)
|
||||
{
|
||||
x += nPlayerDX[nPlayer] * 15;
|
||||
y += nPlayerDY[nPlayer] * 15;
|
||||
}
|
||||
}
|
||||
|
||||
x -= sprite[nBulletSprite].x;
|
||||
y -= sprite[nBulletSprite].y;
|
||||
|
||||
nAngle = GetMyAngle(x, y);
|
||||
sprite[nSprite].ang = nAngle;
|
||||
}
|
||||
else
|
||||
{
|
||||
// loc_2ABA3:
|
||||
x = sprite[nTargetSprite].x - sprite[nBulletSprite].x;
|
||||
y = sprite[nTargetSprite].y - sprite[nBulletSprite].y;
|
||||
}
|
||||
|
||||
int nSqrt = lsqrt(y*y + x*x);
|
||||
if ((unsigned int)nSqrt > 0)
|
||||
{
|
||||
var_18 = ((var_20 - sprite[nBulletSprite].z) * pBulletInfo->field_4) / nSqrt;
|
||||
}
|
||||
else
|
||||
{
|
||||
var_18 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pBullet->z = 0;
|
||||
pBullet->x = (sprite[nSprite].clipdist << 2) * Cos(nAngle);
|
||||
pBullet->y = (sprite[nSprite].clipdist << 2) * Sin(nAngle);
|
||||
nBulletEnemy[nBullet] = -1;
|
||||
|
||||
if (MoveBullet(nBullet))
|
||||
{
|
||||
nBulletSprite = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pBullet->field_10 = pBulletInfo->field_4;
|
||||
pBullet->x = (Cos(nAngle) >> 3) * pBulletInfo->field_4;
|
||||
pBullet->y = (Sin(nAngle) >> 3) * pBulletInfo->field_4;
|
||||
pBullet->z = var_18 >> 3;
|
||||
}
|
||||
|
||||
return nBulletSprite | (nBullet << 16);
|
||||
}
|
||||
|
||||
void FuncBullet(int a, int UNUSED(b), int nRun)
|
||||
{
|
||||
short nBullet = RunData[nRun].nVal;
|
||||
assert(nBullet >= 0 && nBullet < kMaxBullets);
|
||||
|
||||
short nSeq = SeqOffsets[BulletList[nBullet].nSeq];
|
||||
short nSprite = BulletList[nBullet].nSprite;
|
||||
|
||||
int nMessage = a & 0x7F0000;
|
||||
|
||||
switch (nMessage)
|
||||
{
|
||||
case 0x20000:
|
||||
{
|
||||
short nFlag = FrameFlag[SeqBase[nSeq] + BulletList[nBullet].field_2];
|
||||
|
||||
seq_MoveSequence(nSprite, nSeq, BulletList[nBullet].field_2);
|
||||
|
||||
if (nFlag & 0x80)
|
||||
{
|
||||
BuildAnim(-1, 45, 0, sprite[nSprite].x, sprite[nSprite].y, sprite[nSprite].z, sprite[nSprite].sectnum, sprite[nSprite].xrepeat, 0);
|
||||
}
|
||||
|
||||
BulletList[nBullet].field_2++;
|
||||
if (BulletList[nBullet].field_2 >= SeqSize[nSeq])
|
||||
{
|
||||
if (!BulletList[nBullet].field_12)
|
||||
{
|
||||
BulletList[nBullet].nSeq = BulletInfo[BulletList[nBullet].nType].nSeq;
|
||||
BulletList[nBullet].field_12++;
|
||||
}
|
||||
|
||||
BulletList[nBullet].field_2 = 0;
|
||||
}
|
||||
|
||||
if (BulletList[nBullet].field_E != -1 && --BulletList[nBullet].field_E == 0)
|
||||
{
|
||||
DestroyBullet(nBullet);
|
||||
}
|
||||
else
|
||||
{
|
||||
MoveBullet(nBullet);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x90000:
|
||||
{
|
||||
short nSprite2 = a & 0xFFFF;
|
||||
tsprite[nSprite2].statnum = 1000;
|
||||
|
||||
if (BulletList[nBullet].nType == 15)
|
||||
{
|
||||
seq_PlotArrowSequence(nSprite2, nSeq, BulletList[nBullet].field_2);
|
||||
}
|
||||
else
|
||||
{
|
||||
seq_PlotSequence(nSprite2, nSeq, BulletList[nBullet].field_2, 0);
|
||||
tsprite[nSprite2].owner = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xA0000:
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
Printf("unknown msg %x for bullet\n", a & 0x7F0000);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
END_PS_NS
|
59
source/exhumed/src/bullet.h
Normal file
59
source/exhumed/src/bullet.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __bullet_h__
|
||||
#define __bullet_h__
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
// 32 bytes
|
||||
struct bulletInfo
|
||||
{
|
||||
short nDamage; // 0
|
||||
short field_2; // 2
|
||||
int field_4; // 4
|
||||
short field_8; // 8
|
||||
short nSeq; // 10
|
||||
short field_C; // 12
|
||||
short nFlags;
|
||||
short field_10; // damage radius?
|
||||
short xyRepeat;
|
||||
char pad[12];
|
||||
};
|
||||
|
||||
extern bulletInfo BulletInfo[];
|
||||
|
||||
extern short nRadialBullet;
|
||||
extern short lasthitsect;
|
||||
extern int lasthitz;
|
||||
extern int lasthitx;
|
||||
extern int lasthity;
|
||||
|
||||
void InitBullets();
|
||||
short GrabBullet();
|
||||
void DestroyBullet(short nRun);
|
||||
int MoveBullet(short nBullet);
|
||||
void SetBulletEnemy(short nBullet, short nEnemy);
|
||||
int BuildBullet(short nSprite, int nType, int ebx, int ecx, int val1, int nAngle, int val2, int val3);
|
||||
void IgniteSprite(int nSprite);
|
||||
void FuncBullet(int, int, int);
|
||||
void BackUpBullet(int *x, int *y, short nAngle);
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
102
source/exhumed/src/cd.cpp
Normal file
102
source/exhumed/src/cd.cpp
Normal file
|
@ -0,0 +1,102 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "build.h"
|
||||
#include "compat.h"
|
||||
#include "baselayer.h"
|
||||
#include "cd.h"
|
||||
#include "sound.h"
|
||||
#include "exhumed.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "z_music.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
extern short word_9AC30;
|
||||
|
||||
int nLastVolumeSet = 0;
|
||||
|
||||
/* TODO
|
||||
|
||||
Currently playing music must keep playing on return to map screen or exit from training level
|
||||
|
||||
*/
|
||||
|
||||
bool playCDtrack(int nTrack, bool bLoop)
|
||||
{
|
||||
if (nTrack < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
StopCD();
|
||||
|
||||
char filename[128];
|
||||
|
||||
// try ogg vorbis now
|
||||
sprintf(filename, "exhumed%02d.ogg", nTrack);
|
||||
Mus_Play(nullptr, filename, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void StartfadeCDaudio()
|
||||
{
|
||||
}
|
||||
|
||||
int StepFadeCDaudio()
|
||||
{
|
||||
if (!CDplaying()) {
|
||||
return 0;
|
||||
}
|
||||
Mus_Stop();
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool CDplaying()
|
||||
{
|
||||
return Mus_IsPlaying();
|
||||
}
|
||||
|
||||
void StopCD()
|
||||
{
|
||||
Mus_Stop();
|
||||
}
|
||||
|
||||
void FadeSong()
|
||||
{
|
||||
}
|
||||
|
||||
int fadecdaudio()
|
||||
{
|
||||
StartfadeCDaudio();
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (!StepFadeCDaudio()) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
WaitTicks(1);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
END_PS_NS
|
31
source/exhumed/src/cd.h
Normal file
31
source/exhumed/src/cd.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __cd_h__
|
||||
#define __cd_h__
|
||||
|
||||
BEGIN_PS_NS
|
||||
bool playCDtrack(int nTrack, bool bLoop);
|
||||
void StartfadeCDaudio();
|
||||
int StepFadeCDaudio();
|
||||
bool CDplaying();
|
||||
void StopCD();
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
233
source/exhumed/src/d_menu.cpp
Normal file
233
source/exhumed/src/d_menu.cpp
Normal file
|
@ -0,0 +1,233 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2016 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 Christoph Oelckers
|
||||
|
||||
This is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#include "ns.h" // Must come before everything else!
|
||||
#include "build.h"
|
||||
#include "osd.h"
|
||||
#include "osd.h"
|
||||
#include "exhumed.h"
|
||||
#include "engine.h"
|
||||
#include "sound.h"
|
||||
#include "names.h"
|
||||
#include "version.h"
|
||||
|
||||
|
||||
#include "menu/menu.h"
|
||||
|
||||
#include "../../glbackend/glbackend.h"
|
||||
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
int handle1;
|
||||
|
||||
|
||||
int MenuExitCondition;
|
||||
int MenuStartCondition;
|
||||
|
||||
int menu_Menu(int nVal)
|
||||
{
|
||||
MenuStartCondition = nVal;
|
||||
MenuExitCondition = -2;
|
||||
M_StartControlPanel(false);
|
||||
M_SetMenu(NAME_MainMenu);
|
||||
while (M_Active())
|
||||
{
|
||||
auto nLogoTile = EXHUMED ? kExhumedLogo : kPowerslaveLogo;
|
||||
int dword_9AB5F = ((int)totalclock / 16) & 3;
|
||||
|
||||
videoClearScreen(blackcol);
|
||||
|
||||
overwritesprite(160, 100, kSkullHead, 32, 3, kPalNormal);
|
||||
overwritesprite(161, 130, kSkullJaw, 32, 3, kPalNormal);
|
||||
|
||||
overwritesprite(160, 40, nLogoTile, 32, 3, kPalNormal);
|
||||
|
||||
// draw the fire urn/lamp thingies
|
||||
overwritesprite(50, 150, kTile3512 + dword_9AB5F, 32, 3, kPalNormal);
|
||||
overwritesprite(270, 150, kTile3512 + ((dword_9AB5F + 2) & 3), 32, 3, kPalNormal);
|
||||
|
||||
HandleAsync();
|
||||
videoNextPage();
|
||||
|
||||
}
|
||||
return MenuExitCondition;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Implements the native looking menu used for the main menu
|
||||
// and the episode/skill selection screens, i.e. the parts
|
||||
// that need to look authentic
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
void menu_DoPlasma();
|
||||
int zoomsize = 0;
|
||||
|
||||
class PSMainMenu : public DListMenu
|
||||
{
|
||||
|
||||
void Init(DMenu* parent, FListMenuDescriptor* desc) override
|
||||
{
|
||||
DListMenu::Init(parent, desc);
|
||||
PlayLocalSound(StaticSound[kSound31], 0);
|
||||
}
|
||||
|
||||
void Ticker()
|
||||
{
|
||||
// handle the menu zoom-in
|
||||
if (zoomsize < 0x10000)
|
||||
{
|
||||
zoomsize += 4096;
|
||||
if (zoomsize >= 0x10000) {
|
||||
zoomsize = 0x10000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PreDraw() override
|
||||
{
|
||||
menu_DoPlasma();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Menu related game interface functions
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void GameInterface::DrawNativeMenuText(int fontnum, int state, double xpos, double ypos, float fontscale, const char* text, int flags)
|
||||
{
|
||||
int tilenum = (int)strtoll(text, nullptr, 0);
|
||||
double y = ypos - tilesiz[tilenum].y / 2;
|
||||
|
||||
int8_t shade;
|
||||
|
||||
if (state == NIT_SelectedState)
|
||||
{ // currently selected menu item
|
||||
shade = Sin((int)totalclock << 4) >> 9;
|
||||
}
|
||||
else if (state == NIT_ActiveState) {
|
||||
shade = 0;
|
||||
}
|
||||
else {
|
||||
shade = 25;
|
||||
}
|
||||
|
||||
picanm[tilenum].xofs = 0;
|
||||
picanm[tilenum].yofs = 0;
|
||||
rotatesprite(160 << 16, int((y + tilesiz[tilenum].y) *65536), zoomsize, 0, tilenum, shade, 0, 2, 0, 0, xdim, ydim);
|
||||
|
||||
// tilesizx is 51
|
||||
// tilesizy is 33
|
||||
|
||||
if (state == NIT_SelectedState)
|
||||
{
|
||||
overwritesprite(62, short(ypos - 12), kMenuCursorTile, 0, 2, kPalNormal);
|
||||
overwritesprite(62 + 146, short(ypos - 12), kMenuCursorTile, 0, 10, kPalNormal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GameInterface::MenuOpened()
|
||||
{
|
||||
GrabPalette();
|
||||
zoomsize = 0;
|
||||
StopAllSounds();
|
||||
StopLocalSound();
|
||||
}
|
||||
|
||||
void GameInterface::MenuSound(EMenuSounds snd)
|
||||
{
|
||||
switch (snd)
|
||||
{
|
||||
case CursorSound:
|
||||
PlayLocalSound(StaticSound[kSound35], 0);
|
||||
break;
|
||||
|
||||
case AdvanceSound:
|
||||
case BackSound:
|
||||
PlayLocalSound(StaticSound[kSound33], 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void GameInterface::MenuClosed()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GameInterface::StartGame(FGameStartup& gs)
|
||||
{
|
||||
MenuExitCondition = gs.Episode; // Gross hack. The main loop needs to be redone for better handling.
|
||||
}
|
||||
|
||||
FSavegameInfo GameInterface::GetSaveSig()
|
||||
{
|
||||
return { SAVESIG_PS, MINSAVEVER_PS, SAVEVER_PS };
|
||||
}
|
||||
|
||||
void GameInterface::DrawCenteredTextScreen(const DVector2& origin, const char* text, int position, bool bg)
|
||||
{
|
||||
if (text)
|
||||
{
|
||||
int height = 11;
|
||||
|
||||
auto lines = FString(text).MakeUpper().Split("\n");
|
||||
int y = position - (height * lines.Size() / 2);
|
||||
for (auto& l : lines)
|
||||
{
|
||||
int width = MyGetStringWidth(l);
|
||||
myprintext(int(origin.X) + 160 - width / 2, int(origin.Y) + y, l, 0);
|
||||
y += height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameInterface::DrawMenuCaption(const DVector2& origin, const char* text)
|
||||
{
|
||||
DrawCenteredTextScreen(origin, text, 10, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
END_PS_NS
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// Class registration
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
static TMenuClassDescriptor<Powerslave::PSMainMenu> _mm("Exhumed.MainMenu");
|
||||
|
||||
void RegisterPSMenus()
|
||||
{
|
||||
menuClasses.Push(&_mm);
|
||||
}
|
67
source/exhumed/src/engine.h
Normal file
67
source/exhumed/src/engine.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __engine_h__
|
||||
#define __engine_h__
|
||||
|
||||
#include "compat.h"
|
||||
#include "build.h"
|
||||
#include "pragmas.h"
|
||||
#include "typedefs.h"
|
||||
#include "trigdat.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
#define kMaxTiles 6144
|
||||
#define kMaxSprites 4096
|
||||
#define kMaxSectors 1024
|
||||
#define kMaxWalls 8192
|
||||
#define kMaxTiles 6144
|
||||
#define kMaxVoxels 4096
|
||||
|
||||
enum
|
||||
{
|
||||
kStatIgnited = 404
|
||||
};
|
||||
|
||||
#define kMaxSpritesOnscreen 1024
|
||||
|
||||
#define kMaxPalookups 256
|
||||
#define kMaxStatus 1024
|
||||
//#define MAXPSKYTILES 256
|
||||
|
||||
inline int Sin(int angle)
|
||||
{
|
||||
return sintable[angle & kAngleMask];
|
||||
}
|
||||
|
||||
inline int Cos(int angle)
|
||||
{
|
||||
return sintable[(angle + 512) & kAngleMask];
|
||||
}
|
||||
|
||||
int movesprite(short spritenum, int dx, int dy, int dz, int ceildist, int flordist, unsigned int clipmask);
|
||||
void overwritesprite(int thex, int they, short tilenum, signed char shade, char stat, char dapalnum);
|
||||
void precache();
|
||||
void resettiming();
|
||||
void printext(int x, int y, const char* buffer, short tilenum, char invisiblecol);
|
||||
void kensetpalette(unsigned char *vgapal);
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
179
source/exhumed/src/enginesubs.cpp
Normal file
179
source/exhumed/src/enginesubs.cpp
Normal file
|
@ -0,0 +1,179 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "engine.h"
|
||||
|
||||
//#include <io.h>
|
||||
//#include <fcntl.h>
|
||||
#include <malloc.h>
|
||||
#include "gamecvars.h"
|
||||
|
||||
// static int globhiz, globloz, globhihit, globlohit;
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
|
||||
void overwritesprite(int thex, int they, short tilenum, signed char shade, char stat, char dapalnum)
|
||||
{
|
||||
#if 0
|
||||
rotatesprite(thex << 16, they << 16, 0x10000, (short)((flags & 8) << 7), tilenum, shade, dapalnum,
|
||||
(char)(((flags & 1 ^ 1) << 4) + (flags & 2) + ((flags & 4) >> 2) + ((flags & 16) >> 2) ^ ((flags & 8) >> 1)),
|
||||
windowx1, windowy1, windowx2, windowy2);
|
||||
#endif
|
||||
// no animation
|
||||
uint8_t animbak = picanm[tilenum].sf;
|
||||
picanm[tilenum].sf = 0;
|
||||
int offx = 0, offy = 0;
|
||||
if (stat & 1)
|
||||
{
|
||||
offx -= tilesiz[tilenum].x>>1;
|
||||
if (stat & 8)
|
||||
offx += picanm[tilenum].xofs;
|
||||
else
|
||||
offx -= picanm[tilenum].xofs;
|
||||
offy -= (tilesiz[tilenum].y>>1)+picanm[tilenum].yofs;
|
||||
}
|
||||
if (stat&8)
|
||||
offx += tilesiz[tilenum].x;
|
||||
if (stat&16)
|
||||
offy += tilesiz[tilenum].y;
|
||||
thex += offx;
|
||||
they += offy;
|
||||
rotatesprite(thex << 16, they << 16, 65536L, (stat & 8) << 7, tilenum, shade, dapalnum,
|
||||
16 + (stat & 2) + ((stat & 4) >> 2) + (((stat & 16) >> 2) ^ ((stat & 8) >> 1)),
|
||||
windowxy1.x, windowxy1.y, windowxy2.x, windowxy2.y);
|
||||
picanm[tilenum].sf = animbak;
|
||||
}
|
||||
|
||||
void permanentwritesprite(int thex, int they, short tilenum, signed char shade, int cx1, int cy1, int cx2, int cy2, char dapalnum)
|
||||
{
|
||||
rotatesprite(thex << 16, they << 16, 65536L, 0, tilenum, shade, dapalnum, 8 + 16, cx1, cy1, cx2, cy2);
|
||||
}
|
||||
|
||||
void resettiming()
|
||||
{
|
||||
numframes = 0L;
|
||||
totalclock = 0L;
|
||||
// TODO totalclocklock = 0L;
|
||||
}
|
||||
|
||||
void kensetpalette(unsigned char *vgapal)
|
||||
{
|
||||
//setbrightness(0, (char*)vgapal, 4 | 2);
|
||||
// TODO
|
||||
Bmemcpy(palette, vgapal, 768);
|
||||
for (auto &i : palette)
|
||||
i <<= 2;
|
||||
videoSetPalette(0, 0, /*4 | */2);
|
||||
#if 0
|
||||
char vesapal[1024];
|
||||
|
||||
for(int i = 0; i < 256; i++)
|
||||
{
|
||||
vesapal[i*4+0] = vgapal[i*3+2];
|
||||
vesapal[i*4+1] = vgapal[i*3+1];
|
||||
vesapal[i*4+2] = vgapal[i*3+0];
|
||||
vesapal[i*4+3] = 0;
|
||||
}
|
||||
#ifndef __WATCOMC__
|
||||
(0L, 256L, vesapal);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static int32_t xdim_to_320_16(int32_t x)
|
||||
{
|
||||
const int32_t screenwidth = scale(240<<16, xdim, ydim);
|
||||
return scale(x, screenwidth, xdim) + (160<<16) - (screenwidth>>1);
|
||||
}
|
||||
|
||||
static int32_t ydim_to_200_16(int32_t y)
|
||||
{
|
||||
y = scale(y, 200<<16, ydim);
|
||||
return divscale16(y - (200<<15), rotatesprite_yxaspect) - rotatesprite_y_offset + (200<<15);
|
||||
}
|
||||
|
||||
static int32_t xdim_from_320_16(int32_t x)
|
||||
{
|
||||
const int32_t screenwidth = scale(240<<16, xdim, ydim);
|
||||
return scale(x + (screenwidth>>1) - (160<<16), xdim, screenwidth);
|
||||
}
|
||||
|
||||
static int32_t ydim_from_200_16(int32_t y)
|
||||
{
|
||||
y = mulscale16(y + rotatesprite_y_offset - (200<<15), rotatesprite_yxaspect) + (200<<15);
|
||||
return scale(y, ydim, 200<<16);
|
||||
}
|
||||
|
||||
void printext(int x, int y, const char *buffer, short tilenum, char UNUSED(invisiblecol))
|
||||
{
|
||||
int i;
|
||||
unsigned char ch;
|
||||
// const int32_t screenwidth = scale(240<<16, xdim, ydim);
|
||||
|
||||
x = xdim_to_320_16(x);
|
||||
y = ydim_to_200_16(y);
|
||||
|
||||
for (i = 0; buffer[i] != 0; i++)
|
||||
{
|
||||
ch = (unsigned char)buffer[i];
|
||||
rotatesprite(x - ((ch & 15) << (3+16)), y - ((ch >> 4) << (3+16)), 65536L, 0, tilenum, 0, 0, 2 + 8 + 16 + 128, xdim_from_320_16(x), ydim_from_200_16(y),
|
||||
xdim_from_320_16(x + (8<<16))-1, ydim_from_200_16(y + (8<<16))-1);
|
||||
x += (8<<16);
|
||||
}
|
||||
}
|
||||
|
||||
void doTileLoad(int i)
|
||||
{
|
||||
tileLoad(i);
|
||||
|
||||
#ifdef USE_OPENGL
|
||||
if (r_precache) PrecacheHardwareTextures(i);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void precache()
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < numsectors; i++)
|
||||
{
|
||||
short j = sector[i].ceilingpicnum;
|
||||
doTileLoad(j);
|
||||
j = sector[i].floorpicnum;
|
||||
doTileLoad(j);
|
||||
}
|
||||
|
||||
for (i = 0; i < numwalls; i++)
|
||||
{
|
||||
short j = wall[i].picnum;
|
||||
doTileLoad(j);
|
||||
}
|
||||
|
||||
for (i = 0; i < kMaxSprites; i++)
|
||||
{
|
||||
if (sprite[i].statnum < kMaxStatus)
|
||||
{
|
||||
short j = sprite[i].picnum;
|
||||
doTileLoad(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
END_PS_NS
|
3519
source/exhumed/src/exhumed.cpp
Normal file
3519
source/exhumed/src/exhumed.cpp
Normal file
File diff suppressed because it is too large
Load diff
300
source/exhumed/src/exhumed.h
Normal file
300
source/exhumed/src/exhumed.h
Normal file
|
@ -0,0 +1,300 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __exhumed_h__
|
||||
#define __exhumed_h__
|
||||
|
||||
#include "compat.h"
|
||||
#include "baselayer.h"
|
||||
#include "v_text.h"
|
||||
#include "printf.h"
|
||||
#include "gamecvars.h"
|
||||
#include "m_argv.h"
|
||||
#include "gamecontrol.h"
|
||||
#include "c_buttons.h"
|
||||
#include <algorithm>
|
||||
#include "tarray.h"
|
||||
#include "save.h"
|
||||
#include "zstring.h"
|
||||
#include "filesystem/filesystem.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
#define kTimerTicks 120
|
||||
|
||||
#ifdef __WATCOMC__
|
||||
void handleevents();
|
||||
#endif
|
||||
|
||||
enum basepal_t {
|
||||
BASEPAL = 0,
|
||||
ANIMPAL,
|
||||
BASEPALCOUNT
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct demo_header
|
||||
{
|
||||
uint8_t nMap;
|
||||
int16_t nWeapons;
|
||||
int16_t nCurrentWeapon;
|
||||
int16_t clip;
|
||||
int16_t items;
|
||||
|
||||
int16_t nHealth;
|
||||
int16_t field_2;
|
||||
int16_t nAction;
|
||||
int16_t nSprite;
|
||||
int16_t bIsMummified;
|
||||
int16_t someNetVal;
|
||||
int16_t invincibility;
|
||||
int16_t nAir;
|
||||
int16_t nSeq;
|
||||
int16_t nMaskAmount;
|
||||
uint16_t keys;
|
||||
int16_t nMagic;
|
||||
uint8_t item[8];
|
||||
int16_t nAmmo[7]; // TODO - kMaxWeapons?
|
||||
int16_t pad[2];
|
||||
int16_t nCurrentWeapon2;
|
||||
int16_t field_3FOUR;
|
||||
int16_t bIsFiring;
|
||||
int16_t field_38;
|
||||
int16_t field_3A;
|
||||
int16_t field_3C;
|
||||
int16_t nRun;
|
||||
|
||||
int16_t nLives;
|
||||
};
|
||||
|
||||
struct demo_input
|
||||
{
|
||||
int32_t moveframes;
|
||||
|
||||
int32_t xVel;
|
||||
int32_t yVel;
|
||||
int16_t nAngle;
|
||||
uint16_t buttons;
|
||||
int16_t nTarget;
|
||||
uint8_t horizon;
|
||||
int8_t nItem;
|
||||
int32_t h;
|
||||
uint8_t i;
|
||||
uint8_t pad[11];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
void ExitGame();
|
||||
void ShutDown(void);
|
||||
void DebugOut(const char *fmt, ...);
|
||||
int ExhumedMain(int argc, char *argv[]);
|
||||
|
||||
void FinishLevel();
|
||||
|
||||
void SetHiRes();
|
||||
|
||||
void BlackOut();
|
||||
|
||||
void DoGameOverScene();
|
||||
|
||||
int Query(short n, short l, ...);
|
||||
|
||||
extern unsigned char curpal[];
|
||||
|
||||
void TintPalette(int a, int b, int c);
|
||||
//void MySetPalette(unsigned char *palette);
|
||||
//void GetCurPal(unsigned char *palette);
|
||||
|
||||
void EraseScreen(int eax);
|
||||
|
||||
void RestorePalette();
|
||||
|
||||
int FindGString(const char *str);
|
||||
|
||||
void WaitTicks(int nTicks);
|
||||
|
||||
void FadeIn();
|
||||
void FadeOut(int bFadeMusic);
|
||||
|
||||
int myprintext(int x, int y, const char *str, int shade);
|
||||
int MyGetStringWidth(const char *str);
|
||||
|
||||
void mychangespritesect(int nSprite, int nSector);
|
||||
void mydeletesprite(int nSprite);
|
||||
|
||||
void GrabPalette();
|
||||
|
||||
void mysetbrightness(char nBrightness);
|
||||
|
||||
void StartFadeIn();
|
||||
int DoFadeIn();
|
||||
|
||||
void InitSpiritHead();
|
||||
|
||||
int CopyCharToBitmap(char nChar, int nTile, int xPos, int yPos);
|
||||
|
||||
// TODO - relocate
|
||||
void StatusMessage(int messageTime, const char *fmt, ...);
|
||||
|
||||
int DoSpiritHead();
|
||||
|
||||
void UpdateScreenSize();
|
||||
|
||||
void HandleAsync();
|
||||
|
||||
extern int32_t g_commandSetup;
|
||||
extern int32_t g_noSetup;
|
||||
|
||||
extern char sHollyStr[];
|
||||
|
||||
extern int localclock;
|
||||
|
||||
extern int moveframes;
|
||||
|
||||
extern short bSerialPlay;
|
||||
|
||||
extern int nNetPlayerCount;
|
||||
|
||||
extern int htimer;
|
||||
|
||||
extern int nNetTime;
|
||||
|
||||
extern short nTotalPlayers;
|
||||
|
||||
extern short nFontFirstChar;
|
||||
extern short nBackgroundPic;
|
||||
extern short nShadowPic;
|
||||
|
||||
extern short nCreaturesLeft;
|
||||
|
||||
extern int lLocalButtons;
|
||||
|
||||
extern short nEnergyTowers;
|
||||
|
||||
extern short nEnergyChan;
|
||||
|
||||
extern short nSpiritSprite;
|
||||
|
||||
extern short bInDemo;
|
||||
|
||||
extern short nFreeze;
|
||||
|
||||
extern short nCurBodyNum;
|
||||
extern short nBodyTotal;
|
||||
|
||||
extern short bSnakeCam;
|
||||
|
||||
extern short levelnum;
|
||||
//extern short nScreenWidth;
|
||||
//extern short nScreenHeight;
|
||||
|
||||
extern short nMapMode;
|
||||
|
||||
extern short nButtonColor;
|
||||
|
||||
extern short nHeadStage;
|
||||
|
||||
extern short lastfps;
|
||||
|
||||
extern int flash;
|
||||
|
||||
extern short bNoCreatures;
|
||||
|
||||
extern short nLocalSpr;
|
||||
extern short levelnew;
|
||||
|
||||
extern short textpages;
|
||||
|
||||
extern short nSnakeCam;
|
||||
|
||||
extern short bHiRes;
|
||||
extern short bCoordinates;
|
||||
extern short bFullScreen;
|
||||
|
||||
extern short bHolly;
|
||||
|
||||
extern short screensize;
|
||||
|
||||
extern int totalmoves;
|
||||
|
||||
extern int lCountDown;
|
||||
|
||||
extern short bSlipMode;
|
||||
|
||||
extern short nItemTextIndex;
|
||||
extern const char* gString[];
|
||||
extern const char* gPSDemoString[];
|
||||
extern const char* gEXDemoString[];
|
||||
|
||||
extern int bVanilla;
|
||||
|
||||
#define POWERSLAVE (g_gameType & GAMEFLAG_POWERSLAVE)
|
||||
#define EXHUMED (g_gameType & GAMEFLAG_EXHUMED)
|
||||
#define ISDEMOVER (g_gameType & GAMEFLAG_SHAREWARE)
|
||||
|
||||
extern double g_frameDelay;
|
||||
|
||||
static inline double calcFrameDelay(int const maxFPS) { return maxFPS > 0 ? (timerGetFreqU64()/(double)maxFPS) : 0.0; }
|
||||
|
||||
enum {
|
||||
kPalNormal = 0,
|
||||
kPalNoDim,
|
||||
kPalTorch,
|
||||
kPalNoTorch,
|
||||
kPalBrite,
|
||||
kPalRedBrite,
|
||||
kPalGreenBrite,
|
||||
kPalNormal2,
|
||||
kPalNoDim2,
|
||||
kPalTorch2,
|
||||
kPalNoTorch2,
|
||||
kPalBrite2
|
||||
};
|
||||
|
||||
extern char g_modDir[BMAX_PATH];
|
||||
|
||||
extern int loaddefinitions_game(const char* fn, int32_t preload);
|
||||
void G_LoadGroupsInDir(const char* dirname);
|
||||
void G_DoAutoload(const char* dirname);
|
||||
|
||||
struct GameInterface : ::GameInterface
|
||||
{
|
||||
int app_main() override;
|
||||
bool validate_hud(int) override { return true; }
|
||||
void set_hud_layout(int size) override {}
|
||||
void set_hud_scale(int size) override {}
|
||||
void DrawNativeMenuText(int fontnum, int state, double xpos, double ypos, float fontscale, const char* text, int flags) override;
|
||||
void MenuOpened() override;
|
||||
void MenuSound(EMenuSounds snd) override;
|
||||
void MenuClosed() override;
|
||||
void StartGame(FGameStartup& gs) override;
|
||||
FSavegameInfo GetSaveSig() override;
|
||||
void DrawCenteredTextScreen(const DVector2& origin, const char* text, int position, bool bg) override;
|
||||
void DrawMenuCaption(const DVector2& origin, const char* text) override;
|
||||
bool LoadGame(FSaveGameNode* sv) override;
|
||||
bool SaveGame(FSaveGameNode* sv) override;
|
||||
bool CanSave() override;
|
||||
|
||||
FString statFPS() override;
|
||||
//GameStats getStats() override;
|
||||
};
|
||||
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
601
source/exhumed/src/fish.cpp
Normal file
601
source/exhumed/src/fish.cpp
Normal file
|
@ -0,0 +1,601 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "fish.h"
|
||||
#include "anims.h"
|
||||
#include "engine.h"
|
||||
#include "sequence.h"
|
||||
#include "random.h"
|
||||
#include "runlist.h"
|
||||
#include "exhumed.h"
|
||||
#include "move.h"
|
||||
#include "trigdat.h"
|
||||
#include "init.h"
|
||||
#include "sound.h"
|
||||
#include <assert.h>
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
#define kMaxFishes 128
|
||||
#define kMaxChunks 128
|
||||
|
||||
short FishSprite = -1;
|
||||
short FishCount = 0;
|
||||
|
||||
static actionSeq ActionSeq[] = {
|
||||
{8, 0},
|
||||
{8, 0},
|
||||
{0, 0},
|
||||
{24, 0},
|
||||
{8, 0},
|
||||
{32, 1},
|
||||
{33, 1},
|
||||
{34, 1},
|
||||
{35, 1},
|
||||
{39, 1}
|
||||
};
|
||||
|
||||
short nChunksFree;
|
||||
|
||||
int nFreeChunk[kMaxChunks] = { 0 };
|
||||
|
||||
struct Fish
|
||||
{
|
||||
short nHealth;
|
||||
short field_2;
|
||||
short nAction;
|
||||
short nSprite;
|
||||
short nTarget;
|
||||
short field_A;
|
||||
short field_C;
|
||||
short field_E;
|
||||
};
|
||||
|
||||
struct Chunk
|
||||
{
|
||||
short nSprite;
|
||||
short field_2;
|
||||
short field_4;
|
||||
short field_6;
|
||||
};
|
||||
|
||||
Fish FishList[kMaxFishes];
|
||||
Chunk FishChunk[kMaxChunks];
|
||||
|
||||
static SavegameHelper sgh("fish",
|
||||
SV(FishSprite),
|
||||
SV(FishCount),
|
||||
SV(nChunksFree),
|
||||
SA(nFreeChunk),
|
||||
SA(FishList),
|
||||
SA(FishChunk),
|
||||
nullptr);
|
||||
|
||||
|
||||
void InitFishes()
|
||||
{
|
||||
FishCount = 0;
|
||||
FishSprite = 1;
|
||||
nChunksFree = kMaxChunks;
|
||||
|
||||
for (int i = 0; i < kMaxChunks; i++) {
|
||||
nFreeChunk[i] = i;
|
||||
}
|
||||
}
|
||||
|
||||
int BuildFishLimb(short nFish, short edx)
|
||||
{
|
||||
if (nChunksFree <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
short nSprite = FishList[nFish].nSprite;
|
||||
|
||||
nChunksFree--;
|
||||
|
||||
int nFree = nFreeChunk[nChunksFree];
|
||||
|
||||
int nSprite2 = insertsprite(sprite[nSprite].sectnum, 99);
|
||||
assert(nSprite2 >= 0 && nSprite2 < kMaxSprites);
|
||||
|
||||
FishChunk[nFree].nSprite = nSprite2;
|
||||
FishChunk[nFree].field_4 = edx + 40;
|
||||
FishChunk[nFree].field_2 = RandomSize(3) % SeqSize[SeqOffsets[kSeqFish] + edx + 40];
|
||||
|
||||
sprite[nSprite2].x = sprite[nSprite].x;
|
||||
sprite[nSprite2].y = sprite[nSprite].y;
|
||||
sprite[nSprite2].z = sprite[nSprite].z;
|
||||
sprite[nSprite2].cstat = 0;
|
||||
sprite[nSprite2].shade = -12;
|
||||
sprite[nSprite2].pal = 0;
|
||||
sprite[nSprite2].xvel = (RandomSize(5) - 16) << 8;
|
||||
sprite[nSprite2].yvel = (RandomSize(5) - 16) << 8;
|
||||
sprite[nSprite2].xrepeat = 64;
|
||||
sprite[nSprite2].yrepeat = 64;
|
||||
sprite[nSprite2].xoffset = 0;
|
||||
sprite[nSprite2].yoffset = 0;
|
||||
sprite[nSprite2].zvel = (-(RandomByte() + 512)) * 2;
|
||||
|
||||
// not sure what's going on here... return value doesn't seem to be used
|
||||
seq_GetSeqPicnum(kSeqFish, FishChunk[nFree].field_4, 0);
|
||||
|
||||
sprite[nSprite2].picnum = edx;
|
||||
sprite[nSprite2].lotag = runlist_HeadRun() + 1;
|
||||
sprite[nSprite2].clipdist = 0;
|
||||
|
||||
// GrabTimeSlot(3);
|
||||
|
||||
sprite[nSprite2].extra = -1;
|
||||
sprite[nSprite2].owner = runlist_AddRunRec(sprite[nSprite2].lotag - 1, nFree | 0x200000);
|
||||
sprite[nSprite2].hitag = runlist_AddRunRec(NewRun, nFree | 0x200000);
|
||||
|
||||
return nFree | 0x200000;
|
||||
}
|
||||
|
||||
void BuildBlood(int x, int y, int z, short nSector)
|
||||
{
|
||||
BuildAnim(-1, kSeqFish, 36, x, y, z, nSector, 75, 128);
|
||||
}
|
||||
|
||||
void FuncFishLimb(int a, int UNUSED(nDamage), int nRun)
|
||||
{
|
||||
short nFish = RunData[nRun].nVal;
|
||||
short nSprite = FishChunk[nFish].nSprite;
|
||||
|
||||
assert(nSprite >= 0 && nSprite < kMaxSprites);
|
||||
|
||||
int nSeq = SeqOffsets[kSeqFish] + FishChunk[nFish].field_4;
|
||||
|
||||
int nMessage = a & 0x7F0000;
|
||||
|
||||
switch (nMessage)
|
||||
{
|
||||
case 0x20000:
|
||||
{
|
||||
sprite[nSprite].picnum = seq_GetSeqPicnum2(nSeq, FishChunk[nFish].field_2);
|
||||
|
||||
Gravity(nSprite);
|
||||
|
||||
FishChunk[nFish].field_2++;
|
||||
|
||||
if (FishChunk[nFish].field_2 >= SeqSize[nSeq])
|
||||
{
|
||||
FishChunk[nFish].field_2 = 0;
|
||||
if (RandomBit()) {
|
||||
BuildBlood(sprite[nSprite].x, sprite[nSprite].y, sprite[nSprite].z, sprite[nSprite].sectnum);
|
||||
}
|
||||
}
|
||||
|
||||
int FloorZ = sector[sprite[nSprite].sectnum].floorz;
|
||||
|
||||
if (FloorZ <= sprite[nSprite].z)
|
||||
{
|
||||
sprite[nSprite].z += 256;
|
||||
|
||||
if ((sprite[nSprite].z - FloorZ) > 25600)
|
||||
{
|
||||
sprite[nSprite].zvel = 0;
|
||||
runlist_DoSubRunRec(sprite[nSprite].owner);
|
||||
runlist_FreeRun(sprite[nSprite].lotag - 1);
|
||||
runlist_SubRunRec(sprite[nSprite].hitag);
|
||||
mydeletesprite(nSprite);
|
||||
}
|
||||
else if ((sprite[nSprite].z - FloorZ) > 0)
|
||||
{
|
||||
sprite[nSprite].zvel = 1024;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (movesprite(nSprite, sprite[nSprite].xvel << 8, sprite[nSprite].yvel << 8, sprite[nSprite].zvel, 2560, -2560, CLIPMASK1))
|
||||
{
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].xvel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x90000:
|
||||
{
|
||||
seq_PlotSequence(a & 0xFFFF, nSeq, FishChunk[nFish].field_2, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int BuildFish(int nSprite, int x, int y, int z, int nSector, int nAngle)
|
||||
{
|
||||
short nFish = FishCount;
|
||||
FishCount++;
|
||||
|
||||
if (nFish >= kMaxFishes) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nSprite == -1)
|
||||
{
|
||||
nSprite = insertsprite(nSector, 103);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = sprite[nSprite].x;
|
||||
y = sprite[nSprite].y;
|
||||
z = sprite[nSprite].z;
|
||||
nAngle = sprite[nSprite].ang;
|
||||
changespritestat(nSprite, 103);
|
||||
}
|
||||
|
||||
assert(nSprite >= 0 && nSprite < kMaxSprites);
|
||||
|
||||
sprite[nSprite].x = x;
|
||||
sprite[nSprite].y = y;
|
||||
sprite[nSprite].z = z;
|
||||
sprite[nSprite].cstat = 0x101;
|
||||
sprite[nSprite].shade = -12;
|
||||
sprite[nSprite].clipdist = 80;
|
||||
sprite[nSprite].xrepeat = 40;
|
||||
sprite[nSprite].yrepeat = 40;
|
||||
sprite[nSprite].pal = sector[sprite[nSprite].sectnum].ceilingpal;
|
||||
sprite[nSprite].xoffset = 0;
|
||||
sprite[nSprite].yoffset = 0;
|
||||
sprite[nSprite].picnum = seq_GetSeqPicnum(kSeqFish, ActionSeq[0].a, 0);
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].zvel = 0;
|
||||
sprite[nSprite].ang = nAngle;
|
||||
sprite[nSprite].lotag = runlist_HeadRun() + 1;
|
||||
sprite[nSprite].hitag = 0;
|
||||
sprite[nSprite].extra = -1;
|
||||
|
||||
// GrabTimeSlot(3);
|
||||
|
||||
FishList[nFish].nAction = 0;
|
||||
FishList[nFish].nHealth = 200;
|
||||
FishList[nFish].nSprite = nSprite;
|
||||
FishList[nFish].nTarget = -1;
|
||||
FishList[nFish].field_C = 60;
|
||||
FishList[nFish].field_2 = 0;
|
||||
|
||||
sprite[nSprite].owner = runlist_AddRunRec(sprite[nSprite].lotag - 1, nFish | 0x120000);
|
||||
FishList[nFish].field_E = runlist_AddRunRec(NewRun, nFish | 0x120000);
|
||||
|
||||
nCreaturesLeft++;
|
||||
|
||||
return nFish | 0x120000;
|
||||
}
|
||||
|
||||
void IdleFish(short nFish, short edx)
|
||||
{
|
||||
short nSprite = FishList[nFish].nSprite;
|
||||
|
||||
sprite[nSprite].ang += (256 - RandomSize(9)) + 1024;
|
||||
sprite[nSprite].ang &= kAngleMask;
|
||||
|
||||
sprite[nSprite].xvel = Cos(sprite[nSprite].ang) >> 8;
|
||||
sprite[nSprite].yvel = Sin(sprite[nSprite].ang) >> 8;
|
||||
|
||||
FishList[nFish].nAction = 0;
|
||||
FishList[nFish].field_2 = 0;
|
||||
|
||||
sprite[nSprite].zvel = RandomSize(9);
|
||||
|
||||
if (!edx)
|
||||
{
|
||||
if (RandomBit()) {
|
||||
sprite[nSprite].zvel = -sprite[nSprite].zvel;
|
||||
}
|
||||
}
|
||||
else if (edx < 0)
|
||||
{
|
||||
sprite[nSprite].zvel = -sprite[nSprite].zvel;
|
||||
}
|
||||
}
|
||||
|
||||
void DestroyFish(short nFish)
|
||||
{
|
||||
short nSprite = FishList[nFish].nSprite;
|
||||
|
||||
runlist_DoSubRunRec(sprite[nSprite].owner);
|
||||
runlist_FreeRun(sprite[nSprite].lotag - 1);
|
||||
runlist_SubRunRec(FishList[nFish].field_E);
|
||||
mydeletesprite(nSprite);
|
||||
}
|
||||
|
||||
void FuncFish(int a, int nDamage, int nRun)
|
||||
{
|
||||
short nFish = RunData[nRun].nVal;
|
||||
assert(nFish >= 0 && nFish < kMaxFishes);
|
||||
|
||||
short nSprite = FishList[nFish].nSprite;
|
||||
short nAction = FishList[nFish].nAction;
|
||||
|
||||
int nMessage = a & 0x7F0000;
|
||||
|
||||
switch (nMessage)
|
||||
{
|
||||
default:
|
||||
{
|
||||
Printf("unknown msg %d for Fish\n", a & 0x7F0000);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x90000:
|
||||
{
|
||||
seq_PlotSequence(a & 0xFFFF, SeqOffsets[kSeqFish] + ActionSeq[nAction].a, FishList[nFish].field_2, ActionSeq[nAction].b);
|
||||
tsprite[a & 0xFFFF].owner = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
case 0xA0000:
|
||||
{
|
||||
if (FishList[nFish].nHealth <= 0) {
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
nDamage = runlist_CheckRadialDamage(nSprite);
|
||||
if (!nDamage) {
|
||||
return;
|
||||
}
|
||||
|
||||
FishList[nFish].field_C = 10;
|
||||
}
|
||||
// fall through
|
||||
fallthrough__;
|
||||
}
|
||||
case 0x80000:
|
||||
{
|
||||
if (!nDamage) {
|
||||
return;
|
||||
}
|
||||
|
||||
FishList[nFish].nHealth -= nDamage;
|
||||
if (FishList[nFish].nHealth <= 0)
|
||||
{
|
||||
FishList[nFish].nHealth = 0;
|
||||
nCreaturesLeft--;
|
||||
|
||||
sprite[nSprite].cstat &= 0xFEFE;
|
||||
|
||||
if (nMessage == 0x80000)
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
BuildFishLimb(nFish, i);
|
||||
}
|
||||
|
||||
PlayFXAtXYZ(StaticSound[kSound40], sprite[nSprite].x, sprite[nSprite].y, sprite[nSprite].z, sprite[nSprite].sectnum);
|
||||
DestroyFish(nFish);
|
||||
}
|
||||
else
|
||||
{
|
||||
FishList[nFish].nAction = 9;
|
||||
FishList[nFish].field_2 = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
short nTarget = a & 0xFFFF;
|
||||
if (nTarget >= 0 && sprite[nTarget].statnum < 199)
|
||||
{
|
||||
FishList[nFish].nTarget = nTarget;
|
||||
}
|
||||
|
||||
FishList[nFish].nAction = 4;
|
||||
FishList[nFish].field_2 = 0;
|
||||
FishList[nFish].field_C += 10;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x20000:
|
||||
{
|
||||
if (!(SectFlag[sprite[nSprite].sectnum] & kSectUnderwater))
|
||||
{
|
||||
Gravity(nSprite);
|
||||
}
|
||||
|
||||
short nSeq = SeqOffsets[kSeqFish] + ActionSeq[nAction].a;
|
||||
|
||||
sprite[nSprite].picnum = seq_GetSeqPicnum2(nSeq, FishList[nFish].field_2);
|
||||
|
||||
seq_MoveSequence(nSprite, nSeq, FishList[nFish].field_2);
|
||||
|
||||
FishList[nFish].field_2++;
|
||||
if (FishList[nFish].field_2 >= SeqSize[nSeq]) {
|
||||
FishList[nFish].field_2 = 0;
|
||||
}
|
||||
|
||||
short nTarget = FishList[nFish].nTarget;
|
||||
|
||||
switch (nAction)
|
||||
{
|
||||
default:
|
||||
return;
|
||||
|
||||
case 0:
|
||||
{
|
||||
FishList[nFish].field_C--;
|
||||
if (FishList[nFish].field_C <= 0)
|
||||
{
|
||||
nTarget = FindPlayer(nSprite, 60);
|
||||
if (nTarget >= 0)
|
||||
{
|
||||
FishList[nFish].nTarget = nTarget;
|
||||
FishList[nFish].nAction = 2;
|
||||
FishList[nFish].field_2 = 0;
|
||||
|
||||
int nAngle = GetMyAngle(sprite[nTarget].x - sprite[nSprite].x, sprite[nTarget].z - sprite[nSprite].z);
|
||||
sprite[nSprite].zvel = Sin(nAngle) >> 5;
|
||||
|
||||
FishList[nFish].field_C = RandomSize(6) + 90;
|
||||
}
|
||||
else
|
||||
{
|
||||
IdleFish(nFish, 0);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 1:
|
||||
return;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
{
|
||||
FishList[nFish].field_C--;
|
||||
if (FishList[nFish].field_C <= 0)
|
||||
{
|
||||
IdleFish(nFish, 0);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
PlotCourseToSprite(nSprite, nTarget);
|
||||
int nHeight = GetSpriteHeight(nSprite) >> 1;
|
||||
|
||||
int z = sprite[nTarget].z - sprite[nSprite].z;
|
||||
|
||||
if (z < 0) {
|
||||
z = -z;
|
||||
}
|
||||
|
||||
if (z <= nHeight)
|
||||
{
|
||||
sprite[nSprite].xvel = (Sin(sprite[nSprite].ang + 512) >> 5) - (Sin(sprite[nSprite].ang + 512) >> 7);
|
||||
sprite[nSprite].yvel = (Sin(sprite[nSprite].ang) >> 5) - (Sin(sprite[nSprite].ang) >> 7);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].xvel = 0;
|
||||
}
|
||||
|
||||
sprite[nSprite].zvel = (sprite[nTarget].z - sprite[nSprite].z) >> 3;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
if (FishList[nFish].field_2 == 0)
|
||||
{
|
||||
IdleFish(nFish, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case 8:
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
case 9:
|
||||
{
|
||||
if (FishList[nFish].field_2 == 0)
|
||||
{
|
||||
DestroyFish(nFish);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int x = sprite[nSprite].x;
|
||||
int y = sprite[nSprite].y;
|
||||
int z = sprite[nSprite].z;
|
||||
short nSector = sprite[nSprite].sectnum;
|
||||
|
||||
// loc_2EF54
|
||||
int nVal = movesprite(nSprite, sprite[nSprite].xvel << 13, sprite[nSprite].yvel << 13, sprite[nSprite].zvel << 2, 0, 0, CLIPMASK0);
|
||||
|
||||
if (!(SectFlag[sprite[nSprite].sectnum] & kSectUnderwater))
|
||||
{
|
||||
mychangespritesect(nSprite, nSector);
|
||||
sprite[nSprite].x = x;
|
||||
sprite[nSprite].y = y;
|
||||
sprite[nSprite].z = z;
|
||||
|
||||
IdleFish(nFish, 0);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nAction >= 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!nVal)
|
||||
{
|
||||
if (nAction == 3)
|
||||
{
|
||||
FishList[nFish].nAction = 2;
|
||||
FishList[nFish].field_2 = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if ((nVal & 0x30000) == 0)
|
||||
{
|
||||
if ((nVal & 0xC000) == 0x8000)
|
||||
{
|
||||
IdleFish(nFish, 0);
|
||||
}
|
||||
else if ((nVal & 0xC000) == 0xC000)
|
||||
{
|
||||
if (sprite[nVal & 0x3FFF].statnum == 100)
|
||||
{
|
||||
FishList[nFish].nTarget = nVal & 0x3FFF;
|
||||
sprite[nSprite].ang = GetMyAngle(sprite[nTarget].x - sprite[nSprite].x, sprite[nTarget].y - sprite[nSprite].y);
|
||||
|
||||
if (nAction != 3)
|
||||
{
|
||||
FishList[nFish].nAction = 3;
|
||||
FishList[nFish].field_2 = 0;
|
||||
}
|
||||
|
||||
if (!FishList[nFish].field_2)
|
||||
{
|
||||
runlist_DamageEnemy(nTarget, nSprite, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (nVal & 0x20000)
|
||||
{
|
||||
IdleFish(nFish, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
IdleFish(nFish, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
END_PS_NS
|
32
source/exhumed/src/fish.h
Normal file
32
source/exhumed/src/fish.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __fish_h__
|
||||
#define __fish_h__
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
void InitFishes();
|
||||
int BuildFish(int nSprite, int x, int y, int z, int nSector, int nAngle);
|
||||
|
||||
void FuncFish(int, int, int);
|
||||
void FuncFishLimb(int a, int b, int c);
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
446
source/exhumed/src/grenade.cpp
Normal file
446
source/exhumed/src/grenade.cpp
Normal file
|
@ -0,0 +1,446 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "grenade.h"
|
||||
#include "engine.h"
|
||||
#include "player.h"
|
||||
#include "runlist.h"
|
||||
#include "exhumed.h"
|
||||
#include "sound.h"
|
||||
#include "move.h"
|
||||
#include "init.h"
|
||||
#include "bullet.h"
|
||||
#include "gun.h"
|
||||
#include "anims.h"
|
||||
#include "lighting.h"
|
||||
#include "sequence.h"
|
||||
#include "random.h"
|
||||
#include <assert.h>
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
int nGrenadeCount = 0;
|
||||
int nGrenadesFree;
|
||||
|
||||
short GrenadeFree[kMaxGrenades];
|
||||
|
||||
struct Grenade
|
||||
{
|
||||
short field_0;
|
||||
short field_2;
|
||||
short nSprite;
|
||||
short field_6;
|
||||
short field_8;
|
||||
short field_A;
|
||||
short field_C;
|
||||
short field_E;
|
||||
int field_10;
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
Grenade GrenadeList[kMaxGrenades];
|
||||
|
||||
static SavegameHelper sgh("grenade",
|
||||
SV(nGrenadeCount),
|
||||
SV(nGrenadesFree),
|
||||
SA(GrenadeFree),
|
||||
SA(GrenadeList),
|
||||
nullptr);
|
||||
|
||||
|
||||
void InitGrenades()
|
||||
{
|
||||
nGrenadeCount = 0;
|
||||
|
||||
for (int i = 0; i < kMaxGrenades; i++) {
|
||||
GrenadeFree[i] = i;
|
||||
}
|
||||
|
||||
nGrenadesFree = kMaxGrenades;
|
||||
}
|
||||
|
||||
short GrabGrenade()
|
||||
{
|
||||
return GrenadeFree[--nGrenadesFree];
|
||||
}
|
||||
|
||||
void DestroyGrenade(short nGrenade)
|
||||
{
|
||||
runlist_DoSubRunRec(GrenadeList[nGrenade].field_6);
|
||||
runlist_SubRunRec(GrenadeList[nGrenade].field_8);
|
||||
runlist_DoSubRunRec(sprite[GrenadeList[nGrenade].nSprite].lotag - 1);
|
||||
|
||||
mydeletesprite(GrenadeList[nGrenade].nSprite);
|
||||
GrenadeFree[nGrenadesFree] = nGrenade;
|
||||
|
||||
nGrenadesFree++;
|
||||
}
|
||||
|
||||
void BounceGrenade(short nGrenade, short nAngle)
|
||||
{
|
||||
GrenadeList[nGrenade].field_10 >>= 1;
|
||||
|
||||
GrenadeList[nGrenade].x = (Sin(nAngle + 512) >> 5) * GrenadeList[nGrenade].field_10;
|
||||
GrenadeList[nGrenade].y = (Sin(nAngle) >> 5) * GrenadeList[nGrenade].field_10;
|
||||
|
||||
D3PlayFX(StaticSound[kSound3], GrenadeList[nGrenade].nSprite);
|
||||
}
|
||||
|
||||
int ThrowGrenade(short nPlayer, int UNUSED(edx), int UNUSED(ebx), int ecx, int push1)
|
||||
{
|
||||
if (nPlayerGrenade[nPlayer] < 0)
|
||||
return -1;
|
||||
|
||||
short nGrenade = nPlayerGrenade[nPlayer];
|
||||
|
||||
short nGrenadeSprite = GrenadeList[nGrenade].nSprite;
|
||||
short nPlayerSprite = PlayerList[nPlayer].nSprite;
|
||||
|
||||
short nAngle = sprite[nPlayerSprite].ang;
|
||||
|
||||
mychangespritesect(nGrenadeSprite, nPlayerViewSect[nPlayer]);
|
||||
|
||||
sprite[nGrenadeSprite].x = sprite[nPlayerSprite].x;
|
||||
sprite[nGrenadeSprite].y = sprite[nPlayerSprite].y;
|
||||
sprite[nGrenadeSprite].z = sprite[nPlayerSprite].z;
|
||||
|
||||
if (nAngle < 0) {
|
||||
nAngle = sprite[nPlayerSprite].ang;
|
||||
}
|
||||
|
||||
sprite[nGrenadeSprite].cstat &= 0x7FFF;
|
||||
sprite[nGrenadeSprite].ang = nAngle;
|
||||
|
||||
if (push1 >= -3000)
|
||||
{
|
||||
int nVel = totalvel[nPlayer] << 5;
|
||||
|
||||
GrenadeList[nGrenade].field_10 = ((90 - GrenadeList[nGrenade].field_E) * (90 - GrenadeList[nGrenade].field_E)) + nVel;
|
||||
sprite[nGrenadeSprite].zvel = (-64 * push1) - 4352;
|
||||
|
||||
int nMov = movesprite(nGrenadeSprite, Sin(nAngle + 512) * (sprite[nPlayerSprite].clipdist << 3), Sin(nAngle) * (sprite[nPlayerSprite].clipdist << 3), ecx, 0, 0, CLIPMASK1);
|
||||
if (nMov & 0x8000)
|
||||
{
|
||||
nAngle = GetWallNormal(nMov & 0x3FFF);
|
||||
BounceGrenade(nGrenade, nAngle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
GrenadeList[nGrenade].field_10 = 0;
|
||||
sprite[nGrenadeSprite].zvel = sprite[nPlayerSprite].zvel;
|
||||
}
|
||||
|
||||
GrenadeList[nGrenade].x = Sin(nAngle + 512) >> 4;
|
||||
GrenadeList[nGrenade].x *= GrenadeList[nGrenade].field_10;
|
||||
|
||||
GrenadeList[nGrenade].y = Sin(nAngle) >> 4;
|
||||
GrenadeList[nGrenade].y *= GrenadeList[nGrenade].field_10;
|
||||
|
||||
nPlayerGrenade[nPlayer] = -1;
|
||||
|
||||
return nGrenadeSprite;
|
||||
}
|
||||
|
||||
int BuildGrenade(int nPlayer)
|
||||
{
|
||||
if (nGrenadesFree == 0)
|
||||
return -1;
|
||||
|
||||
int nGrenade = GrabGrenade();
|
||||
|
||||
int nSprite = insertsprite(nPlayerViewSect[nPlayer], 201);
|
||||
assert(nSprite >= 0 && nSprite < kMaxSprites);
|
||||
|
||||
int nPlayerSprite = PlayerList[nPlayer].nSprite;
|
||||
|
||||
sprite[nSprite].x = sprite[nPlayerSprite].x;
|
||||
sprite[nSprite].y = sprite[nPlayerSprite].y;
|
||||
sprite[nSprite].z = sprite[nPlayerSprite].z - 3840;
|
||||
sprite[nSprite].shade = -64;
|
||||
sprite[nSprite].xrepeat = 20;
|
||||
sprite[nSprite].yrepeat = 20;
|
||||
sprite[nSprite].cstat = 0x8000u;
|
||||
sprite[nSprite].picnum = 1;
|
||||
sprite[nSprite].pal = 0;
|
||||
sprite[nSprite].clipdist = 30;
|
||||
sprite[nSprite].xoffset = 0;
|
||||
sprite[nSprite].yoffset = 0;
|
||||
sprite[nSprite].ang = sprite[nPlayerSprite].ang;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].owner = nPlayerSprite;
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].zvel = 0;
|
||||
sprite[nSprite].hitag = 0;
|
||||
sprite[nSprite].lotag = runlist_HeadRun() + 1;
|
||||
sprite[nSprite].extra = -1;
|
||||
|
||||
// GrabTimeSlot(3);
|
||||
|
||||
GrenadeList[nGrenade].field_E = 90;
|
||||
GrenadeList[nGrenade].field_2 = 0;
|
||||
GrenadeList[nGrenade].field_0 = 16;
|
||||
GrenadeList[nGrenade].field_10 = -1;
|
||||
GrenadeList[nGrenade].nSprite = nSprite;
|
||||
GrenadeList[nGrenade].field_A = 0;
|
||||
GrenadeList[nGrenade].field_C = 0;
|
||||
GrenadeList[nGrenade].field_6 = runlist_AddRunRec(sprite[nSprite].lotag - 1, nGrenade | 0x0F0000);
|
||||
GrenadeList[nGrenade].field_8 = runlist_AddRunRec(NewRun, nGrenade | 0x0F0000);
|
||||
|
||||
nGrenadePlayer[nGrenade] = nPlayer;
|
||||
nPlayerGrenade[nPlayer] = nGrenade;
|
||||
|
||||
return nSprite;
|
||||
}
|
||||
|
||||
void ExplodeGrenade(short nGrenade)
|
||||
{
|
||||
int var_28, var_20;
|
||||
|
||||
short nPlayer = nGrenadePlayer[nGrenade];
|
||||
int nGrenadeSprite = GrenadeList[nGrenade].nSprite;
|
||||
short nGrenadeSect = sprite[nGrenadeSprite].sectnum;
|
||||
|
||||
GrenadeList[nGrenade].field_C = 1;
|
||||
|
||||
if (SectFlag[nGrenadeSect] & kSectUnderwater)
|
||||
{
|
||||
var_28 = 75;
|
||||
var_20 = 60;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sprite[nGrenadeSprite].z < sector[nGrenadeSect].floorz)
|
||||
{
|
||||
var_20 = 200;
|
||||
var_28 = 36;
|
||||
|
||||
// TODO MonoOut("GRENPOW\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
var_28 = 34;
|
||||
var_20 = 150;
|
||||
|
||||
// TODO MonoOut("GRENBOOM\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (GrenadeList[nGrenade].field_10 < 0)
|
||||
{
|
||||
short nPlayerSprite = PlayerList[nPlayer].nSprite;
|
||||
short nAngle = sprite[nPlayerSprite].ang;
|
||||
|
||||
sprite[nGrenadeSprite].z = sprite[nPlayerSprite].z;
|
||||
sprite[nGrenadeSprite].x = (Sin(nAngle + 512) >> 5) + sprite[nPlayerSprite].x;
|
||||
sprite[nGrenadeSprite].y = (Sin(nAngle) >> 5) + sprite[nPlayerSprite].y;
|
||||
|
||||
changespritesect(nGrenadeSprite, sprite[nPlayerSprite].sectnum);
|
||||
|
||||
if (!PlayerList[nPlayer].invincibility) {
|
||||
PlayerList[nPlayer].nHealth = 1;
|
||||
}
|
||||
}
|
||||
|
||||
short nDamage = BulletInfo[kWeaponGrenade].nDamage;
|
||||
|
||||
if (nPlayerDouble[nPlayer] > 0) {
|
||||
nDamage *= 2;
|
||||
}
|
||||
|
||||
runlist_RadialDamageEnemy(nGrenadeSprite, nDamage, BulletInfo[kWeaponGrenade].field_10);
|
||||
|
||||
BuildAnim(-1, var_28, 0, sprite[nGrenadeSprite].x, sprite[nGrenadeSprite].y, sprite[nGrenadeSprite].z, sprite[nGrenadeSprite].sectnum, var_20, 4);
|
||||
AddFlash(sprite[nGrenadeSprite].sectnum, sprite[nGrenadeSprite].x, sprite[nGrenadeSprite].y, sprite[nGrenadeSprite].z, 128);
|
||||
|
||||
nGrenadePlayer[nGrenade] = -1;
|
||||
DestroyGrenade(nGrenade);
|
||||
}
|
||||
|
||||
void FuncGrenade(int a, int UNUSED(nDamage), int nRun)
|
||||
{
|
||||
short nGrenade = RunData[nRun].nVal;
|
||||
assert(nGrenade >= 0 && nGrenade < kMaxGrenades);
|
||||
|
||||
short nGrenadeSprite = GrenadeList[nGrenade].nSprite;
|
||||
short nSeq;
|
||||
|
||||
if (GrenadeList[nGrenade].field_C)
|
||||
{
|
||||
nSeq = SeqOffsets[kSeqGrenBoom];
|
||||
}
|
||||
else
|
||||
{
|
||||
nSeq = SeqOffsets[kSeqGrenRoll] + GrenadeList[nGrenade].field_A;
|
||||
}
|
||||
|
||||
int nMessage = a & 0x7F0000;
|
||||
|
||||
switch (nMessage)
|
||||
{
|
||||
case 0x90000:
|
||||
{
|
||||
seq_PlotSequence(a & 0xFFFF, nSeq, GrenadeList[nGrenade].field_2 >> 8, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
Printf("unknown msg %d for bullet\n", a & 0x7F0000); // TODO - change 'bullet' to 'grenade' ?
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x20000:
|
||||
{
|
||||
seq_MoveSequence(nGrenadeSprite, nSeq, GrenadeList[nGrenade].field_2 >> 8);
|
||||
sprite[nGrenadeSprite].picnum = seq_GetSeqPicnum2(nSeq, GrenadeList[nGrenade].field_2 >> 8);
|
||||
|
||||
GrenadeList[nGrenade].field_E--;
|
||||
if (!GrenadeList[nGrenade].field_E)
|
||||
{
|
||||
short nPlayer = nGrenadePlayer[nGrenade];
|
||||
|
||||
if (GrenadeList[nGrenade].field_10 < 0)
|
||||
{
|
||||
PlayerList[nPlayer].field_3A = 0;
|
||||
PlayerList[nPlayer].field_3FOUR = 0;
|
||||
|
||||
if (PlayerList[nPlayer].nAmmo[kWeaponGrenade])
|
||||
{
|
||||
PlayerList[nPlayer].bIsFiring = kFalse;
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectNewWeapon(nPlayer);
|
||||
|
||||
PlayerList[nPlayer].nCurrentWeapon = PlayerList[nPlayer].field_38;
|
||||
PlayerList[nPlayer].field_38 = -1;
|
||||
}
|
||||
}
|
||||
|
||||
ExplodeGrenade(nGrenade);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GrenadeList[nGrenade].field_10 < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int ebp = (GrenadeList[nGrenade].field_2 + GrenadeList[nGrenade].field_0) >> 8;
|
||||
|
||||
GrenadeList[nGrenade].field_2 += GrenadeList[nGrenade].field_0;
|
||||
|
||||
if (ebp < 0)
|
||||
{
|
||||
GrenadeList[nGrenade].field_2 += SeqSize[nSeq] << 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ebp >= SeqSize[nSeq])
|
||||
{
|
||||
if (GrenadeList[nGrenade].field_C)
|
||||
{
|
||||
DestroyGrenade(nGrenade);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
GrenadeList[nGrenade].field_2 = GrenadeList[nGrenade].field_C;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (GrenadeList[nGrenade].field_C) {
|
||||
return;
|
||||
}
|
||||
|
||||
int zVel = sprite[nGrenadeSprite].zvel;
|
||||
|
||||
Gravity(nGrenadeSprite);
|
||||
int nMov = movesprite(nGrenadeSprite, GrenadeList[nGrenade].x, GrenadeList[nGrenade].y, sprite[nGrenadeSprite].zvel, sprite[nGrenadeSprite].clipdist >> 1, sprite[nGrenadeSprite].clipdist >> 1, CLIPMASK1);
|
||||
|
||||
if (!nMov)
|
||||
return;
|
||||
|
||||
if (nMov & 0x20000)
|
||||
{
|
||||
if (zVel)
|
||||
{
|
||||
if (SectDamage[sprite[nGrenadeSprite].sectnum] > 0)
|
||||
{
|
||||
ExplodeGrenade(nGrenade);
|
||||
return;
|
||||
}
|
||||
|
||||
GrenadeList[nGrenade].field_0 = (uint8_t)totalmoves; // limit to 8bits?
|
||||
|
||||
D3PlayFX(StaticSound[kSound3], nGrenadeSprite);
|
||||
|
||||
sprite[nGrenadeSprite].zvel = -(zVel >> 1);
|
||||
|
||||
if (sprite[nGrenadeSprite].zvel > -1280)
|
||||
{
|
||||
D3PlayFX(StaticSound[kSound5], nGrenadeSprite);
|
||||
GrenadeList[nGrenade].field_0 = 0;
|
||||
GrenadeList[nGrenade].field_2 = 0;
|
||||
sprite[nGrenadeSprite].zvel = 0;
|
||||
GrenadeList[nGrenade].field_A = 1;
|
||||
}
|
||||
}
|
||||
|
||||
GrenadeList[nGrenade].field_0 = 255 - (RandomByte() * 2);
|
||||
GrenadeList[nGrenade].x -= (GrenadeList[nGrenade].x >> 4);
|
||||
GrenadeList[nGrenade].y -= (GrenadeList[nGrenade].y >> 4);
|
||||
}
|
||||
|
||||
// loc_2CF60:
|
||||
if ((nMov & 0xC000) >= 0x8000)
|
||||
{
|
||||
if ((nMov & 0xC000) <= 0x8000)
|
||||
{
|
||||
BounceGrenade(nGrenade, GetWallNormal(nMov & 0x3FFF));
|
||||
}
|
||||
else if ((nMov & 0xC000) == 0xC000)
|
||||
{
|
||||
BounceGrenade(nGrenade, sprite[nMov & 0x3FFF].ang);
|
||||
}
|
||||
}
|
||||
|
||||
GrenadeList[nGrenade].field_2 = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 0xA0000:
|
||||
{
|
||||
if (nGrenadeSprite != nRadialSpr && !GrenadeList[nGrenade].field_C)
|
||||
{
|
||||
if (runlist_CheckRadialDamage(nGrenadeSprite) > 280)
|
||||
{
|
||||
GrenadeList[nGrenade].field_E = RandomSize(4) + 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
END_PS_NS
|
34
source/exhumed/src/grenade.h
Normal file
34
source/exhumed/src/grenade.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __grenade_h__
|
||||
#define __grenade_h__
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
#define kMaxGrenades 50
|
||||
|
||||
void InitGrenades();
|
||||
int BuildGrenade(int nPlayer);
|
||||
void DestroyGrenade(short nGrenade);
|
||||
int ThrowGrenade(short nPlayer, int edx, int ebx, int ecx, int push1);
|
||||
void FuncGrenade(int, int, int);
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
1128
source/exhumed/src/gun.cpp
Normal file
1128
source/exhumed/src/gun.cpp
Normal file
File diff suppressed because it is too large
Load diff
71
source/exhumed/src/gun.h
Normal file
71
source/exhumed/src/gun.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __gun_h__
|
||||
#define __gun_h__
|
||||
|
||||
#include "compat.h"
|
||||
#include "sequence.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
#define kMaxWeapons 7
|
||||
|
||||
enum
|
||||
{
|
||||
kWeaponSword = 0,
|
||||
kWeaponPistol,
|
||||
kWeaponM60,
|
||||
kWeaponFlamer,
|
||||
kWeaponGrenade,
|
||||
kWeaponStaff,
|
||||
kWeaponRing,
|
||||
kWeaponMummified
|
||||
};
|
||||
|
||||
struct Weapon
|
||||
{
|
||||
short nSeq;
|
||||
short b[12]; // seq offsets?
|
||||
short nAmmoType;
|
||||
short c;
|
||||
short d; // default or min ammo? or ammo used per 'shot' ?
|
||||
short bFireUnderwater;
|
||||
// short pad[15];
|
||||
};
|
||||
|
||||
extern Weapon WeaponInfo[];
|
||||
extern short nTemperature[];
|
||||
|
||||
void RestoreMinAmmo(short nPlayer);
|
||||
void FillWeapons(short nPlayer);
|
||||
void ResetPlayerWeapons(short nPlayer);
|
||||
void InitWeapons();
|
||||
void SetNewWeapon(short nPlayer, short nWeapon);
|
||||
void SetNewWeaponImmediate(short nPlayer, short nWeapon);
|
||||
void SetNewWeaponIfBetter(short nPlayer, short nWeapon);
|
||||
void SelectNewWeapon(short nPlayer);
|
||||
void StopFiringWeapon(short nPlayer);
|
||||
void FireWeapon(short nPlayer);
|
||||
void CheckClip(short nPlayer);
|
||||
void MoveWeapons(short nPlayer);
|
||||
void DrawWeapons(int smooth);
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
952
source/exhumed/src/init.cpp
Normal file
952
source/exhumed/src/init.cpp
Normal file
|
@ -0,0 +1,952 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "compat.h"
|
||||
#include "init.h"
|
||||
#include "runlist.h"
|
||||
#include "switch.h"
|
||||
#include "object.h"
|
||||
#include "aistuff.h"
|
||||
#include "player.h"
|
||||
#include "mummy.h"
|
||||
#include "move.h"
|
||||
#include "ra.h"
|
||||
#include "view.h"
|
||||
#include "runlist.h"
|
||||
#include "engine.h"
|
||||
#include "sound.h"
|
||||
#include "exhumed.h"
|
||||
#include "items.h"
|
||||
#include "light.h"
|
||||
#include "map.h"
|
||||
#include "menu.h"
|
||||
#include "lighting.h"
|
||||
#include "anims.h"
|
||||
#include "ps_input.h"
|
||||
#include "util.h"
|
||||
#include "mapinfo.h"
|
||||
#include "gamecontrol.h"
|
||||
#include "rendering/v_video.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
enum
|
||||
{
|
||||
kTagRamses = 61,
|
||||
};
|
||||
|
||||
ClockTicks ototalclock = 0;
|
||||
|
||||
int initx, inity, initz;
|
||||
short inita, initsect;
|
||||
|
||||
short nCurChunkNum = 0;
|
||||
|
||||
short nBodyGunSprite[50];
|
||||
int movefifoend;
|
||||
int movefifopos;
|
||||
|
||||
short nCurBodyGunNum;
|
||||
|
||||
short SectSoundSect[kMaxSectors] = { 0 };
|
||||
short SectSound[kMaxSectors] = { 0 };
|
||||
short SectFlag[kMaxSectors] = { 0 };
|
||||
int SectDepth[kMaxSectors] = { 0 };
|
||||
int SectAbove[kMaxSectors] = { 0 };
|
||||
short SectDamage[kMaxSectors] = { 0 };
|
||||
short SectSpeed[kMaxSectors] = { 0 };
|
||||
int SectBelow[kMaxSectors] = { 0 };
|
||||
|
||||
|
||||
uint8_t bIsVersion6 = kTrue;
|
||||
|
||||
|
||||
|
||||
|
||||
uint8_t LoadLevel(int nMap)
|
||||
{
|
||||
initspritelists();
|
||||
|
||||
currentLevel = &mapList[nMap];
|
||||
|
||||
// init stuff
|
||||
{
|
||||
StopAllSounds();
|
||||
nCreaturesLeft = 0;
|
||||
nFreeze = 0;
|
||||
nSpiritSprite = -1;
|
||||
|
||||
InitLion();
|
||||
InitRexs();
|
||||
InitSets();
|
||||
InitQueens();
|
||||
InitRoachs();
|
||||
InitWasps();
|
||||
InitRats();
|
||||
InitBullets();
|
||||
InitWeapons();
|
||||
InitGrenades();
|
||||
InitAnims();
|
||||
InitSnakes();
|
||||
InitFishes();
|
||||
InitLights();
|
||||
InitMap();
|
||||
InitBubbles();
|
||||
InitObjects();
|
||||
InitLava();
|
||||
InitPushBlocks();
|
||||
InitAnubis();
|
||||
InitSpider();
|
||||
InitMummy();
|
||||
InitScorp();
|
||||
InitPlayer();
|
||||
InitItems();
|
||||
InitInput();
|
||||
|
||||
if (nMap == kMap20) {
|
||||
InitEnergyTile();
|
||||
}
|
||||
}
|
||||
|
||||
if (nMap > 15)
|
||||
{
|
||||
nSwitchSound = 35;
|
||||
nStoneSound = 23;
|
||||
nElevSound = 51;
|
||||
nStopSound = 35;
|
||||
}
|
||||
else
|
||||
{
|
||||
nSwitchSound = 33;
|
||||
nStoneSound = 23;
|
||||
nElevSound = 23;
|
||||
nStopSound = 66;
|
||||
}
|
||||
|
||||
if (nMap < 0) {
|
||||
return kFalse;
|
||||
}
|
||||
|
||||
vec3_t startPos;
|
||||
int status = engineLoadBoard(currentLevel->fileName, 0, &startPos, &inita, &initsect);
|
||||
if (status == -2)
|
||||
status = engineLoadBoardV5V6(currentLevel->fileName, 0, &startPos, &inita, &initsect);
|
||||
initx = startPos.x;
|
||||
inity = startPos.y;
|
||||
initz = startPos.z;
|
||||
|
||||
#ifdef YAX_ENABLE
|
||||
yax_update(1);
|
||||
#endif
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < kMaxPlayers; i++)
|
||||
{
|
||||
PlayerList[i].nSprite = -1;
|
||||
}
|
||||
|
||||
psky_t* pSky = tileSetupSky(0);
|
||||
|
||||
pSky->tileofs[0] = 0;
|
||||
pSky->tileofs[1] = 0;
|
||||
pSky->tileofs[2] = 0;
|
||||
pSky->tileofs[3] = 0;
|
||||
pSky->yoffs = 256;
|
||||
pSky->lognumtiles = 2;
|
||||
pSky->horizfrac = 65536;
|
||||
pSky->yscale = 65536;
|
||||
parallaxtype = 2;
|
||||
g_visibility = 2048;
|
||||
flash = 0;
|
||||
precache();
|
||||
|
||||
LoadObjects();
|
||||
|
||||
levelnum = nMap;
|
||||
|
||||
return kTrue;
|
||||
}
|
||||
|
||||
void ResetEngine()
|
||||
{
|
||||
SetOverscan(BASEPAL);
|
||||
|
||||
EraseScreen(-1);
|
||||
|
||||
resettiming();
|
||||
|
||||
totalclock = 0;
|
||||
ototalclock = totalclock;
|
||||
localclock = (int)totalclock;
|
||||
|
||||
numframes = 0;
|
||||
}
|
||||
|
||||
void InstallEngine()
|
||||
{
|
||||
// initgroupfile("stuff.dat");
|
||||
TileFiles.LoadArtSet("tiles%03d.art");
|
||||
|
||||
// TEMP
|
||||
|
||||
//nScreenWidth *= 2;
|
||||
//nScreenHeight *= 2;
|
||||
bHiRes = kTrue;
|
||||
// TEMP
|
||||
|
||||
if (engineInit())
|
||||
{
|
||||
G_FatalEngineError();
|
||||
}
|
||||
|
||||
LoadPaletteLookups();
|
||||
V_Init2();
|
||||
|
||||
enginecompatibility_mode = ENGINECOMPATIBILITY_19950829;
|
||||
}
|
||||
|
||||
void RemoveEngine()
|
||||
{
|
||||
engineUnInit();
|
||||
}
|
||||
|
||||
void SetBelow(short nCurSector, short nBelowSector)
|
||||
{
|
||||
SectBelow[nCurSector] = nBelowSector;
|
||||
}
|
||||
|
||||
void SetAbove(short nCurSector, short nAboveSector)
|
||||
{
|
||||
SectAbove[nCurSector] = nAboveSector;
|
||||
}
|
||||
|
||||
void SnapSectors(short nSectorA, short nSectorB, short b)
|
||||
{
|
||||
// edx - nSectorA
|
||||
// eax - nSectorB
|
||||
|
||||
short nWallA = sector[nSectorA].wallptr;
|
||||
short nWallB = sector[nSectorB].wallptr;
|
||||
|
||||
short num1 = sector[nSectorA].wallnum;
|
||||
short num2 = sector[nSectorB].wallnum;
|
||||
|
||||
int nCount = 0;
|
||||
|
||||
while (num1 > nCount)
|
||||
{
|
||||
short dx = nWallB;
|
||||
|
||||
int esi = 0x7FFFFFF;
|
||||
int edi = esi;
|
||||
|
||||
int x = wall[nWallA].x;
|
||||
int y = wall[nWallA].y;
|
||||
|
||||
int var_14 = 0;
|
||||
|
||||
int nCount2 = 0;
|
||||
|
||||
while (nCount2 < num2)
|
||||
{
|
||||
int eax = x - wall[dx].x;
|
||||
int ebx = y - wall[dx].y;
|
||||
|
||||
if (eax < 0) {
|
||||
eax = -eax;
|
||||
}
|
||||
|
||||
int var_38 = eax;
|
||||
|
||||
if (ebx < 0) {
|
||||
ebx = -ebx;
|
||||
}
|
||||
|
||||
int var_3C = ebx;
|
||||
|
||||
var_38 += var_3C;
|
||||
|
||||
eax = esi;
|
||||
if (eax < 0) {
|
||||
eax = -eax;
|
||||
}
|
||||
|
||||
var_3C = eax;
|
||||
|
||||
eax = edi;
|
||||
// int var_34 = edi;
|
||||
if (eax < 0) {
|
||||
eax = -eax;
|
||||
}
|
||||
|
||||
int var_34 = eax;
|
||||
|
||||
var_34 += var_3C;
|
||||
|
||||
if (var_38 < var_34)
|
||||
{
|
||||
esi = x - wall[dx].x;
|
||||
edi = y - wall[dx].y;
|
||||
var_14 = dx;
|
||||
}
|
||||
|
||||
dx++;
|
||||
nCount2++;
|
||||
}
|
||||
|
||||
dragpoint(var_14, wall[var_14].x + esi, wall[var_14].y + edi, 0);
|
||||
|
||||
nCount++;
|
||||
nWallA++;
|
||||
}
|
||||
|
||||
if (b) {
|
||||
sector[nSectorB].ceilingz = sector[nSectorA].floorz;
|
||||
}
|
||||
|
||||
if (SectFlag[nSectorA] & 0x1000) {
|
||||
SnapBobs(nSectorA, nSectorB);
|
||||
}
|
||||
}
|
||||
|
||||
void InitSectFlag()
|
||||
{
|
||||
for (int i = 0; i < kMaxSectors; i++)
|
||||
{
|
||||
SectSoundSect[i] = -1;
|
||||
SectSound[i] = -1;
|
||||
SectAbove[i] = -1;
|
||||
SectBelow[i] = -1;
|
||||
SectDepth[i] = 0;
|
||||
SectFlag[i] = 0;
|
||||
SectSpeed[i] = 0;
|
||||
SectDamage[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessSpriteTag(short nSprite, short lotag, short hitag)
|
||||
{
|
||||
int nChannel = runlist_AllocChannel(hitag % 1000);
|
||||
// int ebp = nChannel;
|
||||
|
||||
// int nHitag2 = hitag / 1000;
|
||||
|
||||
int nLotag2 = lotag / 1000;
|
||||
if (nLotag2 == 0) {
|
||||
nLotag2 = 1;
|
||||
}
|
||||
|
||||
// this value can change in the below code but we also need to retain the original hitag value
|
||||
int nVal = hitag;
|
||||
|
||||
if (lotag >= 900 && lotag <= 949)
|
||||
{
|
||||
ProcessTrailSprite(nSprite, lotag, hitag);
|
||||
return;
|
||||
}
|
||||
|
||||
// handle tags 6 to 60
|
||||
switch (lotag)
|
||||
{
|
||||
case 8: // M-60 ammo belt
|
||||
{
|
||||
nVal = 3 * (hitag / 3);
|
||||
// fall through to 6,7 etc
|
||||
fallthrough__;
|
||||
}
|
||||
case 6:
|
||||
case 7:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 15:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 23:
|
||||
case 24:
|
||||
case 26:
|
||||
case 28:
|
||||
case 29:
|
||||
case 30:
|
||||
case 31:
|
||||
case 32:
|
||||
case 33:
|
||||
case 34:
|
||||
case 35:
|
||||
case 36:
|
||||
case 37:
|
||||
case 39:
|
||||
case 40:
|
||||
case 41:
|
||||
case 42:
|
||||
case 43:
|
||||
case 44:
|
||||
case 45:
|
||||
case 46:
|
||||
case 47:
|
||||
case 48:
|
||||
case 49:
|
||||
case 50:
|
||||
case 51:
|
||||
case 52:
|
||||
case 53:
|
||||
case 54:
|
||||
case 55:
|
||||
case 56:
|
||||
case 57:
|
||||
case 58:
|
||||
case 60:
|
||||
{
|
||||
sprite[nSprite].hitag = nVal;
|
||||
changespritestat(nSprite, lotag + 900);
|
||||
sprite[nSprite].cstat &= 0xFEFE;
|
||||
BuildItemAnim(nSprite);
|
||||
return;
|
||||
}
|
||||
case 12: // berry twig
|
||||
{
|
||||
sprite[nSprite].hitag = 40;
|
||||
changespritestat(nSprite, lotag + 900);
|
||||
sprite[nSprite].cstat &= 0xFEFE;
|
||||
BuildItemAnim(nSprite);
|
||||
return;
|
||||
}
|
||||
case 13: // blood bowl
|
||||
{
|
||||
sprite[nSprite].hitag = 160;
|
||||
changespritestat(nSprite, lotag + 900);
|
||||
sprite[nSprite].cstat &= 0xFEFE;
|
||||
BuildItemAnim(nSprite);
|
||||
return;
|
||||
}
|
||||
case 14: // venom bowl
|
||||
{
|
||||
sprite[nSprite].hitag = -200;
|
||||
changespritestat(nSprite, lotag + 900);
|
||||
sprite[nSprite].cstat &= 0xFEFE;
|
||||
BuildItemAnim(nSprite);
|
||||
return;
|
||||
}
|
||||
|
||||
case 16:
|
||||
// reserved
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
|
||||
case 25:
|
||||
case 59:
|
||||
{
|
||||
// extra life or checkpoint scarab. Delete for multiplayer
|
||||
if (nNetPlayerCount != 0)
|
||||
{
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite[nSprite].hitag = nVal;
|
||||
changespritestat(nSprite, lotag + 900);
|
||||
sprite[nSprite].cstat &= 0xFEFE;
|
||||
BuildItemAnim(nSprite);
|
||||
return;
|
||||
}
|
||||
}
|
||||
case 27:
|
||||
{
|
||||
sprite[nSprite].hitag = 1;
|
||||
changespritestat(nSprite, 9 + 900);
|
||||
sprite[nSprite].cstat &= 0xFEFE;
|
||||
BuildItemAnim(nSprite);
|
||||
return;
|
||||
}
|
||||
|
||||
case 38: // raw energy
|
||||
{
|
||||
nVal++;
|
||||
nVal--; // CHECKME ??
|
||||
sprite[nSprite].hitag = nVal;
|
||||
changespritestat(nSprite, lotag + 900);
|
||||
sprite[nSprite].cstat &= 0xFEFE;
|
||||
BuildItemAnim(nSprite);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int v6 = lotag % 1000;
|
||||
|
||||
if (!bNoCreatures || v6 < 100 || v6 > 118)
|
||||
{
|
||||
if (v6 > 999) {
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (v6)
|
||||
{
|
||||
case 999:
|
||||
{
|
||||
AddFlicker(sprite[nSprite].sectnum, nLotag2);
|
||||
break;
|
||||
}
|
||||
case 998:
|
||||
{
|
||||
AddGlow(sprite[nSprite].sectnum, nLotag2);
|
||||
break;
|
||||
}
|
||||
case 118: // Anubis with drum
|
||||
{
|
||||
if (bNoCreatures) {
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
|
||||
BuildAnubis(nSprite, 0, 0, 0, 0, 0, 1);
|
||||
return;
|
||||
}
|
||||
case 117:
|
||||
{
|
||||
if (bNoCreatures) {
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
|
||||
BuildWasp(nSprite, 0, 0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
case 116:
|
||||
{
|
||||
BuildRat(nSprite, 0, 0, 0, 0, -1);
|
||||
return;
|
||||
}
|
||||
case 115: // Rat (eating)
|
||||
{
|
||||
BuildRat(nSprite, 0, 0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
case 113:
|
||||
{
|
||||
BuildQueen(nSprite, 0, 0, 0, 0, 0, nChannel);
|
||||
return;
|
||||
}
|
||||
case 112:
|
||||
{
|
||||
BuildScorp(nSprite, 0, 0, 0, 0, 0, nChannel);
|
||||
return;
|
||||
}
|
||||
case 111:
|
||||
{
|
||||
if (bNoCreatures) {
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
|
||||
BuildSet(nSprite, 0, 0, 0, 0, 0, nChannel);
|
||||
return;
|
||||
}
|
||||
case 108:
|
||||
{
|
||||
if (bNoCreatures) {
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
|
||||
BuildLava(nSprite, 0, 0, 0, 0, 0, nChannel);
|
||||
return;
|
||||
}
|
||||
case 107:
|
||||
{
|
||||
if (bNoCreatures) {
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
|
||||
BuildRex(nSprite, 0, 0, 0, 0, 0, nChannel);
|
||||
return;
|
||||
}
|
||||
case 106:
|
||||
{
|
||||
if (bNoCreatures) {
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
|
||||
BuildFish(nSprite, 0, 0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
case 105:
|
||||
{
|
||||
if (bNoCreatures) {
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
|
||||
BuildSpider(nSprite, 0, 0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
case 104:
|
||||
{
|
||||
if (bNoCreatures) {
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
|
||||
BuildRoach(1, nSprite, 0, 0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
case 103:
|
||||
{
|
||||
if (bNoCreatures) {
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
|
||||
BuildRoach(0, nSprite, 0, 0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
case 102:
|
||||
{
|
||||
if (bNoCreatures) {
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
|
||||
BuildLion(nSprite, 0, 0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
case 101:
|
||||
{
|
||||
if (bNoCreatures) {
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
|
||||
BuildMummy(nSprite, 0, 0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
case 100:
|
||||
{
|
||||
if (bNoCreatures) {
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
|
||||
BuildAnubis(nSprite, 0, 0, 0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
case 99: // underwater type 2
|
||||
{
|
||||
short nSector = sprite[nSprite].sectnum;
|
||||
SetAbove(nSector, hitag);
|
||||
SectFlag[nSector] |= kSectUnderwater;
|
||||
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
case 98:
|
||||
{
|
||||
short nSector = sprite[nSprite].sectnum;
|
||||
SetBelow(nSector, hitag);
|
||||
SnapSectors(nSector, hitag, 1);
|
||||
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
case 97:
|
||||
{
|
||||
AddSectorBob(sprite[nSprite].sectnum, hitag, 1);
|
||||
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
case 96: // Lava sector
|
||||
{
|
||||
hitag /= 4; // hitag is damage level?
|
||||
if (hitag == 0) {
|
||||
hitag = 1;
|
||||
}
|
||||
|
||||
short nSector = sprite[nSprite].sectnum;
|
||||
|
||||
SectDamage[nSector] = hitag;
|
||||
SectFlag[nSector] |= kSectLava;
|
||||
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
case 95:
|
||||
{
|
||||
AddSectorBob(sprite[nSprite].sectnum, hitag, 0);
|
||||
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
case 94: // water
|
||||
{
|
||||
short nSector = sprite[nSprite].sectnum;
|
||||
SectDepth[nSector] = hitag << 8;
|
||||
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
case 93:
|
||||
{
|
||||
BuildBubbleMachine(nSprite);
|
||||
return;
|
||||
}
|
||||
case 90:
|
||||
{
|
||||
BuildObject(nSprite, 3, hitag);
|
||||
return;
|
||||
}
|
||||
case 79:
|
||||
case 89:
|
||||
{
|
||||
short nSector = sprite[nSprite].sectnum;
|
||||
|
||||
SectSpeed[nSector] = nLotag2;
|
||||
SectFlag[nSector] |= sprite[nSprite].ang;
|
||||
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
case 88:
|
||||
{
|
||||
AddFlow(nSprite, nLotag2, 0);
|
||||
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
case 80: // underwater
|
||||
{
|
||||
short nSector = sprite[nSprite].sectnum;
|
||||
SectFlag[nSector] |= kSectUnderwater;
|
||||
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
case 78:
|
||||
{
|
||||
AddFlow(nSprite, nLotag2, 1);
|
||||
|
||||
short nSector = sprite[nSprite].sectnum;
|
||||
SectFlag[nSector] |= 0x8000;
|
||||
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
case 77:
|
||||
{
|
||||
int nArrow = BuildArrow(nSprite, nLotag2);
|
||||
|
||||
runlist_AddRunRec(sRunChannels[nChannel].a, nArrow);
|
||||
return;
|
||||
}
|
||||
case 76: // Explosion Trigger (Exploding Fire Cauldron)
|
||||
{
|
||||
BuildObject(nSprite, 0, hitag);
|
||||
return;
|
||||
}
|
||||
case 75: // Explosion Target (Cauldrons, fireballs and grenades will destroy nearby 75 sprites)
|
||||
{
|
||||
BuildObject(nSprite, 1, hitag);
|
||||
return;
|
||||
}
|
||||
case 71:
|
||||
{
|
||||
int nFireball = BuildFireBall(nSprite, hitag, nLotag2);
|
||||
|
||||
runlist_AddRunRec(sRunChannels[nChannel].a, nFireball);
|
||||
return;
|
||||
}
|
||||
case 70:
|
||||
{
|
||||
BuildDrip(nSprite);
|
||||
return;
|
||||
}
|
||||
case 63:
|
||||
{
|
||||
changespritestat(nSprite, 405);
|
||||
sprite[nSprite].cstat = 0x8000;
|
||||
return;
|
||||
}
|
||||
case 62:
|
||||
{
|
||||
nNetStartSprite[nNetStartSprites] = nSprite;
|
||||
sprite[nSprite].cstat = 0x8000;
|
||||
|
||||
nNetStartSprites++;
|
||||
return;
|
||||
}
|
||||
case kTagRamses: // Ramses head
|
||||
{
|
||||
nSpiritSprite = nSprite;
|
||||
sprite[nSprite].cstat |= 0x8000;
|
||||
return;
|
||||
}
|
||||
default: // TODO - checkme!
|
||||
{
|
||||
mydeletesprite(nSprite);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mydeletesprite(nSprite);
|
||||
}
|
||||
|
||||
void ExamineSprites()
|
||||
{
|
||||
nNetStartSprites = 0;
|
||||
nCurStartSprite = 0;
|
||||
|
||||
for (int nSprite = 0; nSprite < kMaxSprites; nSprite++)
|
||||
{
|
||||
int nStatus = sprite[nSprite].statnum;
|
||||
if (!nStatus)
|
||||
{
|
||||
short lotag = sprite[nSprite].lotag;
|
||||
short hitag = sprite[nSprite].hitag;
|
||||
|
||||
if ((nStatus < kMaxStatus) && lotag)
|
||||
{
|
||||
sprite[nSprite].lotag = 0;
|
||||
sprite[nSprite].hitag = 0;
|
||||
|
||||
ProcessSpriteTag(nSprite, lotag, hitag);
|
||||
}
|
||||
else
|
||||
{
|
||||
changespritestat(nSprite, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nNetPlayerCount)
|
||||
{
|
||||
int nSprite = insertsprite(initsect, 0);
|
||||
sprite[nSprite].x = initx;
|
||||
sprite[nSprite].y = inity;
|
||||
sprite[nSprite].z = initz;
|
||||
sprite[nSprite].cstat = 0x8000;
|
||||
nNetStartSprite[nNetStartSprites] = nSprite;
|
||||
nNetStartSprites++;
|
||||
}
|
||||
}
|
||||
|
||||
void LoadObjects()
|
||||
{
|
||||
runlist_InitRun();
|
||||
runlist_InitChan();
|
||||
InitLink();
|
||||
InitPoint();
|
||||
InitSlide();
|
||||
InitSwitch();
|
||||
InitElev();
|
||||
InitWallFace();
|
||||
InitTimeSlot();
|
||||
InitSectFlag();
|
||||
|
||||
for (int nSector = 0; nSector < numsectors; nSector++)
|
||||
{
|
||||
short hitag = sector[nSector].hitag;
|
||||
short lotag = sector[nSector].lotag;
|
||||
|
||||
sector[nSector].hitag = 0;
|
||||
sector[nSector].lotag = 0;
|
||||
sector[nSector].extra = -1;
|
||||
|
||||
if (hitag || lotag)
|
||||
{
|
||||
sector[nSector].lotag = runlist_HeadRun() + 1;
|
||||
sector[nSector].hitag = lotag;
|
||||
|
||||
runlist_ProcessSectorTag(nSector, lotag, hitag);
|
||||
}
|
||||
}
|
||||
|
||||
for (int nWall = 0; nWall < numwalls; nWall++)
|
||||
{
|
||||
wall[nWall].extra = -1;
|
||||
|
||||
short lotag = wall[nWall].lotag;
|
||||
short hitag = wall[nWall].hitag;
|
||||
|
||||
wall[nWall].lotag = 0;
|
||||
|
||||
if (hitag || lotag)
|
||||
{
|
||||
wall[nWall].lotag = runlist_HeadRun() + 1;
|
||||
runlist_ProcessWallTag(nWall, lotag, hitag);
|
||||
}
|
||||
}
|
||||
|
||||
ExamineSprites();
|
||||
PostProcess();
|
||||
InitRa();
|
||||
InitChunks();
|
||||
|
||||
for (int nSprite = 0; nSprite < kMaxSprites; nSprite++)
|
||||
{
|
||||
runlist_ChangeChannel(nSprite, 0);
|
||||
runlist_ReadyChannel(nSprite);
|
||||
}
|
||||
|
||||
nCamerax = initx;
|
||||
nCameray = inity;
|
||||
nCameraz = initz;
|
||||
}
|
||||
|
||||
int myloadconfig()
|
||||
{
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int mysaveconfig()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static SavegameHelper sgh("init",
|
||||
SV(initx),
|
||||
SV(inity),
|
||||
SV(initz),
|
||||
SV(inita),
|
||||
SV(initsect),
|
||||
SV(nCurChunkNum),
|
||||
SA(nBodyGunSprite),
|
||||
SV(nCurBodyGunNum),
|
||||
SA(SectSoundSect),
|
||||
SA(SectSound),
|
||||
SA(SectFlag),
|
||||
SA(SectDepth),
|
||||
SA(SectAbove),
|
||||
SA(SectDamage),
|
||||
SA(SectSpeed),
|
||||
SA(SectBelow),
|
||||
nullptr);
|
||||
|
||||
|
||||
END_PS_NS
|
69
source/exhumed/src/init.h
Normal file
69
source/exhumed/src/init.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __init_h__
|
||||
#define __init_h__
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
#define kMap20 20
|
||||
|
||||
enum {
|
||||
kSectUnderwater = 0x2000,
|
||||
kSectLava = 0x4000,
|
||||
};
|
||||
|
||||
extern ClockTicks ototalclock;
|
||||
|
||||
extern int initx;
|
||||
extern int inity;
|
||||
extern int initz;
|
||||
extern short inita;
|
||||
extern short initsect;
|
||||
|
||||
extern short nCurChunkNum;
|
||||
extern short nBodyGunSprite[50];
|
||||
extern int movefifoend;
|
||||
extern int movefifopos;
|
||||
extern short nCurBodyGunNum;
|
||||
|
||||
void SnapSectors(short nSectorA, short nSectorB, short b);
|
||||
|
||||
extern short SectSound[];
|
||||
extern short SectDamage[];
|
||||
extern short SectSpeed[];
|
||||
extern int SectBelow[];
|
||||
extern short SectFlag[];
|
||||
extern int SectDepth[];
|
||||
extern short SectSoundSect[];
|
||||
extern int SectAbove[];
|
||||
|
||||
uint8_t LoadLevel(int nMap);
|
||||
void InstallEngine();
|
||||
void ResetEngine();
|
||||
void RemoveEngine();
|
||||
void LoadObjects();
|
||||
|
||||
int myloadconfig();
|
||||
int mysaveconfig();
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
218
source/exhumed/src/input.cpp
Normal file
218
source/exhumed/src/input.cpp
Normal file
|
@ -0,0 +1,218 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "ps_input.h"
|
||||
#include "engine.h"
|
||||
#include "exhumed.h"
|
||||
#include "player.h"
|
||||
#include "serial.h"
|
||||
#include "network.h"
|
||||
#include <string.h>
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
int nNetMoves = 0;
|
||||
|
||||
short nInputStack = 0;
|
||||
|
||||
short bStackNode[kMaxPlayers];
|
||||
|
||||
short nTypeStack[kMaxPlayers];
|
||||
PlayerInput sPlayerInput[kMaxPlayers];
|
||||
|
||||
int *pStackPtr;
|
||||
|
||||
// (nInputStack * 32) - 11;
|
||||
|
||||
void PushInput(PlayerInput *pInput, int edx)
|
||||
{
|
||||
if (!bStackNode[edx])
|
||||
{
|
||||
// memcpy(sInputStack[nInputStack], pInput,
|
||||
}
|
||||
}
|
||||
|
||||
int PopInput()
|
||||
{
|
||||
if (!nInputStack)
|
||||
return -1;
|
||||
|
||||
nInputStack--;
|
||||
|
||||
// TEMP
|
||||
return 0;
|
||||
}
|
||||
|
||||
void InitInput()
|
||||
{
|
||||
memset(nTypeStack, 0, sizeof(nTypeStack));
|
||||
nInputStack = 0;
|
||||
memset(bStackNode, 0, sizeof(bStackNode));
|
||||
|
||||
// pStackPtr = &sInputStack;
|
||||
}
|
||||
|
||||
void ClearSpaceBar(short nPlayer)
|
||||
{
|
||||
sPlayerInput[nPlayer].buttons &= 0x0FB;
|
||||
buttonMap.ClearButton(gamefunc_Open);
|
||||
}
|
||||
|
||||
void GetLocalInput()
|
||||
{
|
||||
int i;
|
||||
for (i = 6; i >= 0; i--)
|
||||
{
|
||||
if (buttonMap.ButtonDown(gamefunc_Weapon_1+i))
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
|
||||
if (PlayerList[nLocalPlayer].nHealth)
|
||||
{
|
||||
lLocalButtons = (buttonMap.ButtonDown(gamefunc_Crouch) << 4) | (buttonMap.ButtonDown(gamefunc_Fire) << 3)
|
||||
| (buttonMap.ButtonDown(gamefunc_Jump)<<0) | (i<<13);
|
||||
}
|
||||
else
|
||||
{
|
||||
lLocalButtons = 0;
|
||||
}
|
||||
|
||||
lLocalButtons |= buttonMap.ButtonDown(gamefunc_Open) << 2;
|
||||
|
||||
// TODO ExecRecord(&sPlayerInput[nLocalPlayer], sizeof(PlayerInput));
|
||||
}
|
||||
|
||||
void BackupInput()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SendInput()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void LogoffPlayer(int nPlayer)
|
||||
{
|
||||
if (nPlayer == nLocalPlayer)
|
||||
return;
|
||||
|
||||
if (PlayerList[nPlayer].someNetVal == -1)
|
||||
return;
|
||||
|
||||
memset(&sPlayerInput[nPlayer], 0, sizeof(sPlayerInput));
|
||||
|
||||
sprite[nDoppleSprite[nPlayer]].cstat = 0x8000u;
|
||||
sprite[nPlayerFloorSprite[nPlayer]].cstat = 0x8000u;
|
||||
sprite[PlayerList[nPlayer].nSprite].cstat = 0x8000u;
|
||||
|
||||
PlayerList[nPlayer].someNetVal = -1;
|
||||
|
||||
StatusMessage(150, "Player %d has left the game", nPlayer);
|
||||
|
||||
// TODO ClearPlayerInput(&sPlayerInput[nPlayer]);
|
||||
nNetPlayerCount--;
|
||||
}
|
||||
|
||||
void UpdateInputs()
|
||||
{
|
||||
nNetMoveFrames = moveframes;
|
||||
|
||||
if (nNetPlayerCount)
|
||||
{
|
||||
if (bSerialPlay) {
|
||||
UpdateSerialInputs();
|
||||
}
|
||||
else {
|
||||
UpdateNetInputs();
|
||||
}
|
||||
|
||||
nNetMoves++;
|
||||
|
||||
if (!nNetMoves) {
|
||||
nNetMoves++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
ClearSpaceBar_
|
||||
GetLocalInput_
|
||||
GetModemInput_
|
||||
BackupInput_
|
||||
SendInput_
|
||||
SendToUnAckd_
|
||||
LogoffPlayer_
|
||||
UpdateInputs_
|
||||
faketimerhandler_
|
||||
*/
|
||||
|
||||
void ClearAllKeys()
|
||||
{
|
||||
inputState.ClearAllKeyStatus();
|
||||
inputState.keyFlushChars();
|
||||
}
|
||||
|
||||
void WaitNoKey(int nSecs, void (*pFunc) (void))
|
||||
{
|
||||
int nTotalTime = (kTimerTicks * nSecs) + (int)totalclock;
|
||||
|
||||
while (nTotalTime > (int)totalclock)
|
||||
{
|
||||
HandleAsync();
|
||||
if (pFunc) {
|
||||
pFunc();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int WaitAnyKey(int nSecs)
|
||||
{
|
||||
int nTotalTime = (int)totalclock + (kTimerTicks * nSecs);
|
||||
|
||||
while (1)
|
||||
{
|
||||
HandleAsync();
|
||||
if (nTotalTime <= (int)totalclock || nSecs == -1) {
|
||||
return -1;
|
||||
}
|
||||
if (inputState.CheckAllInput()) return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Name: _nLocalPlayer
|
||||
Name: _nNetPlayerCount
|
||||
Name: _nModemPlayer
|
||||
Name: _nNetMoves
|
||||
Name: _lLocalButtons
|
||||
Name: _lLocalCodes
|
||||
Name: _nInputStack
|
||||
Name: _bSyncNet
|
||||
Name: _lStartupTime
|
||||
Name: _bStackNode
|
||||
Name: _sSync
|
||||
Name: _nTypeStack
|
||||
Name: _sPlayerInput
|
||||
Name: _pStackPtr
|
||||
Name: _sInputStack
|
||||
|
||||
*/
|
||||
END_PS_NS
|
506
source/exhumed/src/items.cpp
Normal file
506
source/exhumed/src/items.cpp
Normal file
|
@ -0,0 +1,506 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "items.h"
|
||||
#include "anims.h"
|
||||
#include "player.h"
|
||||
#include "exhumed.h"
|
||||
#include "lighting.h"
|
||||
#include "sound.h"
|
||||
#include "status.h"
|
||||
#include "engine.h"
|
||||
#include "random.h"
|
||||
#include "init.h"
|
||||
#include "ps_input.h"
|
||||
#include "object.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
struct AnimInfo
|
||||
{
|
||||
short a;
|
||||
short repeat;
|
||||
};
|
||||
|
||||
AnimInfo nItemAnimInfo[] = {
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ 6, 64 },
|
||||
{ -1, 48 },
|
||||
{ 0, 64 },
|
||||
{ 1, 64 },
|
||||
{ -1, 32 },
|
||||
{ 4, 64 },
|
||||
{ 5, 64 },
|
||||
{ 16, 64 },
|
||||
{ 10, 64 },
|
||||
{ -1, 32 },
|
||||
{ 8, 64 },
|
||||
{ 9, 64 },
|
||||
{ -1, 40 },
|
||||
{ -1, 32 },
|
||||
{ 7, 64 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ 14, 64 },
|
||||
{ 15, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ 17, 48 },
|
||||
{ 18, 48 },
|
||||
{ 19, 48 },
|
||||
{ 20, 48 },
|
||||
{ 24, 64 },
|
||||
{ 21, 64 },
|
||||
{ 23, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ 11, 30 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 },
|
||||
{ -1, 32 }
|
||||
};
|
||||
|
||||
short nItemMagic[] = { 500, 1000, 100, 500, 400, 200, 700, 0 };
|
||||
|
||||
/*
|
||||
|
||||
short something
|
||||
short x/y repeat
|
||||
|
||||
*/
|
||||
|
||||
short nRegenerates;
|
||||
short nFirstRegenerate;
|
||||
short nMagicCount;
|
||||
|
||||
static SavegameHelper sgh("items",
|
||||
SV(nRegenerates),
|
||||
SV(nFirstRegenerate),
|
||||
SV(nMagicCount),
|
||||
nullptr);
|
||||
|
||||
|
||||
void BuildItemAnim(short nSprite)
|
||||
{
|
||||
int nItem = sprite[nSprite].statnum - 906;
|
||||
|
||||
if (nItemAnimInfo[nItem].a >= 0)
|
||||
{
|
||||
int nAnim = BuildAnim(nSprite, 41, nItemAnimInfo[nItem].a, sprite[nSprite].x, sprite[nSprite].y, sprite[nSprite].z, sprite[nSprite].sectnum, nItemAnimInfo[nItem].repeat, 20);
|
||||
int nAnimSprite = GetAnimSprite(nAnim);
|
||||
|
||||
if (nItem == 44) {
|
||||
sprite[nAnimSprite].cstat |= 2;
|
||||
}
|
||||
|
||||
changespritestat(nAnimSprite, sprite[nSprite].statnum);
|
||||
|
||||
sprite[nAnimSprite].owner = nAnim;
|
||||
sprite[nAnimSprite].hitag = sprite[nSprite].hitag;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite[nSprite].owner = -1;
|
||||
sprite[nSprite].yrepeat = nItemAnimInfo[nItem].repeat;
|
||||
sprite[nSprite].xrepeat = nItemAnimInfo[nItem].repeat;
|
||||
}
|
||||
}
|
||||
|
||||
void DestroyItemAnim(short nSprite)
|
||||
{
|
||||
short nAnim = sprite[nSprite].owner;
|
||||
|
||||
if (nAnim >= 0) {
|
||||
DestroyAnim(nAnim);
|
||||
}
|
||||
}
|
||||
|
||||
void ItemFlash()
|
||||
{
|
||||
TintPalette(16, 16, 16);
|
||||
}
|
||||
|
||||
void FillItems(short nPlayer)
|
||||
{
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
PlayerList[nPlayer].items[i] = 5;
|
||||
}
|
||||
|
||||
PlayerList[nPlayer].nMagic = 1000;
|
||||
|
||||
if (nPlayer == nLocalPlayer)
|
||||
{
|
||||
ItemFlash();
|
||||
SetMagicFrame();
|
||||
}
|
||||
|
||||
if (nPlayerItem[nPlayer] == -1) {
|
||||
SetPlayerItem(nPlayer, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void UseEye(short nPlayer)
|
||||
{
|
||||
if (nPlayerInvisible[nPlayer] >= 0) {
|
||||
nPlayerInvisible[nPlayer] = 900;
|
||||
}
|
||||
|
||||
int nSprite = PlayerList[nPlayer].nSprite;
|
||||
|
||||
sprite[nSprite].cstat |= 0x8000;
|
||||
|
||||
if (nPlayerFloorSprite[nPlayer] >= 0) {
|
||||
sprite[nSprite].cstat |= 0x8000;
|
||||
}
|
||||
|
||||
if (nPlayer == nLocalPlayer)
|
||||
{
|
||||
ItemFlash();
|
||||
D3PlayFX(StaticSound[kSound31], nSprite);
|
||||
}
|
||||
}
|
||||
|
||||
void UseMask(short nPlayer)
|
||||
{
|
||||
PlayerList[nPlayer].nMaskAmount = 1350;
|
||||
PlayerList[nPlayer].nAir = 100;
|
||||
|
||||
if (nPlayer == nLocalPlayer)
|
||||
{
|
||||
SetAirFrame();
|
||||
D3PlayFX(StaticSound[kSound31], PlayerList[nPlayer].nSprite);
|
||||
}
|
||||
}
|
||||
|
||||
void UseTorch(short nPlayer)
|
||||
{
|
||||
if (!nPlayerTorch[nPlayer]) {
|
||||
SetTorch(nPlayer, 1);
|
||||
}
|
||||
|
||||
nPlayerTorch[nPlayer] = 900;
|
||||
}
|
||||
|
||||
void UseHeart(short nPlayer)
|
||||
{
|
||||
if (PlayerList[nPlayer].nHealth < kMaxHealth) {
|
||||
PlayerList[nPlayer].nHealth = kMaxHealth;
|
||||
}
|
||||
|
||||
if (nPlayer == nLocalPlayer)
|
||||
{
|
||||
ItemFlash();
|
||||
SetHealthFrame(1);
|
||||
D3PlayFX(StaticSound[kSound31], PlayerList[nPlayer].nSprite);
|
||||
}
|
||||
}
|
||||
|
||||
// invincibility
|
||||
void UseScarab(short nPlayer)
|
||||
{
|
||||
if (PlayerList[nPlayer].invincibility < 900) {
|
||||
PlayerList[nPlayer].invincibility = 900;
|
||||
}
|
||||
|
||||
if (nPlayer == nLocalPlayer)
|
||||
{
|
||||
ItemFlash();
|
||||
D3PlayFX(StaticSound[kSound31], PlayerList[nPlayer].nSprite);
|
||||
}
|
||||
}
|
||||
|
||||
// faster firing
|
||||
void UseHand(short nPlayer)
|
||||
{
|
||||
nPlayerDouble[nPlayer] = 1350;
|
||||
|
||||
if (nPlayer == nLocalPlayer)
|
||||
{
|
||||
ItemFlash();
|
||||
D3PlayFX(StaticSound[kSound31], PlayerList[nPlayer].nSprite);
|
||||
}
|
||||
}
|
||||
|
||||
void UseItem(short nPlayer, short nItem)
|
||||
{
|
||||
switch (nItem)
|
||||
{
|
||||
case 0:
|
||||
UseHeart(nPlayer);
|
||||
break;
|
||||
case 1:
|
||||
UseScarab(nPlayer);
|
||||
break;
|
||||
case 2:
|
||||
UseTorch(nPlayer);
|
||||
break;
|
||||
case 3:
|
||||
UseHand(nPlayer);
|
||||
break;
|
||||
case 4:
|
||||
UseEye(nPlayer);
|
||||
break;
|
||||
case 5:
|
||||
UseMask(nPlayer);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
PlayerList[nPlayer].items[nItem]--;
|
||||
int nItemCount = PlayerList[nPlayer].items[nItem];
|
||||
|
||||
int nMagic = nItemMagic[nItem];
|
||||
|
||||
if (nPlayer == nLocalPlayer)
|
||||
{
|
||||
BuildStatusAnim(156 + (nItemCount * 2), 0);
|
||||
}
|
||||
|
||||
if (!nItemCount)
|
||||
{
|
||||
for (nItem = 0; nItem < 6; nItem++)
|
||||
{
|
||||
if (PlayerList[nPlayer].items[nItem] > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (nItem == 6) {
|
||||
nItem = -1;
|
||||
}
|
||||
}
|
||||
|
||||
PlayerList[nPlayer].nMagic -= nMagic;
|
||||
SetPlayerItem(nPlayer, nItem);
|
||||
|
||||
if (nPlayer == nLocalPlayer) {
|
||||
SetMagicFrame();
|
||||
}
|
||||
}
|
||||
|
||||
void UseCurItem(short nPlayer)
|
||||
{
|
||||
int nItem = nPlayerItem[nPlayer];
|
||||
|
||||
if (nItem >= 0)
|
||||
{
|
||||
if (PlayerList[nPlayer].items[nItem] > 0)
|
||||
{
|
||||
if (nItemMagic[nItem] <= PlayerList[nPlayer].nMagic)
|
||||
{
|
||||
sPlayerInput[nPlayer].nItem = nItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO - bool return type?
|
||||
int GrabItem(short nPlayer, short nItem)
|
||||
{
|
||||
if (PlayerList[nPlayer].items[nItem] >= 5) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
PlayerList[nPlayer].items[nItem]++;
|
||||
|
||||
if (nPlayerItem[nPlayer] < 0 || nItem == nPlayerItem[nPlayer]) {
|
||||
SetPlayerItem(nPlayer, nItem);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void DropMagic(short nSprite)
|
||||
{
|
||||
if (lFinaleStart) {
|
||||
return;
|
||||
}
|
||||
|
||||
nMagicCount--;
|
||||
|
||||
if (nMagicCount <= 0)
|
||||
{
|
||||
int nAnim = BuildAnim(
|
||||
-1,
|
||||
64,
|
||||
0,
|
||||
sprite[nSprite].x,
|
||||
sprite[nSprite].y,
|
||||
sprite[nSprite].z,
|
||||
sprite[nSprite].sectnum,
|
||||
48,
|
||||
4);
|
||||
|
||||
int nAnimSprite = GetAnimSprite(nAnim);
|
||||
|
||||
sprite[nAnimSprite].owner = nAnim;
|
||||
|
||||
AddFlash(sprite[nAnimSprite].sectnum, sprite[nAnimSprite].x, sprite[nAnimSprite].y, sprite[nAnimSprite].z, 128);
|
||||
changespritestat(nAnimSprite, 950);
|
||||
|
||||
nMagicCount = RandomSize(2);
|
||||
}
|
||||
}
|
||||
|
||||
void InitItems()
|
||||
{
|
||||
nRegenerates = 0;
|
||||
nFirstRegenerate = -1;
|
||||
nMagicCount = 0;
|
||||
}
|
||||
|
||||
void StartRegenerate(short nSprite)
|
||||
{
|
||||
spritetype *pSprite = &sprite[nSprite];
|
||||
|
||||
int edi = -1;
|
||||
|
||||
int nReg = nFirstRegenerate;
|
||||
|
||||
int i = 0;
|
||||
|
||||
// for (int i = 0; i < nRegenerates; i++)
|
||||
while (1)
|
||||
{
|
||||
if (i >= nRegenerates)
|
||||
{
|
||||
// ?? CHECKME
|
||||
pSprite->xvel = pSprite->xrepeat;
|
||||
pSprite->zvel = pSprite->shade;
|
||||
pSprite->yvel = pSprite->pal;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nReg != nSprite)
|
||||
{
|
||||
edi = nReg;
|
||||
nReg = sprite[nReg].ang;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (edi == -1)
|
||||
{
|
||||
nFirstRegenerate = pSprite->ang;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite[edi].ang = sprite[nSprite].ang;
|
||||
}
|
||||
|
||||
nRegenerates--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pSprite->extra = 1350;
|
||||
pSprite->ang = nFirstRegenerate;
|
||||
|
||||
if (levelnum <= kMap20)
|
||||
{
|
||||
pSprite->ang /= 5;
|
||||
}
|
||||
|
||||
pSprite->cstat = 0x8000;
|
||||
pSprite->xrepeat = 1;
|
||||
pSprite->yrepeat = 1;
|
||||
pSprite->pal = 1;
|
||||
|
||||
nRegenerates++;
|
||||
nFirstRegenerate = nSprite;
|
||||
}
|
||||
|
||||
void DoRegenerates()
|
||||
{
|
||||
int nSprite = nFirstRegenerate;
|
||||
|
||||
for (int i = nRegenerates; i > 0; i--, nSprite = sprite[nSprite].ang)
|
||||
{
|
||||
if (sprite[nSprite].extra > 0)
|
||||
{
|
||||
sprite[nSprite].extra--;
|
||||
|
||||
if (sprite[nSprite].extra <= 0)
|
||||
{
|
||||
BuildAnim(-1, 38, 0, sprite[nSprite].x, sprite[nSprite].y, sprite[nSprite].z, sprite[nSprite].sectnum, 64, 4);
|
||||
D3PlayFX(StaticSound[kSoundTorchOn], i);
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sprite[nSprite].xrepeat < sprite[nSprite].xvel)
|
||||
{
|
||||
sprite[nSprite].xrepeat += 2;
|
||||
sprite[nSprite].yrepeat += 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
sprite[nSprite].zvel = 0;
|
||||
sprite[nSprite].yrepeat = sprite[nSprite].xvel;
|
||||
sprite[nSprite].xrepeat = sprite[nSprite].xvel;
|
||||
sprite[nSprite].pal = sprite[nSprite].yvel;
|
||||
sprite[nSprite].yvel = sprite[nSprite].zvel; // setting to 0
|
||||
sprite[nSprite].xvel = sprite[nSprite].zvel; // setting to 0
|
||||
nRegenerates--;
|
||||
|
||||
if (sprite[nSprite].statnum == kStatExplodeTrigger) {
|
||||
sprite[nSprite].cstat = 0x101;
|
||||
}
|
||||
else {
|
||||
sprite[nSprite].cstat = 0;
|
||||
}
|
||||
|
||||
if (nRegenerates == 0) {
|
||||
nFirstRegenerate = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
END_PS_NS
|
56
source/exhumed/src/items.h
Normal file
56
source/exhumed/src/items.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __items_h__
|
||||
#define __items_h__
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
enum
|
||||
{
|
||||
kItemHeart = 0,
|
||||
kItemInvincibility,
|
||||
kItemTorch,
|
||||
kItemDoubleDamage,
|
||||
kItemInvisibility,
|
||||
kItemMask,
|
||||
};
|
||||
|
||||
extern short nItemMagic[];
|
||||
|
||||
void BuildItemAnim(short nSprite);
|
||||
void DestroyItemAnim(short nSprite);
|
||||
void ItemFlash();
|
||||
void FillItems(short nPlayer);
|
||||
void UseEye(short nPlayer);
|
||||
void UseMask(short nPlayer);
|
||||
void UseTorch(short nPlayer);
|
||||
void UseHeart(short nPlayer);
|
||||
void UseScarab(short nPlayer);
|
||||
void UseHand(short nPlayer);
|
||||
void UseItem(short nPlayer, short nItem);
|
||||
void UseCurItem(short nPlayer);
|
||||
int GrabItem(short nPlayer, short nItem);
|
||||
void DropMagic(short nSprite);
|
||||
void InitItems();
|
||||
void StartRegenerate(short nSprite);
|
||||
void DoRegenerates();
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
526
source/exhumed/src/lavadude.cpp
Normal file
526
source/exhumed/src/lavadude.cpp
Normal file
|
@ -0,0 +1,526 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "engine.h"
|
||||
#include "lavadude.h"
|
||||
#include "random.h"
|
||||
#include "runlist.h"
|
||||
#include "sequence.h"
|
||||
#include "exhumed.h"
|
||||
#include "move.h"
|
||||
#include "trigdat.h"
|
||||
#include "move.h"
|
||||
#include "bullet.h"
|
||||
#include "sound.h"
|
||||
#include <assert.h>
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
#define kMaxLavas 20
|
||||
|
||||
struct Lava
|
||||
{
|
||||
short nSprite;
|
||||
short field_2;
|
||||
short nAction;
|
||||
short nTarget;
|
||||
short nHealth;
|
||||
short field_10;
|
||||
short field_12;
|
||||
};
|
||||
|
||||
Lava LavaList[kMaxLavas];
|
||||
|
||||
short LavaCount = 0;
|
||||
short LavaSprite = -1;
|
||||
|
||||
static actionSeq ActionSeq[] = {
|
||||
{0, 1},
|
||||
{0, 1},
|
||||
{1, 0},
|
||||
{10, 0},
|
||||
{19, 0},
|
||||
{28, 1},
|
||||
{29, 1},
|
||||
{33, 0},
|
||||
{42, 1}
|
||||
};
|
||||
|
||||
static SavegameHelper sgh("lavadude",
|
||||
SA(LavaList),
|
||||
SV(LavaCount),
|
||||
SV(LavaSprite),
|
||||
nullptr);
|
||||
|
||||
|
||||
// done
|
||||
void InitLava()
|
||||
{
|
||||
LavaCount = 0;
|
||||
LavaSprite = 1;
|
||||
}
|
||||
|
||||
int BuildLavaLimb(int nSprite, int edx, int ebx)
|
||||
{
|
||||
short nSector = sprite[nSprite].sectnum;
|
||||
|
||||
int nLimbSprite = insertsprite(nSector, 118);
|
||||
assert(nLimbSprite >= 0 && nLimbSprite < kMaxSprites);
|
||||
|
||||
sprite[nLimbSprite].x = sprite[nSprite].x;
|
||||
sprite[nLimbSprite].y = sprite[nSprite].y;
|
||||
sprite[nLimbSprite].z = sprite[nSprite].z - RandomLong() % ebx;
|
||||
sprite[nLimbSprite].cstat = 0;
|
||||
sprite[nLimbSprite].shade = -127;
|
||||
sprite[nLimbSprite].pal = 1;
|
||||
sprite[nLimbSprite].xvel = (RandomSize(5) - 16) << 8;
|
||||
sprite[nLimbSprite].yvel = (RandomSize(5) - 16) << 8;
|
||||
sprite[nLimbSprite].zvel = 2560 - (RandomSize(5) << 8);
|
||||
sprite[nLimbSprite].yoffset = 0;
|
||||
sprite[nLimbSprite].xoffset = 0;
|
||||
sprite[nLimbSprite].xrepeat = 90;
|
||||
sprite[nLimbSprite].yrepeat = 90;
|
||||
sprite[nLimbSprite].picnum = (edx & 3) % 3;
|
||||
sprite[nLimbSprite].hitag = 0;
|
||||
sprite[nLimbSprite].lotag = runlist_HeadRun() + 1;
|
||||
sprite[nLimbSprite].clipdist = 0;
|
||||
|
||||
// GrabTimeSlot(3);
|
||||
|
||||
sprite[nLimbSprite].extra = -1;
|
||||
sprite[nLimbSprite].owner = runlist_AddRunRec(sprite[nLimbSprite].lotag - 1, nLimbSprite | 0x160000);
|
||||
sprite[nLimbSprite].hitag = runlist_AddRunRec(NewRun, nLimbSprite | 0x160000);
|
||||
|
||||
return nLimbSprite;
|
||||
}
|
||||
|
||||
void FuncLavaLimb(int eax, int UNUSED(nDamage), int nRun)
|
||||
{
|
||||
short nSprite = RunData[nRun].nVal;
|
||||
assert(nSprite >= 0 && nSprite < kMaxSprites);
|
||||
|
||||
int nMessage = eax & 0x7F0000;
|
||||
|
||||
switch (nMessage)
|
||||
{
|
||||
case 0x20000:
|
||||
{
|
||||
sprite[nSprite].shade += 3;
|
||||
|
||||
int nRet = movesprite(nSprite, sprite[nSprite].xvel << 12, sprite[nSprite].yvel << 12, sprite[nSprite].zvel, 2560, -2560, CLIPMASK1);
|
||||
|
||||
if (nRet || sprite[nSprite].shade > 100)
|
||||
{
|
||||
sprite[nSprite].zvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].xvel = 0;
|
||||
|
||||
runlist_DoSubRunRec(sprite[nSprite].owner);
|
||||
runlist_FreeRun(sprite[nSprite].lotag - 1);
|
||||
runlist_SubRunRec(sprite[nSprite].hitag);
|
||||
|
||||
mydeletesprite(nSprite);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x90000:
|
||||
{
|
||||
seq_PlotSequence(eax, (SeqOffsets[kSeqLavag] + 30) + sprite[nSprite].picnum, 0, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int BuildLava(short nSprite, int x, int y, int UNUSED(z), short nSector, short nAngle, int lastArg)
|
||||
{
|
||||
short nLava = LavaCount;
|
||||
LavaCount++;
|
||||
|
||||
if (nLava >= kMaxLavas) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nSprite == -1)
|
||||
{
|
||||
nSprite = insertsprite(nSector, 118);
|
||||
}
|
||||
else
|
||||
{
|
||||
nSector = sprite[nSprite].sectnum;
|
||||
nAngle = sprite[nSprite].ang;
|
||||
x = sprite[nSprite].x;
|
||||
y = sprite[nSprite].y;
|
||||
|
||||
changespritestat(nSprite, 118);
|
||||
}
|
||||
|
||||
assert(nSprite >= 0 && nSprite < kMaxSprites);
|
||||
|
||||
sprite[nSprite].x = x;
|
||||
sprite[nSprite].y = y;
|
||||
sprite[nSprite].z = sector[nSector].floorz;
|
||||
sprite[nSprite].cstat = 0x8000u;
|
||||
sprite[nSprite].xrepeat = 200;
|
||||
sprite[nSprite].yrepeat = 200;
|
||||
sprite[nSprite].shade = -12;
|
||||
sprite[nSprite].pal = 0;
|
||||
sprite[nSprite].clipdist = 127;
|
||||
sprite[nSprite].xoffset = 0;
|
||||
sprite[nSprite].yoffset = 0;
|
||||
sprite[nSprite].picnum = seq_GetSeqPicnum(kSeqLavag, ActionSeq[3].a, 0);
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].zvel = 0;
|
||||
sprite[nSprite].ang = nAngle;
|
||||
sprite[nSprite].hitag = 0;
|
||||
sprite[nSprite].lotag = runlist_HeadRun() + 1;
|
||||
|
||||
// GrabTimeSlot(3);
|
||||
|
||||
sprite[nSprite].extra = -1;
|
||||
|
||||
LavaList[nLava].nAction = 0;
|
||||
LavaList[nLava].nHealth = 4000;
|
||||
LavaList[nLava].nSprite = nSprite;
|
||||
LavaList[nLava].nTarget = -1;
|
||||
LavaList[nLava].field_12 = lastArg;
|
||||
LavaList[nLava].field_10 = 0;
|
||||
|
||||
sprite[nSprite].owner = runlist_AddRunRec(sprite[nSprite].lotag - 1, nLava | 0x150000);
|
||||
LavaList[nLava].field_2 = runlist_AddRunRec(NewRun, nLava | 0x150000);
|
||||
|
||||
nCreaturesLeft++;
|
||||
|
||||
return nLava | 0x150000;
|
||||
}
|
||||
|
||||
void FuncLava(int a, int nDamage, int nRun)
|
||||
{
|
||||
short nLava = RunData[nRun].nVal;
|
||||
assert(nLava >= 0 && nLava < kMaxLavas);
|
||||
|
||||
short nAction = LavaList[nLava].nAction;
|
||||
|
||||
short nSeq = ActionSeq[nAction].a + SeqOffsets[kSeqLavag];
|
||||
|
||||
short nSprite = LavaList[nLava].nSprite;
|
||||
|
||||
int nMessage = a & 0x7F0000;
|
||||
|
||||
switch (nMessage)
|
||||
{
|
||||
default:
|
||||
{
|
||||
Printf("unknown msg %d for Lava\n", a & 0x7F0000);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x90000:
|
||||
{
|
||||
seq_PlotSequence(a & 0xFFFF, nSeq, LavaList[nLava].field_10, ActionSeq[nAction].b);
|
||||
tsprite[a & 0xFFFF].owner = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
case 0xA0000:
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x80000:
|
||||
{
|
||||
if (!nDamage) {
|
||||
return;
|
||||
}
|
||||
|
||||
LavaList[nLava].nHealth -= nDamage;
|
||||
|
||||
if (LavaList[nLava].nHealth <= 0)
|
||||
{
|
||||
LavaList[nLava].nHealth = 0;
|
||||
LavaList[nLava].nAction = 5;
|
||||
LavaList[nLava].field_10 = 0;
|
||||
|
||||
nCreaturesLeft--;
|
||||
|
||||
sprite[nSprite].cstat &= 0xFEFE;
|
||||
}
|
||||
else
|
||||
{
|
||||
short nTarget = a & 0xFFFF;
|
||||
|
||||
if (nTarget >= 0)
|
||||
{
|
||||
if (sprite[nTarget].statnum < 199)
|
||||
{
|
||||
LavaList[nLava].nTarget = nTarget;
|
||||
}
|
||||
}
|
||||
|
||||
if (nAction == 3)
|
||||
{
|
||||
if (!RandomSize(2))
|
||||
{
|
||||
LavaList[nLava].nAction = 4;
|
||||
LavaList[nLava].field_10 = 0;
|
||||
sprite[nSprite].cstat = 0;
|
||||
}
|
||||
}
|
||||
|
||||
BuildLavaLimb(nSprite, totalmoves, 0xFA00);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x20000:
|
||||
{
|
||||
sprite[nSprite].picnum = seq_GetSeqPicnum2(nSeq, LavaList[nLava].field_10);
|
||||
int var_38 = LavaList[nLava].field_10;
|
||||
|
||||
short nFlag = FrameFlag[SeqBase[nSeq] + var_38];
|
||||
|
||||
int var_1C;
|
||||
|
||||
if (nAction)
|
||||
{
|
||||
seq_MoveSequence(nSprite, nSeq, var_38);
|
||||
|
||||
LavaList[nLava].field_10++;
|
||||
if (LavaList[nLava].field_10 >= SeqSize[nSeq])
|
||||
{
|
||||
var_1C = 1;
|
||||
LavaList[nLava].field_10 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
var_1C = 0;
|
||||
}
|
||||
}
|
||||
|
||||
short nTarget = LavaList[nLava].nTarget;
|
||||
|
||||
if (nTarget >= 0 && nAction < 4)
|
||||
{
|
||||
if (!(sprite[nTarget].cstat & 0x101) || sprite[nTarget].sectnum >= 1024)
|
||||
{
|
||||
nTarget = -1;
|
||||
LavaList[nLava].nTarget = -1;
|
||||
}
|
||||
}
|
||||
|
||||
switch (nAction)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
if ((nLava & 0x1F) == (totalmoves & 0x1F))
|
||||
{
|
||||
if (nTarget < 0)
|
||||
{
|
||||
nTarget = FindPlayer(nSprite, 76800);
|
||||
}
|
||||
|
||||
PlotCourseToSprite(nSprite, nTarget);
|
||||
|
||||
sprite[nSprite].xvel = Sin(sprite[nSprite].ang + 512);
|
||||
sprite[nSprite].yvel = Sin(sprite[nSprite].ang);
|
||||
|
||||
if (nTarget >= 0 && !RandomSize(1))
|
||||
{
|
||||
LavaList[nLava].nTarget = nTarget;
|
||||
LavaList[nLava].nAction = 2;
|
||||
sprite[nSprite].cstat = 0x101;
|
||||
LavaList[nLava].field_10 = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int x = sprite[nSprite].x;
|
||||
int y = sprite[nSprite].y;
|
||||
int z = sprite[nSprite].z;
|
||||
short nSector = sprite[nSprite].sectnum;
|
||||
|
||||
int nVal = movesprite(nSprite, sprite[nSprite].xvel << 8, sprite[nSprite].yvel << 8, 0, 0, 0, CLIPMASK0);
|
||||
|
||||
if (nSector != sprite[nSprite].sectnum)
|
||||
{
|
||||
changespritesect(nSprite, nSector);
|
||||
sprite[nSprite].x = x;
|
||||
sprite[nSprite].y = y;
|
||||
sprite[nSprite].z = z;
|
||||
|
||||
sprite[nSprite].ang = (sprite[nSprite].ang + ((RandomWord() & 0x3FF) + 1024)) & 0x7FF;
|
||||
sprite[nSprite].xvel = Sin(sprite[nSprite].ang + 512);
|
||||
sprite[nSprite].yvel = Sin(sprite[nSprite].ang);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!nVal) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((nVal & 0x0C000) == 0x8000)
|
||||
{
|
||||
sprite[nSprite].ang = (sprite[nSprite].ang + ((RandomWord() & 0x3FF) + 1024)) & 0x7FF;
|
||||
sprite[nSprite].xvel = Sin(sprite[nSprite].ang + 512);
|
||||
sprite[nSprite].yvel = Sin(sprite[nSprite].ang);
|
||||
break;
|
||||
}
|
||||
else if ((nVal & 0x0C000) == 0x0C000)
|
||||
{
|
||||
if ((nVal & 0x3FFF) == nTarget)
|
||||
{
|
||||
int nAng = getangle(sprite[nTarget].x - sprite[nSprite].x, sprite[nTarget].y - sprite[nSprite].y);
|
||||
if (AngleDiff(sprite[nSprite].ang, nAng) < 64)
|
||||
{
|
||||
LavaList[nLava].nAction = 2;
|
||||
sprite[nSprite].cstat = 0x101;
|
||||
LavaList[nLava].field_10 = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 1:
|
||||
case 6:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
if (var_1C)
|
||||
{
|
||||
LavaList[nLava].nAction = 3;
|
||||
LavaList[nLava].field_10 = 0;
|
||||
|
||||
PlotCourseToSprite(nSprite, nTarget);
|
||||
|
||||
sprite[nSprite].cstat |= 0x101;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
if ((nFlag & 0x80) && nTarget > -1)
|
||||
{
|
||||
int nHeight = GetSpriteHeight(nSprite);
|
||||
GetUpAngle(nSprite, 0x0FFFF0600, nTarget, (-(nHeight >> 1)));
|
||||
|
||||
BuildBullet(nSprite, 10, Sin(sprite[nSprite].ang + 512) << 8, Sin(sprite[nSprite].ang) << 8, -1, sprite[nSprite].ang, nTarget + 10000, 1);
|
||||
}
|
||||
else if (var_1C)
|
||||
{
|
||||
PlotCourseToSprite(nSprite, nTarget);
|
||||
LavaList[nLava].nAction = 7;
|
||||
LavaList[nLava].field_10 = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
if (var_1C)
|
||||
{
|
||||
LavaList[nLava].nAction = 7;
|
||||
sprite[nSprite].cstat &= 0xFEFE;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 5:
|
||||
{
|
||||
if (nFlag & 0x40)
|
||||
{
|
||||
int nLimbSprite = BuildLavaLimb(nSprite, LavaList[nLava].field_10, 0xFA00u);
|
||||
D3PlayFX(StaticSound[kSound26], nLimbSprite);
|
||||
}
|
||||
|
||||
if (LavaList[nLava].field_10)
|
||||
{
|
||||
if (nFlag & 0x80)
|
||||
{
|
||||
int ecx = 0;
|
||||
do
|
||||
{
|
||||
BuildLavaLimb(nSprite, ecx, 0xFA00u);
|
||||
ecx++;
|
||||
}
|
||||
while (ecx < 20);
|
||||
runlist_ChangeChannel(LavaList[nLava].field_12, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int ecx = 0;
|
||||
|
||||
do
|
||||
{
|
||||
BuildLavaLimb(nSprite, ecx, 256);
|
||||
ecx++;
|
||||
}
|
||||
while (ecx < 30);
|
||||
|
||||
runlist_DoSubRunRec(sprite[nSprite].owner);
|
||||
runlist_FreeRun(sprite[nSprite].lotag - 1);
|
||||
runlist_SubRunRec(LavaList[nLava].field_2);
|
||||
mydeletesprite(nSprite);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 7:
|
||||
{
|
||||
if (var_1C)
|
||||
{
|
||||
LavaList[nLava].nAction = 8;
|
||||
LavaList[nLava].field_10 = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 8:
|
||||
{
|
||||
if (var_1C)
|
||||
{
|
||||
LavaList[nLava].nAction = 0;
|
||||
LavaList[nLava].field_10 = 0;
|
||||
sprite[nSprite].cstat = 0x8000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// loc_31521:
|
||||
sprite[nSprite].pal = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
END_PS_NS
|
32
source/exhumed/src/lavadude.h
Normal file
32
source/exhumed/src/lavadude.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __lavadude_h__
|
||||
#define __lavadude_h__
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
void InitLava();
|
||||
int BuildLava(short nSprite, int x, int y, int z, short nSector, short nAngle, int lastArg);
|
||||
int BuildLavaLimb(int nSprite, int edx, int ebx);
|
||||
void FuncLavaLimb(int, int, int);
|
||||
void FuncLava(int, int, int);
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
750
source/exhumed/src/light.cpp
Normal file
750
source/exhumed/src/light.cpp
Normal file
|
@ -0,0 +1,750 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "light.h"
|
||||
#include "engine.h"
|
||||
#include "exhumed.h"
|
||||
#include "view.h"
|
||||
#include "cd.h"
|
||||
#include "lighting.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
#define kMaxGrads 12
|
||||
|
||||
const char *GradList[kMaxGrads] = {
|
||||
"normal.rmp",
|
||||
"nodim.rmp",
|
||||
"torch.rmp",
|
||||
"notorch.rmp",
|
||||
"brite.rmp",
|
||||
"redbrite.rmp",
|
||||
"grnbrite.rmp",
|
||||
"normal.rmp",
|
||||
"nodim.rmp",
|
||||
"torch.rmp",
|
||||
"notorch.rmp",
|
||||
"brite.rmp"
|
||||
};
|
||||
|
||||
int rtint = 0;
|
||||
int gtint = 0;
|
||||
int btint = 0;
|
||||
//char *origpalookup[kMaxPalookups];
|
||||
//unsigned char curpal[768];
|
||||
//unsigned char kenpal[768];
|
||||
palette_t *fadedestpal;
|
||||
palette_t *fadecurpal;
|
||||
short nPalDelay;
|
||||
short nPalDiff;
|
||||
short overscanindex;
|
||||
int bGreenPal = 0;
|
||||
|
||||
// keep a local copy of the palette that would have been sent to the VGA display adapter
|
||||
uint8_t vgaPalette[768];
|
||||
|
||||
|
||||
void MyLoadPalette()
|
||||
{
|
||||
//int hFile = kopen4load("PALETTE.DAT", 1);
|
||||
//if (hFile == -1)
|
||||
//{
|
||||
// initprintf("Error reading palette 'PALETTE.DAT'\n");
|
||||
// return;
|
||||
//}
|
||||
//
|
||||
//kread(hFile, kenpal, sizeof(kenpal));
|
||||
//kclose(hFile);
|
||||
videoSetPalette(0, BASEPAL, 0);
|
||||
SetOverscan(BASEPAL);
|
||||
}
|
||||
|
||||
int LoadPaletteLookups()
|
||||
{
|
||||
uint8_t buffer[256*64];
|
||||
numshades = 64;
|
||||
|
||||
for (int i = 0; i < kMaxGrads; i++)
|
||||
{
|
||||
auto hFile = fileSystem.OpenFileReader(GradList[i], 1);
|
||||
if (!hFile.isOpen())
|
||||
{
|
||||
initprintf("Error reading palette lookup '%s'\n", GradList[i]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
hFile.Read(buffer, 256*64);
|
||||
// TODO: dumb hack
|
||||
if (palookup[i])
|
||||
ALIGNED_FREE_AND_NULL(palookup[i]);
|
||||
paletteSetLookupTable(i, buffer);
|
||||
|
||||
// origpalookup[i] = palookup[i];
|
||||
bGreenPal = 0;
|
||||
|
||||
#ifdef USE_OPENGL
|
||||
/*
|
||||
// Very rough approximation...
|
||||
palookupfogfactor[kPalNormal] = 1.f;
|
||||
palookupfogfactor[kPalNoDim] = 0.f;
|
||||
palookupfogfactor[kPalTorch] = 0.36f;
|
||||
palookupfogfactor[kPalNoTorch] = 0.15f;
|
||||
palookupfogfactor[kPalBrite] = 2.f;
|
||||
palookupfogfactor[kPalRedBrite] = 0.36f;
|
||||
palookupfog[kPalRedBrite] = { 248, 32, 0, 0 };
|
||||
hicsetpalettetint(kPalRedBrite, 255, 255, 255, 248, 32, 0, 0);
|
||||
palookupfog[kPalGreenBrite] = { 248, 32, 0, 0 };
|
||||
palookupfogfactor[kPalGreenBrite] = 0.f;
|
||||
hicsetpalettetint(kPalGreenBrite, 100, 200, 100, 0, 0, 0, 0);
|
||||
palookupfogfactor[kPalNormal2] = 1.f;
|
||||
palookupfogfactor[kPalNoDim2] = 0.f;
|
||||
palookupfogfactor[kPalTorch2] = 0.36f;
|
||||
palookupfogfactor[kPalNoTorch2] = 0.15f;
|
||||
palookupfogfactor[kPalBrite2] = 2.f;
|
||||
*/
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void SetGreenPal()
|
||||
{
|
||||
bGreenPal = 1;
|
||||
// for (int i = 0; i < kMaxGrads; i++)
|
||||
// {
|
||||
// palookup[i] = palookup[6];
|
||||
// }
|
||||
//
|
||||
// palookup[5] = origpalookup[5];
|
||||
}
|
||||
|
||||
void RestoreGreenPal()
|
||||
{
|
||||
bGreenPal = 0;
|
||||
// for (int i = 0; i < kMaxGrads; i++)
|
||||
// {
|
||||
// palookup[i] = origpalookup[i];
|
||||
// }
|
||||
}
|
||||
|
||||
int HavePLURemap()
|
||||
{
|
||||
return bGreenPal || bTorch;
|
||||
}
|
||||
|
||||
uint8_t RemapPLU(uint8_t pal)
|
||||
{
|
||||
if (bGreenPal)
|
||||
{
|
||||
if (pal != kPalRedBrite)
|
||||
pal = kPalGreenBrite;
|
||||
}
|
||||
else if (bTorch)
|
||||
{
|
||||
switch (pal)
|
||||
{
|
||||
case kPalTorch:
|
||||
pal = kPalNoTorch;
|
||||
break;
|
||||
case kPalNoTorch:
|
||||
pal = kPalTorch;
|
||||
break;
|
||||
case kPalTorch2:
|
||||
pal = kPalNoTorch2;
|
||||
break;
|
||||
case kPalNoTorch2:
|
||||
pal = kPalTorch2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return pal;
|
||||
}
|
||||
|
||||
void WaitVBL()
|
||||
{
|
||||
#ifdef __WATCOMC__
|
||||
while (!(inp(0x3da) & 8));
|
||||
#endif
|
||||
}
|
||||
|
||||
//void MySetPalette(unsigned char *palette)
|
||||
//{
|
||||
// WaitVBL();
|
||||
//
|
||||
// // TODO
|
||||
// kensetpalette(palette);
|
||||
//
|
||||
// memcpy(vgaPalette, palette, sizeof(vgaPalette));
|
||||
//}
|
||||
|
||||
//void GetCurPal(unsigned char *palette)
|
||||
//{
|
||||
// if (!palette) {
|
||||
// memcpy(curpal, vgaPalette, sizeof(curpal));
|
||||
// }
|
||||
// else {
|
||||
// memcpy(palette, vgaPalette, sizeof(curpal));
|
||||
// }
|
||||
//}
|
||||
|
||||
void GrabPalette()
|
||||
{
|
||||
SetOverscan(BASEPAL);
|
||||
|
||||
videoSetPalette(0, BASEPAL, 2+8);
|
||||
|
||||
nPalDiff = 0;
|
||||
nPalDelay = 0;
|
||||
|
||||
btint = 0;
|
||||
gtint = 0;
|
||||
rtint = 0;
|
||||
#ifdef USE_OPENGL
|
||||
videoTintBlood(0, 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void BlackOut()
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
curpalettefaded[i].r = 0;
|
||||
curpalettefaded[i].g = 0;
|
||||
curpalettefaded[i].b = 0;
|
||||
}
|
||||
//videoUpdatePalette(0, 256);
|
||||
g_lastpalettesum = -1;
|
||||
#ifdef USE_OPENGL
|
||||
videoTintBlood(0, 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void RestorePalette()
|
||||
{
|
||||
videoSetPalette(0, BASEPAL, 2+8);
|
||||
#ifdef USE_OPENGL
|
||||
videoTintBlood(0, 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void WaitTicks(int nTicks)
|
||||
{
|
||||
if (htimer)
|
||||
{
|
||||
nTicks += (int)totalclock;
|
||||
while (nTicks > (int)totalclock) { HandleAsync(); }
|
||||
}
|
||||
else
|
||||
{
|
||||
while (nTicks > 0) {
|
||||
nTicks--;
|
||||
WaitVBL();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// unused
|
||||
void DoFadeToRed()
|
||||
{
|
||||
#ifdef USE_OPENGL
|
||||
if (videoGetRenderMode() >= REND_POLYMOST)
|
||||
{
|
||||
videoTintBlood(-255, -255, -255);
|
||||
videoNextPage();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
if (curpalettefaded[i].g > 0)
|
||||
{
|
||||
curpalettefaded[i].g -= 4;
|
||||
if (curpalettefaded[i].g < 0)
|
||||
curpalettefaded[i].g = 0;
|
||||
}
|
||||
|
||||
if (curpalettefaded[i].b > 0)
|
||||
{
|
||||
curpalettefaded[i].b -= 4;
|
||||
if (curpalettefaded[i].b < 0)
|
||||
curpalettefaded[i].b = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//videoUpdatePalette(0, 256);
|
||||
g_lastpalettesum = -1;
|
||||
}
|
||||
|
||||
void FadeToWhite()
|
||||
{
|
||||
int ebx = 0;
|
||||
|
||||
#ifdef USE_OPENGL
|
||||
if (videoGetRenderMode() >= REND_POLYMOST)
|
||||
{
|
||||
videoTintBlood(255, 255, 255);
|
||||
videoNextPage();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
palette_t *pPal = curpalettefaded;
|
||||
|
||||
for (int j = 0; j < 256; j++)
|
||||
{
|
||||
if (pPal->r < 255)
|
||||
{
|
||||
pPal->r += 4;
|
||||
if (pPal->r > 255)
|
||||
pPal->r = 255;
|
||||
ebx++;
|
||||
}
|
||||
if (pPal->g < 255)
|
||||
{
|
||||
pPal->g += 4;
|
||||
if (pPal->g > 255)
|
||||
pPal->g = 255;
|
||||
ebx++;
|
||||
}
|
||||
if (pPal->b < 255)
|
||||
{
|
||||
pPal->b += 4;
|
||||
if (pPal->b > 255)
|
||||
pPal->b = 255;
|
||||
ebx++;
|
||||
}
|
||||
pPal++;
|
||||
}
|
||||
|
||||
//videoUpdatePalette(0, 256);
|
||||
g_lastpalettesum = -1;
|
||||
WaitTicks(2);
|
||||
|
||||
// need to page flip in each iteration of the loop for non DOS version
|
||||
videoNextPage();
|
||||
|
||||
if (!ebx) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FadeOut(int bFadeMusic)
|
||||
{
|
||||
if (bFadeMusic) {
|
||||
StartfadeCDaudio();
|
||||
}
|
||||
|
||||
|
||||
#ifdef USE_OPENGL
|
||||
if (videoGetRenderMode() >= REND_POLYMOST)
|
||||
{
|
||||
videoTintBlood(-255, -255, -255);
|
||||
videoNextPage();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
for (int i = 64; i > 0; i--)
|
||||
{
|
||||
int v4 = 0;
|
||||
palette_t *pPal = curpalettefaded;
|
||||
|
||||
for (int j = 0; j < 256; j++)
|
||||
{
|
||||
if (pPal->r > 0)
|
||||
{
|
||||
pPal->r -= 4;
|
||||
if (pPal->r < 0)
|
||||
pPal->r = 0;
|
||||
v4++;
|
||||
}
|
||||
if (pPal->g > 0)
|
||||
{
|
||||
pPal->g -= 4;
|
||||
if (pPal->g < 0)
|
||||
pPal->g = 0;
|
||||
v4++;
|
||||
}
|
||||
if (pPal->b > 0)
|
||||
{
|
||||
pPal->b -= 4;
|
||||
if (pPal->b < 0)
|
||||
pPal->b = 0;
|
||||
v4++;
|
||||
}
|
||||
pPal++;
|
||||
}
|
||||
|
||||
//videoUpdatePalette(0, 256);
|
||||
g_lastpalettesum = -1;
|
||||
WaitTicks(2);
|
||||
|
||||
// need to page flip in each iteration of the loop for non DOS version
|
||||
videoNextPage();
|
||||
|
||||
if (v4 == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (bFadeMusic) {
|
||||
StepFadeCDaudio();
|
||||
}
|
||||
}
|
||||
|
||||
if (bFadeMusic) {
|
||||
while (StepFadeCDaudio() != 0) {}
|
||||
}
|
||||
|
||||
EraseScreen(overscanindex);
|
||||
}
|
||||
|
||||
void StartFadeIn()
|
||||
{
|
||||
//fadedestpal = curpalette;
|
||||
//fadecurpal = curpal;
|
||||
}
|
||||
|
||||
int DoFadeIn()
|
||||
{
|
||||
#ifdef USE_OPENGL
|
||||
if (videoGetRenderMode() >= REND_POLYMOST)
|
||||
{
|
||||
paletteSetColorTable(curbasepal, basepaltable[BASEPAL]);
|
||||
videoSetPalette(0, curbasepal, 2+8);
|
||||
videoNextPage();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
int v2 = 0;
|
||||
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
if (curpalettefaded[i].r != curpalette[i].r)
|
||||
{
|
||||
v2++;
|
||||
int diff = curpalette[i].r - curpalettefaded[i].r;
|
||||
if (klabs(diff) < 4)
|
||||
curpalettefaded[i].r = curpalette[i].r;
|
||||
else
|
||||
curpalettefaded[i].r += 4 * ksgn(diff);
|
||||
}
|
||||
if (curpalettefaded[i].g != curpalette[i].g)
|
||||
{
|
||||
v2++;
|
||||
int diff = curpalette[i].g - curpalettefaded[i].g;
|
||||
if (klabs(diff) < 4)
|
||||
curpalettefaded[i].g = curpalette[i].g;
|
||||
else
|
||||
curpalettefaded[i].g += 4 * ksgn(diff);
|
||||
}
|
||||
if (curpalettefaded[i].b != curpalette[i].b)
|
||||
{
|
||||
v2++;
|
||||
int diff = curpalette[i].b - curpalettefaded[i].b;
|
||||
if (klabs(diff) < 4)
|
||||
curpalettefaded[i].b = curpalette[i].b;
|
||||
else
|
||||
curpalettefaded[i].b += 4 * ksgn(diff);
|
||||
}
|
||||
}
|
||||
|
||||
//videoUpdatePalette(0, 256);
|
||||
g_lastpalettesum = -1;
|
||||
|
||||
return v2;
|
||||
}
|
||||
|
||||
void FadeIn()
|
||||
{
|
||||
#ifdef USE_OPENGL
|
||||
if (videoGetRenderMode() >= REND_POLYMOST)
|
||||
{
|
||||
videoSetPalette(0, BASEPAL, 2+8);
|
||||
videoNextPage();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
StartFadeIn();
|
||||
|
||||
int val;
|
||||
|
||||
do
|
||||
{
|
||||
val = DoFadeIn();
|
||||
WaitTicks(2);
|
||||
|
||||
// need to page flip in each iteration of the loop for non DOS version
|
||||
videoNextPage();
|
||||
} while (val);
|
||||
}
|
||||
|
||||
void FixPalette()
|
||||
{
|
||||
if (!nPalDiff) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nPalDelay > 0)
|
||||
{
|
||||
nPalDelay--;
|
||||
return;
|
||||
}
|
||||
|
||||
nPalDelay = 5;
|
||||
|
||||
#ifdef USE_OPENGL
|
||||
if (videoGetRenderMode() == REND_CLASSIC)
|
||||
#endif
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
short nVal;
|
||||
|
||||
nVal = curpalettefaded[i].r - curpalette[i].r;
|
||||
if (nVal > 0)
|
||||
{
|
||||
if (nVal > 20)
|
||||
{
|
||||
curpalettefaded[i].r -= 20;
|
||||
}
|
||||
else
|
||||
{
|
||||
curpalettefaded[i].r = curpalette[i].r;
|
||||
}
|
||||
}
|
||||
|
||||
nVal = curpalettefaded[i].g - curpalette[i].g;
|
||||
if (nVal > 0)
|
||||
{
|
||||
if (nVal > 20)
|
||||
{
|
||||
curpalettefaded[i].g -= 20;
|
||||
}
|
||||
else
|
||||
{
|
||||
curpalettefaded[i].g = curpalette[i].g;
|
||||
}
|
||||
}
|
||||
|
||||
nVal = curpalettefaded[i].b - curpalette[i].b;
|
||||
if (nVal > 0)
|
||||
{
|
||||
if (nVal > 20)
|
||||
{
|
||||
curpalettefaded[i].b -= 20;
|
||||
}
|
||||
else
|
||||
{
|
||||
curpalettefaded[i].b = curpalette[i].b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nPalDiff -= 20;
|
||||
gtint -= 20;
|
||||
rtint -= 20;
|
||||
btint -= 20;
|
||||
|
||||
if (gtint < 0) {
|
||||
gtint = 0;
|
||||
}
|
||||
|
||||
if (rtint < 0) {
|
||||
rtint = 0;
|
||||
}
|
||||
|
||||
if (btint < 0) {
|
||||
btint = 0;
|
||||
}
|
||||
|
||||
if (nPalDiff < 0) {
|
||||
nPalDiff = 0;
|
||||
}
|
||||
|
||||
#ifdef USE_OPENGL
|
||||
if (videoGetRenderMode() >= REND_POLYMOST) videoTintBlood(rtint, gtint, btint);
|
||||
else
|
||||
#endif
|
||||
{
|
||||
|
||||
//videoUpdatePalette(0, 256);
|
||||
g_lastpalettesum = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void TintPalette(int r, int g, int b)
|
||||
{
|
||||
palette_t *pPal = curpalettefaded;
|
||||
|
||||
if (bCamera) {
|
||||
return;
|
||||
}
|
||||
|
||||
// range limit R between 20 and 255 if positive
|
||||
if (r > 255)
|
||||
{
|
||||
r = 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (r && r < 20) {
|
||||
r = 20;
|
||||
}
|
||||
}
|
||||
|
||||
// range limit G between 20 and 255 if positive
|
||||
if (g > 255)
|
||||
{
|
||||
g = 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g && g < 20) {
|
||||
g = 20;
|
||||
}
|
||||
}
|
||||
|
||||
// range limit B between 20 and 255 if positive
|
||||
if (b > 255)
|
||||
{
|
||||
b = 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (b && b < 20) {
|
||||
b = 20;
|
||||
}
|
||||
}
|
||||
|
||||
// loc_17EFA
|
||||
if (g && gtint > 32) {
|
||||
return;
|
||||
}
|
||||
|
||||
gtint += g;
|
||||
|
||||
if (r && rtint > 256) {
|
||||
return;
|
||||
}
|
||||
|
||||
rtint += r;
|
||||
|
||||
btint += b;
|
||||
|
||||
// do not modify r, g or b variables from this point on
|
||||
int nVal;
|
||||
|
||||
// loc_17F49
|
||||
if (klabs(r) > klabs(g)) {
|
||||
nVal = klabs(r);
|
||||
}
|
||||
else {
|
||||
nVal = klabs(g);
|
||||
}
|
||||
|
||||
if (nVal < klabs(b)) {
|
||||
nVal = klabs(b);
|
||||
}
|
||||
|
||||
nPalDiff += nVal;
|
||||
|
||||
#ifdef USE_OPENGL
|
||||
if (videoGetRenderMode() >= REND_POLYMOST) videoTintBlood(rtint, gtint, btint);
|
||||
else
|
||||
#endif
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
nVal = pPal->r + r;
|
||||
if (nVal > 255) {
|
||||
nVal = 255;
|
||||
}
|
||||
pPal->r = nVal;
|
||||
|
||||
nVal = pPal->g + g;
|
||||
if (nVal > 255) {
|
||||
nVal = 255;
|
||||
}
|
||||
pPal->g = nVal;
|
||||
|
||||
nVal = pPal->b + b;
|
||||
if (nVal > 255) {
|
||||
nVal = 255;
|
||||
}
|
||||
pPal->b = nVal;
|
||||
|
||||
pPal++;
|
||||
}
|
||||
|
||||
nPalDelay = 0;
|
||||
}
|
||||
|
||||
void DoOverscanSet(short someval)
|
||||
{
|
||||
#ifdef __WATCOMC__
|
||||
union REGS regs;
|
||||
|
||||
regs.h.al = 1;
|
||||
regs.h.ah = 0x10;
|
||||
regs.h.ch = someval;
|
||||
|
||||
int386(0x10, ®s, ®s);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// unused
|
||||
void SetWhiteOverscan()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SetOverscan(int id)
|
||||
{
|
||||
if (basepaltable[id] == NULL)
|
||||
return;
|
||||
uint8_t *palette = basepaltable[id];
|
||||
int edi = 1000;
|
||||
overscanindex = 0;
|
||||
|
||||
for (int i = 0; i < 256; i++)
|
||||
{
|
||||
int ebx = 0;
|
||||
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
uint8_t cl = *palette;
|
||||
palette++;
|
||||
ebx += cl;
|
||||
}
|
||||
|
||||
if (ebx < edi)
|
||||
{
|
||||
edi = ebx;
|
||||
overscanindex = i;
|
||||
}
|
||||
}
|
||||
|
||||
DoOverscanSet(overscanindex);
|
||||
}
|
||||
END_PS_NS
|
48
source/exhumed/src/light.h
Normal file
48
source/exhumed/src/light.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __light_h__
|
||||
#define __light_h__
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
void MyLoadPalette();
|
||||
int LoadPaletteLookups();
|
||||
void WaitVBL();
|
||||
void SetGreenPal();
|
||||
void RestoreGreenPal();
|
||||
void FixPalette();
|
||||
void FadeToWhite();
|
||||
int HavePLURemap();
|
||||
uint8_t RemapPLU(uint8_t pal);
|
||||
|
||||
extern void DoOverscanSet(short someval);
|
||||
void SetOverscan(int id);
|
||||
|
||||
//extern unsigned char kenpal[];
|
||||
extern short overscanindex;
|
||||
|
||||
extern char *origpalookup[];
|
||||
|
||||
extern short nPalDiff;
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
804
source/exhumed/src/lighting.cpp
Normal file
804
source/exhumed/src/lighting.cpp
Normal file
|
@ -0,0 +1,804 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "typedefs.h"
|
||||
#include "lighting.h"
|
||||
#include "player.h"
|
||||
#include "engine.h"
|
||||
#include "exhumed.h"
|
||||
#include "sound.h"
|
||||
#include "light.h"
|
||||
#include "random.h"
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
#define kMaxFlashes 2000
|
||||
#define kMaxFlickerMask 25
|
||||
#define kMaxGlows 50
|
||||
#define kMaxFlickers 100
|
||||
#define kMaxFlows 375
|
||||
|
||||
struct Flash
|
||||
{
|
||||
char field_0;
|
||||
short field_1;
|
||||
int8_t shade;
|
||||
};
|
||||
|
||||
struct Glow
|
||||
{
|
||||
short field_0;
|
||||
short field_2;
|
||||
short nSector;
|
||||
short field_6;
|
||||
};
|
||||
|
||||
struct Flicker
|
||||
{
|
||||
short field_0;
|
||||
short nSector;
|
||||
unsigned int field_4;
|
||||
};
|
||||
|
||||
struct Flow
|
||||
{
|
||||
short field_0;
|
||||
short field_2;
|
||||
int field_4;
|
||||
int field_8;
|
||||
int field_C;
|
||||
int field_10;
|
||||
int field_14;
|
||||
int field_18;
|
||||
};
|
||||
|
||||
Flash sFlash[kMaxFlashes];
|
||||
|
||||
Glow sGlow[kMaxGlows];
|
||||
short nNextFlash[kMaxFlashes];
|
||||
Flicker sFlicker[kMaxFlickers];
|
||||
short nFreeFlash[kMaxFlashes];
|
||||
Flow sFlowInfo[kMaxFlows];
|
||||
int flickermask[kMaxFlickerMask];
|
||||
|
||||
short bTorch = 0;
|
||||
short nFirstFlash = -1;
|
||||
short nLastFlash = -1;
|
||||
short nFlashDepth = 2;
|
||||
short nFlashes;
|
||||
short nFlowCount;
|
||||
short nFlickerCount;
|
||||
short nGlowCount;
|
||||
|
||||
int bDoFlicks = 0;
|
||||
int bDoGlows = 0;
|
||||
|
||||
|
||||
static SavegameHelper sgh("lightning",
|
||||
SA(sFlash),
|
||||
SA(sGlow),
|
||||
SA(nNextFlash),
|
||||
SA(sFlicker),
|
||||
SA(nFreeFlash),
|
||||
SA(sFlowInfo),
|
||||
SA(flickermask),
|
||||
SV(bTorch),
|
||||
SV(nFirstFlash),
|
||||
SV(nLastFlash),
|
||||
SV(nFlashDepth),
|
||||
SV(nFlashes),
|
||||
SV(nFlowCount),
|
||||
SV(nFlickerCount),
|
||||
SV(nGlowCount),
|
||||
SV(bDoFlicks),
|
||||
SV(bDoGlows),
|
||||
nullptr);
|
||||
|
||||
|
||||
// done
|
||||
int GrabFlash()
|
||||
{
|
||||
if (nFlashes >= kMaxFlashes) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
short nFlash = nFreeFlash[nFlashes];
|
||||
nNextFlash[nFlash] = -1;
|
||||
|
||||
nFlashes++;
|
||||
|
||||
if (nLastFlash <= -1)
|
||||
{
|
||||
nFirstFlash = nFlash;
|
||||
}
|
||||
else
|
||||
{
|
||||
nNextFlash[nLastFlash] = nFlash;
|
||||
}
|
||||
|
||||
nLastFlash = nFlash;
|
||||
|
||||
return nLastFlash;
|
||||
}
|
||||
|
||||
void InitLights()
|
||||
{
|
||||
int i;
|
||||
nFlickerCount = 0;
|
||||
|
||||
for (i = 0; i < kMaxFlickerMask; i++) {
|
||||
flickermask[i] = RandomSize(0x1F) * 2;
|
||||
}
|
||||
|
||||
nGlowCount = 0;
|
||||
nFlowCount = 0;
|
||||
nFlashes = 0;
|
||||
bDoFlicks = kFalse;
|
||||
bDoGlows = kFalse;
|
||||
|
||||
for (i = 0; i < kMaxFlashes; i++) {
|
||||
nFreeFlash[i] = i;
|
||||
}
|
||||
|
||||
nFirstFlash = -1;
|
||||
nLastFlash = -1;
|
||||
}
|
||||
|
||||
void AddFlash(short nSector, int x, int y, int z, int val)
|
||||
{
|
||||
assert(nSector >= 0 && nSector < kMaxSectors);
|
||||
|
||||
int var_28 = 0;
|
||||
unsigned int var_1C = val >> 8;
|
||||
|
||||
if (var_1C >= nFlashDepth) {
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int var_20 = val & 0x80;
|
||||
unsigned int var_18 = val & 0x40;
|
||||
|
||||
val = ((var_1C + 1) << 8) | char(val);
|
||||
|
||||
int var_14 = 0;
|
||||
|
||||
short startwall = sector[nSector].wallptr;
|
||||
short endwall = sector[nSector].wallptr + sector[nSector].wallnum;
|
||||
|
||||
for (int i = startwall; i < endwall; i++)
|
||||
{
|
||||
short wall2 = wall[i].point2;
|
||||
|
||||
int xAverage = (wall[i].x + wall[wall2].x) / 2;
|
||||
int yAverage = (wall[i].y + wall[wall2].y) / 2;
|
||||
|
||||
sectortype *pNextSector = NULL;
|
||||
if (wall[i].nextsector > -1) {
|
||||
pNextSector = §or[wall[i].nextsector];
|
||||
}
|
||||
|
||||
int ebx = -255;
|
||||
|
||||
if (!var_18)
|
||||
{
|
||||
int x2 = x - xAverage;
|
||||
if (x2 < 0) {
|
||||
x2 = -x2;
|
||||
}
|
||||
|
||||
ebx = x2;
|
||||
|
||||
int y2 = y - yAverage;
|
||||
if (y2 < 0) {
|
||||
y2 = -y2;
|
||||
}
|
||||
|
||||
ebx = ((y2 + ebx) >> 4) - 255;
|
||||
}
|
||||
|
||||
if (ebx < 0)
|
||||
{
|
||||
var_14++;
|
||||
var_28 += ebx;
|
||||
|
||||
if (wall[i].pal < 5)
|
||||
{
|
||||
if (!pNextSector || pNextSector->floorz < sector[nSector].floorz)
|
||||
{
|
||||
short nFlash = GrabFlash();
|
||||
if (nFlash < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
sFlash[nFlash].field_0 = var_20 | 2;
|
||||
sFlash[nFlash].shade = wall[i].shade;
|
||||
sFlash[nFlash].field_1 = i;
|
||||
|
||||
wall[i].pal += 7;
|
||||
|
||||
ebx += wall[i].shade;
|
||||
int eax = ebx;
|
||||
|
||||
if (ebx < -127) {
|
||||
eax = -127;
|
||||
}
|
||||
|
||||
wall[i].shade = eax;
|
||||
|
||||
if (!var_1C && !wall[i].overpicnum && pNextSector)
|
||||
{
|
||||
AddFlash(wall[i].nextsector, x, y, z, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (var_14 && sector[nSector].floorpal < 4)
|
||||
{
|
||||
short nFlash = GrabFlash();
|
||||
if (nFlash < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
sFlash[nFlash].field_0 = var_20 | 1;
|
||||
sFlash[nFlash].field_1 = nSector;
|
||||
sFlash[nFlash].shade = sector[nSector].floorshade;
|
||||
|
||||
sector[nSector].floorpal += 7;
|
||||
|
||||
int edx = sector[nSector].floorshade + var_28;
|
||||
int eax = edx;
|
||||
|
||||
if (edx < -127) {
|
||||
eax = -127;
|
||||
}
|
||||
|
||||
sector[nSector].floorshade = eax;
|
||||
|
||||
if (!(sector[nSector].ceilingstat & 1))
|
||||
{
|
||||
if (sector[nSector].ceilingpal < 4)
|
||||
{
|
||||
short nFlash2 = GrabFlash();
|
||||
if (nFlash2 >= 0)
|
||||
{
|
||||
sFlash[nFlash2].field_0 = var_20 | 3;
|
||||
sFlash[nFlash2].field_1 = nSector;
|
||||
sFlash[nFlash2].shade = sector[nSector].ceilingshade;
|
||||
|
||||
sector[nSector].ceilingpal += 7;
|
||||
|
||||
int edx = sector[nSector].ceilingshade + var_28;
|
||||
int eax = edx;
|
||||
|
||||
if (edx < -127) {
|
||||
eax = -127;
|
||||
}
|
||||
|
||||
sector[nSector].ceilingshade = eax;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (short nSprite = headspritesect[nSector]; nSprite >= 0; nSprite = nextspritesect[nSprite])
|
||||
{
|
||||
if (sprite[nSprite].pal < 4)
|
||||
{
|
||||
short nFlash3 = GrabFlash();
|
||||
if (nFlash3 >= 0)
|
||||
{
|
||||
sFlash[nFlash3].field_0 = var_20 | 4;
|
||||
sFlash[nFlash3].shade = sprite[nSprite].shade;
|
||||
sFlash[nFlash3].field_1 = nSprite;
|
||||
|
||||
sprite[nSprite].pal += 7;
|
||||
|
||||
int eax = -255;
|
||||
|
||||
if (!var_18)
|
||||
{
|
||||
int xDiff = x - sprite[nSprite].x;
|
||||
if (xDiff < 0) {
|
||||
xDiff = -xDiff;
|
||||
}
|
||||
|
||||
int yDiff = y - sprite[nSprite].y;
|
||||
if (yDiff < 0) {
|
||||
yDiff = -yDiff;
|
||||
}
|
||||
|
||||
eax = ((xDiff + yDiff) >> 4) - 255;
|
||||
}
|
||||
|
||||
if (eax < 0)
|
||||
{
|
||||
short shade = sprite[nSprite].shade + eax;
|
||||
if (shade < -127) {
|
||||
shade = -127;
|
||||
}
|
||||
|
||||
sprite[nSprite].shade = shade;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UndoFlashes()
|
||||
{
|
||||
if (!nFlashes) {
|
||||
return;
|
||||
}
|
||||
|
||||
int var_24 = 0; // CHECKME - Watcom error "initializer for variable var_24 may not execute
|
||||
|
||||
int edi = -1;
|
||||
|
||||
for (short nFlash = nFirstFlash; nFlash >= 0; nFlash = nNextFlash[nFlash])
|
||||
{
|
||||
assert(nFlash < 2000 && nFlash >= 0);
|
||||
|
||||
uint8_t var_28 = sFlash[nFlash].field_0 & 0x3F;
|
||||
short nIndex = sFlash[nFlash].field_1;
|
||||
|
||||
if (sFlash[nFlash].field_0 & 0x80)
|
||||
{
|
||||
int var_20 = var_28 - 1;
|
||||
assert(var_20 >= 0);
|
||||
|
||||
int8_t *pShade = NULL;
|
||||
|
||||
switch (var_20)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
assert(nIndex >= 0 && nIndex < kMaxSectors);
|
||||
|
||||
pShade = §or[nIndex].floorshade;
|
||||
break;
|
||||
}
|
||||
|
||||
case 1:
|
||||
{
|
||||
assert(nIndex >= 0 && nIndex < kMaxWalls);
|
||||
|
||||
pShade = &wall[nIndex].shade;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
assert(nIndex >= 0 && nIndex < kMaxSectors);
|
||||
|
||||
pShade = §or[nIndex].ceilingshade;
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
assert(nIndex >= 0 && nIndex < kMaxSprites);
|
||||
|
||||
if (sprite[nIndex].pal >= 7)
|
||||
{
|
||||
pShade = &sprite[nIndex].shade;
|
||||
}
|
||||
else {
|
||||
goto loc_1868A;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
assert(pShade != NULL);
|
||||
|
||||
short var_2C = (*pShade) + 6;
|
||||
int var_30 = sFlash[nFlash].shade;
|
||||
|
||||
if (var_2C < var_30)
|
||||
{
|
||||
*pShade = var_2C;
|
||||
edi = nFlash;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// loc_185FE
|
||||
var_24 = var_28 - 1; // CHECKME - Watcom error "initializer for variable var_24 may not execute
|
||||
assert(var_24 >= 0);
|
||||
|
||||
switch (var_24)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
||||
case 0:
|
||||
{
|
||||
sector[nIndex].floorpal -= 7;
|
||||
sector[nIndex].floorshade = sFlash[nFlash].shade;
|
||||
break;
|
||||
}
|
||||
|
||||
case 1:
|
||||
{
|
||||
wall[nIndex].pal -= 7;
|
||||
wall[nIndex].shade = sFlash[nFlash].shade;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
sector[nIndex].ceilingpal -= 7;
|
||||
sector[nIndex].ceilingshade = sFlash[nFlash].shade;
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
if (sprite[nIndex].pal >= 7)
|
||||
{
|
||||
sprite[nIndex].pal -= 7;
|
||||
sprite[nIndex].shade = sFlash[nFlash].shade;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
loc_1868A:
|
||||
|
||||
nFlashes--;
|
||||
assert(nFlashes >= 0);
|
||||
|
||||
nFreeFlash[nFlashes] = nFlash;
|
||||
|
||||
if (edi != -1)
|
||||
{
|
||||
nNextFlash[edi] = nNextFlash[nFlash];
|
||||
}
|
||||
|
||||
if (nFlash == nFirstFlash)
|
||||
{
|
||||
nFirstFlash = nNextFlash[nFirstFlash];
|
||||
}
|
||||
|
||||
if (nFlash == nLastFlash)
|
||||
{
|
||||
nLastFlash = edi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AddGlow(short nSector, int nVal)
|
||||
{
|
||||
if (nGlowCount >= kMaxGlows) {
|
||||
return;
|
||||
}
|
||||
|
||||
sGlow[nGlowCount].field_6 = nVal;
|
||||
sGlow[nGlowCount].nSector = nSector;
|
||||
sGlow[nGlowCount].field_0 = -1;
|
||||
sGlow[nGlowCount].field_2 = 0;
|
||||
|
||||
nGlowCount++;
|
||||
}
|
||||
|
||||
// ok
|
||||
void AddFlicker(short nSector, int nVal)
|
||||
{
|
||||
if (nFlickerCount >= kMaxFlickers) {
|
||||
return;
|
||||
}
|
||||
|
||||
sFlicker[nFlickerCount].field_0 = nVal;
|
||||
sFlicker[nFlickerCount].nSector = nSector;
|
||||
|
||||
if (nVal >= 25) {
|
||||
nVal = 24;
|
||||
}
|
||||
|
||||
sFlicker[nFlickerCount].field_4 = flickermask[nVal];
|
||||
|
||||
nFlickerCount++;
|
||||
}
|
||||
|
||||
void DoGlows()
|
||||
{
|
||||
bDoGlows++;
|
||||
|
||||
if (bDoGlows < 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
bDoGlows = 0;
|
||||
|
||||
for (int i = 0; i < nGlowCount; i++)
|
||||
{
|
||||
sGlow[i].field_2++;
|
||||
|
||||
short nSector = sGlow[i].nSector;
|
||||
short nShade = sGlow[i].field_0;
|
||||
|
||||
if (sGlow[i].field_2 >= sGlow[i].field_6)
|
||||
{
|
||||
sGlow[i].field_2 = 0;
|
||||
sGlow[i].field_0 = -sGlow[i].field_0;
|
||||
}
|
||||
|
||||
sector[nSector].ceilingshade += nShade;
|
||||
sector[nSector].floorshade += nShade;
|
||||
|
||||
int startwall = sector[nSector].wallptr;
|
||||
int endwall = startwall + sector[nSector].wallnum - 1;
|
||||
|
||||
for (int nWall = startwall; nWall <= endwall; nWall++)
|
||||
{
|
||||
wall[nWall].shade += nShade;
|
||||
|
||||
// CHECKME - ASM has edx decreasing here. why?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoFlickers()
|
||||
{
|
||||
bDoFlicks ^= 1;
|
||||
if (!bDoFlicks) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < nFlickerCount; i++)
|
||||
{
|
||||
short nSector = sFlicker[i].nSector;
|
||||
|
||||
unsigned int eax = (sFlicker[i].field_4 & 1);
|
||||
unsigned int edx = (sFlicker[i].field_4 & 1) << 31;
|
||||
unsigned int ebp = sFlicker[i].field_4 >> 1;
|
||||
|
||||
ebp |= edx;
|
||||
edx = ebp & 1;
|
||||
|
||||
sFlicker[i].field_4 = ebp;
|
||||
|
||||
if (edx ^ eax)
|
||||
{
|
||||
short shade;
|
||||
|
||||
if (eax)
|
||||
{
|
||||
shade = sFlicker[i].field_0;
|
||||
}
|
||||
else
|
||||
{
|
||||
shade = -sFlicker[i].field_0;
|
||||
}
|
||||
|
||||
sector[nSector].ceilingshade += shade;
|
||||
sector[nSector].floorshade += shade;
|
||||
|
||||
int startwall = sector[nSector].wallptr;
|
||||
int endwall = startwall + sector[nSector].wallnum - 1;
|
||||
|
||||
for (int nWall = endwall; nWall >= startwall; nWall--)
|
||||
{
|
||||
wall[nWall].shade += shade;
|
||||
|
||||
// CHECKME - ASM has edx decreasing here. why?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// nWall can also be passed in here via nSprite parameter - TODO - rename nSprite parameter :)
|
||||
void AddFlow(int nSprite, int a, int b)
|
||||
{
|
||||
if (nFlowCount >= kMaxFlows)
|
||||
return;
|
||||
|
||||
short nFlow = nFlowCount;
|
||||
nFlowCount++;
|
||||
|
||||
short var_18;
|
||||
|
||||
if (b < 2)
|
||||
{
|
||||
var_18 = sprite[nSprite].sectnum;
|
||||
short nPic = sector[var_18].floorpicnum;
|
||||
short nAngle = sprite[nSprite].ang;
|
||||
|
||||
sFlowInfo[nFlow].field_14 = (tilesiz[nPic].x << 14) - 1;
|
||||
sFlowInfo[nFlow].field_18 = (tilesiz[nPic].y << 14) - 1;
|
||||
sFlowInfo[nFlow].field_C = -Cos(nAngle) * a;
|
||||
sFlowInfo[nFlow].field_10 = Sin(nAngle) * a;
|
||||
}
|
||||
else
|
||||
{
|
||||
short nAngle;
|
||||
|
||||
if (b == 2) {
|
||||
nAngle = 512;
|
||||
}
|
||||
else {
|
||||
nAngle = 1536;
|
||||
}
|
||||
|
||||
var_18 = nSprite;
|
||||
short nPic = wall[var_18].picnum;
|
||||
|
||||
sFlowInfo[nFlow].field_14 = (tilesiz[nPic].x * wall[var_18].xrepeat) << 8;
|
||||
sFlowInfo[nFlow].field_18 = (tilesiz[nPic].y * wall[var_18].yrepeat) << 8;
|
||||
sFlowInfo[nFlow].field_C = -Cos(nAngle) * a;
|
||||
sFlowInfo[nFlow].field_10 = Sin(nAngle) * a;
|
||||
}
|
||||
|
||||
sFlowInfo[nFlow].field_8 = 0;
|
||||
sFlowInfo[nFlow].field_4 = 0;
|
||||
sFlowInfo[nFlow].field_0 = var_18;
|
||||
sFlowInfo[nFlow].field_2 = b;
|
||||
}
|
||||
|
||||
void DoFlows()
|
||||
{
|
||||
for (int i = 0; i < nFlowCount; i++)
|
||||
{
|
||||
sFlowInfo[i].field_4 += sFlowInfo[i].field_C;
|
||||
sFlowInfo[i].field_8 += sFlowInfo[i].field_10;
|
||||
|
||||
switch (sFlowInfo[i].field_2)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
sFlowInfo[i].field_4 &= sFlowInfo[i].field_14;
|
||||
sFlowInfo[i].field_8 &= sFlowInfo[i].field_18;
|
||||
|
||||
short nSector = sFlowInfo[i].field_0;
|
||||
sector[nSector].floorxpanning = sFlowInfo[i].field_4 >> 14;
|
||||
sector[nSector].floorypanning = sFlowInfo[i].field_8 >> 14;
|
||||
break;
|
||||
}
|
||||
|
||||
case 1:
|
||||
{
|
||||
short nSector = sFlowInfo[i].field_0;
|
||||
|
||||
sector[nSector].ceilingxpanning = sFlowInfo[i].field_4 >> 14;
|
||||
sector[nSector].ceilingypanning = sFlowInfo[i].field_8 >> 14;
|
||||
|
||||
sFlowInfo[i].field_4 &= sFlowInfo[i].field_14;
|
||||
sFlowInfo[i].field_8 &= sFlowInfo[i].field_18;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
short nWall = sFlowInfo[i].field_0;
|
||||
|
||||
wall[nWall].xpanning = sFlowInfo[i].field_4 >> 14;
|
||||
wall[nWall].ypanning = sFlowInfo[i].field_8 >> 14;
|
||||
|
||||
if (sFlowInfo[i].field_4 < 0)
|
||||
{
|
||||
sFlowInfo[i].field_4 += sFlowInfo[i].field_14;
|
||||
}
|
||||
|
||||
if (sFlowInfo[i].field_8 < 0)
|
||||
{
|
||||
sFlowInfo[i].field_8 += sFlowInfo[i].field_18;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
short nWall = sFlowInfo[i].field_0;
|
||||
|
||||
wall[nWall].xpanning = sFlowInfo[i].field_4 >> 14;
|
||||
wall[nWall].ypanning = sFlowInfo[i].field_8 >> 14;
|
||||
|
||||
if (sFlowInfo[i].field_4 >= sFlowInfo[i].field_14)
|
||||
{
|
||||
sFlowInfo[i].field_4 -= sFlowInfo[i].field_14;
|
||||
}
|
||||
|
||||
if (sFlowInfo[i].field_8 >= sFlowInfo[i].field_18)
|
||||
{
|
||||
sFlowInfo[i].field_8 -= sFlowInfo[i].field_18;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DoLights()
|
||||
{
|
||||
DoFlickers();
|
||||
DoGlows();
|
||||
DoFlows();
|
||||
}
|
||||
|
||||
void SetTorch(int nPlayer, int bTorchOnOff)
|
||||
{
|
||||
char buf[40];
|
||||
|
||||
if (bTorchOnOff == bTorch) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nPlayer != nLocalPlayer) {
|
||||
return;
|
||||
}
|
||||
|
||||
// char *pTempPal = origpalookup[kPalTorch];
|
||||
// palookup[kPalTorch] = palookup[kPalNoTorch];
|
||||
// palookup[kPalNoTorch] = pTempPal;
|
||||
//
|
||||
// pTempPal = origpalookup[kPalTorch];
|
||||
// origpalookup[kPalTorch] = origpalookup[kPalNoTorch];
|
||||
// origpalookup[kPalNoTorch] = pTempPal;
|
||||
//
|
||||
// pTempPal = origpalookup[kPalTorch2];
|
||||
// origpalookup[kPalTorch2] = origpalookup[kPalNoTorch2];
|
||||
// origpalookup[kPalNoTorch2] = pTempPal;
|
||||
//
|
||||
// pTempPal = palookup[kPalTorch2];
|
||||
// palookup[kPalNoTorch2] = palookup[kPalTorch2];
|
||||
// palookup[kPalTorch2] = pTempPal;
|
||||
|
||||
if (bTorchOnOff == 2) {
|
||||
bTorch = !bTorch;
|
||||
}
|
||||
else {
|
||||
bTorch = bTorchOnOff;
|
||||
}
|
||||
|
||||
if (bTorch) {
|
||||
PlayLocalSound(kSoundTorchOn, 0);
|
||||
}
|
||||
|
||||
strcpy(buf, "TORCH IS ");
|
||||
|
||||
if (bTorch) {
|
||||
strcat(buf, "LIT");
|
||||
}
|
||||
else {
|
||||
strcat(buf, "OUT");
|
||||
}
|
||||
|
||||
StatusMessage(150, buf);
|
||||
}
|
||||
|
||||
void BuildFlash(short nPlayer, short UNUSED(nSector), int nVal)
|
||||
{
|
||||
if (nPlayer == nLocalPlayer)
|
||||
{
|
||||
flash = nVal;
|
||||
flash = -nVal; // ???
|
||||
}
|
||||
}
|
||||
|
||||
END_PS_NS
|
40
source/exhumed/src/lighting.h
Normal file
40
source/exhumed/src/lighting.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __lighting_h__
|
||||
#define __lighting_h__
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
extern short nFlashDepth;
|
||||
|
||||
void InitLights();
|
||||
void AddFlash(short nSector, int x, int y, int z, int val);
|
||||
void SetTorch(int nPlayer, int bTorchOnOff);
|
||||
void UndoFlashes();
|
||||
void DoLights();
|
||||
void AddFlow(int nSprite, int a, int b);
|
||||
void BuildFlash(short nPlayer, short nSector, int nVal);
|
||||
void AddGlow(short nSector, int nVal);
|
||||
void AddFlicker(short nSector, int nVal);
|
||||
|
||||
extern short bTorch;
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
598
source/exhumed/src/lion.cpp
Normal file
598
source/exhumed/src/lion.cpp
Normal file
|
@ -0,0 +1,598 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "lion.h"
|
||||
#include "engine.h"
|
||||
#include "runlist.h"
|
||||
#include "exhumed.h"
|
||||
#include "sequence.h"
|
||||
#include "move.h"
|
||||
#include "sound.h"
|
||||
#include "random.h"
|
||||
#include "trigdat.h"
|
||||
#include "items.h"
|
||||
#include <assert.h>
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
#define kMaxLions 40
|
||||
|
||||
short LionCount = -1;
|
||||
|
||||
short MoveHook[kMaxLions];
|
||||
|
||||
static actionSeq ActionSeq[] = {{54, 1}, {18, 1}, {0, 0}, {10, 0}, {44, 0}, {18, 0}, {26, 0}, {34, 0}, {8, 1}, {9, 1}, {52, 1}, {53, 1}};
|
||||
|
||||
struct Lion
|
||||
{
|
||||
short nHealth;
|
||||
short _b;
|
||||
short nAction;
|
||||
short nSprite;
|
||||
short nTarget;
|
||||
short _f;
|
||||
short _g;
|
||||
short _h;
|
||||
};
|
||||
|
||||
Lion LionList[kMaxLions];
|
||||
|
||||
static SavegameHelper sgh("lion",
|
||||
SV(LionCount),
|
||||
SA(MoveHook),
|
||||
SA(LionList),
|
||||
nullptr);
|
||||
|
||||
|
||||
void InitLion()
|
||||
{
|
||||
LionCount = kMaxLions;
|
||||
}
|
||||
|
||||
int BuildLion(short nSprite, int x, int y, int z, short nSector, short nAngle)
|
||||
{
|
||||
LionCount--;
|
||||
short nLion = LionCount;
|
||||
|
||||
if (LionCount < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nSprite == -1)
|
||||
{
|
||||
nSprite = insertsprite(nSector, 104);
|
||||
}
|
||||
else
|
||||
{
|
||||
changespritestat(nSprite, 104);
|
||||
x = sprite[nSprite].x;
|
||||
y = sprite[nSprite].y;
|
||||
z = sector[sprite[nSprite].sectnum].floorz;
|
||||
nAngle = sprite[nSprite].ang;
|
||||
|
||||
}
|
||||
|
||||
assert(nSprite >= 0 && nSprite < kMaxSprites);
|
||||
|
||||
sprite[nSprite].x = x;
|
||||
sprite[nSprite].y = y;
|
||||
sprite[nSprite].z = z;
|
||||
sprite[nSprite].cstat = 0x101;
|
||||
sprite[nSprite].clipdist = 60;
|
||||
sprite[nSprite].shade = -12;
|
||||
sprite[nSprite].xrepeat = 40;
|
||||
sprite[nSprite].yrepeat = 40;
|
||||
sprite[nSprite].picnum = 1;
|
||||
sprite[nSprite].pal = sector[sprite[nSprite].sectnum].ceilingpal;
|
||||
sprite[nSprite].xoffset = 0;
|
||||
sprite[nSprite].yoffset = 0;
|
||||
sprite[nSprite].ang = nAngle;
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].zvel = 0;
|
||||
sprite[nSprite].lotag = runlist_HeadRun() + 1;
|
||||
sprite[nSprite].hitag = 0;
|
||||
sprite[nSprite].extra = -1;
|
||||
|
||||
// GrabTimeSlot(3);
|
||||
|
||||
LionList[nLion].nAction = 0;
|
||||
LionList[nLion].nHealth = 500;
|
||||
LionList[nLion]._b = 0;
|
||||
LionList[nLion].nSprite = nSprite;
|
||||
LionList[nLion].nTarget = -1;
|
||||
LionList[nLion]._g = 0;
|
||||
LionList[nLion]._f = nLion;
|
||||
|
||||
sprite[nSprite].owner = runlist_AddRunRec(sprite[nSprite].lotag - 1, nLion | 0x130000);
|
||||
|
||||
MoveHook[nLion] = runlist_AddRunRec(NewRun, nLion | 0x130000);
|
||||
|
||||
nCreaturesLeft++;
|
||||
|
||||
return nLion | 0x130000;
|
||||
}
|
||||
|
||||
void FuncLion(int a, int nDamage, int nRun)
|
||||
{
|
||||
int var_18 = 0;
|
||||
|
||||
short nLion = RunData[nRun].nVal;
|
||||
assert(nLion >= 0 && nLion < kMaxLions);
|
||||
|
||||
short nSprite = LionList[nLion].nSprite;
|
||||
short nAction = LionList[nLion].nAction;
|
||||
|
||||
int nMessage = a & 0x7F0000;
|
||||
|
||||
switch (nMessage)
|
||||
{
|
||||
default:
|
||||
{
|
||||
Printf("unknown msg %d for Lion\n", nMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x90000:
|
||||
{
|
||||
seq_PlotSequence(a, SeqOffsets[kSeqLion] + ActionSeq[nAction].a, LionList[nLion]._b, ActionSeq[nAction].b);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0xA0000:
|
||||
{
|
||||
nDamage = runlist_CheckRadialDamage(nSprite);
|
||||
// now fall through to 0x80000
|
||||
fallthrough__;
|
||||
}
|
||||
case 0x80000:
|
||||
{
|
||||
if (nDamage && LionList[nLion].nHealth > 0)
|
||||
{
|
||||
LionList[nLion].nHealth -= nDamage;
|
||||
if (LionList[nLion].nHealth <= 0)
|
||||
{
|
||||
// R.I.P.
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].zvel = 0;
|
||||
LionList[nLion].nHealth = 0;
|
||||
sprite[nSprite].cstat &= 0xFEFE;
|
||||
|
||||
nCreaturesLeft--;
|
||||
|
||||
if (nAction < 10)
|
||||
{
|
||||
DropMagic(nSprite);
|
||||
|
||||
if (nMessage == 0xA0000) {
|
||||
LionList[nLion].nAction = 11;
|
||||
}
|
||||
else
|
||||
{
|
||||
LionList[nLion].nAction = 10;
|
||||
}
|
||||
|
||||
LionList[nLion]._b = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
short nTarget = a & 0xFFFF;
|
||||
|
||||
if (nTarget > -1)
|
||||
{
|
||||
if (sprite[nTarget].statnum < 199) {
|
||||
LionList[nLion].nTarget = nTarget;
|
||||
}
|
||||
|
||||
if (nAction != 6)
|
||||
{
|
||||
if (RandomSize(8) <= (LionList[nLion].nHealth >> 2))
|
||||
{
|
||||
LionList[nLion].nAction = 4;
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
}
|
||||
else if (RandomSize(1))
|
||||
{
|
||||
PlotCourseToSprite(nSprite, nTarget);
|
||||
LionList[nLion].nAction = 5;
|
||||
LionList[nLion]._g = RandomSize(3);
|
||||
|
||||
sprite[nSprite].ang = (sprite[nSprite].ang - (RandomSize(1) << 8)) + (RandomSize(1) << 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
LionList[nLion].nAction = 8;
|
||||
sprite[nSprite].cstat &= 0xFEFE;
|
||||
}
|
||||
|
||||
LionList[nLion]._b = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x20000:
|
||||
{
|
||||
if (nAction != 7) {
|
||||
Gravity(nSprite);
|
||||
}
|
||||
|
||||
short nSeq = SeqOffsets[kSeqLion] + ActionSeq[nAction].a;
|
||||
|
||||
sprite[nSprite].picnum = seq_GetSeqPicnum2(nSeq, LionList[nLion]._b);
|
||||
|
||||
seq_MoveSequence(nSprite, nSeq, LionList[nLion]._b);
|
||||
|
||||
LionList[nLion]._b++;
|
||||
if (LionList[nLion]._b >= SeqSize[nSeq])
|
||||
{
|
||||
LionList[nLion]._b = 0;
|
||||
var_18 = 1;
|
||||
}
|
||||
|
||||
short nFlag = FrameFlag[SeqBase[nSeq] + LionList[nLion]._b];
|
||||
short nTarget = LionList[nLion].nTarget;
|
||||
|
||||
int nVal = MoveCreatureWithCaution(nSprite);
|
||||
|
||||
switch (nAction)
|
||||
{
|
||||
default:
|
||||
return;
|
||||
|
||||
case 0:
|
||||
case 1:
|
||||
{
|
||||
if ((LionList[nLion]._f & 31) == (totalmoves & 31))
|
||||
{
|
||||
if (nTarget < 0)
|
||||
{
|
||||
nTarget = FindPlayer(nSprite, 40);
|
||||
if (nTarget >= 0)
|
||||
{
|
||||
D3PlayFX(StaticSound[kSound24], nSprite);
|
||||
LionList[nLion].nAction = 2;
|
||||
LionList[nLion]._b = 0;
|
||||
|
||||
sprite[nSprite].xvel = Sin(sprite[nSprite].ang + 512) >> 1;
|
||||
sprite[nSprite].yvel = Sin(sprite[nSprite].ang) >> 1;
|
||||
LionList[nLion].nTarget = nTarget;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nAction)
|
||||
{
|
||||
LionList[nLion]._g--;
|
||||
if (LionList[nLion]._g <= 0)
|
||||
{
|
||||
if (RandomBit())
|
||||
{
|
||||
sprite[nSprite].ang = RandomWord() & kAngleMask;
|
||||
sprite[nSprite].xvel = Sin(sprite[nSprite].ang + 512) >> 1;
|
||||
sprite[nSprite].yvel = Sin(sprite[nSprite].ang) >> 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
}
|
||||
|
||||
LionList[nLion]._g = 100;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
if ((totalmoves & 0x1F) == (LionList[nLion]._f & 0x1F))
|
||||
{
|
||||
PlotCourseToSprite(nSprite, nTarget);
|
||||
|
||||
short nAng = sprite[nSprite].ang & 0xFFF8;
|
||||
|
||||
if (sprite[nSprite].cstat & 0x8000)
|
||||
{
|
||||
sprite[nSprite].xvel = Sin(nAng + 512) * 2;
|
||||
sprite[nSprite].yvel = Sin(nAng) * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite[nSprite].xvel = Sin(nAng + 512) >> 1;
|
||||
sprite[nSprite].yvel = Sin(nAng) >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((nVal & 0xC000) < 0x8000)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if ((nVal & 0xC000) == 0x8000)
|
||||
{
|
||||
// loc_378FA:
|
||||
sprite[nSprite].ang = (sprite[nSprite].ang + 256) & kAngleMask;
|
||||
sprite[nSprite].xvel = Sin(sprite[nSprite].ang + 512) >> 1;
|
||||
sprite[nSprite].yvel = Sin(sprite[nSprite].ang) >> 1;
|
||||
break;
|
||||
}
|
||||
else if ((nVal & 0xC000) == 0xC000)
|
||||
{
|
||||
if ((nVal & 0x3FFF) == nTarget)
|
||||
{
|
||||
if (sprite[nSprite].cstat & 0x8000)
|
||||
{
|
||||
LionList[nLion].nAction = 9;
|
||||
sprite[nSprite].cstat &= 0x7FFF;
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
int nAng = getangle(sprite[nTarget].x - sprite[nSprite].x, sprite[nTarget].y - sprite[nSprite].y);
|
||||
|
||||
if (AngleDiff(sprite[nSprite].ang, nAng) < 64)
|
||||
{
|
||||
LionList[nLion].nAction = 3;
|
||||
}
|
||||
}
|
||||
|
||||
LionList[nLion]._b = 0;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// loc_378FA:
|
||||
sprite[nSprite].ang = (sprite[nSprite].ang + 256) & kAngleMask;
|
||||
sprite[nSprite].xvel = Sin(sprite[nSprite].ang + 512) >> 1;
|
||||
sprite[nSprite].yvel = Sin(sprite[nSprite].ang) >> 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
if (nTarget == -1)
|
||||
{
|
||||
LionList[nLion].nAction = 1;
|
||||
LionList[nLion]._g = 50;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PlotCourseToSprite(nSprite, nTarget) >= 768)
|
||||
{
|
||||
LionList[nLion].nAction = 2;
|
||||
}
|
||||
else if (nFlag & 0x80)
|
||||
{
|
||||
runlist_DamageEnemy(nTarget, nSprite, 10);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
if (var_18)
|
||||
{
|
||||
LionList[nLion].nAction = 2;
|
||||
LionList[nLion]._b = 0;
|
||||
}
|
||||
|
||||
if (nVal & 0x20000)
|
||||
{
|
||||
sprite[nSprite].xvel >>= 1;
|
||||
sprite[nSprite].yvel >>= 1;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case 5:
|
||||
{
|
||||
LionList[nLion]._g--;
|
||||
if (LionList[nLion]._g <= 0)
|
||||
{
|
||||
sprite[nSprite].zvel = -4000;
|
||||
LionList[nLion]._g = 0;
|
||||
|
||||
int x = sprite[nSprite].x;
|
||||
int y = sprite[nSprite].y;
|
||||
int z = sprite[nSprite].z - (GetSpriteHeight(nSprite) >> 1);
|
||||
|
||||
int var_40 = 0x7FFFFFFF;
|
||||
|
||||
short var_28 = sprite[nSprite].ang;
|
||||
|
||||
short nAng = (sprite[nSprite].ang - 512) & kAngleMask;
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
short hitwall;
|
||||
int hitx, hity;
|
||||
vec3_t startPos = { x, y, z };
|
||||
hitdata_t hitData;
|
||||
hitscan(&startPos, sprite[nSprite].sectnum, Sin(nAng + 512), Sin(nAng), 0, &hitData, CLIPMASK1);
|
||||
hitx = hitData.pos.x;
|
||||
hity = hitData.pos.y;
|
||||
hitwall = hitData.wall;
|
||||
|
||||
if (hitwall > -1)
|
||||
{
|
||||
int ebx = klabs(hitx - x);
|
||||
int eax = klabs(hity - y);
|
||||
|
||||
ebx += eax;
|
||||
|
||||
if (ebx < var_40)
|
||||
{
|
||||
var_40 = ebx;
|
||||
var_28 = nAng;
|
||||
}
|
||||
}
|
||||
|
||||
nAng += 256;
|
||||
nAng &= kAngleMask;
|
||||
}
|
||||
|
||||
sprite[nSprite].ang = var_28;
|
||||
|
||||
LionList[nLion].nAction = 6;
|
||||
sprite[nSprite].xvel = (Sin(sprite[nSprite].ang + 512)) - (Sin(sprite[nSprite].ang + 512) >> 3);
|
||||
sprite[nSprite].yvel = (Sin(sprite[nSprite].ang)) - (Sin(sprite[nSprite].ang) >> 3);
|
||||
D3PlayFX(StaticSound[kSound24], nSprite);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case 6:
|
||||
{
|
||||
if (nVal & 0x30000)
|
||||
{
|
||||
LionList[nLion].nAction = 2;
|
||||
LionList[nLion]._b = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((nVal & 0xC000) == 0x8000)
|
||||
{
|
||||
LionList[nLion].nAction = 7;
|
||||
sprite[nSprite].ang = (GetWallNormal(nVal & 0x3FFF) + 1024) & kAngleMask;
|
||||
LionList[nLion]._g = RandomSize(4);
|
||||
return;
|
||||
}
|
||||
else if ((nVal & 0xC000) == 0xC000)
|
||||
{
|
||||
if ((nVal & 0x3FFF) == nTarget)
|
||||
{
|
||||
int nAng = getangle(sprite[nTarget].x - sprite[nSprite].x, sprite[nTarget].y - sprite[nSprite].y);
|
||||
if (AngleDiff(sprite[nSprite].ang, nAng) < 64)
|
||||
{
|
||||
LionList[nLion].nAction = 3;
|
||||
LionList[nLion]._b = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// loc_378FA:
|
||||
sprite[nSprite].ang = (sprite[nSprite].ang + 256) & kAngleMask;
|
||||
sprite[nSprite].xvel = Sin(sprite[nSprite].ang + 512) >> 1;
|
||||
sprite[nSprite].yvel = Sin(sprite[nSprite].ang) >> 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case 7:
|
||||
{
|
||||
LionList[nLion]._g--;
|
||||
|
||||
if (LionList[nLion]._g <= 0)
|
||||
{
|
||||
LionList[nLion]._g = 0;
|
||||
if (nTarget > -1)
|
||||
{
|
||||
PlotCourseToSprite(nSprite, nTarget);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite[nSprite].ang = (RandomSize(9) + (sprite[nSprite].ang + 768)) & kAngleMask;
|
||||
}
|
||||
|
||||
sprite[nSprite].zvel = -1000;
|
||||
|
||||
LionList[nLion].nAction = 6;
|
||||
sprite[nSprite].xvel = (Sin(sprite[nSprite].ang + 512)) - (Sin(sprite[nSprite].ang + 512) >> 3);
|
||||
sprite[nSprite].yvel = (Sin(sprite[nSprite].ang)) - (Sin(sprite[nSprite].ang) >> 3);
|
||||
D3PlayFX(StaticSound[kSound24], nSprite);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case 8:
|
||||
{
|
||||
if (var_18)
|
||||
{
|
||||
LionList[nLion].nAction = 2;
|
||||
LionList[nLion]._b = 0;
|
||||
sprite[nSprite].cstat |= 0x8000;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case 9:
|
||||
{
|
||||
if (var_18)
|
||||
{
|
||||
LionList[nLion]._b = 0;
|
||||
LionList[nLion].nAction = 2;
|
||||
sprite[nSprite].cstat |= 0x101;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case 10:
|
||||
case 11:
|
||||
{
|
||||
if (var_18)
|
||||
{
|
||||
runlist_SubRunRec(sprite[nSprite].owner);
|
||||
runlist_SubRunRec(MoveHook[nLion]);
|
||||
sprite[nSprite].cstat = 0x8000;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// loc_379AD: ?
|
||||
if (nAction != 1 && nTarget != -1)
|
||||
{
|
||||
if (!(sprite[nTarget].cstat & 0x101))
|
||||
{
|
||||
LionList[nLion].nAction = 1;
|
||||
LionList[nLion]._b = 0;
|
||||
LionList[nLion]._g = 100;
|
||||
LionList[nLion].nTarget = -1;
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
END_PS_NS
|
30
source/exhumed/src/lion.h
Normal file
30
source/exhumed/src/lion.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __lion_h__
|
||||
#define __lion_h__
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
void InitLion();
|
||||
int BuildLion(short nSprite, int x, int y, int z, short nSector, short nAngle);
|
||||
void FuncLion(int, int, int);
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
17
source/exhumed/src/main.cpp
Normal file
17
source/exhumed/src/main.cpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
631
source/exhumed/src/map.cpp
Normal file
631
source/exhumed/src/map.cpp
Normal file
|
@ -0,0 +1,631 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "typedefs.h"
|
||||
#include <string.h>
|
||||
#include "player.h"
|
||||
#include "init.h"
|
||||
#include "engine.h"
|
||||
#include "exhumed.h"
|
||||
#include "view.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
|
||||
short bShowTowers = kFalse;int ldMapZoom;
|
||||
int lMapZoom;
|
||||
|
||||
void MarkSectorSeen(short nSector);
|
||||
|
||||
|
||||
void InitMap()
|
||||
{
|
||||
memset(show2dsector, 0, sizeof(show2dsector));
|
||||
memset(show2dwall, 0, sizeof(show2dwall));
|
||||
memset(show2dsprite, 0, sizeof(show2dsprite));
|
||||
|
||||
ldMapZoom = 64;
|
||||
lMapZoom = 1000;
|
||||
}
|
||||
|
||||
void GrabMap()
|
||||
{
|
||||
for (int i = 0; i < numsectors; i++) {
|
||||
MarkSectorSeen(i);
|
||||
}
|
||||
}
|
||||
|
||||
void MarkSectorSeen(short nSector)
|
||||
{
|
||||
if (!((1 << (nSector & 7)) & show2dsector[nSector >> 3]))
|
||||
{
|
||||
show2dsector[nSector >> 3] |= 1 << (nSector & 7);
|
||||
|
||||
short startwall = sector[nSector].wallptr;
|
||||
short nWalls = sector[nSector].wallnum;
|
||||
short endwall = startwall + nWalls;
|
||||
|
||||
while (startwall <= endwall)
|
||||
{
|
||||
show2dwall[startwall >> 3] = (1 << (startwall & 7)) | show2dwall[startwall >> 3];
|
||||
startwall++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void drawoverheadmap(int cposx, int cposy, int czoom, short cang)
|
||||
{
|
||||
#ifndef __WATCOMC__ // FIXME - Won't compile on Watcom
|
||||
int xvect = sintable[(2048 - cang) & 2047] * czoom;
|
||||
int yvect = sintable[(1536 - cang) & 2047] * czoom;
|
||||
int xvect2 = mulscale(xvect, yxaspect, 16);
|
||||
int yvect2 = mulscale(yvect, yxaspect, 16);
|
||||
|
||||
// draw player position arrow
|
||||
renderDrawLine(xdim << 11, (ydim << 11) - 20480, xdim << 11, (ydim << 11) + 20480, 24);
|
||||
renderDrawLine((xdim << 11) - 20480, ydim << 11, xdim << 11, (ydim << 11) - 20480, 24);
|
||||
renderDrawLine((xdim << 11) + 20480, ydim << 11, xdim << 11, (ydim << 11) - 20480, 24);
|
||||
|
||||
short nPlayerSprite = PlayerList[nLocalPlayer].nSprite;
|
||||
|
||||
int nPlayerZ = sprite[nPlayerSprite].z;
|
||||
|
||||
for (int nSector = 0; nSector < numsectors; nSector++)
|
||||
{
|
||||
short startwall = sector[nSector].wallptr;
|
||||
short nWalls = sector[nSector].wallnum;
|
||||
short endwall = startwall + nWalls - 1;
|
||||
|
||||
int nCeilZ = sector[nSector].ceilingz;
|
||||
int nFloorZ = sector[nSector].floorz;
|
||||
|
||||
int nZVal = nFloorZ - nPlayerZ;
|
||||
if (nZVal < 0) {
|
||||
nZVal = -nZVal;
|
||||
}
|
||||
|
||||
int var_10 = nZVal >> 13;
|
||||
if (var_10 > 12) {
|
||||
var_10 = 12;
|
||||
}
|
||||
|
||||
var_10 = 111 - var_10;
|
||||
|
||||
// int startwallB = startwall;
|
||||
|
||||
for (int nWall = startwall; nWall <= endwall; nWall++)
|
||||
{
|
||||
short nextwall = wall[nWall].nextwall;
|
||||
|
||||
if (nextwall >= 0)
|
||||
{
|
||||
if (show2dwall[nWall >> 3] & (1 << (nWall & 7)))
|
||||
{
|
||||
if (nextwall <= nWall || (show2dwall[nextwall >> 3] & (1 << (nextwall & 7))) <= 0)
|
||||
{
|
||||
if (nCeilZ != sector[wall[nWall].nextsector].ceilingz ||
|
||||
nFloorZ != sector[wall[nWall].nextsector].floorz ||
|
||||
((wall[nextwall].cstat | wall[nWall].cstat) & 0x30))
|
||||
{
|
||||
int ox = wall[nWall].x - cposx;
|
||||
int oy = wall[nWall].y - cposy;
|
||||
|
||||
int x1 = mulscale(ox, xvect, 16) - mulscale(oy, yvect, 16);
|
||||
int y1 = mulscale(oy, xvect2, 16) + mulscale(ox, yvect2, 16);
|
||||
|
||||
int nWall2 = wall[nWall].point2;
|
||||
ox = wall[nWall2].x - cposx;
|
||||
oy = wall[nWall2].y - cposy;
|
||||
int x2 = mulscale(ox, xvect, 16) - mulscale(oy, yvect, 16);
|
||||
int y2 = mulscale(oy, xvect2, 16) + mulscale(ox, yvect2, 16);
|
||||
|
||||
renderDrawLine(x1 + (xdim << 11), y1 + (ydim << 11), x2 + (xdim << 11), y2 + (ydim << 11), var_10);
|
||||
|
||||
/*
|
||||
drawline256(
|
||||
((unsigned __int64)(v4 * (signed __int64)v12) >> 16)
|
||||
- ((unsigned __int64)(v5 * (signed __int64)v13) >> 16)
|
||||
+ (xdim << 11),
|
||||
((unsigned __int64)(v42 * (signed __int64)v12) >> 16)
|
||||
+ ((unsigned __int64)(v43 * (signed __int64)v13) >> 16)
|
||||
+ (ydim << 11),
|
||||
(build_xdim << 11)
|
||||
+ ((unsigned __int64)(v4 * (signed __int64)(*v14 - v31)) >> 16)
|
||||
- ((unsigned __int64)(v5 * (signed __int64)(v14[1] - v30)) >> 16),
|
||||
ydim << 11)
|
||||
+ ((unsigned __int64)(v43 * (signed __int64)(v14[1] - v30)) >> 16)
|
||||
+ ((unsigned __int64)(v42 * (signed __int64)(*v14 - v31)) >> 16),
|
||||
v48);
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// int var_4C = 0;
|
||||
// int var_48 = 0;
|
||||
|
||||
for (int nSector = 0; nSector < numsectors; nSector++)
|
||||
{
|
||||
int startwall = sector[nSector].wallptr;
|
||||
int nWalls = sector[nSector].wallnum;
|
||||
int endwall = startwall + nWalls - 1;
|
||||
|
||||
int nFloorZ = sector[nSector].floorz;
|
||||
|
||||
int nVal = nFloorZ - nPlayerZ;
|
||||
if (nVal < 0) {
|
||||
nVal = -nVal;
|
||||
}
|
||||
|
||||
int var_14 = nVal >> 13;
|
||||
|
||||
if (var_14 <= 15)
|
||||
{
|
||||
var_14 = 111 - var_14;
|
||||
|
||||
for (int nWall = startwall; nWall <= endwall; nWall++)
|
||||
{
|
||||
if (wall[nWall].nextwall < 0)
|
||||
{
|
||||
if (show2dwall[nWall >> 3] & (1 << (nWall & 7)))
|
||||
{
|
||||
if (tilesiz[wall[nWall].picnum].x && tilesiz[wall[nWall].picnum].y)
|
||||
{
|
||||
int ox = wall[nWall].x - cposx;
|
||||
int oy = wall[nWall].y - cposy;
|
||||
int x1 = mulscale(ox, xvect, 16) - mulscale(oy, yvect, 16);
|
||||
int y1 = mulscale(oy, xvect2, 16) + mulscale(ox, yvect2, 16);
|
||||
|
||||
int nWall2 = wall[nWall].point2;
|
||||
ox = wall[nWall2].x - cposx;
|
||||
oy = wall[nWall2].y - cposy;
|
||||
int x2 = mulscale(ox, xvect, 16) - mulscale(oy, yvect, 16);
|
||||
int y2 = mulscale(oy, xvect2, 16) + mulscale(ox, yvect2, 16);
|
||||
|
||||
renderDrawLine(x1 + (xdim << 11), y1 + (ydim << 11), x2 + (xdim << 11), y2 + (ydim << 11), 24);
|
||||
|
||||
/*
|
||||
|
||||
v19 = *v17 - v31;
|
||||
v20 = v17[1] - v30;
|
||||
v21 = &wall[8 * *((_WORD *)v17 + 4)];
|
||||
|
||||
build_drawline256(
|
||||
(build_xdim << 11)
|
||||
+ ((unsigned __int64)(v4 * (signed __int64)v19) >> 16)
|
||||
- ((unsigned __int64)(v5 * (signed __int64)v20) >> 16),
|
||||
(build_ydim << 11)
|
||||
+ ((unsigned __int64)(v42 * (signed __int64)v19) >> 16)
|
||||
+ ((unsigned __int64)(v43 * (signed __int64)v20) >> 16),
|
||||
(build_xdim << 11)
|
||||
+ ((unsigned __int64)(v4 * (signed __int64)(*v21 - v31)) >> 16)
|
||||
- ((unsigned __int64)(v5 * (signed __int64)(v21[1] - v30)) >> 16),
|
||||
(build_ydim << 11)
|
||||
+ ((unsigned __int64)(v42 * (signed __int64)(*v21 - v31)) >> 16)
|
||||
+ ((unsigned __int64)(v43 * (signed __int64)(v21[1] - v30)) >> 16),
|
||||
v46);
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bShowTowers)
|
||||
{
|
||||
for (int nSprite = headspritestat[406]; nSprite != -1; nSprite = nextspritestat[nSprite])
|
||||
{
|
||||
int ox = sprite[nSprite].x - cposx; // var_64
|
||||
int oy = sprite[nSprite].y - cposx; // var_68
|
||||
|
||||
// int var_58 = mulscale(var_64, xvect, 16) - mulscale(var_68, yvect, 16);
|
||||
int x1 = mulscale(ox, xvect, 16) - mulscale(oy, yvect, 16);
|
||||
int y1 = mulscale(oy, xvect2, 16) + mulscale(ox, yvect2, 16);
|
||||
|
||||
//int var_58 = mulscale(var_64, xvect, 16) - mulscale(var_68, yvect, 16);
|
||||
//int esi = mulscale(var_68, xvect2, 16) + mulscale(var_65, yvect2, 16)
|
||||
|
||||
//v25 = ((unsigned __int64)(v4 * (signed __int64)ox) >> 16)
|
||||
// - ((unsigned __int64)(v5 * (signed __int64)oy) >> 16);
|
||||
|
||||
//v26 = ((unsigned __int64)(v42 * (signed __int64)ox) >> 16)
|
||||
// + ((unsigned __int64)(v43 * (signed __int64)oy) >> 16);
|
||||
|
||||
//v27 = v26 + 2048;
|
||||
//v28 = v26 + 2048 + (ydim << 11);
|
||||
//v26 -= 2048;
|
||||
|
||||
// v25 is x1
|
||||
// v26 is y1
|
||||
// v27 is y1 + 2048
|
||||
// v28 is y1 + 2048 + (ydim << 1);
|
||||
|
||||
renderDrawLine(
|
||||
x1 - 2048 + (xdim << 11),
|
||||
y1 - 2048 + (ydim << 11),
|
||||
x1 - 2048 + (xdim << 11),
|
||||
y1 + 2048 + (ydim << 1),
|
||||
170);
|
||||
|
||||
renderDrawLine(
|
||||
x1 + (xdim << 11),
|
||||
y1 + (ydim << 11),
|
||||
x1 + (xdim << 11),
|
||||
y1 + 2048 + (ydim << 11),
|
||||
170);
|
||||
|
||||
renderDrawLine(
|
||||
x1 + 2048 + (xdim << 11),
|
||||
y1 + (ydim << 11),
|
||||
x1 + 2048 + (xdim << 11),
|
||||
y1 + 2048 + (ydim << 11),
|
||||
170);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4101) // this function produces a little bit too much noise
|
||||
#endif
|
||||
|
||||
static void G_DrawOverheadMap(int32_t cposx, int32_t cposy, int32_t czoom, int16_t cang)
|
||||
{
|
||||
int32_t i, j, k, x1, y1, x2=0, y2=0, ox, oy;
|
||||
int32_t z1, z2, startwall, endwall;
|
||||
int32_t xvect, yvect, xvect2, yvect2;
|
||||
char col;
|
||||
uwallptr_t wal, wal2;
|
||||
|
||||
int32_t tmpydim = (xdim*5)/8;
|
||||
|
||||
renderSetAspect(65536, divscale16(tmpydim*320, xdim*200));
|
||||
|
||||
xvect = sintable[(-cang)&2047] * czoom;
|
||||
yvect = sintable[(1536-cang)&2047] * czoom;
|
||||
xvect2 = mulscale16(xvect, yxaspect);
|
||||
yvect2 = mulscale16(yvect, yxaspect);
|
||||
|
||||
//renderDisableFog();
|
||||
|
||||
// draw player position arrow
|
||||
renderDrawLine(xdim << 11, (ydim << 11) - 20480, xdim << 11, (ydim << 11) + 20480, 24);
|
||||
renderDrawLine((xdim << 11) - 20480, ydim << 11, xdim << 11, (ydim << 11) - 20480, 24);
|
||||
renderDrawLine((xdim << 11) + 20480, ydim << 11, xdim << 11, (ydim << 11) - 20480, 24);
|
||||
|
||||
short nPlayerSprite = PlayerList[nLocalPlayer].nSprite;
|
||||
|
||||
int nPlayerZ = sprite[nPlayerSprite].z;
|
||||
|
||||
//Draw red lines
|
||||
for (i=numsectors-1; i>=0; i--)
|
||||
{
|
||||
if (!(show2dsector[i>>3]&pow2char[i&7])) continue;
|
||||
|
||||
startwall = sector[i].wallptr;
|
||||
endwall = sector[i].wallptr + sector[i].wallnum;
|
||||
|
||||
z1 = sector[i].ceilingz;
|
||||
z2 = sector[i].floorz;
|
||||
|
||||
for (j=startwall, wal=(uwallptr_t)&wall[startwall]; j<endwall; j++, wal++)
|
||||
{
|
||||
k = wal->nextwall;
|
||||
if (k < 0) continue;
|
||||
|
||||
if (sector[wal->nextsector].ceilingz == z1 && sector[wal->nextsector].floorz == z2)
|
||||
if (((wal->cstat|wall[wal->nextwall].cstat)&(16+32)) == 0) continue;
|
||||
|
||||
if (nMapMode == 2)
|
||||
col = 111;
|
||||
else
|
||||
col = 111 - min(klabs(z2 - nPlayerZ) >> 13, 12);
|
||||
|
||||
ox = wal->x-cposx;
|
||||
oy = wal->y-cposy;
|
||||
x1 = dmulscale16(ox, xvect, -oy, yvect)+(xdim<<11);
|
||||
y1 = dmulscale16(oy, xvect2, ox, yvect2)+(ydim<<11);
|
||||
|
||||
wal2 = (uwallptr_t)&wall[wal->point2];
|
||||
ox = wal2->x-cposx;
|
||||
oy = wal2->y-cposy;
|
||||
x2 = dmulscale16(ox, xvect, -oy, yvect)+(xdim<<11);
|
||||
y2 = dmulscale16(oy, xvect2, ox, yvect2)+(ydim<<11);
|
||||
|
||||
renderDrawLine(x1, y1, x2, y2, col);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
renderEnableFog();
|
||||
|
||||
//Draw sprites
|
||||
k = PlayerList[nLocalPlayer].nSprite;
|
||||
if (!FURY) for (i=numsectors-1; i>=0; i--)
|
||||
{
|
||||
if (!(show2dsector[i>>3]&pow2char[i&7])) continue;
|
||||
for (j=headspritesect[i]; j>=0; j=nextspritesect[j])
|
||||
{
|
||||
spr = &sprite[j];
|
||||
|
||||
if (j == k || (spr->cstat&0x8000) || spr->cstat == 257 || spr->xrepeat == 0) continue;
|
||||
|
||||
col = editorcolors[6]; //cyan
|
||||
if (spr->cstat&1) col = editorcolors[5]; //magenta
|
||||
|
||||
sprx = spr->x;
|
||||
spry = spr->y;
|
||||
|
||||
if ((spr->cstat&257) != 0) switch (spr->cstat&48)
|
||||
{
|
||||
case 0:
|
||||
// break;
|
||||
|
||||
ox = sprx-cposx;
|
||||
oy = spry-cposy;
|
||||
x1 = dmulscale16(ox, xvect, -oy, yvect);
|
||||
y1 = dmulscale16(oy, xvect2, ox, yvect2);
|
||||
|
||||
ox = (sintable[(spr->ang+512)&2047]>>7);
|
||||
oy = (sintable[(spr->ang)&2047]>>7);
|
||||
x2 = dmulscale16(ox, xvect, -oy, yvect);
|
||||
y2 = dmulscale16(oy, xvect, ox, yvect);
|
||||
|
||||
x3 = mulscale16(x2, yxaspect);
|
||||
y3 = mulscale16(y2, yxaspect);
|
||||
|
||||
renderDrawLine(x1-x2+(xdim<<11), y1-y3+(ydim<<11),
|
||||
x1+x2+(xdim<<11), y1+y3+(ydim<<11), col);
|
||||
renderDrawLine(x1-y2+(xdim<<11), y1+x3+(ydim<<11),
|
||||
x1+x2+(xdim<<11), y1+y3+(ydim<<11), col);
|
||||
renderDrawLine(x1+y2+(xdim<<11), y1-x3+(ydim<<11),
|
||||
x1+x2+(xdim<<11), y1+y3+(ydim<<11), col);
|
||||
break;
|
||||
|
||||
case 16:
|
||||
if (spr->picnum == LASERLINE)
|
||||
{
|
||||
x1 = sprx;
|
||||
y1 = spry;
|
||||
tilenum = spr->picnum;
|
||||
xoff = picanm[tilenum].xofs + spr->xoffset;
|
||||
if ((spr->cstat&4) > 0) xoff = -xoff;
|
||||
k = spr->ang;
|
||||
l = spr->xrepeat;
|
||||
dax = sintable[k&2047]*l;
|
||||
day = sintable[(k+1536)&2047]*l;
|
||||
l = tilesiz[tilenum].x;
|
||||
k = (l>>1)+xoff;
|
||||
x1 -= mulscale16(dax, k);
|
||||
x2 = x1+mulscale16(dax, l);
|
||||
y1 -= mulscale16(day, k);
|
||||
y2 = y1+mulscale16(day, l);
|
||||
|
||||
ox = x1-cposx;
|
||||
oy = y1-cposy;
|
||||
x1 = dmulscale16(ox, xvect, -oy, yvect);
|
||||
y1 = dmulscale16(oy, xvect2, ox, yvect2);
|
||||
|
||||
ox = x2-cposx;
|
||||
oy = y2-cposy;
|
||||
x2 = dmulscale16(ox, xvect, -oy, yvect);
|
||||
y2 = dmulscale16(oy, xvect2, ox, yvect2);
|
||||
|
||||
renderDrawLine(x1+(xdim<<11), y1+(ydim<<11),
|
||||
x2+(xdim<<11), y2+(ydim<<11), col);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 32:
|
||||
tilenum = spr->picnum;
|
||||
xoff = picanm[tilenum].xofs + spr->xoffset;
|
||||
yoff = picanm[tilenum].yofs + spr->yoffset;
|
||||
if ((spr->cstat&4) > 0) xoff = -xoff;
|
||||
if ((spr->cstat&8) > 0) yoff = -yoff;
|
||||
|
||||
k = spr->ang;
|
||||
cosang = sintable[(k+512)&2047];
|
||||
sinang = sintable[k&2047];
|
||||
xspan = tilesiz[tilenum].x;
|
||||
xrepeat = spr->xrepeat;
|
||||
yspan = tilesiz[tilenum].y;
|
||||
yrepeat = spr->yrepeat;
|
||||
|
||||
dax = ((xspan>>1)+xoff)*xrepeat;
|
||||
day = ((yspan>>1)+yoff)*yrepeat;
|
||||
x1 = sprx + dmulscale16(sinang, dax, cosang, day);
|
||||
y1 = spry + dmulscale16(sinang, day, -cosang, dax);
|
||||
l = xspan*xrepeat;
|
||||
x2 = x1 - mulscale16(sinang, l);
|
||||
y2 = y1 + mulscale16(cosang, l);
|
||||
l = yspan*yrepeat;
|
||||
k = -mulscale16(cosang, l);
|
||||
x3 = x2+k;
|
||||
x4 = x1+k;
|
||||
k = -mulscale16(sinang, l);
|
||||
y3 = y2+k;
|
||||
y4 = y1+k;
|
||||
|
||||
ox = x1-cposx;
|
||||
oy = y1-cposy;
|
||||
x1 = dmulscale16(ox, xvect, -oy, yvect);
|
||||
y1 = dmulscale16(oy, xvect2, ox, yvect2);
|
||||
|
||||
ox = x2-cposx;
|
||||
oy = y2-cposy;
|
||||
x2 = dmulscale16(ox, xvect, -oy, yvect);
|
||||
y2 = dmulscale16(oy, xvect2, ox, yvect2);
|
||||
|
||||
ox = x3-cposx;
|
||||
oy = y3-cposy;
|
||||
x3 = dmulscale16(ox, xvect, -oy, yvect);
|
||||
y3 = dmulscale16(oy, xvect2, ox, yvect2);
|
||||
|
||||
ox = x4-cposx;
|
||||
oy = y4-cposy;
|
||||
x4 = dmulscale16(ox, xvect, -oy, yvect);
|
||||
y4 = dmulscale16(oy, xvect2, ox, yvect2);
|
||||
|
||||
renderDrawLine(x1+(xdim<<11), y1+(ydim<<11),
|
||||
x2+(xdim<<11), y2+(ydim<<11), col);
|
||||
|
||||
renderDrawLine(x2+(xdim<<11), y2+(ydim<<11),
|
||||
x3+(xdim<<11), y3+(ydim<<11), col);
|
||||
|
||||
renderDrawLine(x3+(xdim<<11), y3+(ydim<<11),
|
||||
x4+(xdim<<11), y4+(ydim<<11), col);
|
||||
|
||||
renderDrawLine(x4+(xdim<<11), y4+(ydim<<11),
|
||||
x1+(xdim<<11), y1+(ydim<<11), col);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
renderDisableFog();
|
||||
#endif
|
||||
|
||||
//Draw white lines
|
||||
for (i=numsectors-1; i>=0; i--)
|
||||
{
|
||||
if (!(show2dsector[i>>3]&pow2char[i&7])) continue;
|
||||
|
||||
startwall = sector[i].wallptr;
|
||||
endwall = sector[i].wallptr + sector[i].wallnum;
|
||||
z2 = sector[i].floorz;
|
||||
|
||||
if (nMapMode == 2)
|
||||
{
|
||||
col = 111;
|
||||
}
|
||||
else
|
||||
{
|
||||
col = klabs(z2 - nPlayerZ) >> 13;
|
||||
if (col > 15)
|
||||
continue;
|
||||
col = 111 - col;
|
||||
}
|
||||
|
||||
k = -1;
|
||||
for (j=startwall, wal=(uwallptr_t)&wall[startwall]; j<endwall; j++, wal++)
|
||||
{
|
||||
if (wal->nextwall >= 0) continue;
|
||||
|
||||
if (tilesiz[wal->picnum].x == 0) continue;
|
||||
if (tilesiz[wal->picnum].y == 0) continue;
|
||||
|
||||
if (j == k)
|
||||
{
|
||||
x1 = x2;
|
||||
y1 = y2;
|
||||
}
|
||||
else
|
||||
{
|
||||
ox = wal->x-cposx;
|
||||
oy = wal->y-cposy;
|
||||
x1 = dmulscale16(ox, xvect, -oy, yvect)+(xdim<<11);
|
||||
y1 = dmulscale16(oy, xvect2, ox, yvect2)+(ydim<<11);
|
||||
}
|
||||
|
||||
k = wal->point2;
|
||||
wal2 = (uwallptr_t)&wall[k];
|
||||
ox = wal2->x-cposx;
|
||||
oy = wal2->y-cposy;
|
||||
x2 = dmulscale16(ox, xvect, -oy, yvect)+(xdim<<11);
|
||||
y2 = dmulscale16(oy, xvect2, ox, yvect2)+(ydim<<11);
|
||||
|
||||
renderDrawLine(x1, y1, x2, y2, col);
|
||||
}
|
||||
}
|
||||
|
||||
//renderEnableFog();
|
||||
|
||||
videoSetCorrectedAspect();
|
||||
|
||||
#if 0
|
||||
for (TRAVERSE_CONNECT(p))
|
||||
{
|
||||
if (ud.scrollmode && p == screenpeek) continue;
|
||||
|
||||
auto const pPlayer = g_player[p].ps;
|
||||
auto const pSprite = (uspriteptr_t)&sprite[pPlayer->i];
|
||||
|
||||
ox = pSprite->x - cposx;
|
||||
oy = pSprite->y - cposy;
|
||||
daang = (pSprite->ang - cang) & 2047;
|
||||
if (p == screenpeek)
|
||||
{
|
||||
ox = 0;
|
||||
oy = 0;
|
||||
daang = 0;
|
||||
}
|
||||
x1 = mulscale16(ox, xvect) - mulscale16(oy, yvect);
|
||||
y1 = mulscale16(oy, xvect2) + mulscale16(ox, yvect2);
|
||||
|
||||
if (p == screenpeek || GTFLAGS(GAMETYPE_OTHERPLAYERSINMAP))
|
||||
{
|
||||
if (pSprite->xvel > 16 && pPlayer->on_ground)
|
||||
i = APLAYERTOP+(((int32_t) totalclock>>4)&3);
|
||||
else
|
||||
i = APLAYERTOP;
|
||||
|
||||
i = VM_OnEventWithReturn(EVENT_DISPLAYOVERHEADMAPPLAYER, pPlayer->i, p, i);
|
||||
|
||||
if (i < 0)
|
||||
continue;
|
||||
|
||||
j = klabs(pPlayer->truefz - pPlayer->pos.z) >> 8;
|
||||
j = mulscale16(czoom * (pSprite->yrepeat + j), yxaspect);
|
||||
|
||||
if (j < 22000) j = 22000;
|
||||
else if (j > (65536<<1)) j = (65536<<1);
|
||||
|
||||
rotatesprite_win((x1<<4)+(xdim<<15), (y1<<4)+(ydim<<15), j, daang, i, pSprite->shade,
|
||||
P_GetOverheadPal(pPlayer), 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void UpdateMap()
|
||||
{
|
||||
if (sector[initsect].ceilingpal != 3 || (nPlayerTorch[nLocalPlayer] != 0)) {
|
||||
MarkSectorSeen(initsect);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawMap()
|
||||
{
|
||||
if (!nFreeze && nMapMode) {
|
||||
//drawoverheadmap(initx, inity, lMapZoom, inita);
|
||||
if (nMapMode == 2)
|
||||
{
|
||||
videoClearViewableArea(blackcol);
|
||||
RefreshBackground();
|
||||
renderDrawMapView(initx, inity, lMapZoom, inita);
|
||||
}
|
||||
G_DrawOverheadMap(initx, inity, lMapZoom, inita);
|
||||
}
|
||||
}
|
||||
END_PS_NS
|
37
source/exhumed/src/map.h
Normal file
37
source/exhumed/src/map.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __map_h__
|
||||
#define __map_h__
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
extern short bShowTowers;
|
||||
extern int ldMapZoom;
|
||||
extern int lMapZoom;
|
||||
|
||||
void InitMap();
|
||||
void GrabMap();
|
||||
void UpdateMap();
|
||||
void DrawMap();
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
2047
source/exhumed/src/menu.cpp
Normal file
2047
source/exhumed/src/menu.cpp
Normal file
File diff suppressed because it is too large
Load diff
81
source/exhumed/src/menu.h
Normal file
81
source/exhumed/src/menu.h
Normal file
|
@ -0,0 +1,81 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __menu_h__
|
||||
#define __menu_h__
|
||||
|
||||
#include "player.h"
|
||||
#include "typedefs.h"
|
||||
#include <stdio.h>
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
#pragma pack(1)
|
||||
// should be 75 bytes
|
||||
struct GameStat
|
||||
{
|
||||
uint8_t nMap;
|
||||
short nWeapons;
|
||||
short nCurrentWeapon;
|
||||
short clip;
|
||||
short items;
|
||||
|
||||
Player player;
|
||||
|
||||
short nLives;
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
extern GameStat GameStats;
|
||||
|
||||
extern unsigned char cinemapal[];
|
||||
|
||||
extern short SavePosition;
|
||||
|
||||
int showmap(short nLevel, short nLevelNew, short nLevelBest);
|
||||
|
||||
void ClearCinemaSeen();
|
||||
void menu_DoPlasma();
|
||||
int menu_Menu(int val);
|
||||
void menu_AdjustVolume();
|
||||
short menu_GameLoad(int nSlot);
|
||||
void menu_GameLoad2(FILE *fp, bool bIsDemo = false);
|
||||
void menu_GameSave2(FILE *fp);
|
||||
void menu_GameSave(int nSaveSlot);
|
||||
|
||||
int menu_DrawTheMap(int nLevel, int param_B, int param_C);
|
||||
|
||||
void DoEnergyTile();
|
||||
|
||||
int LoadCinemaPalette(int nPal);
|
||||
|
||||
void CinemaFadeIn();
|
||||
|
||||
void ReadyCinemaText(uint16_t nVal);
|
||||
uint8_t AdvanceCinemaText();
|
||||
|
||||
void DoFailedFinalScene();
|
||||
|
||||
void DoLastLevelCinema();
|
||||
void DoAfterCinemaScene(int nLevel);
|
||||
|
||||
void InitEnergyTile();
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
74
source/exhumed/src/mono.cpp
Normal file
74
source/exhumed/src/mono.cpp
Normal file
|
@ -0,0 +1,74 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
/*
|
||||
Name: MonoClear_
|
||||
address = 0001:0001CF5A
|
||||
module index = 24
|
||||
kind: (code)
|
||||
Name: MonoInUse_
|
||||
address = 0001:0001CF8A
|
||||
module index = 24
|
||||
kind: (code)
|
||||
Name: MonoOpen_
|
||||
address = 0001:0001CF8A
|
||||
module index = 24
|
||||
kind: (code)
|
||||
Name: MonoClose_
|
||||
address = 0001:0001CF8D
|
||||
module index = 24
|
||||
kind: (code)
|
||||
Name: MonoOut_
|
||||
address = 0001:0001CFAA
|
||||
module index = 24
|
||||
kind: (code)
|
||||
Name: CACopy_
|
||||
address = 0001:0001D1C0
|
||||
module index = 24
|
||||
kind: (static pubdef) (code)
|
||||
Name: CAFill_
|
||||
address = 0001:0001D1CD
|
||||
module index = 24
|
||||
kind: (static pubdef) (code)
|
||||
Name: MonoQuery_
|
||||
address = 0001:0001D1E6
|
||||
module index = 24
|
||||
kind: (code)
|
||||
Name: _rowCur
|
||||
address = 0003:000073D8
|
||||
module index = 24
|
||||
kind: (data)
|
||||
Name: _colCur
|
||||
address = 0003:000073DC
|
||||
module index = 24
|
||||
kind: (data)
|
||||
Name: _fMonoOpen
|
||||
address = 0003:000073E0
|
||||
module index = 24
|
||||
kind: (data)
|
||||
|
||||
|
||||
*/
|
||||
#include "mono.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
int rowCur = 0;
|
||||
int colCur = 0;
|
||||
|
||||
END_PS_NS
|
24
source/exhumed/src/mono.h
Normal file
24
source/exhumed/src/mono.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __mono_h__
|
||||
#define __mono_h__
|
||||
|
||||
|
||||
|
||||
#endif
|
1516
source/exhumed/src/move.cpp
Normal file
1516
source/exhumed/src/move.cpp
Normal file
File diff suppressed because it is too large
Load diff
82
source/exhumed/src/move.h
Normal file
82
source/exhumed/src/move.h
Normal file
|
@ -0,0 +1,82 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __move_h__
|
||||
#define __move_h__
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
// 16 bytes
|
||||
struct BlockInfo
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int field_8;
|
||||
short nSprite;
|
||||
};
|
||||
extern BlockInfo sBlockInfo[];
|
||||
|
||||
extern int hihit;
|
||||
extern short nChunkSprite[];
|
||||
extern short nBodySprite[];
|
||||
|
||||
signed int lsqrt(int a1);
|
||||
void MoveThings();
|
||||
void ResetMoveFifo();
|
||||
void InitChunks();
|
||||
void InitPushBlocks();
|
||||
void Gravity(short nSprite);
|
||||
short UpdateEnemy(short *nEnemy);
|
||||
int MoveCreature(short nSprite);
|
||||
int MoveCreatureWithCaution(int nSprite);
|
||||
void WheresMyMouth(int nPlayer, int *x, int *y, int *z, short *sectnum);
|
||||
|
||||
int GetSpriteHeight(int nSprite);
|
||||
|
||||
int GrabBody();
|
||||
|
||||
int GrabBodyGunSprite();
|
||||
void CreatePushBlock(int nSector);
|
||||
|
||||
void FuncCreatureChunk(int a, int, int nRun);
|
||||
|
||||
int FindPlayer(int nSprite, int nVal);
|
||||
|
||||
int BuildCreatureChunk(int nVal, int nPic);
|
||||
|
||||
void BuildNear(int x, int y, int walldist, int nSector);
|
||||
int BelowNear(short nSprite);
|
||||
|
||||
int PlotCourseToSprite(int nSprite1, int nSprite2);
|
||||
|
||||
void CheckSectorFloor(short nSector, int z, int *a, int *b);
|
||||
|
||||
int GetAngleToSprite(int nSprite1, int nSprite2);
|
||||
|
||||
int GetWallNormal(short nWall);
|
||||
|
||||
int GetUpAngle(short nSprite1, int nVal, short nSprite2, int ecx);
|
||||
void MoveSector(short nSector, int nAngle, int *nXVel, int *nYVel);
|
||||
|
||||
int AngleChase(int nSprite, int nSprite2, int ebx, int ecx, int push1);
|
||||
|
||||
void SetQuake(short nSprite, int nVal);
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
282
source/exhumed/src/movie.cpp
Normal file
282
source/exhumed/src/movie.cpp
Normal file
|
@ -0,0 +1,282 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "engine.h"
|
||||
#include "exhumed.h"
|
||||
#include "names.h"
|
||||
#include "movie.h"
|
||||
#include "light.h"
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include "baselayer.h"
|
||||
#include "typedefs.h"
|
||||
#include "keyboard.h"
|
||||
#include "sound.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
void ServeSample(const char** ptr, uint32_t* length);
|
||||
|
||||
enum {
|
||||
kFramePalette = 0,
|
||||
kFrameSound,
|
||||
kFrameImage,
|
||||
kFrameDone
|
||||
};
|
||||
|
||||
#define kSampleRate 22050
|
||||
#define kSampleSize 2205
|
||||
|
||||
uint8_t bankbuf[kSampleRate];
|
||||
uint32_t bankptr = 0;
|
||||
uint32_t banktail = 0;
|
||||
|
||||
uint32_t lSoundBytesRead = 0;
|
||||
uint32_t lSoundBytesUsed = 0;
|
||||
|
||||
uint8_t lh[32] = { 0 };
|
||||
|
||||
static uint8_t* CurFrame = NULL;
|
||||
|
||||
bool bServedSample = false;
|
||||
palette_t moviepal[256];
|
||||
|
||||
int ReadFrame(FileReader &fp)
|
||||
{
|
||||
static int nFrame = 0;
|
||||
Printf("Reading frame %d...\n", nFrame);
|
||||
nFrame++;
|
||||
|
||||
uint8_t nType;
|
||||
uint8_t var_1C;
|
||||
int nSize;
|
||||
uint16_t yOffset;
|
||||
uint8_t xOffset;
|
||||
uint8_t nPixels;
|
||||
uint8_t palette[768];
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (fp.Read(&nType, sizeof(nType)) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
fp.Read(&nSize, sizeof(nSize));
|
||||
|
||||
nType--;
|
||||
if (nType > 3) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (nType)
|
||||
{
|
||||
case kFramePalette:
|
||||
{
|
||||
fp.Read(palette, sizeof(palette));
|
||||
fp.Read(&var_1C, sizeof(var_1C));
|
||||
|
||||
for (auto &c : palette)
|
||||
c <<= 2;
|
||||
|
||||
paletteSetColorTable(ANIMPAL, palette);
|
||||
videoSetPalette(0, ANIMPAL, 2+8);
|
||||
|
||||
memset(CurFrame, overscanindex, 4); //sizeof(CurFrame));
|
||||
continue;
|
||||
}
|
||||
case kFrameSound:
|
||||
{
|
||||
Printf("Reading sound block size %d...\n", nSize);
|
||||
|
||||
if (lSoundBytesRead - lSoundBytesUsed >= kSampleRate)
|
||||
{
|
||||
DebugOut("SOUND BUF FULL!\n");
|
||||
fp.Seek(nSize, FileReader::SeekCur);
|
||||
}
|
||||
else
|
||||
{
|
||||
//mutex_lock(&mutex);
|
||||
|
||||
int nRead = fp.Read((char*)bankbuf + bankptr, nSize);
|
||||
|
||||
lSoundBytesRead += nRead;
|
||||
bankptr += nSize;
|
||||
|
||||
assert(nSize == nRead);
|
||||
assert(bankptr <= kSampleRate);
|
||||
|
||||
if (bankptr >= kSampleRate) {
|
||||
bankptr -= kSampleRate; // loop back to start
|
||||
}
|
||||
|
||||
//mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
case kFrameImage:
|
||||
{
|
||||
Printf("Reading image block size %d...\n", nSize);
|
||||
if (nSize == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8_t *pFrame = CurFrame;
|
||||
|
||||
int nRead = fp.Read(&yOffset, sizeof(yOffset));
|
||||
nSize -= nRead;
|
||||
|
||||
pFrame += yOffset * 200; // row position
|
||||
|
||||
while (nSize > 0)
|
||||
{
|
||||
fp.Read(&xOffset, sizeof(xOffset));
|
||||
fp.Read(&nPixels, sizeof(nPixels));
|
||||
nSize -= 2;
|
||||
|
||||
pFrame += xOffset;
|
||||
|
||||
if (nPixels)
|
||||
{
|
||||
int nRead = fp.Read(pFrame, nPixels);
|
||||
pFrame += nRead;
|
||||
nSize -= nRead;
|
||||
}
|
||||
}
|
||||
|
||||
tileInvalidate(kMovieTile, -1, -1);
|
||||
|
||||
break;
|
||||
}
|
||||
case kFrameDone:
|
||||
{
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServeSample(const char** ptr, uint32_t* length)
|
||||
{
|
||||
//mutex_lock(&mutex);
|
||||
|
||||
*ptr = (char*)bankbuf + banktail;
|
||||
*length = kSampleSize;
|
||||
|
||||
banktail += kSampleSize;
|
||||
if (banktail >= kSampleRate) {
|
||||
banktail -= kSampleRate; // rotate back to start
|
||||
}
|
||||
|
||||
lSoundBytesUsed += kSampleSize;
|
||||
bServedSample = true;
|
||||
|
||||
//mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
void PlayMovie(const char* fileName)
|
||||
{
|
||||
int bDoFade = kTrue;
|
||||
int hFx = -1;
|
||||
auto fp = fileSystem.OpenFileReader(fileName, 0);
|
||||
if (!fp.isOpen())
|
||||
{
|
||||
Printf("Unable to open %s\n", fileName);
|
||||
return;
|
||||
}
|
||||
|
||||
tileLoad(kMovieTile);
|
||||
CurFrame = TileFiles.tileMakeWritable(kMovieTile);
|
||||
|
||||
|
||||
fp.Read(lh, sizeof(lh));
|
||||
|
||||
// sound stuff
|
||||
bankptr = 0;
|
||||
banktail = 0;
|
||||
|
||||
// clear keys
|
||||
inputState.keyFlushChars();
|
||||
inputState.ClearAllKeyStatus();
|
||||
|
||||
if (bDoFade) {
|
||||
StartFadeIn();
|
||||
}
|
||||
|
||||
int angle = 1536;
|
||||
int z = 0;
|
||||
|
||||
videoSetPalette(0, ANIMPAL, 2 + 8);
|
||||
|
||||
// Read a frame in first
|
||||
if (ReadFrame(fp))
|
||||
{
|
||||
// start audio playback (fixme)
|
||||
#if 0
|
||||
hFx = FX_StartDemandFeedPlayback(ServeSample, kSampleRate, 0, snd_fxvolume, snd_fxvolume, snd_fxvolume, FX_MUSIC_PRIORITY, fix16_one, -1);
|
||||
#else
|
||||
hFx = -1;
|
||||
#endif
|
||||
|
||||
while (!inputState.keyBufferWaiting())
|
||||
{
|
||||
HandleAsync();
|
||||
|
||||
// audio is king for sync - if the backend doesn't need any more samples yet,
|
||||
// don't process any more movie file data.
|
||||
if (!bServedSample && hFx > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bServedSample = false;
|
||||
|
||||
if (z < 65536) { // Zoom - normal zoom is 65536.
|
||||
z += 2048;
|
||||
}
|
||||
if (angle != 0) {
|
||||
angle += 16;
|
||||
if (angle == 2048) {
|
||||
angle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
videoClearViewableArea(blackcol);
|
||||
rotatesprite(160 << 16, 100 << 16, z, angle, kMovieTile, 0, 1, 2, 0, 0, xdim - 1, ydim - 1);
|
||||
|
||||
if (bDoFade) {
|
||||
bDoFade = DoFadeIn();
|
||||
}
|
||||
|
||||
videoNextPage();
|
||||
|
||||
if (ReadFrame(fp) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hFx > 0) {
|
||||
//FX_StopSound(hFx);
|
||||
}
|
||||
|
||||
if (inputState.keyBufferWaiting()) {
|
||||
inputState.keyGetChar();
|
||||
}
|
||||
}
|
||||
END_PS_NS
|
28
source/exhumed/src/movie.h
Normal file
28
source/exhumed/src/movie.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __movie_h__
|
||||
#define __movie_h__
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
void PlayMovie(const char *fileName);
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
530
source/exhumed/src/mummy.cpp
Normal file
530
source/exhumed/src/mummy.cpp
Normal file
|
@ -0,0 +1,530 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "mummy.h"
|
||||
#include "sequence.h"
|
||||
#include "move.h"
|
||||
#include "map.h"
|
||||
#include "sound.h"
|
||||
#include "exhumed.h"
|
||||
#include "random.h"
|
||||
#include "trigdat.h"
|
||||
#include "bullet.h"
|
||||
#include "items.h"
|
||||
#include <assert.h>
|
||||
#include "engine.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
short nMummies = -1;
|
||||
|
||||
struct Mummy
|
||||
{
|
||||
short nHealth;
|
||||
short B;
|
||||
short nAction;
|
||||
short nSprite;
|
||||
short nTarget;
|
||||
short F;
|
||||
short G;
|
||||
short H;
|
||||
};
|
||||
|
||||
Mummy MummyList[kMaxMummies];
|
||||
|
||||
static actionSeq ActionSeq[] = {
|
||||
{8, 0},
|
||||
{0, 0},
|
||||
{16, 0},
|
||||
{24, 0},
|
||||
{32, 1},
|
||||
{40, 1},
|
||||
{48, 1},
|
||||
{50, 0}
|
||||
};
|
||||
|
||||
|
||||
static SavegameHelper sgh("mummy",
|
||||
SV(nMummies),
|
||||
SA(MummyList),
|
||||
nullptr);
|
||||
|
||||
// done
|
||||
void InitMummy()
|
||||
{
|
||||
nMummies = 0;
|
||||
}
|
||||
|
||||
// done
|
||||
int BuildMummy(int nSprite, int x, int y, int z, int nSector, int nAngle)
|
||||
{
|
||||
if (nMummies >= kMaxMummies) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
short nMummy = nMummies++;
|
||||
|
||||
if (nSprite == -1)
|
||||
{
|
||||
nSprite = insertsprite(nSector, 102);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = sprite[nSprite].x;
|
||||
y = sprite[nSprite].y;
|
||||
z = sprite[nSprite].z;
|
||||
nAngle = sprite[nSprite].ang;
|
||||
|
||||
changespritestat(nSprite, 102);
|
||||
}
|
||||
|
||||
assert(nSprite >= 0 && nSprite < kMaxSprites);
|
||||
|
||||
sprite[nSprite].x = x;
|
||||
sprite[nSprite].y = y;
|
||||
sprite[nSprite].z = z;
|
||||
sprite[nSprite].cstat = 0x101;
|
||||
sprite[nSprite].shade = -12;
|
||||
sprite[nSprite].clipdist = 32;
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].zvel = 0;
|
||||
sprite[nSprite].xrepeat = 42;
|
||||
sprite[nSprite].yrepeat = 42;
|
||||
sprite[nSprite].pal = sector[sprite[nSprite].sectnum].ceilingpal;
|
||||
sprite[nSprite].xoffset = 0;
|
||||
sprite[nSprite].yoffset = 0;
|
||||
sprite[nSprite].ang = nAngle;
|
||||
sprite[nSprite].picnum = 1;
|
||||
sprite[nSprite].hitag = 0;
|
||||
sprite[nSprite].lotag = runlist_HeadRun() + 1;
|
||||
sprite[nSprite].extra = -1;
|
||||
|
||||
// GrabTimeSlot(3);
|
||||
|
||||
MummyList[nMummy].nAction = 0;
|
||||
MummyList[nMummy].nHealth = 640;
|
||||
MummyList[nMummy].B = 0;
|
||||
MummyList[nMummy].nSprite = nSprite;
|
||||
MummyList[nMummy].nTarget = -1;
|
||||
MummyList[nMummy].F = nMummy;
|
||||
MummyList[nMummy].G = 0;
|
||||
|
||||
sprite[nSprite].owner = runlist_AddRunRec(sprite[nSprite].lotag - 1, nMummy | 0xE0000);
|
||||
|
||||
MummyList[nMummy].H = runlist_AddRunRec(NewRun, nMummy | 0xE0000);
|
||||
|
||||
nCreaturesLeft++;
|
||||
|
||||
return (nMummy | 0xE0000);
|
||||
}
|
||||
|
||||
// done
|
||||
void CheckMummyRevive(short nMummy)
|
||||
{
|
||||
short nSprite = MummyList[nMummy].nSprite;
|
||||
|
||||
for (int i = 0; i < nMummies; i++)
|
||||
{
|
||||
if (i != nMummy)
|
||||
{
|
||||
short nSprite2 = MummyList[i].nSprite;
|
||||
if (sprite[nSprite2].statnum != 102) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (MummyList[i].nAction != 5) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int x = klabs(sprite[nSprite2].x - sprite[nSprite].x) >> 8;
|
||||
int y = klabs(sprite[nSprite2].y - sprite[nSprite].y) >> 8;
|
||||
|
||||
if (x <= 20 && y <= 20)
|
||||
{
|
||||
if (cansee(sprite[nSprite].x, sprite[nSprite].y, sprite[nSprite].z - 8192, sprite[nSprite].sectnum,
|
||||
sprite[nSprite2].x, sprite[nSprite2].y, sprite[nSprite2].z - 8192, sprite[nSprite2].sectnum))
|
||||
{
|
||||
sprite[nSprite2].cstat = 0;
|
||||
MummyList[i].nAction = 6;
|
||||
MummyList[i].B = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FuncMummy(int a, int nDamage, int nRun)
|
||||
{
|
||||
short nMummy = RunData[nRun].nVal;
|
||||
assert(nMummy >= 0 && nMummy < kMaxMummies);
|
||||
|
||||
short nTarget = UpdateEnemy(&MummyList[nMummy].nTarget);
|
||||
|
||||
short nSprite = MummyList[nMummy].nSprite;
|
||||
short nAction = MummyList[nMummy].nAction;
|
||||
|
||||
int nMessage = a & 0x7F0000;
|
||||
|
||||
switch (nMessage)
|
||||
{
|
||||
case 0x20000:
|
||||
{
|
||||
Gravity(nSprite);
|
||||
|
||||
int nSeq = SeqOffsets[kSeqMummy] + ActionSeq[nAction].a;
|
||||
|
||||
sprite[nSprite].picnum = seq_GetSeqPicnum2(nSeq, MummyList[nMummy].B);
|
||||
|
||||
short nFrame = SeqBase[nSeq] + MummyList[nMummy].B;
|
||||
short nFrameFlag = FrameFlag[nFrame];
|
||||
|
||||
seq_MoveSequence(nSprite, nSeq, MummyList[nMummy].B);
|
||||
|
||||
short ecx = 0;
|
||||
|
||||
MummyList[nMummy].B++;
|
||||
if (MummyList[nMummy].B >= SeqSize[nSeq])
|
||||
{
|
||||
MummyList[nMummy].B = 0;
|
||||
|
||||
ecx = 1;
|
||||
}
|
||||
|
||||
if (nTarget != -1 && nAction < 4)
|
||||
{
|
||||
if ((!sprite[nTarget].cstat) && nAction)
|
||||
{
|
||||
MummyList[nMummy].nAction = 0;
|
||||
MummyList[nMummy].B = 0;
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int nMov = MoveCreatureWithCaution(nSprite);
|
||||
|
||||
if (nAction > 7)
|
||||
return;
|
||||
|
||||
switch (nAction)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
if ((MummyList[nMummy].F & 0x1F) == (totalmoves & 0x1F))
|
||||
{
|
||||
sprite[nSprite].cstat = 0x101;
|
||||
|
||||
if (nTarget < 0)
|
||||
{
|
||||
int nTarget = FindPlayer(nSprite, 100);
|
||||
if (nTarget >= 0)
|
||||
{
|
||||
D3PlayFX(StaticSound[kSound7], nSprite);
|
||||
MummyList[nMummy].B = 0;
|
||||
MummyList[nMummy].nTarget = nTarget;
|
||||
MummyList[nMummy].nAction = 1;
|
||||
MummyList[nMummy].G = 90;
|
||||
|
||||
sprite[nSprite].xvel = Cos(sprite[nSprite].ang) >> 2;
|
||||
sprite[nSprite].yvel = sintable[sprite[nSprite].ang] >> 2; // NOTE no angle masking in original code
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case 1:
|
||||
{
|
||||
if (MummyList[nMummy].G > 0)
|
||||
{
|
||||
MummyList[nMummy].G--;
|
||||
}
|
||||
|
||||
if ((MummyList[nMummy].F & 0x1F) == (totalmoves & 0x1F))
|
||||
{
|
||||
sprite[nSprite].cstat = 0x101;
|
||||
|
||||
PlotCourseToSprite(nSprite, nTarget);
|
||||
|
||||
if (MummyList[nMummy].nAction == 1)
|
||||
{
|
||||
if (RandomBit())
|
||||
{
|
||||
if (cansee(sprite[nSprite].x, sprite[nSprite].y, sprite[nSprite].z - GetSpriteHeight(nSprite), sprite[nSprite].sectnum,
|
||||
sprite[nTarget].x, sprite[nTarget].y, sprite[nTarget].z - GetSpriteHeight(nTarget), sprite[nTarget].sectnum))
|
||||
{
|
||||
MummyList[nMummy].nAction = 3;
|
||||
MummyList[nMummy].B = 0;
|
||||
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// loc_2B5A8
|
||||
if (!MummyList[nMummy].B)
|
||||
{
|
||||
sprite[nSprite].xvel = Cos(sprite[nSprite].ang) >> 1;
|
||||
sprite[nSprite].yvel = Sin(sprite[nSprite].ang) >> 1;
|
||||
}
|
||||
|
||||
if (sprite[nSprite].xvel || sprite[nSprite].yvel)
|
||||
{
|
||||
if (sprite[nSprite].xvel > 0)
|
||||
{
|
||||
sprite[nSprite].xvel -= 1024;
|
||||
if (sprite[nSprite].xvel < 0) {
|
||||
sprite[nSprite].xvel = 0;
|
||||
}
|
||||
}
|
||||
else if (sprite[nSprite].xvel < 0)
|
||||
{
|
||||
sprite[nSprite].xvel += 1024;
|
||||
if (sprite[nSprite].xvel > 0) {
|
||||
sprite[nSprite].xvel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (sprite[nSprite].yvel > 0)
|
||||
{
|
||||
sprite[nSprite].yvel -= 1024;
|
||||
if (sprite[nSprite].yvel < 0) {
|
||||
sprite[nSprite].yvel = 0;
|
||||
}
|
||||
}
|
||||
else if (sprite[nSprite].yvel < 0)
|
||||
{
|
||||
sprite[nSprite].yvel += 1024;
|
||||
if (sprite[nSprite].yvel > 0) {
|
||||
sprite[nSprite].yvel = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nMov)
|
||||
{
|
||||
switch (nMov & 0xC000)
|
||||
{
|
||||
case 0x8000:
|
||||
{
|
||||
sprite[nSprite].ang = (sprite[nSprite].ang + ((RandomWord() & 0x3FF) + 1024)) & kAngleMask;
|
||||
sprite[nSprite].xvel = Cos(sprite[nSprite].ang) >> 2;
|
||||
sprite[nSprite].yvel = Sin(sprite[nSprite].ang) >> 2;
|
||||
return;
|
||||
}
|
||||
|
||||
case 0xC000:
|
||||
{
|
||||
if ((nMov & 0x3FFF) == nTarget)
|
||||
{
|
||||
int nAngle = getangle(sprite[nTarget].x - sprite[nSprite].x, sprite[nTarget].y - sprite[nSprite].y);
|
||||
if (AngleDiff(sprite[nSprite].ang, nAngle) < 64)
|
||||
{
|
||||
MummyList[nMummy].nAction = 2;
|
||||
MummyList[nMummy].B = 0;
|
||||
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
if (nTarget == -1)
|
||||
{
|
||||
MummyList[nMummy].nAction = 0;
|
||||
MummyList[nMummy].B = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PlotCourseToSprite(nSprite, nTarget) >= 1024)
|
||||
{
|
||||
MummyList[nMummy].nAction = 1;
|
||||
MummyList[nMummy].B = 0;
|
||||
}
|
||||
else if (nFrameFlag & 0x80)
|
||||
{
|
||||
runlist_DamageEnemy(nTarget, nSprite, 5);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
if (ecx)
|
||||
{
|
||||
MummyList[nMummy].B = 0;
|
||||
MummyList[nMummy].nAction = 0;
|
||||
MummyList[nMummy].G = 100;
|
||||
MummyList[nMummy].nTarget = -1;
|
||||
return;
|
||||
}
|
||||
else if (nFrameFlag & 0x80)
|
||||
{
|
||||
SetQuake(nSprite, 100);
|
||||
|
||||
// low 16 bits of returned var contains the sprite index, the high 16 the bullet number
|
||||
int nBullet = BuildBullet(nSprite, 9, 0, 0, 0x0FFFFC400, sprite[nSprite].ang, nTarget + 10000, 1);
|
||||
CheckMummyRevive(nMummy);
|
||||
|
||||
if (nBullet > -1)
|
||||
{
|
||||
if (!RandomSize(3))
|
||||
{
|
||||
// FIXME CHECKME - nBullet & 0xFFFF can be -1. Original code doesn't handle this??
|
||||
|
||||
SetBulletEnemy(nBullet >> 16, nTarget); // isolate the bullet number (shift off the sprite index)
|
||||
sprite[nBullet & 0xFFFF].pal = 5;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
if (ecx)
|
||||
{
|
||||
MummyList[nMummy].B = 0;
|
||||
MummyList[nMummy].nAction = 5;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case 5:
|
||||
{
|
||||
MummyList[nMummy].B = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
case 6:
|
||||
{
|
||||
if (ecx)
|
||||
{
|
||||
MummyList[nMummy].nAction = 0;
|
||||
sprite[nSprite].cstat = 0x101;
|
||||
MummyList[nMummy].nHealth = 300;
|
||||
MummyList[nMummy].nTarget = -1;
|
||||
nCreaturesLeft++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case 7:
|
||||
{
|
||||
if (nMov & 0x20000)
|
||||
{
|
||||
sprite[nSprite].xvel >>= 1;
|
||||
sprite[nSprite].yvel >>= 1;
|
||||
}
|
||||
|
||||
if (ecx)
|
||||
{
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].cstat = 0x101;
|
||||
|
||||
MummyList[nMummy].nAction = 0;
|
||||
MummyList[nMummy].B = 0;
|
||||
MummyList[nMummy].nTarget = -1;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x90000:
|
||||
{
|
||||
seq_PlotSequence(a & 0xFFFF, SeqOffsets[kSeqMummy] + ActionSeq[nAction].a, MummyList[nMummy].B, ActionSeq[nAction].b);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0xA0000:
|
||||
{
|
||||
if (MummyList[nMummy].nHealth <= 0)
|
||||
return;
|
||||
|
||||
nDamage = runlist_CheckRadialDamage(nSprite);
|
||||
// fall through to 0x80000
|
||||
fallthrough__;
|
||||
}
|
||||
case 0x80000:
|
||||
{
|
||||
if (nDamage <= 0)
|
||||
return;
|
||||
|
||||
if (MummyList[nMummy].nHealth <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
MummyList[nMummy].nHealth -= nDamage;
|
||||
|
||||
if (MummyList[nMummy].nHealth <= 0)
|
||||
{
|
||||
MummyList[nMummy].nHealth = 0;
|
||||
sprite[nSprite].cstat &= 0xFEFE;
|
||||
nCreaturesLeft--;
|
||||
|
||||
DropMagic(nSprite);
|
||||
|
||||
MummyList[nMummy].B = 0;
|
||||
MummyList[nMummy].nAction = 4;
|
||||
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].zvel = 0;
|
||||
sprite[nSprite].z = sector[sprite[nSprite].sectnum].floorz;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!RandomSize(2))
|
||||
{
|
||||
MummyList[nMummy].nAction = 7;
|
||||
MummyList[nMummy].B = 0;
|
||||
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
Printf("unknown msg %d for Mummy\n", a & 0x7F0000);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
END_PS_NS
|
35
source/exhumed/src/mummy.h
Normal file
35
source/exhumed/src/mummy.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __mummy_h__
|
||||
#define __mummy_h__
|
||||
|
||||
#include "runlist.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
#define kMaxMummies 150
|
||||
|
||||
void InitMummy();
|
||||
int BuildMummy(int val, int x, int y, int z, int nSector, int angle);
|
||||
|
||||
void FuncMummy(int nSector, int edx, int nRun);
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
6167
source/exhumed/src/names.h
Normal file
6167
source/exhumed/src/names.h
Normal file
File diff suppressed because it is too large
Load diff
62
source/exhumed/src/network.cpp
Normal file
62
source/exhumed/src/network.cpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
// this is net.c in the original code
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "network.h"
|
||||
#include "serial.h"
|
||||
#include "ps_input.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
short nNetMoveFrames = 0;
|
||||
|
||||
|
||||
void SendGoodbye()
|
||||
{
|
||||
bSendBye = kTrue;
|
||||
UpdateInputs();
|
||||
}
|
||||
|
||||
void UpdateNetInputs()
|
||||
{
|
||||
|
||||
}
|
||||
/*
|
||||
int InitNet(short nSocket, int nPlayers)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
int InitSerial()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void AbortNetworkPlay()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void UnInitNet()
|
||||
{
|
||||
|
||||
}
|
||||
END_PS_NS
|
35
source/exhumed/src/network.h
Normal file
35
source/exhumed/src/network.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __network_h__
|
||||
#define __network_h__
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
extern short nNetMoveFrames;
|
||||
|
||||
void SendGoodbye();
|
||||
void UpdateNetInputs();
|
||||
int InitNet(short nSocket, int nPlayers);
|
||||
int InitSerial();
|
||||
void AbortNetworkPlay();
|
||||
void UnInitNet();
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
2718
source/exhumed/src/object.cpp
Normal file
2718
source/exhumed/src/object.cpp
Normal file
File diff suppressed because it is too large
Load diff
90
source/exhumed/src/object.h
Normal file
90
source/exhumed/src/object.h
Normal file
|
@ -0,0 +1,90 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __object_h__
|
||||
#define __object_h__
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
#define kMaxPoints 1024
|
||||
#define kMaxSlides 128
|
||||
#define kMaxElevs 1024
|
||||
|
||||
enum kStatus
|
||||
{
|
||||
kStatDestructibleSprite = 97,
|
||||
kStat98,
|
||||
kStatExplodeTrigger = 141,
|
||||
kStatExplodeTarget = 152
|
||||
};
|
||||
|
||||
extern short nSmokeSparks;
|
||||
extern short nDronePitch;
|
||||
extern int lFinaleStart;
|
||||
extern short nFinaleSpr;
|
||||
|
||||
void InitObjects();
|
||||
void InitElev();
|
||||
void InitPoint();
|
||||
void InitSlide();
|
||||
void InitWallFace();
|
||||
void DoDrips();
|
||||
void DoMovingSects();
|
||||
void DoFinale();
|
||||
void PostProcess();
|
||||
|
||||
void FuncElev(int, int, int);
|
||||
void FuncWallFace(int, int, int);
|
||||
void FuncSlide(int, int, int);
|
||||
void FuncObject(int, int, int);
|
||||
void FuncTrap(int, int, int);
|
||||
void FuncEnergyBlock(int, int, int);
|
||||
void FuncSpark(int, int, int);
|
||||
|
||||
void SnapBobs(short nSectorA, short nSectorB);
|
||||
|
||||
short FindWallSprites(short nSector);
|
||||
|
||||
void AddMovingSector(int nSector, int edx, int ebx, int ecx);
|
||||
|
||||
int BuildWallSprite(int nSector);
|
||||
|
||||
void ProcessTrailSprite(int nSprite, int nLotag, int nHitag);
|
||||
|
||||
void AddSectorBob(int nSector, int nHitag, int bx);
|
||||
|
||||
int BuildObject(short nSprite, int nOjectType, int nHitag);
|
||||
|
||||
int BuildArrow(int nSprite, int nVal);
|
||||
|
||||
int BuildFireBall(int nSprite, int a, int b);
|
||||
|
||||
void BuildDrip(int nSprite);
|
||||
|
||||
int BuildEnergyBlock(short nSector);
|
||||
|
||||
int BuildElevC(int arg1, int nChannel, int nSector, int nWallSprite, int arg5, int arg6, int nCount, ...);
|
||||
int BuildElevF(int nChannel, int nSector, int nWallSprite, int arg_4, int arg_5, int nCount, ...);
|
||||
|
||||
int BuildWallFace(short nChannel, short nWall, short nCount, ...);
|
||||
|
||||
int BuildSlide(int nChannel, int edx, int ebx, int ecx, int arg1, int arg2, int arg3);
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
62
source/exhumed/src/osdcmds.cpp
Normal file
62
source/exhumed/src/osdcmds.cpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010 EDuke32 developers and contributors
|
||||
|
||||
This file is part of EDuke32.
|
||||
|
||||
EDuke32 is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "compat.h"
|
||||
#include "build.h"
|
||||
#include "common.h"
|
||||
#include "exhumed.h"
|
||||
#include "osdcmds.h"
|
||||
#include "view.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
|
||||
|
||||
int32_t registerosdcommands(void)
|
||||
{
|
||||
//if (VOLUMEONE)
|
||||
// OSD_RegisterFunction("changelevel","changelevel <level>: warps to the given level", osdcmd_changelevel);
|
||||
//else
|
||||
//{
|
||||
// OSD_RegisterFunction("changelevel","changelevel <volume> <level>: warps to the given level", osdcmd_changelevel);
|
||||
// OSD_RegisterFunction("map","map <mapfile>: loads the given user map", osdcmd_map);
|
||||
// OSD_RegisterFunction("demo","demo <demofile or demonum>: starts the given demo", osdcmd_demo);
|
||||
//}
|
||||
|
||||
//OSD_RegisterFunction("cmenu","cmenu <#>: jumps to menu", osdcmd_cmenu);
|
||||
//OSD_RegisterFunction("crosshaircolor","crosshaircolor: changes the crosshair color", osdcmd_crosshaircolor);
|
||||
|
||||
|
||||
//OSD_RegisterFunction("give","give <all|health|weapons|ammo|armor|keys|inventory>: gives requested item", osdcmd_give);
|
||||
//OSD_RegisterFunction("god","god: toggles god mode", osdcmd_god);
|
||||
//OSD_RegisterFunction("activatecheat","activatecheat <id>: activates a cheat code", osdcmd_activatecheat);
|
||||
|
||||
//OSD_RegisterFunction("restartmap", "restartmap: restarts the current map", osdcmd_restartmap);
|
||||
//OSD_RegisterFunction("restartsound","restartsound: reinitializes the sound system",osdcmd_restartsound);
|
||||
|
||||
//OSD_RegisterFunction("spawn","spawn <picnum> [palnum] [cstat] [ang] [x y z]: spawns a sprite with the given properties",osdcmd_spawn);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
END_PS_NS
|
43
source/exhumed/src/osdcmds.h
Normal file
43
source/exhumed/src/osdcmds.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010 EDuke32 developers and contributors
|
||||
|
||||
This file is part of EDuke32.
|
||||
|
||||
EDuke32 is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef osdcmds_h_
|
||||
#define osdcmds_h_
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
|
||||
int32_t registerosdcommands(void);
|
||||
void onvideomodechange(int32_t newmode);
|
||||
void GAME_onshowosd(int shown);
|
||||
void GAME_clearbackground(int numcols, int numrows);
|
||||
|
||||
//extern float r_ambientlight,r_ambientlightrecip;
|
||||
|
||||
extern const char *const ConsoleButtons[];
|
||||
|
||||
//extern uint32_t cl_cheatmask;
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif // osdcmds_h_
|
||||
|
19
source/exhumed/src/paul.cpp
Normal file
19
source/exhumed/src/paul.cpp
Normal file
|
@ -0,0 +1,19 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#include "paul.h"
|
24
source/exhumed/src/paul.h
Normal file
24
source/exhumed/src/paul.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __paul_h__
|
||||
#define __paul_h__
|
||||
|
||||
|
||||
|
||||
#endif
|
3168
source/exhumed/src/player.cpp
Normal file
3168
source/exhumed/src/player.cpp
Normal file
File diff suppressed because it is too large
Load diff
130
source/exhumed/src/player.h
Normal file
130
source/exhumed/src/player.h
Normal file
|
@ -0,0 +1,130 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __player_h__
|
||||
#define __player_h__
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
void PlayerInterruptKeys();
|
||||
void RestoreSavePoint(int nPlayer, int *x, int *y, int *z, short *nSector, short *nAngle);
|
||||
void SetSavePoint(int nPlayer, int x, int y, int z, short nSector, short nAngle);
|
||||
void InitPlayer();
|
||||
void InitPlayerKeys(short nPlayer);
|
||||
void DoKenTest();
|
||||
int GrabPlayer();
|
||||
void InitPlayerInventory(short nPlayer);
|
||||
void RestartPlayer(short nPlayer);
|
||||
|
||||
void FuncPlayer(int nSector, int nSprite, int nRun);
|
||||
|
||||
#define kMaxPlayers 8
|
||||
#define kDefaultLives 3
|
||||
#define kMaxPlayerLives 5
|
||||
#define kMaxHealth 800
|
||||
|
||||
extern int nLocalPlayer;
|
||||
|
||||
extern int lPlayerXVel;
|
||||
extern int lPlayerYVel;
|
||||
extern fix16_t nPlayerDAng;
|
||||
|
||||
struct Player
|
||||
{
|
||||
short nHealth;
|
||||
short field_2;
|
||||
short nAction;
|
||||
short nSprite;
|
||||
short bIsMummified;
|
||||
short someNetVal;
|
||||
short invincibility;
|
||||
short nAir;
|
||||
short nSeq;
|
||||
short nMaskAmount;
|
||||
uint16_t keys;
|
||||
short nMagic;
|
||||
char items[8];
|
||||
short nAmmo[7]; // TODO - kMaxWeapons?
|
||||
short pad[2];
|
||||
|
||||
short nCurrentWeapon;
|
||||
short field_3FOUR;
|
||||
short bIsFiring;
|
||||
short field_38;
|
||||
short field_3A;
|
||||
short field_3C;
|
||||
short nRun;
|
||||
|
||||
fix16_t q16angle, q16oangle;
|
||||
fix16_t q16horiz, q16ohoriz;
|
||||
vec3_t opos;
|
||||
};
|
||||
|
||||
extern short PlayerCount;
|
||||
|
||||
extern short nPlayerTorch[];
|
||||
|
||||
extern short nPlayerLives[];
|
||||
extern short nPlayerItem[];
|
||||
extern Player PlayerList[];
|
||||
extern short nPlayerInvisible[];
|
||||
extern short nPlayerDouble[];
|
||||
extern short nPlayerViewSect[];
|
||||
extern short nPlayerFloorSprite[];
|
||||
|
||||
extern short nTauntTimer[];
|
||||
|
||||
extern short nDoppleSprite[];
|
||||
|
||||
extern uint16_t nPlayerWeapons[];
|
||||
|
||||
extern short nPlayerOldWeapon[];
|
||||
extern short nPlayerGrenade[kMaxPlayers];
|
||||
extern short nGrenadePlayer[50];
|
||||
|
||||
extern short nPistolClip[];
|
||||
|
||||
extern short nPlayerScore[];
|
||||
|
||||
extern short nPlayerClip[];
|
||||
|
||||
extern short obobangle, bobangle;
|
||||
|
||||
extern int totalvel[];
|
||||
extern int16_t eyelevel[], oeyelevel[];
|
||||
|
||||
extern short nNetStartSprite[kMaxPlayers];
|
||||
extern short nNetStartSprites;
|
||||
extern short nCurStartSprite;
|
||||
|
||||
extern int nXDamage[kMaxPlayers];
|
||||
extern int nYDamage[kMaxPlayers];
|
||||
|
||||
extern int nPlayerDY[kMaxPlayers];
|
||||
extern int nPlayerDX[kMaxPlayers];
|
||||
|
||||
short GetPlayerFromSprite(short nSprite);
|
||||
void SetPlayerMummified(int nPlayer, int bIsMummified);
|
||||
int AddAmmo(int nPlayer, int nWeapon, int nAmmoAmount);
|
||||
void ShootStaff(int nPlayer);
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
70
source/exhumed/src/ps_input.h
Normal file
70
source/exhumed/src/ps_input.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __input_h__
|
||||
#define __input_h__
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
enum {
|
||||
kButtonJump = 0x1,
|
||||
kButtonOpen = 0x4,
|
||||
kButtonFire = 0x8,
|
||||
kButtonCrouch = 0x10,
|
||||
kButtonCheatGuns = 0x20,
|
||||
kButtonCheatGodMode = 0x40,
|
||||
kButtonCheatKeys = 0x80,
|
||||
kButtonCheatItems = 0x100,
|
||||
};
|
||||
|
||||
// 32 bytes
|
||||
struct PlayerInput // TODO consider adjusting this for demo compatibility
|
||||
{
|
||||
int xVel;
|
||||
int yVel;
|
||||
// short nAngle;
|
||||
fix16_t nAngle;
|
||||
uint16_t buttons;
|
||||
short nTarget;
|
||||
// uint8_t horizon;
|
||||
fix16_t horizon;
|
||||
int8_t nItem;
|
||||
int h;
|
||||
char i;
|
||||
char field_15[11];
|
||||
};
|
||||
|
||||
void InitInput();
|
||||
void ClearAllKeys();
|
||||
void WaitNoKey(int nSecs, void (*pFunc) (void));
|
||||
int WaitAnyKey(int nSecs);
|
||||
|
||||
void UpdateInputs();
|
||||
|
||||
void ClearSpaceBar(short nPlayer);
|
||||
|
||||
void GetLocalInput();
|
||||
|
||||
extern PlayerInput sPlayerInput[];
|
||||
extern int nNetMoves;
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
1504
source/exhumed/src/queen.cpp
Normal file
1504
source/exhumed/src/queen.cpp
Normal file
File diff suppressed because it is too large
Load diff
34
source/exhumed/src/queen.h
Normal file
34
source/exhumed/src/queen.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __queen_h__
|
||||
#define __queen_h__
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
void InitQueens();
|
||||
|
||||
int BuildQueen(int nSprite, int x, int y, int z, int nSector, int nAngle, int nVal);
|
||||
|
||||
void FuncQueenEgg(int, int, int);
|
||||
void FuncQueenHead(int, int, int);
|
||||
void FuncQueen(int, int, int);
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
302
source/exhumed/src/ra.cpp
Normal file
302
source/exhumed/src/ra.cpp
Normal file
|
@ -0,0 +1,302 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "ra.h"
|
||||
#include "runlist.h"
|
||||
#include "engine.h"
|
||||
#include "exhumed.h"
|
||||
#include "player.h"
|
||||
#include "move.h"
|
||||
#include "sequence.h"
|
||||
#include "ps_input.h"
|
||||
#include "gun.h"
|
||||
#include "bullet.h"
|
||||
#include <string.h>
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
/* bjd - the content of the ra.* files originally resided in gun.c I think... */
|
||||
|
||||
//#define kMaxRA 8
|
||||
|
||||
RA Ra[kMaxPlayers]; // one Ra for each player
|
||||
short RaCount;
|
||||
|
||||
static actionSeq ActionSeq[] = {
|
||||
{2, 1}, {0, 0}, {1, 0}, {2, 0}
|
||||
};
|
||||
|
||||
static SavegameHelper sgh("ra",
|
||||
SA(Ra),
|
||||
SV(RaCount),
|
||||
nullptr);
|
||||
|
||||
|
||||
void FreeRa(short nPlayer)
|
||||
{
|
||||
int nRun = Ra[nPlayer].field_4;
|
||||
int nSprite = Ra[nPlayer].nSprite;
|
||||
|
||||
runlist_SubRunRec(nRun);
|
||||
runlist_DoSubRunRec(sprite[nSprite].owner);
|
||||
runlist_FreeRun(sprite[nSprite].lotag - 1);
|
||||
|
||||
mydeletesprite(nSprite);
|
||||
}
|
||||
|
||||
int BuildRa(short nPlayer)
|
||||
{
|
||||
short nPlayerSprite = PlayerList[nPlayer].nSprite;
|
||||
|
||||
int nSprite = insertsprite(sprite[nPlayerSprite].sectnum, 203);
|
||||
|
||||
sprite[nSprite].cstat = 0x8000;
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].zvel = 0;
|
||||
sprite[nSprite].extra = -1;
|
||||
sprite[nSprite].lotag = runlist_HeadRun() + 1;
|
||||
sprite[nSprite].hitag = 0;
|
||||
sprite[nSprite].owner = runlist_AddRunRec(sprite[nSprite].lotag - 1, nPlayer | 0x210000);
|
||||
sprite[nSprite].pal = 1;
|
||||
sprite[nSprite].xrepeat = 64;
|
||||
sprite[nSprite].yrepeat = 64;
|
||||
sprite[nSprite].x = sprite[nPlayerSprite].x;
|
||||
sprite[nSprite].y = sprite[nPlayerSprite].y;
|
||||
sprite[nSprite].z = sprite[nPlayerSprite].z;
|
||||
|
||||
// GrabTimeSlot(3);
|
||||
|
||||
Ra[nPlayer].nSprite = nSprite;
|
||||
|
||||
Ra[nPlayer].field_4 = runlist_AddRunRec(NewRun, nPlayer | 0x210000);
|
||||
Ra[nPlayer].nTarget = -1;
|
||||
Ra[nPlayer].field_2 = 0;
|
||||
Ra[nPlayer].field_0 = 0;
|
||||
Ra[nPlayer].field_C = 0;
|
||||
Ra[nPlayer].field_E = nPlayer;
|
||||
|
||||
return nPlayer | 0x210000;
|
||||
}
|
||||
|
||||
void InitRa()
|
||||
{
|
||||
RaCount = 0;
|
||||
memset(Ra, 0, sizeof(RA) * kMaxPlayers);
|
||||
}
|
||||
|
||||
void MoveRaToEnemy(short nPlayer)
|
||||
{
|
||||
short nTarget = Ra[nPlayer].nTarget;
|
||||
short nSprite = Ra[nPlayer].nSprite;
|
||||
short field_0 = Ra[nPlayer].field_0;
|
||||
|
||||
if (nTarget != -1)
|
||||
{
|
||||
if (!(sprite[nTarget].cstat & 0x101) || sprite[nTarget].sectnum == MAXSECTORS)
|
||||
{
|
||||
Ra[nPlayer].nTarget = -1;
|
||||
if (!field_0 || field_0 == 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ra[nPlayer].field_0 = 3;
|
||||
Ra[nPlayer].field_2 = 0;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sprite[nSprite].sectnum != sprite[nTarget].sectnum) {
|
||||
mychangespritesect(nSprite, sprite[nTarget].sectnum);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (field_0 == 1 || field_0 == 2)
|
||||
{
|
||||
Ra[nPlayer].field_0 = 3;
|
||||
Ra[nPlayer].field_2 = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (field_0) {
|
||||
return;
|
||||
}
|
||||
|
||||
sprite[nSprite].cstat = 0x8000;
|
||||
nTarget = PlayerList[nPlayer].nSprite;
|
||||
}
|
||||
|
||||
sprite[nSprite].x = sprite[nTarget].x;
|
||||
sprite[nSprite].y = sprite[nTarget].y;
|
||||
sprite[nSprite].z = sprite[nTarget].z - GetSpriteHeight(nTarget);
|
||||
|
||||
if (sprite[nSprite].sectnum != sprite[nTarget].sectnum) {
|
||||
mychangespritesect(nSprite, sprite[nTarget].sectnum);
|
||||
}
|
||||
}
|
||||
|
||||
void FuncRa(int a, int UNUSED(nDamage), int nRun)
|
||||
{
|
||||
short nPlayer = RunData[nRun].nVal;
|
||||
short nCurrentWeapon = PlayerList[nPlayer].nCurrentWeapon;
|
||||
|
||||
int var_14 = 0;
|
||||
|
||||
short edx = SeqOffsets[kSeqEyeHit] + ActionSeq[Ra[nPlayer].field_0].a;
|
||||
short nSprite = Ra[nPlayer].nSprite;
|
||||
|
||||
int nMessage = a & 0x7F0000;
|
||||
|
||||
switch (nMessage)
|
||||
{
|
||||
default:
|
||||
{
|
||||
Printf("unknown msg %d for Ra\n", a & 0x7F0000);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x30000:
|
||||
case 0xA0000:
|
||||
return;
|
||||
|
||||
case 0x20000:
|
||||
{
|
||||
Ra[nPlayer].nTarget = sPlayerInput[nPlayer].nTarget;
|
||||
sprite[nSprite].picnum = seq_GetSeqPicnum2(edx, Ra[nPlayer].field_2);
|
||||
|
||||
if (Ra[nPlayer].field_0)
|
||||
{
|
||||
seq_MoveSequence(nSprite, edx, Ra[nPlayer].field_2);
|
||||
|
||||
Ra[nPlayer].field_2++;
|
||||
if (Ra[nPlayer].field_2 >= SeqSize[edx])
|
||||
{
|
||||
Ra[nPlayer].field_2 = 0;
|
||||
var_14 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
switch (Ra[nPlayer].field_0)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
MoveRaToEnemy(nPlayer);
|
||||
|
||||
if (!Ra[nPlayer].field_C || Ra[nPlayer].nTarget <= -1)
|
||||
{
|
||||
sprite[nSprite].cstat = 0x8000;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite[nSprite].cstat &= 0x7FFF;
|
||||
Ra[nPlayer].field_0 = 1;
|
||||
Ra[nPlayer].field_2 = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case 1:
|
||||
{
|
||||
if (!Ra[nPlayer].field_C)
|
||||
{
|
||||
Ra[nPlayer].field_0 = 3;
|
||||
Ra[nPlayer].field_2 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (var_14) {
|
||||
Ra[nPlayer].field_0 = 2;
|
||||
}
|
||||
|
||||
MoveRaToEnemy(nPlayer);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
MoveRaToEnemy(nPlayer);
|
||||
|
||||
if (nCurrentWeapon != kWeaponRing)
|
||||
{
|
||||
Ra[nPlayer].field_0 = 3;
|
||||
Ra[nPlayer].field_2 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Ra[nPlayer].field_2 || Ra[nPlayer].nTarget <= -1)
|
||||
{
|
||||
if (!var_14) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ra[nPlayer].field_0 = 3;
|
||||
Ra[nPlayer].field_2 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PlayerList[nPlayer].nAmmo[kWeaponRing] > 0)
|
||||
{
|
||||
runlist_DamageEnemy(Ra[nPlayer].nTarget, PlayerList[Ra[nPlayer].field_E].nSprite, BulletInfo[kWeaponRing].nDamage);
|
||||
AddAmmo(nPlayer, kWeaponRing, -WeaponInfo[kWeaponRing].d);
|
||||
SetQuake(nSprite, 100);
|
||||
}
|
||||
else
|
||||
{
|
||||
Ra[nPlayer].field_0 = 3;
|
||||
Ra[nPlayer].field_2 = 0;
|
||||
SelectNewWeapon(nPlayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
if (var_14)
|
||||
{
|
||||
sprite[nSprite].cstat |= 0x8000;
|
||||
Ra[nPlayer].field_0 = 0;
|
||||
Ra[nPlayer].field_2 = 0;
|
||||
Ra[nPlayer].field_C = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
case 0x90000:
|
||||
{
|
||||
short nSprite2 = a & 0xFFFF;
|
||||
seq_PlotSequence(nSprite2, edx, Ra[nPlayer].field_2, 1);
|
||||
tsprite[nSprite2].owner = -1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
END_PS_NS
|
46
source/exhumed/src/ra.h
Normal file
46
source/exhumed/src/ra.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __ra_h__
|
||||
#define __ra_h__
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
struct RA
|
||||
{
|
||||
short field_0;
|
||||
short field_2;
|
||||
short field_4;
|
||||
short nSprite;
|
||||
short nTarget;
|
||||
short field_A;
|
||||
short field_C;
|
||||
short field_E;
|
||||
};
|
||||
|
||||
extern RA Ra[];
|
||||
|
||||
void FreeRa(short nPlayer);
|
||||
int BuildRa(short nPlayer);
|
||||
void InitRa();
|
||||
void MoveRaToEnemy(short nPlayer);
|
||||
void FuncRa(int, int, int);
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
90
source/exhumed/src/random.cpp
Normal file
90
source/exhumed/src/random.cpp
Normal file
|
@ -0,0 +1,90 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "random.h"
|
||||
#include "exhumed.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
int randA = 0;
|
||||
int randB = 0x11111111;
|
||||
int randC = 0x1010101;
|
||||
|
||||
static SavegameHelper sgh("rand",
|
||||
SV(randA),
|
||||
SV(randB),
|
||||
SV(randC),
|
||||
nullptr);
|
||||
|
||||
|
||||
void InitRandom()
|
||||
{
|
||||
randA = 0;
|
||||
randB = 0x11111111;
|
||||
randC = 0x1010101;
|
||||
}
|
||||
|
||||
// TODO - checkme
|
||||
int RandomBit()
|
||||
{
|
||||
randA = (randA >> 1) | (((randA ^ ((randA >> 1) ^ (randA >> 2) ^ (randA >> 31) ^ (randA >> 6) ^ (randA >> 4))) & 1) << 31);
|
||||
randB = (randB >> 1) | ((((randB >> 2) ^ (randB >> 30)) & 1) << 30);
|
||||
randC = (randC >> 1) | ((((randC >> 1) ^ (randC >> 28)) & 1) << 28);
|
||||
return ((randA == 0) & randC | (randB & randA)) & 1;
|
||||
}
|
||||
|
||||
char RandomByte()
|
||||
{
|
||||
char randByte = RandomBit() << 7;
|
||||
randByte |= RandomBit() << 6;
|
||||
randByte |= RandomBit() << 5;
|
||||
randByte |= RandomBit() << 4;
|
||||
randByte |= RandomBit() << 3;
|
||||
randByte |= RandomBit() << 2;
|
||||
randByte |= RandomBit() << 1;
|
||||
randByte |= RandomBit();
|
||||
return randByte;
|
||||
}
|
||||
|
||||
uint16_t RandomWord()
|
||||
{
|
||||
short randWord = RandomByte() << 8;
|
||||
randWord |= RandomByte();
|
||||
return randWord;
|
||||
}
|
||||
|
||||
int RandomLong()
|
||||
{
|
||||
int randLong = RandomWord() << 16;
|
||||
randLong |= RandomWord();
|
||||
return randLong;
|
||||
}
|
||||
|
||||
int RandomSize(int nSize)
|
||||
{
|
||||
int randSize = 0;
|
||||
|
||||
while (nSize > 0)
|
||||
{
|
||||
randSize = randSize * 2 | RandomBit();
|
||||
nSize--;
|
||||
}
|
||||
|
||||
return randSize;
|
||||
}
|
||||
END_PS_NS
|
34
source/exhumed/src/random.h
Normal file
34
source/exhumed/src/random.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __random_h__
|
||||
#define __random_h__
|
||||
#include "compat.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
void InitRandom();
|
||||
int RandomBit();
|
||||
char RandomByte();
|
||||
uint16_t RandomWord();
|
||||
int RandomLong();
|
||||
int RandomSize(int nSize);
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
395
source/exhumed/src/rat.cpp
Normal file
395
source/exhumed/src/rat.cpp
Normal file
|
@ -0,0 +1,395 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "engine.h"
|
||||
#include "rat.h"
|
||||
#include "sequence.h"
|
||||
#include "runlist.h"
|
||||
#include "random.h"
|
||||
#include "view.h"
|
||||
#include "init.h"
|
||||
#include "exhumed.h"
|
||||
#include "move.h"
|
||||
#include <assert.h>
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
#define kMaxRats 50
|
||||
|
||||
short nMinChunk;
|
||||
short nPlayerPic;
|
||||
short nRatCount;
|
||||
short nMaxChunk;
|
||||
|
||||
struct Rat
|
||||
{
|
||||
short a;
|
||||
short nAction;
|
||||
short nSprite;
|
||||
short d;
|
||||
short nTarget;
|
||||
short f;
|
||||
short g;
|
||||
// short _pad;
|
||||
};
|
||||
|
||||
Rat RatList[kMaxRats];
|
||||
|
||||
static actionSeq ActionSeq[] = {{0, 1}, {1, 0}, {1, 0}, {9, 1}, {0, 1}};
|
||||
|
||||
|
||||
static SavegameHelper sgh("rat",
|
||||
SV(nMinChunk),
|
||||
SV(nPlayerPic),
|
||||
SV(nRatCount),
|
||||
SV(nMaxChunk),
|
||||
SA(RatList),
|
||||
nullptr);
|
||||
|
||||
void InitRats()
|
||||
{
|
||||
nRatCount = 0;
|
||||
nMinChunk = 9999;
|
||||
nMaxChunk = -1;
|
||||
|
||||
for (int i = 122; i <= 131; i++)
|
||||
{
|
||||
int nPic = seq_GetSeqPicnum(kSeqJoe, i, 0);
|
||||
|
||||
if (nPic < nMinChunk)
|
||||
nMinChunk = nPic;
|
||||
|
||||
if (nPic > nMaxChunk)
|
||||
nMaxChunk = nPic;
|
||||
}
|
||||
|
||||
nPlayerPic = seq_GetSeqPicnum(kSeqJoe, 120, 0);
|
||||
}
|
||||
|
||||
void SetRatVel(short nSprite)
|
||||
{
|
||||
sprite[nSprite].xvel = Cos(sprite[nSprite].ang) >> 2;
|
||||
sprite[nSprite].yvel = Sin(sprite[nSprite].ang) >> 2;
|
||||
}
|
||||
|
||||
int BuildRat(short nSprite, int x, int y, int z, short nSector, int nAngle)
|
||||
{
|
||||
if (nRatCount >= kMaxRats) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
short nRat = nRatCount++;
|
||||
|
||||
if (nSprite < 0)
|
||||
{
|
||||
nSprite = insertsprite(nSector, 108);
|
||||
assert(nSprite >= 0 && nSprite < kMaxSprites);
|
||||
|
||||
sprite[nSprite].x = x;
|
||||
sprite[nSprite].y = y;
|
||||
sprite[nSprite].z = z;
|
||||
}
|
||||
else
|
||||
{
|
||||
nAngle = sprite[nSprite].ang;
|
||||
changespritestat(nSprite, 108);
|
||||
}
|
||||
|
||||
sprite[nSprite].cstat = 0x101;
|
||||
sprite[nSprite].shade = -12;
|
||||
sprite[nSprite].xoffset = 0;
|
||||
sprite[nSprite].yoffset = 0;
|
||||
sprite[nSprite].picnum = 1;
|
||||
sprite[nSprite].pal = sector[sprite[nSprite].sectnum].ceilingpal;
|
||||
sprite[nSprite].clipdist = 30;
|
||||
sprite[nSprite].ang = nAngle;
|
||||
sprite[nSprite].xrepeat = 50;
|
||||
sprite[nSprite].yrepeat = 50;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].zvel = 0;
|
||||
sprite[nSprite].lotag = runlist_HeadRun() + 1;
|
||||
sprite[nSprite].hitag = 0;
|
||||
sprite[nSprite].extra = -1;
|
||||
|
||||
if (nAngle >= 0) {
|
||||
RatList[nRat].nAction = 2;
|
||||
}
|
||||
else {
|
||||
RatList[nRat].nAction = 4;
|
||||
}
|
||||
|
||||
RatList[nRat].a = 0;
|
||||
RatList[nRat].nSprite = nSprite;
|
||||
RatList[nRat].nTarget = -1;
|
||||
RatList[nRat].f = RandomSize(5);
|
||||
RatList[nRat].g = RandomSize(3);
|
||||
|
||||
sprite[nSprite].owner = runlist_AddRunRec(sprite[nSprite].lotag - 1, nRat | 0x240000);
|
||||
|
||||
RatList[nRat].d = runlist_AddRunRec(NewRun, nRat | 0x240000);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FindFood(short nSprite)
|
||||
{
|
||||
short nSector = sprite[nSprite].sectnum;
|
||||
int x = sprite[nSprite].x;
|
||||
int y = sprite[nSprite].y;
|
||||
int z = sprite[nSprite].z;
|
||||
|
||||
int z2 = (z + sector[nSector].ceilingz) / 2;
|
||||
|
||||
if (nChunkTotal)
|
||||
{
|
||||
int nSprite2 = nChunkSprite[RandomSize(7) % nChunkTotal];
|
||||
if (nSprite2 != -1)
|
||||
{
|
||||
if (cansee(x, y, z2, nSector, sprite[nSprite2].x, sprite[nSprite2].y, sprite[nSprite2].z, sprite[nSprite2].sectnum)) {
|
||||
return nSprite2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!nBodyTotal) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int nSprite2 = nBodySprite[RandomSize(7) % nBodyTotal];
|
||||
if (nSprite2 != -1)
|
||||
{
|
||||
if (nPlayerPic == sprite[nSprite2].picnum)
|
||||
{
|
||||
if (cansee(x, y, z, nSector, sprite[nSprite2].x, sprite[nSprite2].y, sprite[nSprite2].z, sprite[nSprite2].sectnum)) {
|
||||
return nSprite2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void FuncRat(int a, int nDamage, int nRun)
|
||||
{
|
||||
short nRat = RunData[nRun].nVal;
|
||||
short nSprite = RatList[nRat].nSprite;
|
||||
short nAction = RatList[nRat].nAction;
|
||||
|
||||
bool var_20 = false;
|
||||
|
||||
int nMessage = a & 0x7F0000;
|
||||
|
||||
switch (nMessage)
|
||||
{
|
||||
default:
|
||||
{
|
||||
Printf("unknown msg %d for Rathead\n", nMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0xA0000:
|
||||
{
|
||||
nDamage = runlist_CheckRadialDamage(nSprite);
|
||||
// fall through to 0x80000
|
||||
fallthrough__;
|
||||
}
|
||||
case 0x80000:
|
||||
{
|
||||
if (nDamage)
|
||||
{
|
||||
sprite[nSprite].cstat = 0;
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
RatList[nRat].nAction = 3;
|
||||
RatList[nRat].a = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x90000:
|
||||
{
|
||||
seq_PlotSequence(a & 0xFFFF, SeqOffsets[kSeqRat] + ActionSeq[nAction].a, RatList[nRat].a, ActionSeq[nAction].b);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x20000:
|
||||
{
|
||||
int nSeq = SeqOffsets[kSeqRat] + ActionSeq[nAction].a;
|
||||
sprite[nSprite].picnum = seq_GetSeqPicnum2(nSeq, RatList[nRat].a);
|
||||
|
||||
seq_MoveSequence(nSprite, nSeq, RatList[nRat].a);
|
||||
|
||||
RatList[nRat].a++;
|
||||
if (RatList[nRat].a >= SeqSize[nSeq])
|
||||
{
|
||||
var_20 = true;
|
||||
RatList[nRat].a = 0;
|
||||
}
|
||||
|
||||
short nTarget = RatList[nRat].nTarget;
|
||||
|
||||
Gravity(nSprite);
|
||||
|
||||
switch (nAction)
|
||||
{
|
||||
default:
|
||||
return;
|
||||
|
||||
case 0:
|
||||
{
|
||||
RatList[nRat].f--;
|
||||
if (RatList[nRat].f > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int xVal = klabs(sprite[nSprite].x - sprite[nTarget].x);
|
||||
int yVal = klabs(sprite[nSprite].y - sprite[nTarget].y);
|
||||
|
||||
if (xVal > 50 || yVal > 50)
|
||||
{
|
||||
RatList[nRat].nAction = 2;
|
||||
RatList[nRat].a = 0;
|
||||
RatList[nRat].nTarget = -1;
|
||||
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
RatList[nRat].a ^= 1;
|
||||
RatList[nRat].f = RandomSize(5) + 4;
|
||||
RatList[nRat].g--;
|
||||
|
||||
if (RatList[nRat].g <= 0)
|
||||
{
|
||||
short nFoodSprite = FindFood(nSprite);
|
||||
if (nFoodSprite == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
RatList[nRat].nTarget = nFoodSprite;
|
||||
|
||||
PlotCourseToSprite(nSprite, nFoodSprite);
|
||||
SetRatVel(nSprite);
|
||||
|
||||
RatList[nRat].nAction = 1;
|
||||
RatList[nRat].g = 900;
|
||||
RatList[nRat].a = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
RatList[nRat].g--;
|
||||
|
||||
if (RatList[nRat].g <= 0)
|
||||
{
|
||||
RatList[nRat].nAction = 2;
|
||||
RatList[nRat].a = 0;
|
||||
RatList[nRat].nTarget = -1;
|
||||
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
}
|
||||
|
||||
MoveCreature(nSprite);
|
||||
|
||||
int xVal = klabs(sprite[nSprite].x - sprite[nTarget].x);
|
||||
int yVal = klabs(sprite[nSprite].y - sprite[nTarget].y);
|
||||
|
||||
if (xVal >= 50 || yVal >= 50)
|
||||
{
|
||||
RatList[nRat].f--;
|
||||
if (RatList[nRat].f < 0)
|
||||
{
|
||||
PlotCourseToSprite(nSprite, nTarget);
|
||||
SetRatVel(nSprite);
|
||||
|
||||
RatList[nRat].f = 32;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
RatList[nRat].nAction = 0;
|
||||
RatList[nRat].a = 0;
|
||||
RatList[nRat].g = RandomSize(3);
|
||||
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
return;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
if (sprite[nSprite].xvel || sprite[nSprite].yvel || sprite[nSprite].zvel) {
|
||||
MoveCreature(nSprite);
|
||||
}
|
||||
|
||||
RatList[nRat].f--;
|
||||
if (RatList[nRat].f <= 0)
|
||||
{
|
||||
RatList[nRat].nTarget = FindFood(nSprite);
|
||||
|
||||
if (RatList[nRat].nTarget <= -1)
|
||||
{
|
||||
RatList[nRat].f = RandomSize(6);
|
||||
if (sprite[nSprite].xvel || sprite[nSprite].yvel)
|
||||
{
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
sprite[nSprite].ang = RandomSize(11);
|
||||
SetRatVel(nSprite);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
PlotCourseToSprite(nSprite, RatList[nRat].nTarget);
|
||||
SetRatVel(nSprite);
|
||||
RatList[nRat].nAction = 1;
|
||||
RatList[nRat].g = 900;
|
||||
RatList[nRat].a = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
if (var_20)
|
||||
{
|
||||
runlist_DoSubRunRec(sprite[nSprite].owner);
|
||||
runlist_FreeRun(sprite[nSprite].lotag - 1);
|
||||
runlist_SubRunRec(RatList[nRat].d);
|
||||
|
||||
sprite[nSprite].cstat = 0x8000;
|
||||
mydeletesprite(nSprite);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
END_PS_NS
|
32
source/exhumed/src/rat.h
Normal file
32
source/exhumed/src/rat.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __rat_h__
|
||||
#define __rat_h__
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
void InitRats();
|
||||
void SetRatVel(short nSprite);
|
||||
int BuildRat(short nSprite, int x, int y, int z, short nSector, int nAngle);
|
||||
int FindFood(short nSprite);
|
||||
void FuncRat(int a, int b, int nRun);
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
173
source/exhumed/src/record.cpp
Normal file
173
source/exhumed/src/record.cpp
Normal file
|
@ -0,0 +1,173 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "compat.h"
|
||||
#include "record.h"
|
||||
#include "typedefs.h"
|
||||
#include "save.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
short record_mode = 0;
|
||||
int record_limit = -1;
|
||||
int record_index = 16384;
|
||||
uint8_t record_buffer[16384];
|
||||
FILE *record_file;
|
||||
|
||||
struct RecordHeader
|
||||
{
|
||||
char signature[4];
|
||||
short b;
|
||||
};
|
||||
|
||||
RecordHeader record_head;
|
||||
|
||||
|
||||
uint8_t GetRecord()
|
||||
{
|
||||
if (record_index >= 16384)
|
||||
{
|
||||
record_index = 0;
|
||||
|
||||
int nRead = fread(record_buffer, 1, 16384, record_file);
|
||||
|
||||
if (nRead < 16384) {
|
||||
record_limit = 16384;
|
||||
}
|
||||
else {
|
||||
record_limit = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (record_limit > 0)
|
||||
{
|
||||
if (record_limit <= record_index)
|
||||
{
|
||||
record_mode = 3;
|
||||
}
|
||||
}
|
||||
|
||||
return record_buffer[record_index++];
|
||||
}
|
||||
|
||||
void PutRecord(uint8_t record)
|
||||
{
|
||||
uint8_t val_10 = record;
|
||||
|
||||
if (record_index >= 16384)
|
||||
{
|
||||
record_index = 0;
|
||||
|
||||
fwrite(record_buffer, 16384, 1, record_file);
|
||||
}
|
||||
|
||||
record_buffer[record_index++] = val_10;
|
||||
}
|
||||
|
||||
int OpenRecord(const char *filename, short *edx)
|
||||
{
|
||||
record_file = fopen(filename, "rb");
|
||||
if (record_file)
|
||||
{
|
||||
if (!fread(&record_head, sizeof(record_head), 1, record_file)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (memcmp(record_head.signature, "LOBO", 4) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*edx = record_head.b;
|
||||
|
||||
record_index = 16384;
|
||||
record_limit = -1;
|
||||
record_mode = 2;
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
record_file = fopen(filename, "wb");
|
||||
if (!record_file) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
strncpy(record_head.signature, "LOBO", 4);
|
||||
record_head.b = *edx;
|
||||
|
||||
if (!fwrite(&record_head, sizeof(record_head), 1, record_file)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
record_index = 0;
|
||||
record_limit = -1;
|
||||
record_mode = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int ExecRecord(uint8_t *pRecord, int nSize)
|
||||
{
|
||||
if (record_mode == 2)
|
||||
{
|
||||
for (int i = 0; i < nSize; i++)
|
||||
{
|
||||
pRecord[i] = GetRecord();
|
||||
}
|
||||
}
|
||||
else if (record_mode == 1)
|
||||
{
|
||||
for (int i = 0; i < nSize; i++)
|
||||
{
|
||||
PutRecord(pRecord[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (record_mode == 3) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int CloseRecord()
|
||||
{
|
||||
if (record_mode == 1)
|
||||
{
|
||||
//loadgame(0); ???
|
||||
|
||||
if (record_index)
|
||||
{
|
||||
if (!fwrite(record_buffer, record_index, 1, record_file)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (record_mode == 2 || record_mode == 3)
|
||||
{
|
||||
//loadgame(1); ???
|
||||
}
|
||||
|
||||
fclose(record_file);
|
||||
return 1;
|
||||
}
|
||||
END_PS_NS
|
30
source/exhumed/src/record.h
Normal file
30
source/exhumed/src/record.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __record_h__
|
||||
#define __record_h__
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
|
||||
extern short record_mode;
|
||||
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
491
source/exhumed/src/rex.cpp
Normal file
491
source/exhumed/src/rex.cpp
Normal file
|
@ -0,0 +1,491 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "rex.h"
|
||||
#include "exhumed.h"
|
||||
#include "engine.h"
|
||||
#include "runlist.h"
|
||||
#include "move.h"
|
||||
#include "sequence.h"
|
||||
#include "sound.h"
|
||||
#include "random.h"
|
||||
#include "trigdat.h"
|
||||
#include "player.h"
|
||||
#include "aistuff.h"
|
||||
#include <assert.h>
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
#define kMaxRex 50
|
||||
|
||||
short RexCount = 0;
|
||||
short RexChan[kMaxRex];
|
||||
|
||||
struct Rex
|
||||
{
|
||||
short nHealth;
|
||||
short field_2;
|
||||
short nAction;
|
||||
short nSprite;
|
||||
short nTarget;
|
||||
short field_A;
|
||||
};
|
||||
|
||||
Rex RexList[kMaxRex];
|
||||
|
||||
static actionSeq ActionSeq[] = {
|
||||
{29, 0},
|
||||
{0, 0},
|
||||
{0, 0},
|
||||
{37, 0},
|
||||
{9, 0},
|
||||
{18, 0},
|
||||
{27, 1},
|
||||
{28, 1}
|
||||
};
|
||||
|
||||
|
||||
static SavegameHelper sgh("rex",
|
||||
SV(RexCount),
|
||||
SA(RexChan),
|
||||
SA(RexList),
|
||||
nullptr);
|
||||
|
||||
|
||||
void InitRexs()
|
||||
{
|
||||
RexCount = kMaxRex;
|
||||
}
|
||||
|
||||
int BuildRex(short nSprite, int x, int y, int z, short nSector, short nAngle, int nVal)
|
||||
{
|
||||
RexCount--;
|
||||
|
||||
int nRex = RexCount;
|
||||
if (nRex < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nSprite == -1)
|
||||
{
|
||||
nSprite = insertsprite(nSector, 119);
|
||||
}
|
||||
else
|
||||
{
|
||||
changespritestat(nSprite, 119);
|
||||
x = sprite[nSprite].x;
|
||||
y = sprite[nSprite].y;
|
||||
z = sector[sprite[nSprite].sectnum].floorz;
|
||||
nAngle = sprite[nSprite].ang;
|
||||
}
|
||||
|
||||
assert(nSprite >= 0 && nSprite < kMaxSprites);
|
||||
|
||||
sprite[nSprite].x = x;
|
||||
sprite[nSprite].y = y;
|
||||
sprite[nSprite].z = z;
|
||||
sprite[nSprite].cstat = 0x101;
|
||||
sprite[nSprite].clipdist = 80;
|
||||
sprite[nSprite].shade = -12;
|
||||
sprite[nSprite].xrepeat = 64;
|
||||
sprite[nSprite].yrepeat = 64;
|
||||
sprite[nSprite].picnum = 1;
|
||||
sprite[nSprite].pal = sector[sprite[nSprite].sectnum].ceilingpal;
|
||||
sprite[nSprite].xoffset = 0;
|
||||
sprite[nSprite].yoffset = 0;
|
||||
sprite[nSprite].ang = nAngle;
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].zvel = 0;
|
||||
sprite[nSprite].lotag = runlist_HeadRun() + 1;
|
||||
sprite[nSprite].extra = -1;
|
||||
sprite[nSprite].hitag = 0;
|
||||
|
||||
GrabTimeSlot(3);
|
||||
|
||||
RexList[nRex].nAction = 0;
|
||||
RexList[nRex].nHealth = 4000;
|
||||
RexList[nRex].field_2 = 0;
|
||||
RexList[nRex].nSprite = nSprite;
|
||||
RexList[nRex].nTarget = -1;
|
||||
RexList[nRex].field_A = 0;
|
||||
RexChan[nRex] = nVal;
|
||||
|
||||
sprite[nSprite].owner = runlist_AddRunRec(sprite[nSprite].lotag - 1, nRex | 0x180000);
|
||||
|
||||
// this isn't stored anywhere...
|
||||
runlist_AddRunRec(NewRun, nRex | 0x180000);
|
||||
|
||||
nCreaturesLeft++;
|
||||
|
||||
return nRex | 0x180000;
|
||||
}
|
||||
|
||||
void FuncRex(int a, int nDamage, int nRun)
|
||||
{
|
||||
short nRex = RunData[nRun].nVal;
|
||||
assert(nRex >= 0 && nRex < kMaxRex);
|
||||
|
||||
int var_1C = 0;
|
||||
|
||||
short nAction = RexList[nRex].nAction;
|
||||
short nSprite = RexList[nRex].nSprite;
|
||||
|
||||
int nMessage = a & 0x7F0000;
|
||||
|
||||
switch (nMessage)
|
||||
{
|
||||
default:
|
||||
{
|
||||
Printf("unknown msg %d for Rex\n", a & 0x7F0000);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0xA0000:
|
||||
{
|
||||
if (nAction == 5)
|
||||
{
|
||||
nDamage = runlist_CheckRadialDamage(nSprite);
|
||||
}
|
||||
// fall through to case 0x80000
|
||||
fallthrough__;
|
||||
}
|
||||
|
||||
case 0x80000:
|
||||
{
|
||||
if (nDamage)
|
||||
{
|
||||
short nTarget = a & 0xFFFF;
|
||||
if (nTarget >= 0 && sprite[nTarget].statnum == 100)
|
||||
{
|
||||
RexList[nRex].nTarget = nTarget;
|
||||
}
|
||||
|
||||
if (RexList[nRex].nAction == 5 && RexList[nRex].nHealth > 0)
|
||||
{
|
||||
RexList[nRex].nHealth -= nDamage;
|
||||
|
||||
if (RexList[nRex].nHealth <= 0)
|
||||
{
|
||||
sprite[nSprite].zvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].xvel = 0;
|
||||
RexList[nRex].nHealth = 0;
|
||||
sprite[nSprite].cstat &= 0xFEFE;
|
||||
nCreaturesLeft--;
|
||||
|
||||
if (nAction < 6)
|
||||
{
|
||||
RexList[nRex].nAction = 6;
|
||||
RexList[nRex].field_2 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x90000:
|
||||
{
|
||||
seq_PlotSequence(a & 0xFFFF, SeqOffsets[kSeqRex] + ActionSeq[nAction].a, RexList[nRex].field_2, ActionSeq[nAction].b);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x20000:
|
||||
{
|
||||
Gravity(nSprite);
|
||||
|
||||
int nSeq = SeqOffsets[kSeqRex] + ActionSeq[nAction].a;
|
||||
|
||||
sprite[nSprite].picnum = seq_GetSeqPicnum2(nSeq, RexList[nRex].field_2);
|
||||
|
||||
int ecx;
|
||||
|
||||
if (nAction != 2) {
|
||||
ecx = 1;
|
||||
}
|
||||
else {
|
||||
ecx = 2;
|
||||
}
|
||||
|
||||
// moves the mouth open and closed as it's idle?
|
||||
while (--ecx != -1)
|
||||
{
|
||||
seq_MoveSequence(nSprite, nSeq, RexList[nRex].field_2);
|
||||
|
||||
RexList[nRex].field_2++;
|
||||
if (RexList[nRex].field_2 >= SeqSize[nSeq])
|
||||
{
|
||||
RexList[nRex].field_2 = 0;
|
||||
var_1C = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int nFlag = FrameFlag[SeqBase[nSeq] + RexList[nRex].field_2];
|
||||
|
||||
short nTarget = RexList[nRex].nTarget;
|
||||
|
||||
switch (nAction)
|
||||
{
|
||||
default:
|
||||
return;
|
||||
|
||||
// OK
|
||||
case 0:
|
||||
{
|
||||
if (!RexList[nRex].field_A)
|
||||
{
|
||||
if ((nRex & 0x1F) == (totalmoves & 0x1F))
|
||||
{
|
||||
if (nTarget < 0)
|
||||
{
|
||||
short nAngle = sprite[nSprite].ang; // make backup of this variable
|
||||
RexList[nRex].nTarget = FindPlayer(nSprite, 60);
|
||||
sprite[nSprite].ang = nAngle;
|
||||
}
|
||||
else
|
||||
{
|
||||
RexList[nRex].field_A = 60;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RexList[nRex].field_A--;
|
||||
if (RexList[nRex].field_A <= 0)
|
||||
{
|
||||
RexList[nRex].nAction = 1;
|
||||
RexList[nRex].field_2 = 0;
|
||||
|
||||
sprite[nSprite].xvel = Cos(sprite[nSprite].ang) >> 2;
|
||||
sprite[nSprite].yvel = Sin(sprite[nSprite].ang) >> 2;
|
||||
|
||||
D3PlayFX(StaticSound[kSound48], nSprite);
|
||||
|
||||
RexList[nRex].field_A = 30;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// OK
|
||||
case 1:
|
||||
{
|
||||
if (RexList[nRex].field_A > 0)
|
||||
{
|
||||
RexList[nRex].field_A--;
|
||||
}
|
||||
|
||||
if ((nRex & 0x0F) == (totalmoves & 0x0F))
|
||||
{
|
||||
if (!RandomSize(1))
|
||||
{
|
||||
RexList[nRex].nAction = 5;
|
||||
RexList[nRex].field_2 = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].xvel = 0;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (((PlotCourseToSprite(nSprite, nTarget) >> 8) >= 60) || RexList[nRex].field_A > 0)
|
||||
{
|
||||
sprite[nSprite].xvel = Sin((sprite[nSprite].ang & 0xFFF8) + 512) >> 2;
|
||||
sprite[nSprite].yvel = Sin((sprite[nSprite].ang & 0xFFF8)) >> 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
RexList[nRex].nAction = 2;
|
||||
RexList[nRex].field_A = 240;
|
||||
D3PlayFX(StaticSound[kSound48], nSprite);
|
||||
RexList[nRex].field_2 = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int nVal = MoveCreatureWithCaution(nSprite);
|
||||
|
||||
switch ((nVal & 0xC000))
|
||||
{
|
||||
case 0xc000:
|
||||
if ((nVal & 0x3FFF) == nTarget)
|
||||
{
|
||||
PlotCourseToSprite(nSprite, nTarget);
|
||||
RexList[nRex].nAction = 4;
|
||||
RexList[nRex].field_2 = 0;
|
||||
break;
|
||||
}
|
||||
fallthrough__;
|
||||
case 0x8000:
|
||||
sprite[nSprite].ang = (sprite[nSprite].ang + 256) & kAngleMask;
|
||||
sprite[nSprite].xvel = Cos(sprite[nSprite].ang) >> 2;
|
||||
sprite[nSprite].yvel = Sin(sprite[nSprite].ang) >> 2;
|
||||
RexList[nRex].nAction = 1;
|
||||
RexList[nRex].field_2 = 0;
|
||||
nAction = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
RexList[nRex].field_A--;
|
||||
if (RexList[nRex].field_A > 0)
|
||||
{
|
||||
PlotCourseToSprite(nSprite, nTarget);
|
||||
|
||||
sprite[nSprite].xvel = Cos(sprite[nSprite].ang) >> 1;
|
||||
sprite[nSprite].yvel = Sin(sprite[nSprite].ang) >> 1;
|
||||
|
||||
int nVal = MoveCreatureWithCaution(nSprite);
|
||||
|
||||
switch(nVal & 0x0C000)
|
||||
{
|
||||
case 0x8000:
|
||||
SetQuake(nSprite, 25);
|
||||
RexList[nRex].field_A = 60;
|
||||
|
||||
sprite[nSprite].ang = (sprite[nSprite].ang + 256) & kAngleMask;
|
||||
sprite[nSprite].xvel = Cos(sprite[nSprite].ang) >> 2;
|
||||
sprite[nSprite].yvel = Sin(sprite[nSprite].ang) >> 2;
|
||||
RexList[nRex].nAction = 1;
|
||||
RexList[nRex].field_2 = 0;
|
||||
nAction = 1;
|
||||
break;
|
||||
case 0xc000:
|
||||
RexList[nRex].nAction = 3;
|
||||
RexList[nRex].field_2 = 0;
|
||||
|
||||
short nSprite2 = nVal & 0x3FFF;
|
||||
|
||||
if (sprite[nSprite2].statnum && sprite[nSprite2].statnum < 107)
|
||||
{
|
||||
short nAngle = sprite[nSprite].ang;
|
||||
|
||||
runlist_DamageEnemy(nSprite2, nSprite, 15);
|
||||
|
||||
int ebx = Cos(nAngle) * 15;
|
||||
int edx = Sin(nAngle) * 15;
|
||||
|
||||
if (sprite[nSprite2].statnum == 100)
|
||||
{
|
||||
short nPlayer = GetPlayerFromSprite(nSprite2);
|
||||
nXDamage[nPlayer] += (ebx << 4);
|
||||
nYDamage[nPlayer] += (edx << 4);
|
||||
sprite[nSprite2].zvel = -3584;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite[nSprite2].xvel += (ebx >> 3);
|
||||
sprite[nSprite2].yvel += (edx >> 3);
|
||||
sprite[nSprite2].zvel = -2880;
|
||||
}
|
||||
}
|
||||
|
||||
RexList[nRex].field_A >>= 2;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RexList[nRex].nAction = 1;
|
||||
RexList[nRex].field_2 = 0;
|
||||
RexList[nRex].field_A = 90;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
if (var_1C)
|
||||
{
|
||||
RexList[nRex].nAction = 2;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
if (nTarget != -1)
|
||||
{
|
||||
if (PlotCourseToSprite(nSprite, nTarget) < 768)
|
||||
{
|
||||
if (nFlag & 0x80)
|
||||
{
|
||||
runlist_DamageEnemy(nTarget, nSprite, 15);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RexList[nRex].nAction = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case 5:
|
||||
{
|
||||
if (var_1C)
|
||||
{
|
||||
RexList[nRex].nAction = 1;
|
||||
RexList[nRex].field_A = 15;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case 6:
|
||||
{
|
||||
if (var_1C)
|
||||
{
|
||||
RexList[nRex].nAction = 7;
|
||||
RexList[nRex].field_2 = 0;
|
||||
runlist_ChangeChannel(RexChan[nRex], 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case 7:
|
||||
{
|
||||
sprite[nSprite].cstat &= 0xFEFE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// break-ed
|
||||
if (nAction > 0)
|
||||
{
|
||||
if ((nTarget != -1) && (!(sprite[nTarget].cstat & 0x101)))
|
||||
{
|
||||
RexList[nRex].nAction = 0;
|
||||
RexList[nRex].field_2 = 0;
|
||||
RexList[nRex].field_A = 0;
|
||||
RexList[nRex].nTarget = -1;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].xvel = 0;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
END_PS_NS
|
30
source/exhumed/src/rex.h
Normal file
30
source/exhumed/src/rex.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __rex_h__
|
||||
#define __rex_h__
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
void InitRexs();
|
||||
int BuildRex(short nSprite, int x, int y, int z, short nSector, short nAngle, int nVal);
|
||||
void FuncRex(int, int, int);
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
421
source/exhumed/src/roach.cpp
Normal file
421
source/exhumed/src/roach.cpp
Normal file
|
@ -0,0 +1,421 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
#include "ns.h"
|
||||
#include "exhumed.h"
|
||||
#include "engine.h"
|
||||
#include "runlist.h"
|
||||
#include "roach.h"
|
||||
#include "typedefs.h"
|
||||
#include "sequence.h"
|
||||
#include "move.h"
|
||||
#include "random.h"
|
||||
#include "trigdat.h"
|
||||
#include "bullet.h"
|
||||
#include "items.h"
|
||||
#include <assert.h>
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
#define kMaxRoach 100
|
||||
|
||||
int16_t RoachSprite = -1;
|
||||
int16_t RoachCount = -1;
|
||||
|
||||
static actionSeq ActionSeq[] = {{ 24, 0 }, { 0, 0 }, { 0, 0 }, { 16, 0 }, { 8, 0 }, { 32, 1 }, { 42, 1 }};
|
||||
|
||||
struct Roach
|
||||
{
|
||||
short nHealth;
|
||||
short field_2;
|
||||
short nAction;
|
||||
short nSprite;
|
||||
short nTarget;
|
||||
short field_A;
|
||||
short field_C;
|
||||
short field_E;
|
||||
};
|
||||
|
||||
Roach RoachList[kMaxRoach];
|
||||
|
||||
static SavegameHelper sgh("roach",
|
||||
SV(RoachSprite),
|
||||
SV(RoachCount),
|
||||
SA(RoachList),
|
||||
nullptr);
|
||||
|
||||
|
||||
/* Kilmaat Sentry */
|
||||
|
||||
void InitRoachs()
|
||||
{
|
||||
RoachCount = kMaxRoach;
|
||||
RoachSprite = 1;
|
||||
}
|
||||
|
||||
// TODO - make nType a bool?
|
||||
int BuildRoach(int nType, int nSprite, int x, int y, int z, short nSector, int angle)
|
||||
{
|
||||
RoachCount--;
|
||||
if (RoachCount < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nSprite == -1)
|
||||
{
|
||||
nSprite = insertsprite(nSector, 105);
|
||||
}
|
||||
else
|
||||
{
|
||||
changespritestat(nSprite, 105);
|
||||
x = sprite[nSprite].x;
|
||||
y = sprite[nSprite].y;
|
||||
z = sector[sprite[nSprite].sectnum].floorz;
|
||||
angle = sprite[nSprite].ang;
|
||||
}
|
||||
|
||||
assert(nSprite >= 0 && nSprite < kMaxSprites);
|
||||
|
||||
sprite[nSprite].x = x;
|
||||
sprite[nSprite].y = y;
|
||||
sprite[nSprite].z = z;
|
||||
sprite[nSprite].cstat = 0x101;
|
||||
sprite[nSprite].shade = -12;
|
||||
sprite[nSprite].xoffset = 0;
|
||||
sprite[nSprite].yoffset = 0;
|
||||
sprite[nSprite].picnum = 1;
|
||||
sprite[nSprite].pal = sector[sprite[nSprite].sectnum].ceilingpal;
|
||||
sprite[nSprite].clipdist = 60;
|
||||
sprite[nSprite].ang = angle;
|
||||
sprite[nSprite].xrepeat = 40;
|
||||
sprite[nSprite].yrepeat = 40;
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].zvel = 0;
|
||||
sprite[nSprite].hitag = 0;
|
||||
sprite[nSprite].lotag = runlist_HeadRun() + 1;
|
||||
sprite[nSprite].extra = -1;
|
||||
|
||||
// GrabTimeSlot(3);
|
||||
|
||||
if (nType)
|
||||
{
|
||||
RoachList[RoachCount].nAction = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
RoachList[RoachCount].nAction = 1;
|
||||
}
|
||||
|
||||
RoachList[RoachCount].nSprite = nSprite;
|
||||
RoachList[RoachCount].field_2 = 0;
|
||||
RoachList[RoachCount].field_C = 0;
|
||||
RoachList[RoachCount].nTarget = -1;
|
||||
RoachList[RoachCount].nHealth = 600;
|
||||
|
||||
sprite[nSprite].owner = runlist_AddRunRec(sprite[nSprite].lotag - 1, RoachCount | 0x1C0000);
|
||||
RoachList[RoachCount].field_A = runlist_AddRunRec(NewRun, RoachCount | 0x1C0000);
|
||||
|
||||
nCreaturesLeft++;
|
||||
|
||||
return RoachCount | 0x1C0000;
|
||||
}
|
||||
|
||||
void GoRoach(short nSprite)
|
||||
{
|
||||
sprite[nSprite].xvel = (Sin(sprite[nSprite].ang + 512) >> 1) - (Sin(sprite[nSprite].ang + 512) >> 3);
|
||||
sprite[nSprite].yvel = (Sin(sprite[nSprite].ang) >> 1) - (Sin(sprite[nSprite].ang) >> 3);
|
||||
}
|
||||
|
||||
void FuncRoach(int a, int nDamage, int nRun)
|
||||
{
|
||||
short nRoach = RunData[nRun].nVal;
|
||||
assert(nRoach >= 0 && nRoach < kMaxRoach);
|
||||
|
||||
bool bVar_24 = false;
|
||||
short nSprite = RoachList[nRoach].nSprite;
|
||||
short nAction = RoachList[nRoach].nAction;
|
||||
|
||||
int nMessage = a & 0x7F0000;
|
||||
|
||||
switch (nMessage)
|
||||
{
|
||||
default:
|
||||
{
|
||||
Printf("unknown msg %d for Roach\n", a & 0x7F0000);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x90000:
|
||||
{
|
||||
seq_PlotSequence(a & 0xFFFF, ActionSeq[nAction].a + SeqOffsets[kSeqRoach], RoachList[nRoach].field_2, ActionSeq[nAction].b);
|
||||
return;
|
||||
}
|
||||
|
||||
case 0xA0000: // fall through to next case
|
||||
{
|
||||
nDamage = runlist_CheckRadialDamage(nSprite);
|
||||
fallthrough__;
|
||||
}
|
||||
case 0x80000:
|
||||
{
|
||||
if (nDamage)
|
||||
{
|
||||
if (RoachList[nRoach].nHealth <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
RoachList[nRoach].nHealth -= nDamage;
|
||||
if (RoachList[nRoach].nHealth <= 0)
|
||||
{
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].zvel = 0;
|
||||
RoachList[nRoach].nHealth = 0;
|
||||
sprite[nSprite].cstat &= 0xFEFE;
|
||||
nCreaturesLeft++; // This seems to be incorrect in original exe? should be decrementing?
|
||||
|
||||
if (nAction < 5)
|
||||
{
|
||||
DropMagic(nSprite);
|
||||
RoachList[nRoach].nAction = 5;
|
||||
RoachList[nRoach].field_2 = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
short nSprite2 = a & 0xFFFF;
|
||||
if (nSprite2 >= 0)
|
||||
{
|
||||
if (sprite[nSprite2].statnum < 199) {
|
||||
RoachList[nRoach].nTarget = nSprite2;
|
||||
}
|
||||
|
||||
if (nAction == 0)
|
||||
{
|
||||
RoachList[nRoach].nAction = 2;
|
||||
GoRoach(nSprite);
|
||||
RoachList[nRoach].field_2 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!RandomSize(4))
|
||||
{
|
||||
RoachList[nRoach].nAction = 4;
|
||||
RoachList[nRoach].field_2 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case 0x20000:
|
||||
{
|
||||
Gravity(nSprite);
|
||||
|
||||
int nSeq = SeqOffsets[kSeqRoach] + ActionSeq[RoachList[nRoach].nAction].a;
|
||||
|
||||
sprite[nSprite].picnum = seq_GetSeqPicnum2(nSeq, RoachList[nRoach].field_2);
|
||||
seq_MoveSequence(nSprite, nSeq, RoachList[nRoach].field_2);
|
||||
|
||||
RoachList[nRoach].field_2++;
|
||||
if (RoachList[nRoach].field_2 >= SeqSize[nSeq])
|
||||
{
|
||||
bVar_24 = true;
|
||||
RoachList[nRoach].field_2 = 0;
|
||||
}
|
||||
|
||||
int nFlag = FrameFlag[SeqBase[nSeq] + RoachList[nRoach].field_2];
|
||||
short nTarget = RoachList[nRoach].nTarget;
|
||||
|
||||
if (nAction > 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (nAction)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
if (RoachList[nRoach].field_2 == 1)
|
||||
{
|
||||
RoachList[nRoach].field_C--;
|
||||
if (RoachList[nRoach].field_C <= 0)
|
||||
{
|
||||
RoachList[nRoach].field_C = RandomSize(6);
|
||||
}
|
||||
else
|
||||
{
|
||||
RoachList[nRoach].field_2 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (((nRoach & 0xF) == (totalmoves & 0xF)) && nTarget < 0)
|
||||
{
|
||||
short nTarget = FindPlayer(nSprite, 50);
|
||||
if (nTarget >= 0)
|
||||
{
|
||||
RoachList[nRoach].nAction = 2;
|
||||
RoachList[nRoach].field_2 = 0;
|
||||
RoachList[nRoach].nTarget = nTarget;
|
||||
GoRoach(nSprite);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case 1:
|
||||
{
|
||||
// parltly the same as case 0...
|
||||
if (((nRoach & 0xF) == (totalmoves & 0xF)) && nTarget < 0)
|
||||
{
|
||||
short nTarget = FindPlayer(nSprite, 100);
|
||||
if (nTarget >= 0)
|
||||
{
|
||||
RoachList[nRoach].nAction = 2;
|
||||
RoachList[nRoach].field_2 = 0;
|
||||
RoachList[nRoach].nTarget = nTarget;
|
||||
GoRoach(nSprite);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
if ((totalmoves & 0xF) == (nRoach & 0xF))
|
||||
{
|
||||
PlotCourseToSprite(nSprite, nTarget);
|
||||
GoRoach(nSprite);
|
||||
}
|
||||
|
||||
int nVal = MoveCreatureWithCaution(nSprite);
|
||||
|
||||
if ((nVal & 0xC000) == 49152)
|
||||
{
|
||||
if ((nVal & 0x3FFF) == nTarget)
|
||||
{
|
||||
// repeated below
|
||||
RoachList[nRoach].field_E = RandomSize(2) + 1;
|
||||
RoachList[nRoach].nAction = 3;
|
||||
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].ang = GetMyAngle(sprite[nTarget].x - sprite[nSprite].x, sprite[nTarget].y - sprite[nSprite].y);
|
||||
|
||||
RoachList[nRoach].field_2 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite[nSprite].ang = (sprite[nSprite].ang + 256) & kAngleMask;
|
||||
GoRoach(nSprite);
|
||||
}
|
||||
}
|
||||
else if ((nVal & 0xC000) == 32768)
|
||||
{
|
||||
sprite[nSprite].ang = (sprite[nSprite].ang + 256) & kAngleMask;
|
||||
GoRoach(nSprite);
|
||||
}
|
||||
//else if ((nVal & 0xC000) < 32768)
|
||||
else
|
||||
{
|
||||
if (RoachList[nRoach].field_C != 0)
|
||||
{
|
||||
RoachList[nRoach].field_C--;
|
||||
}
|
||||
else
|
||||
{
|
||||
// same as above
|
||||
RoachList[nRoach].field_E = RandomSize(2) + 1;
|
||||
RoachList[nRoach].nAction = 3;
|
||||
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
sprite[nSprite].ang = GetMyAngle(sprite[nTarget].x - sprite[nSprite].x, sprite[nTarget].y - sprite[nSprite].y);
|
||||
|
||||
RoachList[nRoach].field_2 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (nTarget != -1 && !(sprite[nTarget].cstat & 0x101))
|
||||
{
|
||||
RoachList[nRoach].nAction = 1;
|
||||
RoachList[nRoach].field_2 = 0;
|
||||
RoachList[nRoach].field_C = 100;
|
||||
RoachList[nRoach].nTarget = -1;
|
||||
sprite[nSprite].xvel = 0;
|
||||
sprite[nSprite].yvel = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
if (bVar_24)
|
||||
{
|
||||
RoachList[nRoach].field_E--;
|
||||
if (RoachList[nRoach].field_E <= 0)
|
||||
{
|
||||
RoachList[nRoach].nAction = 2;
|
||||
GoRoach(nSprite);
|
||||
RoachList[nRoach].field_2 = 0;
|
||||
RoachList[nRoach].field_C = RandomSize(7);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nFlag & 0x80)
|
||||
{
|
||||
BuildBullet(nSprite, 13, 0, 0, -1, sprite[nSprite].ang, nTarget + 10000, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
if (bVar_24)
|
||||
{
|
||||
RoachList[nRoach].nAction = 2;
|
||||
RoachList[nRoach].field_2 = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
case 5:
|
||||
{
|
||||
if (bVar_24)
|
||||
{
|
||||
sprite[nSprite].cstat = 0;
|
||||
RoachList[nRoach].nAction = 6;
|
||||
RoachList[nRoach].field_2 = 0;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
END_PS_NS
|
30
source/exhumed/src/roach.h
Normal file
30
source/exhumed/src/roach.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
//-------------------------------------------------------------------------
|
||||
/*
|
||||
Copyright (C) 2010-2019 EDuke32 developers and contributors
|
||||
Copyright (C) 2019 sirlemonhead, Nuke.YKT
|
||||
This file is part of PCExhumed.
|
||||
PCExhumed is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License version 2
|
||||
as published by the Free Software Foundation.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef __roach_h__
|
||||
#define __roach_h__
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
||||
void InitRoachs();
|
||||
int BuildRoach(int nType, int nSprite, int x, int y, int z, short nSector, int angle);
|
||||
void FuncRoach(int a, int nDamage, int nRun);
|
||||
|
||||
END_PS_NS
|
||||
|
||||
#endif
|
1865
source/exhumed/src/runlist.cpp
Normal file
1865
source/exhumed/src/runlist.cpp
Normal file
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue