Merge commit 'b0eb19b'

This commit is contained in:
Rachael Alexanderson 2017-02-26 13:41:02 -05:00
commit 7a5df2bc28
47 changed files with 375 additions and 531 deletions

View file

@ -92,6 +92,8 @@ conversation // Starts a dialog.
choice
{
specialname = <string>; // 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.

View file

@ -397,22 +397,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 )
@ -577,10 +561,6 @@ endif()
# Flags
if( BACKPATCH )
add_definitions( -DBACKPATCH )
endif()
# Update gitinfo.h
add_custom_target( revision_check ALL
@ -727,18 +707,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()

View file

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

View file

@ -389,6 +389,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 ---

View file

@ -90,7 +90,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);
//=============================================================================
@ -2281,58 +2281,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)
@ -2351,7 +2340,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)
{

View file

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

View file

@ -2376,25 +2376,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:

View file

@ -209,13 +209,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

View file

@ -449,7 +449,13 @@ DEFINE_EVENT_LOOPER(WorldLightning)
DEFINE_EVENT_LOOPER(WorldTick)
// declarations
IMPLEMENT_CLASS(DStaticEventHandler, false, false);
IMPLEMENT_CLASS(DStaticEventHandler, false, true);
IMPLEMENT_POINTERS_START(DStaticEventHandler)
IMPLEMENT_POINTER(next)
IMPLEMENT_POINTER(prev)
IMPLEMENT_POINTERS_END
IMPLEMENT_CLASS(DEventHandler, false, false);
IMPLEMENT_CLASS(DBaseEvent, false, false)
IMPLEMENT_CLASS(DRenderEvent, false, false)

View file

@ -76,7 +76,7 @@ void E_SerializeEvents(FSerializer& arc);
class DStaticEventHandler : public DObject // make it a part of normal GC process
{
DECLARE_CLASS(DStaticEventHandler, DObject)
DECLARE_CLASS(DStaticEventHandler, DObject);
HAS_OBJECT_POINTERS
public:
DStaticEventHandler()

View file

@ -1343,12 +1343,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<AInventory*> 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();
}
}
}

View file

@ -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 <FName, std::pair<FString, int> > MapInterMusic;
FString SoundInfo;
FString SndSeq;

View file

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

View file

@ -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())
{

View file

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

View file

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

View file

@ -176,6 +176,7 @@ struct gameinfo_t
FName DefaultEndSequence;
FString mMapArrow, mCheatMapArrow;
FString mEasyKey, mCheatKey;
FString Dialogue;
FGIFont mStatscreenMapNameFont;
FGIFont mStatscreenFinishedFont;
FGIFont mStatscreenEnteringFont;

View file

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

View file

@ -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 <sys/mman.h>
#include <limits.h>
#include <unistd.h>
#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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1162,6 +1162,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
@ -1417,13 +1449,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 );
}
}
}
@ -1729,7 +1772,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))

View file

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

View file

@ -151,7 +151,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();

View file

@ -1177,6 +1177,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)
{
@ -5276,20 +5277,22 @@ bool P_UseTraverse(AActor *usething, const DVector2 &start, const DVector2 &end,
// [RH] Check for things to talk with or use a puzzle item on
if (!in->isaline)
{
if (usething == in->d.thing)
AActor * const mobj = in->d.thing;
if (mobj == usething)
continue;
// Check thing
// Check for puzzle item use or USESPECIAL flag
// Extended to use the same activationtype mechanism as BUMPSPECIAL does
if (in->d.thing->flags5 & MF5_USESPECIAL || in->d.thing->special == UsePuzzleItem)
if (mobj->flags5 & MF5_USESPECIAL || mobj->special == UsePuzzleItem)
{
if (P_ActivateThingSpecial(in->d.thing, usething))
if (P_ActivateThingSpecial(mobj, usething))
return true;
}
IFVIRTUALPTR(usething, AActor, Used)
IFVIRTUALPTR(mobj, AActor, Used)
{
VMValue params[] = { usething, in->d.thing };
VMValue params[] = { mobj, usething };
int ret;
VMReturn vret(&ret);
GlobalVMStack.Call(func, params, 2, &vret, 1);

View file

@ -902,8 +902,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;

View file

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

View file

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

View file

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

View file

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

View file

@ -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),
@ -917,7 +918,7 @@ void InitThingdef()
fieldptr = new PField("gametic", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&gametic);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("demoplayback", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&demoplayback);
fieldptr = new PField("demoplayback", TypeBool, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&demoplayback);
Namespaces.GlobalNamespace->Symbols.AddSymbol(fieldptr);
fieldptr = new PField("BackbuttonTime", TypeSInt32, VARF_Native | VARF_Static, (intptr_t)&BackbuttonTime);

View file

@ -279,6 +279,10 @@ void MusInfo::TimidityVolumeChanged()
{
}
void MusInfo::GMEDepthChanged(float val)
{
}
void MusInfo::FluidSettingInt(const char *, int)
{
}

View file

@ -84,6 +84,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);

View file

@ -43,6 +43,7 @@
#include <gme/gme.h>
#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

View file

@ -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;
}
//==========================================================================
@ -1964,7 +1971,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;
@ -1973,6 +1980,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];
@ -2007,7 +2015,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
@ -2029,7 +2038,7 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, FTexture **l
FixXMoves();
LoadTranslations();
if (!noTranslate) LoadTranslations();
delete[] charlumps;
}
@ -2160,6 +2169,7 @@ void V_InitCustomFonts()
FScanner sc;
FTexture *lumplist[256];
bool notranslate[256];
bool donttranslate;
FString namebuffer, templatebuf;
int i;
int llump,lastlump=0;
@ -2177,6 +2187,7 @@ void V_InitCustomFonts()
{
memset (lumplist, 0, sizeof(lumplist));
memset (notranslate, 0, sizeof(notranslate));
donttranslate = false;
namebuffer = sc.String;
format = 0;
start = 33;
@ -2228,6 +2239,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;
@ -2258,7 +2273,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)
@ -2281,7 +2296,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);
}
}

View file

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

View file

@ -2020,7 +2020,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);

View file

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

View file

@ -1035,6 +1035,13 @@ OptionValue MapBackTypes
2, "$OPTVAL_MAPDEFINEDCOLORSONLY"
}
OptionValue MapTriggers
{
0, "$OPTVAL_OFF"
1, "$OPTVAL_NO_DOORS"
2, "$OPTVAL_ON"
}
OptionMenu AutomapOptions
{
Title "$AUTOMAPMNU_TITLE"
@ -1058,7 +1065,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"
}

View file

@ -791,9 +791,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<actor> missiletype, double missileheight);
action native bool, Actor A_ThrowGrenade(class<Actor> 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);
@ -869,6 +869,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);

View file

@ -1000,6 +1000,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,
@ -1092,17 +1098,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";

View file

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

View file

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