Merge remote-tracking branch 'refs/remotes/origin/zarrotsu' into attack-is-back

This commit is contained in:
TehRealSalt 2017-10-17 00:45:30 -04:00
commit cce7b4374a
65 changed files with 745 additions and 331 deletions

63
.circleci/config.yml Normal file
View file

@ -0,0 +1,63 @@
version: 2
jobs:
build:
working_directory: /root/SRB2
docker:
- image: debian:jessie
environment:
CC: ccache gcc -m32
PKG_CONFIG_LIBDIR: /usr/lib/i386-linux-gnu/pkgconfig
LIBGME_CFLAGS: -I/usr/include
LIBGME_LDFLAGS: -lgme
CCACHE_COMPRESS: true
WFLAGS: -Wno-unsuffixed-float-constants
GCC49: true
#- image: ubuntu:trusty
# environment:
# CC: ccache gcc -m32
# PKG_CONFIG_LIBDIR: /usr/lib/i386-linux-gnu/pkgconfig
# LIBGME_CFLAGS: -I/usr/include
# LIBGME_LDFLAGS: -lgme
# CCACHE_COMPRESS: true
# WFLAGS: -Wno-unsuffixed-float-constants
# GCC48: true
steps:
- run:
name: Add i386 arch
command: dpkg --add-architecture i386
- run:
name: Update APT listing
command: apt-get -qq update
- run:
name: Support S3 upload
command: apt-get -qq -y install ca-certificates
- restore_cache:
keys:
- v1-SRB2-APT
- run:
name: Install SDK
command: apt-get -qq -y install git build-essential nasm libpng12-dev:i386 libsdl2-mixer-dev:i386 libgme-dev:i386 gettext ccache wget gcc-multilib upx
- save_cache:
key: v1-SRB2-APT
paths:
- /var/cache/apt/archives
- checkout
- run:
name: Clean build
command: make -C src LINUX=1 clean
- restore_cache:
keys:
- v1-SRB2-{{ .Branch }}-{{ checksum "objs/Linux/SDL/Release/depend.dep" }}
- run:
name: Compile
command: make -C src LINUX=1 ERRORMODE=1 -k
- store_artifacts:
path: /root/SRB2/bin/Linux/Release/
destination: bin
- save_cache:
key: v1-SRB2-{{ .Branch }}-{{ checksum "objs/Linux/SDL/Release/depend.dep" }}
paths:
- /root/.ccache

View file

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.0)
project(SRB2
VERSION 2.1.17
VERSION 2.1.18
LANGUAGES C)
if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR})

View file

@ -2,6 +2,7 @@
[![Build status](https://ci.appveyor.com/api/projects/status/399d4hcw9yy7hg2y?svg=true)](https://ci.appveyor.com/project/STJr/srb2)
[![Build status](https://travis-ci.org/STJr/SRB2.svg?branch=master)](https://travis-ci.org/STJr/SRB2)
[![CircleCI](https://circleci.com/gh/STJr/SRB2/tree/master.svg?style=svg)](https://circleci.com/gh/STJr/SRB2/tree/master)
[Sonic Robo Blast 2](https://srb2.org/) is a 3D Sonic the Hedgehog fangame based on a modified version of [Doom Legacy](http://doomlegacy.sourceforge.net/).

View file

@ -1,4 +1,4 @@
version: 2.1.17.{branch}-{build}
version: 2.1.18.{branch}-{build}
os: MinGW
environment:
@ -47,7 +47,7 @@ before_build:
- upx -V
- ccache -V
- ccache -s
- set SRB2_MFLAGS=-C src MINGW=1 WARNINGMODE=1 GCC53=1 CCACHE=1
- set SRB2_MFLAGS=-C src MINGW=1 WARNINGMODE=1 GCC63=1 CCACHE=1
build_script:
- cmd: mingw32-make.exe %SRB2_MFLAGS% %CONFIGURATION%=1 clean

View file

@ -1,3 +1,3 @@
/srb2sdl.exe
/srb2win.exe
/r_opengl.dll
*.exe
*.mo
r_opengl.dll

View file

@ -1,3 +1,3 @@
/srb2sdl.exe
/srb2win.exe
/r_opengl.dll
*.exe
*.mo
r_opengl.dll

8
objs/.gitignore vendored Normal file
View file

@ -0,0 +1,8 @@
#All folders
SRB2.res
depend.dep
depend.ped
*.o
#VC9 folder only
/VC9/Win32
/VC9/x64

View file

@ -1 +1,2 @@
/depend.dep
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1 +1,2 @@
/depend.dep
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1,2 +1,2 @@
/depend.dep
/*.o
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1,2 +1,2 @@
/depend.dep
/*.o
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1,2 +1,2 @@
/depend.dep
/*.o
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1,2 +1,2 @@
/depend.dep
/*.o
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1,3 +1,2 @@
/SRB2.res
/depend.dep
/*.o
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1,3 +1,2 @@
/SRB2.res
/depend.dep
/*.o
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1,3 +1,2 @@
/SRB2.res
/depend.dep
/*.o
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1,3 +1,2 @@
/SRB2.res
/depend.dep
/*.o
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1,3 +1,2 @@
/SRB2.res
/depend.dep
/*.o
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1,3 +1,2 @@
/SRB2.res
/depend.dep
/*.o
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1,3 +1,2 @@
/SRB2.res
/depend.dep
/*.o
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1,3 +1,2 @@
/SRB2.res
/depend.dep
/*.o
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1,2 +1,2 @@
/depend.dep
/*.o
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1,2 +1,2 @@
/depend.dep
/*.o
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1 +1,2 @@
/depend.dep
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1 +1,2 @@
/depend.ped
# DON'T REMOVE
# This keeps the folder from disappearing

2
objs/VC/.gitignore vendored
View file

@ -0,0 +1,2 @@
# DON'T REMOVE
# This keeps the folder from disappearing

4
objs/VC9/.gitignore vendored
View file

@ -1,2 +1,2 @@
/Win32
/x64
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1,2 +1,2 @@
/depend.dep
/*.o
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1,2 +1,2 @@
/depend.dep
/*.o
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1 +1,2 @@
/depend.dep
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1 +1,2 @@
/depend.dep
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1 +1,2 @@
/depend.dep
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1,2 +1,2 @@
/depend.dep
/*.o
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -1,2 +1,2 @@
/depend.dep
/*.o
# DON'T REMOVE
# This keeps the folder from disappearing

View file

@ -7,6 +7,23 @@
# and other things
#
ifdef GCC63
GCC62=1
endif
ifdef GCC62
GCC61=1
endif
ifdef GCC61
GCC54=1
endif
ifdef GCC54
GCC53=1
endif
ifdef GCC53
GCC52=1
endif
@ -164,19 +181,29 @@ ifdef GCC45
WFLAGS+=-Wunsuffixed-float-constants
endif
endif
ifdef NOLDWARNING
LDFLAGS+=-Wl,--as-needed
endif
ifdef ERRORMODE
WFLAGS+=-Werror
endif
WFLAGS+=$(OLDWFLAGS)
ifdef GCC43
#WFLAGS+=-Wno-error=clobbered
endif
ifdef GCC46
WFLAGS+=-Wno-error=suggest-attribute=noreturn
endif
WFLAGS+=$(OLDWFLAGS)
ifdef GCC54
WFLAGS+=-Wno-logical-op -Wno-error=logical-op
endif
ifdef GCC61
WFLAGS+=-Wno-tautological-compare -Wno-error=tautological-compare
endif
#indicate platform and what interface use with

View file

@ -2546,7 +2546,7 @@ static void Command_Ban(void)
return;
else
WRITEUINT8(p, pn);
if (I_Ban && !I_Ban(node))
if (server && I_Ban && !I_Ban(node)) // only the server is allowed to do this right now
{
CONS_Alert(CONS_WARNING, M_GetText("Too many bans! Geez, that's a lot of people you're excluding...\n"));
WRITEUINT8(p, KICK_MSG_GO_AWAY);
@ -2554,7 +2554,8 @@ static void Command_Ban(void)
}
else
{
Ban_Add(COM_Argv(2));
if (server) // only the server is allowed to do this right now
Ban_Add(COM_Argv(2));
if (COM_Argc() == 2)
{
@ -2711,12 +2712,14 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
// If a verified admin banned someone, the server needs to know about it.
// If the playernum isn't zero (the server) then the server needs to record the ban.
if (server && playernum && msg == KICK_MSG_BANNED)
if (server && playernum && (msg == KICK_MSG_BANNED || msg == KICK_MSG_CUSTOM_BAN))
{
if (I_Ban && !I_Ban(playernode[(INT32)pnum]))
{
CONS_Alert(CONS_WARNING, M_GetText("Too many bans! Geez, that's a lot of people you're excluding...\n"));
}
#ifndef NONET
else
Ban_Add(reason);
#endif
}
switch (msg)

View file

@ -716,6 +716,12 @@ void Net_CloseConnection(INT32 node)
if (!node)
return;
if (node < 0 || node >= MAXNETNODES) // prevent invalid nodes from crashing the game
{
CONS_Alert(CONS_WARNING, M_GetText("Net_CloseConnection: invalid node %d detected!\n"), node);
return;
}
nodes[node].flags |= NF_CLOSE;
// try to Send ack back (two army problem)
@ -991,12 +997,14 @@ void Command_Droprate(void)
packetdroprate = droprate;
}
#ifndef NONET
static boolean ShouldDropPacket(void)
{
return (packetdropquantity[netbuffer->packettype])
|| (packetdroprate != 0 && rand() < (RAND_MAX * (packetdroprate / 100.f))) || packetdroprate == 100;
}
#endif
#endif
//
// HSendPacket

View file

@ -2155,7 +2155,7 @@ static void Command_Teamchange_f(void)
return;
}
if (!cv_allowteamchange.value && !NetPacket.packet.newteam) // allow swapping to spectator even in locked teams.
if (!cv_allowteamchange.value && NetPacket.packet.newteam) // allow swapping to spectator even in locked teams.
{
CONS_Alert(CONS_NOTICE, M_GetText("The server is not allowing team changes at the moment.\n"));
return;
@ -2252,7 +2252,7 @@ static void Command_Teamchange2_f(void)
return;
}
if (!cv_allowteamchange.value && !NetPacket.packet.newteam) // allow swapping to spectator even in locked teams.
if (!cv_allowteamchange.value && NetPacket.packet.newteam) // allow swapping to spectator even in locked teams.
{
CONS_Alert(CONS_NOTICE, M_GetText("The server is not allowing team changes at the moment.\n"));
return;
@ -3006,6 +3006,7 @@ static void Command_Addfile(void)
XBOXSTATIC char buf[256];
char *buf_p = buf;
INT32 i;
int musiconly; // W_VerifyNMUSlumps isn't boolean
if (COM_Argc() != 2)
{
@ -3020,7 +3021,9 @@ static void Command_Addfile(void)
if (!isprint(fn[i]) || fn[i] == ';')
return;
if (!W_VerifyNMUSlumps(fn))
musiconly = W_VerifyNMUSlumps(fn);
if (!musiconly)
{
// ... But only so long as they contain nothing more then music and sprites.
if (netgame && !(server || adminplayer == consoleplayer))
@ -3032,7 +3035,7 @@ static void Command_Addfile(void)
}
// Add file on your client directly if it is trivial, or you aren't in a netgame.
if (!(netgame || multiplayer) || W_VerifyNMUSlumps(fn))
if (!(netgame || multiplayer) || musiconly)
{
P_AddWadFile(fn, NULL);
return;
@ -3052,9 +3055,7 @@ static void Command_Addfile(void)
#else
FILE *fhandle;
fhandle = fopen(fn, "rb");
if (fhandle)
if ((fhandle = W_OpenWadFile(&fn, true)) != NULL)
{
tic_t t = I_GetTime();
CONS_Debug(DBG_SETUP, "Making MD5 for %s\n",fn);
@ -3062,11 +3063,8 @@ static void Command_Addfile(void)
CONS_Debug(DBG_SETUP, "MD5 calc for %s took %f second\n", fn, (float)(I_GetTime() - t)/TICRATE);
fclose(fhandle);
}
else
{
CONS_Printf(M_GetText("File %s not found.\n"), fn);
else // file not found
return;
}
#endif
WRITEMEM(buf_p, md5sum, 16);
}
@ -4141,7 +4139,8 @@ static void Skin_OnChange(void)
if (!Playing())
return; // do whatever you want
if (!(cv_debug || devparm) && !(multiplayer || netgame)) // In single player.
if (!(cv_debug || devparm) && !(multiplayer || netgame) // In single player.
&& (gamestate != GS_WAITINGPLAYERS)) // allows command line -warp x +skin y
{
CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name);
return;
@ -4184,8 +4183,7 @@ static void Color_OnChange(void)
if (!Playing())
return; // do whatever you want
if (!(cv_debug || devparm) && !(multiplayer || netgame) // In single player.
&& (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_CONTINUING))
if (!(cv_debug || devparm) && !(multiplayer || netgame)) // In single player.
{
CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name);
return;

View file

@ -6966,7 +6966,7 @@ static const char *const MOBJFLAG_LIST[] = {
"SHOOTABLE",
"NOSECTOR",
"NOBLOCKMAP",
"AMBUSH",
"PAPERCOLLISION",
"PUSHABLE",
"BOSS",
"SPAWNCEILING",
@ -7024,6 +7024,7 @@ static const char *const MOBJFLAG2_LIST[] = {
"BOSSNOTRAP", // No Egg Trap after boss
"BOSSFLEE", // Boss is fleeing!
"BOSSDEAD", // Boss is dead! (Not necessarily fleeing, if a fleeing point doesn't exist.)
"AMBUSH", // Alternate behaviour typically set by MTF_AMBUSH
NULL
};
@ -7355,6 +7356,7 @@ struct {
// Frame settings
{"FF_FRAMEMASK",FF_FRAMEMASK},
{"FF_PAPERSPRITE",FF_PAPERSPRITE},
{"FF_ANIMATE",FF_ANIMATE},
{"FF_FULLBRIGHT",FF_FULLBRIGHT},
{"FF_TRANSMASK",FF_TRANSMASK},

View file

@ -1657,11 +1657,6 @@ static void Analog_OnChange(void)
// cameras are not initialized at this point
if (leveltime > 1)
CV_SetValue(&cv_cam_dist, 128);
if (cv_analog.value || demoplayback)
CV_SetValue(&cv_cam_dist, 192);
if (!cv_chasecam.value && cv_analog.value) {
CV_SetValue(&cv_analog, 0);
return;
@ -1682,11 +1677,6 @@ static void Analog2_OnChange(void)
// cameras are not initialized at this point
if (leveltime > 1)
CV_SetValue(&cv_cam2_dist, 128);
if (cv_analog2.value)
CV_SetValue(&cv_cam2_dist, 192);
if (!cv_chasecam2.value && cv_analog2.value) {
CV_SetValue(&cv_analog2, 0);
return;

View file

@ -78,6 +78,7 @@ typedef struct gr_vissprite_s
//Hurdler: 25/04/2000: now support colormap in hardware mode
UINT8 *colormap;
INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing
float z1, z2;
} gr_vissprite_t;
// --------

View file

@ -4227,6 +4227,7 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
GLPatch_t *gpatch; // sprite patch converted to hardware
FSurfaceInfo Surf;
const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES);
//const boolean papersprite = (spr->mobj && (spr->mobj->frame & FF_PAPERSPRITE));
if (spr->mobj)
this_scale = FIXED_TO_FLOAT(spr->mobj->scale);
if (hires)
@ -4270,7 +4271,8 @@ static void HWR_DrawSprite(gr_vissprite_t *spr)
// make a wall polygon (with 2 triangles), using the floor/ceiling heights,
// and the 2d map coords of start/end vertices
wallVerts[0].z = wallVerts[1].z = wallVerts[2].z = wallVerts[3].z = spr->tz;
wallVerts[0].z = wallVerts[3].z = spr->z1;
wallVerts[2].z = wallVerts[1].z = spr->z2;
// transform
wv = wallVerts;
@ -5064,6 +5066,10 @@ static void HWR_ProjectSprite(mobj_t *thing)
UINT8 flip;
angle_t ang;
INT32 heightsec, phs;
const boolean papersprite = (thing->frame & FF_PAPERSPRITE);
float offset;
float ang_scale = 1.0f, ang_scalez = 0.0f;
float z1, z2;
if (!thing)
return;
@ -5078,7 +5084,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
tz = (tr_x * gr_viewcos) + (tr_y * gr_viewsin);
// thing is behind view plane?
if (tz < ZCLIP_PLANE && (!cv_grmd2.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear
if (tz < ZCLIP_PLANE && !papersprite && (!cv_grmd2.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear
return;
tx = (tr_x * gr_viewsin) - (tr_y * gr_viewcos);
@ -5116,31 +5122,60 @@ static void HWR_ProjectSprite(mobj_t *thing)
I_Error("sprframes NULL for sprite %d\n", thing->sprite);
#endif
if (sprframe->rotate)
if (papersprite)
{
// choose a different rotation based on player view
ang = R_PointToAngle(thing->x, thing->y); // uses viewx,viewy
rot = (ang-thing->angle+ANGLE_202h)>>29;
//Fab: lumpid is the index for spritewidth,spriteoffset... tables
lumpoff = sprframe->lumpid[rot];
flip = sprframe->flip & (1<<rot);
// Use the actual view angle, rather than the angle formed
// between the view point and the thing
// this makes sure paper sprites always appear at the right angle!
// Note: DO NOT do this in software mode version, it actually
// makes papersprites look WORSE there (I know, I've tried)
// Monster Iestyn - 13/05/17
ang = dup_viewangle - thing->angle;
ang_scale = FIXED_TO_FLOAT(FINESINE(ang>>ANGLETOFINESHIFT));
ang_scalez = FIXED_TO_FLOAT(FINECOSINE(ang>>ANGLETOFINESHIFT));
if (ang_scale < 0)
{
ang_scale = -ang_scale;
ang_scalez = -ang_scalez;
}
}
else
else if (sprframe->rotate != SRF_SINGLE)
ang = R_PointToAngle (thing->x, thing->y) - thing->angle;
if (sprframe->rotate == SRF_SINGLE)
{
// use single rotation for all views
rot = 0; //Fab: for vis->patch below
lumpoff = sprframe->lumpid[0]; //Fab: see note above
flip = sprframe->flip; // Will only be 0x00 or 0xFF
}
else
{
// choose a different rotation based on player view
if ((ang < ANGLE_180) && (sprframe->rotate & SRF_RIGHT)) // See from right
rot = 6; // F7 slot
else if ((ang >= ANGLE_180) && (sprframe->rotate & SRF_LEFT)) // See from left
rot = 2; // F3 slot
else // Normal behaviour
rot = (ang+ANGLE_202h)>>29;
//Fab: lumpid is the index for spritewidth,spriteoffset... tables
lumpoff = sprframe->lumpid[rot];
flip = sprframe->flip & (1<<rot);
}
if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES)
this_scale = this_scale * FIXED_TO_FLOAT(((skin_t *)thing->skin)->highresscale);
// calculate edges of the shape
if (flip)
tx -= FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width - spritecachedinfo[lumpoff].offset) * this_scale;
offset = FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width - spritecachedinfo[lumpoff].offset) * this_scale;
else
tx -= FIXED_TO_FLOAT(spritecachedinfo[lumpoff].offset) * this_scale;
offset = FIXED_TO_FLOAT(spritecachedinfo[lumpoff].offset) * this_scale;
z1 = tz - (offset * ang_scalez);
tx -= offset * ang_scale;
// project x
x1 = gr_windowcenterx + (tx * gr_centerx / tz);
@ -5151,7 +5186,14 @@ static void HWR_ProjectSprite(mobj_t *thing)
x1 = tx;
tx += FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width) * this_scale;
offset = FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width) * this_scale;
z2 = z1 + (offset * ang_scalez);
tx += offset * ang_scale;
if (papersprite && max(z1, z2) < ZCLIP_PLANE)
return;
x2 = gr_windowcenterx + (tx * gr_centerx / tz);
if (thing->eflags & MFE_VERTICALFLIP)
@ -5200,6 +5242,8 @@ static void HWR_ProjectSprite(mobj_t *thing)
vis->patchlumpnum = sprframe->lumppat[rot];
vis->flip = flip;
vis->mobj = thing;
vis->z1 = z1;
vis->z2 = z2;
//Hurdler: 25/04/2000: now support colormap in hardware mode
if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash"

View file

@ -1836,7 +1836,7 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value)
}
}
static inline void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, UINT32 duration, UINT32 tics, md2_frame_t *nextframe, FTransform *pos, float scale, UINT8 flipped, UINT8 *color)
static void DrawMD2Ex(INT32 *gl_cmd_buffer, md2_frame_t *frame, UINT32 duration, UINT32 tics, md2_frame_t *nextframe, FTransform *pos, float scale, UINT8 flipped, UINT8 *color)
{
INT32 val, count, pindex;
GLfloat s, t;

View file

@ -3031,12 +3031,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
if (player->speed > 0 && cmd->forwardmove < 0 && player->mo->friction == 59392)
player->mo->friction += 1608;
// Splitscreen camera
if (splitscreen && player == &players[consoleplayer])
CV_SetValue(&cv_cam_dist, 190);
if (splitscreen && player == &players[secondarydisplayplayer])
CV_SetValue(&cv_cam2_dist, 190);
K_KartDrift(player, onground);
// Quick Turning

View file

@ -1054,7 +1054,7 @@ void OP_NightsObjectplace(player_t *player)
if (!OP_HeightOkay(player, false))
return;
if (player->mo->target->flags & MF_AMBUSH)
if (player->mo->target->flags2 & MF2_AMBUSH)
angle = (UINT16)player->anotherflyangle;
else
{

View file

@ -3842,6 +3842,7 @@ static void M_ChangeLevel(INT32 choice)
static void M_ConfirmSpectate(INT32 choice)
{
(void)choice;
// We allow switching to spectator even if team changing is not allowed
M_ClearMenus(true);
COM_ImmedExecute("changeteam spectator");
}
@ -3849,6 +3850,11 @@ static void M_ConfirmSpectate(INT32 choice)
static void M_ConfirmEnterGame(INT32 choice)
{
(void)choice;
if (!cv_allowteamchange.value)
{
M_StartMessage(M_GetText("The server is not allowing\nteam changes at this time.\nPress a key.\n"), NULL, MM_NOTHING);
return;
}
M_ClearMenus(true);
COM_ImmedExecute("changeteam playing");
}

View file

@ -585,7 +585,7 @@ static const char *Newsnapshotfile(const char *pathname, const char *ext)
i += add * result;
if (add < 0 || add > 9999)
if (i < 0 || i > 9999)
return NULL;
}

View file

@ -1111,7 +1111,7 @@ void A_JetJawChomp(mobj_t *actor)
if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)
|| actor->target->health <= 0 || !P_CheckSight(actor, actor->target))
{
P_SetMobjState(actor, actor->info->spawnstate);
P_SetMobjStateNF(actor, actor->info->spawnstate);
return;
}
@ -2634,7 +2634,7 @@ for (i = cvar.value; i; --i) spawnchance[numchoices++] = type
newbox = spawnchance[P_RandomKey(numchoices)];
item = mobjinfo[newbox].damage;
remains->flags &= ~MF_AMBUSH;
remains->flags2 &= ~MF2_AMBUSH;
break;
}
default:
@ -3454,7 +3454,7 @@ void A_BubbleSpawn(mobj_t *actor)
}
actor->flags2 &= ~MF2_DONTDRAW;
if (!(actor->flags & MF_AMBUSH))
if (!(actor->flags2 & MF2_AMBUSH))
{
// Quick! Look through players!
// Don't spawn bubbles unless a player is relatively close by (var2).
@ -3502,7 +3502,7 @@ void A_FanBubbleSpawn(mobj_t *actor)
if (!(actor->eflags & MFE_UNDERWATER))
return;
if (!(actor->flags & MF_AMBUSH))
if (!(actor->flags2 & MF2_AMBUSH))
{
// Quick! Look through players!
// Don't spawn bubbles unless a player is relatively close by (var2).
@ -4120,7 +4120,7 @@ void A_JetChase(mobj_t *actor)
return;
#endif
if (actor->flags & MF_AMBUSH)
if (actor->flags2 & MF2_AMBUSH)
return;
if (actor->z >= actor->waterbottom && actor->watertop > actor->floorz
@ -5013,7 +5013,7 @@ void A_SlingAppear(mobj_t *actor)
if (firsttime)
{
// This is the outermost link in the chain
spawnee->flags |= MF_AMBUSH;
spawnee->flags2 |= MF2_AMBUSH;
firsttime = false;
}
@ -5998,7 +5998,7 @@ void A_Boss2Chase(mobj_t *actor)
{
actor->watertop = -actor->watertop;
actor->extravalue1 = 18;
if (actor->flags & MF_AMBUSH)
if (actor->flags2 & MF2_AMBUSH)
actor->extravalue1 -= (actor->info->spawnhealth - actor->health)*2;
actor->extravalue2 = actor->extravalue1;
}
@ -6024,7 +6024,7 @@ void A_Boss2Chase(mobj_t *actor)
else
{
// Only speed up if you have the 'Deaf' flag.
if (actor->flags & MF_AMBUSH)
if (actor->flags2 & MF2_AMBUSH)
speedvar = actor->health;
else
speedvar = actor->info->spawnhealth;
@ -6615,7 +6615,7 @@ void A_BuzzFly(mobj_t *actor)
if (LUA_CallAction("A_BuzzFly", actor))
return;
#endif
if (actor->flags & MF_AMBUSH)
if (actor->flags2 & MF2_AMBUSH)
return;
if (actor->reactiontime)
@ -6755,7 +6755,7 @@ void A_GuardChase(mobj_t *actor)
return; // got a new target
// chase towards player
if (--actor->movecount < 0 || !P_Move(actor, (actor->flags & MF_AMBUSH) ? actor->info->speed * 2 : actor->info->speed))
if (--actor->movecount < 0 || !P_Move(actor, (actor->flags2 & MF2_AMBUSH) ? actor->info->speed * 2 : actor->info->speed))
{
P_NewChaseDir(actor);
actor->movecount += 5; // Increase tics before change in direction allowed.
@ -8139,7 +8139,7 @@ void A_ItemPop(mobj_t *actor)
else if (cv_debug && !(actor->target && actor->target->player))
CONS_Printf("ERROR: Powerup has no target!\n");
remains->flags &= ~MF_AMBUSH;
remains->flags2 &= ~MF2_AMBUSH;
P_RemoveMobj(actor);
}

View file

@ -1352,7 +1352,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
case MT_SMALLMACECHAIN:
case MT_BIGMACECHAIN:
// Is this the last link in the chain?
if (toucher->momz > 0 || !(special->flags & MF_AMBUSH)
if (toucher->momz > 0 || !(special->flags2 & MF2_AMBUSH)
|| (player->pflags & PF_ITEMHANG) || (player->pflags & PF_MACESPIN))
return;

View file

@ -492,6 +492,73 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist)
return true; // didn't hit it
if (thing->flags & MF_PAPERCOLLISION) // CAUTION! Very easy to get stuck inside MF_SOLID objects. Giving the player MF_PAPERCOLLISION is a bad idea unless you know what you're doing.
{
fixed_t cosradius, sinradius;
vertex_t v1, v2; // fake vertexes
line_t junk; // fake linedef
cosradius = FixedMul(thing->radius, FINECOSINE(thing->angle>>ANGLETOFINESHIFT));
sinradius = FixedMul(thing->radius, FINESINE(thing->angle>>ANGLETOFINESHIFT));
v1.x = thing->x - cosradius;
v1.y = thing->y - sinradius;
v2.x = thing->x + cosradius;
v2.y = thing->y + sinradius;
junk.v1 = &v1;
junk.v2 = &v2;
junk.dx = v2.x - v1.x;
junk.dy = v2.y - v1.y;
if (tmthing->flags & MF_PAPERCOLLISION) // more strenuous checking to prevent clipping issues
{
INT32 check1, check2, check3, check4;
cosradius = FixedMul(tmthing->radius, FINECOSINE(tmthing->angle>>ANGLETOFINESHIFT));
sinradius = FixedMul(tmthing->radius, FINESINE(tmthing->angle>>ANGLETOFINESHIFT));
check1 = P_PointOnLineSide(tmx - cosradius, tmy - sinradius, &junk);
check2 = P_PointOnLineSide(tmx + cosradius, tmy + sinradius, &junk);
check3 = P_PointOnLineSide(tmx + tmthing->momx - cosradius, tmy + tmthing->momy - sinradius, &junk);
check4 = P_PointOnLineSide(tmx + tmthing->momx + cosradius, tmy + tmthing->momy + sinradius, &junk);
if ((check1 == check2) && (check2 == check3) && (check3 == check4))
return true; // the line doesn't cross between collider's start or end
}
else
{
if ((P_PointOnLineSide(tmx - tmthing->radius, tmy - tmthing->radius, &junk)
== P_PointOnLineSide(tmx + tmthing->radius, tmy + tmthing->radius, &junk))
&& (P_PointOnLineSide(tmx + tmthing->radius, tmy - tmthing->radius, &junk)
== P_PointOnLineSide(tmx - tmthing->radius, tmy + tmthing->radius, &junk)))
return true; // the line doesn't cross between either pair of opposite corners
}
}
else if (tmthing->flags & MF_PAPERCOLLISION)
{
fixed_t cosradius, sinradius;
vertex_t v1, v2; // fake vertexes
line_t junk; // fake linedef
cosradius = FixedMul(tmthing->radius, FINECOSINE(tmthing->angle>>ANGLETOFINESHIFT));
sinradius = FixedMul(tmthing->radius, FINESINE(tmthing->angle>>ANGLETOFINESHIFT));
v1.x = tmx - cosradius;
v1.y = tmy - sinradius;
v2.x = tmx + cosradius;
v2.y = tmy + sinradius;
junk.v1 = &v1;
junk.v2 = &v2;
junk.dx = v2.x - v1.x;
junk.dy = v2.y - v1.y;
// no need to check whether thing has MF_PAPERCOLLISION, since checked above
if ((P_PointOnLineSide(thing->x - thing->radius, thing->y - thing->radius, &junk)
== P_PointOnLineSide(thing->x + thing->radius, thing->y + thing->radius, &junk))
&& (P_PointOnLineSide(thing->x + thing->radius, thing->y - thing->radius, &junk)
== P_PointOnLineSide(thing->x - thing->radius, thing->y + thing->radius, &junk)))
return true; // the line doesn't cross between either pair of opposite corners
}
#ifdef HAVE_BLUA
{
UINT8 shouldCollide = LUAh_MobjCollide(thing, tmthing); // checks hook for thing's type
@ -1717,6 +1784,17 @@ static boolean PIT_CheckLine(line_t *ld)
if (P_BoxOnLineSide(tmbbox, ld) != -1)
return true;
if (tmthing->flags & MF_PAPERCOLLISION) // Caution! Turning whilst up against a wall will get you stuck. You probably shouldn't give the player this flag.
{
fixed_t cosradius, sinradius;
cosradius = FixedMul(tmthing->radius, FINECOSINE(tmthing->angle>>ANGLETOFINESHIFT));
sinradius = FixedMul(tmthing->radius, FINESINE(tmthing->angle>>ANGLETOFINESHIFT));
if (P_PointOnLineSide(tmx - cosradius, tmy - sinradius, ld)
== P_PointOnLineSide(tmx + cosradius, tmy + sinradius, ld))
return true; // the line doesn't cross between collider's start or end
}
// A line has been hit
// The moving thing's destination position will cross

View file

@ -2525,7 +2525,7 @@ static boolean P_ZMovement(mobj_t *mo)
&& abs(mom.y) < FixedMul(STOPSPEED, mo->scale)
&& abs(mom.z) < FixedMul(STOPSPEED*3, mo->scale))
{
if (mo->flags & MF_AMBUSH)
if (mo->flags2 & MF2_AMBUSH)
{
// If deafed, give the tumbleweed another random kick if it runs out of steam.
mom.z += P_MobjFlip(mo)*FixedMul(6*FRACUNIT, mo->scale);
@ -6724,7 +6724,7 @@ void P_MobjThinker(mobj_t *mobj)
flame->angle = mobj->angle;
if (mobj->flags & MF_AMBUSH) // Wave up and down instead of side-to-side
if (mobj->flags2 & MF2_AMBUSH) // Wave up and down instead of side-to-side
flame->momz = mobj->fuse << (FRACBITS-2);
else
flame->angle += FixedAngle(mobj->fuse*FRACUNIT);
@ -6759,7 +6759,7 @@ void P_MobjThinker(mobj_t *mobj)
strength -= ((20*FRACUNIT)/16)*mobj->movedir;
// If deaf'd, the object spawns on the ceiling.
if (mobj->flags & MF_AMBUSH)
if (mobj->flags2 & MF2_AMBUSH)
{
mobj->z = mobj->ceilingz-mobj->height;
flame->momz = -strength;
@ -7804,7 +7804,7 @@ void P_MobjThinker(mobj_t *mobj)
case MT_EGGMANBOX: // Eggman box
case MT_GRAVITYBOX: // Gravity box
case MT_QUESTIONBOX:
if ((mobj->flags & MF_AMBUSH || mobj->flags2 & MF2_STRONGBOX) && mobj->type != MT_QUESTIONBOX)
if ((mobj->flags2 & MF2_AMBUSH || mobj->flags2 & MF2_STRONGBOX) && mobj->type != MT_QUESTIONBOX)
{
mobjtype_t spawnchance[64];
INT32 numchoices = 0, i = 0;
@ -7832,11 +7832,7 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s
i = P_RandomKey(numchoices); // Gotta love those random numbers!
newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, spawnchance[i]);
// If the monitor respawns randomly, transfer the flag.
if (mobj->flags & MF_AMBUSH)
newmobj->flags |= MF_AMBUSH;
// Transfer flags2 (strongbox, objectflip)
// Transfer flags2 (strongbox, objectflip, ambush)
newmobj->flags2 = mobj->flags2;
}
else
@ -9786,7 +9782,7 @@ ML_NOCLIMB : Direction not controllable
if (firsttime)
{
// This is the outermost link in the chain
spawnee->flags |= MF_AMBUSH;
spawnee->flags2 |= MF2_AMBUSH;
firsttime = false;
}
@ -9858,7 +9854,7 @@ ML_NOCLIMB : Direction not controllable
{
// Inverted if uppermost bit is set
if (mthing->angle & 16384)
mobj->flags |= MF_AMBUSH;
mobj->flags2 |= MF2_AMBUSH;
if (mthing->angle > 0)
mobj->radius = (mthing->angle & 16383)*FRACUNIT;
@ -10039,7 +10035,7 @@ ML_NOCLIMB : Direction not controllable
mthing->type == mobjinfo[MT_YELLOWTV].doomednum || mthing->type == mobjinfo[MT_BLUETV].doomednum ||
mthing->type == mobjinfo[MT_BLACKTV].doomednum || mthing->type == mobjinfo[MT_PITYTV].doomednum ||
mthing->type == mobjinfo[MT_RECYCLETV].doomednum || mthing->type == mobjinfo[MT_MIXUPBOX].doomednum)
mobj->flags |= MF_AMBUSH;
mobj->flags2 |= MF2_AMBUSH;
}
else if (mthing->type != mobjinfo[MT_AXIS].doomednum &&
@ -10047,7 +10043,7 @@ ML_NOCLIMB : Direction not controllable
mthing->type != mobjinfo[MT_AXISTRANSFERLINE].doomednum &&
mthing->type != mobjinfo[MT_NIGHTSBUMPER].doomednum &&
mthing->type != mobjinfo[MT_STARPOST].doomednum)
mobj->flags |= MF_AMBUSH;
mobj->flags2 |= MF2_AMBUSH;
}
if (mthing->options & MTF_OBJECTSPECIAL)
@ -10386,7 +10382,7 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
P_SetMobjState(mobj, mobj->info->seestate);
mobj->angle = FixedAngle(mthing->angle*FRACUNIT);
mobj->flags |= MF_AMBUSH;
mobj->flags2 |= MF2_AMBUSH;
mthing->mobj = mobj;
}
// All manners of rings and coins
@ -10463,7 +10459,7 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
}
mobj->angle = FixedAngle(mthing->angle*FRACUNIT);
mobj->flags |= MF_AMBUSH;
mobj->flags2 |= MF2_AMBUSH;
mthing->mobj = mobj;
}
// ***
@ -10519,7 +10515,7 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
mobj->angle = FixedAngle(mthing->angle*FRACUNIT);
if (mthing->options & MTF_AMBUSH)
mobj->flags |= MF_AMBUSH;
mobj->flags2 |= MF2_AMBUSH;
}
}
// Diagonal rings (handles both types)
@ -10577,7 +10573,7 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing)
mobj->angle = FixedAngle(mthing->angle*FRACUNIT);
if (mthing->options & MTF_AMBUSH)
mobj->flags |= MF_AMBUSH;
mobj->flags2 |= MF2_AMBUSH;
}
}
// Rings of items (all six of them)

View file

@ -107,8 +107,8 @@ typedef enum
MF_NOSECTOR = 1<<3,
// Don't use the blocklinks (inert but displayable)
MF_NOBLOCKMAP = 1<<4,
// Not to be activated by sound, deaf monster.
MF_AMBUSH = 1<<5,
// Thin, paper-like collision bound (for visual equivalent, see FF_PAPERSPRITE)
MF_PAPERCOLLISION = 1<<5,
// You can push this object. It can activate switches and things by pushing it on top.
MF_PUSHABLE = 1<<6,
// Object is a boss.
@ -193,6 +193,7 @@ typedef enum
MF2_BOSSNOTRAP = 1<<25, // No Egg Trap after boss
MF2_BOSSFLEE = 1<<26, // Boss is fleeing!
MF2_BOSSDEAD = 1<<27, // Boss is dead! (Not necessarily fleeing, if a fleeing point doesn't exist.)
MF2_AMBUSH = 1<<28, // Alternate behaviour typically set by MTF_AMBUSH
// free: to and including 1<<31
} mobjflag2_t;

View file

@ -36,7 +36,9 @@
#endif
/// \brief Frame flags: only the frame number
#define FF_FRAMEMASK 0x3fff
#define FF_FRAMEMASK 0x1ff
/// \brief Frame flags: Thin, paper-like sprite (for collision equivalent, see MF_PAPERCOLLISION)
#define FF_PAPERSPRITE 0x800
/// \brief Frame flags: Simple stateless animation
#define FF_ANIMATE 0x4000
/// \brief Frame flags: frame always appears full bright

View file

@ -2547,8 +2547,9 @@ boolean P_SetupLevel(boolean skipprecip)
if (!dedicated)
{
if (!cv_cam_speed.changed)
CV_Set(&cv_cam_speed, cv_cam_speed.defaultvalue);
// Salt: CV_ClearChangedFlags() messes with your settings :(
/*if (!cv_cam_speed.changed)
CV_Set(&cv_cam_speed, cv_cam_speed.defaultvalue);*/
if (!cv_chasecam.changed)
CV_SetValue(&cv_chasecam, chase);
@ -2851,20 +2852,22 @@ boolean P_SetupLevel(boolean skipprecip)
}
}
if (!cv_cam_height.changed)
// Salt: CV_ClearChangedFlags() messes with your settings :(
/*if (!cv_cam_height.changed)
CV_Set(&cv_cam_height, cv_cam_height.defaultvalue);
if (!cv_cam_dist.changed)
CV_Set(&cv_cam_dist, cv_cam_dist.defaultvalue);
if (!cv_cam_rotate.changed)
CV_Set(&cv_cam_rotate, cv_cam_rotate.defaultvalue);
if (!cv_cam2_height.changed)
CV_Set(&cv_cam2_height, cv_cam2_height.defaultvalue);
if (!cv_cam_dist.changed)
CV_Set(&cv_cam_dist, cv_cam_dist.defaultvalue);
if (!cv_cam2_dist.changed)
CV_Set(&cv_cam2_dist, cv_cam2_dist.defaultvalue);
CV_Set(&cv_cam2_dist, cv_cam2_dist.defaultvalue);*/
// Though, I don't think anyone would care about cam_rotate being reset back to the only value that makes sense :P
if (!cv_cam_rotate.changed)
CV_Set(&cv_cam_rotate, cv_cam_rotate.defaultvalue);
if (!cv_cam2_rotate.changed)
CV_Set(&cv_cam2_rotate, cv_cam2_rotate.defaultvalue);

View file

@ -3044,7 +3044,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
case 443: // Calls a named Lua function
#ifdef HAVE_BLUA
LUAh_LinedefExecute(line, mo, callsec);
if (line->text)
LUAh_LinedefExecute(line, mo, callsec);
else
CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in the front texture fields)\n", sizeu1(line-lines));
#else
CONS_Alert(CONS_ERROR, "The map is trying to run a Lua script, but this exe was not compiled with Lua support!\n");
#endif

View file

@ -631,7 +631,7 @@ static void P_DeNightserizePlayer(player_t *player)
if (!(mo2->type == MT_NIGHTSDRONE))
continue;
if (mo2->flags & MF_AMBUSH)
if (mo2->flags2 & MF2_AMBUSH)
P_DamageMobj(player->mo, NULL, NULL, 10000);
break;
@ -5092,7 +5092,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad
boolean transfer1last = false;
boolean transfer2last = false;
vertex_t vertices[4];
fixed_t truexspeed = xspeed*(!(player->pflags & PF_TRANSFERTOCLOSEST) && player->mo->target->flags & MF_AMBUSH ? -1 : 1);
fixed_t truexspeed = xspeed*(!(player->pflags & PF_TRANSFERTOCLOSEST) && player->mo->target->flags2 & MF2_AMBUSH ? -1 : 1);
// Find next waypoint
for (th = thinkercap.next; th != &thinkercap; th = th->next)
@ -5757,7 +5757,7 @@ static void P_NiGHTSMovement(player_t *player)
// The 'ambush' flag says you should rotate
// the other way around the axis.
if (player->mo->target->flags & MF_AMBUSH)
if (player->mo->target->flags2 & MF2_AMBUSH)
backwardaxis = true;
player->angle_pos = R_PointToAngle2(player->mo->target->x, player->mo->target->y, player->mo->x, player->mo->y);
@ -8063,18 +8063,18 @@ static CV_PossibleValue_t CV_CamSpeed[] = {{0, "MIN"}, {1*FRACUNIT, "MAX"}, {0,
static CV_PossibleValue_t rotation_cons_t[] = {{1, "MIN"}, {45, "MAX"}, {0, NULL}};
static CV_PossibleValue_t CV_CamRotate[] = {{-720, "MIN"}, {720, "MAX"}, {0, NULL}};
consvar_t cv_cam_dist = {"cam_dist", "128", CV_FLOAT, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_height = {"cam_height", "40", CV_FLOAT, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_dist = {"cam_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_height = {"cam_height", "50", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_still = {"cam_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_speed = {"cam_speed", "0.25", CV_FLOAT, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_speed = {"cam_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_rotate = {"cam_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_rotspeed = {"cam_rotspeed", "10", 0, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_dist = {"cam2_dist", "128", CV_FLOAT, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_height = {"cam2_height", "40", CV_FLOAT, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam_rotspeed = {"cam_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_dist = {"cam2_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_height = {"cam2_height", "50", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_still = {"cam2_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_speed = {"cam2_speed", "0.25", CV_FLOAT, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_speed = {"cam2_speed", "0.3", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_rotate = {"cam2_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate2_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_rotspeed = {"cam2_rotspeed", "10", 0, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_cam2_rotspeed = {"cam2_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
fixed_t t_cam_dist = -42;
fixed_t t_cam_height = -42;
@ -8128,7 +8128,7 @@ void P_ResetCamera(player_t *player, camera_t *thiscam)
boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcalled)
{
angle_t angle = 0, focusangle = 0, focusaiming = 0;
fixed_t x, y, z, dist, checkdist, viewpointx, viewpointy, camspeed, camdist, camheight, pviewheight;
fixed_t x, y, z, dist, height, checkdist, viewpointx, viewpointy, camspeed, camdist, camheight, pviewheight;
INT32 camrotate;
boolean camstill, cameranoclip;
mobj_t *mo;
@ -8250,7 +8250,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
}
else if (player->mo->target)
{
if (player->mo->target->flags & MF_AMBUSH)
if (player->mo->target->flags2 & MF2_AMBUSH)
angle = R_PointToAngle2(player->mo->target->x, player->mo->target->y, player->mo->x, player->mo->y);
else
angle = R_PointToAngle2(player->mo->x, player->mo->y, player->mo->target->x, player->mo->target->y);
@ -8354,6 +8354,8 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
}
*/
height = camheight;
// sets ideal cam pos
if (twodlevel || (mo->flags2 & MF2_TWOD))
dist = 480<<FRACBITS;
@ -8363,6 +8365,20 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
{
dist = camdist;
// x1.5 dist for splitscreen
if (splitscreen)
{
dist = FixedMul(dist, 3*FRACUNIT/2);
height = FixedMul(height, 3*FRACUNIT/2);
}
// x1.2 dist for analog
if (P_AnalogMove(player))
{
dist = FixedMul(dist, 6*FRACUNIT/5);
height = FixedMul(height, 6*FRACUNIT/5);
}
if (player->climbing || player->exiting || player->playerstate == PST_DEAD || (player->pflags & (PF_MACESPIN|PF_ITEMHANG|PF_ROPEHANG)))
dist <<= 1;
}

View file

@ -210,7 +210,7 @@ void R_PortalClearClipSegs(INT32 start, INT32 end)
//
// It assumes that Doom has already ruled out a door being closed because
// of front-back closure (e.g. front floor is taller than back ceiling).
static inline INT32 R_DoorClosed(void)
static INT32 R_DoorClosed(void)
{
return

View file

@ -722,23 +722,35 @@ typedef struct
#pragma pack()
#endif
typedef enum
{
SRF_SINGLE = 0, // 0-angle for all rotations
SRF_3D = 1, // Angles 1-8
SRF_LEFT = 2, // Left side has single patch
SRF_RIGHT = 4, // Right side has single patch
SRF_2D = 6, // SRF_LEFT|SRF_RIGHT
SRF_NONE = 0xff // Initial value
} spriterotateflags_t; // SRF's up!
//
// Sprites are patches with a special naming convention so they can be
// recognized by R_InitSprites.
// The base name is NNNNFx or NNNNFxFx, with x indicating the rotation,
// x = 0, 1-7.
// x = 0, 1-8, L/R
// The sprite and frame specified by a thing_t is range checked at run time.
// A sprite is a patch_t that is assumed to represent a three dimensional
// object and may have multiple rotations predrawn.
// Horizontal flipping is used to save space, thus NNNNF2F5 defines a mirrored patch.
// Some sprites will only have one picture used for all views: NNNNF0
// Some sprites will take the entirety of the left side: NNNNFL
// Or the right side: NNNNFR
// Or both, mirrored: NNNNFLFR
//
typedef struct
{
// If false use 0 for any position.
// Note: as eight entries are available, we might as well insert the same
// name eight times.
UINT8 rotate;
UINT8 rotate; // see spriterotateflags_t above
// Lump to use for view angles 0-7.
lumpnum_t lumppat[8]; // lump number 16 : 16 wad : lump

View file

@ -101,7 +101,7 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
lumppat <<= 16;
lumppat += lump;
if (frame >= 64 || rotation > 8)
if (frame >= 64 || !(R_ValidSpriteAngle(rotation)))
I_Error("R_InstallSpriteLump: Bad frame characters in lump %s", W_CheckNameForNum(lumppat));
if (maxframe ==(size_t)-1 || frame > maxframe)
@ -110,31 +110,65 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch
if (rotation == 0)
{
// the lump should be used for all rotations
if (sprtemp[frame].rotate == 0)
if (sprtemp[frame].rotate == SRF_SINGLE)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple rot = 0 lump\n", spritename, cn);
if (sprtemp[frame].rotate == 1)
else if (sprtemp[frame].rotate != SRF_NONE) // Let's complain for both 1-8 and L/R rotations.
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has rotations and a rot = 0 lump\n", spritename, cn);
sprtemp[frame].rotate = 0;
sprtemp[frame].rotate = SRF_SINGLE;
for (r = 0; r < 8; r++)
{
sprtemp[frame].lumppat[r] = lumppat;
sprtemp[frame].lumpid[r] = lumpid;
}
sprtemp[frame].flip = flipped ? UINT8_MAX : 0;
sprtemp[frame].flip = flipped ? UINT8_MAX : 0; // 11111111 in binary
return;
}
if (rotation == ROT_L || rotation == ROT_R)
{
UINT8 rightfactor = ((rotation == ROT_R) ? 4 : 0);
// the lump should be used for half of all rotations
if (sprtemp[frame].rotate == SRF_SINGLE)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has L/R rotations and a rot = 0 lump\n", spritename, cn);
else if (sprtemp[frame].rotate == SRF_3D)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8 rotations\n", spritename, cn);
// Let's not complain about multiple L/R rotations. It's not worth the effort.
if (sprtemp[frame].rotate == SRF_NONE)
sprtemp[frame].rotate = SRF_SINGLE;
sprtemp[frame].rotate |= ((rotation == ROT_R) ? SRF_RIGHT : SRF_LEFT);
if (sprtemp[frame].rotate == (SRF_3D|SRF_2D))
sprtemp[frame].rotate = SRF_2D; // SRF_3D|SRF_2D being enabled at the same time doesn't HURT in the current sprite angle implementation, but it DOES mean more to check in some of the helper functions. Let's not allow this scenario to happen.
for (r = 0; r < 4; r++) // Thanks to R_PrecacheLevel, we can't leave sprtemp[*].lumppat[*] == LUMPERROR... so we load into the front/back angle too.
{
sprtemp[frame].lumppat[r + rightfactor] = lumppat;
sprtemp[frame].lumpid[r + rightfactor] = lumpid;
}
sprtemp[frame].flip |= (flipped ? (0x0F << rightfactor) : 0); // 00001111 or 11110000 in binary, depending on rotation being ROT_L or ROT_R
return;
}
// the lump is only used for one rotation
if (sprtemp[frame].rotate == 0)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has rotations and a rot = 0 lump\n", spritename, cn);
sprtemp[frame].rotate = 1;
if (sprtemp[frame].rotate == SRF_SINGLE)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has 1-8 rotations and a rot = 0 lump\n", spritename, cn);
else if ((sprtemp[frame].rotate != SRF_3D) && (sprtemp[frame].rotate != SRF_NONE))
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8 rotations\n", spritename, cn);
// make 0 based
rotation--;
if (rotation == 0 || rotation == 4) // Front or back...
sprtemp[frame].rotate = SRF_3D; // Prevent L and R changeover
else if (rotation > 3) // Right side
sprtemp[frame].rotate = (SRF_3D | (sprtemp[frame].rotate & SRF_LEFT)); // Continue allowing L frame changeover
else // if (rotation <= 3) // Left side
sprtemp[frame].rotate = (SRF_3D | (sprtemp[frame].rotate & SRF_RIGHT)); // Continue allowing R frame changeover
if (sprtemp[frame].lumppat[rotation] != LUMPERROR)
CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s: %c%c has two lumps mapped to it\n", spritename, cn, '1'+rotation);
@ -196,7 +230,7 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef,
frame = R_Char2Frame(lumpinfo[l].name[4]);
rotation = (UINT8)(lumpinfo[l].name[5] - '0');
if (frame >= 64 || rotation > 8) // Give an actual NAME error -_-...
if (frame >= 64 || !(R_ValidSpriteAngle(rotation))) // Give an actual NAME error -_-...
{
CONS_Alert(CONS_WARNING, M_GetText("Bad sprite name: %s\n"), W_CheckNameForNumPwad(wadnum,l));
continue;
@ -279,16 +313,23 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef,
{
switch (sprtemp[frame].rotate)
{
case 0xff:
case SRF_NONE:
// no rotations were found for that frame at all
I_Error("R_AddSingleSpriteDef: No patches found for %.4s frame %c", sprname, R_Frame2Char(frame));
break;
case 0:
case SRF_SINGLE:
// only the first rotation is needed
break;
case 1:
case SRF_2D: // both Left and Right rotations
// we test to see whether the left and right slots are present
if ((sprtemp[frame].lumppat[2] == LUMPERROR) || (sprtemp[frame].lumppat[6] == LUMPERROR))
I_Error("R_AddSingleSpriteDef: Sprite %s frame %c is missing rotations",
sprname, R_Frame2Char(frame));
break;
default:
// must have all 8 frames
for (rotation = 0; rotation < 8; rotation++)
// we test the patch lump, or the id lump whatever
@ -755,11 +796,18 @@ static void R_DrawVisSprite(vissprite_t *vis)
if (overflow_test < 0) overflow_test = -overflow_test;
if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // fixed point mult would overflow
if (vis->scalestep) // handles right edge too
{
overflow_test = (INT64)centeryfrac - (((INT64)vis->texturemid*(vis->scale + (vis->scalestep*(vis->x2 - vis->x1))))>>FRACBITS);
if (overflow_test < 0) overflow_test = -overflow_test;
if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // ditto
}
colfunc = basecolfunc; // hack: this isn't resetting properly somewhere.
dc_colormap = vis->colormap;
if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash"
{
// translate green skin to another color
// translate certain pixels to white
colfunc = transcolfunc;
if (vis->mobj->type == MT_CYBRAKDEMON)
dc_translation = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE);
@ -815,13 +863,10 @@ static void R_DrawVisSprite(vissprite_t *vis)
if (!dc_colormap)
dc_colormap = colormaps;
dc_iscale = FixedDiv(FRACUNIT, vis->scale);
dc_texturemid = vis->texturemid;
dc_texheight = 0;
frac = vis->startfrac;
spryscale = vis->scale;
sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
windowtop = windowbottom = sprbotscreen = INT32_MAX;
if (vis->mobj->skin && ((skin_t *)vis->mobj->skin)->flags & SF_HIRES)
@ -833,28 +878,29 @@ static void R_DrawVisSprite(vissprite_t *vis)
if (!vis->isScaled)
{
vis->scale = FixedMul(vis->scale, this_scale);
spryscale = vis->scale;
dc_iscale = FixedDiv(FRACUNIT, vis->scale);
vis->scalestep = FixedMul(vis->scalestep, this_scale);
vis->xiscale = FixedDiv(vis->xiscale,this_scale);
vis->isScaled = true;
}
dc_texturemid = FixedDiv(dc_texturemid,this_scale);
}
//Oh lordy, mercy me. Don't freak out if sprites go offscreen!
/*if (vis->xiscale > 0)
frac = FixedDiv(frac, this_scale);
else if (vis->x1 <= 0)
frac = (vis->x1 - vis->x2) * vis->xiscale;*/
spryscale = vis->scale;
if (!(vis->scalestep))
{
sprtopscreen = centeryfrac - FixedMul(dc_texturemid, spryscale);
//dc_hires = 1;
dc_iscale = FixedDiv(FRACUNIT, vis->scale);
}
x1 = vis->x1;
x2 = vis->x2;
if (vis->x1 < 0)
{
spryscale += vis->scalestep*(-vis->x1);
vis->x1 = 0;
}
if (vis->x2 >= vid.width)
vis->x2 = vid.width-1;
@ -870,10 +916,16 @@ static void R_DrawVisSprite(vissprite_t *vis)
#else
column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[frac>>FRACBITS]));
#endif
if (vis->scalestep)
{
sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale));
dc_iscale = (0xffffffffu / (unsigned)spryscale);
}
if (vis->vflip)
R_DrawFlippedMaskedColumn(column, patch->height);
else
R_DrawMaskedColumn(column);
spryscale += vis->scalestep;
}
colfunc = basecolfunc;
@ -892,12 +944,18 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis)
#endif
fixed_t frac;
patch_t *patch;
INT64 overflow_test;
//Fab : R_InitSprites now sets a wad lump number
patch = W_CacheLumpNum(vis->patch, PU_CACHE);
if (!patch)
return;
// Check for overflow
overflow_test = (INT64)centeryfrac - (((INT64)vis->texturemid*vis->scale)>>FRACBITS);
if (overflow_test < 0) overflow_test = -overflow_test;
if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // fixed point mult would overflow
if (vis->transmap)
{
colfunc = fuzzcolfunc;
@ -968,7 +1026,7 @@ static void R_SplitSprite(vissprite_t *sprite, mobj_t *thing)
if (testheight <= sprite->gz)
return;
cutfrac = (INT16)((centeryfrac - FixedMul(testheight - viewz, sprite->scale))>>FRACBITS);
cutfrac = (INT16)((centeryfrac - FixedMul(testheight - viewz, sprite->sortscale))>>FRACBITS);
if (cutfrac < 0)
continue;
if (cutfrac > viewheight)
@ -1041,7 +1099,7 @@ static void R_ProjectSprite(mobj_t *thing)
fixed_t tr_x, tr_y;
fixed_t gxt, gyt;
fixed_t tx, tz;
fixed_t xscale, yscale; //added : 02-02-98 : aaargll..if I were a math-guy!!!
fixed_t xscale, yscale, sortscale; //added : 02-02-98 : aaargll..if I were a math-guy!!!
INT32 x1, x2;
@ -1056,8 +1114,11 @@ static void R_ProjectSprite(mobj_t *thing)
vissprite_t *vis;
angle_t ang;
angle_t ang = 0; // gcc 4.6 and lower fix
fixed_t iscale;
fixed_t scalestep; // toast '16
fixed_t offset, offset2;
boolean papersprite = (thing->frame & FF_PAPERSPRITE);
//SoM: 3/17/2000
fixed_t gz, gzt;
@ -1065,6 +1126,8 @@ static void R_ProjectSprite(mobj_t *thing)
INT32 light = 0;
fixed_t this_scale = thing->scale;
fixed_t ang_scale = FRACUNIT;
// transform the origin point
tr_x = thing->x - viewx;
tr_y = thing->y - viewy;
@ -1075,7 +1138,7 @@ static void R_ProjectSprite(mobj_t *thing)
tz = gxt-gyt;
// thing is behind view plane?
if (tz < FixedMul(MINZ, this_scale))
if (!(papersprite) && (tz < FixedMul(MINZ, this_scale))) // papersprite clipping is handled later
return;
gxt = -FixedMul(tr_x, viewsin);
@ -1088,7 +1151,7 @@ static void R_ProjectSprite(mobj_t *thing)
// aspect ratio stuff
xscale = FixedDiv(projection, tz);
yscale = FixedDiv(projectiony, tz);
sortscale = FixedDiv(projectiony, tz);
// decide which patch to use for sprite relative to player
#ifdef RANGECHECK
@ -1130,22 +1193,36 @@ static void R_ProjectSprite(mobj_t *thing)
I_Error("R_ProjectSprite: sprframes NULL for sprite %d\n", thing->sprite);
#endif
if (sprframe->rotate)
if (sprframe->rotate != SRF_SINGLE || papersprite)
{
// choose a different rotation based on player view
ang = R_PointToAngle (thing->x, thing->y);
rot = (ang-thing->angle+ANGLE_202h)>>29;
//Fab: lumpid is the index for spritewidth,spriteoffset... tables
lump = sprframe->lumpid[rot];
flip = sprframe->flip & (1<<rot);
ang = R_PointToAngle (thing->x, thing->y) - thing->angle;
if (papersprite)
ang_scale = abs(FINESINE(ang>>ANGLETOFINESHIFT));
}
else
if (sprframe->rotate == SRF_SINGLE)
{
// use single rotation for all views
rot = 0; //Fab: for vis->patch below
lump = sprframe->lumpid[0]; //Fab: see note above
flip = sprframe->flip; // Will only be 0x00 or 0xFF
}
else
{
// choose a different rotation based on player view
//ang = R_PointToAngle (thing->x, thing->y) - thing->angle;
if ((ang < ANGLE_180) && (sprframe->rotate & SRF_RIGHT)) // See from right
rot = 6; // F7 slot
else if ((ang >= ANGLE_180) && (sprframe->rotate & SRF_LEFT)) // See from left
rot = 2; // F3 slot
else // Normal behaviour
rot = (ang+ANGLE_202h)>>29;
//Fab: lumpid is the index for spritewidth,spriteoffset... tables
lump = sprframe->lumpid[rot];
flip = sprframe->flip & (1<<rot);
}
I_Assert(lump < max_spritelumps);
@ -1154,22 +1231,77 @@ static void R_ProjectSprite(mobj_t *thing)
// calculate edges of the shape
if (flip)
tx -= FixedMul(spritecachedinfo[lump].width-spritecachedinfo[lump].offset, this_scale);
offset = spritecachedinfo[lump].offset - spritecachedinfo[lump].width;
else
tx -= FixedMul(spritecachedinfo[lump].offset, this_scale);
offset = -spritecachedinfo[lump].offset;
offset = FixedMul(offset, this_scale);
tx += FixedMul(offset, ang_scale);
x1 = (centerxfrac + FixedMul (tx,xscale)) >>FRACBITS;
// off the right side?
if (x1 > viewwidth)
return;
tx += FixedMul(spritecachedinfo[lump].width, this_scale);
offset2 = FixedMul(spritecachedinfo[lump].width, this_scale);
tx += FixedMul(offset2, ang_scale);
x2 = ((centerxfrac + FixedMul (tx,xscale)) >>FRACBITS) - 1;
// off the left side
if (x2 < 0)
return;
if (papersprite)
{
fixed_t yscale2, cosmul, sinmul, tz2;
INT32 range;
if (ang >= ANGLE_180)
{
offset *= -1;
offset2 *= -1;
}
cosmul = FINECOSINE(thing->angle>>ANGLETOFINESHIFT);
sinmul = FINESINE(thing->angle>>ANGLETOFINESHIFT);
tr_x += FixedMul(offset, cosmul);
tr_y += FixedMul(offset, sinmul);
gxt = FixedMul(tr_x, viewcos);
gyt = -FixedMul(tr_y, viewsin);
tz = gxt-gyt;
yscale = FixedDiv(projectiony, tz);
if (yscale < 64) return; // Fix some funky visuals
tr_x += FixedMul(offset2, cosmul);
tr_y += FixedMul(offset2, sinmul);
gxt = FixedMul(tr_x, viewcos);
gyt = -FixedMul(tr_y, viewsin);
tz2 = gxt-gyt;
yscale2 = FixedDiv(projectiony, tz2);
if (yscale2 < 64) return; // ditto
if (max(tz, tz2) < FixedMul(MINZ, this_scale)) // non-papersprite clipping is handled earlier
return;
if (x2 > x1)
range = (x2 - x1);
else
range = 1;
scalestep = (yscale2 - yscale)/range;
// The following two are alternate sorting methods which might be more applicable in some circumstances. TODO - maybe enable via MF2?
// sortscale = max(yscale, yscale2);
// sortscale = min(yscale, yscale2);
}
else
{
scalestep = 0;
yscale = sortscale;
}
xscale = FixedMul(xscale, ang_scale);
// PORTAL SPRITE CLIPPING
if (portalrender)
{
@ -1251,6 +1383,7 @@ static void R_ProjectSprite(mobj_t *thing)
vis->heightsec = heightsec; //SoM: 3/17/2000
vis->mobjflags = thing->flags;
vis->scale = yscale; //<<detailshift;
vis->sortscale = sortscale;
vis->dispoffset = thing->info->dispoffset; // Monster Iestyn: 23/11/15
vis->gx = thing->x;
vis->gy = thing->y;
@ -1260,6 +1393,7 @@ static void R_ProjectSprite(mobj_t *thing)
vis->pz = thing->z;
vis->pzt = vis->pz + vis->thingheight;
vis->texturemid = vis->gzt - viewz;
vis->scalestep = scalestep;
vis->mobj = thing; // Easy access! Tails 06-07-2002
@ -1277,8 +1411,8 @@ static void R_ProjectSprite(mobj_t *thing)
vis->xscale = xscale; //SoM: 4/17/2000
vis->sector = thing->subsector->sector;
vis->szt = (INT16)((centeryfrac - FixedMul(vis->gzt - viewz, yscale))>>FRACBITS);
vis->sz = (INT16)((centeryfrac - FixedMul(vis->gz - viewz, yscale))>>FRACBITS);
vis->szt = (INT16)((centeryfrac - FixedMul(vis->gzt - viewz, sortscale))>>FRACBITS);
vis->sz = (INT16)((centeryfrac - FixedMul(vis->gz - viewz, sortscale))>>FRACBITS);
vis->cut = SC_NONE;
if (thing->subsector->sector->numlights)
vis->extra_colormap = thing->subsector->sector->lightlist[light].extra_colormap;
@ -1299,7 +1433,10 @@ static void R_ProjectSprite(mobj_t *thing)
}
if (vis->x1 > x1)
{
vis->startfrac += FixedDiv(vis->xiscale, this_scale)*(vis->x1-x1);
vis->scale += scalestep*(vis->x1 - x1);
}
//Fab: lumppat is the lump number of the patch to use, this is different
// than lumpid for sprites-in-pwad : the graphics are patched
@ -1458,7 +1595,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
// store information in a vissprite
vis = R_NewVisSprite();
vis->scale = yscale; //<<detailshift;
vis->scale = vis->sortscale = yscale; //<<detailshift;
vis->dispoffset = 0; // Monster Iestyn: 23/11/15
vis->gx = thing->x;
vis->gy = thing->y;
@ -1468,6 +1605,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
vis->pz = thing->z;
vis->pzt = vis->pz + vis->thingheight;
vis->texturemid = vis->gzt - viewz;
vis->scalestep = 0;
vis->x1 = x1 < 0 ? 0 : x1;
vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
@ -1646,14 +1784,14 @@ void R_SortVisSprites(void)
bestscale = bestdispoffset = INT32_MAX;
for (ds = unsorted.next; ds != &unsorted; ds = ds->next)
{
if (ds->scale < bestscale)
if (ds->sortscale < bestscale)
{
bestscale = ds->scale;
bestscale = ds->sortscale;
bestdispoffset = ds->dispoffset;
best = ds;
}
// order visprites of same scale by dispoffset, smallest first
else if (ds->scale == bestscale && ds->dispoffset < bestdispoffset)
else if (ds->sortscale == bestscale && ds->dispoffset < bestdispoffset)
{
bestdispoffset = ds->dispoffset;
best = ds;
@ -1844,7 +1982,7 @@ static void R_CreateDrawNodes(void)
{
for (i = x1; i <= x2; i++)
{
if (r2->seg->frontscale[i] > rover->scale)
if (r2->seg->frontscale[i] > rover->sortscale)
break;
}
if (i > x2)
@ -1864,10 +2002,10 @@ static void R_CreateDrawNodes(void)
continue;
scale = r2->thickseg->scale1 > r2->thickseg->scale2 ? r2->thickseg->scale1 : r2->thickseg->scale2;
if (scale <= rover->scale)
if (scale <= rover->sortscale)
continue;
scale = r2->thickseg->scale1 + (r2->thickseg->scalestep * (sintersect - r2->thickseg->x1));
if (scale <= rover->scale)
if (scale <= rover->sortscale)
continue;
#ifdef ESLOPE
@ -1917,11 +2055,11 @@ static void R_CreateDrawNodes(void)
continue;
scale = r2->seg->scale1 > r2->seg->scale2 ? r2->seg->scale1 : r2->seg->scale2;
if (scale <= rover->scale)
if (scale <= rover->sortscale)
continue;
scale = r2->seg->scale1 + (r2->seg->scalestep * (sintersect - r2->seg->x1));
if (rover->scale < scale)
if (rover->sortscale < scale)
{
entry = R_CreateDrawNode(NULL);
(entry->prev = r2->prev)->next = entry;
@ -1937,8 +2075,8 @@ static void R_CreateDrawNodes(void)
if (r2->sprite->szt > rover->sz || r2->sprite->sz < rover->szt)
continue;
if (r2->sprite->scale > rover->scale
|| (r2->sprite->scale == rover->scale && r2->sprite->dispoffset > rover->dispoffset))
if (r2->sprite->sortscale > rover->sortscale
|| (r2->sprite->sortscale == rover->sortscale && r2->sprite->dispoffset > rover->dispoffset))
{
entry = R_CreateDrawNode(NULL);
(entry->prev = r2->prev)->next = entry;
@ -2091,8 +2229,8 @@ void R_ClipSprites(void)
scale = ds->scale2;
}
if (scale < spr->scale ||
(lowscale < spr->scale &&
if (scale < spr->sortscale ||
(lowscale < spr->sortscale &&
!R_PointOnSegSide (spr->gx, spr->gy, ds->curline)))
{
// masked mid texture?
@ -2143,7 +2281,7 @@ void R_ClipSprites(void)
fixed_t mh, h;
INT32 phs = viewplayer->mo->subsector->sector->heightsec;
if ((mh = sectors[spr->heightsec].floorheight) > spr->gz &&
(h = centeryfrac - FixedMul(mh -= viewz, spr->scale)) >= 0 &&
(h = centeryfrac - FixedMul(mh -= viewz, spr->sortscale)) >= 0 &&
(h >>= FRACBITS) < viewheight)
{
if (mh <= 0 || (phs != -1 && viewz > sectors[phs].floorheight))
@ -2161,7 +2299,7 @@ void R_ClipSprites(void)
}
if ((mh = sectors[spr->heightsec].ceilingheight) < spr->gzt &&
(h = centeryfrac - FixedMul(mh-viewz, spr->scale)) >= 0 &&
(h = centeryfrac - FixedMul(mh-viewz, spr->sortscale)) >= 0 &&
(h >>= FRACBITS) < viewheight)
{
if (phs != -1 && viewz >= sectors[phs].ceilingheight)

View file

@ -17,6 +17,10 @@
#include "sounds.h"
#include "r_plane.h"
// "Left" and "Right" character symbols for additional rotation functionality
#define ROT_L ('L' - '0')
#define ROT_R ('R' - '0')
// number of sprite lumps for spritewidth,offset,topoffset lookup tables
// Fab: this is a hack : should allocate the lookup tables per sprite
#define MAXVISSPRITES 2048 // added 2-2-98 was 128
@ -136,7 +140,8 @@ typedef struct vissprite_s
fixed_t pz, pzt; // physical bottom/top for sorting with 3D floors
fixed_t startfrac; // horizontal position of x1
fixed_t scale;
fixed_t scale, sortscale; // sortscale only differs from scale for flat sprites
fixed_t scalestep; // only for flat sprites, 0 otherwise
fixed_t xiscale; // negative if flipped
fixed_t texturemid;
@ -235,4 +240,9 @@ FUNCMATH FUNCINLINE static ATTRINLINE UINT8 R_Char2Frame(char cn)
#endif
}
FUNCMATH FUNCINLINE static ATTRINLINE boolean R_ValidSpriteAngle(UINT8 rotation)
{
return ((rotation <= 8) || (rotation == ROT_L) || (rotation == ROT_R));
}
#endif //__R_THINGS__

View file

@ -1214,7 +1214,7 @@
C01FCF4B08A954540054247B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CURRENT_PROJECT_VERSION = 2.1.17;
CURRENT_PROJECT_VERSION = 2.1.18;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
NORMALSRB2,
@ -1226,7 +1226,7 @@
C01FCF4C08A954540054247B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CURRENT_PROJECT_VERSION = 2.1.17;
CURRENT_PROJECT_VERSION = 2.1.18;
GCC_ENABLE_FIX_AND_CONTINUE = NO;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_PREPROCESSOR_DEFINITIONS = (

View file

@ -1214,7 +1214,7 @@
C01FCF4B08A954540054247B /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CURRENT_PROJECT_VERSION = 2.1.17;
CURRENT_PROJECT_VERSION = 2.1.18;
GCC_PREPROCESSOR_DEFINITIONS = (
"$(inherited)",
NORMALSRB2,
@ -1226,7 +1226,7 @@
C01FCF4C08A954540054247B /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CURRENT_PROJECT_VERSION = 2.1.17;
CURRENT_PROJECT_VERSION = 2.1.18;
GCC_ENABLE_FIX_AND_CONTINUE = NO;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
GCC_PREPROCESSOR_DEFINITIONS = (

View file

@ -758,79 +758,80 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c)
{
UINT8 *dest;
const UINT8 *deststop;
INT32 u, v, dupx, dupy;
if (rendermode == render_none)
return;
#ifdef HWRENDER
if (rendermode != render_soft && rendermode != render_none)
if (rendermode != render_soft && !con_startup)
{
HWR_DrawFill(x, y, w, h, c);
return;
}
#endif
dupx = vid.dupx;
dupy = vid.dupy;
if (!screens[0])
return;
if (c & V_NOSCALESTART)
{
dest = screens[0] + y*vid.width + x;
deststop = screens[0] + vid.rowbytes * vid.height;
}
else
if (!(c & V_NOSCALESTART))
{
INT32 dupx = vid.dupx, dupy = vid.dupy;
if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT)
{ // Clear the entire screen, from dest to deststop. Yes, this really works.
memset(screens[0], (UINT8)(c&255), vid.width * vid.height * vid.bpp);
return;
}
dest = screens[0] + y*dupy*vid.width + x*dupx;
deststop = screens[0] + vid.rowbytes * vid.height;
x *= dupx;
y *= dupy;
w *= dupx;
h *= dupy;
if (w == BASEVIDWIDTH)
w = vid.width;
else
w *= dupx;
if (h == BASEVIDHEIGHT)
h = vid.height;
else
h *= dupy;
if (x && y && x + w < vid.width && y + h < vid.height)
// Center it if necessary
if (vid.width != BASEVIDWIDTH * dupx)
{
// Center it if necessary
if (vid.width != BASEVIDWIDTH * dupx)
{
// dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx,
// so center this imaginary screen
if (c & V_SNAPTORIGHT)
dest += (vid.width - (BASEVIDWIDTH * dupx));
else if (!(c & V_SNAPTOLEFT))
dest += (vid.width - (BASEVIDWIDTH * dupx)) / 2;
}
if (vid.height != BASEVIDHEIGHT * dupy)
{
// same thing here
if (c & V_SNAPTOBOTTOM)
dest += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width;
else if (!(c & V_SNAPTOTOP))
dest += (vid.height - (BASEVIDHEIGHT * dupy)) * vid.width / 2;
}
// dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx,
// so center this imaginary screen
if (c & V_SNAPTORIGHT)
x += (vid.width - (BASEVIDWIDTH * dupx));
else if (!(c & V_SNAPTOLEFT))
x += (vid.width - (BASEVIDWIDTH * dupx)) / 2;
}
if (vid.height != BASEVIDHEIGHT * dupy)
{
// same thing here
if (c & V_SNAPTOBOTTOM)
y += (vid.height - (BASEVIDHEIGHT * dupy));
else if (!(c & V_SNAPTOTOP))
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2;
}
}
if (x >= vid.width || y >= vid.height)
return; // off the screen
if (x < 0)
{
w += x;
x = 0;
}
if (y < 0)
{
h += y;
y = 0;
}
if (w <= 0 || h <= 0)
return; // zero width/height wouldn't draw anything
if (x + w > vid.width)
w = vid.width - x;
if (y + h > vid.height)
h = vid.height - y;
dest = screens[0] + y*vid.width + x;
deststop = screens[0] + vid.rowbytes * vid.height;
c &= 255;
for (v = 0; v < h; v++, dest += vid.width)
for (u = 0; u < w; u++)
{
if (dest > deststop)
return;
dest[u] = (UINT8)c;
}
for (;(--h >= 0) && dest < deststop; dest += vid.width)
memset(dest, (UINT8)(c&255), w * vid.bpp);
}
//

View file

@ -133,6 +133,47 @@ void W_Shutdown(void)
static char filenamebuf[MAX_WADPATH];
// W_OpenWadFile
// Helper function for opening the WAD file.
// Returns the FILE * handle for the file, or NULL if not found or could not be opened
// If "useerrors" is true then print errors in the console, else just don't bother
// "filename" may be modified to have the correct path the actual file is located in, if necessary
FILE *W_OpenWadFile(const char **filename, boolean useerrors)
{
FILE *handle;
strncpy(filenamebuf, *filename, MAX_WADPATH);
filenamebuf[MAX_WADPATH - 1] = '\0';
*filename = filenamebuf;
// open wad file
if ((handle = fopen(*filename, "rb")) == NULL)
{
// If we failed to load the file with the path as specified by
// the user, strip the directories and search for the file.
nameonly(filenamebuf);
// If findfile finds the file, the full path will be returned
// in filenamebuf == *filename.
if (findfile(filenamebuf, NULL, true))
{
if ((handle = fopen(*filename, "rb")) == NULL)
{
if (useerrors)
CONS_Alert(CONS_ERROR, M_GetText("Can't open %s\n"), *filename);
return NULL;
}
}
else
{
if (useerrors)
CONS_Alert(CONS_ERROR, M_GetText("File %s not found.\n"), *filename);
return NULL;
}
}
return handle;
}
// search for all DEHACKED lump in all wads and load it
static inline void W_LoadDehackedLumps(UINT16 wadnum)
{
@ -234,7 +275,6 @@ static void W_InvalidateLumpnumCache(void)
memset(lumpnumcache, 0, sizeof (lumpnumcache));
}
// Allocate a wadfile, setup the lumpinfo (directory) and
// lumpcache, add the wadfile to the current active wadfiles
//
@ -271,33 +311,9 @@ UINT16 W_LoadWadFile(const char *filename)
return INT16_MAX;
}
strncpy(filenamebuf, filename, MAX_WADPATH);
filenamebuf[MAX_WADPATH - 1] = '\0';
filename = filenamebuf;
// open wad file
if ((handle = fopen(filename, "rb")) == NULL)
{
// If we failed to load the file with the path as specified by
// the user, strip the directories and search for the file.
nameonly(filenamebuf);
// If findfile finds the file, the full path will be returned
// in filenamebuf == filename.
if (findfile(filenamebuf, NULL, true))
{
if ((handle = fopen(filename, "rb")) == NULL)
{
CONS_Alert(CONS_ERROR, M_GetText("Can't open %s\n"), filename);
return INT16_MAX;
}
}
else
{
CONS_Alert(CONS_ERROR, M_GetText("File %s not found.\n"), filename);
return INT16_MAX;
}
}
if ((handle = W_OpenWadFile(&filename, true)) == NULL)
return INT16_MAX;
// Check if wad files will overflow fileneededbuffer. Only the filename part
// is send in the packet; cf.
@ -1115,21 +1131,11 @@ static int W_VerifyFile(const char *filename, lumpchecklist_t *checklist,
size_t i, j;
int goodfile = false;
if (!checklist) I_Error("No checklist for %s\n", filename);
strlcpy(filenamebuf, filename, MAX_WADPATH);
filename = filenamebuf;
if (!checklist)
I_Error("No checklist for %s\n", filename);
// open wad file
if ((handle = fopen(filename, "rb")) == NULL)
{
nameonly(filenamebuf); // leave full path here
if (findfile(filenamebuf, NULL, true))
{
if ((handle = fopen(filename, "rb")) == NULL)
return -1;
}
else
return -1;
}
if ((handle = W_OpenWadFile(&filename, false)) == NULL)
return -1;
// detect dehacked file with the "soc" extension
if (stricmp(&filename[strlen(filename) - 4], ".soc") != 0

View file

@ -82,6 +82,8 @@ extern wadfile_t *wadfiles[MAX_WADFILES];
void W_Shutdown(void);
// Opens a WAD file. Returns the FILE * handle for the file, or NULL if not found or could not be opened
FILE *W_OpenWadFile(const char **filename, boolean useerrors);
// Load and add a wadfile to the active wad files, returns numbers of lumps, INT16_MAX on error
UINT16 W_LoadWadFile(const char *filename);
#ifdef DELFILE