Merge branch 'master' into knuxstuff

This commit is contained in:
lachwright 2019-10-15 02:49:44 +08:00
commit 9cad882626
52 changed files with 2722 additions and 450 deletions

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

@ -234,7 +234,9 @@ typedef enum
CR_ZOOMTUBE,
CR_ROPEHANG,
CR_MACESPIN,
CR_MINECART
CR_MINECART,
CR_ROLLOUT,
CR_PTERABYTE
} carrytype_t; // pw_carry
// Player powers. (don't edit this comment)

View file

@ -2447,6 +2447,14 @@ static actionpointer_t actionpointers[] =
{{A_SaloonDoorSpawn}, "A_SALOONDOORSPAWN"},
{{A_MinecartSparkThink}, "A_MINECARTSPARKTHINK"},
{{A_ModuloToState}, "A_MODULOTOSTATE"},
{{A_LavafallRocks}, "A_LAVAFALLROCKS"},
{{A_LavafallLava}, "A_LAVAFALLLAVA"},
{{A_FallingLavaCheck}, "A_FALLINGLAVACHECK"},
{{A_FireShrink}, "A_FIRESHRINK"},
{{A_SpawnPterabytes}, "A_SPAWNPTERABYTES"},
{{A_PterabyteHover}, "A_PTERABYTEHOVER"},
{{A_RolloutSpawn}, "A_ROLLOUTSPAWN"},
{{A_RolloutRock}, "A_ROLLOUTROCK"},
{{NULL}, "NONE"},
// This NULL entry must be the last in the list
@ -4619,6 +4627,22 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_CANARIVOREGAS_7",
"S_CANARIVOREGAS_8",
// Pyre Fly
"S_PYREFLY_FLY",
"S_PYREFLY_BURN",
"S_PYREFIRE1",
"S_PYREFIRE2",
// Pterabyte
"S_PTERABYTESPAWNER",
"S_PTERABYTEWAYPOINT",
"S_PTERABYTE_FLY1",
"S_PTERABYTE_FLY2",
"S_PTERABYTE_FLY3",
"S_PTERABYTE_FLY4",
"S_PTERABYTE_SWOOPDOWN",
"S_PTERABYTE_SWOOPUP",
// Boss Explosion
"S_BOSSEXPLODE",
@ -5862,7 +5886,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",
@ -5895,6 +5919,28 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_FLAMEJETFLAMEB2",
"S_FLAMEJETFLAMEB3",
// Lavafall
"S_LAVAFALL_DORMANT",
"S_LAVAFALL_TELL",
"S_LAVAFALL_SHOOT",
"S_LAVAFALL_LAVA1",
"S_LAVAFALL_LAVA2",
"S_LAVAFALL_LAVA3",
"S_LAVAFALLROCK",
// Rollout Rock
"S_ROLLOUTSPAWN",
"S_ROLLOUTROCK",
// RVZ scenery
"S_BIGFERNLEAF",
"S_BIGFERN1",
"S_BIGFERN2",
"S_JUNGLEPALM",
"S_TORCHFLOWER",
"S_WALLVINE_LONG",
"S_WALLVINE_SHORT",
// Trapgoyles
"S_TRAPGOYLE",
"S_TRAPGOYLE_CHECK",
@ -5946,6 +5992,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",
@ -5953,6 +6000,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
@ -6624,6 +6681,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
"S_SPLISH8",
"S_SPLISH9",
// Lava splish
"S_LAVASPLISH",
// added water splash
"S_SPLASH1",
"S_SPLASH2",
@ -7274,6 +7334,11 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_UNIBALL", // Unidus Ball
"MT_CANARIVORE", // Canarivore
"MT_CANARIVORE_GAS", // Canarivore gas
"MT_PYREFLY", // Pyre Fly
"MT_PYREFLY_FIRE", // Pyre Fly fire
"MT_PTERABYTESPAWNER", // Pterabyte spawner
"MT_PTERABYTEWAYPOINT", // Pterabyte waypoint
"MT_PTERABYTE", // Pterabyte
// Generic Boss Items
"MT_BOSSEXPLODE",
@ -7602,7 +7667,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",
@ -7619,6 +7684,20 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_FLAMEJETFLAMEB", // Blade's flame
"MT_LAVAFALL",
"MT_LAVAFALL_LAVA",
"MT_LAVAFALLROCK",
"MT_ROLLOUTSPAWN",
"MT_ROLLOUTROCK",
"MT_BIGFERNLEAF",
"MT_BIGFERN",
"MT_JUNGLEPALM",
"MT_TORCHFLOWER",
"MT_WALLVINE_LONG",
"MT_WALLVINE_SHORT",
// Dark City Scenery
// Egg Rock Scenery
@ -7650,6 +7729,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",
@ -7657,6 +7737,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
@ -7785,6 +7867,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
"MT_RAIN", // Rain
"MT_SNOWFLAKE", // Snowflake
"MT_SPLISH", // Water splish!
"MT_LAVASPLISH", // Lava splish!
"MT_SMOKE",
"MT_SMALLBUBBLE", // small bubble
"MT_MEDIUMBUBBLE", // medium bubble
@ -8610,6 +8693,8 @@ struct {
{"CR_ROPEHANG",CR_ROPEHANG},
{"CR_MACESPIN",CR_MACESPIN},
{"CR_MINECART",CR_MINECART},
{"CR_ROLLOUT", CR_ROLLOUT},
{"CR_PTERABYTE",CR_PTERABYTE},
// Ring weapons (ringweapons_t)
// Useful for A_GiveWeapon

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

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

@ -180,6 +180,8 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_UNID
&lspr[NOLIGHT], // SPR_CANA
&lspr[NOLIGHT], // SPR_CANG
&lspr[NOLIGHT], // SPR_PYRE
&lspr[NOLIGHT], // SPR_PTER
// Generic Boos Items
&lspr[JETLIGHT_L], // SPR_JETF // Boss jet fumes
@ -260,6 +262,7 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_WSPB
&lspr[NOLIGHT], // SPR_STPT
&lspr[NOLIGHT], // SPR_BMNE
&lspr[NOLIGHT], // SPR_PUMI
// Monitor Boxes
&lspr[NOLIGHT], // SPR_MSTV
@ -377,6 +380,10 @@ light_t *t_lspr[NUMSPRITES] =
// Red Volcano Scenery
&lspr[REDBALL_L], // SPR_FLME
&lspr[REDBALL_L], // SPR_DFLM
&lspr[NOLIGHT], // SPR_LFAL
&lspr[NOLIGHT], // SPR_JPLA
&lspr[NOLIGHT], // SPR_TFLO
&lspr[NOLIGHT], // SPR_WVIN
// Dark City Scenery
@ -388,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
@ -474,6 +483,7 @@ light_t *t_lspr[NUMSPRITES] =
&lspr[NOLIGHT], // SPR_RAIN
&lspr[NOLIGHT], // SPR_SNO1
&lspr[NOLIGHT], // SPR_SPLH
&lspr[NOLIGHT], // SPR_LSPL
&lspr[NOLIGHT], // SPR_SPLA
&lspr[NOLIGHT], // SPR_SMOK
&lspr[NOLIGHT], // SPR_BUBL

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

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

@ -68,6 +68,8 @@ char sprnames[NUMSPRITES + 1][5] =
"UNID", // Unidus
"CANA", // Canarivore
"CANG", // Canarivore gas
"PYRE", // Pyre Fly
"PTER", // Pterabyte
// Generic Boss Items
"JETF", // Boss jet fumes
@ -149,6 +151,7 @@ char sprnames[NUMSPRITES + 1][5] =
"WSPB", // Wall spike base
"STPT", // Starpost
"BMNE", // Big floating mine
"PUMI", // Rollout Rock
// Monitor Boxes
"MSTV", // MiSc TV sprites
@ -263,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
@ -272,6 +274,10 @@ char sprnames[NUMSPRITES + 1][5] =
// Red Volcano Scenery
"FLME", // Flame jet
"DFLM", // Blade's flame
"LFAL", // Lavafall
"JPLA", // Jungle palm
"TFLO", // Torch flower
"WVIN", // Wall vines
// Dark City Scenery
@ -283,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
@ -369,6 +377,7 @@ char sprnames[NUMSPRITES + 1][5] =
"RAIN", // Rain
"SNO1", // Snowflake
"SPLH", // Water Splish
"LSPL", // Lava Splish
"SPLA", // Water Splash
"SMOK",
"BUBL", // Bubble
@ -1185,6 +1194,22 @@ state_t states[NUMSTATES] =
{SPR_CANG, 0|FF_TRANS80, 10, {NULL}, 0, 0, S_CANARIVOREGAS_8}, // S_CANARIVOREGAS_7
{SPR_CANG, 0|FF_TRANS90, 10, {NULL}, 0, 0, S_NULL}, // S_CANARIVOREGAS_8
// Pyre Fly
{SPR_PYRE, FF_ANIMATE, -1, {NULL}, 3, 2, S_NULL}, // S_PYREFLY_FLY
{SPR_PYRE, 4|FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 3, 2, S_NULL}, // S_PYREFLY_BURN
{SPR_FLAM, FF_FULLBRIGHT, 10, {NULL}, 0, 0, S_PYREFIRE2}, // S_PYREFIRE1
{SPR_FLAM, 1|FF_FULLBRIGHT, 10, {A_FireShrink}, 0, 16, S_NULL}, // S_PYREFIRE2
// Pterabyte
{SPR_NULL, 0, -1, {A_SpawnPterabytes}, 0, 0, S_PTERABYTESPAWNER}, // S_PTERABYTESPAWNER
{SPR_NULL, 0, 1, {A_PterabyteHover}, 0, 0, S_PTERABYTEWAYPOINT}, // S_PTERABYTEWAYPOINT
{SPR_PTER, 0, 6, {NULL}, 0, 0, S_PTERABYTE_FLY2}, // S_PTERABYTE_FLY1
{SPR_PTER, 1, 2, {NULL}, 0, 0, S_PTERABYTE_FLY3}, // S_PTERABYTE_FLY2
{SPR_PTER, 2, 6, {NULL}, 0, 0, S_PTERABYTE_FLY4}, // S_PTERABYTE_FLY3
{SPR_PTER, 3, 2, {NULL}, 0, 0, S_PTERABYTE_FLY1}, // S_PTERABYTE_FLY4
{SPR_PTER, 4, 1, {NULL}, 0, 0, S_PTERABYTE_SWOOPDOWN}, // S_PTERABYTE_SWOOPDOWN
{SPR_PTER, 0, 1, {NULL}, 0, 0, S_PTERABYTE_SWOOPUP}, // S_PTERABYTE_SWOOPUP
// Boss Explosion
{SPR_BOM2, FF_FULLBRIGHT|FF_ANIMATE, (5*7), {NULL}, 6, 5, S_NULL}, // S_BOSSEXPLODE
@ -2463,8 +2488,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
@ -2499,6 +2524,28 @@ state_t states[NUMSTATES] =
{SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40, 1, {A_MoveRelative}, 0, 7, S_FLAMEJETFLAMEB3}, // S_FLAMEJETFLAMEB2
{SPR_DFLM, FF_FULLBRIGHT|FF_TRANS40|FF_ANIMATE, (12*7), {NULL}, 7, 12, S_NULL}, // S_FLAMEJETFLAMEB3
// Lavafall
{SPR_LFAL, 5, 1, {NULL}, 0, 0, S_LAVAFALL_DORMANT}, // S_LAVAFALL_DORMANT
{SPR_LFAL, 6|FF_ANIMATE, 4, {A_LavafallRocks}, 1, 2, S_LAVAFALL_TELL}, // S_LAVAFALL_TELL
{SPR_LFAL, 9|FF_FULLBRIGHT|FF_ANIMATE, 2, {A_LavafallLava}, 1, 1, S_LAVAFALL_SHOOT}, // S_LAVAFALL_SHOOT
{SPR_LFAL, FF_FULLBRIGHT, 1, {A_FallingLavaCheck}, 0, 0, S_LAVAFALL_LAVA2}, // S_LAVAFALL_LAVA1
{SPR_LFAL, FF_FULLBRIGHT, 1, {A_FallingLavaCheck}, 0, 0, S_LAVAFALL_LAVA1}, // S_LAVAFALL_LAVA2
{SPR_LFAL, 2|FF_FULLBRIGHT|FF_ANIMATE, 9, {NULL}, 2, 3, S_NULL}, // S_LAVAFALL_LAVA3
{SPR_LFAL, 11|FF_ANIMATE|FF_RANDOMANIM, 12, {NULL}, 3, 3, S_LAVAFALLROCK}, // S_LAVAFALLROCK
// Rollout Rock
{SPR_NULL, 0, 1, {A_RolloutSpawn}, 256*FRACUNIT, MT_ROLLOUTROCK, S_ROLLOUTSPAWN}, // S_ROLLOUTSPAWN
{SPR_PUMI, 0, 1, {A_RolloutRock}, 63*FRACUNIT/64, 7*FRACUNIT/10, S_ROLLOUTROCK}, // S_ROLLOUTROCK
// RVZ scenery
{SPR_JPLA, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_BIGFERNLEAF
{SPR_JPLA, 1, 1, {NULL}, 0, 0, S_BIGFERN2}, // S_BIGFERN1
{SPR_JPLA, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BIGFERN2
{SPR_JPLA, 2, -1, {NULL}, 0, 0, S_NULL}, // S_JUNGLEPALM
{SPR_TFLO, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_TORCHFLOWER}, // S_TORCHFLOWER
{SPR_WVIN, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_WALLVINE_LONG
{SPR_WVIN, 1|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_WALLVINE_SHORT
// Trapgoyles
{SPR_GARG, 0, 67, {NULL}, 0, 0, S_TRAPGOYLE_CHECK}, // S_TRAPGOYLE
{SPR_GARG, 0, 3, {NULL}, 0, 0, S_TRAPGOYLE_FIRE1}, // S_TRAPGOYLE_CHECK
@ -2553,6 +2600,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
@ -2560,6 +2608,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
@ -3235,6 +3293,9 @@ state_t states[NUMSTATES] =
{SPR_SPLH, FF_TRANS50|7, 2, {NULL}, 0, 0, S_SPLISH9}, // S_SPLISH8
{SPR_SPLH, FF_TRANS50|8, 2, {NULL}, 0, 0, S_NULL}, // S_SPLISH9
// Lava splish
{SPR_LSPL, FF_ANIMATE, 16, {NULL}, 7, 2, S_NULL}, // S_LAVASPLISH
// Water Splash
{SPR_SPLA, FF_TRANS50 , 3, {NULL}, 0, 0, S_SPLASH2}, // S_SPLASH1
{SPR_SPLA, FF_TRANS70|1, 3, {NULL}, 0, 0, S_SPLASH3}, // S_SPLASH2
@ -3546,7 +3607,7 @@ state_t states[NUMSTATES] =
// Puma (Mario fireball)
{SPR_PUMA, FF_FULLBRIGHT|2, 1, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_START2}, // S_PUMA_START1
{SPR_PUMA, FF_FULLBRIGHT|2, 1, {A_PlaySound}, sfx_s3k70, 1, S_PUMA_UP1}, // S_PUMA_START2
{SPR_PUMA, FF_FULLBRIGHT|2, 1, {A_PlaySound}, sfx_s3k70, 1 + (1<<16), S_PUMA_UP1}, // S_PUMA_START2
{SPR_PUMA, FF_FULLBRIGHT , 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_UP2}, // S_PUMA_UP1
{SPR_PUMA, FF_FULLBRIGHT|1, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_UP3}, // S_PUMA_UP2
{SPR_PUMA, FF_FULLBRIGHT|2, 2, {A_FishJump}, 0, MT_PUMATRAIL, S_PUMA_UP1}, // S_PUMA_UP3
@ -4781,7 +4842,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
},
@ -4808,7 +4869,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
},
@ -5028,6 +5089,141 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_PYREFLY
136, // doomednum
S_PYREFLY_FLY, // spawnstate
1, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_PYREFLY_BURN, // meleestate
S_NULL, // missilestate
S_XPLD_FLICKY, // deathstate
S_NULL, // xdeathstate
sfx_pop, // deathsound
1, // speed
24*FRACUNIT, // radius
34*FRACUNIT, // height
0, // display offset
DMG_FIRE, // mass
0, // damage
sfx_None, // activesound
MF_NOGRAVITY|MF_SPECIAL|MF_SHOOTABLE|MF_ENEMY|MF_SLIDEME, // flags
S_NULL // raisestate
},
{ // MT_PYREFLY_FIRE
-1, // doomednum
S_PYREFIRE1, // spawnstate
1, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
24*FRACUNIT, // radius
34*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOGRAVITY|MF_NOBLOCKMAP|MF_FIRE|MF_PAIN, // flags
S_NULL // raisestate
},
{ // MT_PTERABYTESPAWNER
135, // doomednum
S_PTERABYTESPAWNER, // spawnstate
1, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
16*FRACUNIT, // radius
16*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOGRAVITY|MF_NOCLIPTHING|MF_NOBLOCKMAP|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate
},
{ // MT_PTERABYTEWAYPOINT
-1, // doomednum
S_PTERABYTEWAYPOINT, // spawnstate
1, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
4*FRACUNIT, // speed
24*FRACUNIT, // radius
48*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOGRAVITY|MF_NOCLIPTHING|MF_NOBLOCKMAP|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate
},
{ // MT_PTERABYTE
-1, // doomednum
S_PTERABYTE_FLY1, // spawnstate
1, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_pscree, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_XPLD_FLICKY, // deathstate
S_NULL, // xdeathstate
sfx_pop, // deathsound
4*FRACUNIT, // speed
24*FRACUNIT, // radius
48*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_SPECIAL|MF_SHOOTABLE|MF_ENEMY|MF_NOGRAVITY|MF_SLIDEME, // flags
S_NULL // raisestate
},
{ // MT_BOSSEXPLODE
-1, // doomednum
S_BOSSEXPLODE, // spawnstate
@ -12200,7 +12396,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
},
@ -12528,9 +12724,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
@ -12551,7 +12747,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
},
@ -12852,6 +13048,303 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_LAVAFALL
1304, // doomednum
S_LAVAFALL_DORMANT, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_lvfal1, // seesound
8, // reactiontime
sfx_s3kd5l, // 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
30*FRACUNIT, // radius
32*FRACUNIT, // height
1, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOGRAVITY|MF_SPAWNCEILING, // flags
S_NULL // raisestate
},
{ // MT_LAVAFALL_LAVA
-1, // doomednum
S_LAVAFALL_LAVA1, // 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_LAVAFALL_LAVA3, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
30*FRACUNIT, // radius
48*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_SPECIAL|MF_PAIN|MF_NOGRAVITY, // flags
S_NULL // raisestate
},
{ // MT_LAVAFALLROCK
-1, // doomednum
S_LAVAFALLROCK, // 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
8*FRACUNIT, // radius
8*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP, // flags
S_NULL // raisestate
},
{ // MT_ROLLOUTSPAWN
1305, // doomednum
S_ROLLOUTSPAWN, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
0, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
8*FRACUNIT, // radius
8*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_SPAWNCEILING, // flags
S_NULL // raisestate
},
{ // MT_ROLLOUTROCK
-1, // doomednum
S_ROLLOUTROCK, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime (sets number of frames the rock cycles through)
sfx_None, // attacksound
S_NULL, // painstate
12*TICRATE, // painchance (sets how long an unridden rock should last before disappearing - set to 0 to disable)
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
32*FRACUNIT, // speed
30*FRACUNIT, // radius
60*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_PUSHABLE|MF_SOLID|MF_SLIDEME, // flags
S_NULL // raisestate
},
{ // MT_BIGFERNLEAF
-1, // doomednum
S_BIGFERNLEAF, // 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
32*FRACUNIT, // radius
48*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_SCENERY|MF_NOBLOCKMAP, // flags
S_NULL // raisestate
},
{ // MT_BIGFERN
1306, // doomednum
S_BIGFERN1, // 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
32*FRACUNIT, // radius
48*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_SCENERY|MF_NOBLOCKMAP|MF_RUNSPAWNFUNC, // flags
S_NULL // raisestate
},
{ // MT_JUNGLEPALM
1307, // doomednum
S_JUNGLEPALM, // 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
32*FRACUNIT, // radius
48*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_SCENERY|MF_NOBLOCKMAP, // flags
S_NULL // raisestate
},
{ // MT_TORCHFLOWER
1308, // doomednum
S_TORCHFLOWER, // 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
14*FRACUNIT, // radius
110*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_SCENERY|MF_NOBLOCKMAP, // flags
S_NULL // raisestate
},
{ // MT_WALLVINE_LONG
1309, // doomednum
S_WALLVINE_LONG, // 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
1*FRACUNIT, // radius
288*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_SCENERY|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP, // flags
S_NULL // raisestate
},
{ // MT_WALLVINE_SHORT
1310, // doomednum
S_WALLVINE_SHORT, // 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
1*FRACUNIT, // radius
288*FRACUNIT, // height
0, // display offset
100, // mass
0, // damage
sfx_None, // activesound
MF_SCENERY|MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP, // flags
S_NULL // raisestate
},
{ // MT_TRAPGOYLE
1500, // doomednum
S_TRAPGOYLE, // spawnstate
@ -13446,6 +13939,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
@ -13581,6 +14101,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
@ -16636,6 +17210,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_LAVASPLISH
-1, // doomednum
S_LAVASPLISH, // 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
6*FRACUNIT, // radius
1*FRACUNIT, // height
0, // display offset
100, // mass
1, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY, // flags
S_NULL // raisestate
},
{ // MT_SMOKE
-1, // doomednum
S_SMOKE1, // spawnstate

View file

@ -268,6 +268,14 @@ void A_SnapperThinker();
void A_SaloonDoorSpawn();
void A_MinecartSparkThink();
void A_ModuloToState();
void A_LavafallRocks();
void A_LavafallLava();
void A_FallingLavaCheck();
void A_FireShrink();
void A_SpawnPterabytes();
void A_PterabyteHover();
void A_RolloutSpawn();
void A_RolloutRock();
// ratio of states to sprites to mobj types is roughly 6 : 1 : 1
#define NUMMOBJFREESLOTS 512
@ -316,6 +324,8 @@ typedef enum sprite
SPR_UNID, // Unidus
SPR_CANA, // Canarivore
SPR_CANG, // Canarivore gas
SPR_PYRE, // Pyre Fly
SPR_PTER, // Pterabyte
// Generic Boss Items
SPR_JETF, // Boss jet fumes
@ -397,6 +407,7 @@ typedef enum sprite
SPR_WSPB, // Wall spike base
SPR_STPT, // Starpost
SPR_BMNE, // Big floating mine
SPR_PUMI, // Rollout Rock
// Monitor Boxes
SPR_MSTV, // MiSc TV sprites
@ -511,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
@ -520,6 +530,10 @@ typedef enum sprite
// Red Volcano Scenery
SPR_FLME, // Flame jet
SPR_DFLM, // Blade's flame
SPR_LFAL, // Lavafall
SPR_JPLA, // Jungle palm
SPR_TFLO, // Torch flower
SPR_WVIN, // Wall vines
// Dark City Scenery
@ -531,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
@ -617,6 +633,7 @@ typedef enum sprite
SPR_RAIN, // Rain
SPR_SNO1, // Snowflake
SPR_SPLH, // Water Splish
SPR_LSPL, // Lava Splish
SPR_SPLA, // Water Splash
SPR_SMOK,
SPR_BUBL, // Bubble
@ -1334,6 +1351,22 @@ typedef enum state
S_CANARIVOREGAS_7,
S_CANARIVOREGAS_8,
// Pyre Fly
S_PYREFLY_FLY,
S_PYREFLY_BURN,
S_PYREFIRE1,
S_PYREFIRE2,
// Pterabyte
S_PTERABYTESPAWNER,
S_PTERABYTEWAYPOINT,
S_PTERABYTE_FLY1,
S_PTERABYTE_FLY2,
S_PTERABYTE_FLY3,
S_PTERABYTE_FLY4,
S_PTERABYTE_SWOOPDOWN,
S_PTERABYTE_SWOOPUP,
// Boss Explosion
S_BOSSEXPLODE,
@ -2577,7 +2610,7 @@ typedef enum state
// Saloon door
S_SALOONDOOR,
S_SALOONDOORTHINKER,
S_SALOONDOORCENTER,
// Train cameo
S_TRAINCAMEOSPAWNER_1,
@ -2610,6 +2643,28 @@ typedef enum state
S_FLAMEJETFLAMEB2,
S_FLAMEJETFLAMEB3,
// Lavafall
S_LAVAFALL_DORMANT,
S_LAVAFALL_TELL,
S_LAVAFALL_SHOOT,
S_LAVAFALL_LAVA1,
S_LAVAFALL_LAVA2,
S_LAVAFALL_LAVA3,
S_LAVAFALLROCK,
// Rollout Rock
S_ROLLOUTSPAWN,
S_ROLLOUTROCK,
// RVZ scenery
S_BIGFERNLEAF,
S_BIGFERN1,
S_BIGFERN2,
S_JUNGLEPALM,
S_TORCHFLOWER,
S_WALLVINE_LONG,
S_WALLVINE_SHORT,
// Trapgoyles
S_TRAPGOYLE,
S_TRAPGOYLE_CHECK,
@ -2661,6 +2716,7 @@ typedef enum state
S_LAMPPOST1, // normal
S_LAMPPOST2, // with snow
S_HANGSTAR,
S_MISTLETOE,
// Xmas GFZ bushes
S_XMASBLUEBERRYBUSH,
S_XMASBERRYBUSH,
@ -2668,6 +2724,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
@ -3339,6 +3405,9 @@ typedef enum state
S_SPLISH8,
S_SPLISH9,
// Lava Splish
S_LAVASPLISH,
// added water splash
S_SPLASH1,
S_SPLASH2,
@ -4011,6 +4080,11 @@ typedef enum mobj_type
MT_UNIBALL, // Unidus Ball
MT_CANARIVORE, // Canarivore
MT_CANARIVORE_GAS, // Canarivore gas
MT_PYREFLY, // Pyre Fly
MT_PYREFLY_FIRE, // Pyre Fly fire
MT_PTERABYTESPAWNER, // Pterabyte spawner
MT_PTERABYTEWAYPOINT, // Pterabyte waypoint
MT_PTERABYTE, // Pterabyte
// Generic Boss Items
MT_BOSSEXPLODE,
@ -4339,7 +4413,7 @@ typedef enum mobj_type
MT_MINECARTSIDEMARK,
MT_MINECARTSPARK,
MT_SALOONDOOR,
MT_SALOONDOORTHINKER,
MT_SALOONDOORCENTER,
MT_TRAINCAMEOSPAWNER,
MT_TRAINSEG,
MT_TRAINDUSTSPAWNER,
@ -4356,6 +4430,20 @@ typedef enum mobj_type
MT_FLAMEJETFLAMEB, // Blade's flame
MT_LAVAFALL,
MT_LAVAFALL_LAVA,
MT_LAVAFALLROCK,
MT_ROLLOUTSPAWN,
MT_ROLLOUTROCK,
MT_BIGFERNLEAF,
MT_BIGFERN,
MT_JUNGLEPALM,
MT_TORCHFLOWER,
MT_WALLVINE_LONG,
MT_WALLVINE_SHORT,
// Dark City Scenery
// Egg Rock Scenery
@ -4387,6 +4475,7 @@ typedef enum mobj_type
MT_LAMPPOST1, // normal
MT_LAMPPOST2, // with snow
MT_HANGSTAR,
MT_MISTLETOE,
// Xmas GFZ bushes
MT_XMASBLUEBERRYBUSH,
MT_XMASBERRYBUSH,
@ -4394,6 +4483,8 @@ typedef enum mobj_type
// FHZ
MT_FHZICE1,
MT_FHZICE2,
MT_ROSY,
MT_CDLHRT,
// Halloween Scenery
// Pumpkins
@ -4522,6 +4613,7 @@ typedef enum mobj_type
MT_RAIN, // Rain
MT_SNOWFLAKE, // Snowflake
MT_SPLISH, // Water splish!
MT_LAVASPLISH, // Lava splish!
MT_SMOKE,
MT_SMALLBUBBLE, // small bubble
MT_MEDIUMBUBBLE, // medium bubble

View file

@ -816,15 +816,12 @@ static int lib_pCheckDeathPitCollide(lua_State *L)
static int lib_pCheckSolidLava(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR));
//HUDSAFE
INLEVEL
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
if (!rover)
return LUA_ErrInvalid(L, "ffloor_t");
lua_pushboolean(L, P_CheckSolidLava(mo, rover));
lua_pushboolean(L, P_CheckSolidLava(rover));
return 1;
}

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},
@ -8330,7 +8331,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 +8412,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

@ -298,6 +298,14 @@ void A_SnapperThinker(mobj_t *actor);
void A_SaloonDoorSpawn(mobj_t *actor);
void A_MinecartSparkThink(mobj_t *actor);
void A_ModuloToState(mobj_t *actor);
void A_LavafallRocks(mobj_t *actor);
void A_LavafallLava(mobj_t *actor);
void A_FallingLavaCheck(mobj_t *actor);
void A_FireShrink(mobj_t *actor);
void A_SpawnPterabytes(mobj_t *actor);
void A_PterabyteHover(mobj_t *actor);
void A_RolloutSpawn(mobj_t *actor);
void A_RolloutRock(mobj_t *actor);
//for p_enemy.c
@ -5343,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;
}
@ -5420,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;
@ -5469,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++)
{
@ -5482,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
@ -8408,8 +8421,8 @@ void A_ChangeAngleAbsolute(mobj_t *actor)
//
// var1 = sound # to play
// var2:
// 0 = Play sound without an origin
// 1 = Play sound using calling object as origin
// lower 16 bits = If 1, play sound using calling object as origin. If 0, play sound without an origin
// upper 16 bits = If 1, do not play sound during preticker.
//
void A_PlaySound(mobj_t *actor)
{
@ -8420,7 +8433,10 @@ void A_PlaySound(mobj_t *actor)
return;
#endif
S_StartSound(locvar2 ? actor : NULL, locvar1);
if (leveltime < 2 && (locvar2 >> 16))
return;
S_StartSound((locvar2 & 65535) ? actor : NULL, locvar1);
}
// Function: A_FindTarget
@ -12197,7 +12213,7 @@ void A_MineExplode(mobj_t *actor)
#undef dist
if (actor->watertop != INT32_MAX)
P_SpawnMobj(actor->x, actor->y, actor->watertop, MT_SPLISH);
P_SpawnMobj(actor->x, actor->y, actor->watertop, (actor->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH);
}
}
@ -13455,6 +13471,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)
{
@ -13668,8 +13691,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);
@ -13684,7 +13705,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.
@ -13704,13 +13726,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);
@ -13738,14 +13761,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;
@ -13893,51 +13916,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
@ -13998,3 +14013,290 @@ void A_ModuloToState(mobj_t *actor)
P_SetMobjState(actor, (locvar2));
modulothing++;
}
// Function: A_LavafallRocks
//
// Description: Spawn random rock particles.
//
// var1 = unused
// var2 = unused
//
void A_LavafallRocks(mobj_t *actor)
{
UINT8 i;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_LavafallRocks", actor))
return;
#endif
// Don't spawn rocks unless a player is relatively close by.
for (i = 0; i < MAXPLAYERS; ++i)
if (playeringame[i] && players[i].mo
&& P_AproxDistance(actor->x - players[i].mo->x, actor->y - players[i].mo->y) < (1600 << FRACBITS))
break; // Stop looking.
if (i < MAXPLAYERS)
{
angle_t fa = (FixedAngle(P_RandomKey(360) << FRACBITS) >> ANGLETOFINESHIFT) & FINEMASK;
fixed_t offset = P_RandomRange(4, 12) << FRACBITS;
fixed_t xoffs = FixedMul(FINECOSINE(fa), actor->radius + offset);
fixed_t yoffs = FixedMul(FINESINE(fa), actor->radius + offset);
P_SpawnMobjFromMobj(actor, xoffs, yoffs, 0, MT_LAVAFALLROCK);
}
}
// Function: A_LavafallLava
//
// Description: Spawn lava from lavafall.
//
// var1 = unused
// var2 = unused
//
void A_LavafallLava(mobj_t *actor)
{
mobj_t *lavafall;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_LavafallLava", actor))
return;
#endif
if ((40 - actor->fuse) % (2*(actor->scale >> FRACBITS)))
return;
lavafall = P_SpawnMobjFromMobj(actor, 0, 0, -8*FRACUNIT, MT_LAVAFALL_LAVA);
lavafall->momz = -P_MobjFlip(actor)*25*FRACUNIT;
}
// Function: A_FallingLavaCheck
//
// Description: If actor hits the ground or a water surface, enter the death animation.
//
// var1 = unused
// var2 = unused
//
void A_FallingLavaCheck(mobj_t *actor)
{
#ifdef HAVE_BLUA
if (LUA_CallAction("A_FallingLavaCheck", actor))
return;
#endif
if (actor->eflags & MFE_TOUCHWATER || P_IsObjectOnGround(actor))
{
actor->flags = MF_NOGRAVITY|MF_NOCLIPTHING;
actor->momz = 0;
if (actor->eflags & MFE_TOUCHWATER)
actor->z = (actor->eflags & MFE_VERTICALFLIP) ? actor->waterbottom : actor->watertop;
P_SetMobjState(actor, actor->info->deathstate);
}
}
// Function: A_FireShrink
//
// Description: Shrink the actor down to the specified scale at the specified speed.
//
// var1 = Scale to shrink to
// var2 = Shrinking speed
//
void A_FireShrink(mobj_t *actor)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_FireShrink", actor))
return;
#endif
actor->destscale = locvar1;
actor->scalespeed = FRACUNIT/locvar2;
}
// Function: A_SpawnPterabytes
//
// Description: Spawn Pterabytes around the actor in a circle.
//
// var1 = unused
// var2 = unused
//
void A_SpawnPterabytes(mobj_t *actor)
{
mobj_t *waypoint, *ptera;
fixed_t c, s;
fixed_t rad = 280*FRACUNIT;
angle_t ang = 0;
angle_t interval, fa;
UINT8 amount = 1;
UINT8 i;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_SpawnPterabytes", actor))
return;
#endif
if (actor->spawnpoint)
amount = actor->spawnpoint->extrainfo + 1;
interval = FixedAngle(FRACUNIT*360/amount);
for (i = 0; i < amount; i++)
{
fa = (ang >> ANGLETOFINESHIFT) & FINEMASK;
c = FINECOSINE(fa);
s = FINESINE(fa);
waypoint = P_SpawnMobjFromMobj(actor, FixedMul(c, rad), FixedMul(s, rad), 0, MT_PTERABYTEWAYPOINT);
waypoint->angle = ang + ANGLE_90;
P_SetTarget(&waypoint->tracer, actor);
ptera = P_SpawnMobjFromMobj(waypoint, 0, 0, 0, MT_PTERABYTE);
ptera->angle = waypoint->angle;
P_SetTarget(&ptera->tracer, waypoint);
ptera->extravalue1 = 0;
ang += interval;
}
}
// Function: A_PterabyteHover
//
// Description: Hover in a circular fashion, bobbing up and down slightly.
//
// var1 = unused
// var2 = unused
//
void A_PterabyteHover(mobj_t *actor)
{
angle_t ang, fa;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_PterabyteHover", actor))
return;
#endif
P_InstaThrust(actor, actor->angle, actor->info->speed);
actor->angle += ANG1;
actor->extravalue1 = (actor->extravalue1 + 3) % 360;
ang = actor->extravalue1*ANG1;
fa = (ang >> ANGLETOFINESHIFT) & FINEMASK;
actor->z += FINESINE(fa);
}
// Function: A_RolloutSpawn
//
// Description: Spawns a new Rollout Rock when the currently spawned rock is destroyed or moves far enough away.
//
// var1 = Distance currently spawned rock should travel before spawning a new one
// var2 = Object type to spawn
//
void A_RolloutSpawn(mobj_t *actor)
{
INT32 locvar1 = var1;
INT32 locvar2 = var2;
#ifdef HAVE_BLUA
if (LUA_CallAction("A_RolloutSpawn", actor))
return;
#endif
if (!(actor->target)
|| P_MobjWasRemoved(actor->target)
|| P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) > locvar1)
{
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;
actor->target->colorized = true;
}
}
}
// Function: A_RolloutRock
//
// Description: Thinker for Rollout Rock.
//
// var1 = Drag
// var2 = Vertical bobbing speed factor
//
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);
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 (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, 8);
}
}
if (speed > topspeed) // cap speed
{
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);
actor->momy = FixedMul(actor->momy, locvar1);
}
speed = P_AproxDistance(actor->momx, actor->momy); // recalculate speed for visual rolling
if (speed < actor->scale >> 1) // stop moving if speed is insignificant
{
actor->momx = 0;
actor->momy = 0;
}
else if (speed > actor->scale)
{
actor->movecount = 1; // rock has moved; fuse should be set so we don't have a trillion rocks lying around
actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy); // set rock's angle to movement direction
actor->movefactor += speed;
if (actor->movefactor > circumference / maxframes) // if distance moved is enough to change frame, change it!
{
actor->reactiontime++;
actor->reactiontime %= maxframes;
actor->movefactor = 0;
}
}
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

@ -1778,6 +1778,7 @@ static mobj_t *SearchMarioNode(msecnode_t *node)
case MT_RAIN:
case MT_SNOWFLAKE:
case MT_SPLISH:
case MT_LAVASPLISH:
case MT_SMOKE:
case MT_SMALLBUBBLE:
case MT_MEDIUMBUBBLE:

View file

@ -450,12 +450,18 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
}
}
break;
case MT_PYREFLY:
if (special->extravalue2 == 2 && P_DamageMobj(player->mo, special, special, 1, DMG_FIRE))
return;
default:
break;
}
if (P_PlayerCanDamage(player, special)) // Do you possess the ability to subdue the object?
{
if (special->type == MT_PTERABYTE && special->target == player->mo && special->extravalue1 == 1)
return; // Can't hurt a Pterabyte if it's trying to pick you up
if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1))
{
if (elementalpierce == 2)
@ -485,7 +491,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
P_TwinSpinRejuvenate(player, player->thokitem);
}
else
{
if (special->type == MT_PTERABYTE && special->target == player->mo)
return; // Don't hurt the player you're trying to grab
P_DamageMobj(toucher, special, special, 1, 0);
}
return;
}
@ -1082,7 +1093,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)
@ -1779,7 +1790,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);
@ -1789,7 +1800,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

@ -303,7 +303,7 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f
boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover);
boolean P_CheckDeathPitCollide(mobj_t *mo);
boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover);
boolean P_CheckSolidLava(ffloor_t *rover);
void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motype);
mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zofs, mobjtype_t type);

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)
@ -490,6 +490,42 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object)
}
}
static void P_DoPterabyteCarry(player_t *player, mobj_t *ptera)
{
if (player->powers[pw_carry] && players->powers[pw_carry] != CR_ROLLOUT)
return;
if (ptera->extravalue1 != 1)
return; // Not swooping
if (ptera->target != player->mo)
return; // Not swooping for you!
if (player->spectator)
return;
if ((player->mo->eflags & MFE_VERTICALFLIP) != (ptera->eflags & MFE_VERTICALFLIP))
return; // Both should be in same gravity
if (ptera->eflags & MFE_VERTICALFLIP)
{
if (ptera->ceilingz - (ptera->z + ptera->height) < player->mo->height - FixedMul(2*FRACUNIT, player->mo->scale))
return;
}
else if (ptera->z - ptera->floorz < player->mo->height - FixedMul(2*FRACUNIT, player->mo->scale))
return; // No room to pick up this guy!
P_ResetPlayer(player);
P_SetTarget(&player->mo->tracer, ptera);
player->pflags &= ~PF_APPLYAUTOBRAKE;
player->powers[pw_carry] = CR_PTERABYTE;
S_StartSound(player->mo, sfx_s3k4a);
P_UnsetThingPosition(player->mo);
player->mo->x = ptera->x;
player->mo->y = ptera->y;
P_SetThingPosition(player->mo);
ptera->movefactor = 3*TICRATE;
ptera->watertop = ptera->waterbottom = ptera->cusval = 0;
}
static void P_DoTailsCarry(player_t *sonic, player_t *tails)
{
INT32 p;
@ -604,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
//
@ -854,6 +918,15 @@ static boolean PIT_CheckThing(mobj_t *thing)
}
#endif
if (tmthing->type == MT_LAVAFALL_LAVA && (thing->type == MT_RING || thing->type == MT_REDTEAMRING || thing->type == MT_BLUETEAMRING || thing->type == MT_FLINGRING))
{
//height check
if (tmthing->z > thing->z + thing->height || thing->z > tmthing->z + tmthing->height || !(thing->health))
return true;
P_KillMobj(thing, tmthing, tmthing, DMG_FIRE);
}
if (tmthing->type == MT_MINECART)
{
//height check
@ -872,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;
@ -885,41 +957,73 @@ 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)
{
if (tmthing->player->powers[pw_carry] == CR_ROLLOUT)
{
return true;
}
if ((thing->flags & MF_PUSHABLE) // not carrying a player
&& (tmthing->player->powers[pw_carry] == CR_NONE) // player is not already riding something
&& ((tmthing->eflags & MFE_VERTICALFLIP) == (thing->eflags & MFE_VERTICALFLIP))
&& (P_AproxDistance(thing->x - tmthing->x, thing->y - tmthing->y) < (thing->radius))
&& (P_MobjFlip(tmthing)*tmthing->momz <= 0)
&& ((!(tmthing->eflags & MFE_VERTICALFLIP) && abs(thing->z + thing->height - tmthing->z) < (thing->height>>2))
|| (tmthing->eflags & MFE_VERTICALFLIP && abs(tmthing->z + tmthing->height - thing->z) < (thing->height>>2))))
{
thing->flags &= ~MF_PUSHABLE; // prevent riding player from applying pushable movement logic
thing->flags2 &= ~MF2_DONTDRAW; // don't leave the rock invisible if it was flashing prior to boarding
P_SetTarget(&thing->tracer, tmthing);
P_ResetPlayer(tmthing->player);
P_SetPlayerMobjState(tmthing, S_PLAY_WALK);
tmthing->player->powers[pw_carry] = CR_ROLLOUT;
P_SetTarget(&tmthing->tracer, thing);
P_SetObjectMomZ(thing, tmthing->momz, true);
return true;
}
}
else if (tmthing->type == MT_ROLLOUTROCK)
{
if (tmthing->z > thing->z + thing->height || thing->z > tmthing->z + tmthing->height || !thing->health)
return true;
if (thing == tmthing->tracer) // don't collide with rider
return true;
if (thing->flags & MF_SPRING) // bounce on springs
{
P_DoSpring(thing, tmthing);
return true;
}
else if ((thing->flags & (MF_MONITOR|MF_SHOOTABLE)) == (MF_MONITOR|MF_SHOOTABLE) && !(tmthing->flags & MF_PUSHABLE)) // pop monitors while carrying a player
{
P_KillMobj(thing, tmthing, tmthing->tracer, 0);
return true;
}
if (thing->type == tmthing->type // bounce against other rollout rocks
&& (tmthing->momx || tmthing->momy || thing->momx || thing->momy))
{
fixed_t tempmomx = thing->momx, tempmomy = thing->momy;
thing->momx = tmthing->momx;
thing->momy = tmthing->momy;
tmthing->momx = tempmomx;
tmthing->momy = tempmomy;
}
}
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;
@ -1560,8 +1664,8 @@ static boolean PIT_CheckThing(mobj_t *thing)
}
}
if ((!tmthing->player) && (thing->player))
; // no solid thing should ever be able to step up onto a player
if ((tmthing->flags & MF_SPRING || tmthing->type == MT_STEAM) && (thing->player))
; // springs and gas jets should never be able to step up onto a player
// z checking at last
// Treat noclip things as non-solid!
else if ((thing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID
@ -1964,7 +2068,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
continue;
}
if (thing->player && (P_CheckSolidLava(thing, rover) || P_CanRunOnWater(thing->player, rover)))
if (thing->player && (P_CheckSolidLava(rover) || P_CanRunOnWater(thing->player, rover)))
;
else if (thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE))
;
@ -3479,6 +3583,64 @@ stairstep:
goto retry;
}
static void P_CheckLavaWall(mobj_t *mo, sector_t *sec)
{
ffloor_t *rover;
fixed_t topheight, bottomheight;
for (rover = sec->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS))
continue;
if (!(rover->flags & FF_SWIMMABLE))
continue;
if (GETSECSPECIAL(rover->master->frontsector->special, 1) != 3)
continue;
if (rover->master->flags & ML_BLOCKMONSTERS)
continue;
topheight =
#ifdef ESLOPE
*rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) :
#endif
*rover->topheight;
if (mo->eflags & MFE_VERTICALFLIP)
{
if (topheight < mo->z - mo->height)
continue;
}
else
{
if (topheight < mo->z)
continue;
}
bottomheight =
#ifdef ESLOPE
*rover->b_slope ? P_GetZAt(*rover->b_slope, mo->x, mo->y) :
#endif
*rover->bottomheight;
if (mo->eflags & MFE_VERTICALFLIP)
{
if (bottomheight > mo->z)
continue;
}
else
{
if (bottomheight > mo->z + mo->height)
continue;
}
P_DamageMobj(mo, NULL, NULL, 1, DMG_FIRE);
return;
}
}
//
// P_SlideMove
// The momx / momy move is bad, so try to slide
@ -3639,6 +3801,12 @@ retry:
P_PathTraverse(leadx, traily, leadx + mo->momx, traily + mo->momy,
PT_ADDLINES, PTR_SlideTraverse);
if (bestslideline && mo->player && bestslideline->sidenum[1] != 0xffff)
{
sector_t *sec = P_PointOnLineSide(mo->x, mo->y, bestslideline) ? bestslideline->frontsector : bestslideline->backsector;
P_CheckLavaWall(mo, sec);
}
// Some walls are bouncy even if you're not
if (bestslideline && bestslideline->flags & ML_BOUNCY)
{

View file

@ -662,7 +662,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
if (!(rover->flags & FF_EXISTS))
continue;
if (mobj->player && (P_CheckSolidLava(mobj, rover) || P_CanRunOnWater(mobj->player, rover)))
if (mobj->player && (P_CheckSolidLava(rover) || P_CanRunOnWater(mobj->player, rover)))
;
else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player)
|| (rover->flags & FF_BLOCKOTHERS && !mobj->player)))
@ -708,7 +708,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
if (!(rover->flags & FF_EXISTS))
continue;
if (mobj->player && (P_CheckSolidLava(mobj, rover) || P_CanRunOnWater(mobj->player, rover)))
if (mobj->player && (P_CheckSolidLava(rover) || P_CanRunOnWater(mobj->player, rover)))
;
else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player)
|| (rover->flags & FF_BLOCKOTHERS && !mobj->player)))

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);
@ -2222,7 +2222,7 @@ void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motype)
topheight = P_GetFOFTopZ(mo, sector, rover, mo->x, mo->y, NULL);
bottomheight = P_GetFOFBottomZ(mo, sector, rover, mo->x, mo->y, NULL);
if (mo->player && (P_CheckSolidLava(mo, rover) || P_CanRunOnWater(mo->player, rover))) // only the player should stand on lava or run on water
if (mo->player && (P_CheckSolidLava(rover) || P_CanRunOnWater(mo->player, rover))) // only the player should stand on lava or run on water
;
else if (motype != 0 && rover->flags & FF_SWIMMABLE) // "scenery" only
continue;
@ -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;
@ -2379,43 +2379,11 @@ boolean P_CheckDeathPitCollide(mobj_t *mo)
return false;
}
boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover)
boolean P_CheckSolidLava(ffloor_t *rover)
{
fixed_t topheight;
I_Assert(mo != NULL);
I_Assert(!P_MobjWasRemoved(mo));
// not a lava block with solid planes
if (!(rover->flags & FF_SWIMMABLE && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3
&& !(rover->master->flags & ML_BLOCKMONSTERS)))
return false;
// is solid from the sides
if (rover->master->flags & ML_EFFECT3)
return true;
if (mo->eflags & MFE_VERTICALFLIP)
{
topheight =
#ifdef ESLOPE
*rover->b_slope ? P_GetZAt(*rover->b_slope, mo->x, mo->y) :
#endif
*rover->bottomheight;
if (mo->z+mo->height-mo->momz < topheight + FixedMul(16*FRACUNIT, mo->scale))
return true;
return false;
}
topheight =
#ifdef ESLOPE
*rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) :
#endif
*rover->topheight;
if (mo->z-mo->momz > topheight - FixedMul(16*FRACUNIT, mo->scale))
return true;
if (rover->flags & FF_SWIMMABLE && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3
&& !(rover->master->flags & ML_BLOCKMONSTERS))
return true;
return false;
}
@ -3350,7 +3318,7 @@ void P_MobjCheckWater(mobj_t *mobj)
mobj->watertop = mobj->waterbottom = mobj->z - 1000*FRACUNIT;
// Reset water state.
mobj->eflags &= ~(MFE_UNDERWATER|MFE_TOUCHWATER|MFE_GOOWATER);
mobj->eflags &= ~(MFE_UNDERWATER|MFE_TOUCHWATER|MFE_GOOWATER|MFE_TOUCHLAVA);
for (rover = sector->ffloors; rover; rover = rover->next)
{
@ -3391,16 +3359,18 @@ void P_MobjCheckWater(mobj_t *mobj)
// Just touching the water?
if (((mobj->eflags & MFE_VERTICALFLIP) && thingtop - height < bottomheight)
|| (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + height > topheight))
{
mobj->eflags |= MFE_TOUCHWATER;
if (rover->flags & FF_GOOWATER && !(mobj->flags & MF_NOGRAVITY))
mobj->eflags |= MFE_GOOWATER;
}
// Actually in the water?
if (((mobj->eflags & MFE_VERTICALFLIP) && thingtop - (height>>1) > bottomheight)
|| (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + (height>>1) < topheight))
{
mobj->eflags |= MFE_UNDERWATER;
if (mobj->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER))
{
if (GETSECSPECIAL(rover->master->frontsector->special, 1) == 3)
mobj->eflags |= MFE_TOUCHLAVA;
if (rover->flags & FF_GOOWATER && !(mobj->flags & MF_NOGRAVITY))
mobj->eflags |= MFE_GOOWATER;
}
@ -3464,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.
@ -3478,14 +3457,15 @@ void P_MobjCheckWater(mobj_t *mobj)
{
// Spawn a splash
mobj_t *splish;
mobjtype_t splishtype = (mobj->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH;
if (mobj->eflags & MFE_VERTICALFLIP)
{
splish = P_SpawnMobj(mobj->x, mobj->y, mobj->waterbottom-FixedMul(mobjinfo[MT_SPLISH].height, mobj->scale), MT_SPLISH);
splish = P_SpawnMobj(mobj->x, mobj->y, mobj->waterbottom-FixedMul(mobjinfo[splishtype].height, mobj->scale), splishtype);
splish->flags2 |= MF2_OBJECTFLIP;
splish->eflags |= MFE_VERTICALFLIP;
}
else
splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, MT_SPLISH);
splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, splishtype);
splish->destscale = mobj->scale;
P_SetScale(splish, mobj->scale);
}
@ -3513,14 +3493,15 @@ void P_MobjCheckWater(mobj_t *mobj)
{
// Spawn a splash
mobj_t *splish;
mobjtype_t splishtype = (mobj->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH;
if (mobj->eflags & MFE_VERTICALFLIP)
{
splish = P_SpawnMobj(mobj->x, mobj->y, mobj->waterbottom-FixedMul(mobjinfo[MT_SPLISH].height, mobj->scale), MT_SPLISH);
splish = P_SpawnMobj(mobj->x, mobj->y, mobj->waterbottom-FixedMul(mobjinfo[splishtype].height, mobj->scale), splishtype);
splish->flags2 |= MF2_OBJECTFLIP;
splish->eflags |= MFE_VERTICALFLIP;
}
else
splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, MT_SPLISH);
splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, splishtype);
splish->destscale = mobj->scale;
P_SetScale(splish, mobj->scale);
}
@ -3536,6 +3517,8 @@ void P_MobjCheckWater(mobj_t *mobj)
if (mobj->eflags & MFE_GOOWATER || wasingoo)
S_StartSound(mobj, sfx_ghit);
else if (mobj->eflags & MFE_TOUCHLAVA)
S_StartSound(mobj, sfx_splash);
else
S_StartSound(mobj, sfx_splish); // And make a sound!
@ -4146,6 +4129,45 @@ void P_RainThinker(precipmobj_t *mobj)
P_SetPrecipMobjState(mobj, S_SPLASH1);
}
static void P_KillRingsInLava(mobj_t *mo)
{
msecnode_t *node;
I_Assert(mo != NULL);
I_Assert(!P_MobjWasRemoved(mo));
// go through all sectors being touched by the ring
for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next)
{
if (!node->m_sector)
break;
if (node->m_sector->ffloors)
{
ffloor_t *rover;
fixed_t topheight, bottomheight;
for (rover = node->m_sector->ffloors; rover; rover = rover->next) // go through all fofs in the sector
{
if (!(rover->flags & FF_EXISTS)) continue; // fof must be real
if (!(rover->flags & FF_SWIMMABLE // fof must be water
&& GETSECSPECIAL(rover->master->frontsector->special, 1) == 3)) // fof must be lava water
continue;
// find heights of FOF
topheight = P_GetFOFTopZ(mo, node->m_sector, rover, mo->x, mo->y, NULL);
bottomheight = P_GetFOFBottomZ(mo, node->m_sector, rover, mo->x, mo->y, NULL);
if (mo->z <= topheight && mo->z + mo->height >= bottomheight) // if ring touches it, KILL IT
{
P_KillMobj(mo, NULL, NULL, DMG_FIRE);
return;
}
}
}
}
}
static void P_RingThinker(mobj_t *mobj)
{
if (mobj->momx || mobj->momy)
@ -7054,6 +7076,16 @@ void P_HandleMinecartSegments(mobj_t *mobj)
P_UpdateMinecartSegments(mobj);
}
static void P_PyreFlyBurn(mobj_t *mobj, fixed_t hoffs, INT16 vrange, mobjtype_t mobjtype, fixed_t momz)
{
angle_t fa = (FixedAngle(P_RandomKey(360)*FRACUNIT) >> ANGLETOFINESHIFT) & FINEMASK;
fixed_t xoffs = FixedMul(FINECOSINE(fa), mobj->radius + hoffs);
fixed_t yoffs = FixedMul(FINESINE(fa), mobj->radius + hoffs);
fixed_t zoffs = P_RandomRange(-vrange, vrange)*FRACUNIT;
mobj_t *particle = P_SpawnMobjFromMobj(mobj, xoffs, yoffs, zoffs, mobjtype);
particle->momz = momz;
}
//
// P_MobjThinker
//
@ -7619,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])
{
@ -7683,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:
{
@ -8896,13 +9160,17 @@ void P_MobjThinker(mobj_t *mobj)
}
break;
case MT_RING:
case MT_REDTEAMRING:
case MT_BLUETEAMRING:
P_KillRingsInLava(mobj);
if (P_MobjWasRemoved(mobj))
return;
/* FALLTHRU */
case MT_COIN:
case MT_BLUESPHERE:
case MT_BOMBSPHERE:
case MT_NIGHTSCHIP:
case MT_NIGHTSSTAR:
case MT_REDTEAMRING:
case MT_BLUETEAMRING:
// No need to check water. Who cares?
P_RingThinker(mobj);
if (mobj->flags2 & MF2_NIGHTSPULL)
@ -8912,6 +9180,10 @@ void P_MobjThinker(mobj_t *mobj)
return;
// Flung items
case MT_FLINGRING:
P_KillRingsInLava(mobj);
if (P_MobjWasRemoved(mobj))
return;
/* FALLTHRU */
case MT_FLINGCOIN:
case MT_FLINGBLUESPHERE:
case MT_FLINGNIGHTSCHIP:
@ -9113,6 +9385,159 @@ void P_MobjThinker(mobj_t *mobj)
}
mobj->flags2 ^= MF2_DONTDRAW;
break;
case MT_LAVAFALLROCK:
if (P_IsObjectOnGround(mobj))
P_RemoveMobj(mobj);
break;
case MT_PYREFLY:
{
fixed_t hdist;
mobj->extravalue1 = (mobj->extravalue1 + 3) % 360;
mobj->z += FINESINE(((mobj->extravalue1*ANG1) >> ANGLETOFINESHIFT) & FINEMASK);
if (!(mobj->flags2 & MF2_BOSSNOTRAP))
P_LookForPlayers(mobj, true, false, 1500*FRACUNIT);
if (!mobj->target)
break;
if (mobj->extravalue2 == 1)
P_PyreFlyBurn(mobj, 0, 20, MT_SMOKE, 4*FRACUNIT);
else if (mobj->extravalue2 == 2)
{
INT32 fireradius = min(100 - mobj->fuse, 52);
P_PyreFlyBurn(mobj, P_RandomRange(0, fireradius)*FRACUNIT, 20, MT_FLAMEPARTICLE, 4*FRACUNIT);
P_PyreFlyBurn(mobj, fireradius*FRACUNIT, 40, MT_PYREFLY_FIRE, 0);
}
hdist = R_PointToDist2(mobj->x, mobj->y, mobj->target->x, mobj->target->y);
if (!(mobj->flags2 & MF2_BOSSNOTRAP) && hdist <= 450*FRACUNIT)
mobj->flags2 |= MF2_BOSSNOTRAP;
if (!(mobj->flags2 & MF2_BOSSNOTRAP))
break;
if (hdist < 1000*FRACUNIT)
{
//Aim for player z position. If too close to floor/ceiling, aim just above/below them.
fixed_t destz = min(max(mobj->target->z, mobj->target->floorz + 70*FRACUNIT), mobj->target->ceilingz - 80*FRACUNIT - mobj->height);
fixed_t dist = P_AproxDistance(hdist, destz - mobj->z);
P_InstaThrust(mobj, R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y), 2*FRACUNIT);
mobj->momz = FixedMul(FixedDiv(destz - mobj->z, dist), 2*FRACUNIT);
}
else
{
mobj->momx = 0;
mobj->momy = 0;
mobj->momz = 0;
if (hdist >= 1500*FRACUNIT)
{
mobj->flags2 &= ~MF2_BOSSNOTRAP;
P_SetTarget(&mobj->target, NULL);
}
}
break;
}
case MT_PTERABYTE:
{
if (mobj->extravalue1 & 4) // Cooldown after grabbing
{
if (mobj->movefactor)
mobj->movefactor--;
else
{
P_SetTarget(&mobj->target, NULL);
mobj->extravalue1 &= 3;
}
}
if ((mobj->extravalue1 & 3) == 0) // Hovering
{
fixed_t vdist, hdist, time;
fixed_t hspeed = 3*mobj->info->speed;
angle_t fa;
var1 = 1;
var2 = 0;
A_CapeChase(mobj);
if (mobj->target)
break; // Still carrying a player or in cooldown
P_LookForPlayers(mobj, true, false, 256*FRACUNIT);
if (!mobj->target)
break;
if (mobj->target->player->powers[pw_flashing])
{
P_SetTarget(&mobj->target, NULL);
break;
}
vdist = mobj->z - mobj->target->z - mobj->target->height;
if (P_MobjFlip(mobj)*vdist <= 0)
{
P_SetTarget(&mobj->target, NULL);
break;
}
hdist = R_PointToDist2(mobj->x, mobj->y, mobj->target->x, mobj->target->y);
if (hdist > 450*FRACUNIT)
{
P_SetTarget(&mobj->target, NULL);
break;
}
P_SetMobjState(mobj, S_PTERABYTE_SWOOPDOWN);
mobj->extravalue1++;
S_StartSound(mobj, mobj->info->attacksound);
time = FixedDiv(hdist, hspeed);
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y);
fa = (mobj->angle >> ANGLETOFINESHIFT) & FINEMASK;
mobj->momx = FixedMul(FINECOSINE(fa), hspeed);
mobj->momy = FixedMul(FINESINE(fa), hspeed);
mobj->momz = -2*FixedDiv(vdist, time);
mobj->extravalue2 = -FixedDiv(mobj->momz, time); //Z accel
mobj->movecount = time >> FRACBITS;
mobj->reactiontime = mobj->movecount;
}
else if ((mobj->extravalue1 & 3) == 1) // Swooping
{
mobj->reactiontime--;
mobj->momz += mobj->extravalue2;
if (mobj->reactiontime)
break;
if (mobj->state - states == S_PTERABYTE_SWOOPDOWN)
{
P_SetMobjState(mobj, S_PTERABYTE_SWOOPUP);
mobj->reactiontime = mobj->movecount;
}
else if (mobj->state - states == S_PTERABYTE_SWOOPUP)
{
P_SetMobjState(mobj, S_PTERABYTE_FLY1);
mobj->extravalue1++;
if (mobj->target && mobj->target->tracer != mobj)
P_SetTarget(&mobj->target, NULL); // Failed to grab the target
mobj->momx = mobj->momy = mobj->momz = 0;
}
}
else // Returning
{
var1 = 2*mobj->info->speed;
var2 = 1;
A_HomingChase(mobj);
if (P_AproxDistance(mobj->x - mobj->tracer->x, mobj->y - mobj->tracer->y) <= mobj->info->speed)
{
mobj->extravalue1 -= 2;
mobj->momx = mobj->momy = mobj->momz = 0;
}
}
break;
}
case MT_SPINFIRE:
if (mobj->flags & MF_NOGRAVITY)
{
@ -9343,6 +9768,52 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s
case MT_NIGHTSCORE:
P_RemoveMobj(mobj);
return;
case MT_LAVAFALL:
if (mobj->state - states == S_LAVAFALL_DORMANT)
{
mobj->fuse = 30;
P_SetMobjState(mobj, S_LAVAFALL_TELL);
S_StartSound(mobj, mobj->info->seesound);
}
else if (mobj->state - states == S_LAVAFALL_TELL)
{
mobj->fuse = 40;
P_SetMobjState(mobj, S_LAVAFALL_SHOOT);
S_StopSound(mobj);
S_StartSound(mobj, mobj->info->attacksound);
}
else
{
mobj->fuse = 30;
P_SetMobjState(mobj, S_LAVAFALL_DORMANT);
S_StopSound(mobj);
}
return;
case MT_PYREFLY:
if (mobj->health <= 0)
break;
mobj->extravalue2 = (mobj->extravalue2 + 1) % 3;
if (mobj->extravalue2 == 0)
{
P_SetMobjState(mobj, mobj->info->spawnstate);
mobj->fuse = 100;
S_StopSound(mobj);
S_StartSound(mobj, sfx_s3k8c);
}
else if (mobj->extravalue2 == 1)
{
mobj->fuse = 50;
S_StartSound(mobj, sfx_s3ka3);
}
else
{
P_SetMobjState(mobj, mobj->info->meleestate);
mobj->fuse = 100;
S_StopSound(mobj);
S_StartSound(mobj, sfx_s3kc2l);
}
return;
case MT_PLAYER:
break; // don't remove
default:
@ -9900,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;
@ -9915,11 +10389,23 @@ 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));
mobj->tracer->angle = mobj->angle + ANGLE_90;
break;
case MT_TORCHFLOWER:
{
mobj_t *fire = P_SpawnMobjFromMobj(mobj, 0, 0, 46*FRACUNIT, MT_FLAME);
P_SetTarget(&mobj->target, fire);
break;
}
case MT_PYREFLY:
mobj->extravalue1 = (FixedHypot(mobj->x, mobj->y)/FRACUNIT) % 360;
mobj->extravalue2 = 0;
mobj->fuse = 100;
break;
default:
break;
}
@ -10237,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);
@ -10250,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);
@ -11070,6 +11556,14 @@ 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 (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
@ -11283,9 +11777,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;
@ -11957,6 +12452,38 @@ ML_EFFECT5 : Don't stop thinking when too far away
if (mthing->angle > 0)
mobj->tics += mthing->angle;
break;
case MT_LAVAFALL:
mobj->fuse = 30 + mthing->angle;
if (mthing->options & MTF_AMBUSH)
{
P_SetScale(mobj, 2*mobj->scale);
mobj->destscale = mobj->scale;
}
break;
case MT_PYREFLY:
//start on fire if Ambush flag is set, otherwise behave normally
if (mthing->options & MTF_AMBUSH)
{
P_SetMobjState(mobj, mobj->info->meleestate);
mobj->extravalue2 = 2;
S_StartSound(mobj, sfx_s3kc2l);
}
break;
case MT_BIGFERN:
{
angle_t angle = FixedAngle(mthing->angle << FRACBITS);
UINT8 j;
for (j = 0; j < 8; j++)
{
angle_t fa = (angle >> ANGLETOFINESHIFT) & FINEMASK;
fixed_t xoffs = FINECOSINE(fa);
fixed_t yoffs = FINESINE(fa);
mobj_t *leaf = P_SpawnMobjFromMobj(mobj, xoffs, yoffs, 0, MT_BIGFERNLEAF);
leaf->angle = angle;
angle += ANGLE_45;
}
break;
}
default:
break;
}

View file

@ -233,15 +233,17 @@ typedef enum
MFE_VERTICALFLIP = 1<<5,
// Goo water
MFE_GOOWATER = 1<<6,
// The mobj is touching a lava block
MFE_TOUCHLAVA = 1<<7,
// Mobj was already pushed this tic
MFE_PUSHED = 1<<7,
MFE_PUSHED = 1<<8,
// Mobj was already sprung this tic
MFE_SPRUNG = 1<<8,
MFE_SPRUNG = 1<<9,
// Platform movement
MFE_APPLYPMOMZ = 1<<9,
MFE_APPLYPMOMZ = 1<<10,
// Compute and trigger on mobj angle relative to tracer
// See Linedef Exec 457 (Track mobj angle to point)
MFE_TRACERANGLE = 1<<10,
MFE_TRACERANGLE = 1<<11,
// free: to and including 1<<15
} mobjeflag_t;

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);
}
@ -6683,6 +6582,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;

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

@ -1031,6 +1031,17 @@ void P_ResetPlayer(player_t *player)
{
player->pflags &= ~(PF_SPINNING|PF_STARTDASH|PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_THOKKED|PF_CANCARRY|PF_SHIELDABILITY|PF_BOUNCING);
if (player->powers[pw_carry] == CR_ROLLOUT)
{
if (player->mo->tracer && !P_MobjWasRemoved(player->mo->tracer))
{
player->mo->tracer->flags |= MF_PUSHABLE;
P_SetTarget(&player->mo->tracer->tracer, NULL);
}
P_SetTarget(&player->mo->tracer, NULL);
player->powers[pw_carry] = CR_NONE;
}
if (!(player->powers[pw_carry] == CR_NIGHTSMODE || player->powers[pw_carry] == CR_NIGHTSFALL || player->powers[pw_carry] == CR_BRAKGOOP || player->powers[pw_carry] == CR_MINECART))
player->powers[pw_carry] = CR_NONE;
@ -2261,7 +2272,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
player->mo->momy = ((player->mo->momy - player->cmomy)/3) + player->cmomy;
}
}
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)
{
@ -3711,7 +3722,7 @@ static void P_DoTeeter(player_t *player)
bottomheight = *rover->bottomheight;
#endif
if (P_CheckSolidLava(player->mo, rover))
if (P_CheckSolidLava(rover))
;
else if (!(rover->flags & FF_BLOCKPLAYER || rover->flags & FF_QUICKSAND))
continue; // intangible 3d floor
@ -4333,6 +4344,16 @@ void P_DoJump(player_t *player, boolean soundandstate)
if (player->mo->ceilingz-player->mo->floorz <= player->mo->height-1)
return;
if (player->powers[pw_carry] == CR_PTERABYTE)
{
S_StartSound(player->mo, sfx_s3kd7s);
player->mo->tracer->cusval += 10;
player->mo->tracer->watertop = P_RandomRange(-player->mo->tracer->cusval, player->mo->tracer->cusval) << (FRACBITS - 1);
player->mo->tracer->waterbottom = P_RandomRange(-player->mo->tracer->cusval, player->mo->tracer->cusval) << (FRACBITS - 1);
player->mo->tracer->cvmem = P_RandomRange(-player->mo->tracer->cusval, player->mo->tracer->cusval) << (FRACBITS - 1);
return;
}
// Jump this high.
if (player->powers[pw_carry] == CR_PLAYER)
{
@ -4346,6 +4367,8 @@ void P_DoJump(player_t *player, boolean soundandstate)
{
player->mo->momz = 9*FRACUNIT;
player->powers[pw_carry] = CR_NONE;
player->mo->tracer->flags |= MF_PUSHABLE;
P_SetTarget(&player->mo->tracer->target, NULL);
P_SetTarget(&player->mo->tracer, NULL);
}
else if (player->powers[pw_carry] == CR_ROPEHANG)
@ -4354,6 +4377,14 @@ void P_DoJump(player_t *player, boolean soundandstate)
player->powers[pw_carry] = CR_NONE;
P_SetTarget(&player->mo->tracer, NULL);
}
else if (player->powers[pw_carry] == CR_ROLLOUT)
{
player->mo->momz = 9*FRACUNIT + player->mo->tracer->momz;
player->powers[pw_carry] = CR_NONE;
player->mo->tracer->flags |= MF_PUSHABLE;
P_SetTarget(&player->mo->tracer->tracer, NULL);
P_SetTarget(&player->mo->tracer, NULL);
}
else if (player->mo->eflags & MFE_GOOWATER)
{
player->mo->momz = 7*FRACUNIT;
@ -4666,8 +4697,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;
@ -5866,35 +5898,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!
@ -7374,10 +7399,13 @@ static void P_NiGHTSMovement(player_t *player)
&& player->mo->z + player->mo->height - P_GetPlayerHeight(player) <= player->mo->waterbottom && player->mo->z + player->mo->height >= player->mo->waterbottom))
&& player->speed > 9000 && leveltime % (TICRATE/7) == 0 && !player->spectator)
{
mobjtype_t splishtype = (player->mo->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH;
mobj_t *water = P_SpawnMobj(player->mo->x, player->mo->y,
((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_SPLISH].height, player->mo->scale) : player->mo->watertop), MT_SPLISH);
((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[splishtype].height, player->mo->scale) : player->mo->watertop), splishtype);
if (player->mo->eflags & MFE_GOOWATER)
S_StartSound(water, sfx_ghit);
else if (player->mo->eflags & MFE_TOUCHLAVA)
S_StartSound(water, sfx_splash);
else
S_StartSound(water, sfx_wslap);
if (player->mo->eflags & MFE_VERTICALFLIP)
@ -8166,10 +8194,13 @@ static void P_MovePlayer(player_t *player)
&& (player->speed > runspd || (player->pflags & PF_STARTDASH))
&& leveltime % (TICRATE/7) == 0 && player->mo->momz == 0 && !(player->pflags & PF_SLIDING) && !player->spectator)
{
mobjtype_t splishtype = (player->mo->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH;
mobj_t *water = P_SpawnMobj(player->mo->x - P_ReturnThrustX(NULL, player->mo->angle, player->mo->radius), player->mo->y - P_ReturnThrustY(NULL, player->mo->angle, player->mo->radius),
((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_SPLISH].height, player->mo->scale) : player->mo->watertop), MT_SPLISH);
((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[splishtype].height, player->mo->scale) : player->mo->watertop), splishtype);
if (player->mo->eflags & MFE_GOOWATER)
S_StartSound(water, sfx_ghit);
else if (player->mo->eflags & MFE_TOUCHLAVA)
S_StartSound(water, sfx_splash);
else
S_StartSound(water, sfx_wslap);
if (player->mo->eflags & MFE_VERTICALFLIP)
@ -8906,7 +8937,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);
@ -10305,7 +10336,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;
@ -11291,6 +11322,8 @@ void P_PlayerThink(player_t *player)
// deez New User eXperiences.
{
angle_t diff = 0;
UINT8 factor;
// Directionchar!
// Camera angle stuff.
if (player->exiting // no control, no modification
@ -11316,8 +11349,16 @@ void P_PlayerThink(player_t *player)
/* FALLTHRU */
case CR_MINECART:
case CR_GENERIC:
case CR_PTERABYTE:
player->drawangle = player->mo->tracer->angle;
break;
case CR_ROLLOUT:
if (cmd->forwardmove || cmd->sidemove) // only when you're pressing movement keys
{ // inverse direction!
diff = ((player->mo->angle + R_PointToAngle2(0, 0, -cmd->forwardmove<<FRACBITS, cmd->sidemove<<FRACBITS)) - player->drawangle);
factor = 4;
}
break;
/* -- in case we wanted to have the camera freely movable during zoom tubes
case CR_ZOOMTUBE:*/
case CR_ROPEHANG:
@ -11384,15 +11425,15 @@ void P_PlayerThink(player_t *player)
diff = (player->mo->angle - player->drawangle);
factor = 8;
}
}
if (diff)
{
if (diff > ANGLE_180)
diff = InvAngle(InvAngle(diff)/factor);
else
diff /= factor;
player->drawangle += diff;
}
if (diff)
{
if (diff > ANGLE_180)
diff = InvAngle(InvAngle(diff)/factor);
else
diff /= factor;
player->drawangle += diff;
}
// Autobrake! check ST_drawInput if you modify this
@ -11711,6 +11752,36 @@ void P_PlayerThink(player_t *player)
}*/
}
// Checks if the mobj is above lava. Used by Pterabyte.
static boolean P_MobjAboveLava(mobj_t *mobj)
{
sector_t *sector = mobj->subsector->sector;
if (sector->ffloors)
{
ffloor_t *rover;
for (rover = sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || GETSECSPECIAL(rover->master->frontsector->special, 1) != 3)
continue;
if (mobj->eflags & MFE_VERTICALFLIP)
{
if (*rover->bottomheight <= mobj->ceilingz && *rover->bottomheight >= mobj->z)
return true;
}
else
{
if (*rover->topheight >= mobj->floorz && *rover->topheight <= mobj->z)
return true;
}
}
}
return false;
}
//
// P_PlayerAfterThink
//
@ -12026,6 +12097,114 @@ void P_PlayerAfterThink(player_t *player)
}
break;
}
case CR_ROLLOUT:
{
mobj_t *mo = player->mo, *rock = player->mo->tracer;
UINT8 walktics = mo->state->tics - P_GetPlayerControlDirection(player);
if (!rock || P_MobjWasRemoved(rock))
{
P_SetTarget(&player->mo->tracer, NULL);
player->powers[pw_carry] = CR_NONE;
break;
}
if (player->cmd.forwardmove || player->cmd.sidemove)
{
rock->movedir = (player->cmd.angleturn << FRACBITS) + R_PointToAngle2(0, 0, player->cmd.forwardmove << FRACBITS, -player->cmd.sidemove << FRACBITS);
P_Thrust(rock, rock->movedir, rock->scale >> 1);
}
mo->momx = rock->momx;
mo->momy = rock->momy;
mo->momz = 0;
if (player->panim == PA_IDLE && (mo->momx || mo->momy))
{
P_SetPlayerMobjState(player->mo, S_PLAY_WALK);
}
if (player->panim == PA_WALK && mo->tics > walktics)
{
mo->tics = walktics;
}
P_TeleportMove(player->mo, rock->x, rock->y, rock->z + rock->height);
break;
}
case CR_PTERABYTE: // being carried by a Pterabyte
{
mobj_t *ptera = player->mo->tracer;
mobj_t *spawnpoint = ptera->tracer->tracer;
player->mo->height = FixedDiv(P_GetPlayerHeight(player), FixedDiv(14 * FRACUNIT, 10 * FRACUNIT));
if (ptera->health <= 0)
goto dropoff;
if (P_MobjAboveLava(ptera) && ptera->movefactor <= 3*TICRATE - 10)
goto dropoff;
if (player->mo->eflags & MFE_VERTICALFLIP)
{
if ((ptera->z + ptera->height + player->mo->height + FixedMul(FRACUNIT, player->mo->scale)) <= ptera->ceilingz
&& (ptera->eflags & MFE_VERTICALFLIP)) // Reverse gravity check for the carrier - Flame
player->mo->z = ptera->z + ptera->height + FixedMul(FRACUNIT, player->mo->scale);
if (ptera->ceilingz - ptera->z > spawnpoint->ceilingz - spawnpoint->z + 512*FRACUNIT && ptera->movefactor <= 3 * TICRATE - 10)
goto dropoff;
}
else
{
if ((ptera->z - player->mo->height - FixedMul(FRACUNIT, player->mo->scale)) >= ptera->floorz
&& !(ptera->eflags & MFE_VERTICALFLIP)) // Correct gravity check for the carrier - Flame
player->mo->z = ptera->z - player->mo->height - FixedMul(FRACUNIT, player->mo->scale);
if (ptera->z - ptera->floorz > spawnpoint->z - spawnpoint->floorz + 512 * FRACUNIT && ptera->movefactor <= 3 * TICRATE - 10)
goto dropoff;
}
ptera->movefactor--;
if (!ptera->movefactor)
goto dropoff;
if (ptera->cusval >= 50)
{
player->powers[pw_carry] = CR_NONE;
P_SetTarget(&player->mo->tracer, NULL);
P_KillMobj(ptera, player->mo, player->mo, 0);
player->mo->momz = 9*FRACUNIT;
player->pflags |= PF_APPLYAUTOBRAKE|PF_JUMPED|PF_THOKKED;
P_SetMobjState(player->mo, S_PLAY_ROLL);
break;
}
if (ptera->cusval)
ptera->cusval--;
P_TryMove(player->mo, ptera->x + ptera->watertop, ptera->y + ptera->waterbottom, true);
player->mo->z += ptera->cvmem;
player->mo->momx = ptera->momx;
player->mo->momy = ptera->momy;
player->mo->momz = ptera->momz;
if (P_AproxDistance(player->mo->x - ptera->x - ptera->watertop, player->mo->y - ptera->y - ptera->waterbottom) > player->mo->radius)
goto dropoff;
ptera->watertop >>= 1;
ptera->waterbottom >>= 1;
ptera->cvmem >>= 1;
if (player->mo->state-states != S_PLAY_FALL)
P_SetPlayerMobjState(player->mo, S_PLAY_FALL);
break;
dropoff:
player->powers[pw_carry] = CR_NONE;
P_SetTarget(&player->mo->tracer, NULL);
ptera->movefactor = TICRATE;
ptera->extravalue1 |= 4;
break;
}
default:
break;
}

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

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

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

@ -218,6 +218,8 @@ sfxinfo_t S_sfx[NUMSFX] =
{"chuchu", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Train horn"},
{"bsnipe", false, 200, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Home-run smash"},
{"sprong", false, 112, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power spring"},
{"lvfal1", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rumble"},
{"pscree", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "SCREE!"},
// Menu, interface
{"chchng", false, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Score"},
@ -504,7 +506,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"s3k6d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s3k6e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Mechanical damage"},
{"s3k6f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous rumbling"},
{"s3k70", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Burst"},
{"s3k70", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Burst"},
{"s3k71", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Basic Shield"},
{"s3k72", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Movement"},
{"s3k73", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Warp"},
@ -555,7 +557,7 @@ sfxinfo_t S_sfx[NUMSFX] =
{"s3ka0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Launch"},
{"s3ka1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s3ka2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Launch"},
{"s3ka3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Lift"},
{"s3ka3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rising charge"},
{"s3ka4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Powering up"},
{"s3ka5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
{"s3ka6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Attraction fizzle"},

View file

@ -267,6 +267,8 @@ typedef enum
sfx_chuchu,
sfx_bsnipe,
sfx_sprong,
sfx_lvfal1,
sfx_pscree,
// Menu, interface
sfx_chchng,

View file

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