diff --git a/specs/usdf_zdoom.txt b/specs/usdf_zdoom.txt index cd4393351..2025b06ba 100644 --- a/specs/usdf_zdoom.txt +++ b/specs/usdf_zdoom.txt @@ -92,6 +92,8 @@ conversation // Starts a dialog. choice { + specialname = ; // Allows specifying a special by name. + // The amount of an item needed for this option to become available. // You can have as many as needed. All require blocks must be satisfied // to show this option. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 124c7320e..f90d92be2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -249,22 +249,6 @@ if (NOT ZDOOM_USE_SSE2) endif() endif() -if( SSE_MATTERS ) - if( WIN32 ) - set( BACKPATCH 1 CACHE BOOL "Enable backpatching." ) - else() - CHECK_FUNCTION_EXISTS(mprotect HAVE_MPROTECT) - if( HAVE_MPROTECT ) - set( BACKPATCH 1 CACHE BOOL "Enable backpatching." ) - else() - set( BACKPATCH 0 ) - endif() - endif() - set( SSE 1 CACHE BOOL "Build SSE and SSE2 versions of key code." ) -else() - set( BACKPATCH 0 ) -endif() - if( X64 ) set( HAVE_MMX 1 ) else( X64 ) @@ -429,10 +413,6 @@ endif() # Flags -if( BACKPATCH ) - add_definitions( -DBACKPATCH ) -endif() - # Update gitinfo.h add_custom_target( revision_check ALL @@ -574,18 +554,6 @@ add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h include_directories( ${CMAKE_CURRENT_BINARY_DIR} ) -if( SSE_MATTERS ) - if( SSE ) - set( X86_SOURCES nodebuild_classify_sse2.cpp ) - set_source_files_properties( nodebuild_classify_sse2.cpp PROPERTIES COMPILE_FLAGS "${SSE2_ENABLE}" ) - else() - add_definitions( -DDISABLE_SSE ) - endif() -else() - add_definitions( -DDISABLE_SSE ) - set( X86_SOURCES ) -endif() - if( SNDFILE_FOUND ) add_definitions( -DHAVE_SNDFILE ) endif() diff --git a/src/actionspecials.h b/src/actionspecials.h index 42861b702..aac1b7161 100644 --- a/src/actionspecials.h +++ b/src/actionspecials.h @@ -15,7 +15,7 @@ DEFINE_SPECIAL(Door_LockedRaise, 13, 4, 5, 5) DEFINE_SPECIAL(Door_Animated, 14, 4, 4, 4) DEFINE_SPECIAL(Autosave, 15, 0, 0, 0) // [RH] Save the game *now* DEFINE_SPECIAL(Transfer_WallLight, 16, -1, -1, 2) -DEFINE_SPECIAL(Thing_Raise, 17, 1, 1, 1) +DEFINE_SPECIAL(Thing_Raise, 17, 1, 2, 2) DEFINE_SPECIAL(StartConversation, 18, 1, 2, 2) DEFINE_SPECIAL(Thing_Stop, 19, 1, 1, 1) DEFINE_SPECIAL(Floor_LowerByValue, 20, 3, 4, 4) diff --git a/src/actor.h b/src/actor.h index 908ed17b2..d5fef1b36 100644 --- a/src/actor.h +++ b/src/actor.h @@ -390,6 +390,7 @@ enum ActorFlag7 MF7_NOSHIELDREFLECT = 0x08000000, // will not be reflected by shields. MF7_FORCEZERORADIUSDMG = 0x10000000, // passes zero radius damage on to P_DamageMobj, this is necessary in some cases where DoSpecialDamage gets overrideen. MF7_NOINFIGHTSPECIES = 0x20000000, // don't start infights with one's own species. + MF7_FORCEINFIGHTING = 0x40000000, // overrides a map setting of 'no infighting'. }; // --- mobj.renderflags --- @@ -430,6 +431,7 @@ enum ActorRenderFlag RF_ABSMASKPITCH = 0x00800000, // [MC] The mask rotation does not offset by the actor's pitch. RF_INTERPOLATEANGLES = 0x01000000, // [MC] Allow interpolation of the actor's angle, pitch and roll. RF_MAYBEINVISIBLE = 0x02000000, + RF_DONTINTERPOLATE = 0x04000000, // no render interpolation ever! }; // This translucency value produces the closest match to Heretic's TINTTAB. @@ -1321,7 +1323,8 @@ public: } DVector3 InterpolatedPosition(double ticFrac) const { - return Prev + (ticFrac * (Pos() - Prev)); + if (renderflags & RF_DONTINTERPOLATE) return Pos(); + else return Prev + (ticFrac * (Pos() - Prev)); } DRotator InterpolatedAngles(double ticFrac) const { diff --git a/src/am_map.cpp b/src/am_map.cpp index ba4af30fb..15f3b5586 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -91,7 +91,7 @@ CVAR (Bool, am_customcolors, true, CVAR_ARCHIVE); CVAR (Int, am_map_secrets, 1, CVAR_ARCHIVE); CVAR (Int, am_drawmapback, 1, CVAR_ARCHIVE); CVAR (Bool, am_showkeys, true, CVAR_ARCHIVE); -CVAR (Bool, am_showtriggerlines, false, CVAR_ARCHIVE); +CVAR (Int, am_showtriggerlines, 0, CVAR_ARCHIVE); CVAR (Int, am_showthingsprites, 0, CVAR_ARCHIVE); //============================================================================= @@ -2282,58 +2282,47 @@ bool AM_checkSpecialBoundary (line_t &line, bool (*function)(int, int *), int *s return (line.backsector && AM_checkSectorActions(line.backsector, function, specialptr, argsptr, false)); } -bool AM_isTeleportSpecial (int special, int *) -{ - return (special == Teleport || - special == Teleport_NoFog || - special == Teleport_ZombieChanger || - special == Teleport_Line); -} - bool AM_isTeleportBoundary (line_t &line) { - return AM_checkSpecialBoundary(line, &AM_isTeleportSpecial); -} - -bool AM_isExitSpecial (int special, int *) -{ - return (special == Teleport_NewMap || - special == Teleport_EndGame || - special == Exit_Normal || - special == Exit_Secret); + return AM_checkSpecialBoundary(line, [](int special, int *) + { + return (special == Teleport || + special == Teleport_NoFog || + special == Teleport_ZombieChanger || + special == Teleport_Line); + }); } bool AM_isExitBoundary (line_t& line) { - return AM_checkSpecialBoundary(line, &AM_isExitSpecial); -} - -bool AM_isTriggerSpecial (int special, int *) -{ - FLineSpecial *spec = P_GetLineSpecialInfo(special); - return spec != NULL - && spec->max_args >= 0 - && special != Door_Open - && special != Door_Close - && special != Door_CloseWaitOpen - && special != Door_Raise - && special != Door_Animated - && special != Generic_Door; + return AM_checkSpecialBoundary(line, [](int special, int *) + { + return (special == Teleport_NewMap || + special == Teleport_EndGame || + special == Exit_Normal || + special == Exit_Secret); + }); } bool AM_isTriggerBoundary (line_t &line) { - return AM_checkSpecialBoundary(line, &AM_isTriggerSpecial); -} - -bool AM_isLockSpecial (int special, int* args) -{ - return special == Door_LockedRaise - || special == ACS_LockedExecute - || special == ACS_LockedExecuteDoor - || (special == Door_Animated && args[3] != 0) - || (special == Generic_Door && args[4] != 0) - || (special == FS_Execute && args[2] != 0); + return am_showtriggerlines == 1? AM_checkSpecialBoundary(line, [](int special, int *) + { + FLineSpecial *spec = P_GetLineSpecialInfo(special); + return spec != NULL + && spec->max_args >= 0 + && special != Door_Open + && special != Door_Close + && special != Door_CloseWaitOpen + && special != Door_Raise + && special != Door_Animated + && special != Generic_Door; + }) : AM_checkSpecialBoundary(line, [](int special, int *) + { + FLineSpecial *spec = P_GetLineSpecialInfo(special); + return spec != NULL + && spec->max_args >= 0; + }); } bool AM_isLockBoundary (line_t &line, int *lockptr = NULL) @@ -2352,7 +2341,15 @@ bool AM_isLockBoundary (line_t &line, int *lockptr = NULL) int special; int *args; - bool result = AM_checkSpecialBoundary(line, &AM_isLockSpecial, &special, &args); + bool result = AM_checkSpecialBoundary(line, [](int special, int* args) + { + return special == Door_LockedRaise + || special == ACS_LockedExecute + || special == ACS_LockedExecuteDoor + || (special == Door_Animated && args[3] != 0) + || (special == Generic_Door && args[4] != 0) + || (special == FS_Execute && args[2] != 0); + }, &special, &args); if (result) { diff --git a/src/c_cmds.cpp b/src/c_cmds.cpp index ff83d8342..7e0a66c4b 100644 --- a/src/c_cmds.cpp +++ b/src/c_cmds.cpp @@ -937,14 +937,20 @@ static void PrintFilteredActorList(const ActorTypeChecker IsActorType, const cha AActor *mo; const PClass *FilterClass = NULL; int counter = 0; + int tid = 0; if (FilterName != NULL) { FilterClass = PClass::FindActor(FilterName); if (FilterClass == NULL) { - Printf("%s is not an actor class.\n", FilterName); - return; + char *endp; + tid = (int)strtol(FilterName, &endp, 10); + if (*endp != 0) + { + Printf("%s is not an actor class.\n", FilterName); + return; + } } } TThinkerIterator it; @@ -953,10 +959,13 @@ static void PrintFilteredActorList(const ActorTypeChecker IsActorType, const cha { if ((FilterClass == NULL || mo->IsA(FilterClass)) && IsActorType(mo)) { - counter++; - if (!countOnly) - Printf ("%s at (%f,%f,%f)\n", - mo->GetClass()->TypeName.GetChars(), mo->X(), mo->Y(), mo->Z()); + if (tid == 0 || tid == mo->tid) + { + counter++; + if (!countOnly) + Printf("%s at (%f,%f,%f)\n", + mo->GetClass()->TypeName.GetChars(), mo->X(), mo->Y(), mo->Z()); + } } } Printf("%i match(s) found.\n", counter); diff --git a/src/d_net.cpp b/src/d_net.cpp index f6ea9efc6..b92c709fe 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -2377,25 +2377,8 @@ void Net_DoCommand (int type, BYTE **stream, int player) break; case DEM_SPRAY: - { - FTraceResults trace; - - DAngle ang = players[player].mo->Angles.Yaw; - DAngle pitch = players[player].mo->Angles.Pitch; - double c = pitch.Cos(); - DVector3 vec(c * ang.Cos(), c * ang.Sin(), -pitch.Sin()); - - s = ReadString (stream); - - if (Trace (players[player].mo->PosPlusZ(players[player].mo->Height/2), players[player].mo->Sector, - vec, 172., 0, ML_BLOCKEVERYTHING, players[player].mo, trace, TRACE_NoSky)) - { - if (trace.HitType == TRACE_HitWall) - { - DImpactDecal::StaticCreate (s, trace.HitPos, trace.Line->sidedef[trace.Side], NULL); - } - } - } + s = ReadString(stream); + SprayDecal(players[player].mo, s); break; case DEM_PAUSE: diff --git a/src/d_player.h b/src/d_player.h index 6dede3d82..7eae93176 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -210,13 +210,7 @@ typedef enum CF_TOTALLYFROZEN = 1 << 12, // [RH] All players can do is press +use CF_PREDICTING = 1 << 13, // [RH] Player movement is being predicted CF_INTERPVIEW = 1 << 14, // [RH] view was changed outside of input, so interpolate one frame - CF_DRAIN = 1 << 16, // Player owns a drain powerup - CF_HIGHJUMP = 1 << 18, // more Skulltag flags. Implementation not guaranteed though. ;) - CF_REFLECTION = 1 << 19, - CF_PROSPERITY = 1 << 20, - CF_DOUBLEFIRINGSPEED= 1 << 21, // Player owns a double firing speed artifact CF_EXTREMELYDEAD = 1 << 22, // [RH] Reliably let the status bar know about extreme deaths. - CF_INFINITEAMMO = 1 << 23, // Player owns an infinite ammo artifact CF_BUDDHA2 = 1 << 24, // [MC] Absolute buddha. No voodoo can kill it either. CF_GODMODE2 = 1 << 25, // [MC] Absolute godmode. No voodoo can kill it either. CF_BUDDHA = 1 << 27, // [SP] Buddha mode - take damage, but don't die diff --git a/src/g_game.cpp b/src/g_game.cpp index 84a6cf1ec..ac1cc1d81 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1344,12 +1344,24 @@ void G_PlayerFinishLevel (int player, EFinishLevelType mode, int flags) if (mode == FINISH_NoHub && !(level.flags2 & LEVEL2_KEEPFULLINVENTORY)) { // Reduce all owned (visible) inventory to defined maximum interhub amount + TArray todelete; for (item = p->mo->Inventory; item != NULL; item = item->Inventory) { // If the player is carrying more samples of an item than allowed, reduce amount accordingly if (item->ItemFlags & IF_INVBAR && item->Amount > item->InterHubAmount) { item->Amount = item->InterHubAmount; + if ((level.flags3 & LEVEL3_RESETINVENTORY) && !(item->ItemFlags & IF_UNDROPPABLE)) + { + todelete.Push(item); + } + } + } + for (auto it : todelete) + { + if (!(it->ObjectFlags & OF_EuthanizeMe)) + { + it->DepleteOrDestroy(); } } } diff --git a/src/g_level.h b/src/g_level.h index d59a4fc09..03fa70dcd 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -223,6 +223,7 @@ enum ELevelFlags : unsigned int // More flags! LEVEL3_FORCEFAKECONTRAST = 0x00000001, // forces fake contrast even with fog enabled + LEVEL3_RESETINVENTORY = 0x00000002, // kills all INVBAR items on map change. }; @@ -324,6 +325,7 @@ struct level_info_t FString ExitPic; FString InterMusic; int intermusicorder; + TMap > MapInterMusic; FString SoundInfo; FString SndSeq; @@ -495,6 +497,7 @@ enum EFSkillProperty // floating point properties SKILLP_Aggressiveness, SKILLP_MonsterHealth, SKILLP_FriendlyHealth, + SKILLP_KickbackFactor, }; int G_SkillProperty(ESkillProperty prop); @@ -512,6 +515,7 @@ struct FSkillInfo double DamageFactor; double ArmorFactor; double HealthFactor; + double KickbackFactor; bool FastMonsters; bool SlowMonsters; diff --git a/src/g_mapinfo.cpp b/src/g_mapinfo.cpp index f83e18ece..7a7960115 100644 --- a/src/g_mapinfo.cpp +++ b/src/g_mapinfo.cpp @@ -915,6 +915,18 @@ DEFINE_MAP_OPTION(intermusic, true) parse.ParseMusic(info->InterMusic, info->intermusicorder); } +DEFINE_MAP_OPTION(mapintermusic, true) +{ + parse.ParseAssign(); + parse.sc.MustGetString(); + FString mapname = parse.sc.String; + FString music; + int order; + parse.ParseComma(); + parse.ParseMusic(music, order); + info->MapInterMusic[FName(mapname)] = std::make_pair(music, order); +} + DEFINE_MAP_OPTION(fadetable, true) { parse.ParseAssign(); @@ -1265,6 +1277,7 @@ MapFlagHandlers[] = { "laxmonsteractivation", MITYPE_SETFLAG2, LEVEL2_LAXMONSTERACTIVATION, LEVEL2_LAXACTIVATIONMAPINFO }, { "additive_scrollers", MITYPE_COMPATFLAG, COMPATF_BOOMSCROLL, 0 }, { "keepfullinventory", MITYPE_SETFLAG2, LEVEL2_KEEPFULLINVENTORY, 0 }, + { "resetitems", MITYPE_SETFLAG3, LEVEL2_RESETINVENTORY, 0 }, { "monsterfallingdamage", MITYPE_SETFLAG2, LEVEL2_MONSTERFALLINGDAMAGE, 0 }, { "nomonsterfallingdamage", MITYPE_CLRFLAG2, LEVEL2_MONSTERFALLINGDAMAGE, 0 }, { "clipmidtextures", MITYPE_SETFLAG2, LEVEL2_CLIPMIDTEX, 0 }, diff --git a/src/g_shared/a_decals.cpp b/src/g_shared/a_decals.cpp index dfa66795c..21f116b07 100644 --- a/src/g_shared/a_decals.cpp +++ b/src/g_shared/a_decals.cpp @@ -704,6 +704,24 @@ CCMD (spray) Net_WriteString (argv[1]); } +void SprayDecal(AActor *shooter, const char *name) +{ + FTraceResults trace; + + DAngle ang = shooter->Angles.Yaw; + DAngle pitch = shooter->Angles.Pitch; + double c = pitch.Cos(); + DVector3 vec(c * ang.Cos(), c * ang.Sin(), -pitch.Sin()); + + if (Trace(shooter->PosPlusZ(shooter->Height / 2), shooter->Sector, vec, 172., 0, ML_BLOCKEVERYTHING, shooter, trace, TRACE_NoSky)) + { + if (trace.HitType == TRACE_HitWall) + { + DImpactDecal::StaticCreate(name, trace.HitPos, trace.Line->sidedef[trace.Side], NULL); + } + } +} + DBaseDecal *ShootDecal(const FDecalTemplate *tpl, AActor *basisactor, sector_t *sec, double x, double y, double z, DAngle angle, double tracedist, bool permanent) { if (tpl == NULL || (tpl = tpl->GetDecal()) == NULL) @@ -751,14 +769,23 @@ IMPLEMENT_CLASS(ADecal, false, false) void ADecal::BeginPlay () { - const FDecalTemplate *tpl; + const FDecalTemplate *tpl = nullptr; Super::BeginPlay (); - int decalid = args[0] + (args[1] << 8); // [KS] High byte for decals. + if (args[0] < 0) + { + FName name = ENamedName(-args[0]); + tpl = DecalLibrary.GetDecalByName(name.GetChars()); + } + else + { + int decalid = args[0] + (args[1] << 8); // [KS] High byte for decals. + tpl = DecalLibrary.GetDecalByNum(decalid); + } // If no decal is specified, don't try to create one. - if (decalid != 0 && (tpl = DecalLibrary.GetDecalByNum (decalid)) != 0) + if (tpl != nullptr) { if (!tpl->PicNum.Exists()) { diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index c9d0d86ce..ea367dd3a 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -11,6 +11,7 @@ struct F3DFloor; class DBaseDecal; class DBaseDecal *ShootDecal(const FDecalTemplate *tpl, AActor *basisactor, sector_t *sec, double x, double y, double z, DAngle angle, double tracedist, bool permanent); +void SprayDecal(AActor *shooter, const char *name); class DBaseDecal : public DThinker { diff --git a/src/g_skill.cpp b/src/g_skill.cpp index d158fa4cd..dd772a745 100644 --- a/src/g_skill.cpp +++ b/src/g_skill.cpp @@ -66,6 +66,7 @@ void FMapInfoParser::ParseSkill () skill.DamageFactor = 1.; skill.ArmorFactor = 1.; skill.HealthFactor = 1.; + skill.KickbackFactor = 1.; skill.FastMonsters = false; skill.SlowMonsters = false; skill.DisableCheats = false; @@ -118,6 +119,12 @@ void FMapInfoParser::ParseSkill () sc.MustGetFloat (); skill.DamageFactor = sc.Float; } + else if (sc.Compare("kickbackfactor")) + { + ParseAssign(); + sc.MustGetFloat(); + skill.KickbackFactor = sc.Float; + } else if (sc.Compare ("fastmonsters")) { skill.FastMonsters = true; @@ -436,6 +443,9 @@ double G_SkillProperty(EFSkillProperty prop) case SKILLP_FriendlyHealth: return AllSkills[gameskill].FriendlyHealth; + case SKILLP_KickbackFactor: + return AllSkills[gameskill].KickbackFactor; + } } return 0; @@ -501,6 +511,7 @@ FSkillInfo &FSkillInfo::operator=(const FSkillInfo &other) DoubleAmmoFactor = other.DoubleAmmoFactor; DropAmmoFactor = other.DropAmmoFactor; DamageFactor = other.DamageFactor; + KickbackFactor = other.KickbackFactor; FastMonsters = other.FastMonsters; SlowMonsters = other.SlowMonsters; DisableCheats = other.DisableCheats; diff --git a/src/gi.cpp b/src/gi.cpp index fa8afb545..672ca3263 100644 --- a/src/gi.cpp +++ b/src/gi.cpp @@ -374,6 +374,7 @@ void FMapInfoParser::ParseGameInfo() GAMEINFOKEY_PATCH(mStatscreenEnteringFont, "statscreen_enteringpatch") GAMEINFOKEY_BOOL(norandomplayerclass, "norandomplayerclass") GAMEINFOKEY_BOOL(forcekillscripts, "forcekillscripts") // [JM] Force kill scripts on thing death. (MF7_NOKILLSCRIPTS overrides.) + GAMEINFOKEY_STRING(Dialogue, "dialogue") else { diff --git a/src/gi.h b/src/gi.h index 24053b002..2c614e3c7 100644 --- a/src/gi.h +++ b/src/gi.h @@ -176,6 +176,7 @@ struct gameinfo_t FName DefaultEndSequence; FString mMapArrow, mCheatMapArrow; FString mEasyKey, mCheatKey; + FString Dialogue; FGIFont mStatscreenMapNameFont; FGIFont mStatscreenFinishedFont; FGIFont mStatscreenEnteringFont; diff --git a/src/menu/messagebox.cpp b/src/menu/messagebox.cpp index a68bbc5f1..a1a0fda76 100644 --- a/src/menu/messagebox.cpp +++ b/src/menu/messagebox.cpp @@ -67,8 +67,7 @@ DMenu *CreateMessageBoxMenu(DMenu *parent, const char *message, int messagemode, { auto c = PClass::FindClass("MessageBoxMenu"); auto p = c->CreateNew(); - const FString msg = '$' == message[0] ? GStrings(message + 1) : message; - VMValue params[] = { p, parent, msg, messagemode, playsound, action.GetIndex(), reinterpret_cast(handler) }; + VMValue params[] = { p, parent, FString(message), messagemode, playsound, action.GetIndex(), reinterpret_cast(handler) }; auto f = dyn_cast(c->Symbols.FindSymbol("Init", false)); GlobalVMStack.Call(f->Variants[0].Implementation, params, countof(params), nullptr, 0); diff --git a/src/namedef.h b/src/namedef.h index 13e9096bc..9cd0a19ec 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -197,6 +197,10 @@ xx(PowerWeaponLevel2) xx(PowerFlight) xx(PowerSpeed) xx(PowerTorch) +xx(PowerHighJump) +xx(PowerReflection) +xx(PowerDrain) +xx(Reflection) xx(CustomInventory) xx(Inventory) xx(CallTryPickup) @@ -356,6 +360,7 @@ xx(CeilingZ) xx(FloorZ) xx(Health) xx(Pitch) +xx(SpecialName) xx(Special) xx(TID) xx(TIDtoHate) diff --git a/src/nodebuild.cpp b/src/nodebuild.cpp index 19dc16b61..6b17c9629 100644 --- a/src/nodebuild.cpp +++ b/src/nodebuild.cpp @@ -1062,95 +1062,3 @@ void FNodeBuilder::PrintSet (int l, DWORD set) } Printf (PRINT_LOG, "*\n"); } - - - -#ifdef BACKPATCH -#ifdef _WIN32 -extern "C" { -__declspec(dllimport) int __stdcall VirtualProtect(void *, unsigned long, unsigned long, unsigned long *); -} -#define PAGE_EXECUTE_READWRITE 64 -#else -#include -#include -#include -#endif - -#ifdef __GNUC__ -extern "C" int ClassifyLineBackpatch (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]) -#else -static int *CallerOffset; -int ClassifyLineBackpatchC (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]) -#endif -{ - // Select the routine based on SSE2 availability and patch the caller so that - // they call that routine directly next time instead of going through here. - int *calleroffset; - int diff; - int (*func)(node_t &, const FSimpleVert *, const FSimpleVert *, int[2]); - -#ifdef __GNUC__ - calleroffset = (int *)__builtin_return_address(0); -#else - calleroffset = CallerOffset; -#endif -// printf ("Patching for SSE %d @ %p %d\n", SSELevel, calleroffset, *calleroffset); - -#ifndef DISABLE_SSE - if (CPU.bSSE2) - { - func = ClassifyLineSSE2; - diff = int((char *)ClassifyLineSSE2 - (char *)calleroffset); - } - else -#endif - { - func = ClassifyLine2; - diff = int((char *)ClassifyLine2 - (char *)calleroffset); - } - - calleroffset--; - // Patch the caller. -#ifdef _WIN32 - unsigned long oldprotect; - if (VirtualProtect (calleroffset, 4, PAGE_EXECUTE_READWRITE, &oldprotect)) -#else - // must make this page-aligned for mprotect - long pagesize = sysconf(_SC_PAGESIZE); - char *callerpage = (char *)((intptr_t)calleroffset & ~(pagesize - 1)); - size_t protectlen = (intptr_t)calleroffset + sizeof(void*) - (intptr_t)callerpage; - int ptect; - if (!(ptect = mprotect(callerpage, protectlen, PROT_READ|PROT_WRITE|PROT_EXEC))) -#endif - { - *calleroffset = diff; -#ifdef _WIN32 - VirtualProtect (calleroffset, sizeof(void*), oldprotect, &oldprotect); -#else - mprotect(callerpage, protectlen, PROT_READ|PROT_EXEC); -#endif - } - - // And return by calling the real function. - return func (node, v1, v2, sidev); -} - -#ifndef __GNUC__ -// The ClassifyLineBackpatch() function here is a stub that uses inline assembly and nakedness -// to retrieve the return address of the stack before sending control to the real -// ClassifyLineBackpatchC() function. Since BACKPATCH shouldn't be defined on 64-bit builds, -// we're okay that VC++ can't do inline assembly on that target. - -extern "C" __declspec(noinline) __declspec(naked) int ClassifyLineBackpatch (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]) -{ - // We store the return address in a global, so as not to need to mess with the parameter list. - __asm - { - mov eax, [esp] - mov CallerOffset, eax - jmp ClassifyLineBackpatchC - } -} -#endif -#endif diff --git a/src/nodebuild.h b/src/nodebuild.h index 9599bc0d2..6d730644e 100644 --- a/src/nodebuild.h +++ b/src/nodebuild.h @@ -53,22 +53,6 @@ struct FSimpleVert fixed_t x, y; }; -extern "C" -{ - int ClassifyLine2 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]); -#ifndef DISABLE_SSE - int ClassifyLineSSE1 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]); - int ClassifyLineSSE2 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]); -#ifdef BACKPATCH -#ifdef __GNUC__ - int ClassifyLineBackpatch (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]) __attribute__((noinline)); -#else - int __declspec(noinline) ClassifyLineBackpatch (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]); -#endif -#endif -#endif -} - class FNodeBuilder { struct FPrivSeg @@ -282,7 +266,7 @@ private: // 1 = seg is in back // -1 = seg cuts the node - inline int ClassifyLine (node_t &node, const FPrivVert *v1, const FPrivVert *v2, int sidev[2]); + int ClassifyLine (node_t &node, const FPrivVert *v1, const FPrivVert *v2, int sidev[2]); void FixSplitSharers (const node_t &node); double AddIntersection (const node_t &node, int vertex); @@ -341,28 +325,3 @@ inline int FNodeBuilder::PointOnSide (int x, int y, int x1, int y1, int dx, int } return s_num > 0.0 ? -1 : 1; } - -inline int FNodeBuilder::ClassifyLine (node_t &node, const FPrivVert *v1, const FPrivVert *v2, int sidev[2]) -{ -#ifdef DISABLE_SSE - return ClassifyLine2 (node, v1, v2, sidev); -#else -#if defined(__SSE2__) || defined(_M_X64) - // If compiling with SSE2 support everywhere, just use the SSE2 version. - return ClassifyLineSSE2 (node, v1, v2, sidev); -#elif defined(_MSC_VER) && _MSC_VER < 1300 - // VC 6 does not support SSE optimizations. - return ClassifyLine2 (node, v1, v2, sidev); -#else - // Select the routine based on our flag. -#ifdef BACKPATCH - return ClassifyLineBackpatch (node, v1, v2, sidev); -#else - if (CPU.bSSE2) - return ClassifyLineSSE2 (node, v1, v2, sidev); - else - return ClassifyLine2 (node, v1, v2, sidev); -#endif -#endif -#endif -} diff --git a/src/nodebuild_classify_nosse2.cpp b/src/nodebuild_classify_nosse2.cpp index 2d2c8edea..44f7e709f 100644 --- a/src/nodebuild_classify_nosse2.cpp +++ b/src/nodebuild_classify_nosse2.cpp @@ -3,7 +3,7 @@ #define FAR_ENOUGH 17179869184.f // 4<<32 -extern "C" int ClassifyLine2 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]) +int FNodeBuilder::ClassifyLine(node_t &node, const FPrivVert *v1, const FPrivVert *v2, int sidev[2]) { double d_x1 = double(node.x); double d_y1 = double(node.y); diff --git a/src/nodebuild_classify_sse2.cpp b/src/nodebuild_classify_sse2.cpp deleted file mode 100644 index 52429ecb8..000000000 --- a/src/nodebuild_classify_sse2.cpp +++ /dev/null @@ -1,144 +0,0 @@ -#ifndef DISABLE_SSE - -#include "doomtype.h" -#include "nodebuild.h" - -#define FAR_ENOUGH 17179869184.f // 4<<32 - -// You may notice that this function is identical to ClassifyLine2. -// The reason it is SSE2 is because this file is explicitly compiled -// with SSE2 math enabled, but the other files are not. - -extern "C" int ClassifyLineSSE2 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]) -{ - double d_x1 = double(node.x); - double d_y1 = double(node.y); - double d_dx = double(node.dx); - double d_dy = double(node.dy); - double d_xv1 = double(v1->x); - double d_xv2 = double(v2->x); - double d_yv1 = double(v1->y); - double d_yv2 = double(v2->y); - - double s_num1 = (d_y1 - d_yv1) * d_dx - (d_x1 - d_xv1) * d_dy; - double s_num2 = (d_y1 - d_yv2) * d_dx - (d_x1 - d_xv2) * d_dy; - - int nears = 0; - - if (s_num1 <= -FAR_ENOUGH) - { - if (s_num2 <= -FAR_ENOUGH) - { - sidev[0] = sidev[1] = 1; - return 1; - } - if (s_num2 >= FAR_ENOUGH) - { - sidev[0] = 1; - sidev[1] = -1; - return -1; - } - nears = 1; - } - else if (s_num1 >= FAR_ENOUGH) - { - if (s_num2 >= FAR_ENOUGH) - { - sidev[0] = sidev[1] = -1; - return 0; - } - if (s_num2 <= -FAR_ENOUGH) - { - sidev[0] = -1; - sidev[1] = 1; - return -1; - } - nears = 1; - } - else - { - nears = 2 | int(fabs(s_num2) < FAR_ENOUGH); - } - - if (nears) - { - double l = 1.f / (d_dx*d_dx + d_dy*d_dy); - if (nears & 2) - { - double dist = s_num1 * s_num1 * l; - if (dist < SIDE_EPSILON*SIDE_EPSILON) - { - sidev[0] = 0; - } - else - { - sidev[0] = s_num1 > 0.0 ? -1 : 1; - } - } - else - { - sidev[0] = s_num1 > 0.0 ? -1 : 1; - } - if (nears & 1) - { - double dist = s_num2 * s_num2 * l; - if (dist < SIDE_EPSILON*SIDE_EPSILON) - { - sidev[1] = 0; - } - else - { - sidev[1] = s_num2 > 0.0 ? -1 : 1; - } - } - else - { - sidev[1] = s_num2 > 0.0 ? -1 : 1; - } - } - else - { - sidev[0] = s_num1 > 0.0 ? -1 : 1; - sidev[1] = s_num2 > 0.0 ? -1 : 1; - } - - if ((sidev[0] | sidev[1]) == 0) - { // seg is coplanar with the splitter, so use its orientation to determine - // which child it ends up in. If it faces the same direction as the splitter, - // it goes in front. Otherwise, it goes in back. - - if (node.dx != 0) - { - if ((node.dx > 0 && v2->x > v1->x) || (node.dx < 0 && v2->x < v1->x)) - { - return 0; - } - else - { - return 1; - } - } - else - { - if ((node.dy > 0 && v2->y > v1->y) || (node.dy < 0 && v2->y < v1->y)) - { - return 0; - } - else - { - return 1; - } - } - } - else if (sidev[0] <= 0 && sidev[1] <= 0) - { - return 0; - } - else if (sidev[0] >= 0 && sidev[1] >= 0) - { - return 1; - } - return -1; -} - -#endif diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 463868d88..ad66627f5 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -9423,7 +9423,10 @@ scriptwait: } case PCD_SETMUGSHOTSTATE: - StatusBar->SetMugShotState(FBehavior::StaticLookupString(STACK(1))); + if (!multiplayer || (activator != nullptr && activator->CheckLocalView(consoleplayer))) + { + StatusBar->SetMugShotState(FBehavior::StaticLookupString(STACK(1))); + } sp--; break; diff --git a/src/p_actionfunctions.cpp b/src/p_actionfunctions.cpp index 16c8c3267..54a577e5b 100644 --- a/src/p_actionfunctions.cpp +++ b/src/p_actionfunctions.cpp @@ -80,6 +80,7 @@ #include "math/cmath.h" #include "g_levellocals.h" #include "r_utility.h" +#include "sbar.h" AActor *SingleActorFromTID(int tid, AActor *defactor); @@ -4602,6 +4603,13 @@ DEFINE_ACTION_FUNCTION(AActor, A_ChangeCountFlags) return 0; } + +enum ERaise +{ + RF_TRANSFERFRIENDLINESS = 1, + RF_NOCHECKPOSITION = 2 +}; + //=========================================================================== // // A_RaiseMaster @@ -4610,11 +4618,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_ChangeCountFlags) DEFINE_ACTION_FUNCTION(AActor, A_RaiseMaster) { PARAM_SELF_PROLOGUE(AActor); - PARAM_BOOL_DEF(copy); + PARAM_INT_DEF(flags); + bool copy = !!(flags & RF_TRANSFERFRIENDLINESS); if (self->master != NULL) { - P_Thing_Raise(self->master, copy ? self : NULL); + P_Thing_Raise(self->master, copy ? self : NULL, (flags & RF_NOCHECKPOSITION)); } return 0; } @@ -4627,16 +4636,17 @@ DEFINE_ACTION_FUNCTION(AActor, A_RaiseMaster) DEFINE_ACTION_FUNCTION(AActor, A_RaiseChildren) { PARAM_SELF_PROLOGUE(AActor); - PARAM_BOOL_DEF(copy); + PARAM_INT_DEF(flags); TThinkerIterator it; AActor *mo; + bool copy = !!(flags & RF_TRANSFERFRIENDLINESS); while ((mo = it.Next()) != NULL) { if (mo->master == self) { - P_Thing_Raise(mo, copy ? self : NULL); + P_Thing_Raise(mo, copy ? self : NULL, (flags & RF_NOCHECKPOSITION)); } } return 0; @@ -4650,18 +4660,19 @@ DEFINE_ACTION_FUNCTION(AActor, A_RaiseChildren) DEFINE_ACTION_FUNCTION(AActor, A_RaiseSiblings) { PARAM_SELF_PROLOGUE(AActor); - PARAM_BOOL_DEF(copy); + PARAM_INT_DEF(flags); TThinkerIterator it; AActor *mo; + bool copy = !!(flags & RF_TRANSFERFRIENDLINESS); if (self->master != NULL) { while ((mo = it.Next()) != NULL) { if (mo->master == self->master && mo != self) { - P_Thing_Raise(mo, copy ? self : NULL); + P_Thing_Raise(mo, copy ? self : NULL, (flags & RF_NOCHECKPOSITION)); } } } @@ -6922,3 +6933,20 @@ DEFINE_ACTION_FUNCTION(AActor, SetCamera) } return 0; } + +DEFINE_ACTION_FUNCTION(AActor, A_SprayDecal) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_STRING(name); + SprayDecal(self, name); + return 0; +} + +DEFINE_ACTION_FUNCTION(AActor, A_SetMugshotState) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_STRING(name); + if (self->CheckLocalView(consoleplayer)) + StatusBar->SetMugShotState(name); + return 0; +} \ No newline at end of file diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index 90271333c..f43313682 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -205,6 +205,11 @@ void P_LoadStrifeConversations (MapData *map, const char *mapname) { if (!LoadScriptFile (scriptname_b, false, 1)) { + if (gameinfo.Dialogue.IsNotEmpty()) + { + if (LoadScriptFile(gameinfo.Dialogue, false, 0)) return; + } + LoadScriptFile ("SCRIPT00", false, 1); } } diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 0ff61651f..1c607bd48 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1163,6 +1163,38 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da // any negative value means that something in the above chain has cancelled out all damage and all damage effects, including pain. return 0; } + + + //[RC] Backported from the Zandronum source.. Mostly. + if( target->player && + damage > 0 && + source && + mod != NAME_Reflection && + target != source) + + { + int reflectdamage = 0; + for (auto p = target->player->mo->Inventory; p != nullptr; p = p->Inventory) + { + // This picks the reflection item with the maximum efficiency for the given damage type. + if (p->IsKindOf(NAME_PowerReflection)) + { + int mydamage = p->ApplyDamageFactor(mod, damage); + if (mydamage > reflectdamage) reflectdamage = mydamage; + } + } + + if (reflectdamage > 0) + { + // use the reflect item's damage factors to get the final value here. + P_DamageMobj(source, nullptr, target, reflectdamage, NAME_Reflection ); + + // Reset means of death flag. + MeansOfDeath = mod; + } + } + + // Push the target unless the source's weapon's kickback is 0. // (i.e. Gauntlets/Chainsaw) if (!plrDontThrust && inflictor && inflictor != target // [RH] Not if hurting own self @@ -1181,6 +1213,7 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da else kickback = source->player->ReadyWeapon->Kickback; + kickback = int(kickback * G_SkillProperty(SKILLP_KickbackFactor)); if (kickback) { AActor *origin = (source && (flags & DMG_INFLICTOR_IS_PUFF))? source : inflictor; @@ -1418,13 +1451,24 @@ static int DamageMobj (AActor *target, AActor *inflictor, AActor *source, int da // If the damaging player has the power of drain, give the player 50% of the damage // done in health. - if ( source && source->player && source->player->cheats & CF_DRAIN && !(target->flags5 & MF5_DONTDRAIN)) + if ( source && source->player && !(target->flags5 & MF5_DONTDRAIN)) { if (!target->player || target->player != source->player) { - if ( P_GiveBody( source, damage / 2 )) + double draindamage = 0; + for (auto p = source->player->mo->Inventory; p != nullptr; p = p->Inventory) { - S_Sound( source, CHAN_ITEM, "*drainhealth", 1, ATTN_NORM ); + // This picks the item with the maximum efficiency. + if (p->IsKindOf(NAME_PowerDrain)) + { + double mydamage = p->FloatVar(NAME_Strength); + if (mydamage > draindamage) draindamage = mydamage; + } + } + + if ( P_GiveBody( source, int(draindamage * damage))) + { + S_Sound(source, CHAN_ITEM, "*drainhealth", 1, ATTN_NORM ); } } } @@ -1730,7 +1774,8 @@ bool AActor::OkayToSwitchTarget (AActor *other) } int infight; - if (flags5 & MF5_NOINFIGHTING) infight=-1; + if (flags7 & MF7_FORCEINFIGHTING) infight = 1; + else if (flags5 & MF5_NOINFIGHTING) infight = -1; else infight = G_SkillProperty(SKILLP_Infight); if (infight < 0 && other->player == NULL && !IsHostile (other)) diff --git a/src/p_linkedsectors.cpp b/src/p_linkedsectors.cpp index 0dd29c10e..7ac614f2e 100644 --- a/src/p_linkedsectors.cpp +++ b/src/p_linkedsectors.cpp @@ -329,11 +329,13 @@ bool P_AddSectorLinks(sector_t *control, int tag, INTBOOL ceiling, int movetype) FSectorTagIterator itr(tag); while ((sec = itr.Next()) >= 0) { - // Don't attach to self! - if (control != &level.sectors[sec]) + // Don't attach to self (but allow attaching to this sector's oposite plane. + if (control == &level.sectors[sec]) { - AddSingleSector(scrollplane, &level.sectors[sec], movetype); + if (ceiling == sector_t::floor && movetype & LINK_FLOOR) continue; + if (ceiling == sector_t::ceiling && movetype & LINK_CEILING) continue; } + AddSingleSector(scrollplane, &level.sectors[sec], movetype); } } else diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 9cbb4aec1..394203c75 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -1737,14 +1737,14 @@ FUNC(LS_Thing_SpawnFacing) } FUNC(LS_Thing_Raise) -// Thing_Raise(tid) +// Thing_Raise(tid, nocheck) { AActor * target; bool ok = false; if (arg0==0) { - ok = P_Thing_Raise (it,NULL); + ok = P_Thing_Raise (it,NULL, arg1); } else { @@ -1752,7 +1752,7 @@ FUNC(LS_Thing_Raise) while ( (target = iterator.Next ()) ) { - ok |= P_Thing_Raise(target,NULL); + ok |= P_Thing_Raise(target,NULL, arg1); } } return ok; diff --git a/src/p_local.h b/src/p_local.h index 99e32366d..e3cee0ece 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -152,7 +152,7 @@ bool P_Thing_Move (int tid, AActor *source, int mapspot, bool fog); int P_Thing_Damage (int tid, AActor *whofor0, int amount, FName type); void P_Thing_SetVelocity(AActor *actor, const DVector3 &vec, bool add, bool setbob); void P_RemoveThing(AActor * actor); -bool P_Thing_Raise(AActor *thing, AActor *raiser); +bool P_Thing_Raise(AActor *thing, AActor *raiser, int nocheck = false); bool P_Thing_CanRaise(AActor *thing); PClassActor *P_GetSpawnableType(int spawnnum); void InitSpawnablesFromMapinfo(); diff --git a/src/p_map.cpp b/src/p_map.cpp index 9ea031f65..f79219acf 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -1178,6 +1178,7 @@ static bool CanAttackHurt(AActor *victim, AActor *shooter) if (!victim->player && !shooter->player) { int infight = G_SkillProperty(SKILLP_Infight); + if (infight < 0 && (victim->flags7 & MF7_FORCEINFIGHTING)) infight = 0; // This must override the 'no infight' setting to take effect. if (infight < 0) { diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index bf3624ad6..cd6e57105 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -903,8 +903,7 @@ bool AActor::TakeInventory(PClassActor *itemclass, int amount, bool fromdecorate // Do not take ammo if the "no take infinite/take as ammo depletion" flag is set // and infinite ammo is on if (notakeinfinite && - ((dmflags & DF_INFINITE_AMMO) || (player && player->cheats & CF_INFINITEAMMO)) && - item->IsKindOf(NAME_Ammo)) + ((dmflags & DF_INFINITE_AMMO) || (player && FindInventory(NAME_PowerInfiniteAmmo))) && item->IsKindOf(NAME_Ammo)) { // Nothing to do here, except maybe res = false;? Would it make sense? result = false; @@ -4439,7 +4438,8 @@ void AActor::Tick () return; // freed itself } } - else + + if (tics == -1 || state->GetCanRaise()) { int respawn_monsters = G_SkillProperty(SKILLP_Respawn); // check for nightmare respawn diff --git a/src/p_things.cpp b/src/p_things.cpp index f6c06a1e5..d4298f934 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -406,7 +406,7 @@ void P_RemoveThing(AActor * actor) } -bool P_Thing_Raise(AActor *thing, AActor *raiser) +bool P_Thing_Raise(AActor *thing, AActor *raiser, int nocheck) { FState * RaiseState = thing->GetRaiseState(); if (RaiseState == NULL) @@ -426,7 +426,7 @@ bool P_Thing_Raise(AActor *thing, AActor *raiser) thing->flags |= MF_SOLID; thing->Height = info->Height; // [RH] Use real height thing->radius = info->radius; // [RH] Use real radius - if (!P_CheckPosition (thing, thing->Pos())) + if (!nocheck && !P_CheckPosition (thing, thing->Pos())) { thing->flags = oldflags; thing->radius = oldradius; diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index fc71160ae..0ba75fc4c 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -1393,7 +1393,7 @@ public: if (isTranslated) sec->special = P_TranslateSectorSpecial(sec->special); else if (namespc == NAME_Hexen) { - if (sec->special < 0 || sec->special > 255 || !HexenSectorSpecialOk[sec->special]) + if (sec->special < 0 || sec->special > 140 || !HexenSectorSpecialOk[sec->special]) sec->special = 0; // NULL all unknown specials } continue; diff --git a/src/p_usdf.cpp b/src/p_usdf.cpp index 5a5f3c826..3d2c2e010 100644 --- a/src/p_usdf.cpp +++ b/src/p_usdf.cpp @@ -192,10 +192,15 @@ class USDFParser : public UDMFParserBase case NAME_Special: reply->ActionSpecial = CheckInt(key); - if (reply->ActionSpecial < 0 || reply->ActionSpecial > 255) + if (reply->ActionSpecial < 0) reply->ActionSpecial = 0; break; + case NAME_SpecialName: + if (namespace_bits == Zd) + reply->ActionSpecial = P_FindLineSpecial(CheckString(key)); + break; + case NAME_Arg0: case NAME_Arg1: case NAME_Arg2: diff --git a/src/p_user.cpp b/src/p_user.cpp index 10b7c4730..2f3a0d7a4 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -2690,9 +2690,19 @@ void P_PlayerThink (player_t *player) else if (level.IsJumpingAllowed() && player->onground && player->jumpTics == 0) { double jumpvelz = player->mo->JumpZ * 35 / TICRATE; + double jumpfac = 0; // [BC] If the player has the high jump power, double his jump velocity. - if ( player->cheats & CF_HIGHJUMP ) jumpvelz *= 2; + // (actually, pick the best factors from all active items.) + for (auto p = player->mo->Inventory; p != nullptr; p = p->Inventory) + { + if (p->IsKindOf(NAME_PowerHighJump)) + { + double f = p->FloatVar(NAME_Strength); + if (f > jumpfac) jumpfac = f; + } + } + if (jumpfac > 0) jumpvelz *= jumpfac; player->mo->Vel.Z += jumpvelz; player->mo->flags2 &= ~MF2_ONMOBJ; diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index f68667bbb..656b75402 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -318,6 +318,7 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(MF7, NOSHIELDREFLECT, AActor, flags7), DEFINE_FLAG(MF7, FORCEZERORADIUSDMG, AActor, flags7), DEFINE_FLAG(MF7, NOINFIGHTSPECIES, AActor, flags7), + DEFINE_FLAG(MF7, FORCEINFIGHTING, AActor, flags7), // Effect flags DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects), @@ -338,6 +339,7 @@ static FFlagDef ActorFlagDefs[]= DEFINE_FLAG(RF, XFLIP, AActor, renderflags), DEFINE_FLAG(RF, YFLIP, AActor, renderflags), DEFINE_FLAG(RF, INTERPOLATEANGLES, AActor, renderflags), + DEFINE_FLAG(RF, DONTINTERPOLATE, AActor, renderflags), // Bounce flags DEFINE_FLAG2(BOUNCE_Walls, BOUNCEONWALLS, AActor, BounceFlags), diff --git a/src/sound/i_music.cpp b/src/sound/i_music.cpp index 5637f4719..0f7141762 100644 --- a/src/sound/i_music.cpp +++ b/src/sound/i_music.cpp @@ -279,6 +279,10 @@ void MusInfo::TimidityVolumeChanged() { } +void MusInfo::GMEDepthChanged(float val) +{ +} + void MusInfo::FluidSettingInt(const char *, int) { } diff --git a/src/sound/i_music.h b/src/sound/i_music.h index 85fb70a56..cf05d739f 100644 --- a/src/sound/i_music.h +++ b/src/sound/i_music.h @@ -83,6 +83,7 @@ public: virtual void FluidSettingNum(const char *setting, double value); // " virtual void FluidSettingStr(const char *setting, const char *value); // " virtual void WildMidiSetOption(int opt, int set); + virtual void GMEDepthChanged(float val); void Start(bool loop, float rel_vol = -1.f, int subsong = 0); diff --git a/src/sound/music_gme.cpp b/src/sound/music_gme.cpp index 6038f2349..d00728ec6 100644 --- a/src/sound/music_gme.cpp +++ b/src/sound/music_gme.cpp @@ -43,6 +43,7 @@ #include #include "v_text.h" #include "files.h" +#include "templates.h" // MACROS ------------------------------------------------------------------ @@ -67,6 +68,7 @@ protected: bool StartTrack(int track, bool getcritsec=true); bool GetTrackInfo(); int CalcSongLength(); + void GMEDepthChanged(float val); static bool Read(SoundStream *stream, void *buff, int len, void *userdata); }; @@ -84,6 +86,12 @@ protected: // Currently not used. CVAR (Float, spc_amp, 1.875f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +CUSTOM_CVAR(Float, gme_stereodepth, 0.f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (currSong != nullptr) + currSong->GMEDepthChanged(self); +} + // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- @@ -146,6 +154,7 @@ MusInfo *GME_OpenSong(FileReader &reader, const char *fmt) reader.Seek(fpos, SEEK_SET); return NULL; } + gme_set_stereo_depth(emu, clamp(*gme_stereodepth, 0.f, 1.f)); return new GMESong(emu, sample_rate); } @@ -189,6 +198,19 @@ GMESong::~GMESong() } +//========================================================================== +// +// GMESong :: GMEDepthChanged +// +//========================================================================== + +void GMESong::GMEDepthChanged(float val) +{ + if (Emu != nullptr) + gme_set_stereo_depth(Emu, clamp(val, 0.f, 1.f)); +} + + //========================================================================== // // GMESong :: Play diff --git a/src/v_font.cpp b/src/v_font.cpp index a82bd16c1..d668de94c 100644 --- a/src/v_font.cpp +++ b/src/v_font.cpp @@ -163,7 +163,7 @@ protected: class FSpecialFont : public FFont { public: - FSpecialFont (const char *name, int first, int count, FTexture **lumplist, const bool *notranslate, int lump); + FSpecialFont (const char *name, int first, int count, FTexture **lumplist, const bool *notranslate, int lump, bool donttranslate); void LoadTranslations(); @@ -357,7 +357,7 @@ DEFINE_ACTION_FUNCTION(FFont, GetFont) // //========================================================================== -FFont::FFont (const char *name, const char *nametemplate, int first, int count, int start, int fdlump, int spacewidth) +FFont::FFont (const char *name, const char *nametemplate, int first, int count, int start, int fdlump, int spacewidth, bool notranslate) { int i; FTextureID lump; @@ -367,6 +367,7 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count, bool doomtemplate = gameinfo.gametype & GAME_DoomChex ? strncmp (nametemplate, "STCFN", 5) == 0 : false; bool stcfn121 = false; + noTranslate = notranslate; Lump = fdlump; Chars = new CharData[count]; charlumps = new FTexture *[count]; @@ -430,7 +431,8 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count, if (charlumps[i] != NULL) { - Chars[i].Pic = new FFontChar1 (charlumps[i]); + if (!noTranslate) Chars[i].Pic = new FFontChar1 (charlumps[i]); + else Chars[i].Pic = charlumps[i]; Chars[i].XMove = Chars[i].Pic->GetScaledWidth(); } else @@ -455,7 +457,7 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count, FixXMoves(); - LoadTranslations(); + if (!noTranslate) LoadTranslations(); delete[] charlumps; } @@ -472,11 +474,15 @@ FFont::~FFont () { int count = LastChar - FirstChar + 1; - for (int i = 0; i < count; ++i) + // A noTranslate font directly references the original textures. + if (!noTranslate) { - if (Chars[i].Pic != NULL && Chars[i].Pic->Name[0] == 0) + for (int i = 0; i < count; ++i) { - delete Chars[i].Pic; + if (Chars[i].Pic != NULL && Chars[i].Pic->Name[0] == 0) + { + delete Chars[i].Pic; + } } } delete[] Chars; @@ -752,7 +758,7 @@ void FFont::BuildTranslations (const double *luminosity, const BYTE *identity, FRemapTable *FFont::GetColorTranslation (EColorRange range) const { - if (ActiveColors == 0) + if (ActiveColors == 0 || noTranslate) return NULL; else if (range >= NumTextColors) range = CR_UNTRANSLATED; @@ -1005,6 +1011,7 @@ FFont::FFont (int lump) PatchRemap = NULL; FontName = NAME_None; Cursor = '_'; + noTranslate = false; } //========================================================================== @@ -1962,7 +1969,7 @@ void FFontChar2::MakeTexture () // //========================================================================== -FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **lumplist, const bool *notranslate, int lump) : FFont(lump) +FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **lumplist, const bool *notranslate, int lump, bool donttranslate) : FFont(lump) { int i; FTexture **charlumps; @@ -1971,6 +1978,7 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **l memcpy(this->notranslate, notranslate, 256*sizeof(bool)); + noTranslate = donttranslate; FontName = name; Chars = new CharData[count]; charlumps = new FTexture*[count]; @@ -2005,7 +2013,8 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **l if (charlumps[i] != NULL) { - Chars[i].Pic = new FFontChar1 (charlumps[i]); + if (!noTranslate) Chars[i].Pic = new FFontChar1 (charlumps[i]); + else Chars[i].Pic = charlumps[i]; Chars[i].XMove = Chars[i].Pic->GetScaledWidth(); } else @@ -2027,7 +2036,7 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **l FixXMoves(); - LoadTranslations(); + if (!noTranslate) LoadTranslations(); delete[] charlumps; } @@ -2158,6 +2167,7 @@ void V_InitCustomFonts() FScanner sc; FTexture *lumplist[256]; bool notranslate[256]; + bool donttranslate; FString namebuffer, templatebuf; int i; int llump,lastlump=0; @@ -2175,6 +2185,7 @@ void V_InitCustomFonts() { memset (lumplist, 0, sizeof(lumplist)); memset (notranslate, 0, sizeof(notranslate)); + donttranslate = false; namebuffer = sc.String; format = 0; start = 33; @@ -2226,6 +2237,10 @@ void V_InitCustomFonts() spacewidth = sc.Number; format = 1; } + else if (sc.Compare("DONTTRANSLATE")) + { + donttranslate = true; + } else if (sc.Compare ("NOTRANSLATION")) { if (format == 1) goto wrong; @@ -2256,7 +2271,7 @@ void V_InitCustomFonts() } if (format == 1) { - FFont *fnt = new FFont (namebuffer, templatebuf, first, count, start, llump, spacewidth); + FFont *fnt = new FFont (namebuffer, templatebuf, first, count, start, llump, spacewidth, donttranslate); fnt->SetCursor(cursor); } else if (format == 2) @@ -2279,7 +2294,7 @@ void V_InitCustomFonts() } if (count > 0) { - FFont *fnt = new FSpecialFont (namebuffer, first, count, &lumplist[first], notranslate, llump); + FFont *fnt = new FSpecialFont (namebuffer, first, count, &lumplist[first], notranslate, llump, donttranslate); fnt->SetCursor(cursor); } } diff --git a/src/v_font.h b/src/v_font.h index 21d773d9d..ec85f7622 100644 --- a/src/v_font.h +++ b/src/v_font.h @@ -75,7 +75,7 @@ extern int NumTextColors; class FFont { public: - FFont (const char *fontname, const char *nametemplate, int first, int count, int base, int fdlump, int spacewidth=-1); + FFont (const char *fontname, const char *nametemplate, int first, int count, int base, int fdlump, int spacewidth=-1, bool notranslate = false); virtual ~FFont (); virtual FTexture *GetChar (int code, int *const width) const; @@ -100,6 +100,7 @@ public: int GetCharCode(int code, bool needpic) const; char GetCursor() const { return Cursor; } void SetCursor(char c) { Cursor = c; } + bool NoTranslate() const { return noTranslate; } protected: FFont (int lump); @@ -116,6 +117,7 @@ protected: int FontHeight; int GlobalKerning; char Cursor; + bool noTranslate; struct CharData { FTexture *Pic; diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index 18910b2b6..e94e0e1d0 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -2021,7 +2021,10 @@ public: if (bcnt == 1) { // intermission music - use the defaults if none specified - if (level.info->InterMusic.IsNotEmpty()) + auto mus = level.info->MapInterMusic.CheckKey(wbs->next); + if (mus != nullptr) + S_ChangeMusic(mus->first, mus->second); + else if (level.info->InterMusic.IsNotEmpty()) S_ChangeMusic(level.info->InterMusic, level.info->intermusicorder); else S_ChangeMusic (gameinfo.intermissionMusic.GetChars(), gameinfo.intermissionOrder); diff --git a/wadsrc/static/language.eng b/wadsrc/static/language.eng index bf0a0a91d..66757cee7 100644 --- a/wadsrc/static/language.eng +++ b/wadsrc/static/language.eng @@ -106,6 +106,7 @@ CMPTMNU_RENDERINGBEHAVIOR = "Rendering Behaviour"; CMPTMNU_SOUNDBEHAVIOR = "Sound Behaviour"; CMPTMNU_SECTORSOUNDS = "Sector sounds use centre as source"; OPTVAL_MAPDEFINEDCOLORSONLY = "Map defined colours only"; +OPTVAL_NODOORS = "All except doors"; C_GRAY = "\ccgrey"; C_DARKGRAY = "\cudark grey"; diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 49642fb68..8d28859ed 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1008,6 +1008,13 @@ OptionValue MapBackTypes 2, "$OPTVAL_MAPDEFINEDCOLORSONLY" } +OptionValue MapTriggers +{ + 0, "$OPTVAL_OFF" + 1, "$OPTVAL_NO_DOORS" + 2, "$OPTVAL_ON" +} + OptionMenu AutomapOptions { Title "$AUTOMAPMNU_TITLE" @@ -1031,7 +1038,7 @@ OptionMenu AutomapOptions Option "$AUTOMAPMNU_SHOWMAPLABEL", "am_showmaplabel", "MaplabelTypes" Option "$AUTOMAPMNU_DRAWMAPBACK", "am_drawmapback", "MapBackTypes" Option "$AUTOMAPMNU_SHOWKEYS", "am_showkeys", "OnOff" - Option "$AUTOMAPMNU_SHOWTRIGGERLINES", "am_showtriggerlines", "OnOff" + Option "$AUTOMAPMNU_SHOWTRIGGERLINES", "am_showtriggerlines", "MapTriggers" Option "$AUTOMAPMNU_SHOWTHINGSPRITES", "am_showthingsprites", "STSTypes" } diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 2e9752b97..9b52e7271 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -790,9 +790,9 @@ class Actor : Thinker native native void A_SetBlend(color color1, double alpha, int tics, color color2 = 0); deprecated native void A_ChangeFlag(string flagname, bool value); native void A_ChangeCountFlags(int kill = FLAG_NO_CHANGE, int item = FLAG_NO_CHANGE, int secret = FLAG_NO_CHANGE); - native void A_RaiseMaster(bool copy = 0); - native void A_RaiseChildren(bool copy = 0); - native void A_RaiseSiblings(bool copy = 0); + native void A_RaiseMaster(int flags = 0); + native void A_RaiseChildren(int flags = 0); + native void A_RaiseSiblings(int flags = 0); deprecated native void A_BasicAttack(int meleedamage, sound meleesound, class missiletype, double missileheight); action native bool, Actor A_ThrowGrenade(class itemtype, double zheight = 0, double xyvel = 0, double zvel = 0, bool useammo = true); native void A_Weave(int xspeed, int yspeed, double xdist, double ydist); @@ -868,6 +868,8 @@ class Actor : Thinker native native bool A_SetVisibleRotation(double anglestart = 0, double angleend = 0, double pitchstart = 0, double pitchend = 0, int flags = 0, int ptr = AAPTR_DEFAULT); native void A_SetTranslation(name transname); native bool A_SetSize(double newradius, double newheight = -1, bool testpos = false); + native void A_SprayDecal(String name); + native void A_SetMugshotState(String name); native void A_RearrangePointers(int newtarget, int newmaster = AAPTR_DEFAULT, int newtracer = AAPTR_DEFAULT, int flags=0); native void A_TransferPointer(int ptr_source, int ptr_recepient, int sourcefield, int recepientfield=AAPTR_DEFAULT, int flags=0); diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index e2390cfd1..9e9d4dae8 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -996,6 +996,12 @@ enum EFindFloorCeiling FFCF_NODROPOFF = 256, // Caller does not need a dropoff (saves some time when checking portals) }; +enum ERaise +{ + RF_TRANSFERFRIENDLINESS = 1, + RF_NOCHECKPOSITION = 2 +} + enum ETeleport { TELF_DESTFOG = 1, @@ -1088,17 +1094,21 @@ enum EPlayerCheats CF_TOTALLYFROZEN = 1 << 12, // [RH] All players can do is press +use CF_PREDICTING = 1 << 13, // [RH] Player movement is being predicted CF_INTERPVIEW = 1 << 14, // [RH] view was changed outside of input, so interpolate one frame - CF_DRAIN = 1 << 16, // Player owns a drain powerup - CF_HIGHJUMP = 1 << 18, // more Skulltag flags. Implementation not guaranteed though. ;) - CF_REFLECTION = 1 << 19, - CF_PROSPERITY = 1 << 20, - CF_DOUBLEFIRINGSPEED= 1 << 21, // Player owns a double firing speed artifact + CF_EXTREMELYDEAD = 1 << 22, // [RH] Reliably let the status bar know about extreme deaths. - CF_INFINITEAMMO = 1 << 23, // Player owns an infinite ammo artifact + CF_BUDDHA2 = 1 << 24, // [MC] Absolute buddha. No voodoo can kill it either. CF_GODMODE2 = 1 << 25, // [MC] Absolute godmode. No voodoo can kill it either. CF_BUDDHA = 1 << 27, // [SP] Buddha mode - take damage, but don't die CF_NOCLIP2 = 1 << 30, // [RH] More Quake-like noclip + + // These flags no longer exist, but keep the names for some stray mod that might have used them. + CF_DRAIN = 0, + CF_HIGHJUMP = 0, + CF_REFLECTION = 0, + CF_PROSPERITY = 0, + CF_DOUBLEFIRINGSPEED= 0, + CF_INFINITEAMMO = 0, }; const TEXTCOLOR_BRICK = "\034A"; diff --git a/wadsrc/static/zscript/inventory/powerups.txt b/wadsrc/static/zscript/inventory/powerups.txt index 346f3d1a7..3b01c97b3 100644 --- a/wadsrc/static/zscript/inventory/powerups.txt +++ b/wadsrc/static/zscript/inventory/powerups.txt @@ -1783,32 +1783,9 @@ class PowerDrain : Powerup { Default { + Powerup.Strength 0.5; Powerup.Duration -60; } - - override void InitEffect() - { - Super.InitEffect(); - - if (Owner!= null && Owner.player != null) - { - // Give the player the power to drain life from opponents when he damages them. - Owner.player.cheats |= CF_DRAIN; - } - } - - override void EndEffect() - { - Super.EndEffect(); - - // Nothing to do if there's no owner. - if (Owner!= null && Owner.player != null) - { - // Take away the drain power. - Owner.player.cheats &= ~CF_DRAIN; - } - } - } //=========================================================================== @@ -1846,27 +1823,9 @@ class PowerRegeneration : Powerup class PowerHighJump : Powerup { - override void InitEffect() + Default { - Super.InitEffect(); - - if (Owner!= null && Owner.player != null) - { - // Give the player the power to jump much higher. - Owner.player.cheats |= CF_HIGHJUMP; - } - } - - override void EndEffect() - { - Super.EndEffect(); - - // Nothing to do if there's no owner. - if (Owner!= null && Owner.player != null) - { - // Take away the high jump power. - Owner.player.cheats &= ~CF_HIGHJUMP; - } + Powerup.Strength 2; } } @@ -1878,27 +1837,9 @@ class PowerHighJump : Powerup class PowerDoubleFiringSpeed : Powerup { - override void InitEffect() + Default { - Super.InitEffect(); - - if (Owner!= null && Owner.player != null) - { - // Give the player the power to shoot twice as fast. - Owner.player.cheats |= CF_DOUBLEFIRINGSPEED; - } - } - - override void EndEffect() - { - Super.EndEffect(); - - // Nothing to do if there's no owner. - if (Owner!= null && Owner.player != null) - { - // Take away the shooting twice as fast power. - Owner.player.cheats &= ~CF_DOUBLEFIRINGSPEED; - } + Powerup.Duration -40; } } @@ -1914,28 +1855,21 @@ class PowerInfiniteAmmo : Powerup { Powerup.Duration -30; } - - override void InitEffect() +} + + +//=========================================================================== +// +// InfiniteAmmo +// +//=========================================================================== + +class PowerReflection : Powerup +{ + Default { - Super.InitEffect(); - - if (Owner!= null && Owner.player != null) - { - // Give the player infinite ammo - Owner.player.cheats |= CF_INFINITEAMMO; - } - } - - override void EndEffect() - { - Super.EndEffect(); - - // Nothing to do if there's no owner. - if (Owner!= null && Owner.player != null) - { - // Take away the limitless ammo - Owner.player.cheats &= ~CF_INFINITEAMMO; - } + Powerup.Duration -60; + DamageFactor 0.5; } } diff --git a/wadsrc/static/zscript/menu/messagebox.txt b/wadsrc/static/zscript/menu/messagebox.txt index b7b611f41..f5a60d9d4 100644 --- a/wadsrc/static/zscript/menu/messagebox.txt +++ b/wadsrc/static/zscript/menu/messagebox.txt @@ -61,7 +61,7 @@ class MessageBoxMenu : Menu int mr2 = 170 + SmallFont.StringWidth(Stringtable.Localize("$TXT_NO")); mMouseRight = MAX(mr1, mr2); mParentMenu = parent; - mMessage = SmallFont.BreakLines(message, 300); + mMessage = SmallFont.BreakLines(Stringtable.Localize(message), 300); mMessageMode = messagemode; if (playsound) {