mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-29 23:33:00 +00:00
Merge https://github.com/rheit/zdoom into z_osx_clean
This commit is contained in:
commit
25b808cd82
36 changed files with 6457 additions and 5463 deletions
|
@ -95,7 +95,7 @@ Note: All <bool> fields default to false unless mentioned otherwise.
|
|||
alpha = <float>; // Translucency of this line, default is 1.0
|
||||
renderstyle = <string>; // Render style, can be "translucent" or "add",
|
||||
// default is "translucent".
|
||||
playeruseback = <bool>; // New SPAC flag, true = player can use from back side.
|
||||
playeruseback = <bool> ; // New SPAC flag, true = player can use from back side.
|
||||
anycross = <bool>; // New SPAC flag, true = any non-projectile
|
||||
// crossing will trigger this line
|
||||
monsteractivate = <bool>; // Monsters can trigger this line.
|
||||
|
@ -109,8 +109,11 @@ Note: All <bool> fields default to false unless mentioned otherwise.
|
|||
clipmidtex = <bool>; // Line's mid textures are clipped to floor and ceiling.
|
||||
wrapmidtex = <bool>; // Line's mid textures are wrapped.
|
||||
midtex3d = <bool>; // Actors can walk on mid texture.
|
||||
checkswitchrange = <bool>;// Switches can only be activated when vertically reachable.
|
||||
blockprojectiles = <bool>;// Line blocks all projectiles
|
||||
midtex3dimpassible = <bool>;// Used in conjuction with midtex3d - causes the mid
|
||||
// texture to behave like an impassible line (projectiles
|
||||
// pass through it).
|
||||
checkswitchrange = <bool>; // Switches can only be activated when vertically reachable.
|
||||
blockprojectiles = <bool>; // Line blocks all projectiles
|
||||
blockuse = <bool>; // Line blocks all use actions
|
||||
blocksight = <bool>; // Line blocks monster line of sight
|
||||
blockhitscan = <bool>; // Line blocks hitscan attacks
|
||||
|
|
|
@ -56,6 +56,13 @@ AActor *COPY_AAPTR(AActor *origin, int selector)
|
|||
case AAPTR_TRACER: return origin->tracer;
|
||||
case AAPTR_FRIENDPLAYER:
|
||||
return origin->FriendPlayer ? AAPTR_RESOLVE_PLAYERNUM(origin->FriendPlayer - 1) : NULL;
|
||||
|
||||
case AAPTR_GET_LINETARGET:
|
||||
{
|
||||
AActor *gettarget = NULL;
|
||||
P_BulletSlope(origin, &gettarget);
|
||||
return gettarget;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,12 +36,13 @@ enum AAPTR
|
|||
AAPTR_PLAYER8 = 0x2000,
|
||||
|
||||
AAPTR_FRIENDPLAYER = 0x4000,
|
||||
AAPTR_GET_LINETARGET = 0x8000,
|
||||
|
||||
AAPTR_PLAYER_SELECTORS =
|
||||
AAPTR_PLAYER_GETTARGET|AAPTR_PLAYER_GETCONVERSATION,
|
||||
|
||||
AAPTR_GENERAL_SELECTORS =
|
||||
AAPTR_TARGET|AAPTR_MASTER|AAPTR_TRACER|AAPTR_FRIENDPLAYER,
|
||||
AAPTR_TARGET|AAPTR_MASTER|AAPTR_TRACER|AAPTR_FRIENDPLAYER|AAPTR_GET_LINETARGET,
|
||||
|
||||
AAPTR_STATIC_SELECTORS =
|
||||
AAPTR_PLAYER1|AAPTR_PLAYER2|AAPTR_PLAYER3|AAPTR_PLAYER4|
|
||||
|
|
|
@ -281,7 +281,8 @@ void CT_Drawer (void)
|
|||
|
||||
if (players[consoleplayer].camera != NULL &&
|
||||
(Button_ShowScores.bDown ||
|
||||
players[consoleplayer].camera->health <= 0) &&
|
||||
players[consoleplayer].camera->health <= 0 ||
|
||||
SB_ForceActive) &&
|
||||
// Don't draw during intermission, since it has its own scoreboard in wi_stuff.cpp.
|
||||
gamestate != GS_INTERMISSION)
|
||||
{
|
||||
|
|
|
@ -756,9 +756,9 @@ void D_Display ()
|
|||
}
|
||||
screen->SetBlendingRect(viewwindowx, viewwindowy,
|
||||
viewwindowx + viewwidth, viewwindowy + viewheight);
|
||||
P_PredictPlayer(&players[consoleplayer]);
|
||||
|
||||
Renderer->RenderView(&players[consoleplayer]);
|
||||
P_UnPredictPlayer();
|
||||
|
||||
if ((hw2d = screen->Begin2D(viewactive)))
|
||||
{
|
||||
// Redraw everything every frame when using 2D accel
|
||||
|
|
182
src/d_net.cpp
182
src/d_net.cpp
|
@ -110,6 +110,8 @@ unsigned int lastrecvtime[MAXPLAYERS]; // [RH] Used for pings
|
|||
unsigned int currrecvtime[MAXPLAYERS];
|
||||
unsigned int lastglobalrecvtime; // Identify the last time a packet was recieved.
|
||||
bool hadlate;
|
||||
int netdelay[MAXNETNODES][BACKUPTICS]; // Used for storing network delay times.
|
||||
int lastaverage;
|
||||
|
||||
int nodeforplayer[MAXPLAYERS];
|
||||
int playerfornode[MAXNETNODES];
|
||||
|
@ -151,6 +153,32 @@ CUSTOM_CVAR (Bool, cl_capfps, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
|||
}
|
||||
}
|
||||
|
||||
CVAR(Bool, net_ticbalance, false, CVAR_SERVERINFO | CVAR_NOSAVE)
|
||||
CUSTOM_CVAR(Int, net_extratic, 0, CVAR_SERVERINFO | CVAR_NOSAVE)
|
||||
{
|
||||
if (self < 0)
|
||||
{
|
||||
self = 0;
|
||||
}
|
||||
else if (self > 2)
|
||||
{
|
||||
self = 2;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
CVAR(Int, net_fakelatency, 0, 0);
|
||||
|
||||
struct PacketStore
|
||||
{
|
||||
int timer;
|
||||
doomcom_t message;
|
||||
};
|
||||
|
||||
static TArray<PacketStore> InBuffer;
|
||||
static TArray<PacketStore> OutBuffer;
|
||||
#endif
|
||||
|
||||
// [RH] Special "ticcmds" get stored in here
|
||||
static struct TicSpecial
|
||||
{
|
||||
|
@ -347,6 +375,9 @@ int NetbufferSize ()
|
|||
k += netbuffer[k] + 1;
|
||||
}
|
||||
|
||||
// Network delay byte
|
||||
k++;
|
||||
|
||||
if (netbuffer[0] & NCMD_MULTI)
|
||||
{
|
||||
count = netbuffer[k];
|
||||
|
@ -487,7 +518,30 @@ void HSendPacket (int node, int len)
|
|||
doomcom.remotenode = node;
|
||||
doomcom.datalength = len;
|
||||
|
||||
I_NetCmd ();
|
||||
#ifdef _DEBUG
|
||||
if (net_fakelatency / 2 > 0)
|
||||
{
|
||||
PacketStore store;
|
||||
store.message = doomcom;
|
||||
store.timer = I_GetTime(false) + ((net_fakelatency / 2) / (1000 / TICRATE));
|
||||
OutBuffer.Push(store);
|
||||
}
|
||||
else
|
||||
I_NetCmd();
|
||||
|
||||
for (unsigned int i = 0; i < OutBuffer.Size(); i++)
|
||||
{
|
||||
if (OutBuffer[i].timer <= I_GetTime(false))
|
||||
{
|
||||
doomcom = OutBuffer[i].message;
|
||||
I_NetCmd();
|
||||
OutBuffer.Delete(i);
|
||||
i = -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
I_NetCmd();
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -513,8 +567,38 @@ bool HGetPacket (void)
|
|||
doomcom.command = CMD_GET;
|
||||
I_NetCmd ();
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (net_fakelatency / 2 > 0 && doomcom.remotenode != -1)
|
||||
{
|
||||
PacketStore store;
|
||||
store.message = doomcom;
|
||||
store.timer = I_GetTime(false) + ((net_fakelatency / 2) / (1000 / TICRATE));
|
||||
InBuffer.Push(store);
|
||||
doomcom.remotenode = -1;
|
||||
}
|
||||
|
||||
if (doomcom.remotenode == -1)
|
||||
{
|
||||
bool gotmessage = false;
|
||||
for (unsigned int i = 0; i < InBuffer.Size(); i++)
|
||||
{
|
||||
if (InBuffer[i].timer <= I_GetTime(false))
|
||||
{
|
||||
doomcom = InBuffer[i].message;
|
||||
InBuffer.Delete(i);
|
||||
gotmessage = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!gotmessage)
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if (doomcom.remotenode == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (debugfile)
|
||||
{
|
||||
|
@ -570,6 +654,9 @@ bool HGetPacket (void)
|
|||
|
||||
if (doomcom.datalength != NetbufferSize ())
|
||||
{
|
||||
Printf("Bad packet length %i (calculated %i)\n",
|
||||
doomcom.datalength, NetbufferSize());
|
||||
|
||||
if (debugfile)
|
||||
fprintf (debugfile,"---bad packet length %i (calculated %i)\n",
|
||||
doomcom.datalength, NetbufferSize());
|
||||
|
@ -782,6 +869,9 @@ void GetPackets (void)
|
|||
}
|
||||
}
|
||||
|
||||
// Pull current network delay from node
|
||||
netdelay[netnode][(nettics[netnode]+1) % BACKUPTICS] = netbuffer[k++];
|
||||
|
||||
playerbytes[0] = netconsole;
|
||||
if (netbuffer[0] & NCMD_MULTI)
|
||||
{
|
||||
|
@ -1150,11 +1240,18 @@ void NetUpdate (void)
|
|||
netbuffer[k++] = lowtic;
|
||||
}
|
||||
|
||||
numtics = lowtic - realstart;
|
||||
numtics = MAX(0, lowtic - realstart);
|
||||
if (numtics > BACKUPTICS)
|
||||
I_Error ("NetUpdate: Node %d missed too many tics", i);
|
||||
|
||||
resendto[i] = MAX (0, lowtic - doomcom.extratics);
|
||||
switch (net_extratic)
|
||||
{
|
||||
case 0:
|
||||
default:
|
||||
resendto[i] = lowtic; break;
|
||||
case 1: resendto[i] = MAX(0, lowtic - 1); break;
|
||||
case 2: resendto[i] = nettics[i]; break;
|
||||
}
|
||||
|
||||
if (numtics == 0 && resendOnly && !remoteresend[i] && nettics[i])
|
||||
{
|
||||
|
@ -1190,6 +1287,10 @@ void NetUpdate (void)
|
|||
}
|
||||
}
|
||||
|
||||
// Send current network delay
|
||||
// The number of tics we just made should be removed from the count.
|
||||
netbuffer[k++] = ((maketic - newtics - gametic) / ticdup);
|
||||
|
||||
if (numtics > 0)
|
||||
{
|
||||
int l;
|
||||
|
@ -1299,9 +1400,37 @@ void NetUpdate (void)
|
|||
// that it won't adapt. Fortunately, player prediction helps
|
||||
// alleviate the lag somewhat.
|
||||
|
||||
if (NetMode != NET_PacketServer)
|
||||
if (NetMode == NET_PeerToPeer)
|
||||
{
|
||||
mastertics = nettics[nodeforplayer[Net_Arbitrator]];
|
||||
int totalavg = 0;
|
||||
if (net_ticbalance)
|
||||
{
|
||||
// Try to guess ahead the time it takes to send responses to the slowest node
|
||||
int nodeavg = 0, arbavg = 0;
|
||||
|
||||
for (j = 0; j < BACKUPTICS; j++)
|
||||
{
|
||||
arbavg += netdelay[nodeforplayer[Net_Arbitrator]][j];
|
||||
nodeavg += netdelay[0][j];
|
||||
}
|
||||
arbavg /= BACKUPTICS;
|
||||
nodeavg /= BACKUPTICS;
|
||||
|
||||
// We shouldn't adapt if we are already the arbitrator isn't what we are waiting for, otherwise it just adds more latency
|
||||
if (arbavg > nodeavg)
|
||||
{
|
||||
lastaverage = totalavg = ((arbavg + nodeavg) / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Allow room to guess two tics ahead
|
||||
if (nodeavg > (arbavg + 2) && lastaverage > 0)
|
||||
lastaverage--;
|
||||
totalavg = lastaverage;
|
||||
}
|
||||
}
|
||||
|
||||
mastertics = nettics[nodeforplayer[Net_Arbitrator]] + totalavg;
|
||||
}
|
||||
if (nettics[0] <= mastertics)
|
||||
{
|
||||
|
@ -1346,9 +1475,8 @@ void NetUpdate (void)
|
|||
//
|
||||
// 0 One byte set to NCMD_SETUP+2
|
||||
// 1 One byte for ticdup setting
|
||||
// 2 One byte for extratics setting
|
||||
// 3 One byte for NetMode setting
|
||||
// 4 String with starting map's name
|
||||
// 2 One byte for NetMode setting
|
||||
// 3 String with starting map's name
|
||||
// . Four bytes for the RNG seed
|
||||
// . Stream containing remaining game info
|
||||
//
|
||||
|
@ -1429,10 +1557,9 @@ bool DoArbitrate (void *userdata)
|
|||
data->gotsetup[0] = 0x80;
|
||||
|
||||
ticdup = doomcom.ticdup = netbuffer[1];
|
||||
doomcom.extratics = netbuffer[2];
|
||||
NetMode = netbuffer[3];
|
||||
NetMode = netbuffer[2];
|
||||
|
||||
stream = &netbuffer[4];
|
||||
stream = &netbuffer[3];
|
||||
s = ReadString (&stream);
|
||||
startmap = s;
|
||||
delete[] s;
|
||||
|
@ -1497,9 +1624,8 @@ bool DoArbitrate (void *userdata)
|
|||
{
|
||||
netbuffer[0] = NCMD_SETUP+2;
|
||||
netbuffer[1] = (BYTE)doomcom.ticdup;
|
||||
netbuffer[2] = (BYTE)doomcom.extratics;
|
||||
netbuffer[3] = NetMode;
|
||||
stream = &netbuffer[4];
|
||||
netbuffer[2] = NetMode;
|
||||
stream = &netbuffer[3];
|
||||
WriteString (startmap, &stream);
|
||||
WriteLong (rngseed, &stream);
|
||||
C_WriteCVars (&stream, CVAR_SERVERINFO, true);
|
||||
|
@ -1647,17 +1773,25 @@ void D_CheckNetGame (void)
|
|||
|
||||
consoleplayer = doomcom.consoleplayer;
|
||||
|
||||
v = Args->CheckValue ("-netmode");
|
||||
if (consoleplayer == Net_Arbitrator)
|
||||
{
|
||||
v = Args->CheckValue("-netmode");
|
||||
if (v != NULL)
|
||||
{
|
||||
NetMode = atoi (v) != 0 ? NET_PacketServer : NET_PeerToPeer;
|
||||
NetMode = atoi(v) != 0 ? NET_PacketServer : NET_PeerToPeer;
|
||||
}
|
||||
if (doomcom.numnodes > 1)
|
||||
{
|
||||
Printf ("Selected " TEXTCOLOR_BLUE "%s" TEXTCOLOR_NORMAL " networking mode. (%s)\n", NetMode == NET_PeerToPeer ? "peer to peer" : "packet server",
|
||||
Printf("Selected " TEXTCOLOR_BLUE "%s" TEXTCOLOR_NORMAL " networking mode. (%s)\n", NetMode == NET_PeerToPeer ? "peer to peer" : "packet server",
|
||||
v != NULL ? "forced" : "auto");
|
||||
}
|
||||
|
||||
if (Args->CheckParm("-extratic"))
|
||||
{
|
||||
net_extratic = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// [RH] Setup user info
|
||||
D_SetupUserInfo ();
|
||||
|
||||
|
@ -1683,6 +1817,11 @@ void D_CheckNetGame (void)
|
|||
for (i = 0; i < doomcom.numnodes; i++)
|
||||
nodeingame[i] = true;
|
||||
|
||||
if (consoleplayer != Net_Arbitrator && doomcom.numnodes > 1)
|
||||
{
|
||||
Printf("Arbitrator selected " TEXTCOLOR_BLUE "%s" TEXTCOLOR_NORMAL " networking mode.\n", NetMode == NET_PeerToPeer ? "peer to peer" : "packet server");
|
||||
}
|
||||
|
||||
Printf ("player %i of %i (%i nodes)\n",
|
||||
consoleplayer+1, doomcom.numplayers, doomcom.numnodes);
|
||||
}
|
||||
|
@ -1809,6 +1948,9 @@ void TryRunTics (void)
|
|||
{
|
||||
C_Ticker();
|
||||
M_Ticker();
|
||||
// Repredict the player for new buffered movement
|
||||
P_UnPredictPlayer();
|
||||
P_PredictPlayer(&players[consoleplayer]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1844,6 +1986,9 @@ void TryRunTics (void)
|
|||
{
|
||||
C_Ticker ();
|
||||
M_Ticker ();
|
||||
// Repredict the player for new buffered movement
|
||||
P_UnPredictPlayer();
|
||||
P_PredictPlayer(&players[consoleplayer]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1857,6 +2002,7 @@ void TryRunTics (void)
|
|||
// run the count tics
|
||||
if (counts > 0)
|
||||
{
|
||||
P_UnPredictPlayer();
|
||||
while (counts--)
|
||||
{
|
||||
if (gametic > lowtic)
|
||||
|
@ -1876,6 +2022,7 @@ void TryRunTics (void)
|
|||
|
||||
NetUpdate (); // check for new console commands
|
||||
}
|
||||
P_PredictPlayer(&players[consoleplayer]);
|
||||
S_UpdateSounds (players[consoleplayer].camera); // move positional sounds
|
||||
}
|
||||
}
|
||||
|
@ -2713,7 +2860,6 @@ void Net_SkipCommand (int type, BYTE **stream)
|
|||
CCMD (pings)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
if (playeringame[i])
|
||||
Printf ("% 4d %s\n", currrecvtime[i] - lastrecvtime[i],
|
||||
|
|
|
@ -70,7 +70,6 @@ struct doomcom_t
|
|||
// info common to all nodes
|
||||
SWORD numnodes; // console is always node 0.
|
||||
SWORD ticdup; // 1 = no duplication, 2-5 = dup for slow nets
|
||||
SWORD extratics; // 1 = send a backup tic in every packet
|
||||
#ifdef DJGPP
|
||||
SWORD pad[5]; // keep things aligned for DOS drivers
|
||||
#endif
|
||||
|
@ -143,6 +142,8 @@ extern struct ticcmd_t localcmds[LOCALCMDTICS];
|
|||
|
||||
extern int maketic;
|
||||
extern int nettics[MAXNETNODES];
|
||||
extern int netdelay[MAXNETNODES][BACKUPTICS];
|
||||
extern int nodeforplayer[MAXPLAYERS];
|
||||
|
||||
extern ticcmd_t netcmds[MAXPLAYERS][BACKUPTICS];
|
||||
extern int ticdup;
|
||||
|
|
|
@ -162,6 +162,7 @@ enum ELineFlags
|
|||
ML_BLOCKUSE = 0x02000000, // blocks all use actions through this line
|
||||
ML_BLOCKSIGHT = 0x04000000, // blocks monster line of sight
|
||||
ML_BLOCKHITSCAN = 0x08000000, // blocks hitscan attacks
|
||||
ML_3DMIDTEX_IMPASS = 0x10000000, // [TP] if 3D midtex, behaves like a height-restricted ML_BLOCKING
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -546,6 +546,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireBFG)
|
|||
P_SpawnPlayerMissile (self, 0, 0, 0, PClass::FindClass("BFGBall"), self->angle, NULL, NULL, !!(dmflags2 & DF2_NO_FREEAIMBFG));
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// A_BFGSpray
|
||||
// Spawn a BFG explosion on every monster in view
|
||||
|
@ -559,14 +560,21 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BFGSpray)
|
|||
AActor *thingToHit;
|
||||
AActor *linetarget;
|
||||
|
||||
ACTION_PARAM_START(3);
|
||||
ACTION_PARAM_START(7);
|
||||
ACTION_PARAM_CLASS(spraytype, 0);
|
||||
ACTION_PARAM_INT(numrays, 1);
|
||||
ACTION_PARAM_INT(damagecnt, 2);
|
||||
ACTION_PARAM_ANGLE(angle, 3);
|
||||
ACTION_PARAM_FIXED(distance, 4);
|
||||
ACTION_PARAM_ANGLE(vrange, 5);
|
||||
ACTION_PARAM_INT(defdamage, 6);
|
||||
|
||||
if (spraytype == NULL) spraytype = PClass::FindClass("BFGExtra");
|
||||
if (numrays <= 0) numrays = 40;
|
||||
if (damagecnt <= 0) damagecnt = 15;
|
||||
if (angle == 0) angle = ANG90;
|
||||
if (distance <= 0) distance = 16 * 64 * FRACUNIT;
|
||||
if (vrange == 0) vrange = ANGLE_1 * 32;
|
||||
|
||||
// [RH] Don't crash if no target
|
||||
if (!self->target)
|
||||
|
@ -575,10 +583,10 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BFGSpray)
|
|||
// offset angles from its attack angle
|
||||
for (i = 0; i < numrays; i++)
|
||||
{
|
||||
an = self->angle - ANG90/2 + ANG90/numrays*i;
|
||||
an = self->angle - angle/2 + angle/numrays*i;
|
||||
|
||||
// self->target is the originator (player) of the missile
|
||||
P_AimLineAttack (self->target, an, 16*64*FRACUNIT, &linetarget, ANGLE_1*32);
|
||||
P_AimLineAttack (self->target, an, distance, &linetarget, vrange);
|
||||
|
||||
if (!linetarget)
|
||||
continue;
|
||||
|
@ -589,10 +597,17 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BFGSpray)
|
|||
if (spray && (spray->flags5 & MF5_PUFFGETSOWNER))
|
||||
spray->target = self->target;
|
||||
|
||||
|
||||
if (defdamage == 0)
|
||||
{
|
||||
damage = 0;
|
||||
for (j = 0; j < damagecnt; ++j)
|
||||
damage += (pr_bfgspray() & 7) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if this is used, damagecnt will be ignored
|
||||
damage = defdamage;
|
||||
}
|
||||
|
||||
thingToHit = linetarget;
|
||||
int newdam = P_DamageMobj (thingToHit, self->target, self->target, damage, spray != NULL? FName(spray->DamageType) : FName(NAME_BFGSplash),
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
// copy would be.
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "doomdef.h"
|
||||
#include "v_video.h"
|
||||
#include "gi.h"
|
||||
#include "c_cvars.h"
|
||||
|
@ -48,6 +49,7 @@
|
|||
#include "p_local.h"
|
||||
#include "doomstat.h"
|
||||
#include "g_level.h"
|
||||
#include "d_net.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
|
@ -73,6 +75,7 @@ CVAR (Bool, hud_showscore, false, CVAR_ARCHIVE); // for user maintained score
|
|||
CVAR (Bool, hud_showweapons, true, CVAR_ARCHIVE); // Show weapons collected
|
||||
CVAR (Int , hud_showtime, 0, CVAR_ARCHIVE); // Show time on HUD
|
||||
CVAR (Int , hud_timecolor, CR_GOLD,CVAR_ARCHIVE); // Color of in-game time on HUD
|
||||
CVAR (Int , hud_showlag, 0, CVAR_ARCHIVE); // Show input latency (maketic - gametic difference)
|
||||
|
||||
CVAR (Int, hud_ammo_red, 25, CVAR_ARCHIVE) // ammo percent less than which status is red
|
||||
CVAR (Int, hud_ammo_yellow, 50, CVAR_ARCHIVE) // ammo percent less is yellow more green
|
||||
|
@ -917,6 +920,51 @@ static void DrawTime()
|
|||
DrawHudText(SmallFont, hud_timecolor, timeString, hudwidth - width, height, FRACUNIT);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Draw in-game latency
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static void DrawLatency()
|
||||
{
|
||||
if (hud_showlag <= 0 ||
|
||||
(hud_showlag == 1 && !netgame) ||
|
||||
hud_showlag > 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
int i, localdelay = 0, arbitratordelay = 0;
|
||||
for (i = 0; i < BACKUPTICS; i++) localdelay += netdelay[0][i];
|
||||
for (i = 0; i < BACKUPTICS; i++) arbitratordelay += netdelay[nodeforplayer[Net_Arbitrator]][i];
|
||||
localdelay = ((localdelay / BACKUPTICS) * ticdup) * (1000 / TICRATE);
|
||||
arbitratordelay = ((arbitratordelay / BACKUPTICS) * ticdup) * (1000 / TICRATE);
|
||||
int color = CR_GREEN;
|
||||
if (MAX(localdelay, arbitratordelay) > 200)
|
||||
{
|
||||
color = CR_YELLOW;
|
||||
}
|
||||
if (MAX(localdelay, arbitratordelay) > 400)
|
||||
{
|
||||
color = CR_ORANGE;
|
||||
}
|
||||
if (MAX(localdelay, arbitratordelay) >= ((BACKUPTICS / 2 - 1) * ticdup) * (1000 / TICRATE))
|
||||
{
|
||||
color = CR_RED;
|
||||
}
|
||||
|
||||
char tempstr[32];
|
||||
|
||||
const int millis = (level.time % TICRATE) * (1000 / TICRATE);
|
||||
mysnprintf(tempstr, sizeof(tempstr), "a:%dms - l:%dms", arbitratordelay, localdelay);
|
||||
|
||||
const int characterCount = strlen(tempstr);
|
||||
const int width = SmallFont->GetCharWidth('0') * characterCount + 2; // small offset from screen's border
|
||||
const int height = SmallFont->GetHeight() * 2;
|
||||
|
||||
DrawHudText(SmallFont, color, tempstr, hudwidth - width, height, FRACUNIT);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -982,6 +1030,7 @@ void DrawHUD()
|
|||
if (idmypos) DrawCoordinates(CPlayer);
|
||||
|
||||
DrawTime();
|
||||
DrawLatency();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -48,6 +48,8 @@
|
|||
#include "d_player.h"
|
||||
#include "hu_stuff.h"
|
||||
#include "gstrings.h"
|
||||
#include "d_net.h"
|
||||
#include "c_dispatch.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
@ -61,7 +63,7 @@
|
|||
|
||||
static void HU_DoDrawScores (player_t *, player_t *[MAXPLAYERS]);
|
||||
static void HU_DrawTimeRemaining (int y);
|
||||
static void HU_DrawPlayer (player_t *, bool, int, int, int, int, int, int, int, int);
|
||||
static void HU_DrawPlayer(player_t *, bool, int, int, int, int, int, int, int, int, int);
|
||||
|
||||
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
|
||||
|
||||
|
@ -116,6 +118,8 @@ int STACK_ARGS compareteams (const void *arg1, const void *arg2)
|
|||
return diff;
|
||||
}
|
||||
|
||||
bool SB_ForceActive = false;
|
||||
|
||||
// PRIVATE DATA DEFINITIONS ------------------------------------------------
|
||||
|
||||
// CODE --------------------------------------------------------------------
|
||||
|
@ -228,7 +232,7 @@ static void HU_DoDrawScores (player_t *player, player_t *sortedplayers[MAXPLAYER
|
|||
int maxnamewidth, maxscorewidth, maxiconheight;
|
||||
int numTeams = 0;
|
||||
int x, y, ypadding, bottom;
|
||||
int col2, col3, col4;
|
||||
int col2, col3, col4, col5;
|
||||
|
||||
if (deathmatch)
|
||||
{
|
||||
|
@ -309,12 +313,14 @@ static void HU_DoDrawScores (player_t *player, player_t *sortedplayers[MAXPLAYER
|
|||
|
||||
const char *text_color = GStrings("SCORE_COLOR"),
|
||||
*text_frags = GStrings(deathmatch ? "SCORE_FRAGS" : "SCORE_KILLS"),
|
||||
*text_name = GStrings("SCORE_NAME");
|
||||
*text_name = GStrings("SCORE_NAME"),
|
||||
*text_delay = GStrings("SCORE_DELAY");
|
||||
|
||||
col2 = (SmallFont->StringWidth(text_color) + 8) * CleanXfac;
|
||||
col3 = col2 + (SmallFont->StringWidth(text_frags) + 8) * CleanXfac;
|
||||
col4 = col3 + maxscorewidth * CleanXfac;
|
||||
x = (SCREENWIDTH >> 1) - ((maxnamewidth * CleanXfac + col4) >> 1);
|
||||
col5 = col4 + (maxnamewidth + 8) * CleanXfac;
|
||||
x = (SCREENWIDTH >> 1) - (((SmallFont->StringWidth(text_delay) * CleanXfac) + col5) >> 1);
|
||||
|
||||
screen->DrawText (SmallFont, color, x, y, text_color,
|
||||
DTA_CleanNoMove, true, TAG_DONE);
|
||||
|
@ -325,6 +331,9 @@ static void HU_DoDrawScores (player_t *player, player_t *sortedplayers[MAXPLAYER
|
|||
screen->DrawText (SmallFont, color, x + col4, y, text_name,
|
||||
DTA_CleanNoMove, true, TAG_DONE);
|
||||
|
||||
screen->DrawText(SmallFont, color, x + col5, y, text_delay,
|
||||
DTA_CleanNoMove, true, TAG_DONE);
|
||||
|
||||
y += height + 6 * CleanYfac;
|
||||
bottom -= height;
|
||||
|
||||
|
@ -332,7 +341,7 @@ static void HU_DoDrawScores (player_t *player, player_t *sortedplayers[MAXPLAYER
|
|||
{
|
||||
if (playeringame[sortedplayers[i] - players])
|
||||
{
|
||||
HU_DrawPlayer (sortedplayers[i], player==sortedplayers[i], x, col2, col3, col4, maxnamewidth, y, ypadding, lineheight);
|
||||
HU_DrawPlayer(sortedplayers[i], player == sortedplayers[i], x, col2, col3, col4, col5, maxnamewidth, y, ypadding, lineheight);
|
||||
y += lineheight + CleanYfac;
|
||||
}
|
||||
}
|
||||
|
@ -377,7 +386,7 @@ static void HU_DrawTimeRemaining (int y)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static void HU_DrawPlayer (player_t *player, bool highlight, int col1, int col2, int col3, int col4, int maxnamewidth, int y, int ypadding, int height)
|
||||
static void HU_DrawPlayer (player_t *player, bool highlight, int col1, int col2, int col3, int col4, int col5, int maxnamewidth, int y, int ypadding, int height)
|
||||
{
|
||||
int color;
|
||||
char str[80];
|
||||
|
@ -387,12 +396,13 @@ static void HU_DrawPlayer (player_t *player, bool highlight, int col1, int col2,
|
|||
// The teamplay mode uses colors to show teams, so we need some
|
||||
// other way to do highlighting. And it may as well be used for
|
||||
// all modes for the sake of consistancy.
|
||||
screen->Dim(MAKERGB(200,245,255), 0.125f, col1 - 12*CleanXfac, y - 1, col4 + (maxnamewidth + 24)*CleanXfac, height + 2);
|
||||
screen->Dim(MAKERGB(200,245,255), 0.125f, col1 - 12*CleanXfac, y - 1, col5 + (maxnamewidth + 24)*CleanXfac, height + 2);
|
||||
}
|
||||
|
||||
col2 += col1;
|
||||
col3 += col1;
|
||||
col4 += col1;
|
||||
col5 += col1;
|
||||
|
||||
color = HU_GetRowColor(player, highlight);
|
||||
HU_DrawColorBar(col1, y, height, (int)(player - players));
|
||||
|
@ -412,6 +422,18 @@ static void HU_DrawPlayer (player_t *player, bool highlight, int col1, int col2,
|
|||
screen->DrawText (SmallFont, color, col4, y + ypadding, player->userinfo.GetName(),
|
||||
DTA_CleanNoMove, true, TAG_DONE);
|
||||
|
||||
int avgdelay = 0;
|
||||
for (int i = 0; i < BACKUPTICS; i++)
|
||||
{
|
||||
avgdelay += netdelay[nodeforplayer[(int)(player - players)]][i];
|
||||
}
|
||||
avgdelay /= BACKUPTICS;
|
||||
|
||||
mysnprintf(str, countof(str), "%d", (avgdelay * ticdup) * (1000 / TICRATE));
|
||||
|
||||
screen->DrawText(SmallFont, color, col5, y + ypadding, str,
|
||||
DTA_CleanNoMove, true, TAG_DONE);
|
||||
|
||||
if (teamplay && Teams[player->userinfo.GetTeam()].GetLogo().IsNotEmpty ())
|
||||
{
|
||||
FTexture *pic = TexMan[Teams[player->userinfo.GetTeam()].GetLogo().GetChars ()];
|
||||
|
@ -473,3 +495,8 @@ int HU_GetRowColor(player_t *player, bool highlight)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
CCMD (togglescoreboard)
|
||||
{
|
||||
SB_ForceActive = !SB_ForceActive;
|
||||
}
|
||||
|
|
|
@ -52,6 +52,8 @@ void HU_GetPlayerWidths(int &maxnamewidth, int &maxscorewidth, int &maxiconheigh
|
|||
void HU_DrawColorBar(int x, int y, int height, int playernum);
|
||||
int HU_GetRowColor(player_t *player, bool hightlight);
|
||||
|
||||
extern bool SB_ForceActive;
|
||||
|
||||
// Sorting routines
|
||||
|
||||
int STACK_ARGS comparepoints(const void *arg1, const void *arg2);
|
||||
|
|
|
@ -208,11 +208,11 @@ void PacketSend (void)
|
|||
{
|
||||
I_FatalError("Netbuffer overflow!");
|
||||
}
|
||||
assert(!(doomcom.data[0] & NCMD_COMPRESSED));
|
||||
|
||||
uLong size = TRANSMIT_SIZE - 1;
|
||||
if (doomcom.datalength >= 10)
|
||||
{
|
||||
assert(!(doomcom.data[0] & NCMD_COMPRESSED));
|
||||
TransmitBuffer[0] = doomcom.data[0] | NCMD_COMPRESSED;
|
||||
c = compress2(TransmitBuffer + 1, &size, doomcom.data + 1, doomcom.datalength - 1, 9);
|
||||
size += 1;
|
||||
|
@ -938,11 +938,6 @@ bool I_InitNetwork (void)
|
|||
doomcom.ticdup = 1;
|
||||
}
|
||||
|
||||
if (Args->CheckParm ("-extratic"))
|
||||
doomcom.extratics = 1;
|
||||
else
|
||||
doomcom.extratics = 0;
|
||||
|
||||
v = Args->CheckValue ("-port");
|
||||
if (v)
|
||||
{
|
||||
|
|
|
@ -298,6 +298,8 @@ xx(Abs)
|
|||
xx(ACS_NamedExecuteWithResult)
|
||||
xx(CallACS)
|
||||
xx(Sqrt)
|
||||
xx(CheckClass)
|
||||
xx(IsPointerEqual)
|
||||
|
||||
// Various actor names which are used internally
|
||||
xx(MapSpot)
|
||||
|
@ -418,6 +420,7 @@ xx(Passuse)
|
|||
xx(Repeatspecial)
|
||||
xx(Conversation)
|
||||
xx(Locknumber)
|
||||
xx(Midtex3dimpassible)
|
||||
|
||||
xx(Playercross)
|
||||
xx(Playeruse)
|
||||
|
|
|
@ -258,6 +258,13 @@ bool P_GetMidTexturePosition(const line_t *line, int sideno, fixed_t *ptextop, f
|
|||
|
||||
bool P_LineOpening_3dMidtex(AActor *thing, const line_t *linedef, FLineOpening &open, bool restrict)
|
||||
{
|
||||
// [TP] Impassible-like 3dmidtextures do not block missiles
|
||||
if ((linedef->flags & ML_3DMIDTEX_IMPASS)
|
||||
&& (thing->flags & MF_MISSILE || thing->BounceFlags & BOUNCE_MBF))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
fixed_t tt, tb;
|
||||
|
||||
open.abovemidtex = false;
|
||||
|
|
|
@ -3843,6 +3843,10 @@ void DLevelScript::DoSetActorProperty (AActor *actor, int property, int value)
|
|||
actor->reactiontime = value;
|
||||
break;
|
||||
|
||||
case APROP_MeleeRange:
|
||||
actor->meleerange = value;
|
||||
break;
|
||||
|
||||
case APROP_ViewHeight:
|
||||
if (actor->IsKindOf (RUNTIME_CLASS (APlayerPawn)))
|
||||
static_cast<APlayerPawn *>(actor)->ViewHeight = value;
|
||||
|
@ -4368,6 +4372,9 @@ enum EACSFunctions
|
|||
ACSF_ChangeActorPitch, // 80
|
||||
ACSF_GetArmorInfo,
|
||||
ACSF_DropInventory,
|
||||
ACSF_PickActor,
|
||||
ACSF_IsPointerEqual,
|
||||
ACSF_CanRaiseActor,
|
||||
|
||||
/* Zandronum's - these must be skipped when we reach 99!
|
||||
-100:ResetMap(0),
|
||||
|
@ -5593,6 +5600,74 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
|
|||
}
|
||||
break;
|
||||
|
||||
case ACSF_PickActor:
|
||||
if (argCount >= 5)
|
||||
{
|
||||
actor = SingleActorFromTID(args[0], activator);
|
||||
if (actor == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD actorMask = MF_SHOOTABLE;
|
||||
if (argCount >= 6) {
|
||||
actorMask = args[5];
|
||||
}
|
||||
|
||||
DWORD wallMask = ML_BLOCKEVERYTHING | ML_BLOCKHITSCAN;
|
||||
if (argCount >= 7) {
|
||||
wallMask = args[6];
|
||||
}
|
||||
|
||||
AActor* pickedActor = P_LinePickActor(actor, args[1] << 16, args[3], args[2] << 16, actorMask, wallMask);
|
||||
if (pickedActor == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
pickedActor->RemoveFromHash();
|
||||
pickedActor->tid = args[4];
|
||||
pickedActor->AddToHash();
|
||||
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case ACSF_IsPointerEqual:
|
||||
{
|
||||
int tid1 = 0, tid2 = 0;
|
||||
switch (argCount)
|
||||
{
|
||||
case 4: tid2 = args[3];
|
||||
case 3: tid1 = args[2];
|
||||
}
|
||||
|
||||
actor = SingleActorFromTID(tid1, activator);
|
||||
AActor * actor2 = tid2 == tid1 ? actor : SingleActorFromTID(tid2, activator);
|
||||
|
||||
return COPY_AAPTR(actor, args[0]) == COPY_AAPTR(actor2, args[1]);
|
||||
}
|
||||
break;
|
||||
|
||||
case ACSF_CanRaiseActor:
|
||||
if (argCount >= 1) {
|
||||
if (args[0] == 0) {
|
||||
actor = SingleActorFromTID(args[0], activator);
|
||||
if (actor != NULL) {
|
||||
return P_Thing_CanRaise(actor);
|
||||
}
|
||||
}
|
||||
|
||||
FActorIterator iterator(args[0]);
|
||||
bool canraiseall = false;
|
||||
while ((actor = iterator.Next()))
|
||||
{
|
||||
canraiseall = !P_Thing_CanRaise(actor) | canraiseall;
|
||||
}
|
||||
|
||||
return !canraiseall;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -171,6 +171,7 @@ int P_Thing_Damage (int tid, AActor *whofor0, int amount, FName type);
|
|||
void P_Thing_SetVelocity(AActor *actor, fixed_t vx, fixed_t vy, fixed_t vz, bool add, bool setbob);
|
||||
void P_RemoveThing(AActor * actor);
|
||||
bool P_Thing_Raise(AActor *thing);
|
||||
bool P_Thing_CanRaise(AActor *thing);
|
||||
const PClass *P_GetSpawnableType(int spawnnum);
|
||||
|
||||
//
|
||||
|
@ -462,6 +463,7 @@ enum // P_LineAttack flags
|
|||
|
||||
AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, const PClass *pufftype, int flags = 0, AActor **victim = NULL, int *actualdamage = NULL);
|
||||
AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, FName pufftype, int flags = 0, AActor **victim = NULL, int *actualdamage = NULL);
|
||||
AActor *P_LinePickActor (AActor *t1, angle_t angle, fixed_t distance, int pitch, DWORD actorMask, DWORD wallMask);
|
||||
void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *target, angle_t angle, int pitch);
|
||||
void P_TraceBleed (int damage, AActor *target, angle_t angle, int pitch);
|
||||
void P_TraceBleed (int damage, AActor *target, AActor *missile); // missile version
|
||||
|
|
|
@ -380,6 +380,8 @@ bool P_TeleportMove(AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefra
|
|||
// ... and some items can never be telefragged while others will be telefragged by everything that teleports upon them.
|
||||
if ((StompAlwaysFrags && !(th->flags6 & MF6_NOTELEFRAG)) || (th->flags7 & MF7_ALWAYSTELEFRAG))
|
||||
{
|
||||
// Don't actually damage if predicting a teleport
|
||||
if (thing->player == NULL || !(thing->player->cheats & CF_PREDICTING))
|
||||
P_DamageMobj(th, thing, thing, TELEFRAG_DAMAGE, NAME_Telefrag, DMG_THRUSTLESS);
|
||||
continue;
|
||||
}
|
||||
|
@ -1981,13 +1983,6 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y,
|
|||
thing->AdjustFloorClip();
|
||||
}
|
||||
|
||||
// [RH] Don't activate anything if just predicting
|
||||
if (thing->player && (thing->player->cheats & CF_PREDICTING))
|
||||
{
|
||||
thing->flags6 &= ~MF6_INTRYMOVE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// if any special lines were hit, do the effect
|
||||
if (!(thing->flags & (MF_TELEPORT | MF_NOCLIP)))
|
||||
{
|
||||
|
@ -1998,7 +1993,11 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y,
|
|||
oldside = P_PointOnLineSide(oldx, oldy, ld);
|
||||
if (side != oldside && ld->special && !(thing->flags6 & MF6_NOTRIGGER))
|
||||
{
|
||||
if (thing->player)
|
||||
if (thing->player && (thing->player->cheats & CF_PREDICTING))
|
||||
{
|
||||
P_PredictLine(ld, thing, oldside, SPAC_Cross);
|
||||
}
|
||||
else if (thing->player)
|
||||
{
|
||||
P_ActivateLine(ld, thing, oldside, SPAC_Cross);
|
||||
}
|
||||
|
@ -2024,6 +2023,13 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y,
|
|||
}
|
||||
}
|
||||
|
||||
// [RH] Don't activate anything if just predicting
|
||||
if (thing->player && (thing->player->cheats & CF_PREDICTING))
|
||||
{
|
||||
thing->flags6 &= ~MF6_INTRYMOVE;
|
||||
return true;
|
||||
}
|
||||
|
||||
// [RH] Check for crossing fake floor/ceiling
|
||||
newsec = thing->Sector;
|
||||
if (newsec->heightsec && oldsec->heightsec && newsec->SecActTarget)
|
||||
|
@ -3783,6 +3789,52 @@ AActor *P_LineAttack(AActor *t1, angle_t angle, fixed_t distance,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// P_LinePickActor
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
AActor *P_LinePickActor(AActor *t1, angle_t angle, fixed_t distance, int pitch,
|
||||
DWORD actorMask, DWORD wallMask)
|
||||
{
|
||||
fixed_t vx, vy, vz, shootz;
|
||||
|
||||
angle >>= ANGLETOFINESHIFT;
|
||||
pitch = (angle_t)(pitch) >> ANGLETOFINESHIFT;
|
||||
|
||||
vx = FixedMul(finecosine[pitch], finecosine[angle]);
|
||||
vy = FixedMul(finecosine[pitch], finesine[angle]);
|
||||
vz = -finesine[pitch];
|
||||
|
||||
shootz = t1->z - t1->floorclip + (t1->height >> 1);
|
||||
if (t1->player != NULL)
|
||||
{
|
||||
shootz += FixedMul(t1->player->mo->AttackZOffset, t1->player->crouchfactor);
|
||||
}
|
||||
else
|
||||
{
|
||||
shootz += 8 * FRACUNIT;
|
||||
}
|
||||
|
||||
FTraceResults trace;
|
||||
Origin TData;
|
||||
|
||||
TData.Caller = t1;
|
||||
TData.hitGhosts = true;
|
||||
|
||||
if (Trace(t1->x, t1->y, shootz, t1->Sector, vx, vy, vz, distance,
|
||||
actorMask, wallMask, t1, trace, TRACE_NoSky, CheckForActor, &TData))
|
||||
{
|
||||
if (trace.HitType == TRACE_HitActor)
|
||||
{
|
||||
return trace.Actor;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
static FRandom pr_playerinspecialsector ("PlayerInSpecialSector");
|
||||
void P_SetupPortals();
|
||||
|
||||
EXTERN_CVAR(Bool, cl_predict_specials)
|
||||
|
||||
IMPLEMENT_POINTY_CLASS (DScroller)
|
||||
DECLARE_POINTER (m_Interpolations[0])
|
||||
|
@ -408,6 +409,48 @@ bool P_TestActivateLine (line_t *line, AActor *mo, int side, int activationType)
|
|||
return true;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// P_PredictLine
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
bool P_PredictLine(line_t *line, AActor *mo, int side, int activationType)
|
||||
{
|
||||
int lineActivation;
|
||||
INTBOOL buttonSuccess;
|
||||
BYTE special;
|
||||
|
||||
// Only predict a very specifc section of specials
|
||||
if (line->special != Teleport_Line &&
|
||||
line->special != Teleport)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!P_TestActivateLine(line, mo, side, activationType) || !cl_predict_specials)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (line->locknumber > 0) return false;
|
||||
lineActivation = line->activation;
|
||||
buttonSuccess = false;
|
||||
buttonSuccess = P_ExecuteSpecial(line->special,
|
||||
line, mo, side == 1, line->args[0],
|
||||
line->args[1], line->args[2],
|
||||
line->args[3], line->args[4]);
|
||||
|
||||
special = line->special;
|
||||
|
||||
// end of changed code
|
||||
if (developer && buttonSuccess)
|
||||
{
|
||||
Printf("Line special %d predicted on line %i\n", special, int(line - lines));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// P_PlayerInSpecialSector
|
||||
// Called every tic frame
|
||||
|
|
|
@ -166,6 +166,7 @@ void P_UpdateSpecials (void);
|
|||
// when needed
|
||||
bool P_ActivateLine (line_t *ld, AActor *mo, int side, int activationType);
|
||||
bool P_TestActivateLine (line_t *ld, AActor *mo, int side, int activationType);
|
||||
bool P_PredictLine (line_t *ld, AActor *mo, int side, int activationType);
|
||||
|
||||
void P_PlayerInSpecialSector (player_t *player, sector_t * sector=NULL);
|
||||
void P_PlayerOnSpecialFlat (player_t *player, int floorType);
|
||||
|
|
|
@ -96,6 +96,8 @@ void P_SpawnTeleportFog(fixed_t x, fixed_t y, fixed_t z, int spawnid)
|
|||
bool P_Teleport (AActor *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
|
||||
bool useFog, bool sourceFog, bool keepOrientation, bool bHaltVelocity, bool keepHeight)
|
||||
{
|
||||
bool predicting = (thing->player && (thing->player->cheats & CF_PREDICTING));
|
||||
|
||||
fixed_t oldx;
|
||||
fixed_t oldy;
|
||||
fixed_t oldz;
|
||||
|
@ -181,19 +183,22 @@ bool P_Teleport (AActor *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
|
|||
angle = thing->angle;
|
||||
}
|
||||
// Spawn teleport fog at source and destination
|
||||
if (sourceFog)
|
||||
if (sourceFog && !predicting)
|
||||
{
|
||||
fixed_t fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT;
|
||||
AActor *fog = Spawn<ATeleportFog> (oldx, oldy, oldz + fogDelta, ALLOW_REPLACE);
|
||||
fog->target = thing;
|
||||
}
|
||||
if (useFog)
|
||||
{
|
||||
if (!predicting)
|
||||
{
|
||||
fixed_t fogDelta = thing->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT;
|
||||
an = angle >> ANGLETOFINESHIFT;
|
||||
AActor *fog = Spawn<ATeleportFog> (x + 20*finecosine[an],
|
||||
y + 20*finesine[an], thing->z + fogDelta, ALLOW_REPLACE);
|
||||
AActor *fog = Spawn<ATeleportFog>(x + 20 * finecosine[an],
|
||||
y + 20 * finesine[an], thing->z + fogDelta, ALLOW_REPLACE);
|
||||
fog->target = thing;
|
||||
}
|
||||
if (thing->player)
|
||||
{
|
||||
// [RH] Zoom player's field of vision
|
||||
|
@ -226,7 +231,7 @@ bool P_Teleport (AActor *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
|
|||
return true;
|
||||
}
|
||||
|
||||
static AActor *SelectTeleDest (int tid, int tag)
|
||||
static AActor *SelectTeleDest (int tid, int tag, bool norandom)
|
||||
{
|
||||
AActor *searcher;
|
||||
|
||||
|
@ -276,7 +281,7 @@ static AActor *SelectTeleDest (int tid, int tag)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (count != 1)
|
||||
if (count != 1 && !norandom)
|
||||
{
|
||||
count = 1 + (pr_teleport() % count);
|
||||
}
|
||||
|
@ -323,6 +328,7 @@ static AActor *SelectTeleDest (int tid, int tag)
|
|||
bool EV_Teleport (int tid, int tag, line_t *line, int side, AActor *thing, bool fog,
|
||||
bool sourceFog, bool keepOrientation, bool haltVelocity, bool keepHeight)
|
||||
{
|
||||
|
||||
AActor *searcher;
|
||||
fixed_t z;
|
||||
angle_t angle = 0;
|
||||
|
@ -334,6 +340,7 @@ bool EV_Teleport (int tid, int tag, line_t *line, int side, AActor *thing, bool
|
|||
{ // Teleport function called with an invalid actor
|
||||
return false;
|
||||
}
|
||||
bool predicting = (thing->player && (thing->player->cheats & CF_PREDICTING));
|
||||
if (thing->flags2 & MF2_NOTELEPORT)
|
||||
{
|
||||
return false;
|
||||
|
@ -342,7 +349,7 @@ bool EV_Teleport (int tid, int tag, line_t *line, int side, AActor *thing, bool
|
|||
{ // Don't teleport if hit back of line, so you can get out of teleporter.
|
||||
return 0;
|
||||
}
|
||||
searcher = SelectTeleDest (tid, tag);
|
||||
searcher = SelectTeleDest(tid, tag, predicting);
|
||||
if (searcher == NULL)
|
||||
{
|
||||
return false;
|
||||
|
@ -390,7 +397,7 @@ bool EV_Teleport (int tid, int tag, line_t *line, int side, AActor *thing, bool
|
|||
thing->velx = FixedMul(velx, c) - FixedMul(vely, s);
|
||||
thing->vely = FixedMul(vely, c) + FixedMul(velx, s);
|
||||
}
|
||||
if ((velx | vely) == 0 && thing->player != NULL && thing->player->mo == thing)
|
||||
if ((velx | vely) == 0 && thing->player != NULL && thing->player->mo == thing && !predicting)
|
||||
{
|
||||
thing->player->mo->PlayIdle ();
|
||||
}
|
||||
|
|
|
@ -445,6 +445,40 @@ bool P_Thing_Raise(AActor *thing)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool P_Thing_CanRaise(AActor *thing)
|
||||
{
|
||||
FState * RaiseState = thing->GetRaiseState();
|
||||
if (RaiseState == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AActor *info = thing->GetDefault();
|
||||
|
||||
// Check against real height and radius
|
||||
int oldflags = thing->flags;
|
||||
fixed_t oldheight = thing->height;
|
||||
fixed_t oldradius = thing->radius;
|
||||
|
||||
thing->flags |= MF_SOLID;
|
||||
thing->height = info->height;
|
||||
thing->radius = info->radius;
|
||||
|
||||
bool check = P_CheckPosition (thing, thing->x, thing->y);
|
||||
|
||||
// Restore checked properties
|
||||
thing->flags = oldflags;
|
||||
thing->radius = oldradius;
|
||||
thing->height = oldheight;
|
||||
|
||||
if (!check)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void P_Thing_SetVelocity(AActor *actor, fixed_t vx, fixed_t vy, fixed_t vz, bool add, bool setbob)
|
||||
{
|
||||
if (actor != NULL)
|
||||
|
|
|
@ -1030,11 +1030,16 @@ public:
|
|||
Flag(ld->flags, ML_BLOCKHITSCAN, key);
|
||||
continue;
|
||||
|
||||
// [Dusk] lock number
|
||||
// [TP] Locks the special with a key
|
||||
case NAME_Locknumber:
|
||||
ld->locknumber = CheckInt(key);
|
||||
continue;
|
||||
|
||||
// [TP] Causes a 3d midtex to behave like an impassible line
|
||||
case NAME_Midtex3dimpassible:
|
||||
Flag(ld->flags, ML_3DMIDTEX_IMPASS, key);
|
||||
continue;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1081,6 +1086,10 @@ public:
|
|||
{
|
||||
ld->args[1] = -FName(arg1str);
|
||||
}
|
||||
if ((ld->flags & ML_3DMIDTEX_IMPASS) && !(ld->flags & ML_3DMIDTEX)) // [TP]
|
||||
{
|
||||
Printf ("Line %d has midtex3dimpassible without midtex3d.\n", index);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
|
|
@ -62,6 +62,7 @@ static FRandom pr_skullpop ("SkullPop");
|
|||
|
||||
// Variables for prediction
|
||||
CVAR (Bool, cl_noprediction, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR(Bool, cl_predict_specials, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
static player_t PredictionPlayerBackup;
|
||||
static BYTE PredictionActorBackup[sizeof(AActor)];
|
||||
static TArray<sector_t *> PredictionTouchingSectorsBackup;
|
||||
|
@ -2722,8 +2723,12 @@ void P_PredictPlayer (player_t *player)
|
|||
}
|
||||
act->BlockNode = NULL;
|
||||
|
||||
bool NoInterpolateOld = R_GetViewInterpolationStatus();
|
||||
for (int i = gametic; i < maxtic; ++i)
|
||||
{
|
||||
if (!NoInterpolateOld)
|
||||
R_RebuildViewInterpolation(player);
|
||||
|
||||
player->cmd = localcmds[i % LOCALCMDTICS];
|
||||
P_PlayerThink (player);
|
||||
player->mo->Tick ();
|
||||
|
|
|
@ -729,6 +729,42 @@ void R_ClearPastViewer (AActor *actor)
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// R_RebuildViewInterpolation
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void R_RebuildViewInterpolation(player_t *player)
|
||||
{
|
||||
if (player == NULL || player->camera == NULL)
|
||||
return;
|
||||
|
||||
if (!NoInterpolateView)
|
||||
return;
|
||||
NoInterpolateView = false;
|
||||
|
||||
InterpolationViewer *iview = FindPastViewer(player->camera);
|
||||
|
||||
iview->oviewx = iview->nviewx;
|
||||
iview->oviewy = iview->nviewy;
|
||||
iview->oviewz = iview->nviewz;
|
||||
iview->oviewpitch = iview->nviewpitch;
|
||||
iview->oviewangle = iview->nviewangle;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// R_GetViewInterpolationStatus
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool R_GetViewInterpolationStatus()
|
||||
{
|
||||
return NoInterpolateView;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// R_SetupFrame
|
||||
|
|
|
@ -61,6 +61,8 @@ inline angle_t R_PointToAngle (fixed_t x, fixed_t y) { return R_PointToAngle2 (v
|
|||
subsector_t *R_PointInSubsector (fixed_t x, fixed_t y);
|
||||
fixed_t R_PointToDist2 (fixed_t dx, fixed_t dy);
|
||||
void R_ResetViewInterpolation ();
|
||||
void R_RebuildViewInterpolation(player_t *player);
|
||||
bool R_GetViewInterpolationStatus();
|
||||
void R_SetViewSize (int blocks);
|
||||
void R_SetFOV (float fov);
|
||||
float R_GetFOV ();
|
||||
|
|
|
@ -2347,14 +2347,14 @@ class AMusicChanger : public ASectorAction
|
|||
{
|
||||
DECLARE_CLASS (AMusicChanger, ASectorAction)
|
||||
public:
|
||||
virtual bool TriggerAction (AActor *triggerer, int activationType);
|
||||
virtual bool DoTriggerAction (AActor *triggerer, int activationType);
|
||||
virtual void Tick();
|
||||
virtual void PostBeginPlay();
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(AMusicChanger)
|
||||
|
||||
bool AMusicChanger::TriggerAction (AActor *triggerer, int activationType)
|
||||
bool AMusicChanger::DoTriggerAction (AActor *triggerer, int activationType)
|
||||
{
|
||||
if (activationType & SECSPAC_Enter)
|
||||
{
|
||||
|
@ -2364,7 +2364,7 @@ bool AMusicChanger::TriggerAction (AActor *triggerer, int activationType)
|
|||
reactiontime = 30;
|
||||
}
|
||||
}
|
||||
return Super::TriggerAction (triggerer, activationType);
|
||||
return Super::DoTriggerAction (triggerer, activationType);
|
||||
}
|
||||
|
||||
void AMusicChanger::Tick()
|
||||
|
|
|
@ -601,11 +601,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Jump)
|
|||
//==========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfHealthLower)
|
||||
{
|
||||
ACTION_PARAM_START(2);
|
||||
ACTION_PARAM_START(3);
|
||||
ACTION_PARAM_INT(health, 0);
|
||||
ACTION_PARAM_STATE(jump, 1);
|
||||
ACTION_PARAM_INT(ptr_selector, 2);
|
||||
|
||||
if (self->health < health) ACTION_JUMP(jump);
|
||||
AActor *measured;
|
||||
|
||||
measured = COPY_AAPTR(self, ptr_selector);
|
||||
|
||||
if (measured && measured->health < health)
|
||||
{
|
||||
ACTION_JUMP(jump);
|
||||
}
|
||||
|
||||
ACTION_SET_RESULT(false); // Jumps should never set the result for inventory state chains!
|
||||
}
|
||||
|
@ -1757,6 +1765,10 @@ enum SIX_Flags
|
|||
SIXF_TRANSFERSTENCILCOL = 1 << 17,
|
||||
SIXF_TRANSFERALPHA = 1 << 18,
|
||||
SIXF_TRANSFERRENDERSTYLE = 1 << 19,
|
||||
SIXF_SETTARGET = 1 << 20,
|
||||
SIXF_SETTRACER = 1 << 21,
|
||||
SIXF_NOPOINTERS = 1 << 22,
|
||||
SIXF_ORIGINATOR = 1 << 23,
|
||||
};
|
||||
|
||||
static bool InitSpawnedItem(AActor *self, AActor *mo, int flags)
|
||||
|
@ -1792,11 +1804,13 @@ static bool InitSpawnedItem(AActor *self, AActor *mo, int flags)
|
|||
{
|
||||
mo->pitch = self->pitch;
|
||||
}
|
||||
if (!(flags & SIXF_ORIGINATOR))
|
||||
{
|
||||
while (originator && originator->isMissile())
|
||||
{
|
||||
originator = originator->target;
|
||||
}
|
||||
|
||||
}
|
||||
if (flags & SIXF_TELEFRAG)
|
||||
{
|
||||
P_TeleportMove(mo, mo->x, mo->y, mo->z, true);
|
||||
|
@ -1813,13 +1827,12 @@ static bool InitSpawnedItem(AActor *self, AActor *mo, int flags)
|
|||
mo->Destroy();
|
||||
return false;
|
||||
}
|
||||
else if (originator)
|
||||
else if (originator && !(flags & SIXF_NOPOINTERS))
|
||||
{
|
||||
if (originator->flags3 & MF3_ISMONSTER)
|
||||
{
|
||||
// If this is a monster transfer all friendliness information
|
||||
mo->CopyFriendliness(originator, true);
|
||||
if (flags & SIXF_SETMASTER) mo->master = originator; // don't let it attack you (optional)!
|
||||
}
|
||||
else if (originator->player)
|
||||
{
|
||||
|
@ -1845,10 +1858,26 @@ static bool InitSpawnedItem(AActor *self, AActor *mo, int flags)
|
|||
// If this is a missile or something else set the target to the originator
|
||||
mo->target = originator ? originator : self;
|
||||
}
|
||||
if (flags & SIXF_NOPOINTERS)
|
||||
{
|
||||
//[MC]Intentionally eliminate pointers. Overrides TRANSFERPOINTERS, but is overridden by SETMASTER/TARGET/TRACER.
|
||||
mo->LastHeard = NULL; //Sanity check.
|
||||
mo->target = NULL;
|
||||
mo->master = NULL;
|
||||
mo->tracer = NULL;
|
||||
}
|
||||
if (flags & SIXF_SETMASTER)
|
||||
{
|
||||
mo->master = originator;
|
||||
}
|
||||
if (flags & SIXF_SETTARGET)
|
||||
{
|
||||
mo->target = originator;
|
||||
}
|
||||
if (flags & SIXF_SETTRACER)
|
||||
{
|
||||
mo->tracer = originator;
|
||||
}
|
||||
if (flags & SIXF_TRANSFERSCALE)
|
||||
{
|
||||
mo->scaleX = self->scaleX;
|
||||
|
@ -2658,69 +2687,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIf)
|
|||
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_KillMaster
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillMaster)
|
||||
{
|
||||
ACTION_PARAM_START(1);
|
||||
ACTION_PARAM_NAME(damagetype, 0);
|
||||
|
||||
if (self->master != NULL)
|
||||
{
|
||||
P_DamageMobj(self->master, self, self, self->master->health, damagetype, DMG_NO_ARMOR | DMG_NO_FACTOR);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_KillChildren
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillChildren)
|
||||
{
|
||||
ACTION_PARAM_START(1);
|
||||
ACTION_PARAM_NAME(damagetype, 0);
|
||||
|
||||
TThinkerIterator<AActor> it;
|
||||
AActor *mo;
|
||||
|
||||
while ( (mo = it.Next()) )
|
||||
{
|
||||
if (mo->master == self)
|
||||
{
|
||||
P_DamageMobj(mo, self, self, mo->health, damagetype, DMG_NO_ARMOR | DMG_NO_FACTOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_KillSiblings
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillSiblings)
|
||||
{
|
||||
ACTION_PARAM_START(1);
|
||||
ACTION_PARAM_NAME(damagetype, 0);
|
||||
|
||||
TThinkerIterator<AActor> it;
|
||||
AActor *mo;
|
||||
|
||||
if (self->master != NULL)
|
||||
{
|
||||
while ( (mo = it.Next()) )
|
||||
{
|
||||
if (mo->master == self->master && mo != self)
|
||||
{
|
||||
P_DamageMobj(mo, self, self, mo->health, damagetype, DMG_NO_ARMOR | DMG_NO_FACTOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_CountdownArg
|
||||
|
@ -3315,18 +3281,19 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckLOF)
|
|||
|
||||
enum JLOS_flags
|
||||
{
|
||||
JLOSF_PROJECTILE=1,
|
||||
JLOSF_NOSIGHT=2,
|
||||
JLOSF_CLOSENOFOV=4,
|
||||
JLOSF_CLOSENOSIGHT=8,
|
||||
JLOSF_CLOSENOJUMP=16,
|
||||
JLOSF_DEADNOJUMP=32,
|
||||
JLOSF_CHECKMASTER=64,
|
||||
JLOSF_TARGETLOS=128,
|
||||
JLOSF_FLIPFOV=256,
|
||||
JLOSF_ALLYNOJUMP=512,
|
||||
JLOSF_COMBATANTONLY=1024,
|
||||
JLOSF_NOAUTOAIM=2048,
|
||||
JLOSF_PROJECTILE = 1,
|
||||
JLOSF_NOSIGHT = 1 << 1,
|
||||
JLOSF_CLOSENOFOV = 1 << 2,
|
||||
JLOSF_CLOSENOSIGHT = 1 << 3,
|
||||
JLOSF_CLOSENOJUMP = 1 << 4,
|
||||
JLOSF_DEADNOJUMP = 1 << 5,
|
||||
JLOSF_CHECKMASTER = 1 << 6,
|
||||
JLOSF_TARGETLOS = 1 << 7,
|
||||
JLOSF_FLIPFOV = 1 << 8,
|
||||
JLOSF_ALLYNOJUMP = 1 << 9,
|
||||
JLOSF_COMBATANTONLY = 1 << 10,
|
||||
JLOSF_NOAUTOAIM = 1 << 11,
|
||||
JLOSF_CHECKTRACER = 1 << 12,
|
||||
};
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
|
||||
|
@ -3351,9 +3318,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfTargetInLOS)
|
|||
{
|
||||
target = self->master;
|
||||
}
|
||||
else if (self->flags & MF_MISSILE && (flags & JLOSF_PROJECTILE))
|
||||
else if ((self->flags & MF_MISSILE && (flags & JLOSF_PROJECTILE)) || (flags & JLOSF_CHECKTRACER))
|
||||
{
|
||||
if (self->flags2 & MF2_SEEKERMISSILE)
|
||||
if ((self->flags2 & MF2_SEEKERMISSILE) || (flags & JLOSF_CHECKTRACER))
|
||||
target = self->tracer;
|
||||
else
|
||||
target = NULL;
|
||||
|
@ -3529,103 +3496,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfInTargetLOS)
|
|||
ACTION_JUMP(jump);
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_DamageMaster (int amount)
|
||||
// Damages the master of this child by the specified amount. Negative values heal.
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageMaster)
|
||||
{
|
||||
ACTION_PARAM_START(2);
|
||||
ACTION_PARAM_INT(amount, 0);
|
||||
ACTION_PARAM_NAME(DamageType, 1);
|
||||
|
||||
if (self->master != NULL)
|
||||
{
|
||||
if (amount > 0)
|
||||
{
|
||||
P_DamageMobj(self->master, self, self, amount, DamageType, DMG_NO_ARMOR);
|
||||
}
|
||||
else if (amount < 0)
|
||||
{
|
||||
amount = -amount;
|
||||
P_GiveBody(self->master, amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_DamageChildren (amount)
|
||||
// Damages the children of this master by the specified amount. Negative values heal.
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageChildren)
|
||||
{
|
||||
TThinkerIterator<AActor> it;
|
||||
AActor * mo;
|
||||
|
||||
ACTION_PARAM_START(2);
|
||||
ACTION_PARAM_INT(amount, 0);
|
||||
ACTION_PARAM_NAME(DamageType, 1);
|
||||
|
||||
while ( (mo = it.Next()) )
|
||||
{
|
||||
if (mo->master == self)
|
||||
{
|
||||
if (amount > 0)
|
||||
{
|
||||
P_DamageMobj(mo, self, self, amount, DamageType, DMG_NO_ARMOR);
|
||||
}
|
||||
else if (amount < 0)
|
||||
{
|
||||
amount = -amount;
|
||||
P_GiveBody(mo, amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// [KS] *** End of my modifications ***
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_DamageSiblings (amount)
|
||||
// Damages the siblings of this master by the specified amount. Negative values heal.
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSiblings)
|
||||
{
|
||||
TThinkerIterator<AActor> it;
|
||||
AActor * mo;
|
||||
|
||||
ACTION_PARAM_START(2);
|
||||
ACTION_PARAM_INT(amount, 0);
|
||||
ACTION_PARAM_NAME(DamageType, 1);
|
||||
|
||||
if (self->master != NULL)
|
||||
{
|
||||
while ( (mo = it.Next()) )
|
||||
{
|
||||
if (mo->master == self->master && mo != self)
|
||||
{
|
||||
if (amount > 0)
|
||||
{
|
||||
P_DamageMobj(mo, self, self, amount, DamageType, DMG_NO_ARMOR);
|
||||
}
|
||||
else if (amount < 0)
|
||||
{
|
||||
amount = -amount;
|
||||
P_GiveBody(mo, amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Modified code pointer from Skulltag
|
||||
|
@ -3805,65 +3675,6 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CheckFlag)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_RemoveMaster
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_RemoveMaster)
|
||||
{
|
||||
if (self->master != NULL)
|
||||
{
|
||||
P_RemoveThing(self->master);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_RemoveChildren
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveChildren)
|
||||
{
|
||||
TThinkerIterator<AActor> it;
|
||||
AActor *mo;
|
||||
ACTION_PARAM_START(1);
|
||||
ACTION_PARAM_BOOL(removeall,0);
|
||||
|
||||
while ((mo = it.Next()) != NULL)
|
||||
{
|
||||
if (mo->master == self && (mo->health <= 0 || removeall))
|
||||
{
|
||||
P_RemoveThing(mo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_RemoveSiblings
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveSiblings)
|
||||
{
|
||||
TThinkerIterator<AActor> it;
|
||||
AActor *mo;
|
||||
ACTION_PARAM_START(1);
|
||||
ACTION_PARAM_BOOL(removeall,0);
|
||||
|
||||
if (self->master != NULL)
|
||||
{
|
||||
while ((mo = it.Next()) != NULL)
|
||||
{
|
||||
if (mo->master == self->master && mo != self && (mo->health <= 0 || removeall))
|
||||
{
|
||||
P_RemoveThing(mo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_RaiseMaster
|
||||
|
@ -4521,7 +4332,8 @@ enum WARPF
|
|||
|
||||
WARPF_STOP = 0x80,
|
||||
WARPF_TOFLOOR = 0x100,
|
||||
WARPF_TESTONLY = 0x200
|
||||
WARPF_TESTONLY = 0x200,
|
||||
WARPF_ABSOLUTEPOSITION = 0x400,
|
||||
};
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp)
|
||||
|
@ -4554,10 +4366,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp)
|
|||
{
|
||||
angle += (flags & WARPF_USECALLERANGLE) ? self->angle : reference->angle;
|
||||
}
|
||||
|
||||
if (!(flags & WARPF_ABSOLUTEPOSITION))
|
||||
{
|
||||
if (!(flags & WARPF_ABSOLUTEOFFSET))
|
||||
{
|
||||
angle_t fineangle = angle>>ANGLETOFINESHIFT;
|
||||
angle_t fineangle = angle >> ANGLETOFINESHIFT;
|
||||
oldx = xofs;
|
||||
|
||||
// (borrowed from A_SpawnItemEx, assumed workable)
|
||||
|
@ -4608,6 +4421,18 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Warp)
|
|||
reference->y + yofs,
|
||||
reference->z + zofs);
|
||||
}
|
||||
}
|
||||
else //[MC] The idea behind "absolute" is meant to be "absolute". Override everything, just like A_SpawnItemEx's.
|
||||
{
|
||||
if (flags & WARPF_TOFLOOR)
|
||||
{
|
||||
self->SetOrigin(xofs, yofs, self->floorz + zofs);
|
||||
}
|
||||
else
|
||||
{
|
||||
self->SetOrigin(xofs, yofs, zofs);
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & WARPF_NOCHECKPOSITION) || P_TestMobjLocation(self))
|
||||
{
|
||||
|
@ -4980,3 +4805,451 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DropItem)
|
|||
|
||||
P_DropItem(self, spawntype, amount, chance);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// A_SetSpeed
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpeed)
|
||||
{
|
||||
ACTION_PARAM_START(1);
|
||||
ACTION_PARAM_FIXED(speed, 0);
|
||||
|
||||
self->Speed = speed;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Common A_Damage handler
|
||||
//
|
||||
// A_Damage* (int amount, str damagetype, int flags)
|
||||
// Damages the specified actor by the specified amount. Negative values heal.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
enum DMSS
|
||||
{
|
||||
DMSS_FOILINVUL = 1,
|
||||
DMSS_AFFECTARMOR = 2,
|
||||
DMSS_KILL = 4,
|
||||
DMSS_NOFACTOR = 8,
|
||||
};
|
||||
|
||||
static void DoDamage(AActor *dmgtarget, AActor *self, int amount, FName DamageType, int flags)
|
||||
{
|
||||
if ((amount > 0) || (flags & DMSS_KILL))
|
||||
{
|
||||
if (!(dmgtarget->flags2 & MF2_INVULNERABLE) || (flags & DMSS_FOILINVUL))
|
||||
{
|
||||
if (flags & DMSS_KILL)
|
||||
{
|
||||
P_DamageMobj(dmgtarget, self, self, dmgtarget->health, DamageType, DMG_NO_FACTOR | DMG_NO_ARMOR | DMG_FOILINVUL);
|
||||
}
|
||||
if (flags & DMSS_AFFECTARMOR)
|
||||
{
|
||||
if (flags & DMSS_NOFACTOR)
|
||||
{
|
||||
P_DamageMobj(dmgtarget, self, self, amount, DamageType, DMG_FOILINVUL | DMG_NO_FACTOR);
|
||||
}
|
||||
else
|
||||
{
|
||||
P_DamageMobj(dmgtarget, self, self, amount, DamageType, DMG_FOILINVUL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flags & DMSS_NOFACTOR)
|
||||
{
|
||||
P_DamageMobj(dmgtarget, self, self, amount, DamageType, DMG_FOILINVUL | DMG_NO_ARMOR | DMG_NO_FACTOR);
|
||||
}
|
||||
//[MC] DMG_FOILINVUL is needed for making the damage occur on the actor.
|
||||
else
|
||||
{
|
||||
P_DamageMobj(dmgtarget, self, self, amount, DamageType, DMG_FOILINVUL | DMG_NO_ARMOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (amount < 0)
|
||||
{
|
||||
amount = -amount;
|
||||
P_GiveBody(dmgtarget, amount);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSelf)
|
||||
{
|
||||
ACTION_PARAM_START(3);
|
||||
ACTION_PARAM_INT(amount, 0);
|
||||
ACTION_PARAM_NAME(DamageType, 1);
|
||||
ACTION_PARAM_INT(flags, 2);
|
||||
|
||||
DoDamage(self, self, amount, DamageType, flags);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTarget)
|
||||
{
|
||||
ACTION_PARAM_START(3);
|
||||
ACTION_PARAM_INT(amount, 0);
|
||||
ACTION_PARAM_NAME(DamageType, 1);
|
||||
ACTION_PARAM_INT(flags, 2);
|
||||
|
||||
if (self->target != NULL) DoDamage(self->target, self, amount, DamageType, flags);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageTracer)
|
||||
{
|
||||
ACTION_PARAM_START(3);
|
||||
ACTION_PARAM_INT(amount, 0);
|
||||
ACTION_PARAM_NAME(DamageType, 1);
|
||||
ACTION_PARAM_INT(flags, 2);
|
||||
|
||||
if (self->tracer != NULL) DoDamage(self->tracer, self, amount, DamageType, flags);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageMaster)
|
||||
{
|
||||
ACTION_PARAM_START(3);
|
||||
ACTION_PARAM_INT(amount, 0);
|
||||
ACTION_PARAM_NAME(DamageType, 1);
|
||||
ACTION_PARAM_INT(flags, 2);
|
||||
|
||||
if (self->master != NULL) DoDamage(self->master, self, amount, DamageType, flags);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageChildren)
|
||||
{
|
||||
ACTION_PARAM_START(3);
|
||||
ACTION_PARAM_INT(amount, 0);
|
||||
ACTION_PARAM_NAME(DamageType, 1);
|
||||
ACTION_PARAM_INT(flags, 2);
|
||||
|
||||
TThinkerIterator<AActor> it;
|
||||
AActor * mo;
|
||||
|
||||
while ( (mo = it.Next()) )
|
||||
{
|
||||
if (mo->master == self) DoDamage(mo, self, amount, DamageType, flags);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_DamageSiblings)
|
||||
{
|
||||
ACTION_PARAM_START(3);
|
||||
ACTION_PARAM_INT(amount, 0);
|
||||
ACTION_PARAM_NAME(DamageType, 1);
|
||||
ACTION_PARAM_INT(flags, 2);
|
||||
|
||||
TThinkerIterator<AActor> it;
|
||||
AActor * mo;
|
||||
|
||||
if (self->master != NULL)
|
||||
{
|
||||
while ((mo = it.Next()))
|
||||
{
|
||||
if (mo->master == self->master && mo != self) DoDamage(mo, self, amount, DamageType, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_Kill*(damagetype, int flags)
|
||||
//
|
||||
//===========================================================================
|
||||
enum KILS
|
||||
{
|
||||
KILS_FOILINVUL = 1 << 0,
|
||||
KILS_KILLMISSILES = 1 << 1,
|
||||
KILS_NOMONSTERS = 1 << 2,
|
||||
};
|
||||
|
||||
static void DoKill(AActor *killtarget, AActor *self, FName damagetype, int flags)
|
||||
{
|
||||
if ((killtarget->flags & MF_MISSILE) && (flags & KILS_KILLMISSILES))
|
||||
{
|
||||
//[MC] Now that missiles can set masters, lets put in a check to properly destroy projectiles. BUT FIRST! New feature~!
|
||||
//Check to see if it's invulnerable. Disregarded if foilinvul is on, but never works on a missile with NODAMAGE
|
||||
//since that's the whole point of it.
|
||||
if ((!(killtarget->flags2 & MF2_INVULNERABLE) || (flags & KILS_FOILINVUL)) && !(killtarget->flags5 & MF5_NODAMAGE))
|
||||
{
|
||||
P_ExplodeMissile(killtarget, NULL, NULL);
|
||||
}
|
||||
}
|
||||
if (!(flags & KILS_NOMONSTERS))
|
||||
{
|
||||
if (flags & KILS_FOILINVUL)
|
||||
{
|
||||
P_DamageMobj(killtarget, self, self, killtarget->health, damagetype, DMG_NO_ARMOR | DMG_NO_FACTOR | DMG_FOILINVUL);
|
||||
}
|
||||
else
|
||||
{
|
||||
P_DamageMobj(killtarget, self, self, killtarget->health, damagetype, DMG_NO_ARMOR | DMG_NO_FACTOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_KillTarget(damagetype, int flags)
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTarget)
|
||||
{
|
||||
ACTION_PARAM_START(2);
|
||||
ACTION_PARAM_NAME(damagetype, 0);
|
||||
ACTION_PARAM_INT(flags, 1);
|
||||
|
||||
if (self->target != NULL) DoKill(self->target, self, damagetype, flags);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_KillTracer(damagetype, int flags)
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillTracer)
|
||||
{
|
||||
ACTION_PARAM_START(2);
|
||||
ACTION_PARAM_NAME(damagetype, 0);
|
||||
ACTION_PARAM_INT(flags, 1);
|
||||
|
||||
if (self->tracer != NULL) DoKill(self->tracer, self, damagetype, flags);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_KillMaster(damagetype, int flags)
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillMaster)
|
||||
{
|
||||
ACTION_PARAM_START(2);
|
||||
ACTION_PARAM_NAME(damagetype, 0);
|
||||
ACTION_PARAM_INT(flags, 1);
|
||||
|
||||
if (self->master != NULL) DoKill(self->master, self, damagetype, flags);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_KillChildren(damagetype, int flags)
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillChildren)
|
||||
{
|
||||
ACTION_PARAM_START(2);
|
||||
ACTION_PARAM_NAME(damagetype, 0);
|
||||
ACTION_PARAM_INT(flags, 1);
|
||||
|
||||
TThinkerIterator<AActor> it;
|
||||
AActor *mo;
|
||||
|
||||
while ( (mo = it.Next()) )
|
||||
{
|
||||
if (mo->master == self) DoKill(mo, self, damagetype, flags);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_KillSiblings(damagetype, int flags)
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_KillSiblings)
|
||||
{
|
||||
ACTION_PARAM_START(2);
|
||||
ACTION_PARAM_NAME(damagetype, 0);
|
||||
ACTION_PARAM_INT(flags, 1);
|
||||
|
||||
TThinkerIterator<AActor> it;
|
||||
AActor *mo;
|
||||
|
||||
if (self->master != NULL)
|
||||
{
|
||||
while ( (mo = it.Next()) )
|
||||
{
|
||||
if (mo->master == self->master && mo != self) DoKill(mo, self, damagetype, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// DoRemove
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
enum RMVF_flags
|
||||
{
|
||||
RMVF_MISSILES = 1 << 0,
|
||||
RMVF_NOMONSTERS = 1 << 1,
|
||||
RMVF_MISC = 1 << 2,
|
||||
RMVF_EVERYTHING = 1 << 3,
|
||||
};
|
||||
|
||||
static void DoRemove(AActor *removetarget, int flags)
|
||||
{
|
||||
if ((flags & RMVF_EVERYTHING))
|
||||
{
|
||||
P_RemoveThing(removetarget);
|
||||
}
|
||||
if ((flags & RMVF_MISC) && !((removetarget->flags3 & MF3_ISMONSTER) && (removetarget->flags & MF_MISSILE)))
|
||||
{
|
||||
P_RemoveThing(removetarget);
|
||||
}
|
||||
if ((removetarget->flags3 & MF3_ISMONSTER) && !(flags & RMVF_NOMONSTERS))
|
||||
{
|
||||
P_RemoveThing(removetarget);
|
||||
}
|
||||
if ((removetarget->flags & MF_MISSILE) && (flags & RMVF_MISSILES))
|
||||
{
|
||||
P_RemoveThing(removetarget);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_RemoveTarget
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTarget)
|
||||
{
|
||||
ACTION_PARAM_START(1);
|
||||
ACTION_PARAM_INT(flags, 0);
|
||||
if (self->master != NULL)
|
||||
{
|
||||
DoRemove(self->target, flags);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_RemoveTracer
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveTracer)
|
||||
{
|
||||
ACTION_PARAM_START(1);
|
||||
ACTION_PARAM_INT(flags, 0);
|
||||
if (self->master != NULL)
|
||||
{
|
||||
DoRemove(self->tracer, flags);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_RemoveMaster
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveMaster)
|
||||
{
|
||||
ACTION_PARAM_START(1);
|
||||
ACTION_PARAM_INT(flags, 0);
|
||||
if (self->master != NULL)
|
||||
{
|
||||
DoRemove(self->master, flags);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_RemoveChildren
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveChildren)
|
||||
{
|
||||
TThinkerIterator<AActor> it;
|
||||
AActor *mo;
|
||||
ACTION_PARAM_START(2);
|
||||
ACTION_PARAM_BOOL(removeall, 0);
|
||||
ACTION_PARAM_INT(flags, 1);
|
||||
|
||||
while ((mo = it.Next()) != NULL)
|
||||
{
|
||||
if (mo->master == self && (mo->health <= 0 || removeall))
|
||||
{
|
||||
DoRemove(mo, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_RemoveSiblings
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_RemoveSiblings)
|
||||
{
|
||||
TThinkerIterator<AActor> it;
|
||||
AActor *mo;
|
||||
ACTION_PARAM_START(2);
|
||||
ACTION_PARAM_BOOL(removeall, 0);
|
||||
ACTION_PARAM_INT(flags, 1);
|
||||
|
||||
if (self->master != NULL)
|
||||
{
|
||||
while ((mo = it.Next()) != NULL)
|
||||
{
|
||||
if (mo->master == self->master && mo != self && (mo->health <= 0 || removeall))
|
||||
{
|
||||
DoRemove(mo, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_Remove
|
||||
//
|
||||
//===========================================================================
|
||||
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Remove)
|
||||
{
|
||||
ACTION_PARAM_START(2);
|
||||
ACTION_PARAM_INT(removee, 0);
|
||||
ACTION_PARAM_INT(flags, 1);
|
||||
|
||||
AActor *reference = COPY_AAPTR(self, removee);
|
||||
|
||||
if (reference != NULL)
|
||||
{
|
||||
DoRemove(reference, flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -88,6 +88,7 @@ DEFINE_MEMBER_VARIABLE(height, AActor)
|
|||
DEFINE_MEMBER_VARIABLE(radius, AActor)
|
||||
DEFINE_MEMBER_VARIABLE(reactiontime, AActor)
|
||||
DEFINE_MEMBER_VARIABLE(meleerange, AActor)
|
||||
DEFINE_MEMBER_VARIABLE(Speed, AActor)
|
||||
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
#include "tarray.h"
|
||||
#include "thingdef.h"
|
||||
#include "thingdef_exp.h"
|
||||
#include "actor.h"
|
||||
#include "actorptrselect.h"
|
||||
|
||||
static TMap<FName, FxGlobalFunctionCall::Creator> CreatorMap;
|
||||
|
||||
|
@ -185,3 +187,110 @@ public:
|
|||
|
||||
GLOBALFUNCTION_ADDER(Sqrt);
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Function: checkclass
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxGlobalFunctionCall_CheckClass : public FxGlobalFunctionCall
|
||||
{
|
||||
public:
|
||||
GLOBALFUNCTION_DEFINE(CheckClass);
|
||||
|
||||
FxExpression *Resolve(FCompileContext& ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
|
||||
if (!ResolveArgs(ctx, 1, 3, false))
|
||||
return NULL;
|
||||
|
||||
for (int i = ArgList->Size(); i > 1;)
|
||||
{
|
||||
if (!(*ArgList)[--i]->ValueType.isNumeric())
|
||||
{
|
||||
ScriptPosition.Message(MSG_ERROR, "numeric value expected for parameter");
|
||||
delete this;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
switch ((*ArgList)[0]->ValueType.Type)
|
||||
{
|
||||
case VAL_Class: case VAL_Name:break;
|
||||
default:
|
||||
ScriptPosition.Message(MSG_ERROR, "actor class expected for parameter");
|
||||
delete this;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ValueType = VAL_Float;
|
||||
return this;
|
||||
}
|
||||
|
||||
ExpVal EvalExpression(AActor *self)
|
||||
{
|
||||
ExpVal ret;
|
||||
ret.Type = VAL_Int;
|
||||
|
||||
const PClass * checkclass;
|
||||
{
|
||||
ExpVal v = (*ArgList)[0]->EvalExpression(self);
|
||||
checkclass = v.GetClass();
|
||||
if (!checkclass)
|
||||
{
|
||||
checkclass = PClass::FindClass(v.GetName());
|
||||
if (!checkclass) { ret.Int = 0; return ret; }
|
||||
}
|
||||
}
|
||||
|
||||
bool match_superclass = false;
|
||||
int pick_pointer = AAPTR_DEFAULT;
|
||||
|
||||
switch (ArgList->Size())
|
||||
{
|
||||
case 3: match_superclass = (*ArgList)[2]->EvalExpression(self).GetBool();
|
||||
case 2: pick_pointer = (*ArgList)[1]->EvalExpression(self).GetInt();
|
||||
}
|
||||
|
||||
self = COPY_AAPTR(self, pick_pointer);
|
||||
if (!self){ ret.Int = 0; return ret; }
|
||||
ret.Int = match_superclass ? checkclass->IsAncestorOf(self->GetClass()) : checkclass == self->GetClass();
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
GLOBALFUNCTION_ADDER(CheckClass);
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Function: ispointerequal
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxGlobalFunctionCall_IsPointerEqual : public FxGlobalFunctionCall
|
||||
{
|
||||
public:
|
||||
GLOBALFUNCTION_DEFINE(IsPointerEqual);
|
||||
|
||||
FxExpression *Resolve(FCompileContext& ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
|
||||
if (!ResolveArgs(ctx, 2, 2, true))
|
||||
return NULL;
|
||||
|
||||
ValueType = VAL_Int;
|
||||
return this;
|
||||
}
|
||||
|
||||
ExpVal EvalExpression(AActor *self)
|
||||
{
|
||||
ExpVal ret;
|
||||
ret.Type = VAL_Int;
|
||||
ret.Int = COPY_AAPTR(self, (*ArgList)[0]->EvalExpression(self).GetInt()) == COPY_AAPTR(self, (*ArgList)[1]->EvalExpression(self).GetInt());
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
GLOBALFUNCTION_ADDER(IsPointerEqual);
|
|
@ -374,6 +374,8 @@ static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClass *cls)
|
|||
FScriptPosition::ErrorCounter++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
FName symname = sc.String;
|
||||
if (sc.CheckToken('['))
|
||||
{
|
||||
|
@ -391,6 +393,15 @@ static void ParseUserVariable (FScanner &sc, PSymbolTable *symt, PClass *cls)
|
|||
}
|
||||
sc.MustGetToken(';');
|
||||
|
||||
// We must ensure that we do not define duplicates, even when they come from a parent table.
|
||||
if (symt->FindSymbol(symname, true) != NULL)
|
||||
{
|
||||
sc.ScriptMessage ("'%s' is already defined in '%s' or one of its ancestors.",
|
||||
symname.GetChars(), cls ? cls->TypeName.GetChars() : "Global");
|
||||
FScriptPosition::ErrorCounter++;
|
||||
return;
|
||||
}
|
||||
|
||||
PSymbolVariable *sym = new PSymbolVariable(symname);
|
||||
sym->offset = cls->Extend(sizeof(int) * (valuetype.Type == VAL_Array ? valuetype.size : 1));
|
||||
sym->ValueType = valuetype;
|
||||
|
|
|
@ -51,7 +51,7 @@ const char *GetVersionString();
|
|||
// Version identifier for network games.
|
||||
// Bump it every time you do a release unless you're certain you
|
||||
// didn't change anything that will affect sync.
|
||||
#define NETGAMEVERSION 230
|
||||
#define NETGAMEVERSION 231
|
||||
|
||||
// Version stored in the ini's [LastRun] section.
|
||||
// Bump it if you made some configuration change that you want to
|
||||
|
|
|
@ -62,6 +62,7 @@ ACTOR Actor native //: Thinker
|
|||
native fixed_t radius;
|
||||
native int reactiontime;
|
||||
native fixed_t meleerange;
|
||||
native fixed_t speed;
|
||||
|
||||
// Meh, MBF redundant functions. Only for DeHackEd support.
|
||||
action native A_Turn(float angle = 0);
|
||||
|
@ -69,7 +70,7 @@ ACTOR Actor native //: Thinker
|
|||
// End of MBF redundant functions.
|
||||
|
||||
action native A_MonsterRail();
|
||||
action native A_BFGSpray(class<Actor> spraytype = "BFGExtra", int numrays = 40, int damagecount = 15);
|
||||
action native A_BFGSpray(class<Actor> spraytype = "BFGExtra", int numrays = 40, int damagecount = 15, float angle = 90, float distance = 16*64, float vrange = 32, int damage = 0);
|
||||
action native A_Pain();
|
||||
action native A_NoBlocking();
|
||||
action native A_XScream();
|
||||
|
@ -203,7 +204,7 @@ ACTOR Actor native //: Thinker
|
|||
action native A_CustomMissile(class<Actor> missiletype, float spawnheight = 32, int spawnofs_xy = 0, float angle = 0, int flags = 0, float pitch = 0);
|
||||
action native A_CustomBulletAttack(float spread_xy, float spread_z, int numbullets, int damageperbullet, class<Actor> pufftype = "BulletPuff", float range = 0, int flags = 0);
|
||||
action native A_CustomRailgun(int damage, int spawnofs_xy = 0, color color1 = "", color color2 = "", int flags = 0, bool aim = false, float maxdiff = 0, class<Actor> pufftype = "BulletPuff", float spread_xy = 0, float spread_z = 0, float range = 0, int duration = 0, float sparsity = 1.0, float driftspeed = 1.0, class<Actor> spawnclass = "none", float spawnofs_z = 0);
|
||||
action native A_JumpIfHealthLower(int health, state label);
|
||||
action native A_JumpIfHealthLower(int health, state label, int ptr_selector = AAPTR_DEFAULT);
|
||||
action native A_JumpIfCloser(float distance, state label);
|
||||
action native A_JumpIfTracerCloser(float distance, state label);
|
||||
action native A_JumpIfMasterCloser(float distance, state label);
|
||||
|
@ -233,12 +234,12 @@ ACTOR Actor native //: Thinker
|
|||
action native A_ChangeFlag(string flagname, bool value);
|
||||
action native A_CheckFlag(string flagname, state label, int check_pointer = AAPTR_DEFAULT);
|
||||
action native A_JumpIf(bool expression, state label);
|
||||
action native A_RemoveMaster();
|
||||
action native A_RemoveChildren(bool removeall = false);
|
||||
action native A_RemoveSiblings(bool removeall = false);
|
||||
action native A_KillMaster(name damagetype = "none");
|
||||
action native A_KillChildren(name damagetype = "none");
|
||||
action native A_KillSiblings(name damagetype = "none");
|
||||
action native A_RemoveMaster(int flags = 0);
|
||||
action native A_RemoveChildren(bool removeall = false, int flags = 0);
|
||||
action native A_RemoveSiblings(bool removeall = false, int flags = 0);
|
||||
action native A_KillMaster(name damagetype = "none", int flags = 0);
|
||||
action native A_KillChildren(name damagetype = "none", int flags = 0);
|
||||
action native A_KillSiblings(name damagetype = "none", int flags = 0);
|
||||
action native A_RaiseMaster();
|
||||
action native A_RaiseChildren();
|
||||
action native A_RaiseSiblings();
|
||||
|
@ -274,9 +275,9 @@ ACTOR Actor native //: Thinker
|
|||
action native A_CheckLOF(state jump, int flags = 0, float range = 0, float minrange = 0, float angle = 0, float pitch = 0, float offsetheight = 0, float offsetwidth = 0, int ptr_target = AAPTR_DEFAULT);
|
||||
action native A_JumpIfTargetInLOS (state label, float fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0);
|
||||
action native A_JumpIfInTargetLOS (state label, float fov = 0, int flags = 0, float dist_max = 0, float dist_close = 0);
|
||||
action native A_DamageMaster(int amount, name damagetype = "none");
|
||||
action native A_DamageChildren(int amount, name damagetype = "none");
|
||||
action native A_DamageSiblings(int amount, name damagetype = "none");
|
||||
action native A_DamageMaster(int amount, name damagetype = "none", int flags = 0);
|
||||
action native A_DamageChildren(int amount, name damagetype = "none", int flags = 0);
|
||||
action native A_DamageSiblings(int amount, name damagetype = "none", int flags = 0);
|
||||
action native A_SelectWeapon(class<Weapon> whichweapon);
|
||||
action native A_Punch();
|
||||
action native A_Feathers();
|
||||
|
@ -302,6 +303,15 @@ ACTOR Actor native //: Thinker
|
|||
action native A_SetTics(int tics);
|
||||
action native A_SetDamageType(name damagetype);
|
||||
action native A_DropItem(class<Actor> item, int dropamount = -1, int chance = 256);
|
||||
action native A_SetSpeed(float speed);
|
||||
action native A_DamageSelf(int amount, name damagetype = "none", int flags = 0);
|
||||
action native A_DamageTarget(int amount, name damagetype = "none", int flags = 0);
|
||||
action native A_DamageTracer(int amount, name damagetype = "none", int flags = 0);
|
||||
action native A_KillTarget(name damagetype = "none", int flags = 0);
|
||||
action native A_KillTracer(name damagetype = "none", int flags = 0);
|
||||
action native A_RemoveTarget(int flags = 0);
|
||||
action native A_RemoveTracer(int flags = 0);
|
||||
action native A_Remove(int removee, int flags = 0);
|
||||
|
||||
action native A_CheckSightOrRange(float distance, state label);
|
||||
action native A_CheckRange(float distance, state label);
|
||||
|
|
|
@ -46,27 +46,31 @@ const int FBF_NOFLASH = 16;
|
|||
const int FBF_NORANDOMPUFFZ = 32;
|
||||
|
||||
// Flags for A_SpawnItemEx
|
||||
const int SXF_TRANSFERTRANSLATION = 1;
|
||||
const int SXF_ABSOLUTEPOSITION = 2;
|
||||
const int SXF_ABSOLUTEANGLE = 4;
|
||||
const int SXF_ABSOLUTEMOMENTUM = 8;
|
||||
const int SXF_ABSOLUTEVELOCITY = 8;
|
||||
const int SXF_SETMASTER = 16;
|
||||
const int SXF_NOCHECKPOSITION = 32;
|
||||
const int SXF_TELEFRAG = 64;
|
||||
const int SXF_CLIENTSIDE = 128; // only used by Skulltag
|
||||
const int SXF_TRANSFERAMBUSHFLAG = 256;
|
||||
const int SXF_TRANSFERPITCH = 512;
|
||||
const int SXF_TRANSFERPOINTERS = 1024;
|
||||
const int SXF_USEBLOODCOLOR = 2048;
|
||||
const int SXF_CLEARCALLERTID = 4096;
|
||||
const int SXF_MULTIPLYSPEED = 8192;
|
||||
const int SXF_TRANSFERSCALE = 16384;
|
||||
const int SXF_TRANSFERSPECIAL = 32768;
|
||||
const int SXF_CLEARCALLERSPECIAL = 65536;
|
||||
const int SXF_TRANSFERSTENCILCOL = 131072;
|
||||
const int SXF_TRANSFERALPHA = 262144;
|
||||
const int SXF_TRANSFERRENDERSTYLE = 524288;
|
||||
const int SXF_TRANSFERTRANSLATION = 1 << 0;
|
||||
const int SXF_ABSOLUTEPOSITION = 1 << 1;
|
||||
const int SXF_ABSOLUTEANGLE = 1 << 2;
|
||||
const int SXF_ABSOLUTEMOMENTUM = 1 << 3; //Since "momentum" is declared to be deprecated in the expressions, for compatibility
|
||||
const int SXF_ABSOLUTEVELOCITY = 1 << 3; //purposes, this was made. It does the same thing though. Do not change the value.
|
||||
const int SXF_SETMASTER = 1 << 4;
|
||||
const int SXF_NOCHECKPOSITION = 1 << 5;
|
||||
const int SXF_TELEFRAG = 1 << 6;
|
||||
const int SXF_CLIENTSIDE = 1 << 7; // only used by Skulltag
|
||||
const int SXF_TRANSFERAMBUSHFLAG = 1 << 8;
|
||||
const int SXF_TRANSFERPITCH = 1 << 9;
|
||||
const int SXF_TRANSFERPOINTERS = 1 << 10;
|
||||
const int SXF_USEBLOODCOLOR = 1 << 11;
|
||||
const int SXF_CLEARCALLERTID = 1 << 12;
|
||||
const int SXF_MULTIPLYSPEED = 1 << 13;
|
||||
const int SXF_TRANSFERSCALE = 1 << 14;
|
||||
const int SXF_TRANSFERSPECIAL = 1 << 15;
|
||||
const int SXF_CLEARCALLERSPECIAL = 1 << 16;
|
||||
const int SXF_TRANSFERSTENCILCOL = 1 << 17;
|
||||
const int SXF_TRANSFERALPHA = 1 << 18;
|
||||
const int SXF_TRANSFERRENDERSTYLE = 1 << 19;
|
||||
const int SXF_SETTARGET = 1 << 20;
|
||||
const int SXF_SETTRACER = 1 << 21;
|
||||
const int SXF_NOPOINTERS = 1 << 22;
|
||||
const int SXF_ORIGINATOR = 1 << 23;
|
||||
|
||||
// Flags for A_Chase
|
||||
const int CHF_FASTCHASE = 1;
|
||||
|
@ -89,18 +93,22 @@ const int RSF_KEEPTARGET = 2;
|
|||
const int RSF_TELEFRAG = 4;
|
||||
|
||||
// Flags for A_JumpIfTargetInLOS and A_JumpIfInTargetLOS
|
||||
const int JLOSF_PROJECTILE = 1;
|
||||
const int JLOSF_NOSIGHT = 2;
|
||||
const int JLOSF_CLOSENOFOV = 4;
|
||||
const int JLOSF_CLOSENOSIGHT = 8;
|
||||
const int JLOSF_CLOSENOJUMP = 16;
|
||||
const int JLOSF_DEADNOJUMP = 32;
|
||||
const int JLOSF_CHECKMASTER = 64;
|
||||
const int JLOSF_TARGETLOS = 128;
|
||||
const int JLOSF_FLIPFOV = 256;
|
||||
const int JLOSF_ALLYNOJUMP = 512;
|
||||
const int JLOSF_COMBATANTONLY = 1024;
|
||||
const int JLOSF_NOAUTOAIM = 2048;
|
||||
enum
|
||||
{
|
||||
JLOSF_PROJECTILE = 1,
|
||||
JLOSF_NOSIGHT = 1 << 1,
|
||||
JLOSF_CLOSENOFOV = 1 << 2,
|
||||
JLOSF_CLOSENOSIGHT = 1 << 3,
|
||||
JLOSF_CLOSENOJUMP = 1 << 4,
|
||||
JLOSF_DEADNOJUMP = 1 << 5,
|
||||
JLOSF_CHECKMASTER = 1 << 6,
|
||||
JLOSF_TARGETLOS = 1 << 7,
|
||||
JLOSF_FLIPFOV = 1 << 8,
|
||||
JLOSF_ALLYNOJUMP = 1 << 9,
|
||||
JLOSF_COMBATANTONLY = 1 << 10,
|
||||
JLOSF_NOAUTOAIM = 1 << 11,
|
||||
JLOSF_CHECKTRACER = 1 << 12,
|
||||
};
|
||||
|
||||
// Flags for A_ChangeVelocity
|
||||
const int CVF_RELATIVE = 1;
|
||||
|
@ -276,24 +284,25 @@ Const Int BLOCKF_USE = 128;
|
|||
// Pointer constants, bitfield-enabled
|
||||
|
||||
Const Int AAPTR_DEFAULT = 0;
|
||||
Const Int AAPTR_NULL = 1;
|
||||
Const Int AAPTR_TARGET = 2;
|
||||
Const Int AAPTR_MASTER = 4;
|
||||
Const Int AAPTR_TRACER = 8;
|
||||
Const Int AAPTR_NULL = 0x1;
|
||||
Const Int AAPTR_TARGET = 0x2;
|
||||
Const Int AAPTR_MASTER = 0x4;
|
||||
Const Int AAPTR_TRACER = 0x8;
|
||||
|
||||
Const Int AAPTR_PLAYER_GETTARGET = 16;
|
||||
Const Int AAPTR_PLAYER_GETCONVERSATION = 32;
|
||||
Const Int AAPTR_PLAYER_GETTARGET = 0x10;
|
||||
Const Int AAPTR_PLAYER_GETCONVERSATION = 0x20;
|
||||
|
||||
Const Int AAPTR_PLAYER1 = 64;
|
||||
Const Int AAPTR_PLAYER2 = 128;
|
||||
Const Int AAPTR_PLAYER3 = 256;
|
||||
Const Int AAPTR_PLAYER4 = 512;
|
||||
Const Int AAPTR_PLAYER5 = 1024;
|
||||
Const Int AAPTR_PLAYER6 = 2048;
|
||||
Const Int AAPTR_PLAYER7 = 4096;
|
||||
Const Int AAPTR_PLAYER8 = 8192;
|
||||
Const Int AAPTR_PLAYER1 = 0x40;
|
||||
Const Int AAPTR_PLAYER2 = 0x80;
|
||||
Const Int AAPTR_PLAYER3 = 0x100;
|
||||
Const Int AAPTR_PLAYER4 = 0x200;
|
||||
Const Int AAPTR_PLAYER5 = 0x400;
|
||||
Const Int AAPTR_PLAYER6 = 0x800;
|
||||
Const Int AAPTR_PLAYER7 = 0x1000;
|
||||
Const Int AAPTR_PLAYER8 = 0x2000;
|
||||
|
||||
Const Int AAPTR_FRIENDPLAYER = 16384;
|
||||
Const Int AAPTR_FRIENDPLAYER = 0x4000;
|
||||
Const Int AAPTR_LINETARGET = 0x8000;
|
||||
|
||||
// Pointer operation flags
|
||||
|
||||
|
@ -314,6 +323,7 @@ Const Int WARPF_COPYINTERPOLATION = 0x40;
|
|||
Const Int WARPF_STOP = 0x80;
|
||||
Const Int WARPF_TOFLOOR = 0x100;
|
||||
Const Int WARPF_TESTONLY = 0x200;
|
||||
Const Int WAPRF_ABSOLUTEPOSITION = 0x400;
|
||||
|
||||
// flags for A_SetPitch/SetAngle
|
||||
const int SPF_FORCECLAMP = 1;
|
||||
|
@ -360,12 +370,32 @@ enum
|
|||
CLOFF_NOAIM = CLOFF_NOAIM_VERT|CLOFF_NOAIM_HORZ
|
||||
};
|
||||
|
||||
// Flags for A_Kill (Master/Target/Tracer/Children/Siblings) series
|
||||
|
||||
const int KILS_FOILINVUL = 1;
|
||||
const int KILS_KILLMISSILES = 2;
|
||||
const int KILS_NOMONSTERS = 4;
|
||||
|
||||
// Flags for A_Damage (Master/Target/Tracer/Children/Siblings/Self) series
|
||||
const int DMSS_FOILINVUL = 1;
|
||||
const int DMSS_AFFECTARMOR = 2;
|
||||
const int DMSS_KILL = 4;
|
||||
const int DMSS_NOFACTOR = 8;
|
||||
|
||||
// Flags for A_AlertMonsters
|
||||
const int AMF_TARGETEMITTER = 1;
|
||||
const int AMF_TARGETNONPLAYER = 2;
|
||||
const int AMF_EMITFROMTARGET = 4;
|
||||
|
||||
// Flags for A_Remove*
|
||||
enum
|
||||
{
|
||||
RMVF_MISSILES = 1 << 0,
|
||||
RMVF_NOMONSTERS = 1 << 1,
|
||||
RMVF_MISC = 1 << 2,
|
||||
RMVF_EVERYTHING = 1 << 3,
|
||||
};
|
||||
|
||||
|
||||
// This is only here to provide one global variable for testing.
|
||||
native int testglobalvar;
|
||||
|
|
|
@ -836,6 +836,7 @@ SCORE_BONUS = "BONUS";
|
|||
SCORE_COLOR = "COLOR";
|
||||
SCORE_SECRET = "SECRET";
|
||||
SCORE_NAME = "NAME";
|
||||
SCORE_DELAY = "DELAY(ms)";
|
||||
SCORE_KILLS = "KILLS";
|
||||
SCORE_FRAGS = "FRAGS";
|
||||
SCORE_DEATHS = "DEATHS";
|
||||
|
|
|
@ -341,6 +341,7 @@ OptionMenu "OptionsMenu"
|
|||
Submenu "Automap Options", "AutomapOptions"
|
||||
Submenu "HUD Options", "HUDOptions"
|
||||
Submenu "Miscellaneous Options", "MiscOptions"
|
||||
Submenu "Network Options", "NetworkOptions"
|
||||
Submenu "Sound Options", "SoundOptions"
|
||||
Submenu "Display Options", "VideoOptions"
|
||||
Submenu "Set video mode", "VideoModeMenu"
|
||||
|
@ -457,6 +458,7 @@ OptionMenu "CustomizeControls"
|
|||
Control "Run", "+speed"
|
||||
Control "Strafe", "+strafe"
|
||||
Control "Show Scoreboard", "+showscores"
|
||||
Control "Toggle Scoreboard", "togglescoreboard"
|
||||
StaticText ""
|
||||
StaticText "Chat", 1
|
||||
Control "Say", "messagemode"
|
||||
|
@ -805,6 +807,13 @@ OptionValue "AltHUDTime"
|
|||
9, "System"
|
||||
}
|
||||
|
||||
OptionValue "AltHUDLag"
|
||||
{
|
||||
0, "Off"
|
||||
1, "Netgames only"
|
||||
2, "Always"
|
||||
}
|
||||
|
||||
OptionMenu "AltHUDOptions"
|
||||
{
|
||||
Title "Alternative HUD"
|
||||
|
@ -819,6 +828,7 @@ OptionMenu "AltHUDOptions"
|
|||
Option "Show weapons", "hud_showweapons", "OnOff"
|
||||
Option "Show time", "hud_showtime", "AltHUDTime"
|
||||
Option "Time color", "hud_timecolor", "TextColors"
|
||||
Option "Show network latency", "hud_showlag", "AltHUDLag"
|
||||
Slider "Red ammo display below %", "hud_ammo_red", 0, 100, 1, 0
|
||||
Slider "Yellow ammo display below %", "hud_ammo_yellow", 0, 100, 1, 0
|
||||
Slider "Red health display below", "hud_health_red", 0, 100, 1, 0
|
||||
|
@ -1591,3 +1601,28 @@ OptionMenu VideoModeMenu
|
|||
class VideoModeMenu
|
||||
}
|
||||
|
||||
/*=======================================
|
||||
*
|
||||
* Network options menu
|
||||
*
|
||||
*=======================================*/
|
||||
|
||||
OptionMenu NetworkOptions
|
||||
{
|
||||
Title "NETWORK OPTIONS"
|
||||
StaticText "Local options", 1
|
||||
Option "Movement prediction", "cl_noprediction", "OffOn"
|
||||
Option "Predict line actions", "cl_predict_specials", "OnOff"
|
||||
StaticText " "
|
||||
StaticText "Host options", 1
|
||||
Option "Extra Tics", "net_extratic", "ExtraTicMode"
|
||||
Option "Latency balancing", "net_ticbalance", "OnOff"
|
||||
|
||||
}
|
||||
|
||||
OptionValue ExtraTicMode
|
||||
{
|
||||
0, "None"
|
||||
1, "1"
|
||||
2, "All unacknowledged"
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue