mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-24 13:21:20 +00:00
Merge commit 'd624ee25' into udmf-thing-types
# Conflicts: # src/p_mobj.c # src/p_spec.c
This commit is contained in:
commit
39b7fb9ff8
32 changed files with 735 additions and 677 deletions
|
@ -4105,16 +4105,16 @@ thingtypes
|
|||
{
|
||||
title = "Egg Mobile";
|
||||
sprite = "EGGMA1";
|
||||
width = 24;
|
||||
height = 76;
|
||||
width = 36;
|
||||
height = 84;
|
||||
flags4text = "[4] End level on death";
|
||||
}
|
||||
201
|
||||
{
|
||||
title = "Egg Slimer";
|
||||
sprite = "EGGNA1";
|
||||
width = 24;
|
||||
height = 76;
|
||||
width = 36;
|
||||
height = 84;
|
||||
flags4text = "[4] End level on death";
|
||||
flags8text = "[8] Speed up when hit";
|
||||
}
|
||||
|
@ -4122,7 +4122,7 @@ thingtypes
|
|||
{
|
||||
title = "Sea Egg";
|
||||
sprite = "EGGOA1";
|
||||
width = 32;
|
||||
width = 36;
|
||||
height = 116;
|
||||
flags4text = "[4] End level on death";
|
||||
}
|
||||
|
@ -4130,8 +4130,8 @@ thingtypes
|
|||
{
|
||||
title = "Egg Colosseum";
|
||||
sprite = "EGGPA1";
|
||||
width = 24;
|
||||
height = 76;
|
||||
width = 36;
|
||||
height = 84;
|
||||
flags4text = "[4] End level on death";
|
||||
}
|
||||
204
|
||||
|
|
60
src/b_bot.c
60
src/b_bot.c
|
@ -17,6 +17,7 @@
|
|||
#include "p_local.h"
|
||||
#include "b_bot.h"
|
||||
#include "lua_hook.h"
|
||||
#include "i_system.h" // I_BaseTiccmd
|
||||
|
||||
void B_UpdateBotleader(player_t *player)
|
||||
{
|
||||
|
@ -132,17 +133,17 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
// Update catchup_tics
|
||||
if (mem->thinkstate == AI_SPINFOLLOW)
|
||||
{
|
||||
mem-> catchup_tics = 0;
|
||||
mem->catchup_tics = 0;
|
||||
}
|
||||
else if (dist > followmax || zdist > comfortheight || stalled)
|
||||
{
|
||||
mem-> catchup_tics = min(mem-> catchup_tics + 2, 70);
|
||||
if (mem-> catchup_tics >= 70)
|
||||
mem->catchup_tics = min(mem->catchup_tics + 2, 70);
|
||||
if (mem->catchup_tics >= 70)
|
||||
mem->thinkstate = AI_CATCHUP;
|
||||
}
|
||||
else
|
||||
{
|
||||
mem-> catchup_tics = max(mem-> catchup_tics - 1, 0);
|
||||
mem->catchup_tics = max(mem->catchup_tics - 1, 0);
|
||||
if (mem->thinkstate == AI_CATCHUP)
|
||||
mem->thinkstate = AI_FOLLOW;
|
||||
}
|
||||
|
@ -317,7 +318,6 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
{
|
||||
// Copy inputs
|
||||
cmd->angleturn = (sonic->angle) >> 16; // NOT FRACBITS DAMNIT
|
||||
bot->drawangle = ang;
|
||||
cmd->forwardmove = 8 * pcmd->forwardmove / 10;
|
||||
cmd->sidemove = 8 * pcmd->sidemove / 10;
|
||||
}
|
||||
|
@ -344,7 +344,7 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
else if (!jump_last && !(bot->pflags & PF_JUMPED) //&& !(player->pflags & PF_SPINNING)
|
||||
&& ((zdist > 32*scale && player->pflags & PF_JUMPED) // Following
|
||||
|| (zdist > 64*scale && mem->thinkstate == AI_CATCHUP) // Vertical catch-up
|
||||
|| (stalled && mem-> catchup_tics > 20 && bot->powers[pw_carry] == CR_NONE)
|
||||
|| (stalled && mem->catchup_tics > 20 && bot->powers[pw_carry] == CR_NONE)
|
||||
//|| (bmom < scale>>3 && dist > followthres && !(bot->powers[pw_carry])) // Stopped & not in carry state
|
||||
|| (bot->pflags & PF_SPINNING && !(bot->pflags & PF_JUMPED)))) // Spinning
|
||||
jump = true;
|
||||
|
@ -371,6 +371,8 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
|
||||
void B_BuildTiccmd(player_t *player, ticcmd_t *cmd)
|
||||
{
|
||||
G_CopyTiccmd(cmd, I_BaseTiccmd(), 1); // empty, or external driver
|
||||
|
||||
// Can't build a ticcmd if we aren't spawned...
|
||||
if (!player->mo)
|
||||
return;
|
||||
|
@ -390,7 +392,7 @@ void B_BuildTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
return;
|
||||
|
||||
// Make sure we have a valid main character to follow
|
||||
B_UpdateBotleader(player);
|
||||
B_UpdateBotleader(player);
|
||||
if (!player->botleader)
|
||||
return;
|
||||
|
||||
|
@ -403,7 +405,7 @@ void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward
|
|||
{
|
||||
player_t *player = mo->player;
|
||||
// don't try to do stuff if your sonic is in a minecart or something
|
||||
if (&player->botleader && player->botleader->powers[pw_carry] && player->botleader->powers[pw_carry] != CR_PLAYER)
|
||||
if (player->botleader && player->botleader->powers[pw_carry] && player->botleader->powers[pw_carry] != CR_PLAYER)
|
||||
return;
|
||||
// Turn the virtual keypresses into ticcmd_t.
|
||||
if (twodlevel || mo->flags2 & MF2_TWOD) {
|
||||
|
@ -593,25 +595,43 @@ void B_HandleFlightIndicator(player_t *player)
|
|||
{
|
||||
mobj_t *tails = player->mo;
|
||||
botmem_t *mem = &player->botmem;
|
||||
boolean shouldExist;
|
||||
|
||||
if (!tails)
|
||||
return;
|
||||
|
||||
if (mem->thinkstate == AI_THINKFLY && player->bot == BOT_2PAI && tails->health)
|
||||
shouldExist = (mem->thinkstate == AI_THINKFLY) && player->botleader
|
||||
&& player->bot == BOT_2PAI && player->playerstate == PST_LIVE;
|
||||
|
||||
// check whether the indicator doesn't exist
|
||||
if (P_MobjWasRemoved(tails->hnext))
|
||||
{
|
||||
if (!tails->hnext)
|
||||
{
|
||||
P_SetTarget(&tails->hnext, P_SpawnMobjFromMobj(tails, 0, 0, 0, MT_OVERLAY));
|
||||
if (tails->hnext)
|
||||
{
|
||||
P_SetTarget(&tails->hnext->target, tails);
|
||||
P_SetTarget(&tails->hnext->hprev, tails);
|
||||
P_SetMobjState(tails->hnext, S_FLIGHTINDICATOR);
|
||||
}
|
||||
}
|
||||
// if it shouldn't exist, everything is fine
|
||||
if (!shouldExist)
|
||||
return;
|
||||
|
||||
// otherwise, spawn it
|
||||
P_SetTarget(&tails->hnext, P_SpawnMobjFromMobj(tails, 0, 0, 0, MT_OVERLAY));
|
||||
P_SetTarget(&tails->hnext->target, tails);
|
||||
P_SetTarget(&tails->hnext->hprev, tails);
|
||||
P_SetMobjState(tails->hnext, S_FLIGHTINDICATOR);
|
||||
}
|
||||
else if (tails->hnext && tails->hnext->type == MT_OVERLAY && tails->hnext->state == states+S_FLIGHTINDICATOR)
|
||||
|
||||
// if the mobj isn't a flight indicator, let's not mess with it
|
||||
if (tails->hnext->type != MT_OVERLAY || (tails->hnext->state != states+S_FLIGHTINDICATOR))
|
||||
return;
|
||||
|
||||
// if it shouldn't exist, remove it
|
||||
if (!shouldExist)
|
||||
{
|
||||
P_RemoveMobj(tails->hnext);
|
||||
P_SetTarget(&tails->hnext, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
// otherwise, update its visibility
|
||||
if (P_IsLocalPlayer(player->botleader))
|
||||
tails->hnext->flags2 &= ~MF2_DONTDRAW;
|
||||
else
|
||||
tails->hnext->flags2 |= MF2_DONTDRAW;
|
||||
}
|
||||
|
|
|
@ -150,26 +150,78 @@ FUNCINLINE static ATTRINLINE UINT32 readulong(void *ptr)
|
|||
|
||||
#undef DEALIGNED
|
||||
|
||||
#define WRITESTRINGN(p,s,n) do { size_t tmp_i = 0; for (; tmp_i < n && s[tmp_i] != '\0'; tmp_i++) WRITECHAR(p, s[tmp_i]); if (tmp_i < n) WRITECHAR(p, '\0');} while (0)
|
||||
#define WRITESTRING(p,s) do { size_t tmp_i = 0; for (; s[tmp_i] != '\0'; tmp_i++) WRITECHAR(p, s[tmp_i]); WRITECHAR(p, '\0');} while (0)
|
||||
#define WRITEMEM(p,s,n) do { memcpy(p, s, n); p += n; } while (0)
|
||||
#define WRITESTRINGN(p, s, n) ({ \
|
||||
size_t tmp_i; \
|
||||
\
|
||||
for (tmp_i = 0; tmp_i < n && s[tmp_i] != '\0'; tmp_i++) \
|
||||
WRITECHAR(p, s[tmp_i]); \
|
||||
\
|
||||
if (tmp_i < n) \
|
||||
WRITECHAR(p, '\0'); \
|
||||
})
|
||||
|
||||
#define SKIPSTRING(p) while (READCHAR(p) != '\0')
|
||||
#define WRITESTRINGL(p, s, n) ({ \
|
||||
size_t tmp_i; \
|
||||
\
|
||||
for (tmp_i = 0; tmp_i < n - 1 && s[tmp_i] != '\0'; tmp_i++) \
|
||||
WRITECHAR(p, s[tmp_i]); \
|
||||
\
|
||||
WRITECHAR(p, '\0'); \
|
||||
})
|
||||
|
||||
#define READSTRINGN(p,s,n) ({ size_t tmp_i = 0; for (; tmp_i < n && (s[tmp_i] = READCHAR(p)) != '\0'; tmp_i++); s[tmp_i] = '\0';})
|
||||
#define READSTRING(p,s) ({ size_t tmp_i = 0; for (; (s[tmp_i] = READCHAR(p)) != '\0'; tmp_i++); s[tmp_i] = '\0';})
|
||||
#define READMEM(p,s,n) ({ memcpy(s, p, n); p += n; })
|
||||
#define WRITESTRING(p, s) ({ \
|
||||
size_t tmp_i; \
|
||||
\
|
||||
for (tmp_i = 0; s[tmp_i] != '\0'; tmp_i++) \
|
||||
WRITECHAR(p, s[tmp_i]); \
|
||||
\
|
||||
WRITECHAR(p, '\0'); \
|
||||
})
|
||||
|
||||
#if 0 // old names
|
||||
#define WRITEBYTE(p,b) WRITEUINT8(p,b)
|
||||
#define WRITESHORT(p,b) WRITEINT16(p,b)
|
||||
#define WRITEUSHORT(p,b) WRITEUINT16(p,b)
|
||||
#define WRITELONG(p,b) WRITEINT32(p,b)
|
||||
#define WRITEULONG(p,b) WRITEUINT32(p,b)
|
||||
#define WRITEMEM(p, s, n) ({ \
|
||||
memcpy(p, s, n); \
|
||||
p += n; \
|
||||
})
|
||||
|
||||
#define READBYTE(p) READUINT8(p)
|
||||
#define READSHORT(p) READINT16(p)
|
||||
#define READUSHORT(p) READUINT16(p)
|
||||
#define READLONG(p) READINT32(p)
|
||||
#define READULONG(p) READUINT32(p)
|
||||
#endif
|
||||
#define SKIPSTRING(p) while (READCHAR(p) != '\0')
|
||||
|
||||
#define SKIPSTRINGN(p, n) ({ \
|
||||
size_t tmp_i = 0; \
|
||||
\
|
||||
while (tmp_i < n && READCHAR(p) != '\0') \
|
||||
tmp_i++; \
|
||||
})
|
||||
|
||||
#define SKIPSTRINGL(p, n) SKIPSTRINGN(p, n)
|
||||
|
||||
#define READSTRINGN(p, s, n) ({ \
|
||||
size_t tmp_i = 0; \
|
||||
\
|
||||
while (tmp_i < n && (s[tmp_i] = READCHAR(p)) != '\0') \
|
||||
tmp_i++; \
|
||||
\
|
||||
s[tmp_i] = '\0'; \
|
||||
})
|
||||
|
||||
#define READSTRINGL(p, s, n) ({ \
|
||||
size_t tmp_i = 0; \
|
||||
\
|
||||
while (tmp_i < n - 1 && (s[tmp_i] = READCHAR(p)) != '\0') \
|
||||
tmp_i++; \
|
||||
\
|
||||
s[tmp_i] = '\0'; \
|
||||
})
|
||||
|
||||
#define READSTRING(p, s) ({ \
|
||||
size_t tmp_i = 0; \
|
||||
\
|
||||
while ((s[tmp_i] = READCHAR(p)) != '\0') \
|
||||
tmp_i++; \
|
||||
\
|
||||
s[tmp_i] = '\0'; \
|
||||
})
|
||||
|
||||
#define READMEM(p, s, n) ({ \
|
||||
memcpy(s, p, n); \
|
||||
p += n; \
|
||||
})
|
||||
|
|
|
@ -1144,8 +1144,9 @@ boolean HGetPacket(void)
|
|||
if (netbuffer->checksum != NetbufferChecksum())
|
||||
{
|
||||
DEBFILE("Bad packet checksum\n");
|
||||
//Net_CloseConnection(nodejustjoined ? (doomcom->remotenode | FORCECLOSE) : doomcom->remotenode);
|
||||
Net_CloseConnection(doomcom->remotenode);
|
||||
// Do not disconnect or anything, just ignore the packet.
|
||||
// Bad checksums with UDP tend to happen very scarcely
|
||||
// so they are not normally an issue.
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -3549,6 +3549,7 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
|||
// because sadly no one remembers this place while searching for full state names.
|
||||
const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity testing later.
|
||||
"MT_NULL",
|
||||
"MT_RAY",
|
||||
"MT_UNKNOWN",
|
||||
|
||||
"MT_THOK", // Thok! mobj
|
||||
|
|
98
src/g_game.c
98
src/g_game.c
|
@ -1411,7 +1411,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
newtarget = P_SpawnMobj(ticcmd_ztargetfocus[forplayer]->x, ticcmd_ztargetfocus[forplayer]->y, ticcmd_ztargetfocus[forplayer]->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker
|
||||
P_SetTarget(&newtarget->target, ticcmd_ztargetfocus[forplayer]);
|
||||
|
||||
if (P_AproxDistance(
|
||||
if (player->mo && P_AproxDistance(
|
||||
player->mo->x - ticcmd_ztargetfocus[forplayer]->x,
|
||||
player->mo->y - ticcmd_ztargetfocus[forplayer]->y
|
||||
) > 50*player->mo->scale)
|
||||
|
@ -1547,12 +1547,17 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
cmd->sidemove = (SINT8)(cmd->sidemove + side);
|
||||
|
||||
// Note: Majority of botstuffs are handled in G_Ticker now.
|
||||
if (player->bot == BOT_2PHUMAN) //Player-controlled bot
|
||||
if (player->bot == BOT_2PAI
|
||||
&& !player->powers[pw_tailsfly]
|
||||
&& (cmd->forwardmove || cmd->sidemove || cmd->buttons))
|
||||
{
|
||||
// Fix offset angle for P2-controlled Tailsbot when P2's controls are set to non-Strafe
|
||||
cmd->angleturn = (INT16)((localangle - *myangle) >> 16);
|
||||
player->bot = BOT_2PHUMAN; // A player-controlled bot. Returns to AI when it respawns.
|
||||
CV_SetValue(&cv_analog[1], true);
|
||||
}
|
||||
|
||||
if (player->bot == BOT_2PHUMAN)
|
||||
cmd->angleturn = (INT16)((localangle - *myangle) >> 16);
|
||||
|
||||
*myangle += (cmd->angleturn<<16);
|
||||
|
||||
if (controlstyle == CS_LMAOGALOG) {
|
||||
|
@ -2307,66 +2312,45 @@ void G_Ticker(boolean run)
|
|||
|
||||
buf = gametic % BACKUPTICS;
|
||||
|
||||
// Generate ticcmds for bots FIRST, then copy received ticcmds for players.
|
||||
// This emulates pre-2.2.10 behaviour where the bot referenced their leader's last copied ticcmd,
|
||||
// which is desirable because P_PlayerThink can override inputs (e.g. while PF_STASIS is applied or in a waterslide),
|
||||
// and the bot AI needs to respect that.
|
||||
#define ISHUMAN (players[i].bot == BOT_NONE || players[i].bot == BOT_2PHUMAN)
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i])
|
||||
if (playeringame[i] && !ISHUMAN) // Less work is required if we're building a bot ticcmd.
|
||||
{
|
||||
INT16 received;
|
||||
// Save last frame's button readings
|
||||
players[i].lastbuttons = players[i].cmd.buttons;
|
||||
players[i].lastbuttons = players[i].cmd.buttons; // Save last frame's button readings
|
||||
B_BuildTiccmd(&players[i], &players[i].cmd);
|
||||
|
||||
G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1);
|
||||
// Bot ticcmd handling
|
||||
// Yes, ordinarily this would be handled in G_BuildTiccmd...
|
||||
// ...however, bot players won't have a corresponding consoleplayer or splitscreen player 2 to send that information.
|
||||
// Therefore, this has to be done after ticcmd sends are received.
|
||||
if (players[i].bot == BOT_2PAI) { // Tailsbot for P2
|
||||
if (!players[i].powers[pw_tailsfly] && (players[i].cmd.forwardmove || players[i].cmd.sidemove || players[i].cmd.buttons))
|
||||
{
|
||||
players[i].bot = BOT_2PHUMAN; // A player-controlled bot. Returns to AI when it respawns.
|
||||
CV_SetValue(&cv_analog[1], true);
|
||||
}
|
||||
else
|
||||
{
|
||||
B_BuildTiccmd(&players[i], &players[i].cmd);
|
||||
}
|
||||
B_HandleFlightIndicator(&players[i]);
|
||||
}
|
||||
else if (players[i].bot == BOT_MPAI) {
|
||||
B_BuildTiccmd(&players[i], &players[i].cmd);
|
||||
}
|
||||
|
||||
// Do angle adjustments.
|
||||
if (players[i].bot == BOT_NONE || players[i].bot == BOT_2PHUMAN)
|
||||
{
|
||||
received = (players[i].cmd.angleturn & TICCMD_RECEIVED);
|
||||
players[i].angleturn += players[i].cmd.angleturn - players[i].oldrelangleturn;
|
||||
players[i].oldrelangleturn = players[i].cmd.angleturn;
|
||||
if (P_ControlStyle(&players[i]) == CS_LMAOGALOG)
|
||||
P_ForceLocalAngle(&players[i], players[i].angleturn << 16);
|
||||
else
|
||||
players[i].cmd.angleturn = players[i].angleturn;
|
||||
if (P_ControlStyle(&players[i]) == CS_LMAOGALOG)
|
||||
P_ForceLocalAngle(&players[i], players[i].angleturn << 16);
|
||||
else
|
||||
players[i].cmd.angleturn = players[i].angleturn;
|
||||
|
||||
players[i].cmd.angleturn &= ~TICCMD_RECEIVED;
|
||||
// Use the leveltime sent in the player's ticcmd to determine control lag
|
||||
players[i].cmd.latency = min(((leveltime & 0xFF) - players[i].cmd.latency) & 0xFF, MAXPREDICTTICS-1);
|
||||
}
|
||||
else // Less work is required if we're building a bot ticcmd.
|
||||
{
|
||||
// Since bot TicCmd is pre-determined for both the client and server, the latency and packet checks are simplified.
|
||||
received = 1;
|
||||
players[i].cmd.latency = 0;
|
||||
players[i].angleturn = players[i].cmd.angleturn;
|
||||
players[i].oldrelangleturn = players[i].cmd.angleturn;
|
||||
}
|
||||
players[i].cmd.angleturn |= received;
|
||||
// Since bot TicCmd is pre-determined for both the client and server, the latency and packet checks are simplified.
|
||||
players[i].cmd.latency = 0;
|
||||
P_SetPlayerAngle(&players[i], players[i].cmd.angleturn << 16);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && ISHUMAN)
|
||||
{
|
||||
players[i].lastbuttons = players[i].cmd.buttons; // Save last frame's button readings
|
||||
G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1);
|
||||
|
||||
// Use the leveltime sent in the player's ticcmd to determine control lag
|
||||
players[i].cmd.latency = min(((leveltime & 0xFF) - players[i].cmd.latency) & 0xFF, MAXPREDICTTICS-1);
|
||||
|
||||
// Do angle adjustments.
|
||||
players[i].angleturn += players[i].cmd.angleturn - players[i].oldrelangleturn;
|
||||
players[i].oldrelangleturn = players[i].cmd.angleturn;
|
||||
if (P_ControlStyle(&players[i]) == CS_LMAOGALOG)
|
||||
P_ForceLocalAngle(&players[i], players[i].angleturn << 16);
|
||||
else
|
||||
players[i].cmd.angleturn = (players[i].angleturn & ~TICCMD_RECEIVED) | (players[i].cmd.angleturn & TICCMD_RECEIVED);
|
||||
}
|
||||
}
|
||||
#undef ISHUMAN
|
||||
|
||||
// do main actions
|
||||
switch (gamestate)
|
||||
{
|
||||
|
|
|
@ -347,19 +347,16 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
|
|||
v[2].t = v[3].t = hwrPatch->max_t;
|
||||
|
||||
// clip it since it is used for bunny scroll in doom I
|
||||
if (blendmode)
|
||||
flags = HWR_GetBlendModeFlag(blendmode+1)|PF_NoDepthTest;
|
||||
else
|
||||
flags = PF_Translucent|PF_NoDepthTest;
|
||||
flags = HWR_GetBlendModeFlag(blendmode+1)|PF_NoDepthTest;
|
||||
|
||||
if (alphalevel)
|
||||
{
|
||||
FSurfaceInfo Surf;
|
||||
Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff;
|
||||
|
||||
if (alphalevel == 10) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency];
|
||||
else if (alphalevel == 11) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency];
|
||||
else if (alphalevel == 12) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency];
|
||||
if (alphalevel == 10) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency]; // V_HUDTRANSHALF
|
||||
else if (alphalevel == 11) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency]; // V_HUDTRANS
|
||||
else if (alphalevel == 12) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency]; // V_HUDTRANSDOUBLE
|
||||
else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
|
||||
flags |= PF_Modulated;
|
||||
HWD.pfnDrawPolygon(&Surf, v, 4, flags);
|
||||
|
@ -644,19 +641,16 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
|
|||
}
|
||||
|
||||
// clip it since it is used for bunny scroll in doom I
|
||||
if (blendmode)
|
||||
flags = HWR_GetBlendModeFlag(blendmode+1)|PF_NoDepthTest;
|
||||
else
|
||||
flags = PF_Translucent|PF_NoDepthTest;
|
||||
flags = HWR_GetBlendModeFlag(blendmode+1)|PF_NoDepthTest;
|
||||
|
||||
if (alphalevel)
|
||||
{
|
||||
FSurfaceInfo Surf;
|
||||
Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff;
|
||||
|
||||
if (alphalevel == 10) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency];
|
||||
else if (alphalevel == 11) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency];
|
||||
else if (alphalevel == 12) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency];
|
||||
if (alphalevel == 10) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency]; // V_HUDTRANSHALF
|
||||
else if (alphalevel == 11) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency]; // V_HUDTRANS
|
||||
else if (alphalevel == 12) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency]; // V_HUDTRANSDOUBLE
|
||||
else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
|
||||
|
||||
flags |= PF_Modulated;
|
||||
|
|
415
src/hu_stuff.c
415
src/hu_stuff.c
|
@ -76,7 +76,7 @@ patch_t *nto_font[NT_FONTSIZE];
|
|||
|
||||
static player_t *plr;
|
||||
boolean chat_on; // entering a chat message?
|
||||
static char w_chat[HU_MAXMSGLEN];
|
||||
static char w_chat[HU_MAXMSGLEN + 1];
|
||||
static size_t c_input = 0; // let's try to make the chat input less shitty.
|
||||
static boolean headsupactive = false;
|
||||
boolean hu_showscores; // draw rankings
|
||||
|
@ -461,7 +461,7 @@ void HU_AddChatText(const char *text, boolean playsound)
|
|||
|
||||
static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
|
||||
{
|
||||
char buf[254];
|
||||
char buf[2 + HU_MAXMSGLEN + 1];
|
||||
size_t numwords, ix;
|
||||
char *msg = &buf[2];
|
||||
const size_t msgspace = sizeof buf - 2;
|
||||
|
@ -537,7 +537,7 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
|
|||
}
|
||||
buf[0] = target;
|
||||
newmsg = msg+5+spc;
|
||||
strlcpy(msg, newmsg, 252);
|
||||
strlcpy(msg, newmsg, HU_MAXMSGLEN + 1);
|
||||
}
|
||||
|
||||
SendNetXCmd(XD_SAY, buf, strlen(msg) + 1 + msg-buf);
|
||||
|
@ -644,7 +644,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
|
|||
target = READSINT8(*p);
|
||||
flags = READUINT8(*p);
|
||||
msg = (char *)*p;
|
||||
SKIPSTRING(*p);
|
||||
SKIPSTRINGL(*p, HU_MAXMSGLEN + 1);
|
||||
|
||||
if ((cv_mute.value || flags & (HU_CSAY|HU_SERVER_SAY)) && playernum != serverplayer && !(IsPlayerAdmin(playernum)))
|
||||
{
|
||||
|
@ -858,72 +858,6 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
|
|||
#endif
|
||||
}
|
||||
|
||||
// Handles key input and string input
|
||||
//
|
||||
static inline boolean HU_keyInChatString(char *s, char ch)
|
||||
{
|
||||
size_t l;
|
||||
|
||||
if ((ch >= HU_FONTSTART && ch <= HU_FONTEND && hu_font[ch-HU_FONTSTART])
|
||||
|| ch == ' ') // Allow spaces, of course
|
||||
{
|
||||
l = strlen(s);
|
||||
if (l < HU_MAXMSGLEN - 1)
|
||||
{
|
||||
if (c_input >= strlen(s)) // don't do anything complicated
|
||||
{
|
||||
s[l++] = ch;
|
||||
s[l]=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// move everything past c_input for new characters:
|
||||
size_t m = HU_MAXMSGLEN-1;
|
||||
while (m>=c_input)
|
||||
{
|
||||
if (s[m])
|
||||
s[m+1] = (s[m]);
|
||||
if (m == 0) // prevent overflow
|
||||
break;
|
||||
m--;
|
||||
}
|
||||
s[c_input] = ch; // and replace this.
|
||||
}
|
||||
c_input++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (ch == KEY_BACKSPACE)
|
||||
{
|
||||
size_t i = c_input;
|
||||
|
||||
if (c_input <= 0)
|
||||
return false;
|
||||
|
||||
if (!s[i-1])
|
||||
return false;
|
||||
|
||||
if (i >= strlen(s)-1)
|
||||
{
|
||||
s[strlen(s)-1] = 0;
|
||||
c_input--;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (; (i < HU_MAXMSGLEN); i++)
|
||||
{
|
||||
s[i-1] = s[i];
|
||||
}
|
||||
c_input--;
|
||||
}
|
||||
else if (ch != KEY_ENTER)
|
||||
return false; // did not eat key
|
||||
|
||||
return true; // ate the key
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
|
@ -945,151 +879,123 @@ void HU_Ticker(void)
|
|||
#ifndef NONET
|
||||
|
||||
static boolean teamtalk = false;
|
||||
static boolean justscrolleddown;
|
||||
static boolean justscrolledup;
|
||||
static INT16 typelines = 1; // number of drawfill lines we need when drawing the chat. it's some weird hack and might be one frame off but I'm lazy to make another loop.
|
||||
// It's up here since it has to be reset when we open the chat.
|
||||
|
||||
// Clear spaces so we don't end up with messages only made out of emptiness
|
||||
static boolean HU_clearChatSpaces(void)
|
||||
static boolean HU_chatboxContainsOnlySpaces(void)
|
||||
{
|
||||
size_t i = 0; // Used to just check our message
|
||||
char c; // current character we're iterating.
|
||||
boolean nothingbutspaces = true;
|
||||
size_t i;
|
||||
|
||||
for (; i < strlen(w_chat); i++) // iterate through message and eradicate all spaces that don't belong.
|
||||
{
|
||||
c = w_chat[i];
|
||||
if (!c)
|
||||
break; // if there's nothing, it's safe to assume our message has ended, so let's not waste any more time here.
|
||||
for (i = 0; w_chat[i]; i++)
|
||||
if (w_chat[i] != ' ')
|
||||
return false;
|
||||
|
||||
if (c != ' ') // Isn't a space
|
||||
{
|
||||
nothingbutspaces = false;
|
||||
}
|
||||
}
|
||||
return nothingbutspaces;
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
static void HU_queueChatChar(char c)
|
||||
static void HU_sendChatMessage(void)
|
||||
{
|
||||
// send automaticly the message (no more chat char)
|
||||
if (c == KEY_ENTER)
|
||||
char buf[2 + HU_MAXMSGLEN + 1];
|
||||
char *msg = &buf[2];
|
||||
size_t ci;
|
||||
INT32 target = 0;
|
||||
|
||||
// if our message was nothing but spaces, don't send it.
|
||||
if (HU_chatboxContainsOnlySpaces())
|
||||
return;
|
||||
|
||||
// copy printable characters and terminating '\0' only.
|
||||
for (ci = 2; w_chat[ci-2]; ci++)
|
||||
{
|
||||
char buf[2+256];
|
||||
char *msg = &buf[2];
|
||||
size_t i = 0;
|
||||
size_t ci = 2;
|
||||
INT32 target = 0;
|
||||
char c = w_chat[ci-2];
|
||||
if (c >= ' ' && !(c & 0x80))
|
||||
buf[ci] = c;
|
||||
};
|
||||
buf[ci] = '\0';
|
||||
|
||||
if (HU_clearChatSpaces()) // Avoids being able to send empty messages, or something.
|
||||
return; // If this returns true, that means our message was NOTHING but spaces, so don't send it period.
|
||||
memset(w_chat, '\0', sizeof(w_chat));
|
||||
c_input = 0;
|
||||
|
||||
do {
|
||||
c = w_chat[-2+ci++];
|
||||
if (!c || (c >= ' ' && !(c & 0x80))) // copy printable characters and terminating '\0' only.
|
||||
buf[ci-1]=c;
|
||||
} while (c);
|
||||
// last minute mute check
|
||||
if (CHAT_MUTE)
|
||||
{
|
||||
HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false);
|
||||
return;
|
||||
}
|
||||
|
||||
for (;(i<HU_MAXMSGLEN);i++)
|
||||
w_chat[i] = 0; // reset this.
|
||||
if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm
|
||||
{
|
||||
INT32 spc = 1; // used if playernum[1] is a space.
|
||||
char playernum[3];
|
||||
const char *newmsg;
|
||||
|
||||
c_input = 0;
|
||||
// what we're gonna do now is check if the player exists
|
||||
// with that logic, characters 4 and 5 are our numbers:
|
||||
|
||||
// last minute mute check
|
||||
if (CHAT_MUTE)
|
||||
// teamtalk can't send PMs, just don't send it, else everyone would be able to see it, and no one wants to see your sex RP sicko.
|
||||
if (teamtalk)
|
||||
{
|
||||
HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false);
|
||||
HU_AddChatText(va("%sCannot send sayto in Say-Team.", "\x85"), false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm
|
||||
strncpy(playernum, msg+3, 3);
|
||||
// check for undesirable characters in our "number"
|
||||
if (!(isdigit(playernum[0]) && isdigit(playernum[1])))
|
||||
{
|
||||
INT32 spc = 1; // used if playernum[1] is a space.
|
||||
char playernum[3];
|
||||
const char *newmsg;
|
||||
|
||||
// what we're gonna do now is check if the player exists
|
||||
// with that logic, characters 4 and 5 are our numbers:
|
||||
|
||||
// teamtalk can't send PMs, just don't send it, else everyone would be able to see it, and no one wants to see your sex RP sicko.
|
||||
if (teamtalk)
|
||||
{
|
||||
HU_AddChatText(va("%sCannot send sayto in Say-Team.", "\x85"), false);
|
||||
return;
|
||||
}
|
||||
|
||||
strncpy(playernum, msg+3, 3);
|
||||
// check for undesirable characters in our "number"
|
||||
if (((playernum[0] < '0') || (playernum[0] > '9')) || ((playernum[1] < '0') || (playernum[1] > '9')))
|
||||
{
|
||||
// check if playernum[1] is a space
|
||||
if (playernum[1] == ' ')
|
||||
spc = 0;
|
||||
// let it slide
|
||||
else
|
||||
{
|
||||
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<player num> \'.", false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// I'm very bad at C, I swear I am, additional checks eww!
|
||||
if (spc != 0)
|
||||
{
|
||||
if (msg[5] != ' ')
|
||||
{
|
||||
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<player num> \'.", false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
target = atoi(playernum); // turn that into a number
|
||||
//CONS_Printf("%d\n", target);
|
||||
|
||||
// check for target player, if it doesn't exist then we can't send the message!
|
||||
if (target < MAXPLAYERS && playeringame[target]) // player exists
|
||||
target++; // even though playernums are from 0 to 31, target is 1 to 32, so up that by 1 to have it work!
|
||||
// check if playernum[1] is a space
|
||||
if (playernum[1] == ' ')
|
||||
spc = 0;
|
||||
// let it slide
|
||||
else
|
||||
{
|
||||
HU_AddChatText(va("\x82NOTICE: \x80Player %d does not exist.", target), false); // same
|
||||
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<player num> \'.", false);
|
||||
return;
|
||||
}
|
||||
|
||||
// we need to get rid of the /pm<player num>
|
||||
newmsg = msg+5+spc;
|
||||
strlcpy(msg, newmsg, 255);
|
||||
}
|
||||
if (ci > 3) // don't send target+flags+empty message.
|
||||
// I'm very bad at C, I swear I am, additional checks eww!
|
||||
if (spc != 0 && msg[5] != ' ')
|
||||
{
|
||||
if (teamtalk)
|
||||
buf[0] = -1; // target
|
||||
else
|
||||
buf[0] = target;
|
||||
|
||||
buf[1] = 0; // flags
|
||||
SendNetXCmd(XD_SAY, buf, 2 + strlen(&buf[2]) + 1);
|
||||
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<player num> \'.", false);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
|
||||
target = atoi(playernum); // turn that into a number
|
||||
|
||||
// check for target player, if it doesn't exist then we can't send the message!
|
||||
if (target < MAXPLAYERS && playeringame[target]) // player exists
|
||||
target++; // even though playernums are from 0 to 31, target is 1 to 32, so up that by 1 to have it work!
|
||||
else
|
||||
{
|
||||
HU_AddChatText(va("\x82NOTICE: \x80Player %d does not exist.", target), false); // same
|
||||
return;
|
||||
}
|
||||
|
||||
// we need to get rid of the /pm<player num>
|
||||
newmsg = msg+5+spc;
|
||||
strlcpy(msg, newmsg, HU_MAXMSGLEN + 1);
|
||||
}
|
||||
if (ci > 2) // don't send target+flags+empty message.
|
||||
{
|
||||
buf[0] = teamtalk ? -1 : target; // target
|
||||
buf[1] = 0; // flags
|
||||
SendNetXCmd(XD_SAY, buf, 2 + strlen(&buf[2]) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void HU_clearChatChars(void)
|
||||
{
|
||||
size_t i = 0;
|
||||
for (;i<HU_MAXMSGLEN;i++)
|
||||
w_chat[i] = 0; // reset this.
|
||||
memset(w_chat, '\0', sizeof(w_chat));
|
||||
chat_on = false;
|
||||
c_input = 0;
|
||||
|
||||
I_UpdateMouseGrab();
|
||||
}
|
||||
|
||||
#ifndef NONET
|
||||
static boolean justscrolleddown;
|
||||
static boolean justscrolledup;
|
||||
static INT16 typelines = 1; // number of drawfill lines we need when drawing the chat. it's some weird hack and might be one frame off but I'm lazy to make another loop.
|
||||
// It's up here since it has to be reset when we open the chat.
|
||||
#endif
|
||||
|
||||
//
|
||||
// Returns true if key eaten
|
||||
//
|
||||
|
@ -1171,21 +1077,23 @@ boolean HU_Responder(event_t *ev)
|
|||
if (shiftdown ^ capslock)
|
||||
c = shiftxform[c];
|
||||
}
|
||||
else // if we're holding shift we should still shift non letter symbols
|
||||
else // if we're holding shift we should still shift non letter symbols
|
||||
{
|
||||
if (shiftdown)
|
||||
c = shiftxform[c];
|
||||
}
|
||||
|
||||
// pasting. pasting is cool. chat is a bit limited, though :(
|
||||
if (((c == 'v' || c == 'V') && ctrldown) && !CHAT_MUTE)
|
||||
if ((c == 'v' || c == 'V') && ctrldown)
|
||||
{
|
||||
const char *paste = I_ClipboardPaste();
|
||||
const char *paste;
|
||||
size_t chatlen;
|
||||
size_t pastelen;
|
||||
|
||||
// create a dummy string real quickly
|
||||
if (CHAT_MUTE)
|
||||
return true;
|
||||
|
||||
paste = I_ClipboardPaste();
|
||||
if (paste == NULL)
|
||||
return true;
|
||||
|
||||
|
@ -1194,40 +1102,16 @@ boolean HU_Responder(event_t *ev)
|
|||
if (chatlen+pastelen > HU_MAXMSGLEN)
|
||||
return true; // we can't paste this!!
|
||||
|
||||
if (c_input >= strlen(w_chat)) // add it at the end of the string.
|
||||
{
|
||||
memcpy(&w_chat[chatlen], paste, pastelen); // copy all of that.
|
||||
c_input += pastelen;
|
||||
/*size_t i = 0;
|
||||
for (;i<pastelen;i++)
|
||||
{
|
||||
HU_queueChatChar(paste[i]); // queue it so that it's actually sent. (this chat write thing is REALLY messy.)
|
||||
}*/
|
||||
return true;
|
||||
}
|
||||
else // otherwise, we need to shift everything and make space, etc etc
|
||||
{
|
||||
size_t i = HU_MAXMSGLEN-1;
|
||||
while (i >= c_input)
|
||||
{
|
||||
if (w_chat[i])
|
||||
w_chat[i+pastelen] = w_chat[i];
|
||||
if (i == 0) // prevent overflow
|
||||
break;
|
||||
i--;
|
||||
}
|
||||
memcpy(&w_chat[c_input], paste, pastelen); // copy all of that.
|
||||
c_input += pastelen;
|
||||
return true;
|
||||
}
|
||||
memmove(&w_chat[c_input + pastelen], &w_chat[c_input], pastelen);
|
||||
memcpy(&w_chat[c_input], paste, pastelen); // copy all of that.
|
||||
c_input += pastelen;
|
||||
return true;
|
||||
}
|
||||
else if (c == KEY_ENTER)
|
||||
{
|
||||
if (!CHAT_MUTE)
|
||||
HU_sendChatMessage();
|
||||
|
||||
if (!CHAT_MUTE && HU_keyInChatString(w_chat,c))
|
||||
{
|
||||
HU_queueChatChar(c);
|
||||
}
|
||||
if (c == KEY_ENTER)
|
||||
{
|
||||
chat_on = false;
|
||||
c_input = 0; // reset input cursor
|
||||
chat_scrollmedown = true; // you hit enter, so you might wanna autoscroll to see what you just sent. :)
|
||||
|
@ -1268,6 +1152,32 @@ boolean HU_Responder(event_t *ev)
|
|||
else
|
||||
c_input++;
|
||||
}
|
||||
else if ((c >= HU_FONTSTART && c <= HU_FONTEND && hu_font[c-HU_FONTSTART])
|
||||
|| c == ' ') // Allow spaces, of course
|
||||
{
|
||||
if (CHAT_MUTE || strlen(w_chat) >= HU_MAXMSGLEN)
|
||||
return true;
|
||||
|
||||
memmove(&w_chat[c_input + 1], &w_chat[c_input], strlen(w_chat) - c_input + 1);
|
||||
w_chat[c_input] = c;
|
||||
c_input++;
|
||||
}
|
||||
else if (c == KEY_BACKSPACE)
|
||||
{
|
||||
if (CHAT_MUTE || c_input <= 0)
|
||||
return true;
|
||||
|
||||
memmove(&w_chat[c_input - 1], &w_chat[c_input], strlen(w_chat) - c_input + 1);
|
||||
c_input--;
|
||||
}
|
||||
else if (c == KEY_DEL)
|
||||
{
|
||||
if (CHAT_MUTE || c_input >= strlen(w_chat))
|
||||
return true;
|
||||
|
||||
memmove(&w_chat[c_input], &w_chat[c_input + 1], strlen(w_chat) - c_input);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
@ -1863,64 +1773,25 @@ static void HU_DrawChat_Old(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
// draw the Crosshair, at the exact center of the view.
|
||||
//
|
||||
// Draw crosshairs at the exact center of the view.
|
||||
// In splitscreen, crosshairs are stretched vertically to compensate for V_PERPLAYER squishing them.
|
||||
// Crosshairs are pre-cached at HU_Init
|
||||
|
||||
static inline void HU_DrawCrosshair(void)
|
||||
static inline void HU_DrawCrosshairs(void)
|
||||
{
|
||||
INT32 i, y, dupz;
|
||||
INT32 cross1 = cv_crosshair.value & 3;
|
||||
INT32 cross2 = cv_crosshair2.value & 3;
|
||||
|
||||
i = cv_crosshair.value & 3;
|
||||
if (!i)
|
||||
if (automapactive || demoplayback)
|
||||
return;
|
||||
|
||||
if ((netgame || multiplayer) && players[displayplayer].spectator)
|
||||
return;
|
||||
stplyr = ((stplyr == &players[displayplayer]) ? &players[secondarydisplayplayer] : &players[displayplayer]);
|
||||
if (!players[displayplayer].spectator && (!camera.chase || ticcmd_ztargetfocus[0]) && cross1)
|
||||
V_DrawStretchyFixedPatch((BASEVIDWIDTH/2)<<FRACBITS, (BASEVIDHEIGHT/2)<<FRACBITS, FRACUNIT, splitscreen ? 2*FRACUNIT : FRACUNIT, V_TRANSLUCENT|V_PERPLAYER, crosshair[cross1 - 1], NULL);
|
||||
|
||||
#ifdef HWRENDER
|
||||
if (rendermode != render_soft)
|
||||
y = (INT32)gl_basewindowcentery;
|
||||
else
|
||||
#endif
|
||||
y = viewwindowy + (viewheight>>1);
|
||||
|
||||
dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
|
||||
|
||||
V_DrawFixedPatch(vid.width<<(FRACBITS-1), y<<FRACBITS, FRACUNIT/dupz, V_TRANSLUCENT, crosshair[i - 1], NULL);
|
||||
}
|
||||
|
||||
static inline void HU_DrawCrosshair2(void)
|
||||
{
|
||||
INT32 i, y, dupz;
|
||||
|
||||
i = cv_crosshair2.value & 3;
|
||||
if (!i)
|
||||
return;
|
||||
|
||||
if ((netgame || multiplayer) && players[secondarydisplayplayer].spectator)
|
||||
return;
|
||||
|
||||
#ifdef HWRENDER
|
||||
if (rendermode != render_soft)
|
||||
y = (INT32)gl_basewindowcentery;
|
||||
else
|
||||
#endif
|
||||
y = viewwindowy + (viewheight>>1);
|
||||
|
||||
if (!splitscreen)
|
||||
return;
|
||||
|
||||
#ifdef HWRENDER
|
||||
if (rendermode != render_soft)
|
||||
y += (INT32)gl_viewheight;
|
||||
else
|
||||
#endif
|
||||
y += viewheight;
|
||||
|
||||
dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
|
||||
|
||||
V_DrawFixedPatch(vid.width<<(FRACBITS-1), y<<FRACBITS, FRACUNIT/dupz, V_TRANSLUCENT, crosshair[i - 1], NULL);
|
||||
stplyr = ((stplyr == &players[displayplayer]) ? &players[secondarydisplayplayer] : &players[displayplayer]);
|
||||
if (!players[secondarydisplayplayer].spectator && (!camera2.chase || ticcmd_ztargetfocus[1]) && cross2 && splitscreen)
|
||||
V_DrawStretchyFixedPatch((BASEVIDWIDTH/2)<<FRACBITS, (BASEVIDHEIGHT/2)<<FRACBITS, FRACUNIT, 2*FRACUNIT, V_TRANSLUCENT|V_PERPLAYER, crosshair[cross2 - 1], NULL);
|
||||
}
|
||||
|
||||
static void HU_DrawCEcho(void)
|
||||
|
@ -2114,19 +1985,9 @@ void HU_Drawer(void)
|
|||
if (gamestate != GS_LEVEL)
|
||||
return;
|
||||
|
||||
// draw the crosshair, not when viewing demos nor with chasecam
|
||||
// draw the crosshair
|
||||
if (LUA_HudEnabled(hud_crosshair))
|
||||
{
|
||||
if (!automapactive && cv_crosshair.value && !demoplayback &&
|
||||
(!camera.chase || ticcmd_ztargetfocus[0])
|
||||
&& !players[displayplayer].spectator)
|
||||
HU_DrawCrosshair();
|
||||
|
||||
if (!automapactive && cv_crosshair2.value && !demoplayback &&
|
||||
(!camera2.chase || ticcmd_ztargetfocus[1])
|
||||
&& !players[secondarydisplayplayer].spectator)
|
||||
HU_DrawCrosshair2();
|
||||
}
|
||||
HU_DrawCrosshairs();
|
||||
|
||||
// draw desynch text
|
||||
if (hu_redownloadinggamestate)
|
||||
|
|
|
@ -62,7 +62,7 @@ typedef struct
|
|||
//------------------------------------
|
||||
// chat stuff
|
||||
//------------------------------------
|
||||
#define HU_MAXMSGLEN 224
|
||||
#define HU_MAXMSGLEN 223
|
||||
#define CHAT_BUFSIZE 64 // that's enough messages, right? We'll delete the older ones when that gets out of hand.
|
||||
#ifdef NETSPLITSCREEN
|
||||
#define OLDCHAT (cv_consolechat.value == 1 || dedicated || vid.width < 640)
|
||||
|
|
57
src/info.c
57
src/info.c
|
@ -3797,7 +3797,7 @@ state_t states[NUMSTATES] =
|
|||
{SPR_NTPN, 3, 4, {NULL}, 0, 0, S_PIAN5}, // S_PIAN4
|
||||
{SPR_NTPN, 2, 4, {NULL}, 0, 0, S_PIAN6}, // S_PIAN5
|
||||
{SPR_NTPN, 1, 4, {NULL}, 0, 0, S_PIAN1}, // S_PIAN6
|
||||
{SPR_NTPN, 5|FF_ANIMATE, 4, {NULL}, 1, 4, S_PIAN1}, // S_PIANSING
|
||||
{SPR_NTPN, 4|FF_ANIMATE, 24, {NULL}, 1, 4, S_PIAN1}, // S_PIANSING
|
||||
|
||||
// Shleep
|
||||
{SPR_SHLP, 0, 15, {NULL}, 0, 0, S_SHLEEP2}, // S_SHLEEP1
|
||||
|
@ -4018,6 +4018,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_RAY
|
||||
-1, // doomednum
|
||||
S_NULL, // spawnstate
|
||||
0, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
0, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
0, // radius
|
||||
0, // height
|
||||
0, // display offset
|
||||
0, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_UNKNOWN
|
||||
-1, // doomednum
|
||||
S_UNKNOWN, // spawnstate
|
||||
|
@ -5655,8 +5682,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_EGGMOBILE_FLEE1, // xdeathstate
|
||||
sfx_s3kb4, // deathsound
|
||||
4, // speed
|
||||
24*FRACUNIT, // radius
|
||||
76*FRACUNIT, // height
|
||||
36*FRACUNIT, // radius
|
||||
84*FRACUNIT, // height
|
||||
0, // display offset
|
||||
sfx_None, // mass
|
||||
3, // damage
|
||||
|
@ -5790,8 +5817,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_EGGMOBILE2_FLEE1,// xdeathstate
|
||||
sfx_s3kb4, // deathsound
|
||||
2*FRACUNIT, // speed
|
||||
24*FRACUNIT, // radius
|
||||
76*FRACUNIT, // height
|
||||
36*FRACUNIT, // radius
|
||||
84*FRACUNIT, // height
|
||||
0, // display offset
|
||||
0, // mass
|
||||
3, // damage
|
||||
|
@ -5898,7 +5925,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_EGGMOBILE3_FLEE1, // xdeathstate
|
||||
sfx_s3kb4, // deathsound
|
||||
8*FRACUNIT, // speed
|
||||
32*FRACUNIT, // radius
|
||||
36*FRACUNIT, // radius
|
||||
116*FRACUNIT, // height
|
||||
0, // display offset
|
||||
MT_FAKEMOBILE, // mass
|
||||
|
@ -5925,7 +5952,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL, // xdeathstate
|
||||
sfx_mswarp, // deathsound
|
||||
8*FRACUNIT, // speed
|
||||
32*FRACUNIT, // radius
|
||||
36*FRACUNIT, // radius
|
||||
116*FRACUNIT, // height
|
||||
0, // display offset
|
||||
0, // mass
|
||||
|
@ -5979,8 +6006,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_EGGMOBILE4_FLEE1,// xdeathstate
|
||||
sfx_s3kb4, // deathsound
|
||||
0, // speed
|
||||
24*FRACUNIT, // radius
|
||||
76*FRACUNIT, // height
|
||||
36*FRACUNIT, // radius
|
||||
84*FRACUNIT, // height
|
||||
0, // display offset
|
||||
0, // mass
|
||||
3, // damage
|
||||
|
@ -8031,7 +8058,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
DMG_SPIKE, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SOLID|MF_SCENERY, // flags
|
||||
MF_NOBLOCKMAP|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
@ -8058,7 +8085,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
DMG_SPIKE, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SOLID|MF_NOGRAVITY|MF_SCENERY|MF_PAPERCOLLISION, // flags
|
||||
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SCENERY|MF_NOCLIPHEIGHT|MF_PAPERCOLLISION, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
@ -8085,7 +8112,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
4, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SCENERY|MF_NOCLIP|MF_NOCLIPTHING, // flags
|
||||
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPTHING, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
@ -20013,8 +20040,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL, // painstate
|
||||
200, // painchance
|
||||
sfx_None, // painsound
|
||||
S_PIANSING, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // meleestate
|
||||
S_PIANSING, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
|
@ -20025,7 +20052,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
16, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SLIDEME|MF_ENEMY|MF_SPECIAL|MF_SHOOTABLE|MF_NOGRAVITY, // flags
|
||||
MF_SLIDEME|MF_SPECIAL|MF_NOGRAVITY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
|
|
|
@ -4376,6 +4376,7 @@ extern playersprite_t free_spr2;
|
|||
typedef enum mobj_type
|
||||
{
|
||||
MT_NULL,
|
||||
MT_RAY, // General purpose mobj
|
||||
MT_UNKNOWN,
|
||||
|
||||
MT_THOK, // Thok! mobj
|
||||
|
|
|
@ -3489,7 +3489,7 @@ static int lib_gAddPlayer(lua_State *L)
|
|||
|
||||
// Read the bot name, if given
|
||||
if (!lua_isnoneornil(L, 3))
|
||||
strcpy(player_names[newplayernum], luaL_checkstring(L, 3));
|
||||
strlcpy(player_names[newplayernum], luaL_checkstring(L, 3), sizeof(*player_names));
|
||||
|
||||
bot = luaL_optinteger(L, 4, 3);
|
||||
newplayer->bot = (bot >= BOT_NONE && bot <= BOT_MPAI) ? bot : BOT_MPAI;
|
||||
|
|
|
@ -347,6 +347,10 @@ static boolean prepare_mobj_hook
|
|||
int hook_type,
|
||||
mobjtype_t mobj_type
|
||||
){
|
||||
#ifdef PARANOIA
|
||||
if (mobj_type == MT_NULL)
|
||||
I_Error("MT_NULL has been passed to a mobj hook\n");
|
||||
#endif
|
||||
return init_hook_type(hook, default_status,
|
||||
hook_type, mobj_type, NULL,
|
||||
mobj_hook_available(hook_type, mobj_type));
|
||||
|
|
|
@ -98,6 +98,7 @@ void AddMServCommands(void)
|
|||
CV_RegisterVar(&cv_servername);
|
||||
#ifdef MASTERSERVER
|
||||
COM_AddCommand("listserv", Command_Listserv_f);
|
||||
COM_AddCommand("masterserver_update", Update_parameters); // allows people to updates manually in case you were delisted by accident
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -2659,7 +2659,7 @@ void A_LobShot(mobj_t *actor)
|
|||
{
|
||||
INT32 locvar1 = var1;
|
||||
INT32 locvar2 = var2 >> 16;
|
||||
mobj_t *shot, *hitspot;
|
||||
mobj_t *shot;
|
||||
angle_t an;
|
||||
fixed_t z;
|
||||
fixed_t dist;
|
||||
|
@ -2698,11 +2698,6 @@ void A_LobShot(mobj_t *actor)
|
|||
P_SetScale(shot, actor->scale);
|
||||
}
|
||||
|
||||
// Keep track of where it's going to land
|
||||
hitspot = P_SpawnMobj(actor->target->x&(64*FRACUNIT-1), actor->target->y&(64*FRACUNIT-1), actor->target->subsector->sector->floorheight, MT_NULL);
|
||||
hitspot->tics = airtime;
|
||||
P_SetTarget(&shot->tracer, hitspot);
|
||||
|
||||
P_SetTarget(&shot->target, actor); // where it came from
|
||||
|
||||
shot->angle = an = actor->angle;
|
||||
|
@ -3338,20 +3333,18 @@ void A_SkullAttack(mobj_t *actor)
|
|||
actor->angle += (P_RandomChance(FRACUNIT/2)) ? ANGLE_90 : -ANGLE_90;
|
||||
else if (locvar1 == 3)
|
||||
{
|
||||
statenum_t oldspawnstate = mobjinfo[MT_NULL].spawnstate;
|
||||
UINT32 oldflags = mobjinfo[MT_NULL].flags;
|
||||
fixed_t oldradius = mobjinfo[MT_NULL].radius;
|
||||
fixed_t oldheight = mobjinfo[MT_NULL].height;
|
||||
mobj_t *check;
|
||||
statenum_t oldspawnstate = mobjinfo[MT_RAY].spawnstate;
|
||||
UINT32 oldflags = mobjinfo[MT_RAY].flags;
|
||||
fixed_t oldradius = mobjinfo[MT_RAY].radius;
|
||||
fixed_t oldheight = mobjinfo[MT_RAY].height;
|
||||
INT32 i, j;
|
||||
static INT32 k;/* static for (at least) GCC 9.1 weirdness */
|
||||
boolean allow;
|
||||
angle_t testang = 0;
|
||||
|
||||
mobjinfo[MT_NULL].spawnstate = S_INVISIBLE;
|
||||
mobjinfo[MT_NULL].flags = MF_NOGRAVITY|MF_NOTHINK|MF_NOCLIPTHING|MF_NOBLOCKMAP;
|
||||
mobjinfo[MT_NULL].radius = mobjinfo[actor->type].radius;
|
||||
mobjinfo[MT_NULL].height = mobjinfo[actor->type].height;
|
||||
mobjinfo[MT_RAY].spawnstate = S_INVISIBLE;
|
||||
mobjinfo[MT_RAY].flags = MF_NOGRAVITY|MF_NOTHINK|MF_NOCLIPTHING|MF_NOBLOCKMAP;
|
||||
mobjinfo[MT_RAY].radius = mobjinfo[actor->type].radius;
|
||||
mobjinfo[MT_RAY].height = mobjinfo[actor->type].height;
|
||||
|
||||
if (P_RandomChance(FRACUNIT/2)) // port priority 1?
|
||||
{
|
||||
|
@ -3364,15 +3357,12 @@ void A_SkullAttack(mobj_t *actor)
|
|||
j = 9;
|
||||
}
|
||||
|
||||
#define dostuff(q) check = P_SpawnMobjFromMobj(actor, 0, 0, 0, MT_NULL);\
|
||||
#define dostuff(q) \
|
||||
testang = actor->angle + ((i+(q))*ANG10);\
|
||||
allow = (P_TryMove(check,\
|
||||
P_ReturnThrustX(check, testang, dist + 2*actor->radius),\
|
||||
P_ReturnThrustY(check, testang, dist + 2*actor->radius),\
|
||||
true));\
|
||||
P_RemoveMobj(check);\
|
||||
if (allow)\
|
||||
break;
|
||||
if (P_CheckMove(actor,\
|
||||
P_ReturnThrustX(actor, testang, dist + 2*actor->radius),\
|
||||
P_ReturnThrustY(actor, testang, dist + 2*actor->radius),\
|
||||
true)) break;
|
||||
|
||||
if (P_RandomChance(FRACUNIT/2)) // port priority 2?
|
||||
{
|
||||
|
@ -3398,10 +3388,10 @@ void A_SkullAttack(mobj_t *actor)
|
|||
|
||||
#undef dostuff
|
||||
|
||||
mobjinfo[MT_NULL].spawnstate = oldspawnstate;
|
||||
mobjinfo[MT_NULL].flags = oldflags;
|
||||
mobjinfo[MT_NULL].radius = oldradius;
|
||||
mobjinfo[MT_NULL].height = oldheight;
|
||||
mobjinfo[MT_RAY].spawnstate = oldspawnstate;
|
||||
mobjinfo[MT_RAY].flags = oldflags;
|
||||
mobjinfo[MT_RAY].radius = oldradius;
|
||||
mobjinfo[MT_RAY].height = oldheight;
|
||||
}
|
||||
|
||||
an = actor->angle >> ANGLETOFINESHIFT;
|
||||
|
@ -4205,7 +4195,6 @@ void A_CustomPower(mobj_t *actor)
|
|||
player_t *player;
|
||||
INT32 locvar1 = var1;
|
||||
INT32 locvar2 = var2;
|
||||
boolean spawnshield = false;
|
||||
|
||||
if (LUA_CallAction(A_CUSTOMPOWER, actor))
|
||||
return;
|
||||
|
@ -4224,15 +4213,10 @@ void A_CustomPower(mobj_t *actor)
|
|||
|
||||
player = actor->target->player;
|
||||
|
||||
if (locvar1 == pw_shield && player->powers[pw_shield] != locvar2)
|
||||
spawnshield = true;
|
||||
P_SetPower(player, locvar1, locvar2);
|
||||
|
||||
player->powers[locvar1] = (UINT16)locvar2;
|
||||
if (actor->info->seesound)
|
||||
S_StartSound(player->mo, actor->info->seesound);
|
||||
|
||||
if (spawnshield) //workaround for a bug
|
||||
P_SpawnShieldOrb(player);
|
||||
}
|
||||
|
||||
// Function: A_GiveWeapon
|
||||
|
@ -6548,7 +6532,7 @@ void A_OldRingExplode(mobj_t *actor) {
|
|||
{
|
||||
const angle_t fa = (i*FINEANGLES/16) & FINEMASK;
|
||||
|
||||
mo = P_SpawnMobj(actor->x, actor->y, actor->z, locvar1);
|
||||
mo = P_SpawnMobjFromMobj(actor, 0, 0, 0, locvar1);
|
||||
P_SetTarget(&mo->target, actor->target); // Transfer target so player gets the points
|
||||
|
||||
mo->momx = FixedMul(FINECOSINE(fa),ns);
|
||||
|
@ -6574,7 +6558,7 @@ void A_OldRingExplode(mobj_t *actor) {
|
|||
}
|
||||
}
|
||||
|
||||
mo = P_SpawnMobj(actor->x, actor->y, actor->z, locvar1);
|
||||
mo = P_SpawnMobjFromMobj(actor, 0, 0, 0, locvar1);
|
||||
|
||||
P_SetTarget(&mo->target, actor->target);
|
||||
mo->momz = ns;
|
||||
|
@ -6589,7 +6573,7 @@ void A_OldRingExplode(mobj_t *actor) {
|
|||
mo->color = skincolor_bluering;
|
||||
}
|
||||
|
||||
mo = P_SpawnMobj(actor->x, actor->y, actor->z, locvar1);
|
||||
mo = P_SpawnMobjFromMobj(actor, 0, 0, 0, locvar1);
|
||||
|
||||
P_SetTarget(&mo->target, actor->target);
|
||||
mo->momz = -ns;
|
||||
|
|
|
@ -154,6 +154,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff);
|
|||
|
||||
void P_SetObjectMomZ(mobj_t *mo, fixed_t value, boolean relative);
|
||||
void P_RestoreMusic(player_t *player);
|
||||
void P_SetPower(player_t *player, powertype_t power, UINT16 value);
|
||||
void P_SpawnShieldOrb(player_t *player);
|
||||
void P_SwitchShield(player_t *player, UINT16 shieldtype);
|
||||
mobj_t *P_SpawnGhostMobj(mobj_t *mobj);
|
||||
|
@ -409,6 +410,7 @@ void P_SetUnderlayPosition(mobj_t *thing);
|
|||
|
||||
boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y);
|
||||
boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam);
|
||||
boolean P_CheckMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff);
|
||||
boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff);
|
||||
boolean P_Move(mobj_t *actor, fixed_t speed);
|
||||
boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z);
|
||||
|
|
195
src/p_map.c
195
src/p_map.c
|
@ -1465,6 +1465,86 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
return true;
|
||||
}
|
||||
|
||||
// Sprite Spikes!
|
||||
// Do not return because solidity code comes below.
|
||||
if (tmthing->type == MT_SPIKE && tmthing->flags & MF_SOLID && thing->player) // moving spike rams into player?!
|
||||
{
|
||||
if (tmthing->eflags & MFE_VERTICALFLIP)
|
||||
{
|
||||
if (thing->z + thing->height <= tmthing->z + FixedMul(FRACUNIT, tmthing->scale)
|
||||
&& thing->z + thing->height + thing->momz >= tmthing->z + FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz
|
||||
&& !(thing->player->charability == CA_BOUNCE && thing->player->panim == PA_ABILITY && thing->eflags & MFE_VERTICALFLIP))
|
||||
P_DamageMobj(thing, tmthing, tmthing, 1, DMG_SPIKE);
|
||||
}
|
||||
else if (thing->z >= tmthing->z + tmthing->height - FixedMul(FRACUNIT, tmthing->scale)
|
||||
&& thing->z + thing->momz <= tmthing->z + tmthing->height - FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz
|
||||
&& !(thing->player->charability == CA_BOUNCE && thing->player->panim == PA_ABILITY && !(thing->eflags & MFE_VERTICALFLIP)))
|
||||
P_DamageMobj(thing, tmthing, tmthing, 1, DMG_SPIKE);
|
||||
}
|
||||
else if (thing->type == MT_SPIKE && thing->flags & MF_SOLID && tmthing->player) // unfortunate player falls into spike?!
|
||||
{
|
||||
if (thing->eflags & MFE_VERTICALFLIP)
|
||||
{
|
||||
if (tmthing->z + tmthing->height <= thing->z - FixedMul(FRACUNIT, thing->scale)
|
||||
&& tmthing->z + tmthing->height + tmthing->momz >= thing->z - FixedMul(FRACUNIT, thing->scale)
|
||||
&& !(tmthing->player->charability == CA_BOUNCE && tmthing->player->panim == PA_ABILITY && tmthing->eflags & MFE_VERTICALFLIP))
|
||||
P_DamageMobj(tmthing, thing, thing, 1, DMG_SPIKE);
|
||||
}
|
||||
else if (tmthing->z >= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale)
|
||||
&& tmthing->z + tmthing->momz <= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale)
|
||||
&& !(tmthing->player->charability == CA_BOUNCE && tmthing->player->panim == PA_ABILITY && !(tmthing->eflags & MFE_VERTICALFLIP)))
|
||||
P_DamageMobj(tmthing, thing, thing, 1, DMG_SPIKE);
|
||||
}
|
||||
|
||||
if (tmthing->type == MT_WALLSPIKE && tmthing->flags & MF_SOLID && thing->player) // wall spike impales player
|
||||
{
|
||||
fixed_t bottomz, topz;
|
||||
bottomz = tmthing->z;
|
||||
topz = tmthing->z + tmthing->height;
|
||||
if (tmthing->eflags & MFE_VERTICALFLIP)
|
||||
bottomz -= FixedMul(FRACUNIT, tmthing->scale);
|
||||
else
|
||||
topz += FixedMul(FRACUNIT, tmthing->scale);
|
||||
|
||||
if (thing->z + thing->height > bottomz // above bottom
|
||||
&& thing->z < topz) // below top
|
||||
// don't check angle, the player was clearly in the way in this case
|
||||
P_DamageMobj(thing, tmthing, tmthing, 1, DMG_SPIKE);
|
||||
}
|
||||
else if (thing->type == MT_WALLSPIKE && thing->flags & MF_SOLID && tmthing->player)
|
||||
{
|
||||
fixed_t bottomz, topz;
|
||||
angle_t touchangle = R_PointToAngle2(thing->tracer->x, thing->tracer->y, tmthing->x, tmthing->y);
|
||||
|
||||
if (P_PlayerInPain(tmthing->player) && (tmthing->momx || tmthing->momy))
|
||||
{
|
||||
angle_t playerangle = R_PointToAngle2(0, 0, tmthing->momx, tmthing->momy) - touchangle;
|
||||
if (playerangle > ANGLE_180)
|
||||
playerangle = InvAngle(playerangle);
|
||||
if (playerangle < ANGLE_90)
|
||||
return true; // Yes, this is intentionally outside the z-height check. No standing on spikes whilst moving away from them.
|
||||
}
|
||||
|
||||
bottomz = thing->z;
|
||||
topz = thing->z + thing->height;
|
||||
|
||||
if (thing->eflags & MFE_VERTICALFLIP)
|
||||
bottomz -= FixedMul(FRACUNIT, thing->scale);
|
||||
else
|
||||
topz += FixedMul(FRACUNIT, thing->scale);
|
||||
|
||||
if (tmthing->z + tmthing->height > bottomz // above bottom
|
||||
&& tmthing->z < topz // below top
|
||||
&& !P_MobjWasRemoved(thing->tracer)) // this probably wouldn't work if we didn't have a tracer
|
||||
{ // use base as a reference point to determine what angle you touched the spike at
|
||||
touchangle = thing->angle - touchangle;
|
||||
if (touchangle > ANGLE_180)
|
||||
touchangle = InvAngle(touchangle);
|
||||
if (touchangle <= ANGLE_22h) // if you touched it at this close an angle, you get poked!
|
||||
P_DamageMobj(tmthing, thing, thing, 1, DMG_SPIKE);
|
||||
}
|
||||
}
|
||||
|
||||
if (thing->flags & MF_PUSHABLE)
|
||||
{
|
||||
if (tmthing->type == MT_FAN || tmthing->type == MT_STEAM)
|
||||
|
@ -1543,22 +1623,6 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
|
||||
if (thing->player)
|
||||
{
|
||||
if (tmthing->type == MT_WALLSPIKE && (tmthing->flags & MF_SOLID)) // wall spike impales player
|
||||
{
|
||||
fixed_t bottomz, topz;
|
||||
bottomz = tmthing->z;
|
||||
topz = tmthing->z + tmthing->height;
|
||||
if (tmthing->eflags & MFE_VERTICALFLIP)
|
||||
bottomz -= FixedMul(FRACUNIT, tmthing->scale);
|
||||
else
|
||||
topz += FixedMul(FRACUNIT, tmthing->scale);
|
||||
|
||||
if (thing->z + thing->height > bottomz // above bottom
|
||||
&& thing->z < topz) // below top
|
||||
// don't check angle, the player was clearly in the way in this case
|
||||
P_DamageMobj(thing, tmthing, tmthing, 1, DMG_SPIKE);
|
||||
}
|
||||
|
||||
// Doesn't matter what gravity player's following! Just do your stuff in YOUR direction only
|
||||
if (tmthing->eflags & MFE_VERTICALFLIP
|
||||
&& (tmthing->z + tmthing->height + tmthing->momz < thing->z
|
||||
|
@ -1593,55 +1657,6 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
if (!tmthing->health)
|
||||
return true;
|
||||
|
||||
if (thing->type == MT_SPIKE && (thing->flags & MF_SOLID)) // unfortunate player falls into spike?!
|
||||
{
|
||||
if (thing->eflags & MFE_VERTICALFLIP)
|
||||
{
|
||||
if (tmthing->z + tmthing->height <= thing->z - FixedMul(FRACUNIT, thing->scale)
|
||||
&& tmthing->z + tmthing->height + tmthing->momz >= thing->z - FixedMul(FRACUNIT, thing->scale)
|
||||
&& !(tmthing->player->charability == CA_BOUNCE && tmthing->player->panim == PA_ABILITY && tmthing->eflags & MFE_VERTICALFLIP))
|
||||
P_DamageMobj(tmthing, thing, thing, 1, DMG_SPIKE);
|
||||
}
|
||||
else if (tmthing->z >= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale)
|
||||
&& tmthing->z + tmthing->momz <= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale)
|
||||
&& !(tmthing->player->charability == CA_BOUNCE && tmthing->player->panim == PA_ABILITY && !(tmthing->eflags & MFE_VERTICALFLIP)))
|
||||
P_DamageMobj(tmthing, thing, thing, 1, DMG_SPIKE);
|
||||
}
|
||||
|
||||
if (thing->type == MT_WALLSPIKE && (thing->flags & MF_SOLID))
|
||||
{
|
||||
fixed_t bottomz, topz;
|
||||
angle_t touchangle = R_PointToAngle2(thing->tracer->x, thing->tracer->y, tmthing->x, tmthing->y);
|
||||
|
||||
if (P_PlayerInPain(tmthing->player) && (tmthing->momx || tmthing->momy))
|
||||
{
|
||||
angle_t playerangle = R_PointToAngle2(0, 0, tmthing->momx, tmthing->momy) - touchangle;
|
||||
if (playerangle > ANGLE_180)
|
||||
playerangle = InvAngle(playerangle);
|
||||
if (playerangle < ANGLE_90)
|
||||
return true; // Yes, this is intentionally outside the z-height check. No standing on spikes whilst moving away from them.
|
||||
}
|
||||
|
||||
bottomz = thing->z;
|
||||
topz = thing->z + thing->height;
|
||||
|
||||
if (thing->eflags & MFE_VERTICALFLIP)
|
||||
bottomz -= FixedMul(FRACUNIT, thing->scale);
|
||||
else
|
||||
topz += FixedMul(FRACUNIT, thing->scale);
|
||||
|
||||
if (tmthing->z + tmthing->height > bottomz // above bottom
|
||||
&& tmthing->z < topz // below top
|
||||
&& !P_MobjWasRemoved(thing->tracer)) // this probably wouldn't work if we didn't have a tracer
|
||||
{ // use base as a reference point to determine what angle you touched the spike at
|
||||
touchangle = thing->angle - touchangle;
|
||||
if (touchangle > ANGLE_180)
|
||||
touchangle = InvAngle(touchangle);
|
||||
if (touchangle <= ANGLE_22h) // if you touched it at this close an angle, you get poked!
|
||||
P_DamageMobj(tmthing, thing, thing, 1, DMG_SPIKE);
|
||||
}
|
||||
}
|
||||
|
||||
if (thing->type == MT_FAN || thing->type == MT_STEAM)
|
||||
P_DoFanAndGasJet(thing, tmthing);
|
||||
else if (thing->flags & MF_SPRING && tmthing->player->powers[pw_carry] != CR_MINECART)
|
||||
|
@ -1706,8 +1721,8 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
}
|
||||
}
|
||||
|
||||
if ((thing->player) && (tmthing->flags & MF_SPRING || tmthing->type == MT_STEAM))
|
||||
; // springs and gas jets should never be able to step up onto a player
|
||||
if ((tmthing->flags & MF_SPRING || tmthing->type == MT_STEAM || tmthing->type == MT_SPIKE || tmthing->type == MT_WALLSPIKE) && (thing->player))
|
||||
; // springs, gas jets and springs should never be able to step up onto a player
|
||||
// z checking at last
|
||||
// Treat noclip things as non-solid!
|
||||
else if ((thing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID
|
||||
|
@ -1715,9 +1730,6 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
{
|
||||
fixed_t topz, tmtopz;
|
||||
|
||||
if (tmthing->type == MT_SPIKE || tmthing->type == MT_WALLSPIKE) // do not run height checks if you are a spike
|
||||
return true;
|
||||
|
||||
if (tmthing->eflags & MFE_VERTICALFLIP)
|
||||
{
|
||||
// pass under
|
||||
|
@ -2654,17 +2666,17 @@ boolean PIT_PushableMoved(mobj_t *thing)
|
|||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// P_TryMove
|
||||
// Attempt to move to a new position.
|
||||
//
|
||||
boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
|
||||
static boolean
|
||||
increment_move
|
||||
( mobj_t * thing,
|
||||
fixed_t x,
|
||||
fixed_t y,
|
||||
boolean allowdropoff)
|
||||
{
|
||||
fixed_t tryx = thing->x;
|
||||
fixed_t tryy = thing->y;
|
||||
fixed_t radius = thing->radius;
|
||||
fixed_t thingtop;
|
||||
fixed_t startingonground = P_IsObjectOnGround(thing);
|
||||
floatok = false;
|
||||
|
||||
if (radius < MAXRADIUS/2)
|
||||
|
@ -2802,7 +2814,38 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
|
|||
}
|
||||
} while (tryx != x || tryy != y);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// P_CheckMove
|
||||
// Check if a P_TryMove would be successful.
|
||||
//
|
||||
boolean P_CheckMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
|
||||
{
|
||||
boolean moveok;
|
||||
mobj_t *hack = P_SpawnMobjFromMobj(thing, 0, 0, 0, MT_RAY);
|
||||
|
||||
hack->radius = thing->radius;
|
||||
hack->height = thing->height;
|
||||
|
||||
moveok = increment_move(hack, x, y, allowdropoff);
|
||||
P_RemoveMobj(hack);
|
||||
|
||||
return moveok;
|
||||
}
|
||||
|
||||
//
|
||||
// P_TryMove
|
||||
// Attempt to move to a new position.
|
||||
//
|
||||
boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
|
||||
{
|
||||
fixed_t startingonground = P_IsObjectOnGround(thing);
|
||||
|
||||
// The move is ok!
|
||||
if (!increment_move(thing, x, y, allowdropoff))
|
||||
return false;
|
||||
|
||||
// If it's a pushable object, check if anything is
|
||||
// standing on top and move it, too.
|
||||
|
|
95
src/p_mobj.c
95
src/p_mobj.c
|
@ -7861,36 +7861,6 @@ static void P_MobjSceneryThink(mobj_t *mobj)
|
|||
if (P_MobjFlip(mobj)*mobj->momz < mobj->info->speed)
|
||||
mobj->momz = P_MobjFlip(mobj)*mobj->info->speed;
|
||||
break;
|
||||
case MT_SPIKE:
|
||||
case MT_WALLSPIKE:
|
||||
if (mobj->fuse)
|
||||
{
|
||||
mobj->fuse--;
|
||||
break;
|
||||
}
|
||||
P_SetMobjState(mobj, mobj->state->nextstate);
|
||||
mobj->fuse = mobj->spawnpoint ? mobj->spawnpoint->args[0] : mobj->info->speed;
|
||||
break;
|
||||
case MT_WALLSPIKEBASE:
|
||||
if (!mobj->target)
|
||||
{
|
||||
P_RemoveMobj(mobj);
|
||||
return;
|
||||
}
|
||||
mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|(mobj->target->frame & FF_FRAMEMASK);
|
||||
#if 0
|
||||
if (mobj->angle != mobj->target->angle + ANGLE_90) // reposition if not the correct angle
|
||||
{
|
||||
mobj_t* target = mobj->target; // shortcut
|
||||
const fixed_t baseradius = target->radius - (target->scale/2); //FixedMul(FRACUNIT/2, target->scale);
|
||||
P_UnsetThingPosition(mobj);
|
||||
mobj->x = target->x - P_ReturnThrustX(target, target->angle, baseradius);
|
||||
mobj->y = target->y - P_ReturnThrustY(target, target->angle, baseradius);
|
||||
P_SetThingPosition(mobj);
|
||||
mobj->angle = target->angle + ANGLE_90;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case MT_ROCKCRUMBLE1:
|
||||
case MT_ROCKCRUMBLE2:
|
||||
case MT_ROCKCRUMBLE3:
|
||||
|
@ -9399,6 +9369,26 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
|
||||
switch (mobj->type)
|
||||
{
|
||||
case MT_WALLSPIKEBASE:
|
||||
if (!mobj->target)
|
||||
{
|
||||
P_RemoveMobj(mobj);
|
||||
return false;
|
||||
}
|
||||
mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|(mobj->target->frame & FF_FRAMEMASK);
|
||||
#if 0
|
||||
if (mobj->angle != mobj->target->angle + ANGLE_90) // reposition if not the correct angle
|
||||
{
|
||||
mobj_t* target = mobj->target; // shortcut
|
||||
const fixed_t baseradius = target->radius - (target->scale/2); //FixedMul(FRACUNIT/2, target->scale);
|
||||
P_UnsetThingPosition(mobj);
|
||||
mobj->x = target->x - P_ReturnThrustX(target, target->angle, baseradius);
|
||||
mobj->y = target->y - P_ReturnThrustY(target, target->angle, baseradius);
|
||||
P_SetThingPosition(mobj);
|
||||
mobj->angle = target->angle + ANGLE_90;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case MT_FALLINGROCK:
|
||||
// Despawn rocks here in case zmovement code can't do so (blame slopes)
|
||||
if (!mobj->momx && !mobj->momy && !mobj->momz
|
||||
|
@ -10083,6 +10073,11 @@ static boolean P_FuseThink(mobj_t *mobj)
|
|||
break;
|
||||
case MT_METALSONIC_BATTLE:
|
||||
break; // don't remove
|
||||
case MT_SPIKE:
|
||||
case MT_WALLSPIKE:
|
||||
P_SetMobjState(mobj, mobj->state->nextstate);
|
||||
mobj->fuse = mobj->spawnpoint ? mobj->spawnpoint->args[0] : mobj->info->speed;
|
||||
break;
|
||||
case MT_NIGHTSCORE:
|
||||
P_RemoveMobj(mobj);
|
||||
return false;
|
||||
|
@ -10572,7 +10567,17 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
|||
const mobjinfo_t *info = &mobjinfo[type];
|
||||
SINT8 sc = -1;
|
||||
state_t *st;
|
||||
mobj_t *mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL);
|
||||
mobj_t *mobj;
|
||||
|
||||
if (type == MT_NULL)
|
||||
{
|
||||
#ifdef PARANOIA
|
||||
I_Error("Tried to spawn MT_NULL\n");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL);
|
||||
|
||||
// this is officially a mobj, declared as soon as possible.
|
||||
mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker;
|
||||
|
@ -13041,34 +13046,36 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
|
|||
case MT_SPIKE:
|
||||
// Pop up spikes!
|
||||
if (mthing->args[0])
|
||||
{
|
||||
mobj->flags &= ~MF_SCENERY;
|
||||
mobj->fuse = mthing->args[1];
|
||||
else
|
||||
mobj->flags |= MF_NOTHINK;
|
||||
}
|
||||
if (mthing->args[2] & TMSF_RETRACTED)
|
||||
P_SetMobjState(mobj, mobj->info->meleestate);
|
||||
// no collision for spikes if the intangible flag is checked
|
||||
if ((mthing->args[2] & TMSF_INTANGIBLE) || metalrecording)
|
||||
// Use per-thing collision for spikes unless the intangible flag is checked.
|
||||
if (!(mthing->args[2] & TMSF_INTANGIBLE) && !metalrecording)
|
||||
{
|
||||
P_UnsetThingPosition(mobj);
|
||||
mobj->flags |= (MF_NOBLOCKMAP|MF_NOCLIPHEIGHT);
|
||||
mobj->flags &= ~MF_SOLID;
|
||||
mobj->flags &= ~(MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIPHEIGHT);
|
||||
mobj->flags |= MF_SOLID;
|
||||
P_SetThingPosition(mobj);
|
||||
}
|
||||
break;
|
||||
case MT_WALLSPIKE:
|
||||
// Pop up spikes!
|
||||
if (mthing->args[0])
|
||||
{
|
||||
mobj->flags &= ~MF_SCENERY;
|
||||
mobj->fuse = mthing->args[1];
|
||||
else
|
||||
mobj->flags |= MF_NOTHINK;
|
||||
}
|
||||
if (mthing->args[2] & TMSF_RETRACTED)
|
||||
P_SetMobjState(mobj, mobj->info->meleestate);
|
||||
// no collision for spikes if the intangible flag is checked
|
||||
if ((mthing->args[2] & TMSF_INTANGIBLE) || metalrecording)
|
||||
// Use per-thing collision for spikes unless the intangible flag is checked.
|
||||
if (!(mthing->args[2] & TMSF_INTANGIBLE) && !metalrecording)
|
||||
{
|
||||
P_UnsetThingPosition(mobj);
|
||||
mobj->flags |= (MF_NOBLOCKMAP|MF_NOCLIPHEIGHT);
|
||||
mobj->flags &= ~MF_SOLID;
|
||||
mobj->flags &= ~(MF_NOBLOCKMAP | MF_NOCLIPHEIGHT);
|
||||
mobj->flags |= MF_SOLID;
|
||||
P_SetThingPosition(mobj);
|
||||
}
|
||||
// spawn base
|
||||
|
@ -13084,8 +13091,6 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
|
|||
P_SetScale(base, mobj->scale);
|
||||
P_SetTarget(&base->target, mobj);
|
||||
P_SetTarget(&mobj->tracer, base);
|
||||
if (!mthing->args[0])
|
||||
base->flags |= MF_NOTHINK;
|
||||
}
|
||||
break;
|
||||
case MT_RING_BOX:
|
||||
|
|
|
@ -2533,7 +2533,10 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype
|
|||
P_InitializeSeg(seg);
|
||||
seg->angle = R_PointToAngle2(v1->x, v1->y, v2->x, v2->y);
|
||||
if (seg->linedef)
|
||||
segs[i].offset = FixedHypot(v1->x - seg->linedef->v1->x, v1->y - seg->linedef->v1->y);
|
||||
{
|
||||
vertex_t *v = (seg->side == 1) ? seg->linedef->v2 : seg->linedef->v1;
|
||||
segs[i].offset = FixedHypot(v1->x - v->x, v1->y - v->y);
|
||||
}
|
||||
seg->length = P_SegLength(seg);
|
||||
#ifdef HWRENDER
|
||||
seg->flength = (rendermode == render_opengl) ? P_SegLengthFloat(seg) : 0;
|
||||
|
@ -6415,7 +6418,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
|
||||
// internal game map
|
||||
maplumpname = G_BuildMapName(gamemap);
|
||||
lastloadedmaplumpnum = W_CheckNumForName(maplumpname);
|
||||
lastloadedmaplumpnum = W_CheckNumForMap(maplumpname);
|
||||
if (lastloadedmaplumpnum == LUMPERROR)
|
||||
I_Error("Map %s not found.\n", maplumpname);
|
||||
|
||||
|
|
20
src/p_spec.c
20
src/p_spec.c
|
@ -2778,21 +2778,15 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
|||
case 434: // Custom Power
|
||||
if (mo && mo->player)
|
||||
{
|
||||
mobj_t *dummy = P_SpawnMobj(mo->x, mo->y, mo->z, MT_NULL);
|
||||
powertype_t power = line->stringargs[0] ? get_number(line->stringargs[0]) : 0;
|
||||
INT32 value = line->stringargs[1] ? get_number(line->stringargs[1]) : 0;
|
||||
if (value == -1) // 'Infinite'
|
||||
value = UINT16_MAX;
|
||||
|
||||
var1 = line->stringargs[0] ? get_number(line->stringargs[0]) : 0;
|
||||
var2 = line->stringargs[1] ? get_number(line->stringargs[1]) : 0;
|
||||
if (var2 == -1) // 'Infinite'
|
||||
var2 = UINT16_MAX;
|
||||
P_SetPower(mo->player, power, value);
|
||||
|
||||
P_SetTarget(&dummy->target, mo);
|
||||
A_CustomPower(dummy);
|
||||
|
||||
if (bot) {
|
||||
P_SetTarget(&dummy->target, bot);
|
||||
A_CustomPower(dummy);
|
||||
}
|
||||
P_RemoveMobj(dummy);
|
||||
if (bot)
|
||||
P_SetPower(bot->player, power, value);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
38
src/p_user.c
38
src/p_user.c
|
@ -1043,7 +1043,8 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor)
|
|||
fallbackspeed = FixedMul(4*FRACUNIT, player->mo->scale);
|
||||
}
|
||||
|
||||
player->drawangle = ang + ANGLE_180;
|
||||
if (player->pflags & PF_DIRECTIONCHAR)
|
||||
player->drawangle = ang + ANGLE_180;
|
||||
P_InstaThrust(player->mo, ang, fallbackspeed);
|
||||
}
|
||||
|
||||
|
@ -1922,6 +1923,24 @@ void P_SwitchShield(player_t *player, UINT16 shieldtype)
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// P_SetPower
|
||||
//
|
||||
// Sets a power and spawns a shield orb if required.
|
||||
//
|
||||
void P_SetPower(player_t *player, powertype_t power, UINT16 value)
|
||||
{
|
||||
boolean spawnshield = false;
|
||||
|
||||
if (power == pw_shield && player->powers[pw_shield] != value)
|
||||
spawnshield = true;
|
||||
|
||||
player->powers[power] = value;
|
||||
|
||||
if (spawnshield) //workaround for a bug
|
||||
P_SpawnShieldOrb(player);
|
||||
}
|
||||
|
||||
//
|
||||
// P_SpawnGhostMobj
|
||||
//
|
||||
|
@ -6197,18 +6216,11 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad
|
|||
if (player->exiting)
|
||||
return;
|
||||
|
||||
if (!P_CheckMove(player->mo,
|
||||
player->mo->x + player->mo->momx,
|
||||
player->mo->y + player->mo->momy, true))
|
||||
{
|
||||
boolean notallowed;
|
||||
mobj_t *hack = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_NULL);
|
||||
hack->flags = MF_NOGRAVITY;
|
||||
hack->radius = player->mo->radius;
|
||||
hack->height = player->mo->height;
|
||||
hack->z = player->mo->z;
|
||||
P_SetThingPosition(hack);
|
||||
notallowed = (!(P_TryMove(hack, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, true)));
|
||||
P_RemoveMobj(hack);
|
||||
if (notallowed)
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -11357,6 +11369,8 @@ void P_PlayerThink(player_t *player)
|
|||
{
|
||||
if (B_CheckRespawn(player))
|
||||
player->playerstate = PST_REBORN;
|
||||
else
|
||||
B_HandleFlightIndicator(player);
|
||||
}
|
||||
if (player->playerstate == PST_REBORN)
|
||||
{
|
||||
|
|
|
@ -170,6 +170,7 @@ void R_DrawViewBorder(void);
|
|||
void R_DrawColumn_8(void);
|
||||
void R_DrawShadeColumn_8(void);
|
||||
void R_DrawTranslucentColumn_8(void);
|
||||
void R_DrawDropShadowColumn_8(void);
|
||||
void R_DrawTranslatedColumn_8(void);
|
||||
void R_DrawTranslatedTranslucentColumn_8(void);
|
||||
void R_Draw2sMultiPatchColumn_8(void);
|
||||
|
|
|
@ -416,6 +416,39 @@ void R_DrawTranslucentColumn_8(void)
|
|||
}
|
||||
}
|
||||
|
||||
// Hack: A cut-down copy of R_DrawTranslucentColumn_8 that does not read texture
|
||||
// data since something about calculating the texture reading address for drop shadows is broken.
|
||||
// dc_texturemid and dc_iscale get wrong values for drop shadows, however those are not strictly
|
||||
// needed for the current design of the shadows, so this function bypasses the issue
|
||||
// by not using those variables at all.
|
||||
void R_DrawDropShadowColumn_8(void)
|
||||
{
|
||||
register INT32 count;
|
||||
register UINT8 *dest;
|
||||
|
||||
count = dc_yh - dc_yl + 1;
|
||||
|
||||
if (count <= 0) // Zero length, column does not exceed a pixel.
|
||||
return;
|
||||
|
||||
dest = &topleft[dc_yl*vid.width + dc_x];
|
||||
|
||||
{
|
||||
#define DSCOLOR 31 // palette index for the color of the shadow
|
||||
register const UINT8 *transmap_offset = dc_transmap + (dc_colormap[DSCOLOR] << 8);
|
||||
#undef DSCOLOR
|
||||
while ((count -= 2) >= 0)
|
||||
{
|
||||
*dest = *(transmap_offset + (*dest));
|
||||
dest += vid.width;
|
||||
*dest = *(transmap_offset + (*dest));
|
||||
dest += vid.width;
|
||||
}
|
||||
if (count & 1)
|
||||
*dest = *(transmap_offset + (*dest));
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief The R_DrawTranslatedTranslucentColumn_8 function
|
||||
Spiffy function. Not only does it colormap a sprite, but does translucency as well.
|
||||
Uber-kudos to Cyan Helkaraxe
|
||||
|
|
|
@ -992,6 +992,9 @@ void R_DrawTiltedFloorSprite_NPO2_8(void)
|
|||
double endz, endu, endv;
|
||||
UINT32 stepu, stepv;
|
||||
|
||||
struct libdivide_u32_t x_divider = libdivide_u32_gen(ds_flatwidth);
|
||||
struct libdivide_u32_t y_divider = libdivide_u32_gen(ds_flatheight);
|
||||
|
||||
iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx);
|
||||
uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx);
|
||||
vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx);
|
||||
|
@ -1033,12 +1036,13 @@ void R_DrawTiltedFloorSprite_NPO2_8(void)
|
|||
|
||||
// Carefully align all of my Friends.
|
||||
if (x < 0)
|
||||
x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
|
||||
x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth;
|
||||
else
|
||||
x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth;
|
||||
if (y < 0)
|
||||
y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
|
||||
|
||||
x %= ds_flatwidth;
|
||||
y %= ds_flatheight;
|
||||
y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight;
|
||||
else
|
||||
y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight;
|
||||
|
||||
val = source[((y * ds_flatwidth) + x)];
|
||||
if (val & 0xFF00)
|
||||
|
@ -1065,12 +1069,13 @@ void R_DrawTiltedFloorSprite_NPO2_8(void)
|
|||
|
||||
// Carefully align all of my Friends.
|
||||
if (x < 0)
|
||||
x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
|
||||
x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth;
|
||||
else
|
||||
x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth;
|
||||
if (y < 0)
|
||||
y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
|
||||
|
||||
x %= ds_flatwidth;
|
||||
y %= ds_flatheight;
|
||||
y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight;
|
||||
else
|
||||
y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight;
|
||||
|
||||
val = source[((y * ds_flatwidth) + x)];
|
||||
if (val & 0xFF00)
|
||||
|
@ -1101,12 +1106,13 @@ void R_DrawTiltedFloorSprite_NPO2_8(void)
|
|||
|
||||
// Carefully align all of my Friends.
|
||||
if (x < 0)
|
||||
x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
|
||||
x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth;
|
||||
else
|
||||
x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth;
|
||||
if (y < 0)
|
||||
y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
|
||||
|
||||
x %= ds_flatwidth;
|
||||
y %= ds_flatheight;
|
||||
y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight;
|
||||
else
|
||||
y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight;
|
||||
|
||||
val = source[((y * ds_flatwidth) + x)];
|
||||
if (val & 0xFF00)
|
||||
|
@ -1142,6 +1148,9 @@ void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void)
|
|||
double endz, endu, endv;
|
||||
UINT32 stepu, stepv;
|
||||
|
||||
struct libdivide_u32_t x_divider = libdivide_u32_gen(ds_flatwidth);
|
||||
struct libdivide_u32_t y_divider = libdivide_u32_gen(ds_flatheight);
|
||||
|
||||
iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx);
|
||||
uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx);
|
||||
vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx);
|
||||
|
@ -1183,12 +1192,13 @@ void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void)
|
|||
|
||||
// Carefully align all of my Friends.
|
||||
if (x < 0)
|
||||
x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
|
||||
x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth;
|
||||
else
|
||||
x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth;
|
||||
if (y < 0)
|
||||
y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
|
||||
|
||||
x %= ds_flatwidth;
|
||||
y %= ds_flatheight;
|
||||
y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight;
|
||||
else
|
||||
y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight;
|
||||
|
||||
val = source[((y * ds_flatwidth) + x)];
|
||||
if (val & 0xFF00)
|
||||
|
@ -1215,12 +1225,13 @@ void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void)
|
|||
|
||||
// Carefully align all of my Friends.
|
||||
if (x < 0)
|
||||
x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
|
||||
x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth;
|
||||
else
|
||||
x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth;
|
||||
if (y < 0)
|
||||
y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
|
||||
|
||||
x %= ds_flatwidth;
|
||||
y %= ds_flatheight;
|
||||
y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight;
|
||||
else
|
||||
y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight;
|
||||
|
||||
val = source[((y * ds_flatwidth) + x)];
|
||||
if (val & 0xFF00)
|
||||
|
@ -1251,12 +1262,13 @@ void R_DrawTiltedTranslucentFloorSprite_NPO2_8(void)
|
|||
|
||||
// Carefully align all of my Friends.
|
||||
if (x < 0)
|
||||
x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth);
|
||||
x += (libdivide_u32_do((UINT32)(-x-1), &x_divider) + 1) * ds_flatwidth;
|
||||
else
|
||||
x -= libdivide_u32_do((UINT32)x, &x_divider) * ds_flatwidth;
|
||||
if (y < 0)
|
||||
y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight);
|
||||
|
||||
x %= ds_flatwidth;
|
||||
y %= ds_flatheight;
|
||||
y += (libdivide_u32_do((UINT32)(-y-1), &y_divider) + 1) * ds_flatheight;
|
||||
else
|
||||
y -= libdivide_u32_do((UINT32)y, &y_divider) * ds_flatheight;
|
||||
|
||||
val = source[((y * ds_flatwidth) + x)];
|
||||
if (val & 0xFF00)
|
||||
|
|
|
@ -1450,7 +1450,7 @@ static void Mask_Post (maskcount_t* m)
|
|||
|
||||
void R_RenderPlayerView(player_t *player)
|
||||
{
|
||||
UINT8 nummasks = 1;
|
||||
INT32 nummasks = 1;
|
||||
maskcount_t* masks = malloc(sizeof(maskcount_t));
|
||||
|
||||
if (cv_homremoval.value && player == &players[displayplayer]) // if this is display player 1
|
||||
|
|
|
@ -132,6 +132,7 @@ static portal_t* Portal_Add (const INT16 x1, const INT16 x2)
|
|||
|
||||
void Portal_Remove (portal_t* portal)
|
||||
{
|
||||
portalcullsector = NULL;
|
||||
portal_base = portal->next;
|
||||
Z_Free(portal->ceilingclip);
|
||||
Z_Free(portal->floorclip);
|
||||
|
|
|
@ -482,7 +482,7 @@ static void R_RasterizeFloorSplat(floorsplat_t *pSplat, vector2_t *verts, visspr
|
|||
continue;
|
||||
|
||||
for (i = x1; i <= x2; i++)
|
||||
cliptab[i] = (y >= mfloorclip[i]);
|
||||
cliptab[i] = (y >= mfloorclip[i] || y <= mceilingclip[i]);
|
||||
|
||||
// clip left
|
||||
while (cliptab[x1])
|
||||
|
|
|
@ -837,6 +837,12 @@ static void R_DrawVisSprite(vissprite_t *vis)
|
|||
else if (vis->mobj->sprite == SPR_PLAY) // Looks like a player, but doesn't have a color? Get rid of green sonic syndrome.
|
||||
colfunc = colfuncs[COLDRAWFUNC_TRANS];
|
||||
|
||||
// Hack: Use a special column function for drop shadows that bypasses
|
||||
// invalid memory access crashes caused by R_ProjectDropShadow putting wrong values
|
||||
// in dc_texturemid and dc_iscale when the shadow is sloped.
|
||||
if (vis->cut & SC_SHADOW)
|
||||
colfunc = R_DrawDropShadowColumn_8;
|
||||
|
||||
if (vis->extra_colormap && !(vis->renderflags & RF_NOCOLORMAPS))
|
||||
{
|
||||
if (!dc_colormap)
|
||||
|
@ -3001,13 +3007,25 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, p
|
|||
|
||||
if (portal)
|
||||
{
|
||||
for (x = x1; x <= x2; x++)
|
||||
INT32 start_index = max(portal->start, x1);
|
||||
INT32 end_index = min(portal->start + portal->end - portal->start, x2);
|
||||
for (x = x1; x < start_index; x++)
|
||||
{
|
||||
spr->clipbot[x] = -1;
|
||||
spr->cliptop[x] = -1;
|
||||
}
|
||||
for (x = start_index; x <= end_index; x++)
|
||||
{
|
||||
if (spr->clipbot[x] > portal->floorclip[x - portal->start])
|
||||
spr->clipbot[x] = portal->floorclip[x - portal->start];
|
||||
if (spr->cliptop[x] < portal->ceilingclip[x - portal->start])
|
||||
spr->cliptop[x] = portal->ceilingclip[x - portal->start];
|
||||
}
|
||||
for (x = end_index + 1; x <= x2; x++)
|
||||
{
|
||||
spr->clipbot[x] = -1;
|
||||
spr->cliptop[x] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3168,10 +3186,10 @@ static void R_DrawMaskedList (drawnode_t* head)
|
|||
}
|
||||
}
|
||||
|
||||
void R_DrawMasked(maskcount_t* masks, UINT8 nummasks)
|
||||
void R_DrawMasked(maskcount_t* masks, INT32 nummasks)
|
||||
{
|
||||
drawnode_t *heads; /**< Drawnode lists; as many as number of views/portals. */
|
||||
SINT8 i;
|
||||
INT32 i;
|
||||
|
||||
heads = calloc(nummasks, sizeof(drawnode_t));
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ typedef struct
|
|||
sector_t* viewsector;
|
||||
} maskcount_t;
|
||||
|
||||
void R_DrawMasked(maskcount_t* masks, UINT8 nummasks);
|
||||
void R_DrawMasked(maskcount_t* masks, INT32 nummasks);
|
||||
|
||||
// ----------
|
||||
// VISSPRITES
|
||||
|
|
|
@ -358,9 +358,10 @@ static void I_ReportSignal(int num, int coredumped)
|
|||
|
||||
I_OutputMsg("\nProcess killed by signal: %s\n\n", sigmsg);
|
||||
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
|
||||
"Process killed by signal",
|
||||
sigmsg, NULL);
|
||||
if (!M_CheckParm("-dedicated"))
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
|
||||
"Process killed by signal",
|
||||
sigmsg, NULL);
|
||||
}
|
||||
|
||||
#ifndef NEWSIGNALHANDLER
|
||||
|
@ -2202,9 +2203,10 @@ static void newsignalhandler_Warn(const char *pr)
|
|||
|
||||
I_OutputMsg("%s\n", text);
|
||||
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
|
||||
"Startup error",
|
||||
text, NULL);
|
||||
if (!M_CheckParm("-dedicated"))
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
|
||||
"Startup error",
|
||||
text, NULL);
|
||||
|
||||
I_ShutdownConsole();
|
||||
exit(-1);
|
||||
|
@ -2405,9 +2407,10 @@ void I_Error(const char *error, ...)
|
|||
// Implement message box with SDL_ShowSimpleMessageBox,
|
||||
// which should fail gracefully if it can't put a message box up
|
||||
// on the target system
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
|
||||
"SRB2 "VERSIONSTRING" Recursive Error",
|
||||
buffer, NULL);
|
||||
if (!M_CheckParm("-dedicated"))
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
|
||||
"SRB2 "VERSIONSTRING" Recursive Error",
|
||||
buffer, NULL);
|
||||
|
||||
W_Shutdown();
|
||||
exit(-1); // recursive errors detected
|
||||
|
@ -2449,9 +2452,10 @@ void I_Error(const char *error, ...)
|
|||
// Implement message box with SDL_ShowSimpleMessageBox,
|
||||
// which should fail gracefully if it can't put a message box up
|
||||
// on the target system
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
|
||||
"SRB2 "VERSIONSTRING" Error",
|
||||
buffer, NULL);
|
||||
if (!M_CheckParm("-dedicated"))
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR,
|
||||
"SRB2 "VERSIONSTRING" Error",
|
||||
buffer, NULL);
|
||||
// Note that SDL_ShowSimpleMessageBox does *not* require SDL to be
|
||||
// initialized at the time, so calling it after SDL_Quit() is
|
||||
// perfectly okay! In addition, we do this on purpose so the
|
||||
|
|
|
@ -539,25 +539,21 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca
|
|||
patchdrawfunc = standardpdraw;
|
||||
|
||||
v_translevel = NULL;
|
||||
if (alphalevel)
|
||||
if (alphalevel || blendmode)
|
||||
{
|
||||
if (alphalevel == 10)
|
||||
if (alphalevel == 10) // V_HUDTRANSHALF
|
||||
alphalevel = hudminusalpha[st_translucency];
|
||||
else if (alphalevel == 11)
|
||||
else if (alphalevel == 11) // V_HUDTRANS
|
||||
alphalevel = 10 - st_translucency;
|
||||
else if (alphalevel == 12)
|
||||
else if (alphalevel == 12) // V_HUDTRANSDOUBLE
|
||||
alphalevel = hudplusalpha[st_translucency];
|
||||
|
||||
if (alphalevel >= 10)
|
||||
return; // invis
|
||||
|
||||
if (alphalevel)
|
||||
if (alphalevel || blendmode)
|
||||
{
|
||||
if (blendmode)
|
||||
v_translevel = R_GetBlendTable(blendmode+1, alphalevel);
|
||||
else
|
||||
v_translevel = R_GetTranslucencyTable(alphalevel);
|
||||
|
||||
v_translevel = R_GetBlendTable(blendmode+1, alphalevel);
|
||||
patchdrawfunc = translucentpdraw;
|
||||
}
|
||||
}
|
||||
|
@ -833,25 +829,21 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, IN
|
|||
patchdrawfunc = standardpdraw;
|
||||
|
||||
v_translevel = NULL;
|
||||
if (alphalevel)
|
||||
if (alphalevel || blendmode)
|
||||
{
|
||||
if (alphalevel == 10)
|
||||
if (alphalevel == 10) // V_HUDTRANSHALF
|
||||
alphalevel = hudminusalpha[st_translucency];
|
||||
else if (alphalevel == 11)
|
||||
else if (alphalevel == 11) // V_HUDTRANS
|
||||
alphalevel = 10 - st_translucency;
|
||||
else if (alphalevel == 12)
|
||||
else if (alphalevel == 12) // V_HUDTRANSDOUBLE
|
||||
alphalevel = hudplusalpha[st_translucency];
|
||||
|
||||
if (alphalevel >= 10)
|
||||
return; // invis
|
||||
|
||||
if (alphalevel)
|
||||
if (alphalevel || blendmode)
|
||||
{
|
||||
if (blendmode)
|
||||
v_translevel = R_GetBlendTable(blendmode+1, alphalevel);
|
||||
else
|
||||
v_translevel = R_GetTranslucencyTable(alphalevel);
|
||||
|
||||
v_translevel = R_GetBlendTable(blendmode+1, alphalevel);
|
||||
patchdrawfunc = translucentpdraw;
|
||||
}
|
||||
}
|
||||
|
@ -1410,11 +1402,11 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
|
|||
|
||||
if ((alphalevel = ((c & V_ALPHAMASK) >> V_ALPHASHIFT)))
|
||||
{
|
||||
if (alphalevel == 10)
|
||||
if (alphalevel == 10) // V_HUDTRANSHALF
|
||||
alphalevel = hudminusalpha[st_translucency];
|
||||
else if (alphalevel == 11)
|
||||
else if (alphalevel == 11) // V_HUDTRANS
|
||||
alphalevel = 10 - st_translucency;
|
||||
else if (alphalevel == 12)
|
||||
else if (alphalevel == 12) // V_HUDTRANSDOUBLE
|
||||
alphalevel = hudplusalpha[st_translucency];
|
||||
|
||||
if (alphalevel >= 10)
|
||||
|
|
10
src/w_wad.c
10
src/w_wad.c
|
@ -1463,8 +1463,14 @@ lumpnum_t W_CheckNumForMap(const char *name)
|
|||
continue;
|
||||
// Now look for the specified map.
|
||||
for (; lumpNum < end; lumpNum++)
|
||||
if (!strnicmp(name, (wadfiles[i]->lumpinfo + lumpNum)->name, 8))
|
||||
return (i<<16) + lumpNum;
|
||||
{
|
||||
if (!strnicmp(name, wadfiles[i]->lumpinfo[lumpNum].name, 8))
|
||||
{
|
||||
const char *extension = strrchr(wadfiles[i]->lumpinfo[lumpNum].fullname, '.');
|
||||
if (!(extension && stricmp(extension, ".wad")))
|
||||
return (i<<16) + lumpNum;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return LUMPERROR;
|
||||
|
|
Loading…
Reference in a new issue