Merge branch 'master' into linedef-153

This commit is contained in:
lachwright 2019-10-20 20:20:41 +08:00
commit a2f0f61d75
57 changed files with 7832 additions and 622 deletions

6428
extras/conf/SRB2-22.cfg Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
# libopenmpt mingw-w64 binary info
Current built version as of 2019/05/23 is 0.4.4+r11531.pkg
Current built version as of 2019/09/27 is 0.4.7+r12088.pkg
* mingw binaries (.dll): `bin/[x86 or x86_64]/mingw`
* mingw import libraries (.dll.a): `lib/[x86 or x86_64]/mingw`

View File

@ -5,6 +5,44 @@ Changelog {#changelog}
For fully detailed change log, please see the source repository directly. This
is just a high-level summary.
### libopenmpt 0.4.7 (2019-09-23)
* [**Bug**] Compilation fix for various platforms that do not provide
`std::aligned_alloc` in C++17 mode. The problematic dependency has been
removed. This should fix build problems on MinGW, OpenBSD, Haiku, and others
for good.
* J2B: Ignore notes with non-existing instrument (fixes Ending.j2b).
* mpg123: Update to v1.25.13 (2019-08-24).
* ogg: Update to v1.3.4. (2019-08-31).
* flac: Update to v1.3.3. (2019-08-04).
### libopenmpt 0.4.6 (2019-08-10)
* [**Bug**] Compilation fix for OpenBSD.
* [**Bug**] Compilation fix for NO_PLUGINS being defined.
* in_openmpt: Correct documentation. `openmpt-mpg123.dll` must be placed into
the Winamp directory.
* Detect IT files unpacked with early UNMO3 versions.
* mpg123: Update to v1.25.11 (2019-07-18).
* minimp3: Update to commit 977514a6dfc4960d819a103f43b358e58ac6c28f
(2019-07-24).
* miniz: Update to v2.1.0 (2019-05-05).
* stb_vorbis: Update to v1.17 (2019-08-09).
### libopenmpt 0.4.5 (2019-05-27)
* [**Sec**] Possible crash during playback due out-of-bounds read in XM and
MT2 files (r11608).
* Breaking out of a sustain loop through Note-Off sometimes didn't continue in
the regular sample loop.
* Seeking did not stop notes playing with XM Key Off (Kxx) effect.
### libopenmpt 0.4.4 (2019-04-07)
* [**Bug**] Channel VU meters were swapped.

View File

@ -19,7 +19,7 @@
/*! \brief libopenmpt minor version number */
#define OPENMPT_API_VERSION_MINOR 4
/*! \brief libopenmpt patch version number */
#define OPENMPT_API_VERSION_PATCH 4
#define OPENMPT_API_VERSION_PATCH 7
/*! \brief libopenmpt pre-release tag */
#define OPENMPT_API_VERSION_PREREL ""
/*! \brief libopenmpt pre-release flag */

View File

@ -140,6 +140,9 @@ void B_BuildTiccmd(player_t *player, ticcmd_t *cmd)
void B_KeysToTiccmd(mobj_t *mo, ticcmd_t *cmd, boolean forward, boolean backward, boolean left, boolean right, boolean strafeleft, boolean straferight, boolean jump, boolean spin)
{
// don't try to do stuff if your sonic is in a minecart or something
if (players[consoleplayer].powers[pw_carry])
return;
// Turn the virtual keypresses into ticcmd_t.
if (twodlevel || mo->flags2 & MF2_TWOD) {
if (players[consoleplayer].climbing
@ -218,7 +221,12 @@ boolean B_CheckRespawn(player_t *player)
return false;
// Low ceiling, do not want!
if (sonic->ceilingz - sonic->z < 2*sonic->height)
if (sonic->eflags & MFE_VERTICALFLIP)
{
if (sonic->z - sonic->floorz < (sonic->player->exiting ? 5 : 2)*sonic->height)
return false;
}
else if (sonic->ceilingz - sonic->z < (sonic->player->exiting ? 6 : 3)*sonic->height)
return false;
// If you're dead, wait a few seconds to respawn.
@ -252,11 +260,11 @@ void B_RespawnBot(INT32 playernum)
y = sonic->y;
if (sonic->eflags & MFE_VERTICALFLIP) {
tails->eflags |= MFE_VERTICALFLIP;
z = sonic->z - FixedMul(512*FRACUNIT,sonic->scale);
z = sonic->z - (512*sonic->scale);
if (z < sonic->floorz)
z = sonic->floorz;
} else {
z = sonic->z + sonic->height + FixedMul(512*FRACUNIT,sonic->scale);
z = sonic->z + sonic->height + (512*sonic->scale);
if (z > sonic->ceilingz - sonic->height)
z = sonic->ceilingz - sonic->height;
}

View File

@ -621,6 +621,10 @@ static inline void resynch_write_player(resynch_pak *rsp, const size_t i)
rsp->friction = LONG(players[i].mo->friction);
rsp->movefactor = LONG(players[i].mo->movefactor);
rsp->sprite = (spritenum_t)LONG(players[i].mo->sprite);
rsp->frame = LONG(players[i].mo->frame);
rsp->sprite2 = players[i].mo->sprite2;
rsp->anim_duration = SHORT(players[i].mo->anim_duration);
rsp->tics = LONG(players[i].mo->tics);
rsp->statenum = (statenum_t)LONG(players[i].mo->state-states); // :(
rsp->eflags = (UINT16)SHORT(players[i].mo->eflags);
@ -767,8 +771,17 @@ static void resynch_read_player(resynch_pak *rsp)
players[i].mo->momy = LONG(rsp->momy);
players[i].mo->momz = LONG(rsp->momz);
players[i].mo->movefactor = LONG(rsp->movefactor);
// Don't use P_SetMobjStateNF to restore state, write/read all the values manually!
// This should stop those stupid console errors, hopefully.
// -- Monster Iestyn
players[i].mo->sprite = (spritenum_t)LONG(rsp->sprite);
players[i].mo->frame = LONG(rsp->frame);
players[i].mo->sprite2 = rsp->sprite2;
players[i].mo->anim_duration = SHORT(rsp->anim_duration);
players[i].mo->tics = LONG(rsp->tics);
P_SetMobjStateNF(players[i].mo, LONG(rsp->statenum));
players[i].mo->state = &states[LONG(rsp->statenum)];
players[i].mo->x = LONG(rsp->x);
players[i].mo->y = LONG(rsp->y);
players[i].mo->z = LONG(rsp->z);
@ -3841,7 +3854,7 @@ static void HandlePacketFromPlayer(SINT8 node)
break;
// Ignore tics from those not synched
if (resynch_inprogress[node])
if (resynch_inprogress[node] && nettics[node] == gametic)
break;
// To save bytes, only the low byte of tic numbers are sent
@ -4699,7 +4712,7 @@ void TryRunTics(tic_t realtics)
if (player_joining)
return;
if (neededtic > gametic)
if (neededtic > gametic && !resynch_local_inprogress)
{
if (advancedemo)
D_StartTitle();
@ -4853,8 +4866,13 @@ void NetUpdate(void)
for (i = 0; i < MAXNETNODES; ++i)
if (resynch_inprogress[i])
{
SV_SendResynch(i);
counts = -666;
if (!nodeingame[i] || nettics[i] == gametic)
{
SV_SendResynch(i);
counts = -666;
}
else
counts = 0; // Let the client catch up with the server
}
// Do not make tics while resynching

View File

@ -265,6 +265,10 @@ typedef struct
fixed_t friction;
fixed_t movefactor;
spritenum_t sprite;
UINT32 frame;
UINT8 sprite2;
UINT16 anim_duration;
INT32 tics;
statenum_t statenum;
UINT32 flags;

View File

@ -363,7 +363,7 @@ consvar_t cv_runscripts = {"runscripts", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL
consvar_t cv_pause = {"pausepermission", "Server", CV_NETVAR, pause_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_mute = {"mute", "Off", CV_NETVAR|CV_CALL, CV_OnOff, Mute_OnChange, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_sleep = {"cpusleep", "-1", CV_SAVE, sleeping_cons_t, NULL, -1, NULL, NULL, 0, 0, NULL};
consvar_t cv_sleep = {"cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL, -1, NULL, NULL, 0, 0, NULL};
INT16 gametype = GT_COOP;
boolean splitscreen = false;
@ -1186,12 +1186,12 @@ static void SendNameAndColor(void)
&& !strcmp(cv_skin.string, skins[players[consoleplayer].skin].name))
return;
players[consoleplayer].availabilities = R_GetSkinAvailabilities();
// We'll handle it later if we're not playing.
if (!Playing())
return;
players[consoleplayer].availabilities = R_GetSkinAvailabilities();
// If you're not in a netgame, merely update the skin, color, and name.
if (!netgame)
{
@ -1304,12 +1304,12 @@ static void SendNameAndColor2(void)
CV_StealthSet(&cv_playercolor2, cv_playercolor2.defaultvalue);
}
players[secondplaya].availabilities = R_GetSkinAvailabilities();
// We'll handle it later if we're not playing.
if (!Playing())
return;
players[secondplaya].availabilities = R_GetSkinAvailabilities();
// If you're not in a netgame, merely update the skin, color, and name.
if (botingame)
{

View File

@ -5885,7 +5885,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// Saloon door
"S_SALOONDOOR",
"S_SALOONDOORTHINKER",
"S_SALOONDOORCENTER",
// Train cameo
"S_TRAINCAMEOSPAWNER_1",
@ -5991,6 +5991,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_LAMPPOST1", // normal
"S_LAMPPOST2", // with snow
"S_HANGSTAR",
"S_MISTLETOE",
// Xmas GFZ bushes
"S_XMASBLUEBERRYBUSH",
"S_XMASBERRYBUSH",
@ -5998,6 +5999,16 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
// FHZ
"S_FHZICE1",
"S_FHZICE2",
"S_ROSY_IDLE1",
"S_ROSY_IDLE2",
"S_ROSY_IDLE3",
"S_ROSY_IDLE4",
"S_ROSY_JUMP",
"S_ROSY_WALK",
"S_ROSY_HUG",
"S_ROSY_PAIN",
"S_ROSY_STND",
"S_ROSY_UNHAPPY",
// Halloween Scenery
// Pumpkins
@ -7655,7 +7666,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_MINECARTSIDEMARK",
"MT_MINECARTSPARK",
"MT_SALOONDOOR",
"MT_SALOONDOORTHINKER",
"MT_SALOONDOORCENTER",
"MT_TRAINCAMEOSPAWNER",
"MT_TRAINSEG",
"MT_TRAINDUSTSPAWNER",
@ -7717,6 +7728,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_LAMPPOST1", // normal
"MT_LAMPPOST2", // with snow
"MT_HANGSTAR",
"MT_MISTLETOE",
// Xmas GFZ bushes
"MT_XMASBLUEBERRYBUSH",
"MT_XMASBERRYBUSH",
@ -7724,6 +7736,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
// FHZ
"MT_FHZICE1",
"MT_FHZICE2",
"MT_ROSY",
"MT_CDLHRT",
// Halloween Scenery
// Pumpkins

View File

@ -637,6 +637,7 @@ static void F_IntroDrawScene(void)
}
else
{
menuanimtimer = animtimer; // Reusing this variable for the intro to fix the scrolling sky, better than changing the function around.
F_SkyScroll(80*4, 0, "TITLESKY");
if (timetonext == 6)
{

View File

@ -709,8 +709,8 @@ void G_DefineDefaultControls(void)
for (i = 1; i < num_gamecontrolschemes; i++) // skip gcs_custom (0)
{
gamecontroldefault[i][gc_weaponnext ][0] = 'e';
gamecontroldefault[i][gc_weaponprev ][0] = 'q';
gamecontroldefault[i][gc_weaponnext ][0] = KEY_MOUSEWHEELUP+0;
gamecontroldefault[i][gc_weaponprev ][0] = KEY_MOUSEWHEELDOWN+0;
gamecontroldefault[i][gc_wepslot1 ][0] = '1';
gamecontroldefault[i][gc_wepslot2 ][0] = '2';
gamecontroldefault[i][gc_wepslot3 ][0] = '3';

View File

@ -47,6 +47,7 @@ EXPORT void HWRAPI(SetPalette) (RGBA_t *ppal, RGBA_t *pgamma);
EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl);
EXPORT void HWRAPI(Draw2DLine) (F2DCoord *v1, F2DCoord *v2, RGBA_t Color);
EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags);
EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform);
EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags);
EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor);
EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo);
@ -89,6 +90,7 @@ struct hwdriver_s
FinishUpdate pfnFinishUpdate;
Draw2DLine pfnDraw2DLine;
DrawPolygon pfnDrawPolygon;
RenderSkyDome pfnRenderSkyDome;
SetBlend pfnSetBlend;
ClearBuffer pfnClearBuffer;
SetTexture pfnSetTexture;

View File

@ -395,7 +395,9 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_XMS3
&lspr[NOLIGHT], // SPR_XMS4
&lspr[NOLIGHT], // SPR_XMS5
&lspr[NOLIGHT], // SPR_XMS6
&lspr[NOLIGHT], // SPR_FHZI
&lspr[NOLIGHT], // SPR_ROSY
// Halloween Scenery
&lspr[RINGLIGHT_L], // SPR_PUMK

View File

@ -5454,7 +5454,7 @@ static void HWR_AddSprites(sector_t *sec)
#ifdef HWPRECIP
precipmobj_t *precipthing;
#endif
fixed_t approx_dist, limit_dist;
fixed_t approx_dist, limit_dist, hoop_limit_dist;
// BSP is traversed by subsector.
// A sector might have been split into several
@ -5471,7 +5471,9 @@ static void HWR_AddSprites(sector_t *sec)
// Handle all things in sector.
// If a limit exists, handle things a tiny bit different.
if ((limit_dist = (fixed_t)((maptol & TOL_NIGHTS) ? cv_drawdist_nights.value : cv_drawdist.value) << FRACBITS))
limit_dist = (fixed_t)(cv_drawdist.value) << FRACBITS;
hoop_limit_dist = (fixed_t)(cv_drawdist_nights.value) << FRACBITS;
if (limit_dist || hoop_limit_dist)
{
for (thing = sec->thinglist; thing; thing = thing->snext)
{
@ -5480,8 +5482,16 @@ static void HWR_AddSprites(sector_t *sec)
approx_dist = P_AproxDistance(viewx-thing->x, viewy-thing->y);
if (approx_dist > limit_dist)
continue;
if (thing->sprite == SPR_HOOP)
{
if (hoop_limit_dist && approx_dist > hoop_limit_dist)
continue;
}
else
{
if (limit_dist && approx_dist > limit_dist)
continue;
}
HWR_ProjectSprite(thing);
}
@ -5711,6 +5721,13 @@ static void HWR_ProjectSprite(mobj_t *thing)
return;
}
if ((thing->flags2 & MF2_LINKDRAW) && thing->tracer)
{
// bodge support - not nearly as comprehensive as r_things.c, but better than nothing
if (thing->tracer->sprite == SPR_NULL || thing->tracer->flags2 & MF2_DONTDRAW)
return;
}
// store information in a vissprite
vis = HWR_NewVisSprite();
vis->x1 = x1;
@ -5724,7 +5741,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
vis->z2 = z2;
//Hurdler: 25/04/2000: now support colormap in hardware mode
if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash"
if ((vis->mobj->flags & (MF_ENEMY|MF_BOSS)) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash"
{
if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized)
vis->colormap = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE);
@ -5869,86 +5886,122 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
// ==========================================================================
//
// ==========================================================================
static void HWR_DrawSkyBackground(void)
static void HWR_DrawSkyBackground(player_t *player)
{
FOutVector v[4];
angle_t angle;
float dimensionmultiply;
float aspectratio;
float angleturn;
HWR_GetTexture(texturetranslation[skytexture]);
aspectratio = (float)vid.width/(float)vid.height;
//Hurdler: the sky is the only texture who need 4.0f instead of 1.0
// because it's called just after clearing the screen
// and thus, the near clipping plane is set to 3.99
// Sryder: Just use the near clipping plane value then
// 3--2
// | /|
// |/ |
// 0--1
v[0].x = v[3].x = -ZCLIP_PLANE-1;
v[1].x = v[2].x = ZCLIP_PLANE+1;
v[0].y = v[1].y = -ZCLIP_PLANE-1;
v[2].y = v[3].y = ZCLIP_PLANE+1;
v[0].z = v[1].z = v[2].z = v[3].z = ZCLIP_PLANE+1;
// X
// NOTE: This doesn't work right with texture widths greater than 1024
// software doesn't draw any further than 1024 for skies anyway, but this doesn't overlap properly
// The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture
angle = (dup_viewangle + gr_xtoviewangle[0]);
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f);
v[0].sow = v[3].sow = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left
v[2].sow = v[1].sow = v[0].sow + (1.0f/dimensionmultiply); // right (or left + 1.0f)
// use +angle and -1.0f above instead if you wanted old backwards behavior
// Y
angle = aimingangle;
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->height/(128.0f*aspectratio));
if (splitscreen)
if (cv_grskydome.value)
{
dimensionmultiply *= 2;
angle *= 2;
}
FTransform transform;
const float fpov = FIXED_TO_FLOAT(cv_grfov.value+player->fovadd);
postimg_t *type;
// Middle of the sky should always be at angle 0
// need to keep correct aspect ratio with X
if (atransform.flip)
{
// During vertical flip the sky should be flipped and it's y movement should also be flipped obviously
v[3].tow = v[2].tow = -(0.5f-(0.5f/dimensionmultiply)); // top
v[0].tow = v[1].tow = v[3].tow - (1.0f/dimensionmultiply); // bottom (or top - 1.0f)
if (splitscreen && player == &players[secondarydisplayplayer])
type = &postimgtype2;
else
type = &postimgtype;
memset(&transform, 0x00, sizeof(FTransform));
//04/01/2000: Hurdler: added for T&L
// It should replace all other gr_viewxxx when finished
transform.anglex = (float)(aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES);
transform.angley = (float)((viewangle-ANGLE_270)>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES);
if (*type == postimg_flip)
transform.flip = true;
else
transform.flip = false;
transform.scalex = 1;
transform.scaley = (float)vid.width/vid.height;
transform.scalez = 1;
transform.fovxangle = fpov; // Tails
transform.fovyangle = fpov; // Tails
transform.splitscreen = splitscreen;
HWR_GetTexture(texturetranslation[skytexture]);
HWD.pfnRenderSkyDome(skytexture, textures[skytexture]->width, textures[skytexture]->height, transform);
}
else
{
v[0].tow = v[1].tow = -(0.5f-(0.5f/dimensionmultiply)); // bottom
v[3].tow = v[2].tow = v[0].tow - (1.0f/dimensionmultiply); // top (or bottom - 1.0f)
}
FOutVector v[4];
angle_t angle;
float dimensionmultiply;
float aspectratio;
float angleturn;
angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply;
HWR_GetTexture(texturetranslation[skytexture]);
aspectratio = (float)vid.width/(float)vid.height;
if (angle > ANGLE_180) // Do this because we don't want the sky to suddenly teleport when crossing over 0 to 360 and vice versa
{
angle = InvAngle(angle);
v[3].tow = v[2].tow += ((float) angle / angleturn);
v[0].tow = v[1].tow += ((float) angle / angleturn);
}
else
{
v[3].tow = v[2].tow -= ((float) angle / angleturn);
v[0].tow = v[1].tow -= ((float) angle / angleturn);
}
//Hurdler: the sky is the only texture who need 4.0f instead of 1.0
// because it's called just after clearing the screen
// and thus, the near clipping plane is set to 3.99
// Sryder: Just use the near clipping plane value then
HWD.pfnDrawPolygon(NULL, v, 4, 0);
// 3--2
// | /|
// |/ |
// 0--1
v[0].x = v[3].x = -ZCLIP_PLANE-1;
v[1].x = v[2].x = ZCLIP_PLANE+1;
v[0].y = v[1].y = -ZCLIP_PLANE-1;
v[2].y = v[3].y = ZCLIP_PLANE+1;
v[0].z = v[1].z = v[2].z = v[3].z = ZCLIP_PLANE+1;
// X
// NOTE: This doesn't work right with texture widths greater than 1024
// software doesn't draw any further than 1024 for skies anyway, but this doesn't overlap properly
// The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture
angle = (dup_viewangle + gr_xtoviewangle[0]);
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f);
v[0].sow = v[3].sow = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left
v[2].sow = v[1].sow = v[0].sow + (1.0f/dimensionmultiply); // right (or left + 1.0f)
// use +angle and -1.0f above instead if you wanted old backwards behavior
// Y
angle = aimingangle;
dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->height/(128.0f*aspectratio));
if (splitscreen)
{
dimensionmultiply *= 2;
angle *= 2;
}
// Middle of the sky should always be at angle 0
// need to keep correct aspect ratio with X
if (atransform.flip)
{
// During vertical flip the sky should be flipped and it's y movement should also be flipped obviously
v[3].tow = v[2].tow = -(0.5f-(0.5f/dimensionmultiply)); // top
v[0].tow = v[1].tow = v[3].tow - (1.0f/dimensionmultiply); // bottom (or top - 1.0f)
}
else
{
v[0].tow = v[1].tow = -(0.5f-(0.5f/dimensionmultiply)); // bottom
v[3].tow = v[2].tow = v[0].tow - (1.0f/dimensionmultiply); // top (or bottom - 1.0f)
}
angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply;
if (angle > ANGLE_180) // Do this because we don't want the sky to suddenly teleport when crossing over 0 to 360 and vice versa
{
angle = InvAngle(angle);
v[3].tow = v[2].tow += ((float) angle / angleturn);
v[0].tow = v[1].tow += ((float) angle / angleturn);
}
else
{
v[3].tow = v[2].tow -= ((float) angle / angleturn);
v[0].tow = v[1].tow -= ((float) angle / angleturn);
}
HWD.pfnDrawPolygon(NULL, v, 4, 0);
}
}
@ -6100,7 +6153,7 @@ if (0)
}
if (drawsky)
HWR_DrawSkyBackground();
HWR_DrawSkyBackground(player);
//Hurdler: it doesn't work in splitscreen mode
drawsky = splitscreen;
@ -6317,7 +6370,7 @@ if (0)
}
if (!skybox && drawsky) // Don't draw the regular sky if there's a skybox
HWR_DrawSkyBackground();
HWR_DrawSkyBackground(player);
//Hurdler: it doesn't work in splitscreen mode
drawsky = splitscreen;

View File

@ -98,6 +98,7 @@ extern consvar_t cv_voodoocompatibility;
extern consvar_t cv_grfovchange;
extern consvar_t cv_grsolvetjoin;
extern consvar_t cv_grspritebillboarding;
extern consvar_t cv_grskydome;
extern float gr_viewwidth, gr_viewheight, gr_baseviewwindowy;

View File

@ -1277,6 +1277,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
// MD2 colormap fix
// colormap test
if (spr->mobj->subsector)
{
sector_t *sector = spr->mobj->subsector->sector;
UINT8 lightlevel = 255;
@ -1308,6 +1309,8 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
else
Surf.FlatColor.rgba = HWR_Lighting(lightlevel, NORMALFOG, FADEFOG, false, false);
}
else
Surf.FlatColor.rgba = 0xFFFFFFFF;
// Look at HWR_ProjectSprite for more
{

View File

@ -1427,6 +1427,219 @@ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf,
Clamp2D(GL_TEXTURE_WRAP_T);
}
typedef struct vbo_vertex_s
{
float x, y, z;
float u, v;
unsigned char r, g, b, a;
} vbo_vertex_t;
typedef struct
{
int mode;
int vertexcount;
int vertexindex;
int use_texture;
} GLSkyLoopDef;
typedef struct
{
int id;
int rows, columns;
int loopcount;
GLSkyLoopDef *loops;
vbo_vertex_t *data;
} GLSkyVBO;
// The texture offset to be applied to the texture coordinates in SkyVertex().
static int rows, columns;
static boolean yflip;
static int texw, texh;
static boolean foglayer;
static float delta = 0.0f;
static int gl_sky_detail = 16;
static INT32 lasttex = -1;
#define MAP_COEFF 128.0f
static void SkyVertex(vbo_vertex_t *vbo, int r, int c)
{
const float radians = (M_PIl / 180.0f);
const float scale = 10000.0f;
const float maxSideAngle = 60.0f;
float topAngle = (c / (float)columns * 360.0f);
float sideAngle = (maxSideAngle * (rows - r) / rows);
float height = sin(sideAngle * radians);
float realRadius = scale * cos(sideAngle * radians);
float x = realRadius * cos(topAngle * radians);
float y = (!yflip) ? scale * height : -scale * height;
float z = realRadius * sin(topAngle * radians);
float timesRepeat = (4 * (256.0f / texw));
if (fpclassify(timesRepeat) == FP_ZERO)
timesRepeat = 1.0f;
if (!foglayer)
{
vbo->r = 255;
vbo->g = 255;
vbo->b = 255;
vbo->a = (r == 0 ? 0 : 255);
// And the texture coordinates.
vbo->u = (-timesRepeat * c / (float)columns);
if (!yflip) // Flipped Y is for the lower hemisphere.
vbo->v = (r / (float)rows) + 0.5f;
else
vbo->v = 1.0f + ((rows - r) / (float)rows) + 0.5f;
}
if (r != 4)
{
y += 300.0f;
}
// And finally the vertex.
vbo->x = x;
vbo->y = y + delta;
vbo->z = z;
}
static GLSkyVBO sky_vbo;
static void gld_BuildSky(int row_count, int col_count)
{
int c, r;
vbo_vertex_t *vertex_p;
int vertex_count = 2 * row_count * (col_count * 2 + 2) + col_count * 2;
GLSkyVBO *vbo = &sky_vbo;
if ((vbo->columns != col_count) || (vbo->rows != row_count))
{
free(vbo->loops);
free(vbo->data);
memset(vbo, 0, sizeof(&vbo));
}
if (!vbo->data)
{
memset(vbo, 0, sizeof(&vbo));
vbo->loops = malloc((row_count * 2 + 2) * sizeof(vbo->loops[0]));
// create vertex array
vbo->data = malloc(vertex_count * sizeof(vbo->data[0]));
}
vbo->columns = col_count;
vbo->rows = row_count;
vertex_p = &vbo->data[0];
vbo->loopcount = 0;
for (yflip = 0; yflip < 2; yflip++)
{
vbo->loops[vbo->loopcount].mode = GL_TRIANGLE_FAN;
vbo->loops[vbo->loopcount].vertexindex = vertex_p - &vbo->data[0];
vbo->loops[vbo->loopcount].vertexcount = col_count;
vbo->loops[vbo->loopcount].use_texture = false;
vbo->loopcount++;
delta = 0.0f;
foglayer = true;
for (c = 0; c < col_count; c++)
{
SkyVertex(vertex_p, 1, c);
vertex_p->r = 255;
vertex_p->g = 255;
vertex_p->b = 255;
vertex_p->a = 255;
vertex_p++;
}
foglayer = false;
delta = (yflip ? 5.0f : -5.0f) / MAP_COEFF;
for (r = 0; r < row_count; r++)
{
vbo->loops[vbo->loopcount].mode = GL_TRIANGLE_STRIP;
vbo->loops[vbo->loopcount].vertexindex = vertex_p - &vbo->data[0];
vbo->loops[vbo->loopcount].vertexcount = 2 * col_count + 2;
vbo->loops[vbo->loopcount].use_texture = true;
vbo->loopcount++;
for (c = 0; c <= col_count; c++)
{
SkyVertex(vertex_p++, r + (yflip ? 1 : 0), (c ? c : 0));
SkyVertex(vertex_p++, r + (yflip ? 0 : 1), (c ? c : 0));
}
}
}
}
//-----------------------------------------------------------------------------
//
//
//
//-----------------------------------------------------------------------------
static void RenderDome(INT32 skytexture)
{
int i, j;
GLSkyVBO *vbo = &sky_vbo;
pglRotatef(270.0f, 0.0f, 1.0f, 0.0f);
rows = 4;
columns = 4 * gl_sky_detail;
if (lasttex != skytexture)
{
lasttex = skytexture;
gld_BuildSky(rows, columns);
}
pglScalef(1.0f, (float)texh / 230.0f, 1.0f);
for (j = 0; j < 2; j++)
{
for (i = 0; i < vbo->loopcount; i++)
{
GLSkyLoopDef *loop = &vbo->loops[i];
if (j == 0 ? loop->use_texture : !loop->use_texture)
continue;
else
{
int k;
pglBegin(loop->mode);
for (k = loop->vertexindex; k < (loop->vertexindex + loop->vertexcount); k++)
{
vbo_vertex_t *v = &vbo->data[k];
if (loop->use_texture)
pglTexCoord2f(v->u, v->v);
pglColor4f(v->r, v->g, v->b, v->a);
pglVertex3f(v->x, v->y, v->z);
}
pglEnd();
}
}
}
pglScalef(1.0f, 1.0f, 1.0f);
pglColor4f(1.0f, 1.0f, 1.0f, 1.0f);
}
EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform)
{
SetBlend(PF_Translucent|PF_NoDepthTest|PF_Modulated);
SetTransform(&transform);
texw = texture_width;
texh = texture_height;
RenderDome(tex);
SetBlend(0);
}
// ==========================================================================
//

View File

@ -266,7 +266,6 @@ char sprnames[NUMSPRITES + 1][5] =
"ADST", // Arid dust
"MCRT", // Minecart
"MCSP", // Minecart spark
"NON2", // Saloon door thinker
"SALD", // Saloon door
"TRAE", // Train cameo locomotive
"TRAI", // Train cameo wagon
@ -290,7 +289,9 @@ char sprnames[NUMSPRITES + 1][5] =
"XMS3", // Snowman
"XMS4", // Lamppost
"XMS5", // Hanging Star
"XMS6", // Mistletoe
"FHZI", // FHZ ice
"ROSY",
// Halloween Scenery
"PUMK", // Pumpkins
@ -2486,8 +2487,8 @@ state_t states[NUMSTATES] =
{SPR_MCSP, FF_FULLBRIGHT, 1, {A_MinecartSparkThink}, 0, 0, S_MINECARTSPARK}, // S_MINECARTSPARK
// Saloon door
{SPR_SALD, 0|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_SALOONDOOR
{SPR_NON2, 0, -1, {A_SaloonDoorSpawn}, 0, 0, S_NULL}, // S_SALONDOORTHINKER
{SPR_SALD, 0|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_SALOONDOOR
{SPR_NULL, 0, -1, {A_SaloonDoorSpawn}, MT_SALOONDOOR, 48, S_NULL}, // S_SALOONDOORCENTER
// Train cameo
{SPR_NULL, 0, -1, {NULL}, 0, 0, S_TRAINCAMEOSPAWNER_2}, // S_TRAINCAMEOSPAWNER_1
@ -2598,6 +2599,7 @@ state_t states[NUMSTATES] =
{SPR_XMS4, 0, -1, {NULL}, 0, 0, S_NULL}, // S_LAMPPOST1
{SPR_XMS4, 1, -1, {NULL}, 0, 0, S_NULL}, // S_LAMPPOST2
{SPR_XMS5, 0, -1, {NULL}, 0, 0, S_NULL}, // S_HANGSTAR
{SPR_XMS6, 0, -1, {NULL}, 0, 0, S_NULL}, // S_MISTLETOE
// Xmas GFZ bushes
{SPR_BUS3, 1, -1, {NULL}, 0, 0, S_NULL}, // S_XMASBLUEBERRYBUSH
{SPR_BUS1, 1, -1, {NULL}, 0, 0, S_NULL}, // S_XMASBERRYBUSH
@ -2605,6 +2607,16 @@ state_t states[NUMSTATES] =
// FHZ
{SPR_FHZI, 0, -1, {NULL}, 0, 0, S_NULL}, // S_FHZICE1
{SPR_FHZI, 1, -1, {NULL}, 0, 0, S_NULL}, // S_FHZICE2
{SPR_ROSY, 16, 8, {NULL}, 0, 0, S_ROSY_IDLE2}, // S_ROSY_IDLE1
{SPR_ROSY, 17, 4, {NULL}, 0, 0, S_ROSY_IDLE3}, // S_ROSY_IDLE2
{SPR_ROSY, 18, 8, {NULL}, 0, 0, S_ROSY_IDLE4}, // S_ROSY_IDLE3
{SPR_ROSY, 17, 4, {NULL}, 0, 0, S_ROSY_IDLE1}, // S_ROSY_IDLE4
{SPR_ROSY, 14, -1, {NULL}, 1, 0, S_NULL}, // S_ROSY_JUMP
{SPR_ROSY, 5, -1, {NULL}, 7, 0, S_NULL}, // S_ROSY_WALK
{SPR_ROSY, 19, -1, {NULL}, 0, 0, S_NULL}, // S_ROSY_HUG
{SPR_ROSY, 13, -1, {NULL}, 0, 0, S_NULL}, // S_ROSY_PAIN
{SPR_ROSY, 1|FF_ANIMATE, -1, {NULL}, 3, 16, S_NULL}, // S_ROSY_STND
{SPR_ROSY, 20|FF_ANIMATE, TICRATE, {NULL}, 3, 4, S_ROSY_WALK}, // S_ROSY_UNHAPPY
// Halloween Scenery
// Pumpkins
@ -4829,7 +4841,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
0, // damage
sfx_None, // activesound
MF_SCENERY|MF_PAIN|MF_NOCLIPHEIGHT|MF_NOBLOCKMAP|MF_NOGRAVITY, // flags
MF_SCENERY|MF_PAIN|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOBLOCKMAP|MF_NOGRAVITY, // flags
S_SNAPPER_LEGRAISE // raisestate
},
@ -4856,7 +4868,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
0, // damage
sfx_None, // activesound
MF_PAIN|MF_NOBLOCKMAP|MF_NOGRAVITY, // flags
MF_PAIN|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOBLOCKMAP|MF_NOGRAVITY, // flags
S_NULL // raisestate
},
@ -12383,7 +12395,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
0, // damage
sfx_None, // activesound
MF_SOLID|MF_SHOOTABLE|MF_ENEMY|MF_PUSHABLE, // flags
MF_SOLID|MF_SHOOTABLE|MF_PUSHABLE, // flags
S_NULL // raisestate
},
@ -12711,9 +12723,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_SALOONDOORTHINKER
{ // MT_SALOONDOORCENTER
1221, // doomednum
S_SALOONDOORTHINKER, // spawnstate
S_SALOONDOORCENTER, // spawnstate
1, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
@ -12734,7 +12746,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
0, // damage
sfx_None, // activesound
MF_NOGRAVITY|MF_RUNSPAWNFUNC, // flags
MF_SOLID|MF_NOGRAVITY|MF_RUNSPAWNFUNC|MF_PAPERCOLLISION|MF_NOCLIPHEIGHT, // flags
S_NULL // raisestate
},
@ -13926,6 +13938,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_MISTLETOE
2105, // doomednum
S_MISTLETOE, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // 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
52*FRACUNIT, // radius
106*FRACUNIT, // height
0, // display offset
100, // mass
1, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIP|MF_SPAWNCEILING|MF_NOGRAVITY|MF_SCENERY, // flags
S_NULL // raisestate
},
{ // MT_XMASBLUEBERRYBUSH
1859, // doomednum
S_XMASBLUEBERRYBUSH, // spawnstate
@ -14061,6 +14100,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_ROSY
2104, // doomednum
S_ROSY_IDLE1, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // 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
16*FRACUNIT, // radius
48*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_SCENERY|MF_ENEMY|MF_SLIDEME, // flags -- "enemy" may seem weird but it doesn't have any unintended consequences in context because no MF_SHOOTABLE|MF_SPECIAL
S_NULL // raisestate
},
{ // MT_CDLHRT
-1, // doomednum
S_LHRT, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // 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
4*FRACUNIT, // speed
4*FRACUNIT, // radius
4*FRACUNIT, // height
1, // display offset
4, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIP|MF_SCENERY, // flags
S_NULL // raisestate
},
{ // MT_JACKO1
2006, // doomednum
S_JACKO1, // spawnstate

View File

@ -522,7 +522,6 @@ typedef enum sprite
SPR_ADST, // Arid dust
SPR_MCRT, // Minecart
SPR_MCSP, // Minecart spark
SPR_NON2, // Saloon door thinker
SPR_SALD, // Saloon door
SPR_TRAE, // Train cameo locomotive
SPR_TRAI, // Train cameo wagon
@ -546,7 +545,9 @@ typedef enum sprite
SPR_XMS3, // Snowman
SPR_XMS4, // Lamppost
SPR_XMS5, // Hanging Star
SPR_XMS6, // Mistletoe
SPR_FHZI, // FHZ Ice
SPR_ROSY,
// Halloween Scenery
SPR_PUMK, // Pumpkins
@ -2608,7 +2609,7 @@ typedef enum state
// Saloon door
S_SALOONDOOR,
S_SALOONDOORTHINKER,
S_SALOONDOORCENTER,
// Train cameo
S_TRAINCAMEOSPAWNER_1,
@ -2714,6 +2715,7 @@ typedef enum state
S_LAMPPOST1, // normal
S_LAMPPOST2, // with snow
S_HANGSTAR,
S_MISTLETOE,
// Xmas GFZ bushes
S_XMASBLUEBERRYBUSH,
S_XMASBERRYBUSH,
@ -2721,6 +2723,16 @@ typedef enum state
// FHZ
S_FHZICE1,
S_FHZICE2,
S_ROSY_IDLE1,
S_ROSY_IDLE2,
S_ROSY_IDLE3,
S_ROSY_IDLE4,
S_ROSY_JUMP,
S_ROSY_WALK,
S_ROSY_HUG,
S_ROSY_PAIN,
S_ROSY_STND,
S_ROSY_UNHAPPY,
// Halloween Scenery
// Pumpkins
@ -4400,7 +4412,7 @@ typedef enum mobj_type
MT_MINECARTSIDEMARK,
MT_MINECARTSPARK,
MT_SALOONDOOR,
MT_SALOONDOORTHINKER,
MT_SALOONDOORCENTER,
MT_TRAINCAMEOSPAWNER,
MT_TRAINSEG,
MT_TRAINDUSTSPAWNER,
@ -4462,6 +4474,7 @@ typedef enum mobj_type
MT_LAMPPOST1, // normal
MT_LAMPPOST2, // with snow
MT_HANGSTAR,
MT_MISTLETOE,
// Xmas GFZ bushes
MT_XMASBLUEBERRYBUSH,
MT_XMASBERRYBUSH,
@ -4469,6 +4482,8 @@ typedef enum mobj_type
// FHZ
MT_FHZICE1,
MT_FHZICE2,
MT_ROSY,
MT_CDLHRT,
// Halloween Scenery
// Pumpkins

View File

@ -1121,7 +1121,7 @@ void LUA_Archive(void)
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
if (!playeringame[i] && i > 0) // dedicated servers...
continue;
// all players in game will be archived, even if they just add a 0.
ArchiveExtVars(&players[i], "player");
@ -1157,7 +1157,7 @@ void LUA_UnArchive(void)
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
if (!playeringame[i] && i > 0) // dedicated servers...
continue;
UnArchiveExtVars(&players[i]);
}

View File

@ -247,6 +247,7 @@ menu_t MISC_ScrambleTeamDef, MISC_ChangeTeamDef;
// Single Player
static void M_StartTutorial(INT32 choice);
static void M_LoadGame(INT32 choice);
static void M_HandleTimeAttackLevelSelect(INT32 choice);
static void M_TimeAttackLevelSelect(INT32 choice);
static void M_TimeAttack(INT32 choice);
static void M_NightsAttackLevelSelect(INT32 choice);
@ -743,7 +744,7 @@ static menuitem_t SP_TimeAttackLevelSelectMenu[] =
// Single Player Time Attack
static menuitem_t SP_TimeAttackMenu[] =
{
{IT_STRING|IT_CALL, NULL, "Level Select...", &M_TimeAttackLevelSelect, 52},
{IT_STRING|IT_KEYHANDLER, NULL, "Level Select...", M_HandleTimeAttackLevelSelect, 52},
{IT_STRING|IT_CVAR, NULL, "Character", &cv_chooseskin, 62},
{IT_DISABLED, NULL, "Guest Option...", &SP_GuestReplayDef, 100},
@ -1224,7 +1225,7 @@ static menuitem_t OP_VideoOptionsMenu[] =
{IT_HEADER, NULL, "Level", NULL, 155},
{IT_STRING | IT_CVAR, NULL, "Draw Distance", &cv_drawdist, 161},
{IT_STRING | IT_CVAR, NULL, "Weather Draw Dist.", &cv_drawdist_precip, 166},
{IT_STRING | IT_CVAR, NULL, "NiGHTS mode Draw Dist.", &cv_drawdist_nights, 171},
{IT_STRING | IT_CVAR, NULL, "NiGHTS Hoop Draw Dist.", &cv_drawdist_nights, 171},
{IT_HEADER, NULL, "Diagnostic", NULL, 180},
{IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 186},
@ -4894,13 +4895,25 @@ static void M_HandleLevelPlatter(INT32 choice)
{
boolean exitmenu = false; // exit to previous menu
INT32 selectval;
UINT8 iter;
switch (choice)
{
case KEY_DOWNARROW:
if (lsrow == levelselect.numrows-1)
{
if (levelselect.numrows < 3)
{
if (!lsoffs[0]) // prevent sound spam
{
lsoffs[0] = -8;
S_StartSound(NULL,sfx_s3kb7);
}
return;
}
lsrow = UINT8_MAX;
}
lsrow++;
if (lsrow == levelselect.numrows)
lsrow = 0;
lsoffs[0] = lsvseperation(lsrow);
@ -4914,17 +4927,29 @@ static void M_HandleLevelPlatter(INT32 choice)
break;
case KEY_UPARROW:
lsoffs[0] = -lsvseperation(lsrow);
iter = lsrow;
if (!lsrow)
{
if (levelselect.numrows < 3)
{
if (!lsoffs[0]) // prevent sound spam
{
lsoffs[0] = 8;
S_StartSound(NULL,sfx_s3kb7);
}
return;
}
lsrow = levelselect.numrows;
}
lsrow--;
if (lsrow == UINT8_MAX)
lsrow = levelselect.numrows-1;
lsoffs[0] = -lsvseperation(iter);
if (levelselect.rows[lsrow].header[0])
lshli = lsrow;
else
{
UINT8 iter = lsrow;
iter = lsrow;
do
iter = ((iter == 0) ? levelselect.numrows-1 : iter-1);
while ((iter != lsrow) && !(levelselect.rows[iter].header[0]));
@ -4957,7 +4982,7 @@ static void M_HandleLevelPlatter(INT32 choice)
M_LevelSelectWarp(0);
Nextmap_OnChange();
}
else if (!lsoffs[0]) // prevent sound spam
else if (!lsoffs[0]) // prevent sound spam
{
lsoffs[0] = -8;
S_StartSound(NULL,sfx_s3kb2);
@ -4987,7 +5012,7 @@ static void M_HandleLevelPlatter(INT32 choice)
ifselectvalnextmap(lscol) else ifselectvalnextmap(0)
}
else if (!lsoffs[1]) // prevent sound spam
else if (!lsoffs[1]) // prevent sound spam
{
lsoffs[1] = 8;
S_StartSound(NULL,sfx_s3kb7);
@ -5016,7 +5041,7 @@ static void M_HandleLevelPlatter(INT32 choice)
ifselectvalnextmap(lscol) else ifselectvalnextmap(0)
}
else if (!lsoffs[1]) // prevent sound spam
else if (!lsoffs[1]) // prevent sound spam
{
lsoffs[1] = -8;
S_StartSound(NULL,sfx_s3kb7);
@ -5187,7 +5212,13 @@ static void M_DrawLevelPlatterMenu(void)
// finds row at top of the screen
while (y > -8)
{
iter = ((iter == 0) ? levelselect.numrows-1 : iter-1);
if (iter == 0)
{
if (levelselect.numrows < 3)
break;
iter = levelselect.numrows;
}
iter--;
y -= lsvseperation(iter);
}
@ -5196,7 +5227,13 @@ static void M_DrawLevelPlatterMenu(void)
{
M_DrawLevelPlatterRow(iter, y);
y += lsvseperation(iter);
iter = ((iter == levelselect.numrows-1) ? 0 : iter+1);
if (iter == levelselect.numrows-1)
{
if (levelselect.numrows < 3)
break;
iter = UINT8_MAX;
}
iter++;
}
// draw cursor box
@ -8330,7 +8367,18 @@ void M_DrawTimeAttackMenu(void)
else
PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE);
V_DrawSmallScaledPatch(208, 32+lsheadingheight, 0, PictureOfLevel);
y = 32+lsheadingheight;
V_DrawSmallScaledPatch(208, y, 0, PictureOfLevel);
if (itemOn == talevel)
{
/* Draw arrows !! */
y = y + 25 - 4;
V_DrawCharacter(208 - 10 - (skullAnimCounter/5), y,
'\x1C' | V_YELLOWMAP, false);
V_DrawCharacter(208 + 80 + 2 + (skullAnimCounter/5), y,
'\x1D' | V_YELLOWMAP, false);
}
V_DrawString(104 - 72, 32+lsheadingheight/2, 0, "* LEVEL RECORDS *");
@ -8400,6 +8448,39 @@ void M_DrawTimeAttackMenu(void)
}
}
static void M_HandleTimeAttackLevelSelect(INT32 choice)
{
switch (choice)
{
case KEY_DOWNARROW:
M_NextOpt();
break;
case KEY_UPARROW:
M_PrevOpt();
break;
case KEY_LEFTARROW:
CV_AddValue(&cv_nextmap, -1);
break;
case KEY_RIGHTARROW:
CV_AddValue(&cv_nextmap, 1);
break;
case KEY_ENTER:
M_TimeAttackLevelSelect(0);
break;
case KEY_ESCAPE:
noFurtherInput = true;
M_GoBack(0);
return;
default:
return;
}
S_StartSound(NULL, sfx_menu1);
}
static void M_TimeAttackLevelSelect(INT32 choice)
{
(void)choice;

View File

@ -5351,20 +5351,22 @@ static mobj_t *minus;
static boolean PIT_MinusCarry(mobj_t *thing)
{
if (minus->tracer)
return true;
if (minus->type == thing->type)
return true;
if (!(thing->flags & MF_SHOOTABLE) || !(thing->flags & MF_ENEMY))
if (!(thing->flags & (MF_PUSHABLE|MF_ENEMY)))
return true;
if (P_AproxDistance(minus->x - thing->x, minus->y - thing->y) >= minus->radius * 3)
if (P_AproxDistance(minus->x - thing->x, minus->y - thing->y) >= minus->radius*3)
return true;
if (abs(thing->z - minus->z) > minus->height)
return true;
P_SetTarget(&minus->tracer, thing);
minus->tracer->flags &= ~MF_PUSHABLE;
return true;
}
@ -5428,6 +5430,9 @@ void A_MinusDigging(mobj_t *actor)
A_Chase(actor);
// Carry over shit, maybe
if (P_MobjWasRemoved(actor->tracer) || !actor->tracer->health)
P_SetTarget(&actor->tracer, NULL);
if (!actor->tracer)
{
fixed_t radius = 3*actor->radius;
@ -5477,7 +5482,6 @@ void A_MinusPopup(mobj_t *actor)
else
actor->momz = 10*FRACUNIT;
actor->flags |= MF_SPECIAL|MF_SHOOTABLE;
S_StartSound(actor, sfx_s3k82);
for (i = 1; i <= num; i++)
{
@ -5490,6 +5494,7 @@ void A_MinusPopup(mobj_t *actor)
if (actor->tracer)
P_DamageMobj(actor->tracer, actor, actor, 1, 0);
actor->flags = (actor->flags & ~MF_NOCLIPTHING)|MF_SPECIAL|MF_SHOOTABLE;
}
// Function: A_MinusCheck
@ -12248,7 +12253,6 @@ void A_ConnectToGround(mobj_t *actor)
mobj_t *work;
fixed_t workz;
fixed_t workh;
SINT8 dir;
angle_t ang;
INT32 locvar1 = var1;
INT32 locvar2 = var2;
@ -12262,23 +12266,17 @@ void A_ConnectToGround(mobj_t *actor)
P_AdjustMobjFloorZ_FFloors(actor, actor->subsector->sector, 2);
if (actor->flags2 & MF2_OBJECTFLIP)
{
workz = actor->ceilingz - (actor->z + actor->height);
dir = -1;
}
workz = (actor->z + actor->height) - actor->ceilingz;
else
{
workz = actor->floorz - actor->z;
dir = 1;
}
if (locvar2)
{
workh = FixedMul(mobjinfo[locvar2].height, actor->scale);
if (actor->flags2 & MF2_OBJECTFLIP)
workz -= workh;
workz += workh;
work = P_SpawnMobjFromMobj(actor, 0, 0, workz, locvar2);
workz += dir*workh;
workz += workh;
}
if (!locvar1)
@ -12287,21 +12285,18 @@ void A_ConnectToGround(mobj_t *actor)
if (!(workh = FixedMul(mobjinfo[locvar1].height, actor->scale)))
return;
if (actor->flags2 & MF2_OBJECTFLIP)
workz -= workh;
ang = actor->angle + ANGLE_45;
while (dir*workz < 0)
while (workz < 0)
{
work = P_SpawnMobjFromMobj(actor, 0, 0, workz, locvar1);
if (work)
work->angle = ang;
ang += ANGLE_90;
workz += dir*workh;
workz += workh;
}
if (workz != 0)
actor->z += workz;
actor->z += P_MobjFlip(actor)*workz;
}
// Function: A_SpawnParticleRelative
@ -13466,6 +13461,13 @@ void A_TNTExplode(mobj_t *actor)
if (LUA_CallAction("A_TNTExplode", actor))
return;
#endif
if (actor->tracer)
{
P_SetTarget(&actor->tracer->tracer, NULL);
P_SetTarget(&actor->tracer, NULL);
}
P_UnsetThingPosition(actor);
if (sector_list)
{
@ -13679,8 +13681,6 @@ void A_KillSegments(mobj_t *actor)
static void P_SnapperLegPlace(mobj_t *mo)
{
mobj_t *seg = mo->tracer;
fixed_t x0 = mo->x;
fixed_t y0 = mo->y;
angle_t a = mo->angle;
angle_t fa = (a >> ANGLETOFINESHIFT) & FINEMASK;
fixed_t c = FINECOSINE(fa);
@ -13695,7 +13695,8 @@ static void P_SnapperLegPlace(mobj_t *mo)
fixed_t rad = mo->radius;
INT32 necklen = (32*(mo->info->reactiontime - mo->reactiontime))/mo->info->reactiontime; // Not in FU
P_TeleportMove(seg, mo->x + FixedMul(c, rad) + necklen*c, mo->y + FixedMul(s, rad) + necklen*s, mo->z + mo->height/3);
seg->z = mo->z + ((mo->eflags & MFE_VERTICALFLIP) ? (((mo->height<<1)/3) - seg->height) : mo->height/3);
P_TryMove(seg, mo->x + FixedMul(c, rad) + necklen*c, mo->y + FixedMul(s, rad) + necklen*s, true);
seg->angle = a;
// Move as many legs as available.
@ -13715,13 +13716,14 @@ static void P_SnapperLegPlace(mobj_t *mo)
{
x = c*o2 + s*o1;
y = s*o2 - c*o1;
P_TryMove(seg, x0 + x, y0 + y, true);
seg->z = mo->z + (((mo->eflags & MFE_VERTICALFLIP) ? (mo->height - seg->height) : 0));
P_TryMove(seg, mo->x + x, mo->y + y, true);
P_SetMobjState(seg, seg->info->raisestate);
}
else
P_SetMobjState(seg, seg->info->spawnstate);
seg->angle = R_PointToAngle2(x0, y0, seg->x, seg->y);
seg->angle = R_PointToAngle2(mo->x, mo->y, seg->x, seg->y);
seg = seg->tracer;
} while (seg);
@ -13749,14 +13751,14 @@ void A_SnapperSpawn(mobj_t *actor)
#endif
// It spawns 1 head.
seg = P_SpawnMobj(actor->x, actor->y, actor->z, headtype);
seg = P_SpawnMobjFromMobj(actor, 0, 0, 0, headtype);
P_SetTarget(&ptr->tracer, seg);
ptr = seg;
// It spawns 4 legs which will be handled in the thinker function.
for (i = 1; i <= 4; i++)
{
seg = P_SpawnMobj(actor->x, actor->y, actor->z, legtype);
seg = P_SpawnMobjFromMobj(actor, 0, 0, 0, legtype);
P_SetTarget(&ptr->tracer, seg);
ptr = seg;
@ -13904,51 +13906,43 @@ void A_SnapperThinker(mobj_t *actor)
//
// Description: Spawns a saloon door.
//
// var1 = unused
// var2 = unused
// var1 = mobjtype for sides
// var2 = distance sides should be placed apart
//
void A_SaloonDoorSpawn(mobj_t *actor)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
angle_t ang = actor->angle;
angle_t fa = (ang >> ANGLETOFINESHIFT) & FINEMASK;
fixed_t c = FINECOSINE(fa);
fixed_t s = FINESINE(fa);
INT32 d = 48;
fixed_t x = actor->x;
fixed_t y = actor->y;
fixed_t z = actor->z;
fixed_t c = FINECOSINE(fa)*locvar2;
fixed_t s = FINESINE(fa)*locvar2;
mobj_t *door;
mobjflag2_t ambush = (actor->flags & MF2_AMBUSH);
#ifdef HAVE_BLUA
if (LUA_CallAction("A_SaloonDoorSpawn", actor))
return;
#endif
//Front
door = P_SpawnMobj(x + c*d, y + s*d, z, MT_SALOONDOOR);
if (!locvar1)
return;
// One door...
if (!(door = P_SpawnMobjFromMobj(actor, c, s, 0, locvar1))) return;
door->angle = ang + ANGLE_180;
door->extravalue1 = AngleFixed(door->angle); // Origin angle
door->extravalue2 = 0; // Angular speed
P_SetTarget(&door->tracer, actor); // Origin door
door->flags2 |= ambush; // Can be opened by normal players?
// Origin angle
door->extravalue1 = AngleFixed(door->angle);
// Angular speed
door->extravalue2 = 0;
// Origin door
P_SetTarget(&door->tracer, actor);
//Back
door = P_SpawnMobj(x - c*d, y - s*d, z, MT_SALOONDOOR);
// ...two door!
if (!(door = P_SpawnMobjFromMobj(actor, -c, -s, 0, locvar1))) return;
door->angle = ang;
// Origin angle
door->extravalue1 = AngleFixed(door->angle);
// Angular speed
door->extravalue2 = 0;
// Origin door
P_SetTarget(&door->tracer, actor);
door->extravalue1 = AngleFixed(door->angle); // Origin angle
door->extravalue2 = 0; // Angular speed
P_SetTarget(&door->tracer, actor); // Origin door
door->flags2 |= ambush; // Can be opened by normal players?
}
// Function: A_MinecartSparkThink
@ -14200,7 +14194,7 @@ void A_RolloutSpawn(mobj_t *actor)
actor->target = P_SpawnMobj(actor->x, actor->y, actor->z, locvar2);
actor->target->flags2 |= (actor->flags2 & (MF2_AMBUSH | MF2_OBJECTFLIP)) | MF2_SLIDEPUSH;
actor->target->eflags |= (actor->eflags & MFE_VERTICALFLIP);
if (actor->target->flags2 & MF2_AMBUSH)
{
actor->target->color = SKINCOLOR_SUPERRUST3;
@ -14220,37 +14214,35 @@ void A_RolloutRock(mobj_t *actor)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_RolloutRock", actor))
return;
#endif
UINT8 maxframes = actor->info->reactiontime; // number of frames the mobj cycles through
fixed_t pi = (22*FRACUNIT/7);
fixed_t circumference = FixedMul(2 * pi, actor->radius); // used to calculate when to change frame
fixed_t speed = P_AproxDistance(actor->momx, actor->momy), topspeed = FixedMul(actor->info->speed, actor->scale);
boolean inwater = actor->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER);
#ifdef HAVE_BLUA
if (LUA_CallAction("A_RolloutRock", actor))
return;
#endif
actor->friction = FRACUNIT; // turns out riding on solids sucks, so let's just make it easier on ourselves
if (actor->threshold)
actor->threshold--;
if (inwater && !(actor->flags2 & MF2_AMBUSH)) // buoyancy in water (or lava)
{
UINT8 flip = P_MobjFlip(actor);
fixed_t prevmomz = actor->momz;
actor->momz = FixedMul(actor->momz, locvar2);
actor->momz += flip * FixedMul(locvar2, actor->scale);
if (actor->threshold)
actor->threshold--;
if (flip*prevmomz < 0 && flip*actor->momz >= 0)
if (flip*prevmomz < 0 && flip*actor->momz >= 0 && !actor->threshold)
{
if (actor->eflags & MFE_UNDERWATER)
S_StartSound(actor, sfx_splash);
else if (!actor->threshold)
{
S_StartSound(actor, sfx_splish);
actor->threshold = max((topspeed - speed) >> FRACBITS, 0);
}
actor->threshold = max((topspeed - speed) >> FRACBITS, 8);
}
}
@ -14259,7 +14251,7 @@ void A_RolloutRock(mobj_t *actor)
actor->momx = FixedMul(FixedDiv(actor->momx, speed), topspeed);
actor->momy = FixedMul(FixedDiv(actor->momy, speed), topspeed);
}
if (P_IsObjectOnGround(actor) || inwater) // apply drag to speed (compensates for lack of friction but also works in liquids)
{
actor->momx = FixedMul(actor->momx, locvar1);
@ -14287,13 +14279,13 @@ void A_RolloutRock(mobj_t *actor)
}
actor->frame = actor->reactiontime % maxframes; // set frame
if (!(actor->flags & MF_PUSHABLE)) // if being ridden, don't disappear
actor->fuse = 0;
else if (!actor->fuse && actor->movecount == 1) // otherwise if rock has moved, set its fuse
actor->fuse = actor->info->painchance;
if (actor->fuse && actor->fuse < 2*TICRATE)
actor->flags2 ^= MF2_DONTDRAW;
}

View File

@ -428,7 +428,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|| special->state == &states[S_FANG_BOUNCE4]
|| special->state == &states[S_FANG_PINCHBOUNCE3]
|| special->state == &states[S_FANG_PINCHBOUNCE4])
&& P_MobjFlip(special)*((special->z + special->height/2) - (toucher->z - toucher->height/2)) > -(special->height/4))
&& P_MobjFlip(special)*((special->z + special->height/2) - (toucher->z - toucher->height/2)) > (special->height/4))
{
P_DamageMobj(toucher, special, special, 1, 0);
P_SetTarget(&special->tracer, toucher);
@ -1085,7 +1085,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (player->exiting)
return;
if (player->bumpertime < TICRATE/4)
if (player->bumpertime <= (TICRATE/2)-5)
{
S_StartSound(toucher, special->info->seesound);
if (player->powers[pw_carry] == CR_NIGHTSMODE)
@ -1776,7 +1776,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
return;
case MT_MINECARTSPAWNER:
if (!special->fuse || player->powers[pw_carry] != CR_MINECART)
if (!player->bot && (special->fuse < TICRATE || player->powers[pw_carry] != CR_MINECART))
{
mobj_t *mcart = P_SpawnMobj(special->x, special->y, special->z, MT_MINECART);
P_SetTarget(&mcart->target, toucher);
@ -1786,7 +1786,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
P_ResetPlayer(player);
player->pflags |= PF_JUMPDOWN;
player->powers[pw_carry] = CR_MINECART;
toucher->player->pflags &= ~PF_APPLYAUTOBRAKE;
player->pflags &= ~PF_APPLYAUTOBRAKE;
P_SetTarget(&toucher->tracer, mcart);
toucher->momx = toucher->momy = toucher->momz = 0;

View File

@ -208,7 +208,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
{
angle_t nightsangle = 0;
if (object->player->bumpertime >= TICRATE/4)
if (object->player->bumpertime > (TICRATE/2)-5)
return false;
if ((object->player->pflags & PF_TRANSFERTOCLOSEST) && object->player->axis1 && object->player->axis2)
@ -640,6 +640,34 @@ static void P_SlapStick(mobj_t *fang, mobj_t *pole)
P_SetTarget(&pole->tracer, NULL);
}
static void P_PlayerBarrelCollide(mobj_t *toucher, mobj_t *barrel)
{
if (toucher->momz < 0)
{
if (toucher->z + toucher->momz > barrel->z + barrel->height)
return;
}
else
{
if (toucher->z > barrel->z + barrel->height)
return;
}
if (toucher->momz > 0)
{
if (toucher->z + toucher->height + toucher->momz < barrel->z)
return;
}
else
{
if (toucher->z + toucher->height < barrel->z)
return;
}
if (P_PlayerCanDamage(toucher->player, barrel))
P_DamageMobj(barrel, toucher, toucher, 1, 0);
}
//
// PIT_CheckThing
//
@ -917,12 +945,11 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->type == MT_SALOONDOOR && tmthing->player)
{
if (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer) && tmthing->tracer->health)
mobj_t *ref = (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer)) ? tmthing->tracer : tmthing;
if ((thing->flags & MF2_AMBUSH) || ref != tmthing)
{
fixed_t dx = tmthing->tracer->momx;
fixed_t dy = tmthing->tracer->momy;
fixed_t dm = min(FixedHypot(dx, dy), 16*FRACUNIT);
angle_t ang = R_PointToAngle2(0, 0, dx, dy) - thing->angle;
fixed_t dm = min(FixedHypot(ref->momx, ref->momy), 16*FRACUNIT);
angle_t ang = R_PointToAngle2(0, 0, ref->momx, ref->momy) - thing->angle;
fixed_t s = FINESINE((ang >> ANGLETOFINESHIFT) & FINEMASK);
S_StartSound(tmthing, thing->info->activesound);
thing->extravalue2 += 2*FixedMul(s, dm)/3;
@ -930,39 +957,10 @@ static boolean PIT_CheckThing(mobj_t *thing)
}
}
if (thing->type == MT_TNTBARREL && tmthing->player)
if (thing->type == MT_SALOONDOORCENTER && tmthing->player)
{
if (tmthing->momz < 0)
{
if (tmthing->z + tmthing->momz > thing->z + thing->height)
return true;
}
else
{
if (tmthing->z > thing->z + thing->height)
return true;
}
if (tmthing->momz > 0)
{
if (tmthing->z + tmthing->height + tmthing->momz < thing->z)
return true;
}
else
{
if (tmthing->z + tmthing->height < thing->z)
return true;
}
if ((tmthing->player->pflags & (PF_SPINNING | PF_GLIDING))
|| ((tmthing->player->pflags & PF_JUMPED)
&& (!(tmthing->player->pflags & PF_NOJUMPDAMAGE)
|| (tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY)))
|| (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2)
|| ((tmthing->player->charflags & SF_STOMPDAMAGE || tmthing->player->pflags & PF_BOUNCING)
&& (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height / 2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0))
|| (((tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (tmthing->player->pflags & PF_SHIELDABILITY)))
P_DamageMobj(thing, tmthing, tmthing, 1, 0);
if ((thing->flags & MF2_AMBUSH) || (tmthing->player->powers[pw_carry] == CR_MINECART && tmthing->tracer && !P_MobjWasRemoved(tmthing->tracer)))
return true;
}
if (thing->type == MT_ROLLOUTROCK && tmthing->player && tmthing->health)
@ -1023,6 +1021,9 @@ static boolean PIT_CheckThing(mobj_t *thing)
if (thing->type == MT_PTERABYTE && tmthing->player)
P_DoPterabyteCarry(tmthing->player, thing);
if (thing->type == MT_TNTBARREL && tmthing->player)
P_PlayerBarrelCollide(tmthing, thing);
if (thing->type == MT_VULTURE && tmthing->type == MT_VULTURE)
{
fixed_t dx = thing->x - tmthing->x;
@ -2732,8 +2733,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
#ifdef ESLOPE
// HACK TO FIX DSZ2: apply only if slopes are involved
else if (tmceilingslope && tmceilingz < thingtop && thingtop - tmceilingz <= maxstep)
else if (tmceilingz < thingtop && thingtop - tmceilingz <= maxstep)
{
thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height;
thing->ceilingrover = tmceilingrover;
@ -2748,8 +2748,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
thing->eflags |= MFE_JUSTSTEPPEDDOWN;
}
#ifdef ESLOPE
// HACK TO FIX DSZ2: apply only if slopes are involved
else if (tmfloorslope && tmfloorz > thing->z && tmfloorz - thing->z <= maxstep)
else if (tmfloorz > thing->z && tmfloorz - thing->z <= maxstep)
{
thing->z = thing->floorz = tmfloorz;
thing->floorrover = tmfloorrover;

View File

@ -1578,7 +1578,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo)
// Goop has slower, reversed gravity
if (goopgravity)
gravityadd = -gravityadd/5;
gravityadd = -((gravityadd/5) + (gravityadd/8));
gravityadd = FixedMul(gravityadd, mo->scale);
@ -2369,9 +2369,9 @@ boolean P_CheckDeathPitCollide(mobj_t *mo)
return false;
if (((mo->z <= mo->subsector->sector->floorheight
&& !(mo->eflags & MFE_VERTICALFLIP) && (mo->subsector->sector->flags & SF_FLIPSPECIAL_FLOOR))
&& ((mo->subsector->sector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & SF_FLIPSPECIAL_FLOOR))
|| (mo->z + mo->height >= mo->subsector->sector->ceilingheight
&& (mo->eflags & MFE_VERTICALFLIP) && (mo->subsector->sector->flags & SF_FLIPSPECIAL_CEILING)))
&& ((mo->subsector->sector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & SF_FLIPSPECIAL_CEILING)))
&& (GETSECSPECIAL(mo->subsector->sector->special, 1) == 6
|| GETSECSPECIAL(mo->subsector->sector->special, 1) == 7))
return true;
@ -3434,9 +3434,18 @@ void P_MobjCheckWater(mobj_t *mobj)
|| ((mobj->eflags & MFE_VERTICALFLIP) && mobj->ceilingz-mobj->waterbottom <= height>>1))
return;
if (!wasgroundpounding && (mobj->eflags & MFE_GOOWATER || wasingoo)) { // Decide what happens to your momentum when you enter/leave goopy water.
if (P_MobjFlip(mobj)*mobj->momz < 0) // You are entering the goo?
mobj->momz = FixedMul(mobj->momz, FixedDiv(2*FRACUNIT, 5*FRACUNIT)); // kill momentum significantly, to make the goo feel thick.
if (mobj->eflags & MFE_GOOWATER || wasingoo) { // Decide what happens to your momentum when you enter/leave goopy water.
if (P_MobjFlip(mobj)*mobj->momz > 0)
{
mobj->momz -= (mobj->momz/8); // cut momentum a little bit to prevent multiple bobs
//CONS_Printf("leaving\n");
}
else
{
if (!wasgroundpounding)
mobj->momz >>= 1; // kill momentum significantly, to make the goo feel thick.
//CONS_Printf("entering\n");
}
}
else if (wasinwater && P_MobjFlip(mobj)*mobj->momz > 0)
mobj->momz = FixedMul(mobj->momz, FixedDiv(780*FRACUNIT, 457*FRACUNIT)); // Give the mobj a little out-of-water boost.
@ -7642,6 +7651,7 @@ void P_MobjThinker(mobj_t *mobj)
case MT_ROCKCRUMBLE16:
case MT_WOODDEBRIS:
case MT_BRICKDEBRIS:
case MT_BROKENROBOT:
if (mobj->z <= P_FloorzAtPos(mobj->x, mobj->y, mobj->z, mobj->height)
&& mobj->state != &states[mobj->info->deathstate])
{
@ -7706,6 +7716,237 @@ void P_MobjThinker(mobj_t *mobj)
if (mobj->movedir)
mobj->angle += mobj->movedir;
break;
case MT_ROSY:
{
UINT8 i;
fixed_t pdist = 1700*mobj->scale, work, actualwork;
player_t *player = NULL;
statenum_t stat = (mobj->state-states);
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
continue;
if (!players[i].mo)
continue;
if (players[i].bot)
continue;
if (!players[i].mo->health)
continue;
actualwork = work = FixedHypot(mobj->x-players[i].mo->x, mobj->y-players[i].mo->y);
if (player)
{
if (players[i].skin == 0 || players[i].skin == 3)
work = (2*work)/3;
if (work >= pdist)
continue;
}
pdist = actualwork;
player = &players[i];
}
if (stat == S_ROSY_JUMP || stat == S_ROSY_PAIN)
{
if (P_IsObjectOnGround(mobj))
{
mobj->momx = mobj->momy = 0;
if (player && mobj->cvmem < (-2*TICRATE))
stat = S_ROSY_UNHAPPY;
else
stat = S_ROSY_WALK;
P_SetMobjState(mobj, stat);
}
else if (P_MobjFlip(mobj)*mobj->momz < 0)
mobj->frame = mobj->state->frame+mobj->state->var1;
}
if (!player)
{
if ((stat < S_ROSY_IDLE1 || stat > S_ROSY_IDLE4) && stat != S_ROSY_JUMP)
{
mobj->momx = mobj->momy = 0;
P_SetMobjState(mobj, S_ROSY_IDLE1);
}
}
else
{
boolean dojump = false, targonground, love, makeheart = false;
if (mobj->target != player->mo)
P_SetTarget(&mobj->target, player->mo);
targonground = (P_IsObjectOnGround(mobj->target) && (player->panim == PA_IDLE || player->panim == PA_WALK || player->panim == PA_RUN));
love = (player->skin == 0 || player->skin == 3);
switch (stat)
{
case S_ROSY_IDLE1:
case S_ROSY_IDLE2:
case S_ROSY_IDLE3:
case S_ROSY_IDLE4:
dojump = true;
break;
case S_ROSY_JUMP:
case S_ROSY_PAIN:
// handled above
break;
case S_ROSY_WALK:
{
fixed_t x = mobj->x, y = mobj->y, z = mobj->z;
angle_t angletoplayer = R_PointToAngle2(x, y, mobj->target->x, mobj->target->y);
boolean allowed = P_TryMove(mobj, mobj->target->x, mobj->target->y, false);
P_UnsetThingPosition(mobj);
mobj->x = x;
mobj->y = y;
mobj->z = z;
P_SetThingPosition(mobj);
if (allowed)
{
fixed_t mom, max;
P_Thrust(mobj, angletoplayer, (3*FRACUNIT)>>1);
mom = FixedHypot(mobj->momx, mobj->momy);
max = pdist;
if ((--mobj->extravalue1) <= 0)
{
if (++mobj->frame > mobj->state->frame+mobj->state->var1)
mobj->frame = mobj->state->frame;
if (mom > 12*mobj->scale)
mobj->extravalue1 = 2;
else if (mom > 6*mobj->scale)
mobj->extravalue1 = 3;
else
mobj->extravalue1 = 4;
}
if (max < (mobj->radius + mobj->target->radius))
{
mobj->momx = mobj->target->player->cmomx;
mobj->momy = mobj->target->player->cmomy;
if ((mobj->cvmem > TICRATE && !player->exiting) || !targonground)
P_SetMobjState(mobj, (stat = S_ROSY_STND));
else
{
mobj->target->momx = mobj->momx;
mobj->target->momy = mobj->momy;
P_SetMobjState(mobj, (stat = S_ROSY_HUG));
S_StartSound(mobj, sfx_cdpcm6);
mobj->angle = angletoplayer;
}
}
else
{
max /= 3;
if (max > 30*mobj->scale)
max = 30*mobj->scale;
if (mom > max && max > mobj->scale)
{
max = FixedDiv(max, mom);
mobj->momx = FixedMul(mobj->momx, max);
mobj->momy = FixedMul(mobj->momy, max);
}
if (abs(mobj->momx) > mobj->scale || abs(mobj->momy) > mobj->scale)
mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy);
}
}
else
dojump = true;
}
break;
case S_ROSY_HUG:
if (targonground)
{
player->pflags |= PF_STASIS;
if (mobj->cvmem < 5*TICRATE)
mobj->cvmem++;
if (love && !(leveltime & 7))
makeheart = true;
}
else
{
if (mobj->cvmem < (love ? 5*TICRATE : 0))
{
P_SetMobjState(mobj, (stat = S_ROSY_PAIN));
S_StartSound(mobj, sfx_cdpcm7);
}
else
P_SetMobjState(mobj, (stat = S_ROSY_JUMP));
var1 = var2 = 0;
A_DoNPCPain(mobj);
mobj->cvmem -= TICRATE;
}
break;
case S_ROSY_STND:
if ((pdist > (mobj->radius + mobj->target->radius + 3*(mobj->scale + mobj->target->scale))))
P_SetMobjState(mobj, (stat = S_ROSY_WALK));
else if (!targonground)
;
else
{
if (love && !(leveltime & 15))
makeheart = true;
if (player->exiting || --mobj->cvmem < TICRATE)
{
P_SetMobjState(mobj, (stat = S_ROSY_HUG));
S_StartSound(mobj, sfx_cdpcm6);
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y);
mobj->target->momx = mobj->momx;
mobj->target->momy = mobj->momy;
}
}
break;
case S_ROSY_UNHAPPY:
default:
break;
}
if (stat == S_ROSY_HUG)
{
if (player->panim != PA_IDLE)
P_SetPlayerMobjState(mobj->target, S_PLAY_STND);
player->pflags |= PF_STASIS;
}
if (dojump)
{
P_SetMobjState(mobj, S_ROSY_JUMP);
mobj->z += P_MobjFlip(mobj);
mobj->momx = mobj->momy = 0;
P_SetObjectMomZ(mobj, 6<<FRACBITS, false);
S_StartSound(mobj, sfx_cdfm02);
}
if (makeheart)
{
mobj_t *cdlhrt = P_SpawnMobjFromMobj(mobj, 0, 0, mobj->height, MT_CDLHRT);
cdlhrt->destscale = (5*mobj->scale)>>4;
P_SetScale(cdlhrt, cdlhrt->destscale);
cdlhrt->fuse = (5*TICRATE)>>1;
cdlhrt->momz = mobj->scale;
P_SetTarget(&cdlhrt->target, mobj);
cdlhrt->extravalue1 = mobj->x;
cdlhrt->extravalue2 = mobj->y;
}
}
}
break;
case MT_CDLHRT:
{
if (mobj->cvmem < 24)
mobj->cvmem++;
mobj->movedir += ANG10;
P_UnsetThingPosition(mobj);
mobj->x = mobj->extravalue1 + P_ReturnThrustX(mobj, mobj->movedir, mobj->cvmem*mobj->scale);
mobj->y = mobj->extravalue2 + P_ReturnThrustY(mobj, mobj->movedir, mobj->cvmem*mobj->scale);
P_SetThingPosition(mobj);
if ((--mobj->fuse) < 6)
{
if (!mobj->fuse)
{
P_RemoveMobj(mobj);
return;
}
mobj->frame = (mobj->frame & ~FF_TRANSMASK)|((10-(mobj->fuse*2))<<(FF_TRANSSHIFT));
}
}
break;
case MT_VWREF:
case MT_VWREB:
{
@ -10130,6 +10371,9 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
case MT_FANG:
sc = 4;
break;
case MT_ROSY:
sc = 5;
break;
case MT_CORK:
mobj->flags2 |= MF2_SUPERFIRE;
break;
@ -10145,6 +10389,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
}
case MT_TNTBARREL:
mobj->momx = 1; //stack hack
mobj->flags2 |= MF2_INVERTAIMABLE;
break;
case MT_MINECARTEND:
P_SetTarget(&mobj->tracer, P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_MINECARTENDSOLID));
@ -10478,7 +10723,7 @@ void P_SpawnPrecipitation(void)
if (curWeather == PRECIP_SNOW)
{
// Not in a sector with visible sky -- exception for NiGHTS.
if (!(maptol & TOL_NIGHTS) && precipsector->sector->ceilingpic != skyflatnum)
if ((!(maptol & TOL_NIGHTS) && (precipsector->sector->ceilingpic != skyflatnum)) == !(precipsector->sector->flags & SF_INVERTPRECIP))
continue;
rainmo = P_SpawnSnowMobj(x, y, height, MT_SNOWFLAKE);
@ -10491,7 +10736,7 @@ void P_SpawnPrecipitation(void)
else // everything else.
{
// Not in a sector with visible sky.
if (precipsector->sector->ceilingpic != skyflatnum)
if ((precipsector->sector->ceilingpic != skyflatnum) == !(precipsector->sector->flags & SF_INVERTPRECIP))
continue;
rainmo = P_SpawnRainMobj(x, y, height, MT_RAIN);
@ -11311,6 +11556,16 @@ You should think about modifying the deathmatch starts to take full advantage of
// They're likely facets of the level's design and therefore required to progress.
}
if (i == MT_ROSY)
{
if (!(gametype == GT_COOP || (mthing->options & MTF_EXTRA)))
return; // she doesn't hang out here
else if (mariomode)
i = MT_TOAD; // don't remove on penalty of death
else if (!(netgame || multiplayer) && players[consoleplayer].skin == 5)
return; // no doubles
}
if (i == MT_TOKEN && ((gametype != GT_COOP && gametype != GT_COMPETITION) || ultimatemode || tokenbits == 30 || tokenlist & (1 << tokenbits++)))
return; // you already got this token, or there are too many, or the gametype's not right
@ -11524,9 +11779,10 @@ You should think about modifying the deathmatch starts to take full advantage of
else
mobj->health = FixedMul(ss->sector->ceilingheight-ss->sector->floorheight, 3*(FRACUNIT/4))>>FRACBITS;
break;
case MT_FANG:
case MT_METALSONIC_RACE:
case MT_METALSONIC_BATTLE:
case MT_FANG:
case MT_ROSY:
if (mthing->options & MTF_EXTRA)
{
mobj->color = SKINCOLOR_SILVER;
@ -12428,7 +12684,7 @@ ML_EFFECT5 : Don't stop thinking when too far away
{
if (mthing->options & MTF_AMBUSH)
{
if (i == MT_YELLOWDIAG || i == MT_REDDIAG)
if (i == MT_YELLOWDIAG || i == MT_REDDIAG || i == MT_BLUEDIAG)
mobj->angle += ANGLE_22h;
if (i == MT_YELLOWHORIZ || i == MT_REDHORIZ || i == MT_BLUEHORIZ)
@ -12467,7 +12723,7 @@ ML_EFFECT5 : Don't stop thinking when too far away
if (mthing->options & MTF_OBJECTSPECIAL)
{
if (i == MT_YELLOWDIAG || i == MT_REDDIAG)
if (i == MT_YELLOWDIAG || i == MT_REDDIAG || i == MT_BLUEDIAG)
mobj->flags |= MF_NOGRAVITY;
if ((mobj->flags & MF_MONITOR) && mobj->info->speed != 0)

View File

@ -3618,7 +3618,7 @@ static void P_NetUnArchiveThinkers(void)
{
executor_t *delay = NULL;
UINT32 mobjnum;
for (currentthinker = thlist[i].next; currentthinker != &thlist[i];
for (currentthinker = thlist[THINK_MAIN].next; currentthinker != &thlist[THINK_MAIN];
currentthinker = currentthinker->next)
{
if (currentthinker->function.acp1 != (actionf_p1)T_ExecutorDelay)

View File

@ -4174,26 +4174,11 @@ sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 n
// Check the 3D floor's type...
if (rover->flags & FF_BLOCKPLAYER)
{
boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == topheight));
boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == bottomheight));
// Thing must be on top of the floor to be affected...
if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)
&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING))
{
if ((player->mo->eflags & MFE_VERTICALFLIP) || player->mo->z != topheight)
continue;
}
else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)
&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR))
{
if (!(player->mo->eflags & MFE_VERTICALFLIP)
|| player->mo->z + player->mo->height != bottomheight)
continue;
}
else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH)
{
if (!((player->mo->eflags & MFE_VERTICALFLIP && player->mo->z + player->mo->height == bottomheight)
|| (!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z == topheight)))
continue;
}
if (!(floorallowed || ceilingallowed))
continue;
}
else
{
@ -4234,26 +4219,11 @@ sector_t *P_PlayerTouchingSectorSpecial(player_t *player, INT32 section, INT32 n
// Check the 3D floor's type...
if (rover->flags & FF_BLOCKPLAYER)
{
boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == topheight));
boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == bottomheight));
// Thing must be on top of the floor to be affected...
if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)
&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING))
{
if ((player->mo->eflags & MFE_VERTICALFLIP) || player->mo->z != topheight)
continue;
}
else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)
&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR))
{
if (!(player->mo->eflags & MFE_VERTICALFLIP)
|| player->mo->z + player->mo->height != bottomheight)
continue;
}
else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH)
{
if (!((player->mo->eflags & MFE_VERTICALFLIP && player->mo->z + player->mo->height == bottomheight)
|| (!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z == topheight)))
continue;
}
if (!(floorallowed || ceilingallowed))
continue;
}
else
{
@ -4304,26 +4274,11 @@ static boolean P_ThingIsOnThe3DFloor(mobj_t *mo, sector_t *sector, sector_t *tar
// Check the 3D floor's type...
if (rover->flags & FF_BLOCKPLAYER)
{
boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == top));
boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == bottom));
// Thing must be on top of the floor to be affected...
if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)
&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING))
{
if ((mo->eflags & MFE_VERTICALFLIP) || mo->z != top)
return false;
}
else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)
&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR))
{
if (!(mo->eflags & MFE_VERTICALFLIP)
|| mo->z + mo->height != bottom)
return false;
}
else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH)
{
if (!((mo->eflags & MFE_VERTICALFLIP && mo->z + mo->height == bottom)
|| (!(mo->eflags & MFE_VERTICALFLIP) && mo->z == top)))
return false;
}
if (!(floorallowed || ceilingallowed))
continue;
}
else
{
@ -4345,10 +4300,10 @@ static boolean P_ThingIsOnThe3DFloor(mobj_t *mo, sector_t *sector, sector_t *tar
//
static boolean P_MobjReadyToTrigger(mobj_t *mo, sector_t *sec)
{
if (mo->eflags & MFE_VERTICALFLIP)
return (mo->z+mo->height == P_GetSpecialTopZ(mo, sec, sec) && sec->flags & SF_FLIPSPECIAL_CEILING);
else
return (mo->z == P_GetSpecialBottomZ(mo, sec, sec) && sec->flags & SF_FLIPSPECIAL_FLOOR);
boolean floorallowed = ((sec->flags & SF_FLIPSPECIAL_FLOOR) && ((sec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == P_GetSpecialBottomZ(mo, sec, sec)));
boolean ceilingallowed = ((sec->flags & SF_FLIPSPECIAL_CEILING) && ((sec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == P_GetSpecialTopZ(mo, sec, sec)));
// Thing must be on top of the floor to be affected...
return (floorallowed || ceilingallowed);
}
/** Applies a sector special to a player.
@ -5312,26 +5267,11 @@ sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo)
if (((rover->flags & FF_BLOCKPLAYER) && mo->player)
|| ((rover->flags & FF_BLOCKOTHERS) && !mo->player))
{
boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == topheight));
boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == bottomheight));
// Thing must be on top of the floor to be affected...
if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)
&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING))
{
if ((mo->eflags & MFE_VERTICALFLIP) || mo->z != topheight)
continue;
}
else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)
&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR))
{
if (!(mo->eflags & MFE_VERTICALFLIP)
|| mo->z + mo->height != bottomheight)
continue;
}
else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH)
{
if (!((mo->eflags & MFE_VERTICALFLIP && mo->z + mo->height == bottomheight)
|| (!(mo->eflags & MFE_VERTICALFLIP) && mo->z == topheight)))
continue;
}
if (!(floorallowed || ceilingallowed))
continue;
}
else
{
@ -5374,26 +5314,11 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector)
// Check the 3D floor's type...
if (rover->flags & FF_BLOCKPLAYER)
{
boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == topheight));
boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == bottomheight));
// Thing must be on top of the floor to be affected...
if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)
&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING))
{
if ((player->mo->eflags & MFE_VERTICALFLIP) || player->mo->z != topheight)
continue;
}
else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)
&& !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR))
{
if (!(player->mo->eflags & MFE_VERTICALFLIP)
|| player->mo->z + player->mo->height != bottomheight)
continue;
}
else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH)
{
if (!((player->mo->eflags & MFE_VERTICALFLIP && player->mo->z + player->mo->height == bottomheight)
|| (!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z == topheight)))
continue;
}
if (!(floorallowed || ceilingallowed))
continue;
}
else
{
@ -5450,38 +5375,16 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector)
}
if (!(po->flags & POF_TESTHEIGHT)) // Don't do height checking
{
}
;
else if (po->flags & POF_SOLID)
{
boolean floorallowed = ((polysec->flags & SF_FLIPSPECIAL_FLOOR) && ((polysec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == polysec->ceilingheight));
boolean ceilingallowed = ((polysec->flags & SF_FLIPSPECIAL_CEILING) && ((polysec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == polysec->floorheight));
// Thing must be on top of the floor to be affected...
if ((polysec->flags & SF_FLIPSPECIAL_FLOOR)
&& !(polysec->flags & SF_FLIPSPECIAL_CEILING))
if (!(floorallowed || ceilingallowed))
{
if ((player->mo->eflags & MFE_VERTICALFLIP) || player->mo->z != polysec->ceilingheight)
{
po = (polyobj_t *)(po->link.next);
continue;
}
}
else if ((polysec->flags & SF_FLIPSPECIAL_CEILING)
&& !(polysec->flags & SF_FLIPSPECIAL_FLOOR))
{
if (!(player->mo->eflags & MFE_VERTICALFLIP)
|| player->mo->z + player->mo->height != polysec->floorheight)
{
po = (polyobj_t *)(po->link.next);
continue;
}
}
else if (polysec->flags & SF_FLIPSPECIAL_BOTH)
{
if (!((player->mo->eflags & MFE_VERTICALFLIP && player->mo->z + player->mo->height == polysec->floorheight)
|| (!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z == polysec->ceilingheight)))
{
po = (polyobj_t *)(po->link.next);
continue;
}
po = (polyobj_t *)(po->link.next);
continue;
}
}
else
@ -5580,17 +5483,13 @@ static void P_RunSpecialSectorCheck(player_t *player, sector_t *sector)
f_affectpoint = P_GetSpecialBottomZ(player->mo, sector, sector);
c_affectpoint = P_GetSpecialTopZ(player->mo, sector, sector);
// Only go further if on the ground
if ((sector->flags & SF_FLIPSPECIAL_FLOOR) && !(sector->flags & SF_FLIPSPECIAL_CEILING) && player->mo->z != f_affectpoint)
return;
if ((sector->flags & SF_FLIPSPECIAL_CEILING) && !(sector->flags & SF_FLIPSPECIAL_FLOOR) && player->mo->z + player->mo->height != c_affectpoint)
return;
if ((sector->flags & SF_FLIPSPECIAL_BOTH)
&& player->mo->z != f_affectpoint
&& player->mo->z + player->mo->height != c_affectpoint)
return;
{
boolean floorallowed = ((sector->flags & SF_FLIPSPECIAL_FLOOR) && ((sector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == f_affectpoint));
boolean ceilingallowed = ((sector->flags & SF_FLIPSPECIAL_CEILING) && ((sector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == c_affectpoint));
// Thing must be on top of the floor to be affected...
if (!(floorallowed || ceilingallowed))
return;
}
P_ProcessSpecialSector(player, sector, NULL);
}
@ -6685,6 +6584,11 @@ void P_SpawnSpecials(INT32 fromnetsave)
if (lines[i].flags & ML_EFFECT3)
sectors[s].flags |= SF_TRIGGERSPECIAL_TOUCH;
if (lines[i].flags & ML_EFFECT2)
sectors[s].flags |= SF_TRIGGERSPECIAL_HEADBUMP;
if (lines[i].flags & ML_EFFECT1)
sectors[s].flags |= SF_INVERTPRECIP;
if (lines[i].frontsector && GETSECSPECIAL(lines[i].frontsector->special, 4) == 12)
sectors[s].camsec = sides[*lines[i].sidenum].sector-sectors;
@ -7178,15 +7082,15 @@ void P_SpawnSpecials(INT32 fromnetsave)
break;
case 252: // Shatter block (breaks when touched)
ffloorflags = FF_EXISTS|FF_RENDERALL|FF_BUSTUP|FF_SHATTER;
ffloorflags = FF_EXISTS|FF_BLOCKOTHERS|FF_RENDERALL|FF_BUSTUP|FF_SHATTER;
if (lines[i].flags & ML_NOCLIMB)
ffloorflags |= FF_SOLID|FF_SHATTERBOTTOM;
ffloorflags |= FF_BLOCKPLAYER|FF_SHATTERBOTTOM;
P_AddFakeFloorsByLine(i, ffloorflags, secthinkers);
break;
case 253: // Translucent shatter block (see 76)
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_RENDERALL|FF_BUSTUP|FF_SHATTER|FF_TRANSLUCENT, secthinkers);
P_AddFakeFloorsByLine(i, FF_EXISTS|FF_BLOCKOTHERS|FF_RENDERALL|FF_BUSTUP|FF_SHATTER|FF_TRANSLUCENT, secthinkers);
break;
case 254: // Bustable block

View File

@ -482,7 +482,7 @@ static inline void P_DoSpecialStageStuff(void)
countspheres += players[i].spheres;
// If in water, deplete timer 6x as fast.
if (players[i].mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER))
if (players[i].mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER) && !(players[i].powers[pw_shield] & SH_PROTECTWATER))
players[i].nightstime -= 5;
if (--players[i].nightstime > 6)
{

View File

@ -898,7 +898,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
if (player->mo->target)
{
player->angle_pos = R_PointToAngle2(player->mo->target->x, player->mo->target->y, player->mo->x, player->mo->y);
player->drawangle = player->mo->angle = player->angle_pos
player->drawangle = player->angle_pos
+ ((player->mo->target->flags2 & MF2_AMBUSH) ? // if axis is invert, take the opposite right angle
-ANGLE_90 : ANGLE_90); // flyangle is always 0 here, below is kept for posterity
/*(player->flyangle > 90 && player->flyangle < 270 ? ANGLE_90 : -ANGLE_90)
@ -2260,7 +2260,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
else if (!player->skidtime)
player->pflags &= ~PF_GLIDING;
}
else if (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)
else if (player->charability2 == CA2_MELEE && ((player->panim == PA_ABILITY2) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY)))
{
if (player->mo->state-states != S_PLAY_MELEE_LANDING)
{
@ -4674,8 +4674,9 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
if (player->speed < FixedMul(player->maxdash, player->mo->scale))
#endif
{
player->drawangle = player->mo->angle;
P_InstaThrust(player->mo, player->mo->angle, FixedMul(player->maxdash, player->mo->scale));
if (player->panim == PA_IDLE)
player->drawangle = player->mo->angle;
P_InstaThrust(player->mo, player->drawangle, FixedMul(player->maxdash, player->mo->scale));
}
player->mo->momx += player->cmomx;
player->mo->momy += player->cmomy;
@ -5873,35 +5874,28 @@ static void P_3dMovement(player_t *player)
else
topspeed = normalspd;
}
else if (player->powers[pw_super] || player->powers[pw_sneakers])
{
thrustfactor = player->thrustfactor*2;
acceleration = player->accelstart/2 + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration/2;
if (player->powers[pw_tailsfly])
topspeed = normalspd;
else if (player->mo->eflags & (MFE_UNDERWATER|MFE_GOOWATER))
{
topspeed = normalspd;
acceleration = 2*acceleration/3;
}
else
topspeed = normalspd * 2;
}
else
{
thrustfactor = player->thrustfactor;
acceleration = player->accelstart + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration;
if (player->powers[pw_tailsfly])
topspeed = normalspd/2;
else if (player->mo->eflags & (MFE_UNDERWATER|MFE_GOOWATER))
if (player->powers[pw_super] || player->powers[pw_sneakers])
{
topspeed = normalspd/2;
acceleration = 2*acceleration/3;
topspeed = 5 * normalspd / 3; // 1.67x
thrustfactor = player->thrustfactor*2;
acceleration = player->accelstart/2 + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration/2;
}
else
{
topspeed = normalspd;
thrustfactor = player->thrustfactor;
acceleration = player->accelstart + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration;
}
if (player->powers[pw_tailsfly])
topspeed >>= 1;
else if (player->mo->eflags & (MFE_UNDERWATER|MFE_GOOWATER))
{
topspeed >>= 1;
acceleration = 2*acceleration/3;
}
}
if (spin) // Prevent gaining speed whilst rolling!
@ -8892,7 +8886,7 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius)
continue;
if (mo->type == MT_MINUS && !(mo->flags & (MF_SPECIAL|MF_SHOOTABLE)))
mo->flags |= MF_SPECIAL|MF_SHOOTABLE;
mo->flags = (mo->flags & ~MF_NOCLIPTHING)|MF_SPECIAL|MF_SHOOTABLE;
if (mo->type == MT_EGGGUARD && mo->tracer) //nuke Egg Guard's shield!
P_KillMobj(mo->tracer, inflictor, source, DMG_NUKE);
@ -10291,7 +10285,7 @@ static sector_t *P_GetMinecartSector(fixed_t x, fixed_t y, fixed_t z, fixed_t *n
ffloor_t *rover;
for (rover = sec->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
if (!(rover->flags & (FF_EXISTS|FF_BLOCKOTHERS)))
continue;
*nz = *rover->t_slope ? P_GetZAt(*rover->t_slope, x, y) : *rover->topheight;

View File

@ -483,7 +483,7 @@ static UINT8 *R_GenerateTexture(size_t texnum)
wadnum = patch->wad;
lumpnum = patch->lump;
lumplength = W_LumpLengthPwad(wadnum, lumpnum);
realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE);
realpatch = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); // can't use W_CachePatchNumPwad because OpenGL
#ifndef NO_PNG_LUMPS
if (R_IsLumpPNG((UINT8 *)realpatch, lumplength))
@ -557,7 +557,7 @@ static UINT8 *R_GenerateTexture(size_t texnum)
texturememory += blocksize;
block = Z_Malloc(blocksize+1, PU_STATIC, &texturecache[texnum]);
memset(block, 0xFF, blocksize+1); // Transparency hack
memset(block, TRANSPARENTPIXEL, blocksize+1); // Transparency hack
// columns lookup table
colofs = (UINT32 *)(void *)block;
@ -2520,7 +2520,11 @@ void R_PrecacheLevel(void)
"spritememory: %s k\n", sizeu1(flatmemory>>10), sizeu2(texturememory>>10), sizeu3(spritememory>>10));
}
// https://github.com/coelckers/prboom-plus/blob/master/prboom2/src/r_patch.c#L350
//
// R_CheckIfPatch
//
// Returns true if the lump is a valid patch.
//
boolean R_CheckIfPatch(lumpnum_t lump)
{
size_t size;
@ -2565,6 +2569,71 @@ boolean R_CheckIfPatch(lumpnum_t lump)
return result;
}
//
// R_TextureToFlat
//
// Convert a texture to a flat.
//
void R_TextureToFlat(size_t tex, UINT8 *flat)
{
texture_t *texture = textures[tex];
fixed_t col, ofs;
column_t *column;
UINT8 *desttop, *dest, *deststop;
UINT8 *source;
// yea
R_CheckTextureCache(tex);
desttop = flat;
deststop = desttop + (texture->width * texture->height);
for (col = 0; col < texture->width; col++, desttop++)
{
// no post_t info
if (!texture->holes)
{
column = (column_t *)(R_GetColumn(tex, col));
source = (UINT8 *)(column);
dest = desttop;
for (ofs = 0; dest < deststop && ofs < texture->height; ofs++)
{
if (source[ofs] != TRANSPARENTPIXEL)
*dest = source[ofs];
dest += texture->width;
}
}
else
{
INT32 topdelta, prevdelta = -1;
column = (column_t *)((UINT8 *)R_GetColumn(tex, col) - 3);
while (column->topdelta != 0xff)
{
topdelta = column->topdelta;
if (topdelta <= prevdelta)
topdelta += prevdelta;
prevdelta = topdelta;
dest = desttop + (topdelta * texture->width);
source = (UINT8 *)column + 3;
for (ofs = 0; dest < deststop && ofs < column->length; ofs++)
{
if (source[ofs] != TRANSPARENTPIXEL)
*dest = source[ofs];
dest += texture->width;
}
column = (column_t *)((UINT8 *)column + column->length + 4);
}
}
}
}
//
// R_PatchToFlat
//
// Convert a patch to a flat.
//
void R_PatchToFlat(patch_t *patch, UINT8 *flat)
{
fixed_t col, ofs;
@ -2599,7 +2668,124 @@ void R_PatchToFlat(patch_t *patch, UINT8 *flat)
}
}
//
// R_FlatToPatch
//
// Convert a flat to a patch.
//
static unsigned char imgbuf[1<<26];
patch_t *R_FlatToPatch(UINT8 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize, boolean transparency)
{
UINT32 x, y;
UINT8 *img;
UINT8 *imgptr = imgbuf;
UINT8 *colpointers, *startofspan;
size_t size = 0;
// Write image size and offset
WRITEINT16(imgptr, width);
WRITEINT16(imgptr, height);
WRITEINT16(imgptr, leftoffset);
WRITEINT16(imgptr, topoffset);
// Leave placeholder to column pointers
colpointers = imgptr;
imgptr += width*4;
// Write columns
for (x = 0; x < width; x++)
{
int lastStartY = 0;
int spanSize = 0;
startofspan = NULL;
// Write column pointer
WRITEINT32(colpointers, imgptr - imgbuf);
// Write pixels
for (y = 0; y < height; y++)
{
UINT8 paletteIndex = raw[((y * width) + x)];
boolean opaque = transparency ? (paletteIndex != TRANSPARENTPIXEL) : true;
// End span if we have a transparent pixel
if (!opaque)
{
if (startofspan)
WRITEUINT8(imgptr, 0);
startofspan = NULL;
continue;
}
// Start new column if we need to
if (!startofspan || spanSize == 255)
{
int writeY = y;
// If we reached the span size limit, finish the previous span
if (startofspan)
WRITEUINT8(imgptr, 0);
if (y > 254)
{
// Make sure we're aligned to 254
if (lastStartY < 254)
{
WRITEUINT8(imgptr, 254);
WRITEUINT8(imgptr, 0);
imgptr += 2;
lastStartY = 254;
}
// Write stopgap empty spans if needed
writeY = y - lastStartY;
while (writeY > 254)
{
WRITEUINT8(imgptr, 254);
WRITEUINT8(imgptr, 0);
imgptr += 2;
writeY -= 254;
}
}
startofspan = imgptr;
WRITEUINT8(imgptr, writeY);
imgptr += 2;
spanSize = 0;
lastStartY = y;
}
// Write the pixel
WRITEUINT8(imgptr, paletteIndex);
spanSize++;
startofspan[1] = spanSize;
}
if (startofspan)
WRITEUINT8(imgptr, 0);
WRITEUINT8(imgptr, 0xFF);
}
size = imgptr-imgbuf;
img = Z_Malloc(size, PU_STATIC, NULL);
memcpy(img, imgbuf, size);
Z_Free(raw);
if (destsize != NULL)
*destsize = size;
return (patch_t *)img;
}
#ifndef NO_PNG_LUMPS
//
// R_IsLumpPNG
//
// Returns true if the lump is a valid PNG.
//
boolean R_IsLumpPNG(const UINT8 *d, size_t s)
{
if (s < 67) // http://garethrees.org/2007/11/14/pngcrush/
@ -2812,125 +2998,31 @@ static UINT8 *PNG_RawConvert(const UINT8 *png, UINT16 *w, UINT16 *h, INT16 *topo
return flat;
}
//
// R_PNGToFlat
//
// Convert a PNG to a flat.
UINT8 *R_PNGToFlat(levelflat_t *levelflat, UINT8 *png, size_t size)
//
UINT8 *R_PNGToFlat(UINT16 *width, UINT16 *height, UINT8 *png, size_t size)
{
return PNG_RawConvert(png, &levelflat->width, &levelflat->height, NULL, NULL, size);
return PNG_RawConvert(png, width, height, NULL, NULL, size);
}
//
// R_PNGToPatch
//
// Convert a PNG to a patch.
static unsigned char imgbuf[1<<26];
//
patch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize, boolean transparency)
{
UINT16 width, height;
INT16 topoffset = 0, leftoffset = 0;
UINT8 *raw = PNG_RawConvert(png, &width, &height, &topoffset, &leftoffset, size);
UINT32 x, y;
UINT8 *img;
UINT8 *imgptr = imgbuf;
UINT8 *colpointers, *startofspan;
if (!raw)
I_Error("R_PNGToPatch: conversion failed");
// Write image size and offset
WRITEINT16(imgptr, width);
WRITEINT16(imgptr, height);
WRITEINT16(imgptr, leftoffset);
WRITEINT16(imgptr, topoffset);
// Leave placeholder to column pointers
colpointers = imgptr;
imgptr += width*4;
// Write columns
for (x = 0; x < width; x++)
{
int lastStartY = 0;
int spanSize = 0;
startofspan = NULL;
//printf("%d ", x);
// Write column pointer (@TODO may be wrong)
WRITEINT32(colpointers, imgptr - imgbuf);
// Write pixels
for (y = 0; y < height; y++)
{
UINT8 paletteIndex = raw[((y * width) + x)];
boolean opaque = transparency ? (paletteIndex != TRANSPARENTPIXEL) : true;
// End span if we have a transparent pixel
if (!opaque)
{
if (startofspan)
WRITEUINT8(imgptr, 0);
startofspan = NULL;
continue;
}
// Start new column if we need to
if (!startofspan || spanSize == 255)
{
int writeY = y;
// If we reached the span size limit, finish the previous span
if (startofspan)
WRITEUINT8(imgptr, 0);
if (y > 254)
{
// Make sure we're aligned to 254
if (lastStartY < 254)
{
WRITEUINT8(imgptr, 254);
WRITEUINT8(imgptr, 0);
imgptr += 2;
lastStartY = 254;
}
// Write stopgap empty spans if needed
writeY = y - lastStartY;
while (writeY > 254)
{
WRITEUINT8(imgptr, 254);
WRITEUINT8(imgptr, 0);
imgptr += 2;
writeY -= 254;
}
}
startofspan = imgptr;
WRITEUINT8(imgptr, writeY);///@TODO calculate starting y pos
imgptr += 2;
spanSize = 0;
lastStartY = y;
}
// Write the pixel
WRITEUINT8(imgptr, paletteIndex);
spanSize++;
startofspan[1] = spanSize;
}
if (startofspan)
WRITEUINT8(imgptr, 0);
WRITEUINT8(imgptr, 0xFF);
}
size = imgptr-imgbuf;
img = Z_Malloc(size, PU_STATIC, NULL);
memcpy(img, imgbuf, size);
Z_Free(raw);
if (destsize != NULL)
*destsize = size;
return (patch_t *)img;
return R_FlatToPatch(raw, width, height, leftoffset, topoffset, destsize, transparency);
}
boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size)
@ -3001,53 +3093,3 @@ boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size)
}
#endif
#endif
void R_TextureToFlat(size_t tex, UINT8 *flat)
{
texture_t *texture = textures[tex];
fixed_t col, ofs;
column_t *column;
UINT8 *desttop, *dest, *deststop;
UINT8 *source;
desttop = flat;
deststop = desttop + (texture->width * texture->height);
for (col = 0; col < texture->width; col++, desttop++)
{
column = (column_t *)R_GetColumn(tex, col);
if (!texture->holes)
{
dest = desttop;
source = (UINT8 *)(column);
for (ofs = 0; dest < deststop && ofs < texture->height; ofs++)
{
if (source[ofs] != TRANSPARENTPIXEL)
*dest = source[ofs];
dest += texture->width;
}
}
else
{
INT32 topdelta, prevdelta = -1;
while (column->topdelta != 0xff)
{
topdelta = column->topdelta;
if (topdelta <= prevdelta)
topdelta += prevdelta;
prevdelta = topdelta;
dest = desttop + (topdelta * texture->width);
source = (UINT8 *)(column) + 3;
for (ofs = 0; dest < deststop && ofs < column->length; ofs++)
{
if (source[ofs] != TRANSPARENTPIXEL)
*dest = source[ofs];
dest += texture->width;
}
column = (column_t *)((UINT8 *)column + column->length + 4);
}
}
}
}

View File

@ -159,15 +159,14 @@ const char *R_NameForColormap(extracolormap_t *extra_colormap);
#define R_PutRgbaRGBA(r, g, b, a) (R_PutRgbaRGB(r, g, b) + R_PutRgbaA(a))
boolean R_CheckIfPatch(lumpnum_t lump);
UINT8 NearestColor(UINT8 r, UINT8 g, UINT8 b);
void R_PatchToFlat(patch_t *patch, UINT8 *flat);
void R_TextureToFlat(size_t tex, UINT8 *flat);
void R_PatchToFlat(patch_t *patch, UINT8 *flat);
patch_t *R_FlatToPatch(UINT8 *raw, UINT16 width, UINT16 height, UINT16 leftoffset, UINT16 topoffset, size_t *destsize, boolean transparency);
#ifndef NO_PNG_LUMPS
boolean R_IsLumpPNG(const UINT8 *d, size_t s);
UINT8 *R_PNGToFlat(levelflat_t *levelflat, UINT8 *png, size_t size);
UINT8 *R_PNGToFlat(UINT16 *width, UINT16 *height, UINT8 *png, size_t size);
patch_t *R_PNGToPatch(const UINT8 *png, size_t size, size_t *destsize, boolean transparency);
boolean R_PNGDimensions(UINT8 *png, INT16 *width, INT16 *height, size_t size);
#endif

View File

@ -263,10 +263,15 @@ typedef struct pslope_s
typedef enum
{
SF_FLIPSPECIAL_FLOOR = 1,
SF_FLIPSPECIAL_CEILING = 2,
SF_FLIPSPECIAL_BOTH = 3,
SF_TRIGGERSPECIAL_TOUCH = 4,
// flipspecial - planes with effect
SF_FLIPSPECIAL_FLOOR = 1,
SF_FLIPSPECIAL_CEILING = 1<<1,
SF_FLIPSPECIAL_BOTH = (SF_FLIPSPECIAL_FLOOR|SF_FLIPSPECIAL_CEILING),
// triggerspecial - conditions under which plane touch causes effect
SF_TRIGGERSPECIAL_TOUCH = 1<<2,
SF_TRIGGERSPECIAL_HEADBUMP = 1<<3,
// invertprecip - inverts presence of precipitation
SF_INVERTPRECIP = 1<<4,
} sectorflags_t;
//

View File

@ -1219,6 +1219,7 @@ void R_RegisterEngineStuff(void)
#endif
CV_RegisterVar(&cv_grmd2);
CV_RegisterVar(&cv_grspritebillboarding);
CV_RegisterVar(&cv_grskydome);
#endif
#ifdef HWRENDER

View File

@ -650,6 +650,11 @@ static void R_DrawSkyPlane(visplane_t *pl)
}
}
//
// R_CheckPowersOfTwo
//
// Self-explanatory?
//
boolean R_CheckPowersOfTwo(void)
{
boolean wpow2 = (!(ds_flatwidth & (ds_flatwidth - 1)));
@ -667,6 +672,11 @@ boolean R_CheckPowersOfTwo(void)
return ds_powersoftwo;
}
//
// R_CheckFlatLength
//
// Determine the flat's dimensions from the lump length.
//
void R_CheckFlatLength(size_t size)
{
switch (size)
@ -723,7 +733,24 @@ void R_CheckFlatLength(size_t size)
}
}
static UINT8 *R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boolean ispng)
//
// R_GenerateFlat
//
// Generate a flat from specified width and height.
//
static UINT8 *R_GenerateFlat(UINT16 width, UINT16 height)
{
UINT8 *flat = Z_Malloc(width * height, PU_LEVEL, NULL);
memset(flat, TRANSPARENTPIXEL, width * height);
return flat;
}
//
// R_GetTextureFlat
//
// Convert a texture or patch to a flat.
//
static UINT8 *R_GetTextureFlat(levelflat_t *levelflat, boolean leveltexture, boolean ispng)
{
UINT8 *flat;
textureflat_t *texflat = &texflats[levelflat->texturenum];
@ -747,14 +774,14 @@ static UINT8 *R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boole
// If the texture changed, or the patch doesn't exist, convert either of them to a flat.
if (levelflat->flatpatch == NULL || texturechanged)
{
// Level texture
if (leveltexture)
{
texture_t *texture = textures[levelflat->texturenum];
texflat->width = ds_flatwidth = texture->width;
texflat->height = ds_flatheight = texture->height;
texflat->flat = Z_Malloc(ds_flatwidth * ds_flatheight, PU_LEVEL, NULL);
memset(texflat->flat, TRANSPARENTPIXEL, ds_flatwidth * ds_flatheight);
texflat->flat = R_GenerateFlat(ds_flatwidth, ds_flatheight);
R_TextureToFlat(levelflat->texturenum, texflat->flat);
flat = texflat->flat;
@ -762,13 +789,14 @@ static UINT8 *R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boole
levelflat->width = ds_flatwidth;
levelflat->height = ds_flatheight;
}
// Patch (never happens yet)
else
{
patch = (patch_t *)ds_source;
#ifndef NO_PNG_LUMPS
if (ispng)
{
levelflat->flatpatch = R_PNGToFlat(levelflat, ds_source, W_LumpLength(levelflat->lumpnum));
levelflat->flatpatch = R_PNGToFlat(&levelflat->width, &levelflat->height, ds_source, W_LumpLength(levelflat->lumpnum));
levelflat->topoffset = levelflat->leftoffset = 0;
ds_flatwidth = levelflat->width;
ds_flatheight = levelflat->height;
@ -782,8 +810,7 @@ static UINT8 *R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boole
levelflat->topoffset = patch->topoffset * FRACUNIT;
levelflat->leftoffset = patch->leftoffset * FRACUNIT;
levelflat->flatpatch = Z_Malloc(ds_flatwidth * ds_flatheight, PU_LEVEL, NULL);
memset(levelflat->flatpatch, TRANSPARENTPIXEL, ds_flatwidth * ds_flatheight);
levelflat->flatpatch = R_GenerateFlat(ds_flatwidth, ds_flatheight);
R_PatchToFlat(patch, levelflat->flatpatch);
}
flat = levelflat->flatpatch;
@ -794,11 +821,11 @@ static UINT8 *R_GetPatchFlat(levelflat_t *levelflat, boolean leveltexture, boole
flat = levelflat->flatpatch;
ds_flatwidth = levelflat->width;
ds_flatheight = levelflat->height;
xoffs += levelflat->leftoffset;
yoffs += levelflat->topoffset;
}
xoffs += levelflat->leftoffset;
yoffs += levelflat->topoffset;
levelflat->lasttexturenum = levelflat->texturenum;
return flat;
}
@ -963,15 +990,15 @@ void R_DrawSinglePlane(visplane_t *pl)
// Check if the flat is actually a wall texture.
if (levelflat->texturenum != 0 && levelflat->texturenum != -1)
flat = R_GetPatchFlat(levelflat, true, false);
flat = R_GetTextureFlat(levelflat, true, false);
#ifndef NO_PNG_LUMPS
// Maybe it's a PNG?!
else if (R_IsLumpPNG(ds_source, size))
flat = R_GetPatchFlat(levelflat, false, true);
flat = R_GetTextureFlat(levelflat, false, true);
#endif
// Maybe it's just a patch, then?
else if (R_CheckIfPatch(levelflat->lumpnum))
flat = R_GetPatchFlat(levelflat, false, false);
flat = R_GetTextureFlat(levelflat, false, false);
// It's a raw flat.
else
{

View File

@ -1230,7 +1230,7 @@ static void R_ProjectSprite(mobj_t *thing)
else
range = 1;
scalestep = (yscale2 - yscale)/range;
scalestep = (yscale2 - yscale)/range ?: 1;
// The following two are alternate sorting methods which might be more applicable in some circumstances. TODO - maybe enable via MF2?
// sortscale = max(yscale, yscale2);
@ -1637,7 +1637,7 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel)
mobj_t *thing;
precipmobj_t *precipthing; // Tails 08-25-2002
INT32 lightnum;
fixed_t approx_dist, limit_dist;
fixed_t approx_dist, limit_dist, hoop_limit_dist;
if (rendermode != render_soft)
return;
@ -1668,7 +1668,9 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel)
// Handle all things in sector.
// If a limit exists, handle things a tiny bit different.
if ((limit_dist = (fixed_t)((maptol & TOL_NIGHTS) ? cv_drawdist_nights.value : cv_drawdist.value) << FRACBITS))
limit_dist = (fixed_t)(cv_drawdist.value) << FRACBITS;
hoop_limit_dist = (fixed_t)(cv_drawdist_nights.value) << FRACBITS;
if (limit_dist || hoop_limit_dist)
{
for (thing = sec->thinglist; thing; thing = thing->snext)
{
@ -1677,8 +1679,16 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel)
approx_dist = P_AproxDistance(viewx-thing->x, viewy-thing->y);
if (approx_dist > limit_dist)
continue;
if (thing->sprite == SPR_HOOP)
{
if (hoop_limit_dist && approx_dist > hoop_limit_dist)
continue;
}
else
{
if (limit_dist && approx_dist > limit_dist)
continue;
}
R_ProjectSprite(thing);
}
@ -2786,9 +2796,9 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
}
if (P_IsLocalPlayer(player))
CONS_Alert(CONS_WARNING, M_GetText("Requested skin not found\n"));
CONS_Alert(CONS_WARNING, M_GetText("Requested skin %d not found\n"), skinnum);
else if(server || IsPlayerAdmin(consoleplayer))
CONS_Alert(CONS_WARNING, "Player %d (%s) skin not found\n", playernum, player_names[playernum]);
CONS_Alert(CONS_WARNING, "Player %d (%s) skin %d not found\n", playernum, player_names[playernum], skinnum);
SetPlayerSkinByNum(playernum, 0); // not found put the sonic skin
}

View File

@ -79,6 +79,7 @@ void *hwSym(const char *funcName,void *handle)
GETFUNC(Init);
GETFUNC(Draw2DLine);
GETFUNC(DrawPolygon);
GETFUNC(RenderSkyDome);
GETFUNC(SetBlend);
GETFUNC(ClearBuffer);
GETFUNC(SetTexture);

View File

@ -1629,6 +1629,7 @@ void I_StartupGraphics(void)
HWD.pfnFinishUpdate = NULL;
HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL);
HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL);
HWD.pfnRenderSkyDome = hwSym("RenderSkyDome",NULL);
HWD.pfnSetBlend = hwSym("SetBlend",NULL);
HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL);
HWD.pfnSetTexture = hwSym("SetTexture",NULL);

View File

@ -878,7 +878,11 @@ boolean I_SetSongSpeed(float speed)
#ifdef HAVE_OPENMPT
if (openmpt_mhandle)
{
char modspd[16];
char modspd[13];
if (speed > 4.0f)
speed = 4.0f; // Limit this to 4x to prevent crashing, stupid fix but... ~SteelT 27/9/19
sprintf(modspd, "%g", speed);
openmpt_module_ctl_set(openmpt_mhandle, "play.tempo_factor", modspd);
return true;

View File

@ -1474,12 +1474,9 @@ static void ST_drawNightsRecords(void)
if (P_HasGrades(gamemap, stplyr->lastmare + 1))
{
if (aflag)
V_DrawTranslucentPatch(BASEVIDWIDTH/2 + 60, 160, aflag,
ngradeletters[P_GetGrade(stplyr->lastmarescore, gamemap, stplyr->lastmare)]);
else
V_DrawScaledPatch(BASEVIDWIDTH/2 + 60, 160, 0,
ngradeletters[P_GetGrade(stplyr->lastmarescore, gamemap, stplyr->lastmare)]);
UINT8 grade = P_GetGrade(stplyr->lastmarescore, gamemap, stplyr->lastmare);
if (modeattacking || grade >= GRADE_A)
V_DrawTranslucentPatch(BASEVIDWIDTH/2 + 60, 160, aflag, ngradeletters[grade]);
}
break;
}
@ -1857,7 +1854,8 @@ static void ST_drawNiGHTSHUD(void)
numbersize = 48/2;
if ((oldspecialstage && leveltime & 2)
&& (stplyr->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)))
&& (stplyr->mo->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER))
&& !(stplyr->powers[pw_shield] & SH_PROTECTWATER))
col = SKINCOLOR_ORANGE;
ST_DrawNightsOverlayNum((160 + numbersize)<<FRACBITS, 14<<FRACBITS, FRACUNIT, V_PERPLAYER|V_SNAPTOTOP, realnightstime, nightsnum, col);

View File

@ -112,6 +112,7 @@ static CV_PossibleValue_t CV_MD2[] = {{0, "Off"}, {1, "On"}, {2, "Old"}, {0, NUL
// console variables in development
consvar_t cv_grmd2 = {"gr_md2", "Off", CV_SAVE, CV_MD2, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grspritebillboarding = {"gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
consvar_t cv_grskydome = {"gr_skydome", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
#endif
// local copy of the palette for V_GetColor()

View File

@ -102,6 +102,7 @@ static loadfunc_t hwdFuncTable[] = {
{"FinishUpdate@4", &hwdriver.pfnFinishUpdate},
{"Draw2DLine@12", &hwdriver.pfnDraw2DLine},
{"DrawPolygon@16", &hwdriver.pfnDrawPolygon},
{"RenderSkyDome@16", &hwdriver.pfnRenderSkyDome},
{"SetBlend@4", &hwdriver.pfnSetBlend},
{"ClearBuffer@12", &hwdriver.pfnClearBuffer},
{"SetTexture@4", &hwdriver.pfnSetTexture},
@ -133,6 +134,7 @@ static loadfunc_t hwdFuncTable[] = {
{"FinishUpdate", &hwdriver.pfnFinishUpdate},
{"Draw2DLine", &hwdriver.pfnDraw2DLine},
{"DrawPolygon", &hwdriver.pfnDrawPolygon},
{"RenderSkyDome", &hwdriver.pfnRenderSkyDome},
{"SetBlend", &hwdriver.pfnSetBlend},
{"ClearBuffer", &hwdriver.pfnClearBuffer},
{"SetTexture", &hwdriver.pfnSetTexture},