diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 66f4d6b38..5f98674b7 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -719,7 +719,11 @@ set( NOT_COMPILED_SOURCE_FILES zcc-parse.c zcc-parse.h common/platform/win32/zutil.natvis - + + games/blood/src/_polymost.cpp + games/duke/src/_polymost.cpp + games/sw/src/_polymost.cpp + # Blood games/blood/src/actor.cpp games/blood/src/ai.cpp diff --git a/source/build/include/build.h b/source/build/include/build.h index 2e747bfdc..6f09a4d15 100644 --- a/source/build/include/build.h +++ b/source/build/include/build.h @@ -15,11 +15,8 @@ static_assert('\xff' == 255, "Char must be unsigned!"); -#if !defined __cplusplus || (__cplusplus < 201103L && !defined _MSC_VER) -# error C++11 or greater is required. -#endif - #include "compat.h" +#include "printf.h" #include "palette.h" #include "binaryangle.h" @@ -218,6 +215,7 @@ typedef struct { // The texel index offset in the y direction of a parallaxed sky: // XXX: currently always 0. int yoffs; + int yoffs2; int lognumtiles; // 1<> 3] |= 1 << (tilenume & 7); } +inline void cleargotpic(int32_t tilenume) +{ + gotpic[tilenume >> 3] &= ~(1 << (tilenume & 7)); +} + +inline bool testgotpic(int32_t tilenume, bool reset = false) +{ + bool res = gotpic[tilenume >> 3] & (1 << (tilenume & 7)); + if (reset) gotpic[tilenume >> 3] &= ~(1 << (tilenume & 7)); + return res; +} #include "iterators.h" diff --git a/source/build/include/compat.h b/source/build/include/compat.h index 5b1097088..930315c4f 100644 --- a/source/build/include/compat.h +++ b/source/build/include/compat.h @@ -14,19 +14,6 @@ ////////// Language and compiler feature polyfills ////////// -# define EXTERNC - -#ifndef UNREFERENCED_PARAMETER -# define UNREFERENCED_PARAMETER(x) (x) = (x) -#endif - -#if defined __GNUC__ || defined __clang__ -# define ATTRIBUTE(attrlist) __attribute__(attrlist) -#else -# define ATTRIBUTE(attrlist) -#endif - - # define fallthrough__ [[fallthrough]] ////////// Architecture detection ////////// diff --git a/source/build/include/mmulti.h b/source/build/include/mmulti.h deleted file mode 100644 index 1c5d2c5ea..000000000 --- a/source/build/include/mmulti.h +++ /dev/null @@ -1,19 +0,0 @@ -// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman -// Ken Silverman's official web site: "http://www.advsys.net/ken" -// See the included license file "BUILDLIC.TXT" for license info. -// -// This file has been modified from Ken Silverman's original release -// by Jonathon Fowler (jf@jonof.id.au) -// by the EDuke32 team (development@voidpoint.com) - -#ifndef mmulti_h_ -#define mmulti_h_ - -#define MAXMULTIPLAYERS 16 - -extern int myconnectindex, numplayers; -extern int connecthead, connectpoint2[MAXMULTIPLAYERS]; - - -#endif // mmulti_h_ - diff --git a/source/build/src/engine.cpp b/source/build/src/engine.cpp index f3f4ac344..75da21c2d 100644 --- a/source/build/src/engine.cpp +++ b/source/build/src/engine.cpp @@ -595,19 +595,20 @@ psky_t * tileSetupSky(int32_t const tilenum) return &multipskies.Last(); } -psky_t * defineSky(int32_t const tilenum, int horiz, int lognumtiles, const uint16_t *tileofs, int yoff) +psky_t * defineSky(int32_t const tilenum, int horiz, int lognumtiles, const uint16_t *tileofs, int yoff, int yoff2) { auto sky = tileSetupSky(tilenum); sky->horizfrac = horiz; sky->lognumtiles = lognumtiles; sky->yoffs = yoff; + sky->yoffs2 = yoff2 == 0x7fffffff ? yoff : yoff2; memcpy(sky->tileofs, tileofs, 2 << lognumtiles); return sky; } // Get properties of parallaxed sky to draw. // Returns: pointer to tile offset array. Sets-by-pointer the other three. -const int16_t* getpsky(int32_t picnum, int32_t* dapyscale, int32_t* dapskybits, int32_t* dapyoffs, int32_t* daptileyscale) +const int16_t* getpsky(int32_t picnum, int32_t* dapyscale, int32_t* dapskybits, int32_t* dapyoffs, int32_t* daptileyscale, bool alt) { psky_t const* const psky = getpskyidx(picnum); @@ -616,7 +617,7 @@ const int16_t* getpsky(int32_t picnum, int32_t* dapyscale, int32_t* dapskybits, if (dapyscale) *dapyscale = (parallaxyscale_override == 0 ? psky->horizfrac : parallaxyscale_override); if (dapyoffs) - *dapyoffs = psky->yoffs + parallaxyoffs_override; + *dapyoffs = (alt? psky->yoffs2 : psky->yoffs) + parallaxyoffs_override; if (daptileyscale) *daptileyscale = psky->yscale; diff --git a/source/build/src/mdsprite.cpp b/source/build/src/mdsprite.cpp index 422e40605..bac6b65cf 100644 --- a/source/build/src/mdsprite.cpp +++ b/source/build/src/mdsprite.cpp @@ -26,11 +26,10 @@ static int32_t curextra=MAXTILES; using namespace Polymost; int32_t polymost_voxdraw(voxmodel_t* m, tspriteptr_t const tspr, bool rotate); -static int32_t addtileP(int32_t model,int32_t tile,int32_t pallet) +static int32_t addtileP(int32_t ,int32_t tile,int32_t pallet) { // tile >= 0 && tile < MAXTILES - UNREFERENCED_PARAMETER(model); if (curextra==MAXTILES+EXTRATILES-1) { Printf("warning: max EXTRATILES reached\n"); @@ -1108,7 +1107,7 @@ void md3_vox_calcmat_common(tspriteptr_t tspr, const vec3f_t *a0, float f, float } static void md3draw_handle_triangles(const md3surf_t *s, uint16_t *indexhandle, - int32_t texunits, const md3model_t *M) + int32_t , const md3model_t *M) { int32_t i; @@ -1130,10 +1129,6 @@ static void md3draw_handle_triangles(const md3surf_t *s, uint16_t *indexhandle, } } GLInterface.Draw(DT_Triangles, data.second, s->numtris *3); - -#ifndef USE_GLEXT - UNREFERENCED_PARAMETER(texunits); -#endif } static int32_t polymost_md3draw(md3model_t *m, tspriteptr_t tspr) diff --git a/source/build/src/polymost.cpp b/source/build/src/polymost.cpp index 4e52720b6..a8a7572bc 100644 --- a/source/build/src/polymost.cpp +++ b/source/build/src/polymost.cpp @@ -57,7 +57,7 @@ int pm_smoothratio; // For testing - will be removed later. CVAR(Int, skytile, 0, 0) -CVAR(Bool, testnewrenderer, true, 0) +CVAR(Bool, testnewrenderer, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) extern fixed_t global100horiz; // (-100..300)-scale horiz (the one passed to drawrooms) static vec3_t spritesxyz[MAXSPRITESONSCREEN + 1]; diff --git a/source/common/rendering/vulkan/renderer/vk_renderbuffers.cpp b/source/common/rendering/vulkan/renderer/vk_renderbuffers.cpp index 34e44096d..75288a4f2 100644 --- a/source/common/rendering/vulkan/renderer/vk_renderbuffers.cpp +++ b/source/common/rendering/vulkan/renderer/vk_renderbuffers.cpp @@ -239,8 +239,13 @@ void VkRenderBuffers::CreateShadowmap() ImageBuilder builder; builder.setSize(gl_shadowmap_quality, 1024); - builder.setFormat(VK_FORMAT_R32_SFLOAT); + builder.setFormat(SceneNormalFormat); builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); + if (!builder.isFormatSupported(fb->device, VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) + { + SceneNormalFormat = VK_FORMAT_R8G8B8A8_UNORM; + builder.setFormat(SceneNormalFormat); + } Shadowmap.Image = builder.create(fb->device); Shadowmap.Image->SetDebugName("VkRenderBuffers.Shadowmap"); diff --git a/source/core/cheats.cpp b/source/core/cheats.cpp index d422e5c20..9b670931c 100644 --- a/source/core/cheats.cpp +++ b/source/core/cheats.cpp @@ -41,7 +41,6 @@ #include "c_dispatch.h" #include "d_net.h" #include "gamestate.h" -#include "mmulti.h" #include "gstrings.h" #include "gamecontrol.h" #include "screenjob.h" diff --git a/source/core/d_net.cpp b/source/core/d_net.cpp index 5650ea43f..30c7891d1 100644 --- a/source/core/d_net.cpp +++ b/source/core/d_net.cpp @@ -63,7 +63,6 @@ #include "vm.h" #include "gstrings.h" #include "s_music.h" -#include "mmulti.h" #include "printf.h" #include "i_time.h" #include "d_ticcmd.h" diff --git a/source/core/d_net.h b/source/core/d_net.h index 1562c1dbf..db4b11f53 100644 --- a/source/core/d_net.h +++ b/source/core/d_net.h @@ -10,6 +10,9 @@ enum MAXPLAYERS = 8 }; +extern int myconnectindex, numplayers; +extern int connecthead, connectpoint2[MAXPLAYERS]; + class FDynamicBuffer { public: diff --git a/source/core/defparser.cpp b/source/core/defparser.cpp index d237eab71..65c00ab68 100644 --- a/source/core/defparser.cpp +++ b/source/core/defparser.cpp @@ -887,6 +887,7 @@ void parseMultiPsky(FScanner& sc, FScriptPosition& pos) if (sky.tilenum != DEFAULTPSKY && (unsigned)sky.tilenum >= MAXUSERTILES) return; if ((1 << sky.lognumtiles) > MAXPSKYTILES) return; + sky.yoffs2 = sky.yoffs; auto psky = tileSetupSky(sky.tilenum); *psky = sky; } diff --git a/source/core/g_mapinfo.cpp b/source/core/g_mapinfo.cpp index ff24af727..60afb7d1b 100644 --- a/source/core/g_mapinfo.cpp +++ b/source/core/g_mapinfo.cpp @@ -651,6 +651,94 @@ MapFlagHandlers[] = { NULL, MITYPE_IGNORE, 0, 0} }; +void PrintCutscene(const char* name, CutsceneDef& cut) +{ + if (cut.function.IsEmpty() && cut.video.IsEmpty()) return; + Printf("\t%s\n\t{\n", name); + if (cut.function.IsNotEmpty()) + { + Printf("\t\tfunction = %s\n", cut.function.GetChars()); + } + if (cut.video.IsNotEmpty()) + { + Printf("\t\tvideo = \"%s\"\n", cut.video.GetChars()); + } + if (cut.soundName.IsNotEmpty()) + { + Printf("\t\tsound = \"%s\"\n", cut.soundName.GetChars()); + } + Printf("\t}\n"); +} + +CCMD(mapinfo) +{ + for (auto& vol : volumes) + { + Printf("episode %s\n{\n", vol.startmap.GetChars()); + if (vol.name.IsNotEmpty()) Printf("\tname = \"%s\"\n", vol.name.GetChars()); + if (vol.subtitle.IsNotEmpty()) Printf("\tsubtitle = \"%s\"\n{\n", vol.subtitle.GetChars()); + Printf("}\n"); + } + for (auto& clust : clusters) + { + Printf("cluster %d\n{\n", clust.index); + if (clust.name.IsNotEmpty()) Printf("\tname = \"%s\"\n", clust.name.GetChars()); + if (clust.InterBackground.IsNotEmpty()) Printf("\tInterBackground = %s\n", clust.InterBackground.GetChars()); + PrintCutscene("intro", clust.intro); + PrintCutscene("outro", clust.outro); + PrintCutscene("gameover", clust.gameover); + Printf("}\n"); + } + for (auto& map : mapList) + { + int lump = fileSystem.FindFile(map->fileName); + if (lump >= 0) + { + int rfnum = fileSystem.GetFileContainer(lump); + Printf("map %s \"%s\"\n{\n", map->labelName.GetChars(), map->DisplayName()); + Printf("\tlevelnum = %d\n\tCluster = %d\n", map->levelNumber, map->cluster); + if (map->Author.IsNotEmpty()) + { + FString auth = map->Author; + auth.Substitute("\"", "\\\""); + Printf("\tAuthor = \"%s\"\n", auth.GetChars()); + } + if (map->NextMap.IsNotEmpty()) Printf("\tNext = %s\n", map->NextMap.GetChars()); + if (map->NextSecret.IsNotEmpty()) Printf("\tSecretNext = %s\n", map->NextSecret.GetChars()); + if (map->InterBackground.IsNotEmpty()) Printf("\tInterBackground = %s\n", map->InterBackground.GetChars()); + if (map->music.IsNotEmpty()) Printf("\tMusic = \"%s\"\n", map->music.GetChars()); + if (map->musicorder > 0) Printf("\tMusicorder = %d\n", map->musicorder); + if (map->cdSongId > 0) Printf("\tCDtrack = %d\n", map->cdSongId); + if (map->parTime) Printf("\tParTime = %d\n", map->parTime); + if (map->designerTime) Printf("\tDesignerTime = %d\n", map->designerTime); + for (int i = 0; i < MAX_MESSAGES; i++) + { + if (map->messages[i].IsNotEmpty()) Printf("\tMessage = %d, \"%s\"\n", i + 1, map->messages[i].GetChars()); + } + + for (auto& flagh : MapFlagHandlers) + { + if (flagh.type == MITYPE_SETFLAG) + { + if (map->flags & flagh.data1) Printf("\t%s\n", flagh.name); + } + if (flagh.type == MITYPE_SETFLAGG) + { + if (map->gameflags & flagh.data1) Printf("\t%s\n", flagh.name); + } + } + PrintCutscene("intro", map->intro); + PrintCutscene("outro", map->outro); + Printf("}\n"); + } + else + { + //Printf("%s - %s (defined but does not exist)\n", map->fileName.GetChars(), map->DisplayName()); + } + } +} + + //========================================================================== // // ParseMapDefinition @@ -786,7 +874,7 @@ static int GetDefaultLevelNum(const char *mapname) (mapname[2] == 'M' || mapname[2] == 'L') && mapname[3] >= '0' && mapname[3] <= '9') { - int epinum = mapname[1] - '1'; + int epinum = mapname[1] - '0'; int mapnum = mapname[3] - '0'; return makelevelnum(epinum, mapnum); } @@ -837,7 +925,7 @@ MapRecord *FMapInfoParser::ParseMapHeader(MapRecord &defaultinfo) if (map != &sink && map->name.IsEmpty()) sc.ScriptError("Missing level name"); sc.UnGet(); } - map->levelNumber = GetDefaultLevelNum(map->labelName); + if (!map->levelNumber) map->levelNumber = GetDefaultLevelNum(map->labelName); return map; } @@ -1218,6 +1306,7 @@ void G_ParseMapInfo () } // Parse any extra RMAPINFOs. + lastlump = 0; while ((lump = fileSystem.FindLump ("RMAPINFO", &lastlump, false)) != -1) { FMapInfoParser parse; diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index 611bf88bf..2a99b4cdc 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -57,7 +57,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "c_dispatch.h" #include "glbackend/glbackend.h" #include "engineerrors.h" -#include "mmulti.h" #include "gamestate.h" #include "gstrings.h" #include "texturemanager.h" @@ -106,7 +105,7 @@ CUSTOM_CVAR(Int, mouse_capturemode, 1, CVAR_GLOBALCONFIG | CVAR_ARCHIVE) // The last remains of sdlayer.cpp GameInterface* gi; int myconnectindex, numplayers; -int connecthead, connectpoint2[MAXMULTIPLAYERS]; +int connecthead, connectpoint2[MAXPLAYERS]; auto vsnprintfptr = vsnprintf; // This is an inline in Visual Studio but we need an address for it to satisfy the MinGW compiled libraries. int lastTic; @@ -565,12 +564,12 @@ int GameMain() { r = RunGame(); } - catch (const CExitEvent & exit) + catch (const CExitEvent& exit) { // Just let the rest of the function execute. r = exit.Reason(); } - catch (const std::exception & err) + catch (const std::exception& err) { // shut down critical systems before showing a message box. I_ShowFatalError(err.what()); @@ -617,22 +616,6 @@ int GameMain() void SetDefaultStrings() { - // Duke 1.3 does not define its episodes through CON. - if ((g_gameType & GAMEFLAG_DUKE) && fileSystem.FindFile("E4L1.MAP") < 0) - { - auto vol0 = AllocateVolume(); vol0->index = 0; - auto vol1 = AllocateVolume(); vol1->index = 1; vol1->flags = VF_SHAREWARELOCK; - auto vol2 = AllocateVolume(); vol2->index = 2; vol1->flags = VF_SHAREWARELOCK; - // Pre-Atomic releases do not define this. - vol0->name = "$L.A. Meltdown"; - vol1->name = "$Lunar Apocalypse"; - vol2->name = "$Shrapnel City"; - - gSkillNames[0] = "$Piece of Cake"; - gSkillNames[1] = "$Let's Rock"; - gSkillNames[2] = "$Come get Some"; - gSkillNames[3] = "$Damn I'm Good"; - } // Blood hard codes its skill names, so we have to define them manually. if (isBlood()) { @@ -854,6 +837,56 @@ void CreateStatusBar() StatusBar = static_cast(stbarclass->CreateNew()); } + +void GetGames() +{ + auto getgames = Args->CheckValue("-getgames"); + if (getgames) + { + try + { + auto groups = GrpScan(); + FSerializer arc; + if (arc.OpenWriter()) + { + if (arc.BeginArray("games")) + { + for (auto& entry : groups) + { + if (arc.BeginObject(nullptr)) + { + arc("filename", entry.FileName) + ("description", entry.FileInfo.name) + ("defname", entry.FileInfo.defname) + ("scriptname", entry.FileInfo.scriptname) + ("gamefilter", entry.FileInfo.gamefilter) + ("gameid", entry.FileInfo.gameid) + ("fgcolor", entry.FileInfo.FgColor) + ("bkcolor", entry.FileInfo.BgColor) + ("addon", entry.FileInfo.isAddon) + .EndObject(); + } + } + arc.EndArray(); + } + unsigned int len; + auto p = arc.GetOutput(&len); + FILE* f = fopen(getgames, "wb"); + if (f) + { + fwrite(p, 1, len, f); + fclose(f); + } + } + } + catch (...) + { + // Ignore all errors + } + throw CExitEvent(0); + } +} + //========================================================================== // // @@ -880,6 +913,7 @@ int RunGame() I_DetectOS(); userConfig.ProcessOptions(); G_LoadConfig(); + GetGames(); auto usedgroups = SetupGame(); bool colorset = false; diff --git a/source/core/gamestruct.h b/source/core/gamestruct.h index e98e975c4..97b0a857b 100644 --- a/source/core/gamestruct.h +++ b/source/core/gamestruct.h @@ -84,7 +84,6 @@ struct GameInterface virtual double SmallFontScale() { return 1; } virtual void SerializeGameState(FSerializer& arc) {} virtual void DrawPlayerSprite(const DVector2& origin, bool onteam) {} - virtual void QuitToTitle() {} virtual void SetAmbience(bool on) {} virtual FString GetCoordString() { return "'stat coord' not implemented"; } virtual void ExitFromMenu() { throw CExitEvent(0); } diff --git a/source/core/mainloop.cpp b/source/core/mainloop.cpp index 9b52149c4..03a20a7c9 100644 --- a/source/core/mainloop.cpp +++ b/source/core/mainloop.cpp @@ -74,7 +74,6 @@ #include "vm.h" #include "gamestate.h" #include "screenjob.h" -#include "mmulti.h" #include "c_console.h" #include "uiinput.h" #include "v_video.h" diff --git a/source/core/mapinfo.cpp b/source/core/mapinfo.cpp index 4b52d6677..3231c990a 100644 --- a/source/core/mapinfo.cpp +++ b/source/core/mapinfo.cpp @@ -68,59 +68,6 @@ CCMD(listmaps) } } -CCMD(mapinfo) -{ - const char* mapname = nullptr; - if (argv.argc() > 1) mapname = argv[1]; - - if (!mapname) - { - for (auto& vol : volumes) - { - Printf("Volume %d\n\tName = '%s'\n\tstartmap = '%s'\n}\n", vol.index, vol.name.GetChars(), vol.startmap.GetChars()); - } - for (auto& clus : clusters) - { - if (clus.intro.isdefined() || clus.outro.isdefined()) - { - Printf("Cluster %d\n\tName = '%s'\n", clus.index, clus.name.GetChars()); - if (clus.intro.function.IsNotEmpty()) Printf("\tIntro function = %s\n", clus.intro.function.GetChars()); - if (clus.intro.video.IsNotEmpty()) Printf("\tIntro video = %s\n", clus.intro.video.GetChars()); - if (clus.outro.function.IsNotEmpty()) Printf("\tOutro function = %s\n", clus.outro.function.GetChars()); - if (clus.outro.video.IsNotEmpty()) Printf("\tOutro video = %s\n", clus.outro.video.GetChars()); - Printf("}\n"); - } - } - } - for (auto& map : mapList) - { - if (mapname && map->labelName.CompareNoCase(mapname)) continue; - int lump = fileSystem.FindFile(map->fileName); - if (lump >= 0) - { - int rfnum = fileSystem.GetFileContainer(lump); - Printf("%s - %s (%s)\n{\n", map->fileName.GetChars(), map->DisplayName(), fileSystem.GetResourceFileName(rfnum)); - Printf("\tlevel number = %d\n\tCluster = %d\n\tIndex = %d\n", map->levelNumber, map->cluster, map->mapindex); - if (map->Author.IsNotEmpty()) Printf("\tAuthor = '%s'\n", map->Author.GetChars()); - if (map->NextMap.IsNotEmpty()) Printf("\tNext map = '%s'\n", map->NextMap.GetChars()); - if (map->NextSecret.IsNotEmpty()) Printf("\tNext secret map = '%s'\n", map->NextSecret.GetChars()); - if (map->music.IsNotEmpty()) Printf("\tMusic = '%s:%d'", map->music.GetChars(), map->musicorder); - if (map->cdSongId > 0) Printf("\tCD track = %d\n", map->cdSongId); - if (map->parTime) Printf("\tPar Time = %d\n", map->parTime); - if (map->designerTime) Printf("\tPar Time = %d\n", map->designerTime); - if (map->intro.function.IsNotEmpty()) Printf("\tIntro function = %s\n", map->intro.function.GetChars()); - if (map->intro.video.IsNotEmpty()) Printf("\tIntro video = %s\n", map->intro.video.GetChars()); - if (map->outro.function.IsNotEmpty()) Printf("\tOutro function = %s\n", map->outro.function.GetChars()); - if (map->outro.video.IsNotEmpty()) Printf("\tOutro video = %s\n", map->outro.video.GetChars()); - Printf("}\n"); - } - else - { - Printf("%s - %s (defined but does not exist)\n", map->fileName.GetChars(), map->DisplayName()); - } - } -} - int CutsceneDef::GetSound() { int id; @@ -185,9 +132,10 @@ VolumeRecord* AllocateVolume() MapRecord* FindMapByIndexOnly(int cluster, int num) { + int levelnum = makelevelnum(cluster, num); for (auto& map : mapList) { - if (map->mapindex == num && map->cluster == cluster) return map.Data(); + if (map->levelNumber == levelnum) return map.Data(); } return nullptr; } @@ -195,7 +143,7 @@ MapRecord* FindMapByIndexOnly(int cluster, int num) MapRecord* FindMapByIndex(int cluster, int num) { auto map = FindMapByLevelNum(num); - if (!map) map = FindMapByIndexOnly(cluster, num); // modern definitions take precedence. + if (!map && num < 1000) map = FindMapByLevelNum(makelevelnum(cluster, num)); return map; } diff --git a/source/core/mapinfo.h b/source/core/mapinfo.h index 9b94cd47f..56addf366 100644 --- a/source/core/mapinfo.h +++ b/source/core/mapinfo.h @@ -115,7 +115,6 @@ struct ClusterDef FString InterBackground; int index = -1; int flags = 0; // engine and common flags - int gameflags = 0; // game specific flags. }; struct VolumeRecord // episodes @@ -147,7 +146,6 @@ struct MapRecord int flags = 0; int gameflags = 0; int levelNumber = -1; - int mapindex = -1; // index in the episode. This only for finding the next map in the progression when nothing explicit is defined. int cluster = -1; PalEntry fadeto = 0; diff --git a/source/core/menu/razemenu.cpp b/source/core/menu/razemenu.cpp index 66a8ec62d..7eeac3809 100644 --- a/source/core/menu/razemenu.cpp +++ b/source/core/menu/razemenu.cpp @@ -64,6 +64,7 @@ #include "i_net.h" #include "savegamehelp.h" #include "gi.h" +#include "raze_music.h" EXTERN_CVAR(Int, cl_gfxlocalization) EXTERN_CVAR(Bool, m_quickexit) @@ -272,7 +273,8 @@ CCMD(menu_endgame) { STAT_Cancel(); M_ClearMenus(); - gi->QuitToTitle(); + Mus_Stop(); + gameaction = ga_mainmenu; }); M_ActivateMenu(newmenu); diff --git a/source/core/rendering/scene/hw_bunchdrawer.cpp b/source/core/rendering/scene/hw_bunchdrawer.cpp index 50ef2995a..b81b9c0ef 100644 --- a/source/core/rendering/scene/hw_bunchdrawer.cpp +++ b/source/core/rendering/scene/hw_bunchdrawer.cpp @@ -275,10 +275,13 @@ int BunchDrawer::ClipLine(int aline, bool portal) void BunchDrawer::ProcessBunch(int bnch) { FBunch* bunch = &Bunches[bnch]; + int start = bunch->startline; + int end = bunch->endline; ClipWall.Clock(); - for (int i = bunch->startline; i <= bunch->endline; i++) + for (int i = start; i <= end; i++) { + bunch = &Bunches[bnch]; // re-get the pointer in case of reallocation. int clipped = ClipLine(i, bunch->portal); if (clipped & CL_Draw) diff --git a/source/core/rendering/scene/hw_drawlist.cpp b/source/core/rendering/scene/hw_drawlist.cpp index 64f67a725..5ec6df07f 100644 --- a/source/core/rendering/scene/hw_drawlist.cpp +++ b/source/core/rendering/scene/hw_drawlist.cpp @@ -251,8 +251,8 @@ void HWDrawList::SortPlaneIntoPlane(SortNode * head,SortNode * sort) if (fh->z == fs->z) { // Make sure we have consistent ordering with two floor sprites of the same distance if they overlap - int time1 = fh->sprite ? fh->sprite->time : -1; - int time2 = fs->sprite ? fs->sprite->time : -1; + int time1 = fh->Sprite ? fh->Sprite->time : -1; + int time2 = fs->Sprite ? fs->Sprite->time : -1; if (time1 == time2) head->AddToEqual(sort); else if (time2 < time1)head->AddToLeft(sort); else head->AddToRight(sort); @@ -404,8 +404,8 @@ void HWDrawList::SortWallIntoWall(HWDrawInfo *di, SortNode * head,SortNode * sor if (fabs(v1)sprite ? wh->sprite->time : -1; - int time2 = ws->sprite ? ws->sprite->time : -1; + int time1 = wh->Sprite ? wh->Sprite->time : -1; + int time2 = ws->Sprite ? ws->Sprite->time : -1; if ((ws->type==RENDERWALL_FOGBOUNDARY && wh->type!=RENDERWALL_FOGBOUNDARY) || time2 < time1) { @@ -591,7 +591,7 @@ inline int HWDrawList::CompareSprites(SortNode * a,SortNode * b) if (s1->depth < s2->depth) return 1; if (s1->depth > s2->depth) return -1; - return s1->sprite->time - s2->sprite->time; + return s1->Sprite->time - s2->Sprite->time; } //========================================================================== @@ -737,8 +737,8 @@ void HWDrawList::SortWallsVert(HWDrawInfo* di) HWWall* w1 = walls[a.index]; HWWall* w2 = walls[b.index]; if (w1->glseg.y1 != w2->glseg.y1) return w1->glseg.y1 < w2->glseg.y1; - int time1 = w1->sprite ? w1->sprite->time : -1; - int time2 = w2->sprite ? w2->sprite->time : -1; + int time1 = w1->Sprite ? w1->Sprite->time : -1; + int time2 = w2->Sprite ? w2->Sprite->time : -1; return time1 < time2; }); @@ -747,8 +747,8 @@ void HWDrawList::SortWallsVert(HWDrawInfo* di) HWWall* w1 = walls[a.index]; HWWall* w2 = walls[b.index]; if (w1->glseg.y1 != w2->glseg.y1) return w1->glseg.y1 > w2->glseg.y1; - int time1 = w1->sprite ? w1->sprite->time : -1; - int time2 = w2->sprite ? w2->sprite->time : -1; + int time1 = w1->Sprite ? w1->Sprite->time : -1; + int time2 = w2->Sprite ? w2->Sprite->time : -1; return time1 < time2; }); @@ -784,8 +784,8 @@ void HWDrawList::SortWallsHorz(HWDrawInfo* di) HWWall* w1 = walls[a.index]; HWWall* w2 = walls[b.index]; if (w1->glseg.x1 != w2->glseg.x1) return w1->glseg.x1 < w2->glseg.x1; - int time1 = w1->sprite ? w1->sprite->time : -1; - int time2 = w2->sprite ? w2->sprite->time : -1; + int time1 = w1->Sprite ? w1->Sprite->time : -1; + int time2 = w2->Sprite ? w2->Sprite->time : -1; return time1 < time2; }); @@ -794,8 +794,8 @@ void HWDrawList::SortWallsHorz(HWDrawInfo* di) HWWall* w1 = walls[a.index]; HWWall* w2 = walls[b.index]; if (w1->glseg.x1 != w2->glseg.x1) return w1->glseg.x1 > w2->glseg.x1; - int time1 = w1->sprite ? w1->sprite->time : -1; - int time2 = w2->sprite ? w2->sprite->time : -1; + int time1 = w1->Sprite ? w1->Sprite->time : -1; + int time2 = w2->Sprite ? w2->Sprite->time : -1; return time1 < time2; }); @@ -831,8 +831,8 @@ void HWDrawList::SortFlats(HWDrawInfo* di) HWFlat* w1 = flats[a.index]; HWFlat* w2 = flats[b.index]; if (w1->z != w2->z) return w1->z < w2->z; - int time1 = w1->sprite ? w1->sprite->time : -1; - int time2 = w2->sprite ? w2->sprite->time : -1; + int time1 = w1->Sprite ? w1->Sprite->time : -1; + int time2 = w2->Sprite ? w2->Sprite->time : -1; return time1 < time2; }); @@ -841,8 +841,8 @@ void HWDrawList::SortFlats(HWDrawInfo* di) HWFlat* w1 = flats[a.index]; HWFlat* w2 = flats[b.index]; if (w1->z != w2->z) return w2->z < w1->z; - int time1 = w1->sprite ? w1->sprite->time : -1; - int time2 = w2->sprite ? w2->sprite->time : -1; + int time1 = w1->Sprite ? w1->Sprite->time : -1; + int time2 = w2->Sprite ? w2->Sprite->time : -1; return time1 < time2; }); diff --git a/source/core/rendering/scene/hw_drawlistadd.cpp b/source/core/rendering/scene/hw_drawlistadd.cpp index 69fb35222..59a6a6f47 100644 --- a/source/core/rendering/scene/hw_drawlistadd.cpp +++ b/source/core/rendering/scene/hw_drawlistadd.cpp @@ -50,7 +50,7 @@ void HWDrawInfo::AddWall(HWWall *wall) int list; if (wall->type != RENDERWALL_M2S) list = GLDL_PLAINWALLS; - else if (wall->sprite == nullptr) list = GLDL_MASKEDWALLS; + else if (wall->Sprite == nullptr) list = GLDL_MASKEDWALLS; else if (wall->glseg.x1 == wall->glseg.x2) list = GLDL_MASKEDWALLSV; else if (wall->glseg.y1 == wall->glseg.y2) list = GLDL_MASKEDWALLSH; else list = GLDL_MASKEDWALLSS; @@ -98,11 +98,11 @@ void HWDrawInfo::AddFlat(HWFlat *flat) if (flat->RenderStyle != LegacyRenderStyles[STYLE_Translucent] || flat->alpha < 1.f - FLT_EPSILON || checkTranslucentReplacement(flat->texture->GetID(), flat->palette)) { // translucent portals go into the translucent border list. - list = flat->sprite? GLDL_TRANSLUCENT : GLDL_TRANSLUCENTBORDER; + list = flat->Sprite? GLDL_TRANSLUCENT : GLDL_TRANSLUCENTBORDER; } else { - list = flat->sprite ? GLDL_MASKEDFLATS : GLDL_PLAINFLATS; + list = flat->Sprite ? GLDL_MASKEDFLATS : GLDL_PLAINFLATS; } auto newflat = drawlists[list].NewFlat(); *newflat = *flat; diff --git a/source/core/rendering/scene/hw_drawstructs.h b/source/core/rendering/scene/hw_drawstructs.h index 244bb39e1..f5658b8f3 100644 --- a/source/core/rendering/scene/hw_drawstructs.h +++ b/source/core/rendering/scene/hw_drawstructs.h @@ -185,7 +185,7 @@ public: public: walltype* seg; - spritetype* sprite; + spritetype* Sprite; sectortype* frontsector, * backsector; //private: @@ -251,7 +251,7 @@ class HWFlat public: int section; sectortype * sec; - spritetype* sprite; // for flat sprites. + spritetype* Sprite; // for flat sprites. FGameTexture *texture; float z; // the z position of the flat (only valid for non-sloped planes) @@ -294,7 +294,7 @@ class HWSprite { public: - spritetype* sprite; + spritetype* Sprite; PalEntry fade; int shade, palette; float visibility; diff --git a/source/core/rendering/scene/hw_flats.cpp b/source/core/rendering/scene/hw_flats.cpp index 3b1257d5e..cd8cdeeb7 100644 --- a/source/core/rendering/scene/hw_flats.cpp +++ b/source/core/rendering/scene/hw_flats.cpp @@ -96,7 +96,7 @@ void HWFlat::MakeVertices() { if (vertcount > 0) return; bool canvas = texture->isHardwareCanvas(); - if (sprite == nullptr) + if (Sprite == nullptr) { auto mesh = sectorGeometry.get(section, plane, geoofs); if (!mesh) return; @@ -117,12 +117,12 @@ void HWFlat::MakeVertices() else { vec2_t pos[4]; - GetFlatSpritePosition(sprite, sprite->pos.vec2, pos, true); + GetFlatSpritePosition(Sprite, Sprite->pos.vec2, pos, true); auto ret = screen->mVertexData->AllocVertices(6); auto vp = ret.first; - float x = !(sprite->cstat & CSTAT_SPRITE_XFLIP) ? 0.f : 1.f; - float y = !(sprite->cstat & CSTAT_SPRITE_YFLIP) ? 0.f : 1.f; + float x = !(Sprite->cstat & CSTAT_SPRITE_XFLIP) ? 0.f : 1.f; + float y = !(Sprite->cstat & CSTAT_SPRITE_YFLIP) ? 0.f : 1.f; for (unsigned i = 0; i < 6; i++) { const static unsigned indices[] = { 0, 1, 2, 0, 2, 3 }; @@ -144,7 +144,7 @@ void HWFlat::MakeVertices() //========================================================================== void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) { - if (screen->BuffersArePersistent() && !sprite) + if (screen->BuffersArePersistent() && !Sprite) { MakeVertices(); } @@ -156,7 +156,7 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) } #endif - if (!sprite) + if (!Sprite) { auto mesh = sectorGeometry.get(section, plane, geoofs); state.SetNormal(mesh->normal); @@ -182,7 +182,7 @@ void HWFlat::DrawFlat(HWDrawInfo *di, FRenderState &state, bool translucent) if (texture && !checkTranslucentReplacement(texture->GetID(), palette)) state.AlphaFunc(Alpha_GEqual, texture->alphaThreshold); else state.AlphaFunc(Alpha_GEqual, 0.f); } - state.SetMaterial(texture, UF_Texture, 0, sprite == nullptr? CLAMP_NONE : CLAMP_XY, TRANSLATION(Translation_Remap + curbasepal, palette), -1); + state.SetMaterial(texture, UF_Texture, 0, Sprite == nullptr? CLAMP_NONE : CLAMP_XY, TRANSLATION(Translation_Remap + curbasepal, palette), -1); state.SetLightIndex(dynlightindex); state.Draw(DT_Triangles, vertindex, vertcount); @@ -208,7 +208,7 @@ void HWFlat::PutFlat(HWDrawInfo *di, int whichplane) { vertcount = 0; plane = whichplane; - if (!screen->BuffersArePersistent() || sprite || di->ingeo) // should be made static buffer content later (when the logic is working) + if (!screen->BuffersArePersistent() || Sprite || di->ingeo) // should be made static buffer content later (when the logic is working) { #if 0 if (di->Level->HasDynamicLights && texture != nullptr && !di->isFullbrightScene() && !(hacktype & (SSRF_PLANEHACK | SSRF_FLOODHACK))) @@ -250,7 +250,7 @@ void HWFlat::ProcessSector(HWDrawInfo *di, sectortype * frontsector, int section visibility = sectorVisibility(frontsector); sec = frontsector; section = section_; - sprite = nullptr; + Sprite = nullptr; geoofs = di->geoofs; // @@ -352,7 +352,7 @@ void HWFlat::ProcessFlatSprite(HWDrawInfo* di, spritetype* sprite, sectortype* s if (texture && texture->isValid()) { - this->sprite = sprite; + this->Sprite = sprite; sec = sector; shade = sprite->shade; palette = sprite->pal; diff --git a/source/core/rendering/scene/hw_portal.cpp b/source/core/rendering/scene/hw_portal.cpp index 1bce5d4e6..1ce9e32df 100644 --- a/source/core/rendering/scene/hw_portal.cpp +++ b/source/core/rendering/scene/hw_portal.cpp @@ -118,13 +118,42 @@ bool FPortalSceneState::RenderFirstSkyPortal(int recursion, HWDrawInfo *outer_di HWPortal* best = nullptr; unsigned bestindex = 0; - if (recursion > 0 || outer_di->Portals.Size() != 1 || !outer_di->Portals[0]->IsSky()) return false; + // Find the one with the highest amount of lines. + // Normally this is also the one that saves the largest amount + // of time by drawing it before the scene itself. + auto& portals = outer_di->Portals; + for (int i = portals.Size() - 1; i >= 0; --i) + { + auto p = portals[i]; + if (p->lines.Size() > 0 && p->IsSky()) + { + // Cannot clear the depth buffer inside a portal recursion + if (recursion && p->NeedDepthBuffer()) continue; - best = outer_di->Portals[0]; - outer_di->Portals.Clear(); - RenderPortal(best, state, false, outer_di); - delete best; - return true; + if (!best || p->lines.Size() > best->lines.Size()) + { + best = p; + bestindex = i; + } + + // If the portal area contains the current camera viewpoint, let's always use it because it's likely to give the largest area. + if (p->boundingBox.contains(outer_di->Viewpoint.Pos)) + { + best = p; + bestindex = i; + break; + } + } + } + + if (best) + { + portals.Delete(bestindex); + RenderPortal(best, state, false, outer_di); + delete best; + return true; + } + return false; } diff --git a/source/core/rendering/scene/hw_sky.cpp b/source/core/rendering/scene/hw_sky.cpp index 1a008ece9..c708a8ba2 100644 --- a/source/core/rendering/scene/hw_sky.cpp +++ b/source/core/rendering/scene/hw_sky.cpp @@ -54,7 +54,7 @@ void initSkyInfo(HWDrawInfo *di, HWSkyInfo* sky, sectortype* sector, int plane, { int remap = TRANSLATION(Translation_Remap + curbasepal, palette); - int16_t const* dapskyoff = getpsky(picnum, &dapyscale, &dapskybits, &dapyoffs, &daptileyscale); + int16_t const* dapskyoff = getpsky(picnum, &dapyscale, &dapskybits, &dapyoffs, &daptileyscale, true); int tw = tileWidth(picnum); if ((1 << sizeToBits(tw)) < tw) dapskybits--; // Build math is weird. diff --git a/source/core/rendering/scene/hw_sprites.cpp b/source/core/rendering/scene/hw_sprites.cpp index 31ec01a47..e55eda495 100644 --- a/source/core/rendering/scene/hw_sprites.cpp +++ b/source/core/rendering/scene/hw_sprites.cpp @@ -315,7 +315,7 @@ void HWSprite::Process(HWDrawInfo* di, spritetype* spr, sectortype* sector, int if (!tex || !tex->isValid()) return; texture = tex; - sprite = spr; + Sprite = spr; modelframe = 0; dynlightindex = -1; @@ -442,7 +442,7 @@ void HWSprite::Process(HWDrawInfo* di, spritetype* spr, sectortype* sector, int bool HWSprite::ProcessVoxel(HWDrawInfo* di, voxmodel_t* vox, spritetype* spr, sectortype* sector, bool rotate) { - sprite = spr; + Sprite = spr; auto sprext = &spriteext[spr->owner]; texture = nullptr; @@ -528,7 +528,7 @@ bool HWSprite::ProcessVoxel(HWDrawInfo* di, voxmodel_t* vox, spritetype* spr, se auto vp = di->Viewpoint; depth = (float)((x - vp.Pos.X) * vp.TanCos + (y - vp.Pos.Y) * vp.TanSin); - PutSprite(di, spriteHasTranslucency(sprite)); + PutSprite(di, spriteHasTranslucency(Sprite)); rendered_sprites++; return true; } diff --git a/source/core/rendering/scene/hw_walls.cpp b/source/core/rendering/scene/hw_walls.cpp index 1bdc3a944..4c528a7a3 100644 --- a/source/core/rendering/scene/hw_walls.cpp +++ b/source/core/rendering/scene/hw_walls.cpp @@ -158,7 +158,7 @@ void HWWall::RenderTexturedWall(HWDrawInfo *di, FRenderState &state, int rflags) SetLightAndFog(state, fade, palette, shade, visibility, alpha); state.SetMaterial(texture, UF_Texture, 0, (flags & (HWF_CLAMPX | HWF_CLAMPY)), TRANSLATION(Translation_Remap + curbasepal, palette), -1); - if (sprite == nullptr) + if (Sprite == nullptr) { int h = (int)texture->GetDisplayHeight(); int h2 = 1 << sizeToBits(h); @@ -479,7 +479,8 @@ void HWWall::PutPortal(HWDrawInfo *di, int ptype, int plane) case PORTALTYPE_LINETOSPRITE: // These are also unique. - portal = new HWLineToSpritePortal(&portalState, seg, &sprite[seg->portalnum]); + assert(seg->portalnum >= 0 && seg->portalnum < MAXSPRITES); + portal = new HWLineToSpritePortal(&portalState, seg, &::sprite[seg->portalnum]); di->Portals.Push(portal); portal->AddLine(this); break; @@ -704,7 +705,7 @@ void HWWall::DoTexture(HWDrawInfo* di, walltype* wal, walltype* refwall, float r { float h = hl + (hr - hl) * frac; h = (-(float)(refheight + (h * 256)) / ((th * 2048.0f) / (float)(wal->yrepeat))) + ypanning; - if (wal->cstat & CSTAT_WALL_YFLIP) h = -h; + if (refwall->cstat & CSTAT_WALL_YFLIP) h = -h; return h; }; @@ -866,7 +867,7 @@ void HWWall::Process(HWDrawInfo* di, walltype* wal, sectortype* frontsector, sec this->seg = wal; this->frontsector = frontsector; this->backsector = backsector; - sprite = nullptr; + Sprite = nullptr; vertindex = 0; vertcount = 0; @@ -1021,7 +1022,7 @@ void HWWall::ProcessWallSprite(HWDrawInfo* di, spritetype* spr, sectortype* sect if (!tex || !tex->isValid()) return; seg = nullptr; - sprite = spr; + Sprite = spr; vec2_t pos[2]; int sprz = spr->pos.z; @@ -1053,7 +1054,7 @@ void HWWall::ProcessWallSprite(HWDrawInfo* di, spritetype* spr, sectortype* sect fade = lookups.getFade(sector->floorpal); // fog is per sector. visibility = sectorVisibility(sector); - SetSpriteTranslucency(sprite, alpha, RenderStyle); + SetSpriteTranslucency(Sprite, alpha, RenderStyle); int height, topofs; if (hw_hightile && TileFiles.tiledata[spr->picnum].hiofs.xsize) @@ -1122,5 +1123,5 @@ void HWWall::ProcessWallSprite(HWDrawInfo* di, spritetype* spr, sectortype* sect std::swap(tcs[UPLFT], tcs[UPRGT]); } - PutWall(di, spriteHasTranslucency(sprite)); + PutWall(di, spriteHasTranslucency(Sprite)); } \ No newline at end of file diff --git a/source/core/savegamehelp.cpp b/source/core/savegamehelp.cpp index a0fd0dc87..2ff1fa7b4 100644 --- a/source/core/savegamehelp.cpp +++ b/source/core/savegamehelp.cpp @@ -59,6 +59,7 @@ #include "render.h" #include "hw_sections.h" #include "sectorgeometry.h" +#include "d_net.h" #include @@ -144,8 +145,8 @@ bool ReadSavegame(const char* name) FSerializer arc; if (!arc.OpenReader((const char*)data, info->LumpSize)) { - delete savereader; info->Unlock(); + delete savereader; return false; } info->Unlock(); @@ -422,7 +423,6 @@ FString G_BuildSaveName (const char *prefix) } #include "build.h" -#include "mmulti.h" #define V(x) x static spritetype zsp; diff --git a/source/games/blood/src/_polymost.cpp b/source/games/blood/src/_polymost.cpp index 417da88b0..64b755d73 100644 --- a/source/games/blood/src/_polymost.cpp +++ b/source/games/blood/src/_polymost.cpp @@ -110,7 +110,7 @@ void processSpritesOnOtherSideOfPortal(int x, int y, int interpolation) for (int i = mirrorcnt-1; i >= 0; i--) { int nTile = 4080+i; - if (TestBitString(gotpic, nTile)) + if (testgotpic(nTile)) { if (mirror[i].type == 1 || mirror[i].type == 2) { @@ -144,9 +144,9 @@ void render3DViewPolymost(int nSectnum, int cX, int cY, int cZ, binangle cA, fix } cH = q16horiz(ClipRange(cH.asq16(), gi->playerHorizMin(), gi->playerHorizMax())); RORHACK: - int ror_status[16]; + bool ror_status[16]; for (int i = 0; i < 16; i++) - ror_status[i] = TestBitString(gotpic, 4080 + i); + ror_status[i] = testgotpic(4080 + i); fixed_t deliriumPitchI = interpolatedvalue(IntToFixed(deliriumPitchO), IntToFixed(deliriumPitch), gInterpolate); DrawMirrors(cX, cY, cZ, cA.asq16(), cH.asq16() + deliriumPitchI, gInterpolate, gViewIndex); int bakCstat = gView->pSprite->cstat; @@ -163,7 +163,7 @@ RORHACK: viewProcessSprites(pm_tsprite, pm_spritesortcnt, cX, cY, cZ, cA.asbuild(), gInterpolate); bool do_ror_hack = false; for (int i = 0; i < 16; i++) - if (ror_status[i] != TestBitString(gotpic, 4080 + i)) + if (ror_status[i] != testgotpic(4080 + i)) do_ror_hack = true; if (do_ror_hack) { @@ -188,7 +188,7 @@ void setPortalFlags(char mode) for (int i = mirrorcnt - 1; i >= 0; i--) { int nTile = 4080 + i; - if (TestBitString(gotpic, nTile)) + if (testgotpic(nTile)) { switch (mirror[i].type) { @@ -215,9 +215,8 @@ void DrawMirrors(int x, int y, int z, fixed_t a, fixed_t horiz, int smooth, int for (int i = mirrorcnt - 1; i >= 0; i--) { int nTile = 4080 + i; - if (TestBitString(gotpic, nTile)) + if (testgotpic(nTile, true)) { - ClearBitString(gotpic, nTile); switch (mirror[i].type) { case 0: @@ -287,7 +286,7 @@ void DrawMirrors(int x, int y, int z, fixed_t a, fixed_t horiz, int smooth, int renderDrawMasks(); sector[nSector].floorstat = fstat; for (int i = 0; i < 16; i++) - ClearBitString(gotpic, 4080 + i); + cleargotpic(4080 + i); if (viewPlayer >= 0) { gPlayer[viewPlayer].pSprite->cstat = bakCstat; @@ -319,7 +318,7 @@ void DrawMirrors(int x, int y, int z, fixed_t a, fixed_t horiz, int smooth, int renderDrawMasks(); sector[nSector].ceilingstat = cstat; for (int i = 0; i < 16; i++) - ClearBitString(gotpic, 4080 + i); + cleargotpic(4080 + i); if (viewPlayer >= 0) { gPlayer[viewPlayer].pSprite->cstat = bakCstat; diff --git a/source/games/blood/src/actor.cpp b/source/games/blood/src/actor.cpp index f78571942..60bbf823b 100644 --- a/source/games/blood/src/actor.cpp +++ b/source/games/blood/src/actor.cpp @@ -27,13 +27,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "build.h" #include "automap.h" -#include "mmulti.h" #include "savegamehelp.h" #include "blood.h" BEGIN_BLD_NS +static DBloodActor* actDropObject(DBloodActor* actor, int nType); + + VECTORDATA gVectorData[] = { // this is constant EXCEPT for [VECTOR_TYPE_20].maxDist. What were they thinking... // Tine @@ -2351,7 +2353,7 @@ bool IsUnderwaterSector(int nSector) // //--------------------------------------------------------------------------- -void actInitTraps() +static void actInitTraps() { BloodStatIterator it(kStatTraps); while (auto act = it.Next()) @@ -2375,7 +2377,7 @@ void actInitTraps() // //--------------------------------------------------------------------------- -void actInitThings() +static void actInitThings() { BloodStatIterator it(kStatThing); while (auto act = it.Next()) @@ -2429,7 +2431,7 @@ void actInitThings() // //--------------------------------------------------------------------------- -void actInitDudes() +static void actInitDudes() { if (gGameOptions.nMonsterSettings == 0) { @@ -2439,7 +2441,7 @@ void actInitDudes() { spritetype* pSprite = &act->s(); if (act->hasX() && act->x().key > 0) // Drop Key - actDropObject(pSprite, kItemKeyBase + (act->x().key - 1)); + actDropObject(act, kItemKeyBase + (act->x().key - 1)); DeleteSprite(act); } } @@ -2463,7 +2465,7 @@ void actInitDudes() for (int i = 0; i < kDudeMax - kDudeBase; i++) for (int j = 0; j < 7; j++) - dudeInfo[i].at70[j] = MulScale(DudeDifficulty[gGameOptions.nDifficulty], dudeInfo[i].startDamage[j], 8); + dudeInfo[i].damageVal[j] = MulScale(DudeDifficulty[gGameOptions.nDifficulty], dudeInfo[i].startDamage[j], 8); it.Reset(kStatDude); while (auto act = it.Next()) @@ -2553,1049 +2555,1302 @@ void actInit(bool bSaveLoad) // //--------------------------------------------------------------------------- -void ConcussSprite(int a1, spritetype *pSprite, int x, int y, int z, int a6) +static void ConcussSprite(DBloodActor* source, DBloodActor* actor, int x, int y, int z, int damage) { - assert(pSprite != NULL); - int dx = pSprite->x-x; - int dy = pSprite->y-y; - int dz = (pSprite->z-z)>>4; - int dist2 = 0x40000+dx*dx+dy*dy+dz*dz; - assert(dist2 > 0); - a6 = scale(0x40000, a6, dist2); + auto pSprite = &actor->s(); + int dx = pSprite->x - x; + int dy = pSprite->y - y; + int dz = (pSprite->z - z) >> 4; + int dist2 = 0x40000 + dx * dx + dy * dy + dz * dz; + assert(dist2 > 0); + damage = scale(0x40000, damage, dist2); - if (pSprite->flags & kPhysMove) { - int mass = 0; - if (IsDudeSprite(pSprite)) { - - mass = getDudeInfo(pSprite->type)->mass; - #ifdef NOONE_EXTENSIONS - switch (pSprite->type) { - case kDudeModernCustom: - case kDudeModernCustomBurning: - mass = getSpriteMassBySize(pSprite); - break; - } - #endif - - } else if (pSprite->type >= kThingBase && pSprite->type < kThingMax) { - mass = thingInfo[pSprite->type - kThingBase].mass; - } else { - Printf(PRINT_HIGH, "Unexpected type in ConcussSprite(): Sprite: %d Type: %d Stat: %d", (int)pSprite->index, (int)pSprite->type, (int)pSprite->statnum); - return; - } - - int size = (tileWidth(pSprite->picnum)*pSprite->xrepeat*tileHeight(pSprite->picnum)*pSprite->yrepeat)>>1; - assert(mass > 0); - - int t = scale(a6, size, mass); - dx = MulScale(t, dx, 16); - dy = MulScale(t, dy, 16); - dz = MulScale(t, dz, 16); - int nSprite = pSprite->index; - assert(nSprite >= 0 && nSprite < kMaxSprites); - xvel[nSprite] += dx; - yvel[nSprite] += dy; - zvel[nSprite] += dz; - } - - actDamageSprite(a1, pSprite, DAMAGE_TYPE_3, a6); -} - -int actWallBounceVector(int *x, int *y, int nWall, int a4) -{ - int wx, wy; - GetWallNormal(nWall, &wx, &wy); - int t = DMulScale(*x, wx, *y, wy, 16); - int t2 = mulscale16r(t, a4+0x10000); - *x -= MulScale(wx, t2, 16); - *y -= MulScale(wy, t2, 16); - return mulscale16r(t, 0x10000-a4); -} - -int actFloorBounceVector(int *x, int *y, int *z, int nSector, int a5) -{ - int t = 0x10000-a5; - if (sector[nSector].floorheinum == 0) - { - int t2 = MulScale(*z, t, 16); - *z = -(*z-t2); - return t2; - } - walltype *pWall = &wall[sector[nSector].wallptr]; - walltype *pWall2 = &wall[pWall->point2]; - int angle = getangle(pWall2->x-pWall->x, pWall2->y-pWall->y)+512; - int t2 = sector[nSector].floorheinum<<4; - int t3 = approxDist(-0x10000, t2); - int t4 = DivScale(-0x10000, t3, 16); - int t5 = DivScale(t2, t3, 16); - int t6 = MulScale(t5, Cos(angle), 30); - int t7 = MulScale(t5, Sin(angle), 30); - int t8 = TMulScale(*x, t6, *y, t7, *z, t4, 16); - int t9 = MulScale(t8, 0x10000+a5, 16); - *x -= MulScale(t6, t9, 16); - *y -= MulScale(t7, t9, 16); - *z -= MulScale(t4, t9, 16); - return mulscale16r(t8, t); -} - -void sub_2A620(int nSprite, int x, int y, int z, int nSector, int nDist, int a7, int a8, DAMAGE_TYPE a9, int a10, int a11, int a12, int a13) -{ - UNREFERENCED_PARAMETER(a12); - UNREFERENCED_PARAMETER(a13); - uint8_t va0[(kMaxSectors+7)>>3]; - int nOwner = sprite[nSprite].owner; - GetClosestSpriteSectors(nSector, x, y, nDist, va0); - nDist <<= 4; - if (a10 & 2) - { - int i; - StatIterator it(kStatDude); - while ((i = it.NextIndex()) >= 0) - { - if (i != nSprite || (a10 & 1)) - { - spritetype *pSprite2 = &sprite[i]; - if (pSprite2->extra > 0 && pSprite2->extra < kMaxXSprites) - { - - if (pSprite2->flags & 0x20) - continue; - if (!TestBitString(va0, pSprite2->sectnum)) - continue; - if (!CheckProximity(pSprite2, x, y, z, nSector, nDist)) - continue; - int dx = abs(x-pSprite2->x); - int dy = abs(y-pSprite2->y); - int dz = abs(z-pSprite2->z)>>4; - int dist = ksqrt(dx*dx+dy*dy+dz*dz); - if (dist > nDist) - continue; - int vcx; - if (dist != 0) - vcx = a7+((nDist-dist)*a8)/nDist; - else - vcx = a7+a8; - actDamageSprite(nSprite, pSprite2, a9, vcx<<4); - if (a11) - actBurnSprite(nOwner, &xsprite[pSprite2->extra], a11); - } - } - } - } - if (a10 & 4) - { - int i; - StatIterator it(kStatThing); - while ((i = it.NextIndex()) >= 0) - { - spritetype *pSprite2 = &sprite[i]; - - if (pSprite2->flags&0x20) - continue; - if (!TestBitString(va0, pSprite2->sectnum)) - continue; - if (!CheckProximity(pSprite2, x, y, z, nSector, nDist)) - continue; - XSPRITE *pXSprite2 = &xsprite[pSprite2->extra]; - if (pXSprite2->locked) - continue; - int dx = abs(x-pSprite2->x); - int dy = abs(y-pSprite2->y); - int dist = ksqrt(dx*dx+dy*dy); - if (dist > nDist) - continue; - int vcx; - if (dist != 0) - vcx = a7+((nDist-dist)*a8)/nDist; - else - vcx = a7+a8; - actDamageSprite(nSprite, pSprite2, a9, vcx<<4); - if (a11) - actBurnSprite(nOwner, pXSprite2, a11); - } - } -} - -void sub_2AA94(DBloodActor* actor) -{ - auto pXSprite = &actor->x(); - auto pSprite = &actor->s(); - int nOwner = pSprite->owner; - actPostSprite(pSprite->index, kStatDecoration); - seqSpawn(9, 3, pSprite->extra); - if (Chance(0x8000)) - pSprite->cstat |= 4; - - sfxPlay3DSound(pSprite, 303, 24+(pSprite->flags&3), 1); - sub_2A620(nOwner, pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, 128, 0, 60, DAMAGE_TYPE_3, 15, 120, 0, 0); - if (pXSprite->data4 > 1) - { - GibSprite(pSprite, GIBTYPE_5, NULL, NULL); - int v14[2]; - v14[0] = pXSprite->data4>>1; - v14[1] = pXSprite->data4-v14[0]; - int v4 = pSprite->ang; - xvel[pSprite->index] = 0; - yvel[pSprite->index] = 0; - zvel[pSprite->index] = 0; - for (int i = 0; i < 2; i++) - { - int t1 = Random(0x33333)+0x33333; - int t2 = Random2(0x71); - pSprite->ang = (t2+v4+2048)&2047; - spritetype *pSprite2 = actFireThing(pSprite, 0, 0, -0x93d0, kThingNapalmBall, t1); - XSPRITE *pXSprite2 = &xsprite[pSprite2->extra]; - pSprite2->owner = pSprite->owner; - seqSpawn(61, 3, pSprite2->extra, nNapalmClient); - pXSprite2->data4 = v14[i]; - } - } -} - -spritetype *actSpawnFloor(spritetype *pSprite) -{ - short nSector = pSprite->sectnum; - int x = pSprite->x; - int y = pSprite->y; - updatesector(x, y, &nSector); - int zFloor = getflorzofslope(nSector, x, y); - spritetype *pSprite2 = actSpawnSprite(nSector, x, y, zFloor, 3, 0); - if (pSprite2) - pSprite2->cstat &= ~257; - return pSprite2; -} - -spritetype *actDropAmmo(spritetype *pSprite, int nType) -{ - spritetype *pSprite2 = NULL; - if (pSprite && pSprite->statnum < kMaxStatus && nType >= kItemAmmoBase && nType < kItemAmmoMax) - { - pSprite2 = actSpawnFloor(pSprite); - const AMMOITEMDATA *pAmmo = &gAmmoItemData[nType - kItemAmmoBase]; - pSprite2->type = nType; - pSprite2->picnum = pAmmo->picnum; - pSprite2->shade = pAmmo->shade; - pSprite2->xrepeat = pAmmo->xrepeat; - pSprite2->yrepeat = pAmmo->yrepeat; - } - return pSprite2; -} - -spritetype *actDropWeapon(spritetype *pSprite, int nType) -{ - spritetype *pSprite2 = NULL; - if (pSprite && pSprite->statnum < kMaxStatus && nType >= kItemWeaponBase && nType < kItemWeaponMax) - { - pSprite2 = actSpawnFloor(pSprite); - const WEAPONITEMDATA *pWeapon = &gWeaponItemData[nType - kItemWeaponBase]; - pSprite2->type = nType; - pSprite2->picnum = pWeapon->picnum; - pSprite2->shade = pWeapon->shade; - pSprite2->xrepeat = pWeapon->xrepeat; - pSprite2->yrepeat = pWeapon->yrepeat; - } - return pSprite2; -} - -spritetype *actDropItem(spritetype *pSprite, int nType) -{ - spritetype *pSprite2 = NULL; - if (pSprite && pSprite->statnum < kMaxStatus && nType >= kItemBase && nType < kItemMax) - { - pSprite2 = actSpawnFloor(pSprite); - const ITEMDATA *pItem = &gItemData[nType - kItemBase]; - pSprite2->type = nType; - pSprite2->picnum = pItem->picnum; - pSprite2->shade = pItem->shade; - pSprite2->xrepeat = pItem->xrepeat; - pSprite2->yrepeat = pItem->yrepeat; - } - return pSprite2; -} - -spritetype *actDropKey(spritetype *pSprite, int nType) -{ - spritetype *pSprite2 = NULL; - if (pSprite && pSprite->statnum < kMaxStatus && nType >= kItemKeyBase && nType < kItemKeyMax) - { - pSprite2 = actDropItem(pSprite, nType); - if (pSprite2 && gGameOptions.nGameType == 1) - { - if (pSprite2->extra == -1) - dbInsertXSprite(pSprite2->index); - xsprite[pSprite2->extra].respawn = 3; - gSpriteHit[pSprite2->extra].florhit = 0; - gSpriteHit[pSprite2->extra].ceilhit = 0; - } - } - return pSprite2; -} - -spritetype *actDropFlag(spritetype *pSprite, int nType) -{ - spritetype *pSprite2 = NULL; - if (pSprite && pSprite->statnum < kMaxStatus && (nType == 147 || nType == 148)) - { - pSprite2 = actDropItem(pSprite, nType); - if (pSprite2 && gGameOptions.nGameType == 3) - { - evPost(pSprite2->index, 3, 1800, kCallbackReturnFlag); - } - } - return pSprite2; -} - -spritetype *actDropObject(spritetype *pSprite, int nType) { - spritetype *pSprite2 = NULL; - - if (nType >= kItemKeyBase && nType < kItemKeyMax) pSprite2 = actDropKey(pSprite, nType); - else if (nType == kItemFlagA || nType == kItemFlagB) pSprite2 = actDropFlag(pSprite, nType); - else if (nType >= kItemBase && nType < kItemMax) pSprite2 = actDropItem(pSprite, nType); - else if (nType >= kItemAmmoBase && nType < kItemAmmoMax) pSprite2 = actDropAmmo(pSprite, nType); - else if (nType >= kItemWeaponBase && nType < kItemWeaponMax) pSprite2 = actDropWeapon(pSprite, nType); - - if (pSprite2) { - if (pSprite2->picnum == -1) - { - DeleteSprite(pSprite2 - sprite); - return nullptr; - } - int top, bottom; - GetSpriteExtents(pSprite2, &top, &bottom); - if (bottom >= pSprite2->z) - pSprite2->z -= bottom - pSprite2->z; - } - - return pSprite2; -} - -bool actHealDude(XSPRITE *pXDude, int a2, int a3) -{ - assert(pXDude != NULL); - a2 <<= 4; - a3 <<= 4; - if (pXDude->health < a3) - { - spritetype *pSprite = &sprite[pXDude->reference]; - if (IsPlayerSprite(pSprite)) - sfxPlay3DSound(pSprite->x, pSprite->y, pSprite->z, 780, pSprite->sectnum); - pXDude->health = ClipHigh(pXDude->health+a2, a3); - return 1; - } - return 0; -} - -void actKillDude(int nKillerSprite, spritetype *pSprite, DAMAGE_TYPE damageType, int damage) -{ - spritetype *pKillerSprite = &sprite[nKillerSprite]; - assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax); - int nType = pSprite->type-kDudeBase; - int nXSprite = pSprite->extra; - assert(nXSprite > 0); - XSPRITE *pXSprite = &xsprite[pSprite->extra]; - - switch (pSprite->type) { - #ifdef NOONE_EXTENSIONS - case kDudeModernCustom: { - - GENDUDEEXTRA* pExtra = genDudeExtra(pSprite); - removeDudeStuff(pSprite); - if (pXSprite->txID <= 0 || getNextIncarnation(pXSprite) == NULL) { - - if (pExtra->weaponType == kGenDudeWeaponKamikaze && Chance(0x4000) && damageType != 5 && damageType != 4) { - doExplosion(pSprite, pXSprite->data1 - kTrapExploder); - if (Chance(0x9000)) damageType = (DAMAGE_TYPE) 3; - } - - if (damageType == DAMAGE_TYPE_1) { - if (pExtra->availDeaths[DAMAGE_TYPE_1] && !spriteIsUnderwater(pSprite)) { - if (pExtra->canBurn) { - pSprite->type = kDudeModernCustomBurning; - if (pXSprite->data2 == kGenDudeDefaultSeq) // don't inherit palette for burning if using default animation - pSprite->pal = 0; - - aiGenDudeNewState(pSprite, &genDudeBurnGoto); - actHealDude(pXSprite, dudeInfo[55].startHealth, dudeInfo[55].startHealth); - if (pXSprite->burnTime <= 0) pXSprite->burnTime = 1200; - gDudeExtra[pSprite->extra].time = PlayClock + 360; - return; - } - - } else { - pXSprite->burnTime = 0; - pXSprite->burnSource = -1; - damageType = DAMAGE_TYPE_0; - } - } - - } else { - - pXSprite->locked = 1; // lock while transforming - - aiSetGenIdleState(pSprite, pXSprite); // set idle state - - if (pXSprite->key > 0) // drop keys - actDropObject(pSprite, kItemKeyBase + pXSprite->key - 1); - - if (pXSprite->dropMsg > 0) // drop items - actDropObject(pSprite, pXSprite->dropMsg); - - - pSprite->flags &= ~kPhysMove; xvel[pSprite->index] = yvel[pSprite->index] = 0; - - playGenDudeSound(pSprite, kGenDudeSndTransforming); - int seqId = pXSprite->data2 + kGenDudeSeqTransform; - if (getSequence(seqId)) seqSpawn(seqId, 3, nXSprite, -1); - else { - seqKill(3, nXSprite); - spritetype* pEffect = gFX.fxSpawn((FX_ID)52, pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, pSprite->ang); - if (pEffect != NULL) { - pEffect->cstat = CSTAT_SPRITE_ALIGNMENT_FACING; - pEffect->pal = 6; - pEffect->xrepeat = pSprite->xrepeat; - pEffect->yrepeat = pSprite->yrepeat; - } - - GIBTYPE nGibType; - for (int i = 0; i < 3; i++) { - if (Chance(0x3000)) nGibType = GIBTYPE_6; - else if (Chance(0x2000)) nGibType = GIBTYPE_5; - else nGibType = GIBTYPE_17; - - int top, bottom; - GetSpriteExtents(pSprite, &top, &bottom); - CGibPosition gibPos(pSprite->x, pSprite->y, top); - CGibVelocity gibVel(xvel[pSprite->index] >> 1, yvel[pSprite->index] >> 1, -0xccccc); - GibSprite(pSprite, nGibType, &gibPos, &gibVel); - } - } - - pXSprite->sysData1 = kGenDudeTransformStatus; // in transform - return; - } - break; - } - #endif - case kDudeCerberusTwoHead: // Cerberus - seqSpawn(dudeInfo[nType].seqStartID+1, 3, nXSprite, -1); - return; - case kDudeCultistTommy: - case kDudeCultistShotgun: - case kDudeCultistTesla: - case kDudeCultistTNT: - if (damageType == DAMAGE_TYPE_1 && pXSprite->medium == kMediumNormal) - { - pSprite->type = kDudeBurningCultist; - aiNewState(&bloodActors[pXSprite->reference], &cultistBurnGoto); - actHealDude(pXSprite, dudeInfo[40].startHealth, dudeInfo[40].startHealth); - return; - } - // no break - fallthrough__; - case kDudeBeast: - if (damageType == DAMAGE_TYPE_1 && pXSprite->medium == kMediumNormal) - { - pSprite->type = kDudeBurningBeast; - aiNewState(&bloodActors[pXSprite->reference], &beastBurnGoto); - actHealDude(pXSprite, dudeInfo[53].startHealth, dudeInfo[53].startHealth); - return; - } - // no break - fallthrough__; - case kDudeInnocent: - if (damageType == DAMAGE_TYPE_1 && pXSprite->medium == kMediumNormal) - { - pSprite->type = kDudeBurningInnocent; - aiNewState(&bloodActors[pXSprite->reference], &innocentBurnGoto); - actHealDude(pXSprite, dudeInfo[39].startHealth, dudeInfo[39].startHealth); - return; - } - break; - } - for (int p = connecthead; p >= 0; p = connectpoint2[p]) - { - if (gPlayer[p].fraggerId == pSprite->index && gPlayer[p].deathTime > 0) - gPlayer[p].fraggerId = -1; - } - if (pSprite->type != kDudeCultistBeast) - trTriggerSprite(pSprite->index, pXSprite, kCmdOff); - - pSprite->flags |= 7; - if (VanillaMode()) { - if (IsPlayerSprite(pKillerSprite)) { - PLAYER *pPlayer = &gPlayer[pKillerSprite->type - kDudePlayer1]; - if (gGameOptions.nGameType == 1) - pPlayer->fragCount++; - } - } else if (gGameOptions.nGameType == 1 && IsPlayerSprite(pKillerSprite) && pSprite->statnum == kStatDude) { - switch (pSprite->type) { - case kDudeBat: - case kDudeRat: - case kDudeInnocent: - case kDudeBurningInnocent: - break; - default: - PLAYER* pKillerPlayer = &gPlayer[pKillerSprite->type - kDudePlayer1]; - pKillerPlayer->fragCount++; - break; - } - - } - - if (pXSprite->key > 0) - actDropObject(pSprite, kItemKeyBase + pXSprite->key - 1); - - if (pXSprite->dropMsg > 0) - actDropObject(pSprite, pXSprite->dropMsg); - - switch (pSprite->type) { - case kDudeCultistTommy: { - int nRand = Random(100); - if (nRand < 10) actDropObject(pSprite, kItemWeaponTommygun); - else if (nRand < 50) actDropObject(pSprite, kItemAmmoTommygunFew); - } - break; - case kDudeCultistShotgun: { - int nRand = Random(100); - if (nRand <= 10) actDropObject(pSprite, kItemWeaponSawedoff); - else if (nRand <= 50) actDropObject(pSprite, kItemAmmoSawedoffFew); - } - break; - } - - int nSeq; - switch (damageType) - { - case DAMAGE_TYPE_3: - nSeq = 2; - switch (pSprite->type) { - #ifdef NOONE_EXTENSIONS - case kDudeModernCustom: - case kDudeModernCustomBurning: { - playGenDudeSound(pSprite, kGenDudeSndDeathExplode); - GENDUDEEXTRA* pExtra = genDudeExtra(pSprite); - if (!pExtra->availDeaths[damageType]) { - nSeq = 1; damageType = DAMAGE_TYPE_0; - } - break; - } - #endif - case kDudeCultistTommy: - case kDudeCultistShotgun: - case kDudeCultistTommyProne: - case kDudeBurningInnocent: - case kDudeBurningCultist: - case kDudeInnocent: - case kDudeCultistShotgunProne: - case kDudeCultistTesla: - case kDudeCultistTNT: - case kDudeCultistBeast: - case kDudeTinyCaleb: - case kDudeBurningTinyCaleb: - sfxPlay3DSound(pSprite, 717,-1,0); - break; - } - break; - case DAMAGE_TYPE_1: - nSeq = 3; - sfxPlay3DSound(pSprite, 351, -1, 0); - break; - case DAMAGE_TYPE_5: - switch (pSprite->type) { - case kDudeZombieAxeNormal: - case kDudeZombieAxeBuried: - nSeq = 14; - break; - case kDudeZombieButcher: - nSeq = 11; - break; - default: - nSeq = 1; - break; - } - break; - case DAMAGE_TYPE_0: - switch (pSprite->type) - { - case kDudeCultistTommy: - case kDudeCultistShotgun: - nSeq = 1; - break; - default: - nSeq = 1; - break; - } - break; - default: - nSeq = 1; - break; - } - - if (!getSequence(getDudeInfo(nType+kDudeBase)->seqStartID + nSeq)) - { - seqKill(3, nXSprite); - gKillMgr.AddKill(pSprite); - actPostSprite(pSprite->index, kStatFree); - return; - } - - switch (pSprite->type) { - case kDudeZombieAxeNormal: - sfxPlay3DSound(pSprite, 1107+Random(2), -1, 0); - if (nSeq == 2) { - - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, nDudeToGibClient1); - int top, bottom; - GetSpriteExtents(pSprite, &top, &bottom); - CGibPosition gibPos(pSprite->x, pSprite->y, top); - CGibVelocity gibVel(xvel[pSprite->index]>>1, yvel[pSprite->index]>>1, -0xccccc); - GibSprite(pSprite, GIBTYPE_27, &gibPos, &gibVel); - - } else if (nSeq == 1 && Chance(0x4000)) { - - seqSpawn(dudeInfo[nType].seqStartID+7, 3, nXSprite, nDudeToGibClient1); - evPost(pSprite->index, 3, 0, kCallbackFXZombieSpurt); - sfxPlay3DSound(pSprite, 362, -1, 0); - pXSprite->data1 = 35; - pXSprite->data2 = 5; - int top, bottom; - GetSpriteExtents(pSprite, &top, &bottom); - CGibPosition gibPos(pSprite->x, pSprite->y, top); - CGibVelocity gibVel(xvel[pSprite->index] >> 1, yvel[pSprite->index] >> 1, -0x111111); - GibSprite(pSprite, GIBTYPE_27, &gibPos, &gibVel); - - } else if (nSeq == 14) - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1); - else if (nSeq == 3) - seqSpawn(dudeInfo[nType].seqStartID+13, 3, nXSprite, nDudeToGibClient2); - else - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, nDudeToGibClient1); - break; - case kDudeCultistTommy: - case kDudeCultistShotgun: - case kDudeCultistTesla: - case kDudeCultistTNT: - sfxPlay3DSound(pSprite, 1018+Random(2), -1, 0); - if (nSeq == 3) - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, nDudeToGibClient2); - else - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, nDudeToGibClient1); - break; - case kDudeBurningCultist: - if (Chance(0x4000) && nSeq == 3) - sfxPlay3DSound(pSprite, 718, -1, 0); - else - sfxPlay3DSound(pSprite, 1018+Random(2), -1, 0); - damageType = DAMAGE_TYPE_3; - if (Chance(0x8000)) - { - for (int i = 0; i < 3; i++) - GibSprite(pSprite, GIBTYPE_7, NULL, NULL); - seqSpawn(dudeInfo[nType].seqStartID+16-Random(1), 3, nXSprite, nDudeToGibClient1); - } - else - seqSpawn(dudeInfo[nType].seqStartID+15, 3, nXSprite, nDudeToGibClient2); - break; + if (pSprite->flags & kPhysMove) + { + int mass = 0; + if (actor->IsDudeActor()) + { + mass = getDudeInfo(pSprite->type)->mass; #ifdef NOONE_EXTENSIONS - case kDudeModernCustom: { - playGenDudeSound(pSprite, kGenDudeSndDeathNormal); - int dudeToGib = (actCheckRespawn(pSprite)) ? -1 : ((nSeq == 3) ? nDudeToGibClient2 : nDudeToGibClient1); - if (nSeq == 3) { - - GENDUDEEXTRA* pExtra = genDudeExtra(pSprite); - if (pExtra->availDeaths[kDmgBurn] == 3) seqSpawn((15 + Random(2)) + pXSprite->data2, 3, nXSprite, dudeToGib); - else if (pExtra->availDeaths[kDmgBurn] == 2) seqSpawn(16 + pXSprite->data2, 3, nXSprite, dudeToGib); - else if (pExtra->availDeaths[kDmgBurn] == 1) seqSpawn(15 + pXSprite->data2, 3, nXSprite, dudeToGib); - else if (getSequence(pXSprite->data2 + nSeq))seqSpawn(nSeq + pXSprite->data2, 3, nXSprite, dudeToGib); - else seqSpawn(1 + pXSprite->data2, 3, nXSprite, dudeToGib); - - } else { - seqSpawn(nSeq + pXSprite->data2, 3, nXSprite, dudeToGib); - } - genDudePostDeath(pSprite, damageType, damage); - return; - - } - case kDudeModernCustomBurning: { - playGenDudeSound(pSprite, kGenDudeSndDeathExplode); - int dudeToGib = (actCheckRespawn(pSprite)) ? -1 : nDudeToGibClient1; - damageType = DAMAGE_TYPE_3; - - if (Chance(0x4000)) { - int top, bottom; - GetSpriteExtents(pSprite, &top, &bottom); - CGibPosition gibPos(pSprite->x, pSprite->y, top); - CGibVelocity gibVel(xvel[pSprite->index] >> 1, yvel[pSprite->index] >> 1, -0xccccc); - GibSprite(pSprite, GIBTYPE_7, &gibPos, &gibVel); - } - - GENDUDEEXTRA* pExtra = genDudeExtra(pSprite); - if (pExtra->availDeaths[kDmgBurn] == 3) seqSpawn((15 + Random(2)) + pXSprite->data2, 3, nXSprite, dudeToGib); - else if (pExtra->availDeaths[kDmgBurn] == 2) seqSpawn(16 + pXSprite->data2, 3, nXSprite, dudeToGib); - else if (pExtra->availDeaths[kDmgBurn] == 1) seqSpawn(15 + pXSprite->data2, 3, nXSprite, dudeToGib); - else seqSpawn(1 + pXSprite->data2, 3, nXSprite, dudeToGib); - genDudePostDeath(pSprite, damageType, damage); - return; - } + if (pSprite->type == kDudeModernCustom || pSprite->type == kDudeModernCustomBurning) + { + mass = getSpriteMassBySize(pSprite); + } #endif - case kDudeBurningZombieAxe: - if (Chance(0x8000) && nSeq == 3) - sfxPlay3DSound(pSprite, 1109, -1, 0); - else - sfxPlay3DSound(pSprite, 1107+Random(2), -1, 0); - damageType = DAMAGE_TYPE_3; - if (Chance(0x8000)) - { - seqSpawn(dudeInfo[nType].seqStartID+13, 3, nXSprite, nDudeToGibClient1); - int top, bottom; - GetSpriteExtents(pSprite, &top, &bottom); - CGibPosition gibPos(pSprite->x, pSprite->y, top); - CGibVelocity gibVel(xvel[pSprite->index]>>1, yvel[pSprite->index]>>1, -0xccccc); - GibSprite(pSprite, GIBTYPE_27, &gibPos, &gibVel); - } - else - seqSpawn(dudeInfo[nType].seqStartID+13, 3, nXSprite, nDudeToGibClient2); - break; - case kDudeBurningZombieButcher: - if (Chance(0x4000) && nSeq == 3) - sfxPlay3DSound(pSprite, 1206, -1, 0); - else - sfxPlay3DSound(pSprite, 1204+Random(2), -1, 0); - seqSpawn(dudeInfo[4].seqStartID+10, 3, nXSprite, -1); - break; - case kDudeBurningInnocent: - damageType = DAMAGE_TYPE_3; - seqSpawn(dudeInfo[nType].seqStartID+7, 3, nXSprite, nDudeToGibClient1); - break; - case kDudeZombieButcher: - if (nSeq == 14) { - sfxPlay3DSound(pSprite, 1206, -1, 0); - seqSpawn(dudeInfo[nType].seqStartID+11, 3, nXSprite, -1); - break; - } - sfxPlay3DSound(pSprite, 1204+Random(2), -1, 0); - if (nSeq == 3) - seqSpawn(dudeInfo[nType].seqStartID+10, 3, nXSprite, -1); - else - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1); - break; - case kDudeGargoyleFlesh: - if (Chance(0x4000) && nSeq == 3) sfxPlay3DSound(pSprite, 1405, -1, 0); - else sfxPlay3DSound(pSprite, 1403+Random(2), -1, 0); - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1); - break; - case kDudeGargoyleStone: - if (Chance(0x4000) && nSeq == 3) sfxPlay3DSound(pSprite, 1455, -1, 0); - else sfxPlay3DSound(pSprite, 1453+Random(2), -1, 0); - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1); - break; - case kDudePhantasm: - if (Chance(0x4000) && nSeq == 3) sfxPlay3DSound(pSprite, 1605, -1, 0); - else sfxPlay3DSound(pSprite, 1603+Random(2), -1, 0); - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1); - break; - case kDudeHellHound: - if (Chance(0x4000) && nSeq == 3) sfxPlay3DSound(pSprite, 1305, -1, 0); - else sfxPlay3DSound(pSprite, 1303+Random(2), -1, 0); - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1); - break; - case kDudeHand: - if (Chance(0x4000) && nSeq == 3) sfxPlay3DSound(pSprite, 1905, -1, 0); - else sfxPlay3DSound(pSprite, 1903+Random(2), -1, 0); - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1); - break; - case kDudeSpiderBrown: - if (pSprite->owner != -1) { - spritetype *pOwner = &sprite[pSprite->owner]; - gDudeExtra[pOwner->extra].at6.u1.xval2--; - } - - if (Chance(0x4000) && nSeq == 3) sfxPlay3DSound(pSprite, 1805, -1, 0); - else sfxPlay3DSound(pSprite, 1803+Random(2), -1, 0); - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1); - break; - case kDudeSpiderRed: - if (pSprite->owner != -1) { - spritetype *pOwner = &sprite[pSprite->owner]; - gDudeExtra[pOwner->extra].at6.u1.xval2--; - } - - if (Chance(0x4000) && nSeq == 3) sfxPlay3DSound(pSprite, 1805, -1, 0); - else sfxPlay3DSound(pSprite, 1803+Random(2), -1, 0); - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1); - break; - case kDudeSpiderBlack: - if (pSprite->owner != -1) { - spritetype *pOwner = &sprite[pSprite->owner]; - gDudeExtra[pOwner->extra].at6.u1.xval2--; - } - - if (Chance(0x4000) && nSeq == 3) sfxPlay3DSound(pSprite, 1805, -1, 0); - else sfxPlay3DSound(pSprite, 1803+Random(2), -1, 0); - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1); - break; - case kDudeSpiderMother: - sfxPlay3DSound(pSprite, 1850, -1, 0); - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1); - break; - case kDudeGillBeast: - if (Chance(0x4000) && nSeq == 3) sfxPlay3DSound(pSprite, 1705, -1, 0); - else sfxPlay3DSound(pSprite, 1703+Random(2), -1, 0); - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1); - break; - case kDudeBoneEel: - if (Chance(0x4000) && nSeq == 3) sfxPlay3DSound(pSprite, 1505, -1, 0); - else sfxPlay3DSound(pSprite, 1503+Random(2), -1, 0); - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1); - break; - case kDudeBat: - if (Chance(0x4000) && nSeq == 3) - sfxPlay3DSound(pSprite, 2005, -1, 0); - else - sfxPlay3DSound(pSprite, 2003+Random(2), -1, 0); - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1); - break; - case kDudeRat: - if (Chance(0x4000) && nSeq == 3) - sfxPlay3DSound(pSprite, 2105, -1, 0); - else - sfxPlay3DSound(pSprite, 2103+Random(2), -1, 0); - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1); - break; - case kDudePodGreen: - case kDudeTentacleGreen: - case kDudePodFire: - case kDudeTentacleFire: - if ((pSprite->cstat & CSTAT_SPRITE_YFLIP)) pSprite->cstat &= ~CSTAT_SPRITE_YFLIP; - switch (pSprite->type) { - case kDudePodGreen: - if (Chance(0x4000) && nSeq == 3) - sfxPlay3DSound(pSprite, 2205, -1, 0); - else - sfxPlay3DSound(pSprite, 2203 + Random(2), -1, 0); - seqSpawn(dudeInfo[nType].seqStartID + nSeq, 3, nXSprite, -1); - break; - case kDudeTentacleGreen: - if (damage == 5) - sfxPlay3DSound(pSprite, 2471, -1, 0); - else - sfxPlay3DSound(pSprite, 2472, -1, 0); - seqSpawn(dudeInfo[nType].seqStartID + nSeq, 3, nXSprite, -1); - break; - case kDudePodFire: - if (damage == 5) - sfxPlay3DSound(pSprite, 2451, -1, 0); - else - sfxPlay3DSound(pSprite, 2452, -1, 0); - seqSpawn(dudeInfo[nType].seqStartID + nSeq, 3, nXSprite, -1); - break; - case kDudeTentacleFire: - sfxPlay3DSound(pSprite, 2501, -1, 0); - seqSpawn(dudeInfo[nType].seqStartID + nSeq, 3, nXSprite, -1); - break; - } - break; - case kDudePodMother: - if (Chance(0x4000) && nSeq == 3) - sfxPlay3DSound(pSprite, 2205, -1, 0); - else - sfxPlay3DSound(pSprite, 2203+Random(2), -1, 0); - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1); - break; - case kDudeTentacleMother: - if (Chance(0x4000) && nSeq == 3) - sfxPlay3DSound(pSprite, 2205, -1, 0); - else - sfxPlay3DSound(pSprite, 2203+Random(2), -1, 0); - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1); - break; - case kDudeCerberusTwoHead: - if (Chance(0x4000) && nSeq == 3) - sfxPlay3DSound(pSprite, 2305, -1, 0); - else - sfxPlay3DSound(pSprite, 2305+Random(2), -1, 0); - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1); - break; - case kDudeCerberusOneHead: - if (Chance(0x4000) && nSeq == 3) - sfxPlay3DSound(pSprite, 2305, -1, 0); - else - sfxPlay3DSound(pSprite, 2305+Random(2), -1, 0); - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1); - break; - case kDudeTchernobog: - sfxPlay3DSound(pSprite, 2380, -1, 0); - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, -1); - break; - case kDudeBurningTinyCaleb: - damageType = DAMAGE_TYPE_3; - seqSpawn(dudeInfo[nType].seqStartID+11, 3, nXSprite, nDudeToGibClient1); - break; - case kDudeBeast: - sfxPlay3DSound(pSprite, 9000+Random(2), -1, 0); - if (nSeq == 3) - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, nDudeToGibClient2); - else - seqSpawn(dudeInfo[nType].seqStartID+nSeq, 3, nXSprite, nDudeToGibClient1); - break; - case kDudeBurningBeast: - damageType = DAMAGE_TYPE_3; - seqSpawn(dudeInfo[nType].seqStartID+12, 3, nXSprite, nDudeToGibClient1); - break; - default: - seqSpawn(getDudeInfo(nType+kDudeBase)->seqStartID+nSeq, 3, nXSprite, -1); - break; - } - - if (damageType == DAMAGE_TYPE_3) - { - DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); - for (int i = 0; i < 3; i++) - if (pDudeInfo->nGibType[i] > -1) - GibSprite(pSprite, (GIBTYPE)pDudeInfo->nGibType[i], NULL, NULL); - for (int i = 0; i < 4; i++) - fxSpawnBlood(pSprite, damage); - } - gKillMgr.AddKill(pSprite); - actCheckRespawn(pSprite); - pSprite->type = kThingBloodChunks; - actPostSprite(pSprite->index, kStatThing); + } + else if (pSprite->type >= kThingBase && pSprite->type < kThingMax) + { + mass = thingInfo[pSprite->type - kThingBase].mass; + } + else + { + Printf(PRINT_HIGH, "Unexpected type in ConcussSprite(): Sprite: %d Type: %d Stat: %d", (int)pSprite->index, (int)pSprite->type, (int)pSprite->statnum); + return; + } + + if (mass > 0) + { + int size = (tileWidth(pSprite->picnum) * pSprite->xrepeat * tileHeight(pSprite->picnum) * pSprite->yrepeat) >> 1; + int t = scale(damage, size, mass); + int nSprite = pSprite->index; + actor->xvel() += MulScale(t, dx, 16); + actor->yvel() += MulScale(t, dy, 16); + actor->zvel() += MulScale(t, dz, 16); + } + } + actDamageSprite(source, actor, DAMAGE_TYPE_3, damage); } -int actDamageSprite(int nSource, spritetype *pSprite, DAMAGE_TYPE damageType, int damage) { - assert(nSource < kMaxSprites); +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- - if (pSprite->flags&32 || pSprite->extra <= 0 || pSprite->extra >= kMaxXSprites || xsprite[pSprite->extra].reference != pSprite->index) - return 0; - - XSPRITE *pXSprite = &xsprite[pSprite->extra]; - if ((pXSprite->health == 0 && pSprite->statnum != kStatDude) || pXSprite->locked) - return 0; - - if (nSource == -1) - nSource = pSprite->index; - - PLAYER *pSourcePlayer = NULL; - if (IsPlayerSprite(&sprite[nSource])) pSourcePlayer = &gPlayer[sprite[nSource].type - kDudePlayer1]; - if (!gGameOptions.bFriendlyFire && IsTargetTeammate(pSourcePlayer, pSprite)) return 0; - - switch (pSprite->statnum) { - case kStatDude: { - if (!IsDudeSprite(pSprite)) { - Printf(PRINT_HIGH, "Bad Dude Failed: initial=%d type=%d %s\n", (int)pSprite->inittype, (int)pSprite->type, (int)(pSprite->flags & kHitagRespawn) ? "RESPAWN" : "NORMAL"); - return damage >> 4; - //I_Error("Bad Dude Failed: initial=%d type=%d %s\n", (int)pSprite->inittype, (int)pSprite->type, (int)(pSprite->flags & 16) ? "RESPAWN" : "NORMAL"); - } - - int nType = pSprite->type - kDudeBase; int nDamageFactor = getDudeInfo(nType+kDudeBase)->at70[damageType]; - #ifdef NOONE_EXTENSIONS - if (pSprite->type == kDudeModernCustom) - nDamageFactor = gGenDudeExtra[pSprite->index].dmgControl[damageType]; - #endif - - if (!nDamageFactor) return 0; - else if (nDamageFactor != 256) - damage = MulScale(damage, nDamageFactor, 8); - - if (!IsPlayerSprite(pSprite)) { - - if (pXSprite->health <= 0) return 0; - damage = aiDamageSprite(pSprite, pXSprite, nSource, damageType, damage); - if (pXSprite->health <= 0) - actKillDude(nSource, pSprite, ((damageType == DAMAGE_TYPE_3 && damage < 160) ? DAMAGE_TYPE_0 : damageType), damage); - - } else { - - PLAYER *pPlayer = &gPlayer[pSprite->type - kDudePlayer1]; - if (pXSprite->health > 0 || playerSeqPlaying(pPlayer, 16)) - damage = playerDamageSprite(nSource, pPlayer, damageType, damage); - - } - } - break; - case kStatThing: - assert(pSprite->type >= kThingBase && pSprite->type < kThingMax); - int nType = pSprite->type - kThingBase; int nDamageFactor = thingInfo[nType].dmgControl[damageType]; - - if (!nDamageFactor) return 0; - else if (nDamageFactor != 256) - damage = MulScale(damage, nDamageFactor, 8); - - pXSprite->health = ClipLow(pXSprite->health - damage, 0); - if (pXSprite->health <= 0) { - switch (pSprite->type) { - case kThingDroppedLifeLeech: - #ifdef NOONE_EXTENSIONS - case kModernThingEnemyLifeLeech: - #endif - GibSprite(pSprite, GIBTYPE_14, NULL, NULL); - pXSprite->data1 = pXSprite->data2 = pXSprite->data3 = pXSprite->DudeLockout = 0; - pXSprite->stateTimer = pXSprite->data4 = pXSprite->isTriggered = 0; - - #ifdef NOONE_EXTENSIONS - if (pSprite->owner >= 0 && sprite[pSprite->owner].type == kDudeModernCustom) - sprite[pSprite->owner].owner = kMaxSprites - 1; // indicates if custom dude had life leech. - #endif - break; - - default: - if (!(pSprite->flags & kHitagRespawn)) - pSprite->owner = nSource; - break; - } - - trTriggerSprite(pSprite->index, pXSprite, kCmdOff); - - switch (pSprite->type) { - case kThingObjectGib: - case kThingObjectExplode: - case kThingBloodBits: - case kThingBloodChunks: - case kThingZombieHead: - if (damageType == 3 && pSourcePlayer && PlayClock > pSourcePlayer->laughCount && Chance(0x4000)) { - sfxPlay3DSound(pSourcePlayer->pSprite, gPlayerGibThingComments[Random(10)], 0, 2); - pSourcePlayer->laughCount = PlayClock+3600; - } - break; - case kTrapMachinegun: - seqSpawn(28, 3, pSprite->extra, -1); - break; - case kThingFluorescent: - seqSpawn(12, 3, pSprite->extra, -1); - GibSprite(pSprite, GIBTYPE_6, NULL, NULL); - break; - case kThingSpiderWeb: - seqSpawn(15, 3, pSprite->extra, -1); - break; - case kThingMetalGrate: - seqSpawn(21, 3, pSprite->extra, -1); - GibSprite(pSprite, GIBTYPE_4, NULL, NULL); - break; - case kThingFlammableTree: - switch (pXSprite->data1) { - case -1: - GibSprite(pSprite, GIBTYPE_14, NULL, NULL); - sfxPlay3DSound(pSprite->x, pSprite->y, pSprite->z, 312, pSprite->sectnum); - actPostSprite(pSprite->index, kStatFree); - break; - case 0: - seqSpawn(25, 3, pSprite->extra, nTreeToGibClient); - sfxPlay3DSound(pSprite, 351, -1, 0); - break; - case 1: - seqSpawn(26, 3, pSprite->extra, nTreeToGibClient); - sfxPlay3DSound(pSprite, 351, -1, 0); - break; - } - break; - } - } - break; - } - - return damage >> 4; +int actWallBounceVector(int* x, int* y, int nWall, int a4) +{ + int wx, wy; + GetWallNormal(nWall, &wx, &wy); + int t = DMulScale(*x, wx, *y, wy, 16); + int t2 = mulscale16r(t, a4 + 0x10000); + *x -= MulScale(wx, t2, 16); + *y -= MulScale(wy, t2, 16); + return mulscale16r(t, 0x10000 - a4); } +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +int actFloorBounceVector(int* x, int* y, int* z, int nSector, int a5) +{ + int t = 0x10000 - a5; + if (sector[nSector].floorheinum == 0) + { + int t2 = MulScale(*z, t, 16); + *z = -(*z - t2); + return t2; + } + walltype* pWall = &wall[sector[nSector].wallptr]; + walltype* pWall2 = &wall[pWall->point2]; + int angle = getangle(pWall2->x - pWall->x, pWall2->y - pWall->y) + 512; + int t2 = sector[nSector].floorheinum << 4; + int t3 = approxDist(-0x10000, t2); + int t4 = DivScale(-0x10000, t3, 16); + int t5 = DivScale(t2, t3, 16); + int t6 = MulScale(t5, Cos(angle), 30); + int t7 = MulScale(t5, Sin(angle), 30); + int t8 = TMulScale(*x, t6, *y, t7, *z, t4, 16); + int t9 = MulScale(t8, 0x10000 + a5, 16); + *x -= MulScale(t6, t9, 16); + *y -= MulScale(t7, t9, 16); + *z -= MulScale(t4, t9, 16); + return mulscale16r(t8, t); +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +void actRadiusDamage(DBloodActor* source, int x, int y, int z, int nSector, int nDist, int baseDmg, int distDmg, DAMAGE_TYPE dmgType, int flags, int burn) +{ + uint8_t sectmap[(kMaxSectors + 7) >> 3]; + auto pOwner = source->GetOwner(); + GetClosestSpriteSectors(nSector, x, y, nDist, sectmap); + nDist <<= 4; + if (flags & 2) + { + BloodStatIterator it(kStatDude); + while (auto act2 = it.Next()) + { + if (act2 != source || (flags & 1)) + { + auto pSprite2 = &act2->s(); + if (act2->hasX()) + { + if (pSprite2->flags & 0x20) continue; + if (!TestBitString(sectmap, pSprite2->sectnum)) continue; + if (!CheckProximity(pSprite2, x, y, z, nSector, nDist)) continue; + + int dx = abs(x - pSprite2->x); + int dy = abs(y - pSprite2->y); + int dz = abs(z - pSprite2->z) >> 4; + int dist = ksqrt(dx * dx + dy * dy + dz * dz); + if (dist > nDist) continue; + + int totaldmg; + if (dist != 0) totaldmg = baseDmg + ((nDist - dist) * distDmg) / nDist; + else totaldmg = baseDmg + distDmg; + + actDamageSprite(source, act2, dmgType, totaldmg << 4); + if (burn) actBurnSprite(pOwner, act2, burn); + } + } + } + } + if (flags & 4) + { + BloodStatIterator it(kStatDude); + while (auto act2 = it.Next()) + { + auto pSprite2 = &act2->s(); + + if (pSprite2->flags & 0x20) continue; + if (!TestBitString(sectmap, pSprite2->sectnum)) continue; + if (!CheckProximity(pSprite2, x, y, z, nSector, nDist)) continue; + + XSPRITE* pXSprite2 = &act2->x(); + if (pXSprite2->locked) continue; + + int dx = abs(x - pSprite2->x); + int dy = abs(y - pSprite2->y); + int dist = ksqrt(dx * dx + dy * dy); + if (dist > nDist) continue; + + int totaldmg; + if (dist != 0) totaldmg = baseDmg + ((nDist - dist) * distDmg) / nDist; + else totaldmg = baseDmg + distDmg; + + actDamageSprite(source, act2, dmgType, totaldmg << 4); + if (burn) actBurnSprite(pOwner, act2, burn); + } + } +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void actNapalmMove(DBloodActor* actor) +{ + auto pXSprite = &actor->x(); + auto pSprite = &actor->s(); + auto pOwner = actor->GetOwner(); + + actPostSprite(actor, kStatDecoration); + seqSpawn(9, actor); + if (Chance(0x8000)) pSprite->cstat |= 4; + + sfxPlay3DSound(pSprite, 303, 24 + (pSprite->flags & 3), 1); + actRadiusDamage(pOwner, pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, 128, 0, 60, DAMAGE_TYPE_3, 15, 120); + + if (pXSprite->data4 > 1) + { + GibSprite(pSprite, GIBTYPE_5, NULL, NULL); + int spawnparam[2]; + spawnparam[0] = pXSprite->data4 >> 1; + spawnparam[1] = pXSprite->data4 - spawnparam[0]; + int ang = pSprite->ang; + actor->xvel() = 0; + actor->yvel() = 0; + actor->zvel() = 0; + for (int i = 0; i < 2; i++) + { + int t1 = Random(0x33333) + 0x33333; + int rndang = Random2(0x71); + pSprite->ang = (rndang + ang + 2048) & 2047; + auto spawned = actFireThing(actor, 0, 0, -0x93d0, kThingNapalmBall, t1); + spawned->SetOwner(actor->GetOwner()); + seqSpawn(61, spawned, nNapalmClient); + spawned->x().data4 = spawnparam[i]; + } + } +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static DBloodActor* actSpawnFloor(DBloodActor* actor) +{ + auto pSprite = &actor->s(); + short sector = pSprite->sectnum; + int x = pSprite->x; + int y = pSprite->y; + updatesector(x, y, §or); + int zFloor = getflorzofslope(sector, x, y); + auto* spawned = actSpawnSprite(sector, x, y, zFloor, 3, 0); + if (spawned) spawned->s().cstat &= ~257; + return spawned; +} + +static DBloodActor* actDropAmmo(DBloodActor* actor, int nType) +{ + if (!actor) return nullptr; + auto pSprite = &actor->s(); + if (pSprite->statnum < kMaxStatus && nType >= kItemAmmoBase && nType < kItemAmmoMax) + { + auto act2 = actSpawnFloor(actor); + const AMMOITEMDATA* pAmmo = &gAmmoItemData[nType - kItemAmmoBase]; + auto pSprite2 = &act2->s(); + pSprite2->type = nType; + pSprite2->picnum = pAmmo->picnum; + pSprite2->shade = pAmmo->shade; + pSprite2->xrepeat = pAmmo->xrepeat; + pSprite2->yrepeat = pAmmo->yrepeat; + return act2; + } + return nullptr; +} + +static DBloodActor* actDropWeapon(DBloodActor* actor, int nType) +{ + if (!actor) return nullptr; + auto pSprite = &actor->s(); + if (pSprite->statnum < kMaxStatus && nType >= kItemWeaponBase && nType < kItemWeaponMax) + { + auto act2 = actSpawnFloor(actor); + const WEAPONITEMDATA* pWeapon = &gWeaponItemData[nType - kItemWeaponBase]; + auto pSprite2 = &act2->s(); + pSprite2->type = nType; + pSprite2->picnum = pWeapon->picnum; + pSprite2->shade = pWeapon->shade; + pSprite2->xrepeat = pWeapon->xrepeat; + pSprite2->yrepeat = pWeapon->yrepeat; + return act2; + } + return nullptr; +} + +static DBloodActor* actDropItem(DBloodActor* actor, int nType) +{ + if (!actor) return nullptr; + auto pSprite = &actor->s(); + if (pSprite->statnum < kMaxStatus && nType >= kItemBase && nType < kItemMax) + { + auto act2 = actSpawnFloor(actor); + const ITEMDATA* pItem = &gItemData[nType - kItemBase]; + auto pSprite2 = &act2->s(); + pSprite2->type = nType; + pSprite2->picnum = pItem->picnum; + pSprite2->shade = pItem->shade; + pSprite2->xrepeat = pItem->xrepeat; + pSprite2->yrepeat = pItem->yrepeat; + return act2; + } + return nullptr; +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static DBloodActor* actDropKey(DBloodActor* actor, int nType) +{ + if (!actor) return nullptr; + auto pSprite = &actor->s(); + if (pSprite->statnum < kMaxStatus && nType >= kItemKeyBase && nType < kItemKeyMax) + { + auto act2 = actDropItem(actor, nType); + if (act2 && gGameOptions.nGameType == 1) + { + act2->addX(); + auto pSprite2 = &act2->s(); + act2->x().respawn = 3; + act2->hit().florhit = 0; + act2->hit().ceilhit = 0; + } + return act2; + } + return nullptr; +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static DBloodActor* actDropFlag(DBloodActor* actor, int nType) +{ + if (!actor) return nullptr; + auto pSprite = &actor->s(); + if (pSprite->statnum < kMaxStatus && (nType == 147 || nType == 148)) + { + auto act2 = actDropItem(actor, nType); + if (act2 && gGameOptions.nGameType == 3) + { + evPost(act2->s().index, 3, 1800, kCallbackReturnFlag); + } + return act2; + } + return nullptr; +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static DBloodActor* actDropObject(DBloodActor* actor, int nType) +{ + DBloodActor* act2 = nullptr; + + if (nType >= kItemKeyBase && nType < kItemKeyMax) act2 = actDropKey(actor, nType); + else if (nType == kItemFlagA || nType == kItemFlagB) act2 = actDropFlag(actor, nType); + else if (nType >= kItemBase && nType < kItemMax) act2 = actDropItem(actor, nType); + else if (nType >= kItemAmmoBase && nType < kItemAmmoMax) act2 = actDropAmmo(actor, nType); + else if (nType >= kItemWeaponBase && nType < kItemWeaponMax) act2 = actDropWeapon(actor, nType); + + if (act2) + { + int top, bottom; + GetActorExtents(act2, &top, &bottom); + if (bottom >= act2->s().z) + act2->s().z -= bottom - act2->s().z; + } + + return act2; +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +bool actHealDude(DBloodActor* actor, int add, int threshold) +{ + if (!actor) return false; + auto pXDude = &actor->x(); + add <<= 4; + threshold <<= 4; + if (pXDude->health < threshold) + { + spritetype* pSprite = &actor->s(); + if (actor->IsPlayerActor()) sfxPlay3DSound(pSprite->x, pSprite->y, pSprite->z, 780, pSprite->sectnum); + pXDude->health = min(pXDude->health + add, threshold); + return true; + } + return false; +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +#ifdef NOONE_EXTENSIONS +static bool actKillModernDude(DBloodActor* actor, DAMAGE_TYPE damageType) +{ + auto pSprite = &actor->s(); + auto pXSprite = &actor->x(); + GENDUDEEXTRA* pExtra = genDudeExtra(pSprite); + removeDudeStuff(pSprite); + if (pXSprite->txID <= 0 || getNextIncarnation(pXSprite) == NULL) + { + if (pExtra->weaponType == kGenDudeWeaponKamikaze && Chance(0x4000) && damageType != DAMAGE_TYPE_5 && damageType != DAMAGE_TYPE_4) + { + doExplosion(pSprite, pXSprite->data1 - kTrapExploder); + if (Chance(0x9000)) damageType = (DAMAGE_TYPE)3; + } + + if (damageType == DAMAGE_TYPE_1) + { + if (pExtra->availDeaths[DAMAGE_TYPE_1] && !spriteIsUnderwater(pSprite)) + { + if (pExtra->canBurn) + { + pSprite->type = kDudeModernCustomBurning; + if (pXSprite->data2 == kGenDudeDefaultSeq) // don't inherit palette for burning if using default animation + pSprite->pal = 0; + + aiGenDudeNewState(pSprite, &genDudeBurnGoto); + actHealDude(pXSprite, dudeInfo[55].startHealth, dudeInfo[55].startHealth); + if (pXSprite->burnTime <= 0) pXSprite->burnTime = 1200; + actor->dudeExtra().time = PlayClock + 360; + return true; + } + + } + else + { + pXSprite->burnTime = 0; + pXSprite->burnSource = -1; + damageType = DAMAGE_TYPE_0; + } + } + } + else + { + pXSprite->locked = 1; // lock while transforming + + aiSetGenIdleState(pSprite, pXSprite); // set idle state + + if (pXSprite->key > 0) // drop keys + actDropObject(pSprite, kItemKeyBase + pXSprite->key - 1); + + if (pXSprite->dropMsg > 0) // drop items + actDropObject(pSprite, pXSprite->dropMsg); + + pSprite->flags &= ~kPhysMove; xvel[pSprite->index] = yvel[pSprite->index] = 0; + + playGenDudeSound(pSprite, kGenDudeSndTransforming); + int seqId = pXSprite->data2 + kGenDudeSeqTransform; + if (getSequence(seqId)) seqSpawn(seqId, actor, -1); + else + { + seqKill(actor); + DBloodActor* pEffectA = gFX.fxSpawnActor((FX_ID)52, pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, pSprite->ang); + if (pEffectA != nullptr) + { + auto pEffect = &pEffectA->s(); + pEffect->cstat = CSTAT_SPRITE_ALIGNMENT_FACING; + pEffect->pal = 6; + pEffect->xrepeat = pSprite->xrepeat; + pEffect->yrepeat = pSprite->yrepeat; + } + + GIBTYPE nGibType; + for (int i = 0; i < 3; i++) + { + if (Chance(0x3000)) nGibType = GIBTYPE_6; + else if (Chance(0x2000)) nGibType = GIBTYPE_5; + else nGibType = GIBTYPE_17; + + int top, bottom; + GetActorExtents(actor, &top, &bottom); + CGibPosition gibPos(pSprite->x, pSprite->y, top); + CGibVelocity gibVel(actor->xvel() >> 1, actor->yvel() >> 1, -0xccccc); + GibSprite(pSprite, nGibType, &gibPos, &gibVel); + } + } + + pXSprite->sysData1 = kGenDudeTransformStatus; // in transform + return true; + } + return false; +} +#endif + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static bool actKillDudeStage1(DBloodActor* actor, DAMAGE_TYPE damageType) +{ + auto pSprite = &actor->s(); + auto pXSprite = &actor->x(); + switch (pSprite->type) + { +#ifdef NOONE_EXTENSIONS + case kDudeModernCustom: + if (actKillModernDude(actor, damageType)) return true; + break; +#endif + case kDudeCerberusTwoHead: // Cerberus + seqSpawn(dudeInfo[pSprite->type - kDudeBase].seqStartID + 1, actor, -1); + return true; + + case kDudeCultistTommy: + case kDudeCultistShotgun: + case kDudeCultistTesla: + case kDudeCultistTNT: + if (damageType == DAMAGE_TYPE_1 && pXSprite->medium == kMediumNormal) + { + pSprite->type = kDudeBurningCultist; + aiNewState(actor, &cultistBurnGoto); + actHealDude(actor, dudeInfo[40].startHealth, dudeInfo[40].startHealth); + return true; + } + break; + + case kDudeBeast: + if (damageType == DAMAGE_TYPE_1 && pXSprite->medium == kMediumNormal) + { + pSprite->type = kDudeBurningBeast; + aiNewState(actor, &beastBurnGoto); + actHealDude(actor, dudeInfo[53].startHealth, dudeInfo[53].startHealth); + return true; + } + break; + + case kDudeInnocent: + if (damageType == DAMAGE_TYPE_1 && pXSprite->medium == kMediumNormal) + { + pSprite->type = kDudeBurningInnocent; + aiNewState(actor, &innocentBurnGoto); + actHealDude(actor, dudeInfo[39].startHealth, dudeInfo[39].startHealth); + return true; + } + break; + } + return false; +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void checkAddFrag(DBloodActor* killerActor, DBloodActor* actor) +{ + auto pKillerSprite = &killerActor->s(); + auto pSprite = &actor->s(); + if (VanillaMode()) + { + if (killerActor->IsPlayerActor()) + { + PLAYER* pPlayer = &gPlayer[pKillerSprite->type - kDudePlayer1]; + if (gGameOptions.nGameType == 1) + pPlayer->fragCount++; + } + } + else if (gGameOptions.nGameType == 1 && killerActor->IsPlayerActor() && pSprite->statnum == kStatDude) + { + switch (pSprite->type) + { + case kDudeBat: + case kDudeRat: + case kDudeInnocent: + case kDudeBurningInnocent: + break; + default: + PLAYER* pKillerPlayer = &gPlayer[pKillerSprite->type - kDudePlayer1]; + pKillerPlayer->fragCount++; + break; + } + + } +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void checkDropObjects(DBloodActor* actor) +{ + auto pXSprite = &actor->x(); + + if (pXSprite->key > 0) actDropObject(actor, kItemKeyBase + pXSprite->key - 1); + if (pXSprite->dropMsg > 0) actDropObject(actor, pXSprite->dropMsg); + + switch (actor->s().type) + { + case kDudeCultistTommy: + { + int nRand = Random(100); + if (nRand < 10) actDropObject(actor, kItemWeaponTommygun); + else if (nRand < 50) actDropObject(actor, kItemAmmoTommygunFew); + break; + } + case kDudeCultistShotgun: + { + int nRand = Random(100); + if (nRand <= 10) actDropObject(actor, kItemWeaponSawedoff); + else if (nRand <= 50) actDropObject(actor, kItemAmmoSawedoffFew); + break; + } + } +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static int checkDamageType(DBloodActor* actor, DAMAGE_TYPE damageType) +{ + int nSeq; + auto pSprite = &actor->s(); + + switch (damageType) + { + case DAMAGE_TYPE_3: + nSeq = 2; + switch (pSprite->type) + { +#ifdef NOONE_EXTENSIONS + case kDudeModernCustom: + case kDudeModernCustomBurning: + { + playGenDudeSound(pSprite, kGenDudeSndDeathExplode); + GENDUDEEXTRA* pExtra = &actor->genDudeExtra(); + if (!pExtra->availDeaths[damageType]) + { + nSeq = 1; + damageType = DAMAGE_TYPE_0; + } + break; + } +#endif + case kDudeCultistTommy: + case kDudeCultistShotgun: + case kDudeCultistTommyProne: + case kDudeBurningInnocent: + case kDudeBurningCultist: + case kDudeInnocent: + case kDudeCultistShotgunProne: + case kDudeCultistTesla: + case kDudeCultistTNT: + case kDudeCultistBeast: + case kDudeTinyCaleb: + case kDudeBurningTinyCaleb: + sfxPlay3DSound(pSprite, 717, -1, 0); + break; + } + break; + case DAMAGE_TYPE_1: + nSeq = 3; + sfxPlay3DSound(pSprite, 351, -1, 0); + break; + case DAMAGE_TYPE_5: + switch (pSprite->type) { + case kDudeZombieAxeNormal: + case kDudeZombieAxeBuried: + nSeq = 14; + break; + case kDudeZombieButcher: + nSeq = 11; + break; + default: + nSeq = 1; + break; + } + break; + case DAMAGE_TYPE_0: + switch (pSprite->type) + { + case kDudeCultistTommy: + case kDudeCultistShotgun: + nSeq = 1; + break; + default: + nSeq = 1; + break; + } + break; + default: + nSeq = 1; + break; + } + return nSeq; +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void spawnGibs(DBloodActor* actor, int type, int velz) +{ + int top, bottom; + GetActorExtents(actor, &top, &bottom); + CGibPosition gibPos(actor->s().x, actor->s().y, top); + CGibVelocity gibVel(actor->xvel() >> 1, actor->yvel() >> 1, velz); + GibSprite(&actor->s(), GIBTYPE_27, &gibPos, &gibVel); +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void zombieAxeNormalDeath(DBloodActor* actor, int nSeq) +{ + auto pSprite = &actor->s(); + int nType = pSprite->type - kDudeBase; + + sfxPlay3DSound(pSprite, 1107 + Random(2), -1, 0); + if (nSeq == 2) + { + seqSpawn(dudeInfo[nType].seqStartID + nSeq, actor, nDudeToGibClient1); + spawnGibs(actor, GIBTYPE_27, -0xccccc); + } + else if (nSeq == 1 && Chance(0x4000)) + { + seqSpawn(dudeInfo[nType].seqStartID + 7, actor, nDudeToGibClient1); + evPost(pSprite->index, 3, 0, kCallbackFXZombieSpurt); + sfxPlay3DSound(pSprite, 362, -1, 0); + actor->x().data1 = 35; + actor->x().data2 = 5; + + spawnGibs(actor, GIBTYPE_27, -0x111111); + } + else if (nSeq == 14)seqSpawn(dudeInfo[nType].seqStartID + nSeq, actor, -1); + else if (nSeq == 3) seqSpawn(dudeInfo[nType].seqStartID + 13, actor, nDudeToGibClient2); + else seqSpawn(dudeInfo[nType].seqStartID + nSeq, actor, nDudeToGibClient1); +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void burningCultistDeath(DBloodActor* actor, int nSeq) +{ + auto pSprite = &actor->s(); + if (Chance(0x4000) && nSeq == 3) sfxPlay3DSound(pSprite, 718, -1, 0); + else sfxPlay3DSound(pSprite, 1018 + Random(2), -1, 0); + + int nType = pSprite->type - kDudeBase; + if (Chance(0x8000)) + { + for (int i = 0; i < 3; i++) + GibSprite(pSprite, GIBTYPE_7, NULL, NULL); + seqSpawn(dudeInfo[nType].seqStartID + 16 - Random(1), actor, nDudeToGibClient1); + } + else + seqSpawn(dudeInfo[nType].seqStartID + 15, actor, nDudeToGibClient2); +} + +#ifdef NOONE_EXTENSIONS +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void modernCustomDudeDeath(DBloodActor* actor, int nSeq, int damageType) +{ + auto pSprite = &actor->s(); + auto pXSprite = &actor->x(); + + playGenDudeSound(pSprite, kGenDudeSndDeathNormal); + int dudeToGib = (actCheckRespawn(pSprite)) ? -1 : ((nSeq == 3) ? nDudeToGibClient2 : nDudeToGibClient1); + if (nSeq == 3) + { + GENDUDEEXTRA* pExtra = genDudeExtra(pSprite); + if (pExtra->availDeaths[kDmgBurn] == 3) seqSpawn((15 + Random(2)) + pXSprite->data2, actor, dudeToGib); + else if (pExtra->availDeaths[kDmgBurn] == 2) seqSpawn(16 + pXSprite->data2, actor, dudeToGib); + else if (pExtra->availDeaths[kDmgBurn] == 1) seqSpawn(15 + pXSprite->data2, actor, dudeToGib); + else if (getSequence(pXSprite->data2 + nSeq))seqSpawn(nSeq + pXSprite->data2, actor, dudeToGib); + else seqSpawn(1 + pXSprite->data2, actor, dudeToGib); + + } + else + { + seqSpawn(nSeq + pXSprite->data2, actor, dudeToGib); + } +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void modernCustomDudeBurningDeath(DBloodActor* actor, int nSeq) +{ + auto pSprite = &actor->s(); + + playGenDudeSound(pSprite, kGenDudeSndDeathExplode); + int dudeToGib = (actCheckRespawn(pSprite)) ? -1 : nDudeToGibClient1; + + if (Chance(0x4000)) spawnGibs(actor, GIBTYPE_27, -0xccccc); + + GENDUDEEXTRA* pExtra = &actor->genDudeExtra(); + int seqofs = actor->x().data2; + if (pExtra->availDeaths[kDmgBurn] == 3) seqSpawn((15 + Random(2)) + seqofs, actor, dudeToGib); + else if (pExtra->availDeaths[kDmgBurn] == 2) seqSpawn(16 + seqofs, actor, dudeToGib); + else if (pExtra->availDeaths[kDmgBurn] == 1) seqSpawn(15 + seqofs, actor, dudeToGib); + else seqSpawn(1 + seqofs, actor, dudeToGib); +} +#endif + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +void zombieAxeBurningDeath(DBloodActor* actor, int nSeq) +{ + auto pSprite = &actor->s(); + int nType = pSprite->type - kDudeBase; + + if (Chance(0x8000) && nSeq == 3) + sfxPlay3DSound(pSprite, 1109, -1, 0); + else + sfxPlay3DSound(pSprite, 1107 + Random(2), -1, 0); + + if (Chance(0x8000)) + { + seqSpawn(dudeInfo[nType].seqStartID + 13, actor, nDudeToGibClient1); + spawnGibs(actor, GIBTYPE_27, -0xccccc); + } + else + seqSpawn(dudeInfo[nType].seqStartID + 13, actor, nDudeToGibClient2); +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void zombieButcherDeath(DBloodActor* actor, int nSeq) +{ + auto pSprite = &actor->s(); + int nType = pSprite->type - kDudeBase; + + if (nSeq == 14) + { + sfxPlay3DSound(pSprite, 1206, -1, 0); + seqSpawn(dudeInfo[nType].seqStartID + 11, actor, -1); + return; + } + sfxPlay3DSound(pSprite, 1204 + Random(2), -1, 0); + if (nSeq == 3) + seqSpawn(dudeInfo[nType].seqStartID + 10, actor, -1); + else + seqSpawn(dudeInfo[nType].seqStartID + nSeq, actor, -1); +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static void genericDeath(DBloodActor* actor, int nSeq, int sound1, int seqnum) +{ + auto pSprite = &actor->s(); + if (Chance(0x4000) && nSeq == 3) sfxPlay3DSound(pSprite, sound1 + 2, -1, 0); + else sfxPlay3DSound(pSprite, sound1 + Random(2), -1, 0); + seqSpawn(seqnum, actor, -1); +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +void actKillDude(DBloodActor* killerActor, DBloodActor* actor, DAMAGE_TYPE damageType, int damage) +{ + spritetype* pKillerSprite = &killerActor->s(); + auto pSprite = &actor->s(); + assert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax&& actor->hasX()); + int nType = pSprite->type - kDudeBase; + XSPRITE* pXSprite = &actor->x(); + + if (actKillDudeStage1(actor, damageType)) return; + + for (int p = connecthead; p >= 0; p = connectpoint2[p]) + { + if (gPlayer[p].fragger() == actor && gPlayer[p].deathTime > 0) + gPlayer[p].setFragger(nullptr); + } + if (pSprite->type != kDudeCultistBeast) + trTriggerSprite(pSprite->index, pXSprite, kCmdOff); + + pSprite->flags |= 7; + checkAddFrag(killerActor, actor); + checkDropObjects(actor); + + int nSeq = checkDamageType(actor, damageType); + + if (!getSequence(getDudeInfo(nType + kDudeBase)->seqStartID + nSeq)) + { + seqKill(actor); + gKillMgr.AddKill(pSprite); + actPostSprite(actor, kStatFree); + return; + } + + switch (pSprite->type) + { + case kDudeZombieAxeNormal: + zombieAxeNormalDeath(actor, nSeq); + break; + + case kDudeCultistTommy: + case kDudeCultistShotgun: + case kDudeCultistTesla: + case kDudeCultistTNT: + sfxPlay3DSound(pSprite, 1018 + Random(2), -1, 0); + seqSpawn(dudeInfo[nType].seqStartID + nSeq, actor, nSeq == 3 ? nDudeToGibClient2 : nDudeToGibClient1); + break; + + case kDudeBurningCultist: + burningCultistDeath(actor, nSeq); + damageType = DAMAGE_TYPE_3; + break; + +#ifdef NOONE_EXTENSIONS + case kDudeModernCustom: + modernCustomDudeDeath(actor, nSeq, damageType); + genDudePostDeath(pSprite, damageType, damage); + return; + + case kDudeModernCustomBurning: + modernCustomDudeBurningDeath(actor, nSeq); + genDudePostDeath(pSprite, DAMAGE_TYPE_3, damage); + return; +#endif + + case kDudeBurningZombieAxe: + zombieAxeBurningDeath(actor, nSeq); + damageType = DAMAGE_TYPE_3; + break; + + case kDudeBurningZombieButcher: + genericDeath(actor, nSeq, 1204, dudeInfo[4].seqStartID + 10); + break; + + case kDudeBurningInnocent: + damageType = DAMAGE_TYPE_3; + seqSpawn(dudeInfo[nType].seqStartID + 7, actor, nDudeToGibClient1); + break; + + case kDudeZombieButcher: + zombieButcherDeath(actor, nSeq); + break; + + case kDudeGargoyleFlesh: + genericDeath(actor, nSeq, 1403, dudeInfo[nType].seqStartID + nSeq); + break; + + case kDudeGargoyleStone: + genericDeath(actor, nSeq, 1453, dudeInfo[nType].seqStartID + nSeq); + break; + + case kDudePhantasm: + genericDeath(actor, nSeq, 1603, dudeInfo[nType].seqStartID + nSeq); + break; + + case kDudeHellHound: + genericDeath(actor, nSeq, 1303, dudeInfo[nType].seqStartID + nSeq); + break; + + case kDudeHand: + genericDeath(actor, nSeq, 1903, dudeInfo[nType].seqStartID + nSeq); + break; + + case kDudeSpiderBrown: + if (pSprite->owner != -1) + { + spritetype* pOwner = &sprite[pSprite->owner]; + gDudeExtra[pOwner->extra].at6.u1.xval2--; + } + genericDeath(actor, nSeq, 1803, dudeInfo[nType].seqStartID + nSeq); + break; + + case kDudeSpiderRed: + if (pSprite->owner != -1) + { + spritetype* pOwner = &sprite[pSprite->owner]; + gDudeExtra[pOwner->extra].at6.u1.xval2--; + } + genericDeath(actor, nSeq, 1803, dudeInfo[nType].seqStartID + nSeq); + break; + + case kDudeSpiderBlack: + if (pSprite->owner != -1) + { + spritetype* pOwner = &sprite[pSprite->owner]; + gDudeExtra[pOwner->extra].at6.u1.xval2--; + } + genericDeath(actor, nSeq, 1803, dudeInfo[nType].seqStartID + nSeq); + break; + + case kDudeSpiderMother: + sfxPlay3DSound(pSprite, 1850, -1, 0); + seqSpawn(dudeInfo[nType].seqStartID + nSeq, actor, -1); + break; + + case kDudeGillBeast: + genericDeath(actor, nSeq, 1703, dudeInfo[nType].seqStartID + nSeq); + break; + + case kDudeBoneEel: + genericDeath(actor, nSeq, 1503, dudeInfo[nType].seqStartID + nSeq); + break; + + case kDudeBat: + genericDeath(actor, nSeq, 2003, dudeInfo[nType].seqStartID + nSeq); + break; + + case kDudeRat: + genericDeath(actor, nSeq, 2103, dudeInfo[nType].seqStartID + nSeq); + break; + + case kDudePodGreen: + case kDudeTentacleGreen: + case kDudePodFire: + case kDudeTentacleFire: + if ((pSprite->cstat & CSTAT_SPRITE_YFLIP)) pSprite->cstat &= ~CSTAT_SPRITE_YFLIP; + switch (pSprite->type) + { + case kDudePodGreen: + genericDeath(actor, nSeq, 2203, dudeInfo[nType].seqStartID + nSeq); + break; + case kDudeTentacleGreen: + sfxPlay3DSound(pSprite, damage == 5 ? 2471 : 2472, -1, 0); + seqSpawn(dudeInfo[nType].seqStartID + nSeq, actor, -1); + break; + case kDudePodFire: + sfxPlay3DSound(pSprite, damage == 5 ? 2451 : 2452, -1, 0); + seqSpawn(dudeInfo[nType].seqStartID + nSeq, actor, -1); + break; + case kDudeTentacleFire: + sfxPlay3DSound(pSprite, 2501, -1, 0); + seqSpawn(dudeInfo[nType].seqStartID + nSeq, actor, -1); + break; + } + break; + + case kDudePodMother: + case kDudeTentacleMother: + genericDeath(actor, nSeq, 2203, dudeInfo[nType].seqStartID + nSeq); + break; + + case kDudeCerberusTwoHead: + case kDudeCerberusOneHead: + genericDeath(actor, nSeq, 2303, dudeInfo[nType].seqStartID + nSeq); + break; + + case kDudeTchernobog: + sfxPlay3DSound(pSprite, 2380, -1, 0); + seqSpawn(dudeInfo[nType].seqStartID + nSeq, actor, -1); + break; + + case kDudeBurningTinyCaleb: + damageType = DAMAGE_TYPE_3; + seqSpawn(dudeInfo[nType].seqStartID + 11, actor, nDudeToGibClient1); + break; + + case kDudeBeast: + sfxPlay3DSound(pSprite, 9000 + Random(2), -1, 0); + seqSpawn(dudeInfo[nType].seqStartID + nSeq, actor, nSeq == 3 ? nDudeToGibClient2 : nDudeToGibClient1); + break; + + case kDudeBurningBeast: + damageType = DAMAGE_TYPE_3; + seqSpawn(dudeInfo[nType].seqStartID + 12, actor, nDudeToGibClient1); + break; + + default: + seqSpawn(getDudeInfo(nType + kDudeBase)->seqStartID + nSeq, actor, -1); + break; + } + + if (damageType == DAMAGE_TYPE_3) + { + DUDEINFO* pDudeInfo = getDudeInfo(pSprite->type); + for (int i = 0; i < 3; i++) + if (pDudeInfo->nGibType[i] > -1) + GibSprite(pSprite, (GIBTYPE)pDudeInfo->nGibType[i], nullptr, nullptr); + for (int i = 0; i < 4; i++) + fxSpawnBlood(pSprite, damage); + } + gKillMgr.AddKill(pSprite); + actCheckRespawn(pSprite); + pSprite->type = kThingBloodChunks; + actPostSprite(actor, kStatThing); +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static int actDamageDude(DBloodActor* source, DBloodActor* actor, int damage, DAMAGE_TYPE damageType) +{ + auto pSprite = &actor->s(); + XSPRITE* pXSprite = &actor->x(); + + if (!actor->IsDudeActor()) + { + Printf(PRINT_HIGH, "Bad Dude Failed: initial=%d type=%d %s\n", (int)pSprite->inittype, (int)pSprite->type, (int)(pSprite->flags & kHitagRespawn) ? "RESPAWN" : "NORMAL"); + return damage >> 4; + //I_Error("Bad Dude Failed: initial=%d type=%d %s\n", (int)pSprite->inittype, (int)pSprite->type, (int)(pSprite->flags & 16) ? "RESPAWN" : "NORMAL"); + } + + int nType = pSprite->type - kDudeBase; + int nDamageFactor = getDudeInfo(nType + kDudeBase)->damageVal[damageType]; +#ifdef NOONE_EXTENSIONS + if (pSprite->type == kDudeModernCustom) + nDamageFactor = actor->genDudeExtra().dmgControl[damageType]; +#endif + + if (!nDamageFactor) return 0; + else if (nDamageFactor != 256) damage = MulScale(damage, nDamageFactor, 8); + + if (!IsPlayerSprite(pSprite)) + { + if (pXSprite->health <= 0) return 0; + damage = aiDamageSprite(source, actor, damageType, damage); + if (pXSprite->health <= 0) + actKillDude(source, actor, ((damageType == DAMAGE_TYPE_3 && damage < 160) ? DAMAGE_TYPE_0 : damageType), damage); + } + else + { + PLAYER* pPlayer = &gPlayer[pSprite->type - kDudePlayer1]; + if (pXSprite->health > 0 || playerSeqPlaying(pPlayer, 16)) + damage = playerDamageSprite(source, pPlayer, damageType, damage); + + } + return damage; +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +static int actDamageThing(DBloodActor* source, DBloodActor* actor, int damage, DAMAGE_TYPE damageType, PLAYER* pSourcePlayer) +{ + auto pSprite = &actor->s(); + XSPRITE* pXSprite = &actor->x(); + + assert(pSprite->type >= kThingBase && pSprite->type < kThingMax); + int nType = pSprite->type - kThingBase; + int nDamageFactor = thingInfo[nType].dmgControl[damageType]; + + if (!nDamageFactor) return 0; + else if (nDamageFactor != 256) damage = MulScale(damage, nDamageFactor, 8); + + pXSprite->health = ClipLow(pXSprite->health - damage, 0); + if (pXSprite->health <= 0) + { + auto Owner = actor->GetOwner(); + switch (pSprite->type) + { + case kThingDroppedLifeLeech: +#ifdef NOONE_EXTENSIONS + case kModernThingEnemyLifeLeech: +#endif + GibSprite(pSprite, GIBTYPE_14, NULL, NULL); + pXSprite->data1 = pXSprite->data2 = pXSprite->data3 = pXSprite->DudeLockout = 0; + pXSprite->stateTimer = pXSprite->data4 = pXSprite->isTriggered = 0; + +#ifdef NOONE_EXTENSIONS + if (Owner && Owner->s().type == kDudeModernCustom) + Owner->SetSpecialOwner(); // indicates if custom dude had life leech. +#endif + break; + + default: + if (!(pSprite->flags & kHitagRespawn)) + actor->SetOwner(source); + break; + } + + trTriggerSprite(pSprite->index, pXSprite, kCmdOff); + + switch (pSprite->type) + { + case kThingObjectGib: + case kThingObjectExplode: + case kThingBloodBits: + case kThingBloodChunks: + case kThingZombieHead: + if (damageType == 3 && pSourcePlayer && PlayClock > pSourcePlayer->laughCount && Chance(0x4000)) + { + sfxPlay3DSound(pSourcePlayer->pSprite, gPlayerGibThingComments[Random(10)], 0, 2); + pSourcePlayer->laughCount = PlayClock + 3600; + } + break; + case kTrapMachinegun: + seqSpawn(28, 3, pSprite->extra, -1); + break; + + case kThingFluorescent: + seqSpawn(12, 3, pSprite->extra, -1); + GibSprite(pSprite, GIBTYPE_6, NULL, NULL); + break; + + case kThingSpiderWeb: + seqSpawn(15, 3, pSprite->extra, -1); + break; + + case kThingMetalGrate: + seqSpawn(21, 3, pSprite->extra, -1); + GibSprite(pSprite, GIBTYPE_4, NULL, NULL); + break; + + case kThingFlammableTree: + switch (pXSprite->data1) + { + case -1: + GibSprite(pSprite, GIBTYPE_14, NULL, NULL); + sfxPlay3DSound(pSprite->x, pSprite->y, pSprite->z, 312, pSprite->sectnum); + actPostSprite(actor, kStatFree); + break; + + case 0: + seqSpawn(25, actor, nTreeToGibClient); + sfxPlay3DSound(pSprite, 351, -1, 0); + break; + + case 1: + seqSpawn(26, 3, pSprite->extra, nTreeToGibClient); + sfxPlay3DSound(pSprite, 351, -1, 0); + break; + } + break; + } + } + return damage; +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + +int actDamageSprite(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE damageType, int damage) +{ + auto pSprite = &actor->s(); + + if (pSprite->flags & 32 || !actor->hasX()) + return 0; + + XSPRITE* pXSprite = &actor->x(); + if ((pXSprite->health == 0 && pSprite->statnum != kStatDude) || pXSprite->locked) + return 0; + + if (source == nullptr) source = actor; + + PLAYER* pSourcePlayer = NULL; + if (source->IsPlayerActor()) pSourcePlayer = &gPlayer[source->s().type - kDudePlayer1]; + if (!gGameOptions.bFriendlyFire && IsTargetTeammate(pSourcePlayer, pSprite)) return 0; + + switch (pSprite->statnum) + { + case kStatDude: + damage = actDamageDude(source, actor, damage, damageType); + break; + case kStatThing: + damage = actDamageThing(source, actor, damage, damageType, pSourcePlayer); + break; + } + + return damage >> 4; +} + +//--------------------------------------------------------------------------- +// +// +// +//--------------------------------------------------------------------------- + void actHitcodeToData(int a1, HITINFO *pHitInfo, int *a3, spritetype **a4, XSPRITE **a5, int *a6, walltype **a7, XWALL **a8, int *a9, sectortype **a10, XSECTOR **a11) { assert(pHitInfo != NULL); @@ -3687,7 +3942,7 @@ void actImpactMissile(spritetype *pMissile, int hitCode) DAMAGE_TYPE rand1 = (DAMAGE_TYPE)Random(7); int rand2 = (7 + Random(7)) << 4; int nDamage = actDamageSprite(nOwner, pSpriteHit, rand1, rand2); - if ((pThingInfo && pThingInfo->dmgControl[DAMAGE_TYPE_1] != 0) || (pDudeInfo && pDudeInfo->at70[DAMAGE_TYPE_1] != 0)) + if ((pThingInfo && pThingInfo->dmgControl[DAMAGE_TYPE_1] != 0) || (pDudeInfo && pDudeInfo->damageVal[DAMAGE_TYPE_1] != 0)) actBurnSprite(pMissile->owner, pXSpriteHit, 360); // by NoOne: make Life Leech heal user, just like it was in 1.0x versions @@ -3779,12 +4034,12 @@ void actImpactMissile(spritetype *pMissile, int hitCode) sfxKill3DSound(pMissile, -1, -1); if ((hitCode == 3 && pSpriteHit) && (pThingInfo || pDudeInfo)) { int nOwner = pMissile->owner; - if ((pThingInfo && pThingInfo->dmgControl[DAMAGE_TYPE_1] != 0) || (pDudeInfo && pDudeInfo->at70[DAMAGE_TYPE_1] != 0)) { + if ((pThingInfo && pThingInfo->dmgControl[DAMAGE_TYPE_1] != 0) || (pDudeInfo && pDudeInfo->damageVal[DAMAGE_TYPE_1] != 0)) { if (pThingInfo && pSpriteHit->type == kThingTNTBarrel && pXSpriteHit->burnTime == 0) evPost(nSpriteHit, 3, 0, kCallbackFXFlameLick); actBurnSprite(pMissile->owner, pXSpriteHit, 480); - sub_2A620(nOwner, pMissile->x, pMissile->y, pMissile->z, pMissile->sectnum, 16, 20, 10, DAMAGE_TYPE_2, 6, 480, 0, 0); + actRadiusDamage(&bloodActors[nOwner], pMissile->x, pMissile->y, pMissile->z, pMissile->sectnum, 16, 20, 10, DAMAGE_TYPE_2, 6, 480); // by NoOne: allow additional bullet damage for Flare Gun if (gGameOptions.weaponsV10x && !VanillaMode() && !DemoRecordStatus()) { @@ -4424,7 +4679,7 @@ int MoveThing(spritetype *pSprite) switch (pSprite->type) { case kThingNapalmBall: - if (zvel[nSprite] == 0 || Chance(0xA000)) sub_2AA94(&bloodActors[pXSprite->reference]); + if (zvel[nSprite] == 0 || Chance(0xA000)) actNapalmMove(&bloodActors[pXSprite->reference]); break; case kThingZombieHead: if (abs(zvel[nSprite]) > 0x80000) { @@ -4714,11 +4969,11 @@ void MoveDude(spritetype *pSprite) switch (nLink) { case kMarkerLowStack: if (pPlayer == gView) - SetBitString(gotpic, sector[pSprite->sectnum].floorpicnum); + setgotpic(sector[pSprite->sectnum].floorpicnum); break; case kMarkerUpStack: if (pPlayer == gView) - SetBitString(gotpic, sector[pSprite->sectnum].ceilingpicnum); + setgotpic(sector[pSprite->sectnum].ceilingpicnum); break; case kMarkerLowWater: case kMarkerLowGoo: @@ -5268,7 +5523,7 @@ void actExplodeSprite(spritetype *pSprite) break; case kThingTNTBarrel: { - spritetype *pSprite2 = actSpawnSprite(pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, 0, 1); + spritetype *pSprite2 = actSpawnSprite_(pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, 0, 1); pSprite2->owner = pSprite->owner; if (actCheckRespawn(pSprite)) { @@ -5599,7 +5854,7 @@ void actProcessSprites(void) case kThingPodGreenBall: if ((hit&0xc000) == 0x4000) { - sub_2A620(pSprite->owner, pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, 200, 1, 20, DAMAGE_TYPE_3, 6, 0, 0, 0); + actRadiusDamage(&bloodActors[pSprite->owner], pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, 200, 1, 20, DAMAGE_TYPE_3, 6, 0); evPost(pSprite->index, 3, 0, kCallbackFXPodBloodSplat); } else @@ -5649,6 +5904,7 @@ void actProcessSprites(void) if (pSprite->flags & 32) continue; int nOwner = pSprite->owner; + auto pOwner = nOwner == -1? nullptr : &bloodActors[pSprite->owner]; int nType = pSprite->type; assert(nType >= 0 && nType < kExplodeMax); const EXPLOSION *pExplodeInfo = &explodeInfo[nType]; @@ -5684,7 +5940,8 @@ void actProcessSprites(void) StatIterator it1(kStatDude); while ((nSprite2 = it1.NextIndex()) >= 0) { - spritetype *pDude = &sprite[nSprite2]; + DBloodActor* act2 = &bloodActors[nSprite2]; + spritetype *pDude = &act2->s(); if (pDude->flags & 32) continue; @@ -5698,7 +5955,7 @@ void actProcessSprites(void) actDamageSprite(nOwner, pDude, DAMAGE_TYPE_0, (pExplodeInfo->dmg+Random(pExplodeInfo->dmgRng))<<4); } if (pExplodeInfo->dmgType) - ConcussSprite(nOwner, pDude, x, y, z, pExplodeInfo->dmgType); + ConcussSprite(pOwner, act2, x, y, z, pExplodeInfo->dmgType); if (pExplodeInfo->burnTime) { assert(pDude->extra > 0 && pDude->extra < kMaxXSprites); @@ -5714,6 +5971,7 @@ void actProcessSprites(void) it1.Reset(kStatThing); while ((nSprite2 = it1.NextIndex()) >= 0) { + auto act2 = &bloodActors[nSprite2]; spritetype *pThing = &sprite[nSprite2]; if (pThing->flags & 32) @@ -5726,7 +5984,7 @@ void actProcessSprites(void) if (!pXSprite2->locked) { if (pExplodeInfo->dmgType) - ConcussSprite(nOwner, pThing, x, y, z, pExplodeInfo->dmgType); + ConcussSprite(pOwner, act2, x, y, z, pExplodeInfo->dmgType); if (pExplodeInfo->burnTime) { assert(pThing->extra > 0 && pThing->extra < kMaxXSprites); @@ -6041,7 +6299,7 @@ void actProcessSprites(void) gFX.fxProcess(); } -spritetype * actSpawnSprite(int nSector, int x, int y, int z, int nStat, char a6) +spritetype * actSpawnSprite_(int nSector, int x, int y, int z, int nStat, char a6) { int nSprite = InsertSprite(nSector, nStat); if (nSprite >= 0) @@ -6070,6 +6328,12 @@ spritetype * actSpawnSprite(int nSector, int x, int y, int z, int nStat, char a6 return pSprite; } +DBloodActor* actSpawnSprite(int nSector, int x, int y, int z, int nStat, bool a6) +{ + auto spr = actSpawnSprite_(nSector, x, y, z, nStat, a6); + return &bloodActors[spr->index]; +} + spritetype * actSpawnSprite(spritetype *pSource, int nStat); spritetype *actSpawnDude(spritetype *pSource, short nType, int a3, int a4) @@ -6166,7 +6430,7 @@ spritetype * actSpawnSprite(spritetype *pSource, int nStat) spritetype * actSpawnThing(int nSector, int x, int y, int z, int nThingType) { assert(nThingType >= kThingBase && nThingType < kThingMax); - spritetype *pSprite = actSpawnSprite(nSector, x, y, z, 4, 1); + spritetype *pSprite = actSpawnSprite_(nSector, x, y, z, 4, 1); int nType = nThingType-kThingBase; int nThing = pSprite->index; int nXThing = pSprite->extra; @@ -6248,7 +6512,7 @@ spritetype * actSpawnThing(int nSector, int x, int y, int z, int nThingType) return pSprite; } -spritetype * actFireThing(spritetype *pSprite, int a2, int a3, int a4, int thingType, int a6) +spritetype * actFireThing_(spritetype *pSprite, int a2, int a3, int a4, int thingType, int a6) { assert(thingType >= kThingBase && thingType < kThingMax); int x = pSprite->x+MulScale(a2, Cos(pSprite->ang+512), 30); @@ -6273,6 +6537,12 @@ spritetype * actFireThing(spritetype *pSprite, int a2, int a3, int a4, int thing return pThing; } +DBloodActor* actFireThing(DBloodActor* pSprite, int a2, int a3, int a4, int thingType, int a6) +{ + auto spr = actFireThing_(&pSprite->s(), a2, a3, a4, thingType, a6); + return &bloodActors[spr->index]; +} + spritetype* actFireMissile(spritetype *pSprite, int a2, int a3, int a4, int a5, int a6, int nType) { @@ -6301,7 +6571,7 @@ spritetype* actFireMissile(spritetype *pSprite, int a2, int a3, int a4, int a5, y = gHitInfo.hity-MulScale(pMissileInfo->clipDist<<1, Sin(pSprite->ang), 28); } } - spritetype *pMissile = actSpawnSprite(pSprite->sectnum, x, y, z, 5, 1); + spritetype *pMissile = actSpawnSprite_(pSprite->sectnum, x, y, z, 5, 1); int nMissile = pMissile->index; show2dsprite.Set(nMissile); pMissile->type = nType; @@ -6862,6 +7132,11 @@ void actPostSprite(int nSprite, int nStatus) gPost[n].status = nStatus; } +void actPostSprite(DBloodActor* actor, int status) +{ + actPostSprite(actor->s().index, status); +} + void actPostProcess(void) { for (int i = 0; i < gPostCount; i++) @@ -6957,10 +7232,31 @@ void SerializeActor(FSerializer& arc) { for (int i = 0; i < kDudeMax - kDudeBase; i++) for (int j = 0; j < 7; j++) - dudeInfo[i].at70[j] = MulScale(DudeDifficulty[gGameOptions.nDifficulty], dudeInfo[i].startDamage[j], 8); + dudeInfo[i].damageVal[j] = MulScale(DudeDifficulty[gGameOptions.nDifficulty], dudeInfo[i].startDamage[j], 8); } } } +spritetype* actDropObject(spritetype* pSprite, int nType) +{ + auto act = actDropObject(&bloodActors[pSprite->index], nType); + return act ? &act->s() : nullptr; +} + +bool actHealDude(XSPRITE* pXDude, int a2, int a3) +{ + return actHealDude(&bloodActors[pXDude->reference], a2, a3); +} + +void actKillDude(int a1, spritetype* pSprite, DAMAGE_TYPE a3, int a4) +{ + actKillDude(&bloodActors[a1], &bloodActors[pSprite->index], a3, a4); +} + +int actDamageSprite(int nSource, spritetype* pSprite, DAMAGE_TYPE damageType, int damage) +{ + return actDamageSprite(nSource == -1 ? nullptr : &bloodActors[nSource], &bloodActors[pSprite->index], damageType, damage); +} + END_BLD_NS diff --git a/source/games/blood/src/actor.h b/source/games/blood/src/actor.h index 28a80be2c..34fa07c5a 100644 --- a/source/games/blood/src/actor.h +++ b/source/games/blood/src/actor.h @@ -211,21 +211,16 @@ void actDoLight(int spriteNum); bool IsUnderwaterSector(int nSector); void actInit(bool bSaveLoad); -void ConcussSprite(int a1, spritetype *pSprite, int x, int y, int z, int a6); int actWallBounceVector(int *x, int *y, int nWall, int a4); int actFloorBounceVector(int *x, int *y, int *z, int nSector, int a5); -void sub_2A620(int nSprite, int x, int y, int z, int nSector, int nDist, int a7, int a8, DAMAGE_TYPE a9, int a10, int a11, int a12, int a13); -void sub_2AA94(DBloodActor *actor); -spritetype *actSpawnFloor(spritetype *pSprite); -spritetype *actDropAmmo(spritetype *pSprite, int nType); -spritetype *actDropWeapon(spritetype *pSprite, int nType); -spritetype *actDropItem(spritetype *pSprite, int nType); -spritetype *actDropKey(spritetype *pSprite, int nType); -spritetype *actDropFlag(spritetype *pSprite, int nType); +void actRadiusDamage(DBloodActor* source, int x, int y, int z, int nSector, int nDist, int a7, int a8, DAMAGE_TYPE a9, int a10, int a11); spritetype *actDropObject(spritetype *pSprite, int nType); +bool actHealDude(DBloodActor* pXDude, int a2, int a3); bool actHealDude(XSPRITE *pXDude, int a2, int a3); +void actKillDude(DBloodActor* a1, DBloodActor* pSprite, DAMAGE_TYPE a3, int a4); void actKillDude(int a1, spritetype *pSprite, DAMAGE_TYPE a3, int a4); int actDamageSprite(int nSource, spritetype *pSprite, DAMAGE_TYPE a3, int a4); +int actDamageSprite(DBloodActor* pSource, DBloodActor* pTarget, DAMAGE_TYPE damageType, int damage); void actHitcodeToData(int a1, HITINFO *pHitInfo, int *a3, spritetype **a4, XSPRITE **a5, int *a6, walltype **a7, XWALL **a8, int *a9, sectortype **a10, XSECTOR **a11); void actImpactMissile(spritetype *pMissile, int hitCode); void actKickObject(spritetype *pSprite1, spritetype *pSprite2); @@ -239,17 +234,21 @@ void actExplodeSprite(spritetype *pSprite); void actActivateGibObject(DBloodActor *actor); bool IsUnderWater(spritetype *pSprite); void actProcessSprites(void); -spritetype * actSpawnSprite(int nSector, int x, int y, int z, int nStat, char a6); +spritetype * actSpawnSprite_(int nSector, int x, int y, int z, int nStat, char a6); +DBloodActor* actSpawnSprite(int nSector, int x, int y, int z, int nStat, bool a6); spritetype *actSpawnDude(spritetype *pSource, short nType, int a3, int a4); spritetype * actSpawnSprite(spritetype *pSource, int nStat); spritetype * actSpawnThing(int nSector, int x, int y, int z, int nThingType); -spritetype * actFireThing(spritetype *pSprite, int a2, int a3, int a4, int thingType, int a6); +spritetype * actFireThing_(spritetype *pSprite, int a2, int a3, int a4, int thingType, int a6); +DBloodActor* actFireThing(DBloodActor* pSprite, int a2, int a3, int a4, int thingType, int a6); + spritetype* actFireMissile(spritetype *pSprite, int a2, int a3, int a4, int a5, int a6, int nType); int actGetRespawnTime(spritetype *pSprite); bool actCheckRespawn(spritetype *pSprite); bool actCanSplatWall(int nWall); void actFireVector(spritetype *pShooter, int a2, int a3, int a4, int a5, int a6, VECTOR_TYPE vectorType); void actPostSprite(int nSprite, int nStatus); +void actPostSprite(DBloodActor* actor, int status); void actPostProcess(void); void MakeSplash(DBloodActor *actor); void actBuildMissile(spritetype* pMissile, int nXSprite, int nSprite); diff --git a/source/games/blood/src/ai.cpp b/source/games/blood/src/ai.cpp index 3bde01d66..beac0ff94 100644 --- a/source/games/blood/src/ai.cpp +++ b/source/games/blood/src/ai.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "build.h" #include "savegamehelp.h" -#include "mmulti.h" #include "blood.h" @@ -93,7 +92,7 @@ bool isImmune(spritetype* pSprite, int dmgType, int minScale) else if (IsDudeSprite(pSprite)) { if (IsPlayerSprite(pSprite)) return (gPlayer[pSprite->type - kDudePlayer1].godMode || gPlayer[pSprite->type - kDudePlayer1].damageControl[dmgType] <= minScale); - else return (dudeInfo[pSprite->type - kDudeBase].at70[dmgType] <= minScale); + else return (dudeInfo[pSprite->type - kDudeBase].damageVal[dmgType] <= minScale); } } @@ -879,19 +878,21 @@ void aiSetTarget(XSPRITE *pXSprite, int nTarget) } -int aiDamageSprite(spritetype *pSprite, XSPRITE *pXSprite, int nSource, DAMAGE_TYPE nDmgType, int nDamage) +int aiDamageSprite(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE nDmgType, int nDamage) { - assert(nSource < kMaxSprites); + auto pSprite = &actor->s(); + XSPRITE* pXSprite = &actor->x(); + if (!pXSprite->health) return 0; - auto actor = &bloodActors[pXSprite->reference]; pXSprite->health = ClipLow(pXSprite->health - nDamage, 0); cumulDamage[pSprite->extra] += nDamage; DUDEINFO *pDudeInfo = getDudeInfo(pSprite->type); int nSprite = pXSprite->reference; - if (nSource >= 0) + if (source) { - spritetype *pSource = &sprite[nSource]; + spritetype *pSource = &source->s(); + int nSource = pSource->index; if (pSprite == pSource) return 0; if (pXSprite->target == -1 || (nSource != pXSprite->target && Chance(pSprite->type == pSource->type ? nDamage*pDudeInfo->changeTargetKin : nDamage*pDudeInfo->changeTarget))) diff --git a/source/games/blood/src/ai.h b/source/games/blood/src/ai.h index 5061ce60e..ca0eef908 100644 --- a/source/games/blood/src/ai.h +++ b/source/games/blood/src/ai.h @@ -88,7 +88,6 @@ struct TARGETTRACK { extern const int dword_138BB0[5]; extern DUDEEXTRA gDudeExtra[]; -extern int gDudeSlope[]; bool dudeIsPlayingSeq(spritetype *pSprite, int nSeq); void aiPlay3DSound(spritetype *pSprite, int a2, AI_SFX_PRIORITY a3, int a4); @@ -100,7 +99,7 @@ void aiMoveDodge(DBloodActor *actor); void aiActivateDude(DBloodActor *actor); void aiSetTarget(XSPRITE *pXSprite, int x, int y, int z); void aiSetTarget(XSPRITE *pXSprite, int nTarget); -int aiDamageSprite(spritetype *pSprite, XSPRITE *pXSprite, int nSource, DAMAGE_TYPE nDmgType, int nDamage); +int aiDamageSprite(DBloodActor* source, DBloodActor* actor, DAMAGE_TYPE nDmgType, int nDamage); void aiThinkTarget(DBloodActor* actor); void sub_5F15C(spritetype *pSprite, XSPRITE *pXSprite); void aiProcessDudes(void); diff --git a/source/games/blood/src/aibat.cpp b/source/games/blood/src/aibat.cpp index 6db80f812..878affe7d 100644 --- a/source/games/blood/src/aibat.cpp +++ b/source/games/blood/src/aibat.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "blood.h" diff --git a/source/games/blood/src/aibeast.cpp b/source/games/blood/src/aibeast.cpp index 30dd7d47b..857d01cfe 100644 --- a/source/games/blood/src/aibeast.cpp +++ b/source/games/blood/src/aibeast.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "blood.h" diff --git a/source/games/blood/src/aiboneel.cpp b/source/games/blood/src/aiboneel.cpp index 2fccc1674..0c56f7725 100644 --- a/source/games/blood/src/aiboneel.cpp +++ b/source/games/blood/src/aiboneel.cpp @@ -24,7 +24,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "ns.h" // Must come before everything else! #include "build.h" -#include "mmulti.h" #include "blood.h" diff --git a/source/games/blood/src/aiburn.cpp b/source/games/blood/src/aiburn.cpp index 15ad1528e..7470a20e0 100644 --- a/source/games/blood/src/aiburn.cpp +++ b/source/games/blood/src/aiburn.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "blood.h" diff --git a/source/games/blood/src/aicaleb.cpp b/source/games/blood/src/aicaleb.cpp index 9bf1c779f..7024c0b8f 100644 --- a/source/games/blood/src/aicaleb.cpp +++ b/source/games/blood/src/aicaleb.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "blood.h" diff --git a/source/games/blood/src/aicerber.cpp b/source/games/blood/src/aicerber.cpp index 7360f6b8c..414d267dc 100644 --- a/source/games/blood/src/aicerber.cpp +++ b/source/games/blood/src/aicerber.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "blood.h" diff --git a/source/games/blood/src/aicult.cpp b/source/games/blood/src/aicult.cpp index 36703635c..ef19c51df 100644 --- a/source/games/blood/src/aicult.cpp +++ b/source/games/blood/src/aicult.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "blood.h" @@ -147,7 +146,7 @@ void cultThrowSeqCallback(int, DBloodActor* actor) int nDist2 = nDist / 540; if (nDist > 0x1e00) v4 = 0; - spritetype *pMissile = actFireThing(pSprite, 0, 0, dz/128-14500, nMissile, (nDist2<<23)/120); + spritetype *pMissile = actFireThing_(pSprite, 0, 0, dz/128-14500, nMissile, (nDist2<<23)/120); if (v4) xsprite[pMissile->extra].Impact = 1; else @@ -162,7 +161,7 @@ void sub_68170(int, DBloodActor* actor) if (gGameOptions.nDifficulty > 2) nMissile = kThingArmedTNTBundle; sfxPlay3DSound(pSprite, 455, -1, 0); - spritetype* pMissile = actFireThing(pSprite, 0, 0, actor->dudeSlope - 9460, nMissile, 0x133333); + spritetype* pMissile = actFireThing_(pSprite, 0, 0, actor->dudeSlope - 9460, nMissile, 0x133333); evPost(pMissile->index, 3, 120*(2+Random(2)), kCmdOn); } @@ -182,7 +181,7 @@ void sub_68230(int, DBloodActor* actor) int dz = pTarget->z - pSprite->z; int nDist = approxDist(dx, dy); int nDist2 = nDist / 540; - spritetype *pMissile = actFireThing(pSprite, 0, 0, dz/128-14500, nMissile, (nDist2<<17)/120); + spritetype *pMissile = actFireThing_(pSprite, 0, 0, dz/128-14500, nMissile, (nDist2<<17)/120); xsprite[pMissile->extra].Impact = 1; } diff --git a/source/games/blood/src/aigarg.cpp b/source/games/blood/src/aigarg.cpp index b70bc1b6c..d16563cba 100644 --- a/source/games/blood/src/aigarg.cpp +++ b/source/games/blood/src/aigarg.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "blood.h" @@ -103,7 +102,7 @@ void ThrowFSeqCallback(int, DBloodActor* actor) { XSPRITE* pXSprite = &actor->x(); spritetype* pSprite = &actor->s(); - actFireThing(&actor->s(), 0, 0, actor->dudeSlope-7500, kThingBone, 0xeeeee); + actFireThing_(&actor->s(), 0, 0, actor->dudeSlope-7500, kThingBone, 0xeeeee); } void BlastSSeqCallback(int, DBloodActor* actor) @@ -203,7 +202,7 @@ void BlastSSeqCallback(int, DBloodActor* actor) void ThrowSSeqCallback(int, DBloodActor* actor) { spritetype* pSprite = &actor->s(); - actFireThing(pSprite, 0, 0, actor->dudeSlope - 7500, kThingBone, Chance(0x6000) ? 0x133333 : 0x111111); + actFireThing_(pSprite, 0, 0, actor->dudeSlope - 7500, kThingBone, Chance(0x6000) ? 0x133333 : 0x111111); } static void gargThinkTarget(DBloodActor* actor) diff --git a/source/games/blood/src/aighost.cpp b/source/games/blood/src/aighost.cpp index 7b6d39541..5b753d4eb 100644 --- a/source/games/blood/src/aighost.cpp +++ b/source/games/blood/src/aighost.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "blood.h" @@ -86,7 +85,7 @@ void ghostSlashSeqCallback(int, DBloodActor* actor) void ghostThrowSeqCallback(int, DBloodActor* actor) { - actFireThing(&actor->s(), 0, 0, actor->dudeSlope - 7500, kThingBone, 0xeeeee); + actFireThing_(&actor->s(), 0, 0, actor->dudeSlope - 7500, kThingBone, 0xeeeee); } void ghostBlastSeqCallback(int, DBloodActor* actor) diff --git a/source/games/blood/src/aigilbst.cpp b/source/games/blood/src/aigilbst.cpp index 1de41c886..47b6267e9 100644 --- a/source/games/blood/src/aigilbst.cpp +++ b/source/games/blood/src/aigilbst.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "blood.h" diff --git a/source/games/blood/src/aihand.cpp b/source/games/blood/src/aihand.cpp index 389c6bfab..5f31be3ff 100644 --- a/source/games/blood/src/aihand.cpp +++ b/source/games/blood/src/aihand.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "blood.h" diff --git a/source/games/blood/src/aihound.cpp b/source/games/blood/src/aihound.cpp index 790a5180d..206871d6e 100644 --- a/source/games/blood/src/aihound.cpp +++ b/source/games/blood/src/aihound.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "blood.h" diff --git a/source/games/blood/src/aiinnoc.cpp b/source/games/blood/src/aiinnoc.cpp index b0595c500..09b83bdd8 100644 --- a/source/games/blood/src/aiinnoc.cpp +++ b/source/games/blood/src/aiinnoc.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "blood.h" diff --git a/source/games/blood/src/aipod.cpp b/source/games/blood/src/aipod.cpp index 822b45307..4d8f1eb2a 100644 --- a/source/games/blood/src/aipod.cpp +++ b/source/games/blood/src/aipod.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "blood.h" @@ -98,7 +97,7 @@ void podAttack(int, DBloodActor* actor) sfxPlay3DSound(pSprite, 2474, -1, 0); else sfxPlay3DSound(pSprite, 2475, -1, 0); - pMissile = actFireThing(pSprite, 0, -8000, dz/128-14500, kThingPodGreenBall, (nDist2<<23)/120); + pMissile = actFireThing_(pSprite, 0, -8000, dz/128-14500, kThingPodGreenBall, (nDist2<<23)/120); } if (pMissile) seqSpawn(68, 3, pMissile->extra, -1); @@ -108,7 +107,7 @@ void podAttack(int, DBloodActor* actor) if (pDudeInfo->seeDist*0.1 < nDist) { sfxPlay3DSound(pSprite, 2454, -1, 0); - pMissile = actFireThing(pSprite, 0, -8000, dz/128-14500, kThingPodFireBall, (nDist2<<23)/120); + pMissile = actFireThing_(pSprite, 0, -8000, dz/128-14500, kThingPodFireBall, (nDist2<<23)/120); } if (pMissile) seqSpawn(22, 3, pMissile->extra, -1); @@ -120,8 +119,7 @@ void podAttack(int, DBloodActor* actor) void sub_70284(int, DBloodActor* actor) { - XSPRITE* pXSprite = &actor->x(); - spritetype* pSprite = &actor->s(); + auto pSprite = &actor->s(); sfxPlay3DSound(pSprite, 2502, -1, 0); int nDist, nBurn; DAMAGE_TYPE dmgType; @@ -138,7 +136,7 @@ void sub_70284(int, DBloodActor* actor) nDist = 75; break; } - sub_2A620(pSprite->index, pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, nDist, 1, 5*(1+gGameOptions.nDifficulty), dmgType, 2, nBurn, 0, 0); + actRadiusDamage(actor, pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum, nDist, 1, 5*(1+gGameOptions.nDifficulty), dmgType, 2, nBurn); } static void aiPodSearch(DBloodActor* actor) diff --git a/source/games/blood/src/airat.cpp b/source/games/blood/src/airat.cpp index 53198e62d..3cf5d93a8 100644 --- a/source/games/blood/src/airat.cpp +++ b/source/games/blood/src/airat.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "blood.h" diff --git a/source/games/blood/src/aispid.cpp b/source/games/blood/src/aispid.cpp index cd34b36e8..14517d58a 100644 --- a/source/games/blood/src/aispid.cpp +++ b/source/games/blood/src/aispid.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "blood.h" diff --git a/source/games/blood/src/aitchern.cpp b/source/games/blood/src/aitchern.cpp index 05cd294b9..17be3e2e5 100644 --- a/source/games/blood/src/aitchern.cpp +++ b/source/games/blood/src/aitchern.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "blood.h" diff --git a/source/games/blood/src/aiunicult.cpp b/source/games/blood/src/aiunicult.cpp index 85e6b9ea2..31315d457 100644 --- a/source/games/blood/src/aiunicult.cpp +++ b/source/games/blood/src/aiunicult.cpp @@ -26,7 +26,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "raze_sound.h" #include "blood.h" @@ -307,7 +306,7 @@ static void ThrowThing(DBloodActor* actor, bool impact) } spritetype* pThing = NULL; - if ((pThing = actFireThing(pSprite, 0, 0, (dz / 128) - zThrow, curWeapon, DivScale(dist / 540, 120, 23))) == NULL) return; + if ((pThing = actFireThing_(pSprite, 0, 0, (dz / 128) - zThrow, curWeapon, DivScale(dist / 540, 120, 23))) == NULL) return; else if (pThinkInfo->picnum < 0 && pThing->type != kModernThingThrowableRock) pThing->picnum = 0; pThing->owner = pSprite->index; @@ -1593,7 +1592,7 @@ void dudeLeechOperate(spritetype* pSprite, XSPRITE* pXSprite, EVENT event) } bool doExplosion(spritetype* pSprite, int nType) { - spritetype* pExplosion = actSpawnSprite(pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, kStatExplosion, true); + spritetype* pExplosion = actSpawnSprite_(pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z, kStatExplosion, true); if (pExplosion->extra < 0 || pExplosion->extra >= kMaxXSprites) return false; diff --git a/source/games/blood/src/aizomba.cpp b/source/games/blood/src/aizomba.cpp index 442bdecfa..2351e1858 100644 --- a/source/games/blood/src/aizomba.cpp +++ b/source/games/blood/src/aizomba.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "blood.h" diff --git a/source/games/blood/src/aizombf.cpp b/source/games/blood/src/aizombf.cpp index ee74f601a..64b8fbd6d 100644 --- a/source/games/blood/src/aizombf.cpp +++ b/source/games/blood/src/aizombf.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "blood.h" diff --git a/source/games/blood/src/animatesprite.cpp b/source/games/blood/src/animatesprite.cpp index eaf4de715..f96554cca 100644 --- a/source/games/blood/src/animatesprite.cpp +++ b/source/games/blood/src/animatesprite.cpp @@ -27,7 +27,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "v_font.h" #include "blood.h" diff --git a/source/games/blood/src/blood.cpp b/source/games/blood/src/blood.cpp index 2b59a0761..f37c40693 100644 --- a/source/games/blood/src/blood.cpp +++ b/source/games/blood/src/blood.cpp @@ -24,7 +24,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "ns.h" // Must come before everything else! #include "build.h" -#include "mmulti.h" #include "compat.h" #include "g_input.h" #include "automap.h" @@ -419,7 +418,7 @@ void GameInterface::app_init() HookReplaceFunctions(); Printf(PRINT_NONOTIFY, "Loading tiles\n"); - if (!tileInit(0, NULL)) + if (!tileInit()) I_FatalError("TILES###.ART files not found"); levelLoadDefaults(); diff --git a/source/games/blood/src/blood.h b/source/games/blood/src/blood.h index b1adaec6a..6202eca69 100644 --- a/source/games/blood/src/blood.h +++ b/source/games/blood/src/blood.h @@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "build.h" #include "gamestruct.h" #include "mapinfo.h" +#include "d_net.h" #include "common_game.h" #include "fx.h" @@ -120,7 +121,6 @@ struct GameInterface : ::GameInterface void MenuOpened() override; void MenuClosed() override; bool CanSave() override; - void QuitToTitle() override; FString GetCoordString() override; ReservedSpace GetReservedScreenSpace(int viewsize) override; void UpdateSounds() override; diff --git a/source/games/blood/src/bloodactor.h b/source/games/blood/src/bloodactor.h index afab01824..4947650ea 100644 --- a/source/games/blood/src/bloodactor.h +++ b/source/games/blood/src/bloodactor.h @@ -22,6 +22,10 @@ public: dudeSlope = 0; } bool hasX() { return sprite[index].extra > 0; } + void addX() + { + if (s().extra == -1) dbInsertXSprite(s().index); + } spritetype& s() { return sprite[index]; } XSPRITE& x() { return xsprite[sprite[index].extra]; } // calling this does not validate the xsprite! SPRITEHIT& hit() { return gSpriteHit[sprite[index].extra]; } @@ -42,10 +46,20 @@ public: DBloodActor* GetOwner() { - if (s().owner == -1) return nullptr; + if (s().owner == -1 || s().owner == kMaxSprites-1) return nullptr; return base() + s().owner; } + void SetSpecialOwner() // nnext hackery + { + s().owner = kMaxSprites - 1; + } + + bool GetSpecialOwner() + { + return (s().owner == kMaxSprites - 1); + } + bool IsPlayerActor() { return s().type >= kDudePlayer1 && s().type <= kDudePlayer8; @@ -124,5 +138,26 @@ inline int DeleteSprite(DBloodActor* nSprite) return 0; } +inline void actBurnSprite(DBloodActor* pSource, DBloodActor* pTarget, int nTime) +{ + auto pXSprite = &pTarget->x(); + pXSprite->burnTime = ClipHigh(pXSprite->burnTime + nTime, sprite[pXSprite->reference].statnum == kStatDude ? 2400 : 1200); + pXSprite->burnSource = pSource->s().index; +} + +inline void GetActorExtents(DBloodActor* actor, int* top, int* bottom) +{ + GetSpriteExtents(&actor->s(), top, bottom); +} + +inline DBloodActor *PLAYER::fragger() +{ + return fraggerId == -1? nullptr : &bloodActors[fraggerId]; +} + +inline void PLAYER::setFragger(DBloodActor* actor) +{ + fraggerId = actor == nullptr ? -1 : actor->s().index; +} END_BLD_NS diff --git a/source/games/blood/src/common_game.h b/source/games/blood/src/common_game.h index a313364e7..e3ff6bc7b 100644 --- a/source/games/blood/src/common_game.h +++ b/source/games/blood/src/common_game.h @@ -440,21 +440,6 @@ enum // ------------------------------- -// NUKE-TODO: - - - -enum BLOOD_GLOBALFLAGS { - BLOOD_FORCE_WIDELOADSCREEN = 1<<0, -}; - -enum searchpathtypes_t { - SEARCHPATH_REMOVE = 1<<0, -}; - -extern void G_SetupGlobalPsky(void); - - #pragma pack(push,1) struct LOCATION { @@ -475,35 +460,6 @@ struct Aim { #pragma pack(pop) -inline int ksgnf(float f) -{ - if (f < 0) - return -1; - if (f > 0) - return 1; - return 0; -} - -inline int IncBy(int a, int b) -{ - a += b; - int q = a % b; - a -= q; - if (q < 0) - a -= b; - return a; -} - -inline int DecBy(int a, int b) -{ - a--; - int q = a % b; - a -= q; - if (q < 0) - a -= b; - return a; -} - inline int ClipLow(int a, int b) { if (a < b) diff --git a/source/games/blood/src/controls.cpp b/source/games/blood/src/controls.cpp index 9b9c09a7c..41b5f27ee 100644 --- a/source/games/blood/src/controls.cpp +++ b/source/games/blood/src/controls.cpp @@ -24,7 +24,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "ns.h" // Must come before everything else! -#include "mmulti.h" #include "blood.h" #include "gamestate.h" #include "inputstate.h" diff --git a/source/games/blood/src/d_menu.cpp b/source/games/blood/src/d_menu.cpp index 7207729db..ec3818489 100644 --- a/source/games/blood/src/d_menu.cpp +++ b/source/games/blood/src/d_menu.cpp @@ -26,7 +26,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "build.h" #include "compat.h" -#include "mmulti.h" #include "c_bind.h" #include "razemenu.h" #include "gamestate.h" @@ -164,12 +163,6 @@ FSavegameInfo GameInterface::GetSaveSig() return { SAVESIG_BLD, MINSAVEVER_BLD, SAVEVER_BLD }; } -void GameInterface::QuitToTitle() -{ - Mus_Stop(); - gameaction = ga_mainmenu; -} - END_BLD_NS using namespace Blood; diff --git a/source/games/blood/src/dude.h b/source/games/blood/src/dude.h index 5bf74b744..57d065a77 100644 --- a/source/games/blood/src/dude.h +++ b/source/games/blood/src/dude.h @@ -49,7 +49,7 @@ struct DUDEINFO { int angSpeed; // turn speed int nGibType[3]; // which gib used when explode dude int startDamage[7]; // start damage shift - int at70[7]; // real damage? Hmm? + int damageVal[7]; // real damage? Hmm? int at8c; // unused ? int at90; // unused ? }; diff --git a/source/games/blood/src/endgame.cpp b/source/games/blood/src/endgame.cpp index 38b73a489..452711f74 100644 --- a/source/games/blood/src/endgame.cpp +++ b/source/games/blood/src/endgame.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "build.h" #include "v_draw.h" -#include "mmulti.h" #include "statistics.h" #include "gstrings.h" #include "gamestate.h" diff --git a/source/games/blood/src/fx.cpp b/source/games/blood/src/fx.cpp index 074b71f03..c156c9415 100644 --- a/source/games/blood/src/fx.cpp +++ b/source/games/blood/src/fx.cpp @@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "build.h" #include "blood.h" +#include "bloodactor.h" BEGIN_BLD_NS @@ -164,7 +165,7 @@ spritetype * CFX::fxSpawn(FX_ID nFx, int nSector, int x, int y, int z, unsigned return NULL; destroy(nSprite); } - spritetype *pSprite = actSpawnSprite(nSector, x, y, z, 1, 0); + spritetype *pSprite = actSpawnSprite_(nSector, x, y, z, 1, 0); pSprite->type = nFx; pSprite->picnum = pFX->picnum; pSprite->cstat |= pFX->cstat; @@ -261,9 +262,8 @@ void CFX::fxProcess(void) } } -void fxSpawnBlood(spritetype *pSprite, int a2) +void fxSpawnBlood(spritetype *pSprite, int ) { - UNREFERENCED_PARAMETER(a2); if (pSprite->sectnum < 0 || pSprite->sectnum >= numsectors) return; int nSector = pSprite->sectnum; @@ -282,9 +282,8 @@ void fxSpawnBlood(spritetype *pSprite, int a2) } } -void sub_746D4(spritetype *pSprite, int a2) +void sub_746D4(spritetype *pSprite, int ) { - UNREFERENCED_PARAMETER(a2); if (pSprite->sectnum < 0 || pSprite->sectnum >= numsectors) return; int nSector = pSprite->sectnum; @@ -355,4 +354,11 @@ void fxPrecache() } } + +DBloodActor* CFX::fxSpawnActor(FX_ID nFx, int nSector, int x, int y, int z, unsigned int a6) +{ + auto spr = fxSpawn(nFx, nSector, x, y, z, a6); + return spr ? &bloodActors[spr->index] : nullptr; +} + END_BLD_NS diff --git a/source/games/blood/src/fx.h b/source/games/blood/src/fx.h index c2806d676..e1dc76025 100644 --- a/source/games/blood/src/fx.h +++ b/source/games/blood/src/fx.h @@ -94,6 +94,7 @@ public: void destroy(int); void remove(int); spritetype * fxSpawn(FX_ID, int, int, int, int, unsigned int); + DBloodActor* fxSpawnActor(FX_ID, int, int, int, int, unsigned int); void fxProcess(void); }; diff --git a/source/games/blood/src/hudsprites.cpp b/source/games/blood/src/hudsprites.cpp index 4da7c6410..bb0f4a311 100644 --- a/source/games/blood/src/hudsprites.cpp +++ b/source/games/blood/src/hudsprites.cpp @@ -27,7 +27,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "v_font.h" #include "blood.h" diff --git a/source/games/blood/src/levels.cpp b/source/games/blood/src/levels.cpp index bbb2d2c3a..449f617ce 100644 --- a/source/games/blood/src/levels.cpp +++ b/source/games/blood/src/levels.cpp @@ -97,7 +97,7 @@ void levelLoadMapInfo(IniFile* pIni, MapRecord* pLevelInfo, const char* pzSectio char buffer[16]; pLevelInfo->SetName(pIni->GetKeyString(pzSection, "Title", pLevelInfo->labelName)); pLevelInfo->Author = pIni->GetKeyString(pzSection, "Author", ""); - pLevelInfo->music = pIni->GetKeyString(pzSection, "Song", ""); DefaultExtension(pLevelInfo->music, ".mid"); + pLevelInfo->music = pIni->GetKeyString(pzSection, "Song", ""); if (pLevelInfo->music.IsNotEmpty()) DefaultExtension(pLevelInfo->music, ".mid"); pLevelInfo->cdSongId = pIni->GetKeyInt(pzSection, "Track", -1); *nextmap = pIni->GetKeyInt(pzSection, "EndingA", 0); *nextsecret = pIni->GetKeyInt(pzSection, "EndingB", 0); @@ -193,7 +193,6 @@ void levelLoadDefaults(void) CheckSectionAbend(pMap); SetLevelNum(pLevelInfo, makelevelnum(i, j)); pLevelInfo->cluster = i; - pLevelInfo->mapindex = j; pLevelInfo->labelName = pMap; if (j == 1) volume->startmap = pLevelInfo->labelName; pLevelInfo->fileName.Format("%s.map", pMap); @@ -219,12 +218,14 @@ void levelLoadDefaults(void) if (nmap) map->NextMap = nmap->labelName; else map->NextMap = "-"; } + else map->NextMap = "-"; if (nextsecrets[j - 1] > 0) { auto nmap = FindMapByIndexOnly(i, nextsecrets[j - 1]); if (nmap) map->NextSecret = nmap->labelName; else map->NextSecret = "-"; } + else map->NextSecret = "-"; } } } @@ -246,7 +247,7 @@ void levelTryPlayMusic() { buffer = currentLevel->music; if (Mus_Play(currentLevel->labelName, buffer, true)) return; - DefaultExtension(buffer, ".mid"); + if (buffer.IsNotEmpty()) DefaultExtension(buffer, ".mid"); } if (!Mus_Play(currentLevel->labelName, buffer, true)) { diff --git a/source/games/blood/src/loadsave.cpp b/source/games/blood/src/loadsave.cpp index a8436d8a2..69d36a3ab 100644 --- a/source/games/blood/src/loadsave.cpp +++ b/source/games/blood/src/loadsave.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include #include "build.h" #include "compat.h" -#include "mmulti.h" #include "blood.h" #include "i_specialpaths.h" @@ -643,6 +642,7 @@ void SerializeState(FSerializer& arc) ("cheating", bPlayerCheated) ("skyhoriz", pSky->horizfrac) ("skyy", pSky->yoffs) + ("skyy2", pSky->yoffs2) ("scale", pSky->yscale) .Array("tileofs", pSky->tileofs, countof(pSky->tileofs)) ("numtiles", pSky->lognumtiles) diff --git a/source/games/blood/src/messages.cpp b/source/games/blood/src/messages.cpp index 8ff7ad3f7..250dba55d 100644 --- a/source/games/blood/src/messages.cpp +++ b/source/games/blood/src/messages.cpp @@ -23,7 +23,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "ns.h" // Must come before everything else! #include "build.h" -#include "mmulti.h" #include "compat.h" #include "gamecontrol.h" diff --git a/source/games/blood/src/mirrors.cpp b/source/games/blood/src/mirrors.cpp index dcebacecb..72ad38070 100644 --- a/source/games/blood/src/mirrors.cpp +++ b/source/games/blood/src/mirrors.cpp @@ -24,7 +24,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "build.h" #include "automap.h" -#include "mmulti.h" #include "savegamehelp.h" #include "blood.h" diff --git a/source/games/blood/src/misc.h b/source/games/blood/src/misc.h index c77979eea..7f4491f93 100644 --- a/source/games/blood/src/misc.h +++ b/source/games/blood/src/misc.h @@ -119,7 +119,7 @@ extern short voxelIndex[MAXTILES]; extern int nPrecacheCount; -int tileInit(char a1, const char *a2); +int tileInit(); void tilePrecacheTile(int nTile, int nType, int palette); char tileGetSurfType(int hit); diff --git a/source/games/blood/src/nnexts.cpp b/source/games/blood/src/nnexts.cpp index 35e267875..c49388ef7 100644 --- a/source/games/blood/src/nnexts.cpp +++ b/source/games/blood/src/nnexts.cpp @@ -31,7 +31,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifdef NOONE_EXTENSIONS #include -#include "mmulti.h" #include "blood.h" #include "savegamehelp.h" @@ -127,7 +126,7 @@ bool nnExtIsImmune(spritetype* pSprite, int dmgType, int minScale) { else if (IsDudeSprite(pSprite)) { if (IsPlayerSprite(pSprite)) return (gPlayer[pSprite->type - kDudePlayer1].damageControl[dmgType]); else if (pSprite->type == kDudeModernCustom) return (gGenDudeExtra[pSprite->index].dmgControl[dmgType] <= minScale); - else return (getDudeInfo(pSprite->type)->at70[dmgType] <= minScale); + else return (getDudeInfo(pSprite->type)->damageVal[dmgType] <= minScale); } } @@ -2336,11 +2335,11 @@ void useSpriteDamager(XSPRITE* pXSource, spritetype* pSprite) { } else if (!pPlayer) actKillDude(pSource->index, pSprite, (DAMAGE_TYPE)dmgType, dmg); - else playerDamageSprite(pSource->index, pPlayer, (DAMAGE_TYPE)dmgType, dmg); + else playerDamageSprite(&bloodActors[pSource->index], pPlayer, (DAMAGE_TYPE)dmgType, dmg); } else if ((pXSprite->health = ClipLow(pXSprite->health - dmg, 1)) > 16) return; else if (!pPlayer) actKillDude(pSource->index, pSprite, DAMAGE_TYPE_2, dmg); - else playerDamageSprite(pSource->index, pPlayer, DAMAGE_TYPE_2, dmg); + else playerDamageSprite(&bloodActors[pSource->index], pPlayer, DAMAGE_TYPE_2, dmg); return; } @@ -2532,8 +2531,6 @@ void condError(XSPRITE* pXCond, const char* pzFormat, ...) { bool condCheckMixed(XSPRITE* pXCond, EVENT event, int cmpOp, bool PUSH) { - UNREFERENCED_PARAMETER(PUSH); - //int var = -1; int cond = pXCond->data1 - kCondMixedBase; int arg1 = pXCond->data2; int arg2 = pXCond->data3; int arg3 = pXCond->data4; @@ -2812,8 +2809,6 @@ bool condCheckSector(XSPRITE* pXCond, int cmpOp, bool PUSH) { bool condCheckWall(XSPRITE* pXCond, int cmpOp, bool PUSH) { - UNREFERENCED_PARAMETER(PUSH); - int var = -1; int cond = pXCond->data1 - kCondWallBase; int arg1 = pXCond->data2; int arg2 = pXCond->data3; //int arg3 = pXCond->data4; @@ -2929,8 +2924,6 @@ bool condCheckPlayer(XSPRITE* pXCond, int cmpOp, bool PUSH) { bool condCheckDude(XSPRITE* pXCond, int cmpOp, bool PUSH) { - UNREFERENCED_PARAMETER(cmpOp); - int var = -1; //PLAYER* pPlayer = NULL; int cond = pXCond->data1 - kCondDudeBase; int arg1 = pXCond->data2; int arg2 = pXCond->data3; //int arg3 = pXCond->data4; @@ -3026,7 +3019,6 @@ bool condCheckDude(XSPRITE* pXCond, int cmpOp, bool PUSH) { bool condCheckSprite(XSPRITE* pXCond, int cmpOp, bool PUSH) { - UNREFERENCED_PARAMETER(PUSH); auto actor = &bloodActors[pXCond->reference]; int var = -1; PLAYER* pPlayer = NULL; bool retn = false; int cond = pXCond->data1 - kCondSpriteBase; int arg1 = pXCond->data2; @@ -4093,8 +4085,7 @@ void seqTxSendCmdAll(XSPRITE* pXSource, int nIndex, COMMAND_ID cmd, bool modernS void useRandomTx(XSPRITE* pXSource, COMMAND_ID cmd, bool setState) { - UNREFERENCED_PARAMETER(cmd); - + spritetype* pSource = &sprite[pXSource->reference]; int tx = 0; int maxRetries = kMaxRandomizeRetries; diff --git a/source/games/blood/src/osdcmd.cpp b/source/games/blood/src/osdcmd.cpp index f0a2b5b57..fbc73d9de 100644 --- a/source/games/blood/src/osdcmd.cpp +++ b/source/games/blood/src/osdcmd.cpp @@ -25,7 +25,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "build.h" #include "compat.h" -#include "mmulti.h" #include "blood.h" #include "mapinfo.h" diff --git a/source/games/blood/src/player.cpp b/source/games/blood/src/player.cpp index 0a87dfd11..b32c5e76d 100644 --- a/source/games/blood/src/player.cpp +++ b/source/games/blood/src/player.cpp @@ -27,7 +27,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "automap.h" #include "compat.h" #include "build.h" -#include "mmulti.h" #include "blood.h" #include "gstrings.h" @@ -582,7 +581,7 @@ void playerSetRace(PLAYER *pPlayer, int nLifeMode) pPlayer->pSprite->clipdist = pDudeInfo->clipdist; for (int i = 0; i < 7; i++) - pDudeInfo->at70[i] = MulScale(Handicap[gSkill], pDudeInfo->startDamage[i], 8); + pDudeInfo->damageVal[i] = MulScale(Handicap[gSkill], pDudeInfo->startDamage[i], 8); } void playerSetGodMode(PLAYER *pPlayer, bool bGodMode) @@ -661,7 +660,7 @@ void playerStart(int nPlayer, int bNewLevel) pStartZone = &gStartZone[Random(8)]; } - spritetype *pSprite = actSpawnSprite(pStartZone->sectnum, pStartZone->x, pStartZone->y, pStartZone->z, 6, 1); + spritetype *pSprite = actSpawnSprite_(pStartZone->sectnum, pStartZone->x, pStartZone->y, pStartZone->z, 6, 1); assert(pSprite->extra > 0 && pSprite->extra < kMaxXSprites); XSPRITE *pXSprite = &xsprite[pSprite->extra]; pPlayer->pSprite = pSprite; @@ -1741,7 +1740,7 @@ spritetype *playerFireMissile(PLAYER *pPlayer, int a2, int a3, int a4, int a5, i spritetype * playerFireThing(PLAYER *pPlayer, int a2, int a3, int thingType, int a5) { assert(thingType >= kThingBase && thingType < kThingMax); - return actFireThing(pPlayer->pSprite, a2, pPlayer->zWeapon-pPlayer->pSprite->z, pPlayer->slope+a3, thingType, a5); + return actFireThing_(pPlayer->pSprite, a2, pPlayer->zWeapon-pPlayer->pSprite->z, pPlayer->slope+a3, thingType, a5); } void playerFrag(PLAYER *pKiller, PLAYER *pVictim) @@ -1883,9 +1882,9 @@ spritetype *flagDropped(PLAYER *pPlayer, int a2) return pSprite; } -int playerDamageSprite(int nSource, PLAYER *pPlayer, DAMAGE_TYPE nDamageType, int nDamage) +int playerDamageSprite(DBloodActor* source, PLAYER *pPlayer, DAMAGE_TYPE nDamageType, int nDamage) { - assert(nSource < kMaxSprites); + int nSource = source ? source->s().index : -1; assert(pPlayer != NULL); if (pPlayer->damageControl[nDamageType] || pPlayer->godMode) return 0; @@ -2116,7 +2115,7 @@ void PlayerKneelsOver(int, DBloodActor* actor) if (gPlayer[p].pXSprite == pXSprite) { PLAYER *pPlayer = &gPlayer[p]; - playerDamageSprite(pPlayer->fraggerId, pPlayer, DAMAGE_TYPE_5, 500<<4); + playerDamageSprite(pPlayer->fragger(), pPlayer, DAMAGE_TYPE_5, 500<<4); return; } } diff --git a/source/games/blood/src/player.h b/source/games/blood/src/player.h index c5f72d49d..245042027 100644 --- a/source/games/blood/src/player.h +++ b/source/games/blood/src/player.h @@ -145,6 +145,8 @@ struct PLAYER int fragInfo[8]; int teamId; int fraggerId; + DBloodActor* fragger(); + void setFragger(DBloodActor*); int underwaterTime; int bubbleTime; int restTime; @@ -272,7 +274,7 @@ void playerFrag(PLAYER *pKiller, PLAYER *pVictim); void FragPlayer(PLAYER *pPlayer, int nSprite); int playerDamageArmor(PLAYER *pPlayer, DAMAGE_TYPE nType, int nDamage); spritetype *flagDropped(PLAYER *pPlayer, int a2); -int playerDamageSprite(int nSource, PLAYER *pPlayer, DAMAGE_TYPE nDamageType, int nDamage); +int playerDamageSprite(DBloodActor* nSource, PLAYER *pPlayer, DAMAGE_TYPE nDamageType, int nDamage); int UseAmmo(PLAYER *pPlayer, int nAmmoType, int nDec); void voodooTarget(PLAYER *pPlayer); void playerLandingSound(PLAYER *pPlayer); diff --git a/source/games/blood/src/prediction.cpp b/source/games/blood/src/prediction.cpp index b3bd4bec1..69403dd43 100644 --- a/source/games/blood/src/prediction.cpp +++ b/source/games/blood/src/prediction.cpp @@ -27,7 +27,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "v_font.h" #include "blood.h" diff --git a/source/games/blood/src/sbar.cpp b/source/games/blood/src/sbar.cpp index e7967861c..4f9621f87 100644 --- a/source/games/blood/src/sbar.cpp +++ b/source/games/blood/src/sbar.cpp @@ -27,7 +27,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "v_font.h" #include "blood.h" diff --git a/source/games/blood/src/seq.cpp b/source/games/blood/src/seq.cpp index 7024d25ea..b777ba645 100644 --- a/source/games/blood/src/seq.cpp +++ b/source/games/blood/src/seq.cpp @@ -487,6 +487,12 @@ void seqKillAll() activeList.clear(); } +void seqKill(DBloodActor* actor) +{ + activeList.remove(4, actor->s().extra); +} + + //--------------------------------------------------------------------------- // // @@ -586,6 +592,11 @@ void seqSpawn(int nSeqID, int type, int nXIndex, int callback) pInst->Update(); } +void seqSpawn(int a1, DBloodActor* actor, int a4) +{ + seqSpawn(a1, 3, actor->s().extra, a4); +} + //--------------------------------------------------------------------------- // // diff --git a/source/games/blood/src/seq.h b/source/games/blood/src/seq.h index 7e0baed6f..3c2a76f74 100644 --- a/source/games/blood/src/seq.h +++ b/source/games/blood/src/seq.h @@ -100,7 +100,10 @@ void seqPrecacheId(int id, int palette); SEQINST* GetInstance(int a1, int a2); void UnlockInstance(SEQINST* pInst); void seqSpawn(int a1, int a2, int a3, int a4 = -1); +void seqSpawn(int a1, DBloodActor* actor, int a4 = -1); + void seqKill(int a1, int a2); +void seqKill(DBloodActor* actor); void seqKillAll(void); int seqGetStatus(int a1, int a2); int seqGetID(int a1, int a2); diff --git a/source/games/blood/src/tile.cpp b/source/games/blood/src/tile.cpp index 2ee8fc334..0c4be50a5 100644 --- a/source/games/blood/src/tile.cpp +++ b/source/games/blood/src/tile.cpp @@ -33,7 +33,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. BEGIN_BLD_NS -bool artLoaded = false; int nTileFiles = 0; int tileStart[256]; @@ -44,14 +43,8 @@ char surfType[kMaxTiles]; int8_t tileShade[kMaxTiles]; short voxelIndex[kMaxTiles]; -int tileInit(char a1, const char *a2) +int tileInit() { - UNREFERENCED_PARAMETER(a1); - if (artLoaded) - return 1; - for (int i = 0; i < kMaxTiles; i++) - voxelIndex[i] = 0; - auto hFile = fileSystem.OpenFileReader("SURFACE.DAT"); if (hFile.isOpen()) { @@ -76,8 +69,6 @@ int tileInit(char a1, const char *a2) if (voxelIndex[i] >= 0 && voxelIndex[i] < kMaxVoxels) voxreserve.Set(voxelIndex[i]); } - - artLoaded = 1; return 1; } diff --git a/source/games/blood/src/triggers.cpp b/source/games/blood/src/triggers.cpp index 4d46e1f07..5bc3c10b0 100644 --- a/source/games/blood/src/triggers.cpp +++ b/source/games/blood/src/triggers.cpp @@ -26,7 +26,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "build.h" #include "compat.h" -#include "mmulti.h" #include "blood.h" #include "d_net.h" diff --git a/source/games/blood/src/view.cpp b/source/games/blood/src/view.cpp index d6ee63a39..fa3498741 100644 --- a/source/games/blood/src/view.cpp +++ b/source/games/blood/src/view.cpp @@ -27,7 +27,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "compat.h" #include "build.h" -#include "mmulti.h" #include "v_font.h" #include "blood.h" @@ -341,8 +340,6 @@ void UpdateBlend() videoTintBlood(nRed, nGreen, nBlue); } -uint8_t otherMirrorGotpic[2]; -uint8_t bakMirrorGotpic[2]; // int gVisibility; int deliriumTilt, deliriumTurn, deliriumPitch; @@ -543,7 +540,6 @@ void SetupView(int &cX, int& cY, int& cZ, binangle& cA, fixedhoriz& cH, int& nSe void renderCrystalBall() { #if 0 - // needs to be redone for pure hardware rendering when MP is working again. int tmp = (PlayClock / 240) % (gNetPlayers - 1); int i = connecthead; while (1) @@ -594,37 +590,7 @@ void renderCrystalBall() { v14 = 10; } - memcpy(bakMirrorGotpic, gotpic + 510, 2); - memcpy(gotpic + 510, otherMirrorGotpic, 2); - g_visibility = (int32_t)(ClipLow(gVisibility - 32 * pOther->visibility, 0)); - int vc4, vc8; - getzsofslope(vcc, vd8, vd4, &vc8, &vc4); - if (vd0 >= vc4) - { - vd0 = vc4 - (gUpperLink[vcc] >= 0 ? 0 : (8 << 8)); - } - if (vd0 <= vc8) - { - vd0 = vc8 + (gLowerLink[vcc] >= 0 ? 0 : (8 << 8)); - } - v54 = ClipRange(v54, -200, 200); -RORHACKOTHER: - int ror_status[16]; - for (int i = 0; i < 16; i++) - ror_status[i] = TestBitString(gotpic, 4080 + i); - DrawMirrors(vd8, vd4, vd0, IntToFixed(v50), IntToFixed(v54), gInterpolate, -1); drawrooms(vd8, vd4, vd0, v50, v54, vcc); - bool do_ror_hack = false; - for (int i = 0; i < 16; i++) - if (ror_status[i] != TestBitString(gotpic, 4080 + i)) - do_ror_hack = true; - if (do_ror_hack) - { - spritesortcnt = 0; - goto RORHACKOTHER; - } - memcpy(otherMirrorGotpic, gotpic + 510, 2); - memcpy(gotpic + 510, bakMirrorGotpic, 2); viewProcessSprites(vd8, vd4, vd0, v50, gInterpolate); renderDrawMasks(); renderRestoreTarget(); @@ -637,10 +603,9 @@ void viewDrawScreen(bool sceneonly) { int nPalette = 0; - if (TestBitString(gotpic, 2342)) + if (testgotpic(2342, true)) { FireProcess(); - ClearBitString(gotpic, 2342); } if (!paused && (!M_Active() || gGameOptions.nGameType != 0)) diff --git a/source/games/blood/src/weapon.cpp b/source/games/blood/src/weapon.cpp index 3d4bb9ca1..f180a3092 100644 --- a/source/games/blood/src/weapon.cpp +++ b/source/games/blood/src/weapon.cpp @@ -27,7 +27,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include #include "compat.h" #include "build.h" -#include "mmulti.h" #include "blood.h" @@ -1548,9 +1547,8 @@ void AltFireVoodoo(int nTrigger, PLAYER *pPlayer) } } -void DropVoodoo(int nTrigger, PLAYER *pPlayer) +void DropVoodoo(int , PLAYER *pPlayer) { - UNREFERENCED_PARAMETER(nTrigger); sfxPlay3DSound(pPlayer->pSprite, 455, 2, 0); spritetype *pSprite = playerFireThing(pPlayer, 0, -4730, kThingVoodooHead, 0xccccc); if (pSprite) @@ -1610,9 +1608,8 @@ void FireTesla(int nTrigger, PLAYER *pPlayer) } } -void AltFireTesla(int nTrigger, PLAYER *pPlayer) +void AltFireTesla(int , PLAYER *pPlayer) { - UNREFERENCED_PARAMETER(nTrigger); spritetype *pSprite = pPlayer->pSprite; playerFireMissile(pPlayer, 0, pPlayer->aim.dx, pPlayer->aim.dy, pPlayer->aim.dz, kMissileTeslaAlt); UseAmmo(pPlayer, pPlayer->weaponAmmo, 35); @@ -1640,9 +1637,8 @@ void FireNapalm(int nTrigger, PLAYER *pPlayer) pPlayer->flashEffect = 1; } -void FireNapalm2(int nTrigger, PLAYER *pPlayer) +void FireNapalm2(int , PLAYER *pPlayer) { - UNREFERENCED_PARAMETER(nTrigger); spritetype *pSprite = pPlayer->pSprite; playerFireMissile(pPlayer, -120, pPlayer->aim.dx, pPlayer->aim.dy, pPlayer->aim.dz, kMissileFireballNapam); playerFireMissile(pPlayer, 120, pPlayer->aim.dx, pPlayer->aim.dy, pPlayer->aim.dz, kMissileFireballNapam); @@ -1651,9 +1647,8 @@ void FireNapalm2(int nTrigger, PLAYER *pPlayer) pPlayer->flashEffect = 1; } -void AltFireNapalm(int nTrigger, PLAYER *pPlayer) +void AltFireNapalm(int , PLAYER *pPlayer) { - UNREFERENCED_PARAMETER(nTrigger); int nSpeed = MulScale(0x8000, 0x177777, 16)+0x66666; spritetype *pMissile = playerFireThing(pPlayer, 0, -4730, kThingNapalmBall, nSpeed); if (pMissile) @@ -1691,9 +1686,8 @@ void FireLifeLeech(int nTrigger, PLAYER *pPlayer) pPlayer->visibility = ClipHigh(pPlayer->visibility+5, 50); } -void AltFireLifeLeech(int nTrigger, PLAYER *pPlayer) +void AltFireLifeLeech(int , PLAYER *pPlayer) { - UNREFERENCED_PARAMETER(nTrigger); sfxPlay3DSound(pPlayer->pSprite, 455, 2, 0); spritetype *pMissile = playerFireThing(pPlayer, 0, -4730, kThingDroppedLifeLeech, 0x19999); if (pMissile) @@ -1726,9 +1720,8 @@ void AltFireLifeLeech(int nTrigger, PLAYER *pPlayer) } } -void FireBeast(int nTrigger, PLAYER * pPlayer) +void FireBeast(int , PLAYER * pPlayer) { - UNREFERENCED_PARAMETER(nTrigger); int r1 = Random2(2000); int r2 = Random2(2000); int r3 = Random2(2000); diff --git a/source/games/duke/src/_polymost.cpp b/source/games/duke/src/_polymost.cpp index bb3d544ad..6aca17699 100644 --- a/source/games/duke/src/_polymost.cpp +++ b/source/games/duke/src/_polymost.cpp @@ -15,8 +15,7 @@ void SE40_Draw(int tag, spritetype *spr, int x, int y, int z, binangle a, fixedh i = FOF; //Effect TILE tileDelete(FOF); - if (!(gotpic[i >> 3] & (1 << (i & 7)))) return; - gotpic[i >> 3] &= ~(1 << (i & 7)); + if (!testgotpic(FOF, true)) return; floor1 = spr; @@ -165,7 +164,7 @@ void se40code(int x, int y, int z, binangle a, fixedhoriz h, int smoothratio) void renderMirror(int cposx, int cposy, int cposz, binangle cang, fixedhoriz choriz, int smoothratio) { - if ((gotpic[TILE_MIRROR >> 3] & (1 << (TILE_MIRROR & 7))) > 0) + if (testgotpic(TILE_MIRROR, true)) { int dst = 0x7fffffff, i = 0; for (int k = 0; k < mirrorcnt; k++) @@ -194,7 +193,6 @@ void renderMirror(int cposx, int cposy, int cposz, binangle cang, fixedhoriz cho renderCompleteMirror(); //Reverse screen x-wise in this function g_visibility = j; } - gotpic[TILE_MIRROR >> 3] &= ~(1 << (TILE_MIRROR & 7)); } } diff --git a/source/games/duke/src/actors_lava.cpp b/source/games/duke/src/actors_lava.cpp index ddebf025e..290b1932f 100644 --- a/source/games/duke/src/actors_lava.cpp +++ b/source/games/duke/src/actors_lava.cpp @@ -563,9 +563,8 @@ void thunder(void) if (!thunderflash) { - if ((gotpic[RRTILE2577 >> 3] & (1 << (RRTILE2577 & 7))) > 0) + if (testgotpic(RRTILE2577, true)) { - gotpic[RRTILE2577 >> 3] &= ~(1 << (RRTILE2577 & 7)); g_visibility = 256; // this is an engine variable if (krand() > 65000) { @@ -593,9 +592,8 @@ void thunder(void) } if (!winderflash) { - if ((gotpic[RRTILE2562 >> 3] & (1 << (RRTILE2562 & 7))) > 0) + if (testgotpic(RRTILE2562, true)) { - gotpic[RRTILE2562 >> 3] &= ~(1 << (RRTILE2562 & 7)); if (krand() > 65000) { winderflash = 1; diff --git a/source/games/duke/src/actors_r.cpp b/source/games/duke/src/actors_r.cpp index 8403bb23c..76fcc7170 100644 --- a/source/games/duke/src/actors_r.cpp +++ b/source/games/duke/src/actors_r.cpp @@ -29,7 +29,6 @@ Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms #include "ns.h" #include "global.h" #include "names_r.h" -#include "mmulti.h" #include "mapinfo.h" #include "dukeactor.h" diff --git a/source/games/duke/src/d_menu.cpp b/source/games/duke/src/d_menu.cpp index 343483ee3..ea3ea9a23 100644 --- a/source/games/duke/src/d_menu.cpp +++ b/source/games/duke/src/d_menu.cpp @@ -136,10 +136,4 @@ void GameInterface::DrawPlayerSprite(const DVector2& origin, bool onteam) DrawTexture(twod, tex, x, y, DTA_FullscreenScale, FSMode_Fit320x200, DTA_TranslationIndex, color, DTA_ScaleX, scale, DTA_ScaleY, scale, TAG_DONE); } -void GameInterface::QuitToTitle() -{ - gameaction = ga_startup; -} - - END_DUKE_NS diff --git a/source/games/duke/src/duke3d.h b/source/games/duke/src/duke3d.h index 96c9ce5b9..da153613a 100644 --- a/source/games/duke/src/duke3d.h +++ b/source/games/duke/src/duke3d.h @@ -40,7 +40,6 @@ struct GameInterface : public ::GameInterface FSavegameInfo GetSaveSig() override; double SmallFontScale() override { return isRR() ? 0.5 : 1.; } void SerializeGameState(FSerializer& arc) override; - void QuitToTitle() override; FString GetCoordString() override; void ExitFromMenu() override; ReservedSpace GetReservedScreenSpace(int viewsize) override; diff --git a/source/games/duke/src/game.cpp b/source/games/duke/src/game.cpp index 9dc6d5d45..08f898c48 100644 --- a/source/games/duke/src/game.cpp +++ b/source/games/duke/src/game.cpp @@ -219,6 +219,12 @@ static void setupbackdrop() } } } + + if (isNam()) + { + defineSky(212, 65536, 3, pskyoff, 0, 140); + defineSky(225, 65536, 3, pskyoff, 0, 140); + } } //--------------------------------------------------------------------------- diff --git a/source/games/duke/src/gamedef.cpp b/source/games/duke/src/gamedef.cpp index 51c912959..76859c7d1 100644 --- a/source/games/duke/src/gamedef.cpp +++ b/source/games/duke/src/gamedef.cpp @@ -1728,7 +1728,6 @@ int ConCompiler::parsecommand() SetLevelNum(map, makelevelnum(j + 1, k + 1)); - map->mapindex = k + 1; map->cluster = j + 1; textptr += 5; @@ -3236,7 +3235,7 @@ void loadcons() { if (map->cluster == 1) { - if (!FindMapByIndexOnly(map->cluster, map->mapindex + 1)) + if (!FindMapByLevelNum(map->levelNumber + 1)) { auto nextmap = FindMapByIndexOnly(map->cluster + 1, 1); if (nextmap) diff --git a/source/games/duke/src/gamevar.cpp b/source/games/duke/src/gamevar.cpp index 95a031ab3..c48830490 100644 --- a/source/games/duke/src/gamevar.cpp +++ b/source/games/duke/src/gamevar.cpp @@ -37,7 +37,6 @@ source as it is released. #include "serializer.h" #include "names.h" #include "build.h" -#include "mmulti.h" #include "gamevar.h" #include "mapinfo.h" diff --git a/source/games/duke/src/global.h b/source/games/duke/src/global.h index d492d754e..9e101fb4f 100644 --- a/source/games/duke/src/global.h +++ b/source/games/duke/src/global.h @@ -3,7 +3,6 @@ #include "build.h" #include "compat.h" #include "duke3d.h" -#include "mmulti.h" #include "quotemgr.h" #include "sounds.h" #include "constants.h" diff --git a/source/games/duke/src/premap.cpp b/source/games/duke/src/premap.cpp index af1e757fd..d3ff8350c 100644 --- a/source/games/duke/src/premap.cpp +++ b/source/games/duke/src/premap.cpp @@ -824,7 +824,7 @@ static void SpawnPortals() { for (int i = 0; i < numwalls; i++) { - if (wall[i].overpicnum == TILE_MIRROR) wall[i].portalflags |= PORTAL_WALL_MIRROR; + if (wall[i].overpicnum == TILE_MIRROR && (wall[i].cstat & CSTAT_WALL_1WAY)) wall[i].portalflags |= PORTAL_WALL_MIRROR; } portalClear(); diff --git a/source/games/duke/src/spawn.cpp b/source/games/duke/src/spawn.cpp index b087cba1b..44043f7c3 100644 --- a/source/games/duke/src/spawn.cpp +++ b/source/games/duke/src/spawn.cpp @@ -994,7 +994,11 @@ void spawneffector(DDukeActor* actor) } if (!found) { - I_Error("Found lonely Sector Effector (lotag 0) at (%d,%d)\n", sp->x, sp->y); + sp->picnum = 0; + sp->cstat = CSTAT_SPRITE_NOFIND; + changespritesect(actor, STAT_REMOVED); + Printf("Found lonely Sector Effector (lotag 0) at (%d,%d)\n", sp->x, sp->y); + return; } } diff --git a/source/games/exhumed/src/cheats.cpp b/source/games/exhumed/src/cheats.cpp index 27f4872c2..0dc38b898 100644 --- a/source/games/exhumed/src/cheats.cpp +++ b/source/games/exhumed/src/cheats.cpp @@ -39,7 +39,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "d_protocol.h" #include "gstrings.h" #include "aistuff.h" -#include "mmulti.h" +#include "d_net.h" BEGIN_PS_NS diff --git a/source/games/exhumed/src/d_menu.cpp b/source/games/exhumed/src/d_menu.cpp index 50d7282ef..176770f23 100644 --- a/source/games/exhumed/src/d_menu.cpp +++ b/source/games/exhumed/src/d_menu.cpp @@ -67,11 +67,6 @@ void GameInterface::MenuSound(EMenuSounds snd) } } -void GameInterface::QuitToTitle() -{ - gameaction = ga_mainmenu; -} - FSavegameInfo GameInterface::GetSaveSig() { return { SAVESIG_PS, MINSAVEVER_PS, SAVEVER_PS }; diff --git a/source/games/exhumed/src/exhumed.h b/source/games/exhumed/src/exhumed.h index 005ff042f..32ac8f035 100644 --- a/source/games/exhumed/src/exhumed.h +++ b/source/games/exhumed/src/exhumed.h @@ -225,7 +225,6 @@ struct GameInterface : ::GameInterface void SerializeGameState(FSerializer& arc); bool CanSave() override; ReservedSpace GetReservedScreenSpace(int viewsize) override { return { 0, 24 }; } - void QuitToTitle() override; void UpdateSounds() override; void ErrorCleanup() override; void Ticker() override; diff --git a/source/games/exhumed/src/gameloop.cpp b/source/games/exhumed/src/gameloop.cpp index ab08b2721..644e45d1b 100644 --- a/source/games/exhumed/src/gameloop.cpp +++ b/source/games/exhumed/src/gameloop.cpp @@ -79,7 +79,7 @@ void GameInterface::Render() DrawView(smoothratio); DrawStatusBar(); - DrawCrosshair(MAXTILES, PlayerList[nLocalPlayer].nHealth >> 3, -PlayerList[nLocalPlayer].angle.look_anghalf(smoothratio), 0, 1); + DrawCrosshair(kCrosshairTile, PlayerList[nLocalPlayer].nHealth >> 3, -PlayerList[nLocalPlayer].angle.look_anghalf(smoothratio), 0, 1); if (paused && !M_Active()) { diff --git a/source/games/exhumed/src/init.cpp b/source/games/exhumed/src/init.cpp index 5c2c1db7c..031a057aa 100644 --- a/source/games/exhumed/src/init.cpp +++ b/source/games/exhumed/src/init.cpp @@ -156,6 +156,7 @@ uint8_t LoadLevel(MapRecord* map) pSky->tileofs[2] = 0; pSky->tileofs[3] = 0; pSky->yoffs = 256; + pSky->yoffs2 = 256; pSky->lognumtiles = 2; pSky->horizfrac = 65536; pSky->yscale = 65536; diff --git a/source/games/exhumed/src/map.cpp b/source/games/exhumed/src/map.cpp index 0cd8a570f..80d7357cc 100644 --- a/source/games/exhumed/src/map.cpp +++ b/source/games/exhumed/src/map.cpp @@ -23,7 +23,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "view.h" #include "v_2ddrawer.h" #include "automap.h" -#include "mmulti.h" #include "v_draw.h" BEGIN_PS_NS diff --git a/source/games/exhumed/src/namelist.h b/source/games/exhumed/src/namelist.h index 50787ef8d..8d7076723 100644 --- a/source/games/exhumed/src/namelist.h +++ b/source/games/exhumed/src/namelist.h @@ -1,3 +1,4 @@ +x(CrosshairTile, 1579) x(SkullJaw, 3437) x(PowerslaveLogo, 3442) x(MenuNewGameTile, 3460) diff --git a/source/games/exhumed/src/osdcmds.cpp b/source/games/exhumed/src/osdcmds.cpp index 81efd81e8..469843e22 100644 --- a/source/games/exhumed/src/osdcmds.cpp +++ b/source/games/exhumed/src/osdcmds.cpp @@ -31,7 +31,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "cheathandler.h" #include "gamestate.h" #include "gamefuncs.h" -#include "mmulti.h" BEGIN_PS_NS diff --git a/source/games/exhumed/src/save.cpp b/source/games/exhumed/src/save.cpp index 8046808f6..e51bc81a5 100644 --- a/source/games/exhumed/src/save.cpp +++ b/source/games/exhumed/src/save.cpp @@ -22,7 +22,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "raze_music.h" #include "engine.h" #include "exhumed.h" -#include "mmulti.h" #include "savegamehelp.h" #include "sound.h" #include "mapinfo.h" @@ -111,6 +110,7 @@ void GameInterface::SerializeGameState(FSerializer& arc) pSky->tileofs[2] = 0; pSky->tileofs[3] = 0; pSky->yoffs = 256; + pSky->yoffs2 = 256; pSky->lognumtiles = 2; pSky->horizfrac = 65536; pSky->yscale = 65536; diff --git a/source/games/exhumed/src/sound.cpp b/source/games/exhumed/src/sound.cpp index 5f80bf79c..3504bc2f6 100644 --- a/source/games/exhumed/src/sound.cpp +++ b/source/games/exhumed/src/sound.cpp @@ -16,7 +16,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ //------------------------------------------------------------------------- #include "ns.h" -#include "mmulti.h" #include "compat.h" #include "build.h" #include "engine.h" diff --git a/source/games/sw/src/_polymost.cpp b/source/games/sw/src/_polymost.cpp index 903fb96f2..ae6e80d5f 100644 --- a/source/games/sw/src/_polymost.cpp +++ b/source/games/sw/src/_polymost.cpp @@ -29,9 +29,8 @@ ViewSectorInScene(short cursectnum, short level) // found a potential match match = sp->lotag; - if (!PicInView(FAF_MIRROR_PIC, true)) + if (!testgotpic(FAF_MIRROR_PIC, true)) return -1; - return match; } } @@ -136,7 +135,7 @@ void FAF_DrawRooms(int x, int y, int z, fixed_t q16ang, fixed_t q16horiz, short // manually set gotpic if (gotsector[sprite[i].sectnum]) { - SET_GOTPIC(FAF_MIRROR_PIC); + setgotpic(FAF_MIRROR_PIC); } if (SPRITE_TAG3(i) == 0) @@ -195,25 +194,19 @@ void JS_DrawMirrors(PLAYERp pp, int tx, int ty, int tz, fixed_t tpq16ang, fixed // drift! bool bIsWallMirror = false; - // WARNING! Assuming (MIRRORLABEL&31) = 0 and MAXMIRRORS = 64 <-- JBF: wrong - longptr = (int *)&gotpic[MIRRORLABEL >> 3]; - if (longptr && (longptr[0] || longptr[1])) { for (cnt = MAXMIRRORS - 1; cnt >= 0; cnt--) - //if (TEST_GOTPIC(cnt + MIRRORLABEL) || TEST_GOTPIC(cnt + CAMSPRITE)) - if (TEST_GOTPIC(cnt + MIRRORLABEL) || ((unsigned)mirror[cnt].campic < MAXTILES && TEST_GOTPIC(mirror[cnt].campic))) + //if (testgotpic(cnt + MIRRORLABEL) || testgotpic(cnt + CAMSPRITE)) + if (testgotpic(cnt + MIRRORLABEL) || ((unsigned)mirror[cnt].campic < MAXTILES && testgotpic(mirror[cnt].campic))) { bIsWallMirror = false; - if (TEST_GOTPIC(cnt + MIRRORLABEL)) + if (testgotpic(cnt + MIRRORLABEL, true)) { bIsWallMirror = true; - RESET_GOTPIC(cnt + MIRRORLABEL); } - //else if (TEST_GOTPIC(cnt + CAMSPRITE)) - else if ((unsigned)mirror[cnt].campic < MAXTILES && TEST_GOTPIC(mirror[cnt].campic)) + else if ((unsigned)mirror[cnt].campic < MAXTILES && testgotpic(mirror[cnt].campic)) { - //RESET_GOTPIC(cnt + CAMSPRITE); - RESET_GOTPIC(mirror[cnt].campic); + cleargotpic(mirror[cnt].campic); } mirrorinview = true; diff --git a/source/games/sw/src/break.cpp b/source/games/sw/src/break.cpp index b8403d267..5fd3e09b2 100644 --- a/source/games/sw/src/break.cpp +++ b/source/games/sw/src/break.cpp @@ -478,10 +478,6 @@ BREAK_INFOp SetupWallForBreak(WALLp wallp) { wallp->lotag = TAG_WALL_BREAK; SET(wallp->extra, WALLFX_DONT_STICK); - - // set for cacheing - if (break_info->breaknum >= 0) - SET_GOTPIC(break_info->breaknum); } if (wallp->overpicnum > 0 && TEST(wallp->cstat, CSTAT_WALL_MASKED)) @@ -528,10 +524,6 @@ BREAK_INFOp SetupSpriteForBreak(SPRITEp sp) sp->clipdist = SPRITEp_SIZE_X(sp); SET(sp->cstat, CSTAT_SPRITE_BREAKABLE); - - // set for cacheing - if (break_info->breaknum >= 0) - SET_GOTPIC(break_info->breaknum); } return break_info; diff --git a/source/games/sw/src/d_menu.cpp b/source/games/sw/src/d_menu.cpp index e1425e8ec..2cf495f84 100644 --- a/source/games/sw/src/d_menu.cpp +++ b/source/games/sw/src/d_menu.cpp @@ -1,11 +1,11 @@ //------------------------------------------------------------------------- /* -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. +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -61,13 +61,6 @@ BEGIN_SW_NS // //---------------------------------------------------------------------------- -void GameInterface::QuitToTitle() -{ - Mus_Stop(); - gameaction = ga_mainmenu; -} - - void GameInterface::MenuSound(EMenuSounds snd) { switch (snd) diff --git a/source/games/sw/src/draw.cpp b/source/games/sw/src/draw.cpp index 524e2ef0b..7bb9dc414 100644 --- a/source/games/sw/src/draw.cpp +++ b/source/games/sw/src/draw.cpp @@ -1365,7 +1365,6 @@ void PreDrawStackedWater(void) short ScreenSavePic = false; -bool PicInView(short, bool); void DoPlayerDiveMeter(PLAYERp pp); void polymost_drawscreen(PLAYERp pp, int tx, int ty, int tz, binangle tang, fixedhoriz thoriz, int tsectnum); @@ -1374,9 +1373,12 @@ void polymost_drawscreen(PLAYERp pp, int tx, int ty, int tz, binangle tang, fixe void UpdateWallPortalState() { // This is too obtuse to be maintained statically, but with 8 mirrors at most easy to be kept up to date. - for (int i = 0; i < MAXMIRRORS; i++) + for (int i = 0; i < mirrorcnt; i++) { - auto wal = &wall[mirror[i].mirrorwall]; + if (mirror[i].mirrorwall < 0) { + continue; + } + walltype* wal = &wall[mirror[i].mirrorwall]; wal->portalflags = 0; wal->portalnum = 0; @@ -1608,20 +1610,6 @@ drawscreen(PLAYERp pp, double smoothratio) if (!ScreenSavePic) UpdatePanel(smoothratio); -#define SLIME 2305 - // Only animate lava if its picnum is on screen - // gotpic is a bit array where the tile number's bit is set - // whenever it is drawn (ceilings, walls, sprites, etc.) -#if 0 // This needs a different implementation. - if ((gotpic[SLIME >> 3] & (1 << (SLIME & 7))) > 0) - { - gotpic[SLIME >> 3] &= ~(1 << (SLIME & 7)); - - if (waloff[SLIME]) - movelava((char *) waloff[SLIME]); - } -#endif - // if doing a screen save don't need to process the rest if (ScreenSavePic) { diff --git a/source/games/sw/src/game.h b/source/games/sw/src/game.h index 0b950d29b..f2c7d24ad 100644 --- a/source/games/sw/src/game.h +++ b/source/games/sw/src/game.h @@ -38,7 +38,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "build.h" #include "compat.h" -#include "mmulti.h" +#include "d_net.h" #include "mytypes.h" #include "sounds.h" @@ -354,10 +354,6 @@ inline int SPRITEp_SIZE_BOS(const spritetype* sp) // just determine if the player is moving #define PLAYER_MOVING(pp) ((pp)->xvect|(pp)->yvect) -#define TEST_GOTPIC(tile_num) (TEST(gotpic[(tile_num) >> 3], 1 << ((tile_num) & 7))) -#define RESET_GOTPIC(tile_num) (RESET(gotpic[(tile_num) >> 3], 1 << ((tile_num) & 7))) -#define SET_GOTPIC(tile_num) (SET(gotpic[(tile_num) >> 3], 1 << ((tile_num) & 7))) - #define LOW_TAG(sectnum) ( sector[sectnum].lotag ) #define HIGH_TAG(sectnum) ( sector[sectnum].hitag ) @@ -2250,8 +2246,7 @@ struct GameInterface : ::GameInterface void SetAmbience(bool on) override { if (on) StartAmbientSound(); else StopAmbientSound(); } FString GetCoordString() override; ReservedSpace GetReservedScreenSpace(int viewsize) override; - void QuitToTitle() override; - void UpdateSounds() override; + void UpdateSounds() override; void ErrorCleanup() override; void GetInput(InputPacket* input, ControlInfo* const hidInput) override; void DrawBackground(void) override; diff --git a/source/games/sw/src/jsector.cpp b/source/games/sw/src/jsector.cpp index aefe4c442..0f81b8245 100644 --- a/source/games/sw/src/jsector.cpp +++ b/source/games/sw/src/jsector.cpp @@ -559,9 +559,6 @@ void JS_DrawCameras(PLAYERp pp, int tx, int ty, int tz, double smoothratio) } lastcamclock = camclock; - // WARNING! Assuming (MIRRORLABEL&31) = 0 and MAXMIRRORS = 64 <-- JBF: wrong - longptr = (int*)&gotpic[MIRRORLABEL >> 3]; - if (longptr && (longptr[0] || longptr[1])) { uint32_t oscilation_delta = camclock - oscilationclock; oscilation_delta -= oscilation_delta % 4; @@ -571,11 +568,10 @@ void JS_DrawCameras(PLAYERp pp, int tx, int ty, int tz, double smoothratio) { if (!mirror[cnt].ismagic) continue; // these are definitely not camera textures. - //if (TEST_GOTPIC(cnt + MIRRORLABEL) || TEST_GOTPIC(cnt + CAMSPRITE)) - if (TEST_GOTPIC(cnt + MIRRORLABEL) || ((unsigned)mirror[cnt].campic < MAXTILES && TEST_GOTPIC(mirror[cnt].campic))) + if (testgotpic(cnt + MIRRORLABEL) || ((unsigned)mirror[cnt].campic < MAXTILES && testgotpic(mirror[cnt].campic))) { // Do not change any global state here! - bIsWallMirror = !!(TEST_GOTPIC(cnt + MIRRORLABEL)); + bIsWallMirror = testgotpic(cnt + MIRRORLABEL); dist = 0x7fffffff; if (bIsWallMirror) diff --git a/source/games/sw/src/network.cpp b/source/games/sw/src/network.cpp index e449f6754..ac9592e19 100644 --- a/source/games/sw/src/network.cpp +++ b/source/games/sw/src/network.cpp @@ -26,7 +26,6 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms #include "ns.h" #include "build.h" -#include "mmulti.h" #include "gamecontrol.h" diff --git a/source/games/sw/src/rooms.cpp b/source/games/sw/src/rooms.cpp index 4dd1098b7..cf561f10b 100644 --- a/source/games/sw/src/rooms.cpp +++ b/source/games/sw/src/rooms.cpp @@ -633,21 +633,6 @@ void FAFgetzrangepoint(int32_t x, int32_t y, int32_t z, int16_t sectnum, } } -// doesn't work for blank pics -bool -PicInView(short tile_num, bool reset) -{ - if (TEST(gotpic[tile_num >> 3], 1 << (tile_num & 7))) - { - if (reset) - RESET(gotpic[tile_num >> 3], 1 << (tile_num & 7)); - - return true; - } - - return false; -} - void SetupMirrorTiles(void) { @@ -1182,7 +1167,7 @@ void CollectPortals() auto pt2 = findother(pt.othersector); if (pt2) { - int pnum = portalAdd(PORTAL_SECTOR_FLOOR, -1, pt.offset.x, pt.offset.y, 0); + int pnum = portalAdd(PORTAL_SECTOR_CEILING, -1, pt.offset.x, pt.offset.y, 0); allPortals[pnum].targets = std::move(pt2->sectors); for (auto sec : pt.sectors) { diff --git a/source/games/sw/src/sprite.cpp b/source/games/sw/src/sprite.cpp index fb93034c1..6646bae45 100644 --- a/source/games/sw/src/sprite.cpp +++ b/source/games/sw/src/sprite.cpp @@ -870,6 +870,7 @@ SpawnUser(short SpriteNum, short id, STATEp state) ASSERT(!Prediction); + User[SpriteNum].Clear(); // make sure to delete old, stale content first! User[SpriteNum].Alloc(); u = User[SpriteNum].Data(); diff --git a/wadsrc/static/engine/grpinfo.txt b/wadsrc/static/engine/grpinfo.txt index 7982dcbc5..2fd0789ef 100644 --- a/wadsrc/static/engine/grpinfo.txt +++ b/wadsrc/static/engine/grpinfo.txt @@ -50,7 +50,7 @@ grpinfo size 26524524 crc DUKE13_CRC flags GAMEFLAG_DUKE - gamefilter "Duke.Duke" + gamefilter "Duke.Duke.13" dependency 0 FgColor 0xffff00 BkColor 0xff6f00 @@ -63,7 +63,7 @@ grpinfo size 26385383 crc DUKEKR_CRC flags GAMEFLAG_DUKE - gamefilter "Duke.Duke" + gamefilter "Duke.Duke.13" dependency 0 FgColor 0xffff00 BkColor 0xff6f00 @@ -76,7 +76,7 @@ grpinfo size 44356548 crc DUKE15_CRC flags GAMEFLAG_DUKE - gamefilter "Duke.Duke" + gamefilter "Duke.Duke.15" dependency 0 FgColor 0xffff00 BkColor 0xff6f00 @@ -89,7 +89,7 @@ grpinfo size 44356548 crc DukeWorldTour_CRC flags GAMEFLAG_DUKE - gamefilter "Duke.Duke" + gamefilter "Duke.Duke.15" dependency 0 FgColor 0xffff00 BkColor 0xff6f00 @@ -102,7 +102,7 @@ grpinfo // another variant? I got this one, dated 2016-10-12 size 44486702 crc 0x89792E05 flags GAMEFLAG_DUKE - gamefilter "Duke.Duke" + gamefilter "Duke.Duke.15" dependency 0 FgColor 0xffff00 BkColor 0xff6f00 @@ -115,7 +115,7 @@ grpinfo size 44348015 crc DUKEPP_CRC flags GAMEFLAG_DUKE - gamefilter "Duke.Duke" + gamefilter "Duke.Duke.15" dependency 0 FgColor 0xffff00 BkColor 0xff6f00 @@ -201,7 +201,7 @@ grpinfo crc DUKEDC13_CRC flags GAMEFLAG_DUKE|GAMEFLAG_ADDON|GAMEFLAG_DUKEDC dependency DUKE13_CRC - gamefilter "Duke.DukeDC" + gamefilter "Duke.DukeDC.13" GameID "DukeDC13" } @@ -212,7 +212,7 @@ grpinfo crc DUKEDCPP_CRC flags GAMEFLAG_DUKE|GAMEFLAG_ADDON|GAMEFLAG_DUKEDC dependency DUKE15_CRC - gamefilter "Duke.DukeDC" + gamefilter "Duke.DukeDC.13" GameID "DukeDC" } @@ -223,7 +223,7 @@ grpinfo crc DUKEDC_CRC flags GAMEFLAG_DUKE|GAMEFLAG_ADDON|GAMEFLAG_DUKEDC dependency DUKE15_CRC - gamefilter "Duke.DukeDC" + gamefilter "Duke.DukeDC.15" GameID "DukeDC" } @@ -235,14 +235,49 @@ grpinfo crc 0x39A692BF flags GAMEFLAG_DUKE|GAMEFLAG_ADDON|GAMEFLAG_DUKEDC dependency DUKE15_CRC - gamefilter "Duke.DukeDC" + gamefilter "Duke.DukeDC.15" GameID "DukeDC" } -// These are a bit strange but without anything to check I do not know in what way. -// { "Duke Caribbean: Life's a Beach (1.3D)", VACA13_CRC, 23559381, GAMEFLAG_DUKE|GAMEFLAG_ADDON, DUKE13_CRC, NULL, process_vaca13}, -// { "Duke Caribbean: Life's a Beach (PPak)", VACAPP_CRC, 22551333, GAMEFLAG_DUKE|GAMEFLAG_ADDON, DUKEPP_CRC, NULL, process_vacapp15}, -// { "Duke Caribbean: Life's a Beach", VACA15_CRC, 22521880, GAMEFLAG_DUKE|GAMEFLAG_ADDON, DUKE15_CRC, NULL, process_vacapp15}, +grpinfo +{ + name "Duke Caribbean: Life's a Beach (1.3)" + size 23559381 + crc VACA13_CRC + flags GAMEFLAG_DUKE|GAMEFLAG_ADDON + dependency DUKE13_CRC + gamefilter "Duke.Vacation.13" + FgColor 0x00004f + BkColor 0x8f8fff + GameID "DukeVacation13" +} + +grpinfo +{ + name "Duke Caribbean: Life's a Beach" + size 22551333 + crc VACAPP_CRC + flags GAMEFLAG_DUKE|GAMEFLAG_ADDON + dependency DUKE15_CRC + gamefilter "Duke.Vacation.15" + FgColor 0x00004f + BkColor 0x8f8fff + GameID "DukeVacation" +} + +grpinfo +{ + name "Duke Caribbean: Life's a Beach" + size 22521880 + crc VACA15_CRC + flags GAMEFLAG_DUKE|GAMEFLAG_ADDON + dependency DUKE15_CRC + gamefilter "Duke.Vacation.15" + FgColor 0x00004f + BkColor 0x8f8fff + GameID "DukeVacation" +} + grpinfo { @@ -251,7 +286,7 @@ grpinfo crc DUKECB_CRC flags GAMEFLAG_DUKE|GAMEFLAG_ADDON|GAMEFLAG_DUKEVACA dependency DUKE15_CRC - gamefilter "Duke.Vacation" + gamefilter "Duke.Vacation.15" FgColor 0x00004f BkColor 0x8f8fff GameID "DukeVacation" @@ -265,7 +300,7 @@ grpinfo crc 0x65B5F690 flags GAMEFLAG_DUKE|GAMEFLAG_ADDON|GAMEFLAG_DUKEVACA dependency DUKE15_CRC - gamefilter "Duke.Vacation" + gamefilter "Duke.Vacation.15" FgColor 0x00004f BkColor 0x8f8fff GameID "DukeVacation" @@ -315,7 +350,7 @@ grpinfo crc 0xC7EFBFA9 flags GAMEFLAG_DUKE|GAMEFLAG_ADDON dependency DUKE13_CRC - gamefilter "Duke.Zone" + gamefilter "Duke.Zone.13" } grpinfo @@ -326,7 +361,7 @@ grpinfo crc DZ2_PP_CRC flags GAMEFLAG_DUKE|GAMEFLAG_ADDON dependency DUKE15_CRC - gamefilter "Duke.Zone" + gamefilter "Duke.Zone.15" } grpinfo @@ -337,7 +372,7 @@ grpinfo crc 0x1E9516F1 flags GAMEFLAG_DUKE|GAMEFLAG_ADDON dependency DUKE13_CRC - gamefilter "Duke.Zone" + gamefilter "Duke.Zone.13" } grpinfo diff --git a/wadsrc/static/filter/duke.duke.13/engine/engine.con b/wadsrc/static/filter/duke.duke.13/engine/engine.con new file mode 100644 index 000000000..7f607f47b --- /dev/null +++ b/wadsrc/static/filter/duke.duke.13/engine/engine.con @@ -0,0 +1,9 @@ +definevolumename 0 L.A. MELTDOWN +definevolumename 1 LUNAR APOCALYPSE +definevolumename 2 SHRAPNEL CITY + +defineskillname 0 PIECE OF CAKE +defineskillname 1 LET'S ROCK +defineskillname 2 COME GET SOME +defineskillname 3 DAMN I'M GOOD + diff --git a/wadsrc/static/filter/duke.dukedc.13/engine/engine.con b/wadsrc/static/filter/duke.dukedc.13/engine/engine.con new file mode 100644 index 000000000..87c25aeb4 --- /dev/null +++ b/wadsrc/static/filter/duke.dukedc.13/engine/engine.con @@ -0,0 +1,9 @@ +definevolumename 0 L.A. MELTDOWN +definevolumename 1 DUKE IT OUT IN D.C. +definevolumename 2 SHRAPNEL CITY + +defineskillname 0 PIECE OF CAKE +defineskillname 1 LET'S ROCK +defineskillname 2 COME GET SOME +defineskillname 3 DAMN I'M GOOD + diff --git a/wadsrc/static/filter/duke.vacation.13/engine/engine.con b/wadsrc/static/filter/duke.vacation.13/engine/engine.con new file mode 100644 index 000000000..b3baafdfe --- /dev/null +++ b/wadsrc/static/filter/duke.vacation.13/engine/engine.con @@ -0,0 +1,8 @@ +definevolumename 0 L.A. MELTDOWN +definevolumename 1 VACATION DUKEMATCH +definevolumename 2 LIFE'S A BEACH + +defineskillname 0 LOW TIDE +defineskillname 1 MAKIN' WAVES +defineskillname 2 BIG KAHUNA +defineskillname 3 TSUNAMI diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index da9417acd..cc8373328 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -650,7 +650,7 @@ OptionMenu "ChatControlsMenu" protected StaticTextSwitchable "$CNTRLMNU_SWITCHTEXT1", "$CNTRLMNU_SWITCHTEXT2", "ControlMessage" StaticText "" - Control "$CNTRLMNU_SAY" , "+send_message" + Control "$CNTRLMNU_SAY" , "messagemode" } OptionMenu "WeaponsControlMenu" protected