Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 21-installer-nodd
  • 2210-pre1
  • 2210-pre2
  • 2210-rc1
  • 2210-rc2
  • 2210-rc3
  • 2211-pre1
  • 2211-pre2
  • 2211-rc1
  • 2212-pre1
  • 2212-pre2
  • 2212-pre3
  • 2212-rc1
  • 2213
  • 2214-pre1
  • 2214-pre2
  • 2214-pre3
  • 2214-pre4
  • 2_2_12
  • 64-gl-log
  • COM_ImmedExecute-lua
  • DJGPP
  • accel-momentum
  • acs
  • action-args
  • alpha-fixes
  • any-resolution
  • appveyor
  • blend-locking
  • blentran
  • blua-unary-not-fix
  • boost-tickrate
  • bustablesoundz
  • cleanup-opengl
  • cleanupmusic
  • clipmidtex
  • cmake-valgrind
  • crawlacommander-sprites
  • custom-map-names
  • custom-teams
  • cutscene-cleanup
  • dd-music-bypass
  • dd-music-fix
  • delfile2
  • deprecate-lua-dedicated-server
  • dpl-2
  • dropshadows-spawning
  • dynabsp
  • emblem-drawing
  • exchndl-xp-fix
  • extra-textures
  • few-kart-lua-changes
  • ffloorclip
  • fix-167
  • fix-cvar-conflicts
  • fix-opengl-parameter-crash
  • fix-opengl-shear-roll
  • flipfuncpointers
  • fof-lightlist-fixes
  • font-FUCK
  • frictionrefactor
  • fuck-macros-1
  • gamepad-luakeydown
  • gamepad-morefixes
  • gamepad_experiments
  • gametype-refactor
  • gametype-refactor-1
  • gametype-refactor-player-spawns
  • ghost-networking
  • gif-splitting
  • grr-lj
  • hitboxviewer
  • hwr-texture-cache-refactor
  • hwrender2
  • improve-439
  • increase-maxconditionsets
  • increase-packet-tics
  • input-display
  • input-display-translucency
  • io
  • joystick-juggling-maz
  • just-in-case
  • keycodes-only
  • ksf-wadfiles
  • ld413-mp-fix
  • levelstruct
  • libpng-version-support
  • linedef-actions
  • lj-test
  • lol-states
  • loopedsounds
  • lower-unpegged-fix
  • lua-change-gametype
  • lua-command-netids
  • lua-gfx-2
  • lua-gfx-sprites
  • lua-local
  • makefile-auto-mingw-gcc
  • makefile-tinkering
  • map-components-signedness-fixes
  • SRB2_release_2.1
  • SRB2_release_2.1.1
  • SRB2_release_2.1.10
  • SRB2_release_2.1.11
  • SRB2_release_2.1.12
  • SRB2_release_2.1.14
  • SRB2_release_2.1.15
  • SRB2_release_2.1.16
  • SRB2_release_2.1.16a
  • SRB2_release_2.1.17
  • SRB2_release_2.1.18
  • SRB2_release_2.1.19
  • SRB2_release_2.1.2
  • SRB2_release_2.1.20
  • SRB2_release_2.1.21
  • SRB2_release_2.1.22
  • SRB2_release_2.1.23
  • SRB2_release_2.1.24
  • SRB2_release_2.1.25
  • SRB2_release_2.1.3
  • SRB2_release_2.1.4
  • SRB2_release_2.1.5
  • SRB2_release_2.1.6
  • SRB2_release_2.1.7
  • SRB2_release_2.1.8
  • SRB2_release_2.1.9
  • SRB2_release_2.2.0
  • SRB2_release_2.2.1
  • SRB2_release_2.2.10
  • SRB2_release_2.2.11
  • SRB2_release_2.2.12
  • SRB2_release_2.2.13
  • SRB2_release_2.2.15
  • SRB2_release_2.2.2
  • SRB2_release_2.2.3
  • SRB2_release_2.2.4
  • SRB2_release_2.2.5
  • SRB2_release_2.2.6
  • SRB2_release_2.2.7
  • SRB2_release_2.2.8
  • SRB2_release_2.2.9
  • td-release-v1.0.0
142 results

Target

Select target project
  • STJr/SRB2
  • Sryder/SRB2
  • wolfy852/SRB2
  • Alpha2244/SRB2
  • Inuyasha/SRB2
  • yoshibot/SRB2
  • TehRealSalt/SRB2
  • PrisimaTF/SRB2
  • Hatninja/SRB2
  • SteelT/SRB2
  • james/SRB2
  • ShaderWraith/SRB2
  • SinnamonLat/SRB2
  • mazmazz_/SRB2
  • filpAM/SRB2
  • chaoloveicemdboy/SRB2
  • Whooa21/SRB2
  • Machturne/SRB2
  • Golden/SRB2
  • Tatsuru/SRB2
  • Snu/SRB2
  • Zwip-Zwap_Zapony/SRB2
  • fickleheart/SRB2
  • alphaRexJames/SRB2
  • JJK/SRB2
  • diskpoppy/SRB2
  • Hannu_Hanhi/SRB2
  • ZipperQR/SRB2
  • kays/SRB2
  • spherallic/SRB2
  • Zippy_Zolton/SRB2
  • namiishere/SRB2
  • Ors/SRB2
  • SMS_Alfredo/SRB2
  • sonic_edge/SRB2
  • lavla/SRB2
  • ashi/SRB2
  • X.organic/SRB2
  • Fafabis/SRB2
  • Meziu/SRB2
  • v-rob/SRB2
  • tertu/SRB2
  • bitten2up/SRB2
  • flarn2006/SRB2
  • Krabs/SRB2
  • clairebun/SRB2
  • Lactozilla/SRB2
  • thehackstack/SRB2
  • Spice/SRB2
  • win8linux/SRB2
  • JohnFrostFox/SRB2
  • talktoneon726/SRB2
  • Wane/SRB2
  • Lamibe/SRB2
  • spectrumuk2/srb-2
  • nerdyminer18/srb-2
  • 256nil/SRB2
  • ARJr/SRB2
  • Alam/SRB2
  • Zenya/srb-2-marathon-demos
  • Acelite/srb-2-archivedmodifications
  • MIDIMan/SRB2
  • Lach/SRB2
  • Frostiikin/bounce-tweaks
  • Jaden/SRB2
  • Tyron/SRB2
  • Astronight/SRB2
  • Mari0shi06/SRB2
  • aiire/SRB2
  • Galactice/SRB2
  • srb2-ports/srb2-dreamcast
  • sdasdas/SRB2
  • chreas/srb-2-vr
  • StarManiaKG/the-story-of-sinically-rocketing-and-botching-the-2nd
  • LoganAir/SRB2
  • NepDisk/srb-2
  • alufolie91/SRB2
  • Felicia.iso/SRB2
  • twi/SRB2
  • BarrelsOFun/SRB2
  • Speed2411/SRB2
  • Leather_Realms/SRB2
  • Ayemar/SRB2
  • Acelite/SRB2
  • VladDoc/SRB2
  • kaldrum/model-features
  • strawberryfox417/SRB2
  • Lugent/SRB2
  • Rem/SRB2
  • Refrag/SRB2
  • Henry_3230/srb-3230
  • TehPuertoRicanSpartan2/tprs-srb2
  • Leminn/srb-2-marathon-stuff
  • chromaticpipe2/SRB2
  • MiguelGustavo15/SRB2
  • Maru/srb-2-tests
  • SilicDev/SRB2
  • UnmatchedBracket/SRB2
  • HybridDog/SRB2
  • xordspar0/SRB2
  • jsjhbewfhh/SRB2
  • Fancy2209/SRB2
  • Lorsoen/SRB2
  • shindoukin/SRB2
  • GamerOfDays/SRB2
  • Craftyawesome/SRB2
  • tenshi-tensai-tennoji/SRB2
  • Scarfdudebalder/SRB2
  • luigi-budd/srb-2-fix-interplag-lockon
  • mskluesner/SRB2
  • johnpetersa19/SRB2
  • Pheazant/SRB2
  • chromaticpipe2/srb2classic
  • romoney5/SRB2
  • BlueStaggo/SRB2
  • Jisk/srb-2-beef-jerky
  • voltybystorm/SRB2
  • ZenithNeko/srb-2-xp
  • Nep2Disk/SRB2
  • Cloudeon/SRB2
  • mushe/srb-2-ps-b
  • GlassCanonLover77/SRB2
  • PAS/SRB2
  • nothingjust752/SRB2
  • yusufali1009/srb-2-zintaru
125 results
Select Git revision
Loading items
Show changes
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -313,6 +313,7 @@ typedef struct mobj_s
UINT32 renderflags; // render flags
INT32 blendmode; // blend mode
fixed_t alpha; // alpha
fixed_t spritexscale, spriteyscale;
fixed_t spritexoffset, spriteyoffset;
fixed_t old_spritexscale, old_spriteyscale, old_spritexscale2, old_spriteyscale2;
......@@ -456,6 +457,7 @@ typedef struct precipmobj_s
UINT32 renderflags; // render flags
INT32 blendmode; // blend mode
fixed_t alpha; // alpha
fixed_t spritexscale, spriteyscale;
fixed_t spritexoffset, spriteyoffset;
fixed_t old_spritexscale, old_spriteyscale, old_spritexscale2, old_spriteyscale2;
......@@ -537,6 +539,8 @@ boolean P_SceneryZMovement(mobj_t *mo);
void P_PlayerZMovement(mobj_t *mo);
void P_EmeraldManager(void);
mobj_t *P_FindNewPosition(UINT32 oldposition);
extern INT32 modulothing;
#define MAXHUNTEMERALDS 64
......
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2006 by James Haley
// Copyright (C) 2006-2023 by Sonic Team Junior.
// Copyright (C) 2006-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -878,15 +878,15 @@ static void Polyobj_carryThings(polyobj_t *po, fixed_t dx, fixed_t dy)
{
mobj_t *mo;
blocknode_t *block;
blocknode_t *next = NULL;
if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
continue;
block = blocklinks[y * bmapwidth + x];
for (; block; block = block->mnext)
for (block = blocklinks[y * bmapwidth + x]; block != NULL; block = next)
{
mo = block->mobj;
next = block->mnext;
if (mo->lastlook == pomovecount)
continue;
......@@ -927,11 +927,11 @@ static INT32 Polyobj_clipThings(polyobj_t *po, line_t *line)
if (!(po->flags & POF_SOLID))
return hitflags;
// adjust linedef bounding box to blockmap, extend by MAXRADIUS
linebox[BOXLEFT] = (unsigned)(line->bbox[BOXLEFT] - bmaporgx - MAXRADIUS) >> MAPBLOCKSHIFT;
linebox[BOXRIGHT] = (unsigned)(line->bbox[BOXRIGHT] - bmaporgx + MAXRADIUS) >> MAPBLOCKSHIFT;
linebox[BOXBOTTOM] = (unsigned)(line->bbox[BOXBOTTOM] - bmaporgy - MAXRADIUS) >> MAPBLOCKSHIFT;
linebox[BOXTOP] = (unsigned)(line->bbox[BOXTOP] - bmaporgy + MAXRADIUS) >> MAPBLOCKSHIFT;
// adjust linedef bounding box to blockmap
linebox[BOXLEFT] = (unsigned)(line->bbox[BOXLEFT] - bmaporgx) >> MAPBLOCKSHIFT;
linebox[BOXRIGHT] = (unsigned)(line->bbox[BOXRIGHT] - bmaporgx) >> MAPBLOCKSHIFT;
linebox[BOXBOTTOM] = (unsigned)(line->bbox[BOXBOTTOM] - bmaporgy) >> MAPBLOCKSHIFT;
linebox[BOXTOP] = (unsigned)(line->bbox[BOXTOP] - bmaporgy) >> MAPBLOCKSHIFT;
// check all mobj blockmap cells the line contacts
for (y = linebox[BOXBOTTOM]; y <= linebox[BOXTOP]; ++y)
......@@ -942,9 +942,11 @@ static INT32 Polyobj_clipThings(polyobj_t *po, line_t *line)
{
mobj_t *mo = NULL;
blocknode_t *block = blocklinks[y * bmapwidth + x];
blocknode_t *next = NULL;
for (; block; block = block->mnext)
for (; block != NULL; block = next)
{
next = block->mnext;
mo = block->mobj;
// Don't scroll objects that aren't affected by gravity
......@@ -1115,15 +1117,15 @@ static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta,
{
mobj_t *mo;
blocknode_t *block;
blocknode_t *next = NULL;
if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
continue;
block = blocklinks[y * bmapwidth + x];
for (; block; block = block->mnext)
for (block = blocklinks[y * bmapwidth + x]; block != NULL; block = next)
{
mo = block->mobj;
next = block->mnext;
if (mo->lastlook == pomovecount)
continue;
......@@ -1316,7 +1318,7 @@ void Polyobj_InitLevel(void)
// the mobj_t pointers on a queue for use below.
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
mo = (mobj_t *)th;
......@@ -1649,7 +1651,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
distx = target->x - pox;
disty = target->y - poy;
distz = target->z - poz;
dist = P_AproxDistance(P_AproxDistance(distx, disty), distz);
dist = GetDistance3D(pox, poy, poz, target->x, target->y, target->z);
if (dist < 1)
dist = 1;
......@@ -2032,7 +2034,7 @@ boolean EV_DoPolyObjRotate(polyrotdata_t *prdata)
// create a new thinker
th = Z_Malloc(sizeof(polyrotate_t), PU_LEVSPEC, NULL);
th->thinker.function.acp1 = (actionf_p1)T_PolyObjRotate;
th->thinker.function = (actionf_p1)T_PolyObjRotate;
P_AddThinker(THINK_POLYOBJ, &th->thinker);
po->thinker = &th->thinker;
......@@ -2104,7 +2106,7 @@ boolean EV_DoPolyObjMove(polymovedata_t *pmdata)
// create a new thinker
th = Z_Malloc(sizeof(polymove_t), PU_LEVSPEC, NULL);
th->thinker.function.acp1 = (actionf_p1)T_PolyObjMove;
th->thinker.function = (actionf_p1)T_PolyObjMove;
P_AddThinker(THINK_POLYOBJ, &th->thinker);
po->thinker = &th->thinker;
......@@ -2166,7 +2168,7 @@ boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
// create a new thinker
th = Z_Malloc(sizeof(polywaypoint_t), PU_LEVSPEC, NULL);
th->thinker.function.acp1 = (actionf_p1)T_PolyObjWaypoint;
th->thinker.function = (actionf_p1)T_PolyObjWaypoint;
P_AddThinker(THINK_POLYOBJ, &th->thinker);
po->thinker = &th->thinker;
......@@ -2234,7 +2236,7 @@ static void Polyobj_doSlideDoor(polyobj_t *po, polydoordata_t *doordata)
// allocate and add a new slide door thinker
th = Z_Malloc(sizeof(polyslidedoor_t), PU_LEVSPEC, NULL);
th->thinker.function.acp1 = (actionf_p1)T_PolyDoorSlide;
th->thinker.function = (actionf_p1)T_PolyDoorSlide;
P_AddThinker(THINK_POLYOBJ, &th->thinker);
// point the polyobject to this thinker
......@@ -2285,7 +2287,7 @@ static void Polyobj_doSwingDoor(polyobj_t *po, polydoordata_t *doordata)
// allocate and add a new swing door thinker
th = Z_Malloc(sizeof(polyswingdoor_t), PU_LEVSPEC, NULL);
th->thinker.function.acp1 = (actionf_p1)T_PolyDoorSwing;
th->thinker.function = (actionf_p1)T_PolyDoorSwing;
P_AddThinker(THINK_POLYOBJ, &th->thinker);
// point the polyobject to this thinker
......@@ -2370,7 +2372,7 @@ boolean EV_DoPolyObjDisplace(polydisplacedata_t *prdata)
// create a new thinker
th = Z_Malloc(sizeof(polydisplace_t), PU_LEVSPEC, NULL);
th->thinker.function.acp1 = (actionf_p1)T_PolyObjDisplace;
th->thinker.function = (actionf_p1)T_PolyObjDisplace;
P_AddThinker(THINK_POLYOBJ, &th->thinker);
po->thinker = &th->thinker;
......@@ -2419,7 +2421,7 @@ boolean EV_DoPolyObjRotDisplace(polyrotdisplacedata_t *prdata)
// create a new thinker
th = Z_Malloc(sizeof(polyrotdisplace_t), PU_LEVSPEC, NULL);
th->thinker.function.acp1 = (actionf_p1)T_PolyObjRotDisplace;
th->thinker.function = (actionf_p1)T_PolyObjRotDisplace;
P_AddThinker(THINK_POLYOBJ, &th->thinker);
po->thinker = &th->thinker;
......@@ -2524,7 +2526,7 @@ boolean EV_DoPolyObjFlag(polyflagdata_t *pfdata)
// create a new thinker
th = Z_Malloc(sizeof(polymove_t), PU_LEVSPEC, NULL);
th->thinker.function.acp1 = (actionf_p1)T_PolyObjFlag;
th->thinker.function = (actionf_p1)T_PolyObjFlag;
P_AddThinker(THINK_POLYOBJ, &th->thinker);
po->thinker = &th->thinker;
......@@ -2672,12 +2674,12 @@ boolean EV_DoPolyObjFade(polyfadedata_t *pfdata)
if (po->translucency == pfdata->destvalue)
return true;
if (po->thinker && po->thinker->function.acp1 == (actionf_p1)T_PolyObjFade)
if (po->thinker && po->thinker->function == (actionf_p1)T_PolyObjFade)
P_RemoveThinker(po->thinker);
// create a new thinker
th = Z_Malloc(sizeof(polyfade_t), PU_LEVSPEC, NULL);
th->thinker.function.acp1 = (actionf_p1)T_PolyObjFade;
th->thinker.function = (actionf_p1)T_PolyObjFade;
P_AddThinker(THINK_POLYOBJ, &th->thinker);
po->thinker = &th->thinker;
......
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -39,7 +39,7 @@
#define FF_FRAMEMASK 0xff
/// \brief Frame flags - SPR2: Super sprite2
#define FF_SPR2SUPER 0x80
#define FF_SPR2SUPER SPR2F_SUPER //TODO: 2.3: remove this backwards compat hack
/// \brief Frame flags - SPR2: A change of state at the end of Sprite2 animation
#define FF_SPR2ENDSTATE 0x100
/// \brief Frame flags - SPR2: 50% of starting in middle of Sprite2 animation
......
Source diff could not be displayed: it is too large. Options to address this: view the blob.
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -18,17 +18,24 @@
#pragma interface
#endif
#include "tables.h"
#define NEWSKINSAVES (INT16_MAX) // TODO: 2.3: Delete (Purely for backwards compatibility)
// Persistent storage/archiving.
// These are the load / save game routines.
void P_SaveGame(INT16 mapnum);
void P_SaveNetGame(boolean resending);
boolean P_LoadGame(INT16 mapoverride);
boolean P_LoadNetGame(boolean reloading);
typedef struct
{
unsigned char *buf;
size_t size;
size_t pos;
} save_t;
mobj_t *P_FindNewPosition(UINT32 oldposition);
void P_SaveGame(save_t *save_p, INT16 mapnum);
void P_SaveNetGame(save_t *save_p, boolean resending);
boolean P_LoadGame(save_t *save_p, INT16 mapoverride);
boolean P_LoadNetGame(save_t *save_p, boolean reloading);
typedef struct
{
......@@ -42,6 +49,37 @@ typedef struct
} savedata_t;
extern savedata_t savedata;
extern UINT8 *save_p;
void P_WriteUINT8(save_t *p, UINT8 v);
void P_WriteSINT8(save_t *p, SINT8 v);
void P_WriteUINT16(save_t *p, UINT16 v);
void P_WriteINT16(save_t *p, INT16 v);
void P_WriteUINT32(save_t *p, UINT32 v);
void P_WriteINT32(save_t *p, INT32 v);
void P_WriteChar(save_t *p, char v);
void P_WriteFixed(save_t *p, fixed_t v);
void P_WriteAngle(save_t *p, angle_t v);
void P_WriteStringN(save_t *p, char const *s, size_t n);
void P_WriteStringL(save_t *p, char const *s, size_t n);
void P_WriteString(save_t *p, char const *s);
void P_WriteMem(save_t *p, void const *s, size_t n);
void P_SkipStringN(save_t *p, size_t n);
void P_SkipStringL(save_t *p, size_t n);
void P_SkipString(save_t *p);
UINT8 P_ReadUINT8(save_t *p);
SINT8 P_ReadSINT8(save_t *p);
UINT16 P_ReadUINT16(save_t *p);
INT16 P_ReadINT16(save_t *p);
UINT32 P_ReadUINT32(save_t *p);
INT32 P_ReadINT32(save_t *p);
char P_ReadChar(save_t *p);
fixed_t P_ReadFixed(save_t *p);
angle_t P_ReadAngle(save_t *p);
void P_ReadStringN(save_t *p, char *s, size_t n);
void P_ReadStringL(save_t *p, char *s, size_t n);
void P_ReadString(save_t *p, char *s);
void P_ReadMem(save_t *p, void *s, size_t n);
#endif
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -11,6 +11,9 @@
/// \file p_setup.c
/// \brief Do all the WAD I/O, get map description, set up initial state and misc. LUTs
#include <errno.h>
#include "doomdef.h"
#include "d_main.h"
#include "byteptr.h"
......@@ -108,7 +111,7 @@ vertex_t *vertexes;
seg_t *segs;
sector_t *sectors;
subsector_t *subsectors;
node_t *nodes;
bspnode_t *nodes;
line_t *lines;
side_t *sides;
mapthing_t *mapthings;
......@@ -238,7 +241,7 @@ mobj_t *P_GetClosestWaypoint(UINT8 sequence, mobj_t *mo)
if (!mo2)
continue;
curdist = P_AproxDistance(P_AproxDistance(mo->x - mo2->x, mo->y - mo2->y), mo->z - mo2->z);
curdist = P_GetMobjDistance3D(mo, mo2);
if (result && curdist > bestdist)
continue;
......@@ -609,15 +612,15 @@ Ploadflat (levelflat_t *levelflat, const char *flatname, boolean resize)
levelflat->type = LEVELFLAT_TEXTURE;
// Look for a flat
int texturenum = R_CheckFlatNumForName(levelflat->name);
int texturenum = R_CheckTextureNumForName(levelflat->name, TEXTURETYPE_FLAT);
if (texturenum < 0)
{
// If we can't find a flat, try looking for a texture!
texturenum = R_CheckTextureNumForName(levelflat->name);
texturenum = R_CheckTextureNumForName(levelflat->name, TEXTURETYPE_TEXTURE);
if (texturenum < 0)
{
// Use "not found" texture
texturenum = R_CheckTextureNumForName("REDWALL");
texturenum = R_CheckTextureNumForName("REDWALL", TEXTURETYPE_TEXTURE);
// Give up?
if (texturenum < 0)
......@@ -692,7 +695,7 @@ void P_ReloadRings(void)
// scan the thinkers to find rings/spheres/hoops to unset
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
mo = (mobj_t *)th;
......@@ -750,7 +753,7 @@ void P_SwitchSpheresBonusMode(boolean bonustime)
// scan the thinkers to find spheres to switch
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
mo = (mobj_t *)th;
......@@ -831,13 +834,15 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum)
static void P_SpawnEmeraldHunt(void)
{
INT32 emer[3], num[MAXHUNTEMERALDS], i, randomkey;
INT32 emer[3], num[MAXHUNTEMERALDS], i, amount, randomkey;
fixed_t x, y, z;
for (i = 0; i < numhuntemeralds; i++)
num[i] = i;
for (i = 0; i < 3; i++)
amount = min(numhuntemeralds, 3);
for (i = 0; i < amount; i++)
{
// generate random index, shuffle afterwards
randomkey = P_RandomKey(numhuntemeralds--);
......@@ -1075,6 +1080,7 @@ static void P_LoadSectors(UINT8 *data)
ss->triggerer = TO_PLAYER;
ss->friction = ORIG_FRICTION;
ss->customargs = NULL;
P_InitializeSector(ss);
}
......@@ -1113,6 +1119,8 @@ static void P_InitializeLinedef(line_t *ld)
ld->callcount = 0;
ld->secportal = UINT32_MAX;
ld->midtexslope = NULL;
// cph 2006/09/30 - fix sidedef errors right away.
// cph 2002/07/20 - these errors are fatal if not fixed, so apply them
for (j = 0; j < 2; j++)
......@@ -1195,6 +1203,8 @@ static void P_LoadLinedefs(UINT8 *data)
if (ld->sidenum[1] == 0xffff)
ld->sidenum[1] = NO_SIDEDEF;
ld->customargs = NULL;
P_InitializeLinedef(ld);
}
}
......@@ -1363,6 +1373,11 @@ static void P_LoadSidedefs(UINT8 *data)
sd->scalex_top = sd->scalex_mid = sd->scalex_bottom = FRACUNIT;
sd->scaley_top = sd->scaley_mid = sd->scaley_bottom = FRACUNIT;
sd->light = sd->light_top = sd->light_mid = sd->light_bottom = 0;
sd->lightabsolute = sd->lightabsolute_top = sd->lightabsolute_mid = sd->lightabsolute_bottom = false;
sd->customargs = NULL;
P_SetSidedefSector(i, (UINT16)SHORT(msd->sector));
// Special info stored in texture fields!
......@@ -1546,15 +1561,46 @@ static void P_LoadThings(UINT8 *data)
mt->z = mt->options >> ZSHIFT;
mt->mobj = NULL;
mt->customargs = NULL;
}
}
// Stores positions for relevant map data spread through a TEXTMAP.
UINT32 mapthingsPos[UINT16_MAX];
UINT32 linesPos[UINT16_MAX];
UINT32 sidesPos[UINT16_MAX];
UINT32 vertexesPos[UINT16_MAX];
UINT32 sectorsPos[UINT16_MAX];
typedef struct textmap_block_s
{
UINT32 *pos;
size_t capacity;
} textmap_block_t;
static textmap_block_t mapthingBlocks;
static textmap_block_t linedefBlocks;
static textmap_block_t sidedefBlocks;
static textmap_block_t vertexBlocks;
static textmap_block_t sectorBlocks;
static void TextmapStorePos(textmap_block_t *blocks, size_t *count)
{
size_t locCount = (*count) + 1;
if (blocks->pos == NULL)
{
// Initial capacity (half of the former one.)
blocks->capacity = UINT16_MAX / 2;
Z_Calloc(sizeof(blocks->pos) * blocks->capacity, PU_LEVEL, &blocks->pos);
}
else if (locCount >= blocks->capacity)
{
// If we hit the list's capacity, make space for 1024 more blocks
blocks->capacity += 1024;
Z_Realloc(blocks->pos, sizeof(blocks->pos) * blocks->capacity, PU_LEVEL, &blocks->pos);
}
blocks->pos[locCount - 1] = M_TokenizerGetEndPos();
(*count) = locCount;
}
// Determine total amount of map data in TEXTMAP.
static boolean TextmapCount(size_t size)
......@@ -1598,15 +1644,15 @@ static boolean TextmapCount(size_t size)
brackets++;
// Check for valid fields.
else if (fastcmp(tkn, "thing"))
mapthingsPos[nummapthings++] = M_TokenizerGetEndPos();
TextmapStorePos(&mapthingBlocks, &nummapthings);
else if (fastcmp(tkn, "linedef"))
linesPos[numlines++] = M_TokenizerGetEndPos();
TextmapStorePos(&linedefBlocks, &numlines);
else if (fastcmp(tkn, "sidedef"))
sidesPos[numsides++] = M_TokenizerGetEndPos();
TextmapStorePos(&sidedefBlocks, &numsides);
else if (fastcmp(tkn, "vertex"))
vertexesPos[numvertexes++] = M_TokenizerGetEndPos();
TextmapStorePos(&vertexBlocks, &numvertexes);
else if (fastcmp(tkn, "sector"))
sectorsPos[numsectors++] = M_TokenizerGetEndPos();
TextmapStorePos(&sectorBlocks, &numsectors);
else
CONS_Alert(CONS_NOTICE, "Unknown field '%s'.\n", tkn);
}
......@@ -1620,6 +1666,89 @@ static boolean TextmapCount(size_t size)
return true;
}
static void ParseTextmapCustomFields(const char* param, const char* val, customargs_t** headptr)
{
if (val[0] == '\0')
return;
//
// GET latest node
//
customargs_t* newnode = Z_Malloc(sizeof(customargs_t), PU_LEVEL, NULL);
if (!newnode)
return;
newnode->next = NULL;
if (*headptr == NULL) {
*headptr = newnode;
}
else {
customargs_t* curr = *headptr;
while (curr->next != NULL) {
curr = curr->next;
}
curr->next = newnode;
}
//
// Setup
//
newnode->name = Z_Malloc(strlen(param + 5) + 1, PU_LEVEL, NULL);
M_Memcpy(newnode->name, param + 5, strlen(param + 5) + 1);
if (fastcmp(val, "true"))
{
newnode->type = UDMF_TYPE_BOOLEAN;
newnode->value.vbool = true;
}
else if (fastcmp(val, "false"))
{
newnode->type = UDMF_TYPE_BOOLEAN;
newnode->value.vbool = false;
}
else
{
char* endptr;
long lval;
float fval;
// Eval integer
errno = 0;
lval = strtol(val, &endptr, 10);
if (*endptr == '\0' && endptr != val && errno == 0) {
newnode->type = UDMF_TYPE_NUMERIC;
newnode->value.vint = lval;
return;
}
// Eval float
errno = 0;
fval = strtof(val, &endptr);
if (*endptr == '\0' && endptr != val && errno == 0) {
newnode->type = UDMF_TYPE_FIXED;
newnode->value.vfloat = FLOAT_TO_FIXED(fval);
return;
}
// Just string
newnode->type = UDMF_TYPE_STRING;
newnode->value.vstring = Z_Malloc(strlen(val) + 1, PU_LEVEL, NULL);
M_Memcpy(newnode->value.vstring, val, strlen(val) + 1);
}
}
static void ParseTextmapVertexParameter(UINT32 i, const char *param, const char *val)
{
if (fastcmp(param, "x"))
......@@ -1719,6 +1848,8 @@ static void ParseTextmapSectorParameter(UINT32 i, const char *param, const char
sectors[i].floorangle = FixedAngle(FLOAT_TO_FIXED(atof(val)));
else if (fastcmp(param, "rotationceiling"))
sectors[i].ceilingangle = FixedAngle(FLOAT_TO_FIXED(atof(val)));
else if (fastncmp(param, "user_", 5) && strlen(param) > 5)
ParseTextmapCustomFields(param, val, &sectors[i].customargs);
else if (fastcmp(param, "floorplane_a"))
{
textmap_planefloor.defined |= PD_A;
......@@ -1943,6 +2074,24 @@ static void ParseTextmapSidedefParameter(UINT32 i, const char *param, const char
P_SetSidedefSector(i, atol(val));
else if (fastcmp(param, "repeatcnt"))
sides[i].repeatcnt = atol(val);
else if (fastcmp(param, "light"))
sides[i].light = atol(val);
else if (fastcmp(param, "light_top"))
sides[i].light_top = atol(val);
else if (fastcmp(param, "light_mid"))
sides[i].light_mid = atol(val);
else if (fastcmp(param, "light_bottom"))
sides[i].light_bottom = atol(val);
else if (fastcmp(param, "lightabsolute") && fastcmp("true", val))
sides[i].lightabsolute = true;
else if (fastcmp(param, "lightabsolute_top") && fastcmp("true", val))
sides[i].lightabsolute_top = true;
else if (fastcmp(param, "lightabsolute_mid") && fastcmp("true", val))
sides[i].lightabsolute_mid = true;
else if (fastcmp(param, "lightabsolute_bottom") && fastcmp("true", val))
sides[i].lightabsolute_bottom = true;
else if (fastncmp(param, "user_", 5) && strlen(param) > 5)
ParseTextmapCustomFields(param, val, &sides[i].customargs);
}
static void ParseTextmapLinedefParameter(UINT32 i, const char *param, const char *val)
......@@ -2037,6 +2186,9 @@ static void ParseTextmapLinedefParameter(UINT32 i, const char *param, const char
lines[i].flags |= ML_BOUNCY;
else if (fastcmp(param, "transfer") && fastcmp("true", val))
lines[i].flags |= ML_TFERLINE;
else if (fastncmp(param, "user_", 5) && strlen(param) > 5)
ParseTextmapCustomFields(param, val, &lines[i].customargs);
}
static void ParseTextmapThingParameter(UINT32 i, const char *param, const char *val)
......@@ -2096,6 +2248,8 @@ static void ParseTextmapThingParameter(UINT32 i, const char *param, const char *
return;
mapthings[i].args[argnum] = atol(val);
}
else if (fastncmp(param, "user_", 5) && strlen(param) > 5)
ParseTextmapCustomFields(param, val, &mapthings[i].customargs);
}
/** From a given position table, run a specified parser function through a {}-encapsuled text.
......@@ -2670,6 +2824,22 @@ static void P_WriteTextmap(void)
fprintf(f, "texturemiddle = \"%.*s\";\n", 8, textures[wsides[i].midtexture]->name);
if (wsides[i].repeatcnt != 0)
fprintf(f, "repeatcnt = %d;\n", wsides[i].repeatcnt);
if (wsides[i].light != 0)
fprintf(f, "light = %d;\n", wsides[i].light);
if (wsides[i].light_top != 0)
fprintf(f, "light_top = %d;\n", wsides[i].light_top);
if (wsides[i].light_mid != 0)
fprintf(f, "light_mid = %d;\n", wsides[i].light_mid);
if (wsides[i].light_bottom != 0)
fprintf(f, "light_bottom = %d;\n", wsides[i].light_bottom);
if (wsides[i].lightabsolute)
fprintf(f, "lightabsolute = true;\n");
if (wsides[i].lightabsolute_top)
fprintf(f, "lightabsolute_top = true;\n");
if (wsides[i].lightabsolute_mid)
fprintf(f, "lightabsolute_mid = true;\n");
if (wsides[i].lightabsolute_bottom)
fprintf(f, "lightabsolute_bottom = true;\n");
fprintf(f, "}\n");
fprintf(f, "\n");
}
......@@ -2926,7 +3096,7 @@ static void P_LoadTextmap(void)
side_t *sd;
mapthing_t *mt;
CONS_Alert(CONS_NOTICE, "UDMF support is still a work-in-progress; its specs and features are prone to change until it is fully implemented.\n");
//CONS_Alert(CONS_NOTICE, "UDMF support is still a work-in-progress; its specs and features are prone to change until it is fully implemented.\n");
/// Given the UDMF specs, some fields are given a default value.
/// If an element's field has a default value set, it is omitted
......@@ -2940,7 +3110,7 @@ static void P_LoadTextmap(void)
vt->floorzset = vt->ceilingzset = false;
vt->floorz = vt->ceilingz = 0;
TextmapParse(vertexesPos[i], i, ParseTextmapVertexParameter);
TextmapParse(vertexBlocks.pos[i], i, ParseTextmapVertexParameter);
if (vt->x == INT32_MAX)
I_Error("P_LoadTextmap: vertex %s has no x value set!\n", sizeu1(i));
......@@ -2984,6 +3154,7 @@ static void P_LoadTextmap(void)
sc->triggerer = TO_PLAYER;
sc->friction = ORIG_FRICTION;
sc->customargs = NULL;
textmap_colormap.used = false;
textmap_colormap.lightcolor = 0;
......@@ -2997,7 +3168,7 @@ static void P_LoadTextmap(void)
textmap_planefloor.defined = 0;
textmap_planeceiling.defined = 0;
TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter);
TextmapParse(sectorBlocks.pos[i], i, ParseTextmapSectorParameter);
P_InitializeSector(sc);
if (textmap_colormap.used)
......@@ -3045,8 +3216,9 @@ static void P_LoadTextmap(void)
ld->executordelay = 0;
ld->sidenum[0] = NO_SIDEDEF;
ld->sidenum[1] = NO_SIDEDEF;
ld->customargs = NULL;
TextmapParse(linesPos[i], i, ParseTextmapLinedefParameter);
TextmapParse(linedefBlocks.pos[i], i, ParseTextmapLinedefParameter);
if (!ld->v1)
I_Error("P_LoadTextmap: linedef %s has no v1 value set!\n", sizeu1(i));
......@@ -3072,8 +3244,11 @@ static void P_LoadTextmap(void)
sd->bottomtexture = R_TextureNumForName("-");
sd->sector = NULL;
sd->repeatcnt = 0;
sd->light = sd->light_top = sd->light_mid = sd->light_bottom = 0;
sd->lightabsolute = sd->lightabsolute_top = sd->lightabsolute_mid = sd->lightabsolute_bottom = false;
sd->customargs = NULL;
TextmapParse(sidesPos[i], i, ParseTextmapSidedefParameter);
TextmapParse(sidedefBlocks.pos[i], i, ParseTextmapSidedefParameter);
if (!sd->sector)
I_Error("P_LoadTextmap: sidedef %s has no sector value set!\n", sizeu1(i));
......@@ -3096,8 +3271,9 @@ static void P_LoadTextmap(void)
memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args));
memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs));
mt->mobj = NULL;
mt->customargs = NULL;
TextmapParse(mapthingsPos[i], i, ParseTextmapThingParameter);
TextmapParse(mapthingBlocks.pos[i], i, ParseTextmapThingParameter);
}
}
......@@ -3296,7 +3472,7 @@ static void P_LoadNodes(UINT8 *data)
{
UINT8 j, k;
mapnode_t *mn = (mapnode_t*)data;
node_t *no = nodes;
bspnode_t *no = nodes;
size_t i;
for (i = 0; i < numnodes; i++, no++, mn++)
......@@ -3415,13 +3591,13 @@ typedef enum {
} nodetype_t;
// Find out the BSP format.
static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata)
static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata, char signature[4 + 1])
{
boolean supported[NUMNODETYPES] = {0};
nodetype_t nodetype = NT_UNSUPPORTED;
char signature[4 + 1];
*nodedata = NULL;
signature[0] = signature[4] = '\0';
if (udmf)
{
......@@ -3430,7 +3606,7 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata)
if (virtznodes && virtznodes->size)
{
*nodedata = virtznodes->data;
supported[NT_XGLN] = supported[NT_XGL3] = true;
supported[NT_XGLN] = supported[NT_XGL2] = supported[NT_XGL3] = true;
}
}
else
......@@ -3452,9 +3628,9 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata)
virtssectors = vres_Find(virt, "SSECTORS");
if (virtssectors && virtssectors->size)
{ // Possibly GL nodes: NODES ignored, SSECTORS takes precedence as nodes lump, (It is confusing yeah) and has a signature.
{ // Possibly GL nodes: NODES ignored, SSECTORS takes precedence as nodes lump (it is confusing, yeah), and has a signature.
*nodedata = virtssectors->data;
supported[NT_XGLN] = supported[NT_ZGLN] = supported[NT_XGL3] = true;
supported[NT_XGLN] = supported[NT_ZGLN] = supported[NT_XGL2] = supported[NT_XGL3] = true;
}
else
{ // Possibly ZDoom extended nodes: SSECTORS is empty, NODES has a signature.
......@@ -3474,19 +3650,42 @@ static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata)
}
M_Memcpy(signature, *nodedata, 4);
signature[4] = '\0';
(*nodedata) += 4;
if (!strcmp(signature, "XNOD"))
nodetype = NT_XNOD;
else if (!strcmp(signature, "ZNOD"))
nodetype = NT_ZNOD;
else if (!strcmp(signature, "XGLN"))
nodetype = NT_XGLN;
else if (!strcmp(signature, "ZGLN"))
nodetype = NT_ZGLN;
else if (!strcmp(signature, "XGL3"))
nodetype = NT_XGL3;
// Identify node format from its starting signature.
if (memcmp(&signature[1], "NOD", 3) == 0) // ZDoom extended nodes
{
if (signature[0] == 'X')
{
nodetype = NT_XNOD; // Uncompressed
}
else if (signature[0] == 'Z')
{
nodetype = NT_ZNOD; // Compressed
}
}
else if (memcmp(&signature[1], "GL", 2) == 0) // GL nodes
{
switch (signature[0])
{
case 'X': // Uncompressed
switch (signature[3])
{
case 'N': nodetype = NT_XGLN; break; // GL nodes
case '2': nodetype = NT_XGL2; break; // Version 2 GL nodes
case '3': nodetype = NT_XGL3; break; // Version 3 GL nodes
}
break;
case 'Z': // Compressed
switch (signature[3])
{
case 'N': nodetype = NT_ZGLN; break; // GL nodes (compressed)
case '2': nodetype = NT_ZGL2; break; // Version 2 GL nodes (compressed)
case '3': nodetype = NT_ZGL3; break; // Version 3 GL nodes (compressed)
}
break;
}
}
return supported[nodetype] ? nodetype : NT_UNSUPPORTED;
}
......@@ -3498,7 +3697,6 @@ static boolean P_LoadExtraVertices(UINT8 **data)
UINT32 xtrvrtx = READUINT32((*data));
line_t* ld = lines;
vertex_t *oldpos = vertexes;
ssize_t offset;
size_t i;
if (numvertexes != origvrtx) // If native vertex count doesn't match node original vertex count, bail out (broken data?).
......@@ -3513,12 +3711,11 @@ static boolean P_LoadExtraVertices(UINT8 **data)
// If extra vertexes were generated, reallocate the vertex array and fix the pointers.
numvertexes += xtrvrtx;
vertexes = Z_Realloc(vertexes, numvertexes*sizeof(*vertexes), PU_LEVEL, NULL);
offset = (size_t)(vertexes - oldpos);
for (i = 0, ld = lines; i < numlines; i++, ld++)
{
ld->v1 += offset;
ld->v2 += offset;
ld->v1 = &vertexes[ld->v1 - oldpos];
ld->v2 = &vertexes[ld->v2 - oldpos];
}
// Read extra vertex data.
......@@ -3556,6 +3753,7 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype
switch (nodetype)
{
case NT_XGLN:
case NT_XGL2:
case NT_XGL3:
for (m = 0; m < (size_t)subsectors[i].numlines; m++, k++)
{
......@@ -3567,7 +3765,7 @@ static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype
READUINT32((*data)); // partner, can be ignored by software renderer
if (nodetype == NT_XGL3)
if (nodetype != NT_XGLN)
{
UINT32 linenum = READUINT32((*data));
if (linenum != 0xFFFFFFFF && linenum >= numlines)
......@@ -3650,7 +3848,7 @@ static UINT16 ShrinkNodeID(UINT32 x) {
static void P_LoadExtendedNodes(UINT8 **data, nodetype_t nodetype)
{
node_t *mn;
bspnode_t *mn;
size_t i, j, k;
boolean xgl3 = (nodetype == NT_XGL3);
......@@ -3678,8 +3876,9 @@ static void P_LoadExtendedNodes(UINT8 **data, nodetype_t nodetype)
static void P_LoadMapBSP(const virtres_t *virt)
{
char signature[4 + 1];
UINT8 *nodedata = NULL;
nodetype_t nodetype = P_GetNodetype(virt, &nodedata);
nodetype_t nodetype = P_GetNodetype(virt, &nodedata, signature);
switch (nodetype)
{
......@@ -3711,6 +3910,7 @@ static void P_LoadMapBSP(const virtres_t *virt)
}
case NT_XNOD:
case NT_XGLN:
case NT_XGL2:
case NT_XGL3:
if (!P_LoadExtraVertices(&nodedata))
return;
......@@ -3719,10 +3919,13 @@ static void P_LoadMapBSP(const virtres_t *virt)
P_LoadExtendedNodes(&nodedata, nodetype);
break;
default:
CONS_Alert(CONS_WARNING, "Unsupported BSP format detected.\n");
if (isprint(signature[0]) && isprint(signature[1]) && isprint(signature[2]) && isprint(signature[3]))
{
I_Error("Unsupported BSP format '%s' detected!\n", signature);
return;
}
return;
I_Error("Unknown BSP format detected!\n");
}
}
// Split from P_LoadBlockMap for convenience
......@@ -5527,7 +5730,7 @@ static void P_ConvertBinaryLinedefTypes(void)
}
else
{
lines[i].args[2] = R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> (FRACBITS + 1);
lines[i].args[2] = GetDistance2D(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> (FRACBITS + 1);
lines[i].args[3] = lines[i].args[2] / 4;
}
lines[i].special = 429;
......@@ -5556,7 +5759,7 @@ static void P_ConvertBinaryLinedefTypes(void)
break;
case 435: //Change plane scroller direction
lines[i].args[0] = tag;
lines[i].args[1] = R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> FRACBITS;
lines[i].args[1] = GetDistance2D(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y) >> FRACBITS;
break;
case 436: //Shatter FOF
lines[i].args[0] = sides[lines[i].sidenum[0]].textureoffset >> FRACBITS;
......@@ -5957,7 +6160,7 @@ static void P_ConvertBinaryLinedefTypes(void)
lines[i].args[0] = tag;
lines[i].args[1] = ((lines[i].special % 10) < 6) ? (((lines[i].special % 10) < 3) ? TMP_FLOOR : TMP_CEILING) : TMP_BOTH;
lines[i].args[2] = ((lines[i].special - 510)/10 + 1) % 3;
lines[i].args[3] = ((lines[i].flags & ML_EFFECT6) ? sides[lines[i].sidenum[0]].textureoffset : R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y)) >> FRACBITS;
lines[i].args[3] = ((lines[i].flags & ML_EFFECT6) ? sides[lines[i].sidenum[0]].textureoffset : GetDistance2D(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y)) >> FRACBITS;
lines[i].args[4] = (lines[i].special % 10) % 3;
if (lines[i].args[2] != TMS_SCROLLONLY && !(lines[i].flags & ML_NOCLIMB))
lines[i].args[4] |= TMST_NONEXCLUSIVE;
......@@ -5989,7 +6192,7 @@ static void P_ConvertBinaryLinedefTypes(void)
case 545: //Upwards current
case 546: //Downwards current
{
fixed_t strength = (lines[i].flags & ML_EFFECT6) ? sides[lines[i].sidenum[0]].textureoffset : R_PointToDist2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y);
fixed_t strength = (lines[i].flags & ML_EFFECT6) ? sides[lines[i].sidenum[0]].textureoffset : GetDistance2D(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y);
lines[i].args[0] = tag;
switch ((lines[i].special - 541) % 3)
{
......@@ -6694,7 +6897,7 @@ static void P_ConvertBinaryThingTypes(void)
break;
}
mapthings[i].args[0] = mapthings[i].z;
mapthings[i].args[1] = R_PointToDist2(lines[j].v1->x, lines[j].v1->y, lines[j].v2->x, lines[j].v2->y) >> FRACBITS;
mapthings[i].args[1] = GetDistance2D(lines[j].v1->x, lines[j].v1->y, lines[j].v2->x, lines[j].v2->y) >> FRACBITS;
mapthings[i].args[2] = sides[lines[j].sidenum[0]].textureoffset >> FRACBITS;
mapthings[i].args[3] = sides[lines[j].sidenum[0]].rowoffset >> FRACBITS;
mapthings[i].args[4] = lines[j].backsector ? sides[lines[j].sidenum[1]].textureoffset >> FRACBITS : 0;
......@@ -6992,19 +7195,12 @@ static void P_ConvertBinaryMap(void)
*/
static INT32 P_MakeBufferMD5(const char *buffer, size_t len, void *resblock)
{
#ifdef NOMD5
(void)buffer;
(void)len;
memset(resblock, 0x00, 16);
return 1;
#else
tic_t t = I_GetTime();
CONS_Debug(DBG_SETUP, "Making MD5\n");
if (md5_buffer(buffer, len, resblock) == NULL)
return 1;
CONS_Debug(DBG_SETUP, "MD5 calc took %f seconds\n", (float)(I_GetTime() - t)/NEWTICRATE);
return 0;
#endif
}
static void P_MakeMapMD5(virtres_t *virt, void *dest)
......@@ -7147,7 +7343,7 @@ static void P_InitLevelSettings(void)
countdowntimer = mapheaderinfo[gamemap-1]->countdown * TICRATE;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
if (!players[i].ingame)
continue;
if (players[i].starposttime > maxtime)
maxtime = players[i].starposttime;
......@@ -7181,7 +7377,7 @@ static void P_InitLevelSettings(void)
{
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && players[i].lives > 0)
if (players[i].ingame && players[i].lives > 0)
{
canresetlives = false;
break;
......@@ -7195,7 +7391,7 @@ static void P_InitLevelSettings(void)
{
G_PlayerReborn(i, true);
if (canresetlives && (netgame || multiplayer) && playeringame[i] && (G_CompetitionGametype() || players[i].lives <= 0))
if (canresetlives && (netgame || multiplayer) && players[i].ingame && (G_CompetitionGametype() || players[i].lives <= 0))
{
// In Co-Op, replenish a user's lives if they are depleted.
players[i].lives = cv_startinglives.value;
......@@ -7235,7 +7431,7 @@ void P_RespawnThings(void)
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (think->removing)
continue;
P_RemoveMobj((mobj_t *)think);
}
......@@ -7271,11 +7467,11 @@ static void P_RunLevelScript(const char *scriptname)
return;
}
COM_BufInsertText(W_CacheLumpNum(lumpnum, PU_CACHE));
COM_BufInsertTextEx(W_CacheLumpNum(lumpnum, PU_CACHE), COM_LUA);
}
else
{
COM_BufAddText(va("exec %s\n", scriptname));
COM_ExecFile(scriptname, COM_LUA, false);
}
COM_BufExecute(); // Run it!
}
......@@ -7288,7 +7484,7 @@ static void P_ForceCharacter(const char *forcecharskin)
for (unsigned i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
if (!players[i].ingame)
continue;
INT32 skinnum = R_SkinAvailable(forcecharskin);
......@@ -7463,7 +7659,7 @@ static void P_InitTagGametype(void)
//Also, you'd never have to loop through all 32 players slots to find anything ever again.
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && !(players[i].spectator || players[i].quittime))
if (players[i].ingame && !(players[i].spectator || players[i].quittime))
{
playersactive[realnumplayers] = i; //stores the player's node in the array.
realnumplayers++;
......@@ -7547,7 +7743,6 @@ static void P_InitCamera(void)
CV_SetValue(&cv_analog[1], 0);
displayplayer = consoleplayer; // Start with your OWN view, please!
}
if (twodlevel)
{
......@@ -7563,6 +7758,7 @@ static void P_InitCamera(void)
CV_SetValue(&cv_analog[1], true);
}
}
}
static void P_RunSpecialStageWipe(void)
{
......@@ -7570,7 +7766,7 @@ static void P_RunSpecialStageWipe(void)
tic_t endtime = starttime + (3*TICRATE)/2;
tic_t nowtime;
S_StartSound(NULL, sfx_s3kaf);
S_StartSoundFromEverywhere(sfx_s3kaf);
// Fade music! Time it to S3KAF: 0.25 seconds is snappy.
if (RESETMUSIC ||
......@@ -7640,7 +7836,7 @@ static void P_InitPlayers(void)
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
if (!players[i].ingame)
continue;
// Start players with pity shields if possible
......@@ -7715,7 +7911,7 @@ static void P_InitGametype(void)
tic_t maxstarposttime = 0;
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && players[i].starposttime > maxstarposttime)
if (players[i].ingame && players[i].starposttime > maxstarposttime)
maxstarposttime = players[i].starposttime;
}
leveltime = maxstarposttime;
......@@ -7755,6 +7951,10 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
maptol = mapheaderinfo[gamemap-1]->typeoflevel;
gametyperules = gametypedefaultrules[gametype];
// clear the target on map change, since the object will be invalidated
P_SetTarget(&ticcmd_ztargetfocus[0], NULL);
P_SetTarget(&ticcmd_ztargetfocus[1], NULL);
CON_Drawer(); // let the user know what we are going to do
I_FinishUpdate(); // page flip or blit buffer
......@@ -7859,7 +8059,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
if (ranspecialwipe == 2)
{
pausedelay = -3; // preticker plus one
S_StartSound(NULL, sfx_s3k73);
S_StartSoundFromEverywhere(sfx_s3k73);
}
// Print "SPEEDING OFF TO [ZONE] [ACT 1]..."
......@@ -7904,6 +8104,9 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
// Free GPU textures before freeing patches.
if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED))
HWR_ClearAllTextures();
// Delete light table textures
HWR_ClearLightTables();
#endif
Patch_FreeTag(PU_PATCH_LOWPRIORITY);
......@@ -7950,7 +8153,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
if (M_UpdateUnlockablesAndExtraEmblems(clientGamedata))
{
S_StartSound(NULL, sfx_s3k68);
S_StartSoundFromEverywhere(sfx_s3k68);
G_SaveGameData(clientGamedata);
}
else if (!reloadinggamestate)
......@@ -8015,6 +8218,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
R_PrecacheLevel();
nextmapoverride = 0;
keepcutscene = false;
skipstats = 0;
levelloading = false;
......@@ -8044,7 +8248,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
INT32 buf = gametic % BACKUPTICS;
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i])
if (players[i].ingame)
G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1);
}
P_PreTicker(2);
......
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......
......@@ -355,7 +355,7 @@ static boolean P_CrossBSPNode(INT32 bspnum, register los_t *los)
{
while (!(bspnum & NF_SUBSECTOR))
{
register node_t *bsp = nodes + bspnum;
register bspnode_t *bsp = nodes + bspnum;
INT32 side = P_DivlineSide(los->strace.x,los->strace.y,(divline_t *)bsp)&1;
if (side == P_DivlineSide(los->t2x, los->t2y, (divline_t *) bsp))
bspnum = bsp->children[side]; // doesn't touch the other side
......
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2009 by Stephen McGranahan.
// Copyright (C) 2015-2023 by Sonic Team Junior.
// Copyright (C) 2015-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -28,6 +28,8 @@
pslope_t *slopelist = NULL;
UINT16 slopecount = 0;
static void P_UpdateMidtextureSlopesForSector(sector_t *sector);
// Calculate line normal
void P_CalculateSlopeNormal(pslope_t *slope)
{
......@@ -98,7 +100,7 @@ static void ReconfigureViaVertexes (pslope_t *slope, const vector3_t v1, const v
);
// NOTE: FV3_Magnitude() doesn't work properly in some cases, and chaining FixedHypot() seems to give worse results.
m = R_PointToDist2(0, 0, R_PointToDist2(0, 0, slope->normal.x, slope->normal.y), slope->normal.z);
m = GetDistance3D(0, 0, 0, slope->normal.x, slope->normal.y, slope->normal.z);
// Invert normal if it's facing down.
if (slope->normal.z < 0)
......@@ -107,7 +109,7 @@ static void ReconfigureViaVertexes (pslope_t *slope, const vector3_t v1, const v
FV3_Divide(&slope->normal, m);
// Get direction vector
m = FixedHypot(slope->normal.x, slope->normal.y);
m = GetDistance2D(0, 0, slope->normal.x, slope->normal.y);
slope->d.x = -FixedDiv(slope->normal.x, m);
slope->d.y = -FixedDiv(slope->normal.y, m);
......@@ -151,7 +153,7 @@ static void ReconfigureViaConstants (pslope_t *slope, const double pa, const dou
FV3_Negate(normal);
// Get direction vector
m = FixedHypot(normal->x, normal->y);
m = GetDistance2D(0, 0, normal->x, normal->y);
slope->d.x = -FixedDiv(normal->x, m);
slope->d.y = -FixedDiv(normal->y, m);
......@@ -180,7 +182,7 @@ void T_DynamicSlopeLine (dynlineplanethink_t* th)
pslope_t* slope = th->slope;
line_t* srcline = th->sourceline;
fixed_t zdelta;
fixed_t zdelta, oldoz = slope->o.z;
switch(th->type) {
case DP_FRONTFLOOR:
......@@ -207,11 +209,14 @@ void T_DynamicSlopeLine (dynlineplanethink_t* th)
return;
}
if (slope->zdelta != FixedDiv(zdelta, th->extent)) {
if (slope->zdelta != FixedDiv(zdelta, th->extent) || oldoz != slope->o.z) {
slope->zdelta = FixedDiv(zdelta, th->extent);
slope->zangle = R_PointToAngle2(0, 0, th->extent, -zdelta);
slope->moved = true;
P_CalculateSlopeNormal(slope);
P_UpdateMidtextureSlopesForSector(srcline->frontsector);
if (srcline->backsector)
P_UpdateMidtextureSlopesForSector(srcline->backsector);
}
}
......@@ -232,12 +237,18 @@ void T_DynamicSlopeVert (dynvertexplanethink_t* th)
}
ReconfigureViaVertexes(th->slope, th->vex[0], th->vex[1], th->vex[2]);
for (i = 0; i < 3; i++)
{
if (th->secs[i])
P_UpdateMidtextureSlopesForSector(th->secs[i]);
}
}
static inline void P_AddDynLineSlopeThinker (pslope_t* slope, dynplanetype_t type, line_t* sourceline, fixed_t extent)
{
dynlineplanethink_t* th = Z_Calloc(sizeof (*th), PU_LEVSPEC, NULL);
th->thinker.function.acp1 = (actionf_p1)T_DynamicSlopeLine;
th->thinker.function = (actionf_p1)T_DynamicSlopeLine;
th->slope = slope;
th->type = type;
th->sourceline = sourceline;
......@@ -253,7 +264,7 @@ static inline void P_AddDynVertexSlopeThinker (pslope_t* slope, const INT16 tags
dynvertexplanethink_t* th = Z_Calloc(sizeof (*th), PU_LEVSPEC, NULL);
size_t i;
INT32 l;
th->thinker.function.acp1 = (actionf_p1)T_DynamicSlopeVert;
th->thinker.function = (actionf_p1)T_DynamicSlopeVert;
th->slope = slope;
for (i = 0; i < 3; i++) {
......@@ -319,13 +330,13 @@ static fixed_t GetExtent(sector_t *sector, line_t *line)
continue;
P_ClosestPointOnLine(li->v1->x, li->v1->y, line, &tempv);
dist = R_PointToDist2(tempv.x, tempv.y, li->v1->x, li->v1->y);
dist = GetDistance2D(tempv.x, tempv.y, li->v1->x, li->v1->y);
if(dist > fardist)
fardist = dist;
// Okay, maybe do it for v2 as well?
P_ClosestPointOnLine(li->v2->x, li->v2->y, line, &tempv);
dist = R_PointToDist2(tempv.x, tempv.y, li->v2->x, li->v2->y);
dist = GetDistance2D(tempv.x, tempv.y, li->v2->x, li->v2->y);
if(dist > fardist)
fardist = dist;
}
......@@ -389,7 +400,7 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker)
}
{
fixed_t len = R_PointToDist2(0, 0, line->dx, line->dy);
fixed_t len = GetDistance2D(0, 0, line->dx, line->dy);
nx = FixedDiv(line->dy, len);
ny = -FixedDiv(line->dx, len);
}
......@@ -758,6 +769,111 @@ pslope_t *P_MakeSlopeViaEquationConstants(const double a, const double b, const
return ret;
}
static pslope_t *P_GetReferenceSlopeForMidtexture(line_t *line)
{
if (line->flags & ML_MIDPEG)
{
// Line has ML_MIDPEG, so use the floor slope
fixed_t frontheight = P_GetSectorFloorZAt(line->frontsector, line->v1->x, line->v1->y);
fixed_t backheight = P_GetSectorFloorZAt(line->backsector, line->v1->x, line->v1->y);
if (frontheight > backheight)
{
return line->frontsector->f_slope;
}
else
{
return line->backsector->f_slope;
}
}
else
{
// Line does not have ML_MIDPEG, so use the ceiling slope
fixed_t frontheight = P_GetSectorCeilingZAt(line->frontsector, line->v1->x, line->v1->y);
fixed_t backheight = P_GetSectorCeilingZAt(line->backsector, line->v1->x, line->v1->y);
if (frontheight < backheight)
{
return line->frontsector->c_slope;
}
else
{
return line->backsector->c_slope;
}
}
return NULL;
}
// Updates a slope for a solid midtexture based on the slope of the sector it's in.
static void P_UpdateSolidMidtextureSlope(line_t *line, pslope_t *ref)
{
pslope_t *slope = line->midtexslope;
if (ref == NULL)
return;
// Set origin
vector3_t origin;
origin.x = line->v1->x;
origin.y = line->v1->y;
origin.z = P_GetSlopeZAt(ref, origin.x, origin.y);
FV3_Copy(&slope->o, &origin);
// Get where the line ends
vector3_t point;
point.x = line->v2->x;
point.y = line->v2->y;
point.z = P_GetSlopeZAt(ref, point.x, point.y);
// Get length of the line
fixed_t extent = GetDistance2D(0, 0, line->dx, line->dy);
// Precalculate variables
slope->zdelta = FixedDiv(origin.z - point.z, extent);
slope->zangle = R_PointToAngle2(0, origin.z, extent, point.z);
slope->xydirection = line->angle;
// Precalculate the direction
vector2_t dir;
dir.x = FixedMul(FINECOSINE(slope->zangle >> ANGLETOFINESHIFT), FINECOSINE((slope->xydirection+ANGLE_180) >> ANGLETOFINESHIFT));
dir.y = FixedMul(FINECOSINE(slope->zangle >> ANGLETOFINESHIFT), FINESINE((slope->xydirection+ANGLE_180) >> ANGLETOFINESHIFT));
FV2_Copy(&slope->d, &dir);
P_CalculateSlopeNormal(slope);
// Calling P_CalculateSlopeVectors is not necessary.
slope->moved = true;
}
// Goes through every line in the sector and updates the midtexture slope if it is present
static void P_UpdateMidtextureSlopesForSector(sector_t *sector)
{
for (size_t i = 0; i < sector->linecount; i++)
{
if (sector->lines[i]->midtexslope != NULL)
P_UpdateSolidMidtextureSlope(sector->lines[i], P_GetReferenceSlopeForMidtexture(sector->lines[i]));
}
}
// Creates a solid midtexture slope for the line if possible
static void P_CreateSolidMidtextureSlope(line_t *line)
{
if (line->backsector == NULL) // Ignore single-sided lines (of course)
return;
if ((line->flags & ML_MIDSOLID) == 0) // Ignore if the midtexture is not solid
return;
pslope_t *ref = P_GetReferenceSlopeForMidtexture(line);
if (ref)
{
line->midtexslope = Slope_Add(ref->flags & SL_NOPHYSICS);
P_UpdateSolidMidtextureSlope(line, ref);
}
}
/// Initializes and reads the slopes from the map data.
void P_SpawnSlopes(const boolean fromsave) {
size_t i;
......@@ -785,14 +901,21 @@ void P_SpawnSlopes(const boolean fromsave) {
/// Copies slopes from tagged sectors via line specials.
/// \note Doesn't actually copy, but instead they share the same pointers.
// Also, creates midtexture slopes.
for (i = 0; i < numlines; i++)
switch (lines[i].special)
{
line_t *line = &lines[i];
switch (line->special)
{
case 720:
P_CopySectorSlope(&lines[i]);
P_CopySectorSlope(line);
default:
break;
}
P_CreateSolidMidtextureSlope(line);
}
}
/// Initializes slopes.
......@@ -810,10 +933,10 @@ void P_InitSlopes(void)
// Returns the height of the sloped plane at (x, y) as a fixed_t
fixed_t P_GetSlopeZAt(const pslope_t *slope, fixed_t x, fixed_t y)
{
fixed_t dist = FixedMul(x - slope->o.x, slope->d.x) +
FixedMul(y - slope->o.y, slope->d.y);
fixed_t dist = FixedMul(x - slope->o.x, slope->d.x) / 2 +
FixedMul(y - slope->o.y, slope->d.y) / 2;
return slope->o.z + FixedMul(dist, slope->zdelta);
return slope->o.z + FixedMul(dist, slope->zdelta) * 2;
}
// Like P_GetSlopeZAt but falls back to z if slope is NULL
......@@ -923,15 +1046,37 @@ fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope)
{
vector3_t slopemom, axis;
angle_t ang;
angle_t advanceAng = ANG15;
const boolean upwards = (slope->zangle < ANGLE_180);
if (slope->flags & SL_NOPHYSICS)
return 0;
// If there's physics, time for launching.
// Doesn't kill the vertical momentum as much as P_SlopeLaunch does.
ang = slope->zangle + ANG15*((slope->zangle > 0) ? 1 : -1);
if (ang > ANGLE_90 && ang < ANGLE_180)
ang = ((slope->zangle > 0) ? ANGLE_90 : InvAngle(ANGLE_90)); // hard cap of directly upwards
ang = slope->zangle;
// for the time being, let's pretend the slope inclines upwards only
if (!upwards)
{
ang += ANGLE_180;
}
// angles past 90 degrees need to shrink to get closer to 90 degrees
if (ang > ANGLE_90)
{
advanceAng = InvAngle(advanceAng);
}
// now we set the actual final angle
if ((ang > ANGLE_90) != (ang + advanceAng > ANGLE_90)) // does advancing the angle push it past directly upwards?
{
ang = (upwards ? ANGLE_90 : InvAngle(ANGLE_90)); // hard cap of directly upwards
}
else
{
ang = slope->zangle + advanceAng;
}
slopemom.x = mo->momx;
slopemom.y = mo->momy;
......
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2009 by Stephen McGranahan.
// Copyright (C) 2015-2023 by Sonic Team Junior.
// Copyright (C) 2015-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -135,22 +135,24 @@ void P_ParseAnimationDefintion(SINT8 istexture);
static boolean P_FindTextureForAnimation(anim_t *anim, animdef_t *animdef)
{
if (R_CheckTextureNumForName(animdef->startname) == -1)
INT32 start = R_CheckTextureNumForName(animdef->startname, TEXTURETYPE_TEXTURE);
if (start == -1)
return false;
anim->picnum = R_TextureNumForName(animdef->endname);
anim->basepic = R_TextureNumForName(animdef->startname);
anim->basepic = start;
anim->picnum = R_CheckTextureNumForName(animdef->endname, TEXTURETYPE_TEXTURE);
return true;
}
static boolean P_FindFlatForAnimation(anim_t *anim, animdef_t *animdef)
{
if (R_CheckFlatNumForName(animdef->startname) == -1)
INT32 start = R_CheckTextureNumForName(animdef->startname, TEXTURETYPE_FLAT);
if (start == -1)
return false;
anim->picnum = R_CheckFlatNumForName(animdef->endname);
anim->basepic = R_CheckFlatNumForName(animdef->startname);
anim->basepic = start;
anim->picnum = R_CheckTextureNumForName(animdef->endname, TEXTURETYPE_FLAT);
return true;
}
......@@ -1042,7 +1044,7 @@ static boolean PolyFade(line_t *line)
// Prevent continuous execs from interfering on an existing fade
if (!(line->args[3] & TMPF_OVERRIDE)
&& po->thinker
&& po->thinker->function.acp1 == (actionf_p1)T_PolyObjFade)
&& po->thinker->function == (actionf_p1)T_PolyObjFade)
{
CONS_Debug(DBG_POLYOBJ, "Line type 492 Executor: Fade PolyObject thinker already exists\n");
return 0;
......@@ -1115,7 +1117,7 @@ static boolean PolyFlag(line_t *line)
static boolean PolyDisplace(line_t *line)
{
polydisplacedata_t pdd;
fixed_t length = R_PointToDist2(line->v2->x, line->v2->y, line->v1->x, line->v1->y);
fixed_t length = GetDistance2D(line->v2->x, line->v2->y, line->v1->x, line->v1->y);
fixed_t speed = line->args[1] << FRACBITS;
pdd.polyObjNum = line->args[0];
......@@ -1273,7 +1275,7 @@ static void P_AddExecutorDelay(line_t *line, mobj_t *mobj, sector_t *sector)
e = Z_Calloc(sizeof (*e), PU_LEVSPEC, NULL);
e->thinker.function.acp1 = (actionf_p1)T_ExecutorDelay;
e->thinker.function = (actionf_p1)T_ExecutorDelay;
e->line = line;
e->sector = sector;
e->timer = delay;
......@@ -1364,7 +1366,7 @@ static boolean P_CheckNightsTriggerLine(line_t *triggerline, mobj_t *actor)
for (i = 0; i < MAXPLAYERS; i++)
{
UINT8 lap;
if (!playeringame[i] || players[i].spectator)
if (!players[i].ingame || players[i].spectator)
continue;
// denightserize: run only if all players are not nights
......@@ -1488,7 +1490,7 @@ static boolean P_CheckPlayerRings(line_t *triggerline, mobj_t *actor)
{
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
if (!players[i].ingame || players[i].spectator)
continue;
if (!players[i].mo || ((maptol & TOL_NIGHTS) ? players[i].spheres : players[i].rings) <= 0)
......@@ -1970,23 +1972,23 @@ static void P_PlaySFX(INT32 sfxnum, mobj_t *mo, sector_t *callsec, INT16 tag, te
{
case TMSS_TRIGGERMOBJ: // play the sound from mobj that triggered it
if (mo)
S_StartSound(mo, sfxnum);
S_StartSoundFromMobj(mo, sfxnum);
break;
case TMSS_TRIGGERSECTOR: // play the sound from calling sector's soundorg
if (callsec)
S_StartSound(&callsec->soundorg, sfxnum);
S_StartSoundFromSector(callsec, sfxnum);
else if (mo)
S_StartSound(&mo->subsector->sector->soundorg, sfxnum);
S_StartSoundFromSector(mo->subsector->sector, sfxnum);
break;
case TMSS_NOWHERE: // play the sound from nowhere
S_StartSound(NULL, sfxnum);
S_StartSoundFromEverywhere(sfxnum);
break;
case TMSS_TAGGEDSECTOR: // play the sound from tagged sectors' soundorgs
{
INT32 secnum;
TAG_ITER_SECTORS(tag, secnum)
S_StartSound(&sectors[secnum].soundorg, sfxnum);
S_StartSoundFromSector(&sectors[secnum], sfxnum);
break;
}
default:
......@@ -2033,7 +2035,7 @@ void P_SwitchWeather(INT32 weathernum)
for (think = thlist[THINK_PRECIP].next; think != &thlist[THINK_PRECIP]; think = think->next)
{
if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker)
if (think->function != (actionf_p1)P_NullPrecipThinker)
continue; // not a precipmobj thinker
precipmobj = (precipmobj_t *)think;
......@@ -2049,7 +2051,7 @@ void P_SwitchWeather(INT32 weathernum)
for (think = thlist[THINK_PRECIP].next; think != &thlist[THINK_PRECIP]; think = think->next)
{
if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker)
if (think->function != (actionf_p1)P_NullPrecipThinker)
continue; // not a precipmobj thinker
precipmobj = (precipmobj_t *)think;
......@@ -2066,7 +2068,7 @@ void P_SwitchWeather(INT32 weathernum)
precipmobj->precipflags &= ~PCF_INVISIBLE;
precipmobj->precipflags |= PCF_RAIN;
//think->function.acp1 = (actionf_p1)P_RainThinker;
//think->function = (actionf_p1)P_RainThinker;
}
else if (weathernum == PRECIP_SNOW) // Rain To Snow
{
......@@ -2091,11 +2093,11 @@ void P_SwitchWeather(INT32 weathernum)
precipmobj->precipflags &= ~(PCF_INVISIBLE|PCF_RAIN);
//think->function.acp1 = (actionf_p1)P_SnowThinker;
//think->function = (actionf_p1)P_SnowThinker;
}
else // Remove precip, but keep it around for reuse.
{
//think->function.acp1 = (actionf_p1)P_NullPrecipThinker;
//think->function = (actionf_p1)P_NullPrecipThinker;
precipmobj->precipflags |= PCF_INVISIBLE;
}
......@@ -2405,11 +2407,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
y = line->args[3] << FRACBITS;
z = line->args[4] << FRACBITS;
P_UnsetThingPosition(mo);
mo->x += x;
mo->y += y;
mo->z += z;
P_SetThingPosition(mo);
P_SetOrigin(mo, mo->x + x, mo->y + y, mo->z + z);
if (mo->player)
{
......@@ -2417,6 +2415,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
P_SetOrigin(bot, bot->x + x, bot->y + y, bot->z + z);
if (splitscreen && mo->player == &players[secondarydisplayplayer] && camera2.chase)
{
camera2.reset = true;
camera2.x += x;
camera2.y += y;
camera2.z += z;
......@@ -2424,6 +2423,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
}
else if (camera.chase && mo->player == &players[displayplayer])
{
camera.reset = true;
camera.x += x;
camera.y += y;
camera.z += z;
......@@ -2448,7 +2448,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
P_Teleport(bot, dest->x, dest->y, dest->z, angle, !silent, keepmomentum);
P_Teleport(mo, dest->x, dest->y, dest->z, angle, !silent, keepmomentum);
if (!silent)
S_StartSound(dest, sfx_mixup); // Play the 'bowrwoosh!' sound
S_StartSoundFromMobj(dest, sfx_mixup); // Play the 'bowrwoosh!' sound
}
}
break;
......@@ -2548,7 +2548,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
char *text = Z_Malloc(len + 1, PU_CACHE, NULL);
memcpy(text, lump, len);
text[len] = '\0';
COM_BufInsertText(text);
COM_BufInsertTextEx(text, COM_LUA);
Z_Free(text);
}
}
......@@ -2754,14 +2754,14 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
scroll_t *scroller;
thinker_t *th;
fixed_t length = R_PointToDist2(line->v2->x, line->v2->y, line->v1->x, line->v1->y);
fixed_t length = GetDistance2D(line->v2->x, line->v2->y, line->v1->x, line->v1->y);
fixed_t speed = line->args[1] << FRACBITS;
fixed_t dx = FixedMul(FixedMul(FixedDiv(line->dx, length), speed) >> SCROLL_SHIFT, CARRYFACTOR);
fixed_t dy = FixedMul(FixedMul(FixedDiv(line->dy, length), speed) >> SCROLL_SHIFT, CARRYFACTOR);
for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)T_Scroll)
if (th->function != (actionf_p1)T_Scroll)
continue;
scroller = (scroll_t *)th;
......@@ -2893,7 +2893,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (M_UpdateUnlockablesAndExtraEmblems(clientGamedata))
{
S_StartSound(NULL, sfx_s3k68);
S_StartSoundFromEverywhere(sfx_s3k68);
G_SaveGameData(clientGamedata); // only save if unlocked something
}
}
......@@ -3603,7 +3603,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
UINT8 i;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
if (!players[i].ingame)
continue;
P_DoPlayerExit(&players[i], true);
}
......@@ -3644,7 +3644,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (mo2->type != MT_EGGTRAP)
continue;
if (mo2->thinker.function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (mo2->thinker.removing)
continue;
P_KillMobj(mo2, NULL, mo, 0);
......@@ -3657,7 +3657,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
// Mark all players with the time to exit thingy!
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
if (!players[i].ingame)
continue;
P_DoPlayerExit(&players[i], true);
}
......@@ -3684,7 +3684,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
case 466: // Set level failure state
{
if (line->args[1])
if (line->args[0])
{
stagefailed = false;
CONS_Debug(DBG_GAMELOGIC, "Stage can be completed successfully!\n");
......@@ -3844,7 +3844,7 @@ void P_SetupSignExit(player_t *player)
P_SetObjectMomZ(thing, 12*FRACUNIT, false);
P_SetMobjState(thing, S_SIGNSPIN1);
if (thing->info->seesound)
S_StartSound(thing, thing->info->seesound);
S_StartSoundFromMobj(thing, thing->info->seesound);
++numfound;
}
......@@ -3856,7 +3856,7 @@ void P_SetupSignExit(player_t *player)
// spin all signposts in the level then.
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (think->removing)
continue;
thing = (mobj_t *)think;
......@@ -3875,7 +3875,7 @@ void P_SetupSignExit(player_t *player)
P_SetObjectMomZ(thing, 12*FRACUNIT, false);
P_SetMobjState(thing, S_SIGNSPIN1);
if (thing->info->seesound)
S_StartSound(thing, thing->info->seesound);
S_StartSoundFromMobj(thing, thing->info->seesound);
++numfound;
}
......@@ -3894,7 +3894,7 @@ boolean P_IsFlagAtBase(mobjtype_t flag)
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (think->removing)
continue;
mo = (mobj_t *)think;
......@@ -4345,7 +4345,7 @@ sector_t *P_FindPlayerTrigger(player_t *player, line_t *sourceline)
boolean P_IsPlayerValid(size_t playernum)
{
if (!playeringame[playernum])
if (!players[playernum].ingame)
return false;
if (!players[playernum].mo)
......@@ -4397,7 +4397,7 @@ static void P_ProcessEggCapsule(player_t *player, sector_t *sector)
// The chimps are my friends.. heeheeheheehehee..... - LouisJM
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
mo2 = (mobj_t *)th;
if (mo2->type != MT_EGGTRAP)
......@@ -4419,7 +4419,7 @@ static void P_ProcessEggCapsule(player_t *player, sector_t *sector)
// Mark all players with the time to exit thingy!
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
if (!players[i].ingame)
continue;
P_DoPlayerExit(&players[i], true);
}
......@@ -4511,7 +4511,7 @@ static void P_ProcessSpeedPad(player_t *player, sector_t *sector, sector_t *rove
if (!sfxnum)
sfxnum = sfx_spdpad;
S_StartSound(player->mo, sfxnum);
S_StartSoundFromMobj(player->mo, sfxnum);
}
static void P_ProcessSpecialStagePit(player_t* player)
......@@ -4575,6 +4575,10 @@ static void P_ProcessExitSector(player_t *player, mtag_t sectag)
if (lines[lineindex].args[1] & TMEF_SKIPTALLY)
skipstats = 1;
//skip stats actually skips post-level cutscenes.
if (lines[lineindex].args[1] & TMEF_KEEPCUTSCENE)
keepcutscene = true;
}
static void P_ProcessTeamBase(player_t *player, boolean redteam)
......@@ -4603,9 +4607,9 @@ static void P_ProcessTeamBase(player_t *player, boolean redteam)
HU_DoCEcho(va(M_GetText("%s%s\200\\CAPTURED THE %s%s FLAG\200.\\\\\\\\"), redteam ? "\205" : "\204", player_names[player-players], redteam ? "\204" : "\205", redteam ? "BLUE" : "RED"));
if (splitscreen || players[consoleplayer].ctfteam == (redteam ? 1 : 2))
S_StartSound(NULL, sfx_flgcap);
S_StartSoundFromEverywhere(sfx_flgcap);
else if (players[consoleplayer].ctfteam == (redteam ? 2 : 1))
S_StartSound(NULL, sfx_lose);
S_StartSoundFromEverywhere(sfx_lose);
mo = P_SpawnMobj(player->mo->x,player->mo->y,player->mo->z, redteam ? MT_BLUEFLAG : MT_REDFLAG);
player->gotflag &= ~(redteam ? GF_BLUEFLAG : GF_REDFLAG);
......@@ -4677,10 +4681,10 @@ static void P_ProcessZoomTube(player_t *player, mtag_t sectag, boolean end)
player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_BOUNCING|PF_SLIDING|PF_CANCARRY);
player->climbing = 0;
if (player->mo->state-states != S_PLAY_ROLL)
if (!P_IsPlayerInState(player, S_PLAY_ROLL))
{
P_SetMobjState(player->mo, S_PLAY_ROLL);
S_StartSound(player->mo, sfx_spin);
S_StartSoundFromMobj(player->mo, sfx_spin);
}
}
......@@ -4712,13 +4716,13 @@ static void P_ProcessFinishLine(player_t *player)
P_ResetStarposts();
// Play the starpost sound for 'consistency'
S_StartSound(player->mo, sfx_strpst);
S_StartSoundFromMobj(player->mo, sfx_strpst);
}
else if (player->starpostnum)
{
// blatant reuse of a variable that's normally unused in circuit
if (!player->tossdelay)
S_StartSound(player->mo, sfx_lose);
S_StartSoundFromMobj(player->mo, sfx_lose);
player->tossdelay = 3;
}
......@@ -4758,7 +4762,7 @@ static void P_ProcessRopeHang(player_t *player, mtag_t sectag)
if (player->cmd.buttons & BT_SPIN)
return;
if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate])
if (!(player->pflags & PF_SLIDING) && P_IsPlayerInState(player, S_PLAY_PAIN))
return;
if (player->exiting)
......@@ -4864,9 +4868,8 @@ static void P_ProcessRopeHang(player_t *player, mtag_t sectag)
}
else
{
if (P_AproxDistance(P_AproxDistance(player->mo->x-resultlow.x, player->mo->y-resultlow.y),
player->mo->z-resultlow.z) < P_AproxDistance(P_AproxDistance(player->mo->x-resulthigh.x,
player->mo->y-resulthigh.y), player->mo->z-resulthigh.z))
if (GetDistance3D(player->mo->x, player->mo->y, player->mo->z, resultlow.x, resultlow.y, resultlow.z) <
GetDistance3D(player->mo->x, player->mo->y, player->mo->z, resulthigh.x, resulthigh.y, resulthigh.z))
{
// Line between Mid and Low is closer
closest = waypointmid;
......@@ -4888,7 +4891,7 @@ static void P_ProcessRopeHang(player_t *player, mtag_t sectag)
player->powers[pw_carry] = CR_ROPEHANG;
player->speed = speed;
S_StartSound(player->mo, sfx_s3k4a);
S_StartSoundFromMobj(player->mo, sfx_s3k4a);
player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_GLIDING|PF_BOUNCING|PF_SLIDING|PF_CANCARRY);
player->climbing = 0;
......@@ -5073,7 +5076,7 @@ static void P_EvaluateOldSectorSpecial(player_t *player, sector_t *sector, secto
if (leveltime % (TICRATE/2) == 0 && player->rings > 0)
{
player->rings--;
S_StartSound(player->mo, sfx_antiri);
S_StartSoundFromMobj(player->mo, sfx_antiri);
}
break;
}
......@@ -5563,7 +5566,7 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, I
break;
// Should this FOF have friction?
if(th->function.acp1 == (actionf_p1)T_Friction)
if(th->function == (actionf_p1)T_Friction)
{
f = (friction_t *)th;
......@@ -5571,7 +5574,7 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, I
Add_Friction(f->friction, f->movefactor, (INT32)(sec-sectors), f->affectee);
}
// Should this FOF have wind/current/pusher?
else if(th->function.acp1 == (actionf_p1)T_Pusher)
else if(th->function == (actionf_p1)T_Pusher)
{
p = (pusher_t *)th;
......@@ -5658,7 +5661,7 @@ static void P_AddFloatThinker(sector_t *sec, UINT16 tag, line_t *sourceline)
floater = Z_Calloc(sizeof (*floater), PU_LEVSPEC, NULL);
P_AddThinker(THINK_MAIN, &floater->thinker);
floater->thinker.function.acp1 = (actionf_p1)T_FloatSector;
floater->thinker.function = (actionf_p1)T_FloatSector;
floater->sector = sec;
floater->tag = (INT16)tag;
......@@ -5689,7 +5692,7 @@ static void P_AddPlaneDisplaceThinker(INT32 type, fixed_t speed, INT32 control,
displace = Z_Calloc(sizeof (*displace), PU_LEVSPEC, NULL);
P_AddThinker(THINK_MAIN, &displace->thinker);
displace->thinker.function.acp1 = (actionf_p1)T_PlaneDisplace;
displace->thinker.function = (actionf_p1)T_PlaneDisplace;
displace->affectee = affectee;
displace->control = control;
displace->last_height = sectors[control].floorheight;
......@@ -5719,7 +5722,7 @@ static void P_AddBlockThinker(sector_t *sec, line_t *sourceline)
block = Z_Calloc(sizeof (*block), PU_LEVSPEC, NULL);
P_AddThinker(THINK_MAIN, &block->thinker);
block->thinker.function.acp1 = (actionf_p1)T_MarioBlockChecker;
block->thinker.function = (actionf_p1)T_MarioBlockChecker;
block->sourceline = sourceline;
block->sector = sec;
......@@ -5744,7 +5747,7 @@ static void P_AddRaiseThinker(sector_t *sec, INT16 tag, fixed_t speed, fixed_t c
raise = Z_Calloc(sizeof (*raise), PU_LEVSPEC, NULL);
P_AddThinker(THINK_MAIN, &raise->thinker);
raise->thinker.function.acp1 = (actionf_p1)T_RaiseSector;
raise->thinker.function = (actionf_p1)T_RaiseSector;
raise->tag = tag;
raise->sector = sec;
......@@ -5771,7 +5774,7 @@ static void P_AddAirbob(sector_t *sec, INT16 tag, fixed_t dist, boolean raise, b
airbob = Z_Calloc(sizeof (*airbob), PU_LEVSPEC, NULL);
P_AddThinker(THINK_MAIN, &airbob->thinker);
airbob->thinker.function.acp1 = (actionf_p1)T_RaiseSector;
airbob->thinker.function = (actionf_p1)T_RaiseSector;
airbob->tag = tag;
airbob->sector = sec;
......@@ -5813,7 +5816,7 @@ static inline void P_AddThwompThinker(sector_t *sec, line_t *sourceline, fixed_t
thwomp = Z_Calloc(sizeof (*thwomp), PU_LEVSPEC, NULL);
P_AddThinker(THINK_MAIN, &thwomp->thinker);
thwomp->thinker.function.acp1 = (actionf_p1)T_ThwompSector;
thwomp->thinker.function = (actionf_p1)T_ThwompSector;
// set up the fields according to the type of elevator action
thwomp->sourceline = sourceline;
......@@ -5852,7 +5855,7 @@ static inline void P_AddNoEnemiesThinker(line_t *sourceline)
nobaddies = Z_Calloc(sizeof (*nobaddies), PU_LEVSPEC, NULL);
P_AddThinker(THINK_MAIN, &nobaddies->thinker);
nobaddies->thinker.function.acp1 = (actionf_p1)T_NoEnemiesSector;
nobaddies->thinker.function = (actionf_p1)T_NoEnemiesSector;
nobaddies->sourceline = sourceline;
}
......@@ -5872,7 +5875,7 @@ static void P_AddEachTimeThinker(line_t *sourceline, boolean triggerOnExit)
eachtime = Z_Calloc(sizeof (*eachtime), PU_LEVSPEC, NULL);
P_AddThinker(THINK_MAIN, &eachtime->thinker);
eachtime->thinker.function.acp1 = (actionf_p1)T_EachTimeThinker;
eachtime->thinker.function = (actionf_p1)T_EachTimeThinker;
eachtime->sourceline = sourceline;
eachtime->triggerOnExit = triggerOnExit;
......@@ -5894,7 +5897,7 @@ static inline void P_AddCameraScanner(sector_t *sourcesec, sector_t *actionsecto
elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL);
P_AddThinker(THINK_MAIN, &elevator->thinker);
elevator->thinker.function.acp1 = (actionf_p1)T_CameraScanner;
elevator->thinker.function = (actionf_p1)T_CameraScanner;
elevator->type = elevateBounce;
// set up the fields according to the type of elevator action
......@@ -5940,7 +5943,7 @@ void T_LaserFlash(laserthink_t *flash)
top = P_GetFFloorTopZAt (fflr, sector->soundorg.x, sector->soundorg.y);
bottom = P_GetFFloorBottomZAt(fflr, sector->soundorg.x, sector->soundorg.y);
sector->soundorg.z = (top + bottom)/2;
S_StartSound(&sector->soundorg, sfx_laser);
S_StartSoundFromSector(sector, sfx_laser);
// Seek out objects to DESTROY! MUAHAHHAHAHAA!!!*cough*
for (node = sector->touching_thinglist; node && node->m_thing; node = node->m_thinglist_next)
......@@ -5978,7 +5981,7 @@ static inline void P_AddLaserThinker(INT16 tag, line_t *line, boolean nobosses)
P_AddThinker(THINK_MAIN, &flash->thinker);
flash->thinker.function.acp1 = (actionf_p1)T_LaserFlash;
flash->thinker.function = (actionf_p1)T_LaserFlash;
flash->tag = tag;
flash->sourceline = line;
flash->nobosses = nobosses;
......@@ -6238,7 +6241,7 @@ static void P_DoPortalCopyFromLine(sector_t *dest_sector, int plane_type, int ta
}
}
static sectorportal_t *P_SectorGetPortalOrCreate(sector_t *sector, UINT32 *num, UINT32 *result)
static sectorportal_t *P_SectorGetPortalOrCreate(sector_t *sector, UINT32 *num, UINT32 *result, boolean ceiling)
{
sectorportal_t *secportal = NULL;
......@@ -6246,8 +6249,8 @@ static sectorportal_t *P_SectorGetPortalOrCreate(sector_t *sector, UINT32 *num,
{
*num = P_NewSectorPortal();
secportal = &secportals[*num];
secportal->origin.x = sector->soundorg.x;
secportal->origin.y = sector->soundorg.y;
secportal->target = sector;
secportal->ceiling = ceiling;
*result = *num;
}
else
......@@ -6261,12 +6264,12 @@ static sectorportal_t *P_SectorGetPortalOrCreate(sector_t *sector, UINT32 *num,
static sectorportal_t *P_SectorGetFloorPortalOrCreate(sector_t *sector, UINT32 *result)
{
return P_SectorGetPortalOrCreate(sector, &sector->portal_floor, result);
return P_SectorGetPortalOrCreate(sector, &sector->portal_floor, result, false);
}
static sectorportal_t *P_SectorGetCeilingPortalOrCreate(sector_t *sector, UINT32 *result)
{
return P_SectorGetPortalOrCreate(sector, &sector->portal_ceiling, result);
return P_SectorGetPortalOrCreate(sector, &sector->portal_ceiling, result, true);
}
static void P_CopySectorPortalToLines(UINT32 portal_num, int sector_tag)
......@@ -6379,9 +6382,9 @@ void P_SpawnSpecials(boolean fromnetsave)
// Firstly, find out how many there are in each sector
for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)T_Friction)
if (th->function == (actionf_p1)T_Friction)
secthinkers[((friction_t *)th)->affectee].count++;
else if (th->function.acp1 == (actionf_p1)T_Pusher)
else if (th->function == (actionf_p1)T_Pusher)
secthinkers[((pusher_t *)th)->affectee].count++;
}
......@@ -6399,9 +6402,9 @@ void P_SpawnSpecials(boolean fromnetsave)
{
size_t secnum = (size_t)-1;
if (th->function.acp1 == (actionf_p1)T_Friction)
if (th->function == (actionf_p1)T_Friction)
secnum = ((friction_t *)th)->affectee;
else if (th->function.acp1 == (actionf_p1)T_Pusher)
else if (th->function == (actionf_p1)T_Pusher)
secnum = ((pusher_t *)th)->affectee;
if (secnum != (size_t)-1)
......@@ -7763,7 +7766,7 @@ static boolean IsSector3DBlock(sector_t* sec)
static void Add_Scroller(INT32 type, fixed_t dx, fixed_t dy, INT32 control, INT32 affectee, INT32 accel, INT32 exclusive)
{
scroll_t *s = Z_Calloc(sizeof *s, PU_LEVSPEC, NULL);
s->thinker.function.acp1 = (actionf_p1)T_Scroll;
s->thinker.function = (actionf_p1)T_Scroll;
s->type = type;
s->dx = dx;
s->dy = dy;
......@@ -7850,7 +7853,7 @@ static void P_SpawnScrollers(void)
case 510: // plane scroller
{
fixed_t length = R_PointToDist2(l->v2->x, l->v2->y, l->v1->x, l->v1->y);
fixed_t length = GetDistance2D(l->v2->x, l->v2->y, l->v1->x, l->v1->y);
fixed_t speed = l->args[3] << FRACBITS;
fixed_t dx = FixedMul(FixedDiv(l->dx, length), speed) >> SCROLL_SHIFT;
fixed_t dy = FixedMul(FixedDiv(l->dy, length), speed) >> SCROLL_SHIFT;
......@@ -7905,7 +7908,7 @@ static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t o
{
disappear_t *d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL);
d->thinker.function.acp1 = (actionf_p1)T_Disappear;
d->thinker.function = (actionf_p1)T_Disappear;
d->appeartime = appeartime;
d->disappeartime = disappeartime;
d->offset = offset;
......@@ -7952,7 +7955,7 @@ void T_Disappear(disappear_t *d)
if (!(lines[d->sourceline].args[5]))
{
sectors[s].soundorg.z = P_GetFFloorTopZAt(rover, sectors[s].soundorg.x, sectors[s].soundorg.y);
S_StartSound(&sectors[s].soundorg, sfx_appear);
S_StartSoundFromSector(&sectors[s], sfx_appear);
}
}
}
......@@ -8298,7 +8301,7 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor
d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL);
d->thinker.function.acp1 = (actionf_p1)T_Fade;
d->thinker.function = (actionf_p1)T_Fade;
d->rover = rover;
d->sectornum = (UINT32)sectornum;
d->ffloornum = (UINT32)ffloornum;
......@@ -8450,7 +8453,7 @@ static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, ext
}
d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL);
d->thinker.function.acp1 = (actionf_p1)T_FadeColormap;
d->thinker.function = (actionf_p1)T_FadeColormap;
d->sector = sector;
d->source_exc = source_exc;
d->dest_exc = dest_exc;
......@@ -8574,7 +8577,7 @@ static void Add_Friction(INT32 friction, INT32 movefactor, INT32 affectee, INT32
{
friction_t *f = Z_Calloc(sizeof *f, PU_LEVSPEC, NULL);
f->thinker.function.acp1 = (actionf_p1)T_Friction;
f->thinker.function = (actionf_p1)T_Friction;
f->friction = friction;
f->movefactor = movefactor;
f->affectee = affectee;
......@@ -8712,7 +8715,7 @@ static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, fixed_t
{
pusher_t *p = Z_Calloc(sizeof *p, PU_LEVSPEC, NULL);
p->thinker.function.acp1 = (actionf_p1)T_Pusher;
p->thinker.function = (actionf_p1)T_Pusher;
p->type = type;
p->x_mag = x_mag;
p->y_mag = y_mag;
......@@ -8805,7 +8808,7 @@ void T_Pusher(pusher_t *p)
if (thing->player && thing->player->powers[pw_carry] == CR_ROPEHANG)
continue;
if (thing->player && (thing->state == &states[thing->info->painstate]) && (thing->player->powers[pw_flashing] > (flashingtics/4)*3 && thing->player->powers[pw_flashing] <= flashingtics))
if (thing->player && P_IsPlayerInState(thing->player, S_PLAY_PAIN) && (thing->player->powers[pw_flashing] > (flashingtics/4)*3 && thing->player->powers[pw_flashing] <= flashingtics))
continue;
inFOF = touching = moved = false;
......@@ -8883,7 +8886,7 @@ void T_Pusher(pusher_t *p)
// Tumbleweeds bounce a bit...
if (thing->type == MT_LITTLETUMBLEWEED || thing->type == MT_BIGTUMBLEWEED)
thing->momz += P_AproxDistance(xspeed, yspeed) >> 2;
thing->momz += GetDistance2D(0, 0, xspeed, yspeed) / 4;
if (moved)
{
......@@ -8931,7 +8934,7 @@ static void P_SpawnPushers(void)
if (l->special != 541)
continue;
length = R_PointToDist2(l->v2->x, l->v2->y, l->v1->x, l->v1->y);
length = GetDistance2D(l->v2->x, l->v2->y, l->v1->x, l->v1->y);
hspeed = l->args[1] << FRACBITS;
dx = FixedMul(FixedDiv(l->dx, length), hspeed);
dy = FixedMul(FixedDiv(l->dy, length), hspeed);
......
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -130,6 +130,7 @@ typedef enum
{
TMEF_SKIPTALLY = 1,
TMEF_EMERALDCHECK = 1<<1,
TMEF_KEEPCUTSCENE = 1<<2,
} textmapexitflags_t;
typedef enum
......
......@@ -128,7 +128,7 @@ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle
if (!dontstopmove)
thing->momx = thing->momy = thing->momz = 0;
else // Change speed to match direction
P_InstaThrust(thing, angle, FixedHypot(thing->momx, thing->momy));
P_InstaThrust(thing, angle, P_GetMobjMomentum2D(thing));
if (thing->player)
{
......@@ -143,7 +143,7 @@ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle
INT32 p;
// Search for any players you might be carrying, so you can get them off before they end up being taken with you!
for (p = 0; p < MAXPLAYERS; p++)
if (playeringame[p] && players[p].mo && players[p].powers[pw_carry] == CR_PLAYER && players[p].mo->tracer == thing)
if (players[p].ingame && players[p].mo && players[p].powers[pw_carry] == CR_PLAYER && players[p].mo->tracer == thing)
{
players[p].powers[pw_carry] = CR_NONE;
P_SetTarget(&players[p].mo->tracer, NULL);
......
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -124,7 +124,7 @@ void Command_Numthinkers_f(void)
{
for (think = thlist[i].next; think != &thlist[i]; think = think->next)
{
if (think->function.acp1 != action)
if (think->function != action)
continue;
count++;
......@@ -162,7 +162,7 @@ void Command_CountMobjs_f(void)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
if (((mobj_t *)th)->type == i)
......@@ -182,7 +182,7 @@ void Command_CountMobjs_f(void)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
if (((mobj_t *)th)->type == i)
......@@ -228,7 +228,7 @@ void P_AddThinker(const thinklistnum_t n, thinker_t *thinker)
static const char *MobjTypeName(const mobj_t *mobj)
{
mobjtype_t type;
actionf_p1 p1 = mobj->thinker.function.acp1;
actionf_p1 p1 = mobj->thinker.function;
if (p1 == (actionf_p1)P_MobjThinker)
type = mobj->type;
......@@ -247,7 +247,7 @@ static const char *MobjTypeName(const mobj_t *mobj)
static const char *MobjThinkerName(const mobj_t *mobj)
{
actionf_p1 p1 = mobj->thinker.function.acp1;
actionf_p1 p1 = mobj->thinker.function;
if (p1 == (actionf_p1)P_MobjThinker)
{
......@@ -348,7 +348,8 @@ void P_RemoveThinkerDelayed(thinker_t *thinker)
void P_RemoveThinker(thinker_t *thinker)
{
LUA_InvalidateUserdata(thinker);
thinker->function.acp1 = (actionf_p1)P_RemoveThinkerDelayed;
thinker->removing = true;
thinker->function = (actionf_p1)P_RemoveThinkerDelayed;
}
/*
......@@ -436,9 +437,9 @@ static inline void P_RunThinkers(void)
for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = currentthinker->next)
{
#ifdef PARANOIA
I_Assert(currentthinker->function.acp1 != NULL);
I_Assert(currentthinker->function != NULL);
#endif
currentthinker->function.acp1(currentthinker);
currentthinker->function(currentthinker);
}
PS_STOP_TIMING(ps_thlist_times[i]);
}
......@@ -473,7 +474,7 @@ static void P_DoAutobalanceTeams(void)
//We can then pick a random player to be forced to change teams.
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && players[i].ctfteam)
if (players[i].ingame && players[i].ctfteam)
{
if (players[i].ctfteam == 1)
{
......@@ -578,7 +579,7 @@ static inline void P_DoSpecialStageStuff(void)
// Can't drown in a special stage
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
if (!players[i].ingame || players[i].spectator)
continue;
players[i].powers[pw_underwater] = players[i].powers[pw_spacetime] = 0;
......@@ -593,7 +594,7 @@ static inline void P_DoSpecialStageStuff(void)
// Count up the rings of all the players and see if
// they've collected the required amount.
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
if (players[i].ingame)
{
tic_t oldnightstime = players[i].nightstime;
countspheres += players[i].spheres;
......@@ -611,7 +612,7 @@ static inline void P_DoSpecialStageStuff(void)
if (mapheaderinfo[gamemap-1]->levelflags & LF_MIXNIGHTSCOUNTDOWN)
{
S_FadeMusic(0, 10*MUSICRATE);
S_StartSound(NULL, sfx_timeup); // that creepy "out of time" music from NiGHTS.
S_StartSoundFromEverywhere(sfx_timeup); // that creepy "out of time" music from NiGHTS.
}
else
S_ChangeMusicInternal("_drown", false);
......@@ -624,7 +625,7 @@ static inline void P_DoSpecialStageStuff(void)
players[i].pflags &= ~(PF_GLIDING|PF_BOUNCING);
players[i].nightstime = 0;
if (P_IsLocalPlayer(&players[i]))
S_StartSound(NULL, sfx_s3k66);
S_StartSoundFromEverywhere(sfx_s3k66);
}
}
......@@ -634,7 +635,7 @@ static inline void P_DoSpecialStageStuff(void)
{
// Halt all the players
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && !players[i].exiting)
if (players[i].ingame && !players[i].exiting)
{
players[i].mo->momx = players[i].mo->momy = 0;
players[i].exiting = (14*TICRATE)/5 + 1;
......@@ -673,13 +674,13 @@ static inline void P_DoTagStuff(void)
for (i=0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && !players[i].spectator)
if (players[i].ingame && !players[i].spectator)
participants++;
}
for (i=0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && !players[i].spectator && players[i].playerstate == PST_LIVE
if (players[i].ingame && !players[i].spectator && players[i].playerstate == PST_LIVE
&& !(players[i].pflags & (PF_TAGIT|PF_GAMETYPEOVER)))
//points given is the number of participating players divided by two.
P_AddPlayerScore(&players[i], participants/2);
......@@ -717,7 +718,7 @@ void P_Ticker(boolean run)
// Increment jointime even if paused
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
if (players[i].ingame)
players[i].jointime++;
if (objectplacing)
......@@ -726,6 +727,7 @@ void P_Ticker(boolean run)
{
P_MapStart();
R_UpdateMobjInterpolators();
R_UpdateLevelInterpolators();
OP_ObjectplaceMovement(&players[0]);
P_MoveChaseCamera(&players[0], &camera, false);
R_UpdateViewInterpolation();
......@@ -775,7 +777,7 @@ void P_Ticker(boolean run)
PS_START_TIMING(ps_playerthink_time);
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
if (players[i].ingame && players[i].mo && !P_MobjWasRemoved(players[i].mo))
P_PlayerThink(&players[i]);
PS_STOP_TIMING(ps_playerthink_time);
}
......@@ -801,7 +803,7 @@ void P_Ticker(boolean run)
// Run any "after all the other thinkers" stuff
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
if (players[i].ingame && players[i].mo && !P_MobjWasRemoved(players[i].mo))
P_PlayerAfterThink(&players[i]);
PS_START_TIMING(ps_lua_thinkframe_time);
......@@ -837,7 +839,7 @@ void P_Ticker(boolean run)
countdowntimeup = true;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator)
if (!players[i].ingame || players[i].spectator)
continue;
if (!players[i].mo)
......@@ -935,7 +937,7 @@ void P_PreTicker(INT32 frames)
LUA_HOOK(PreThinkFrame);
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
if (players[i].ingame && players[i].mo && !P_MobjWasRemoved(players[i].mo))
{
// stupid fucking cmd hack
// if it isn't for this, players can move in preticker time
......@@ -956,7 +958,7 @@ void P_PreTicker(INT32 frames)
// Run any "after all the other thinkers" stuff
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo))
if (players[i].ingame && players[i].mo && !P_MobjWasRemoved(players[i].mo))
P_PlayerAfterThink(&players[i]);
LUA_HookThinkFrame();
......
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2025 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -47,6 +47,7 @@
#include "m_cheat.h"
// Thok camera snap (ctrl-f "chalupa")
#include "g_input.h"
#include "simple_hashmap.h"
#ifdef HW3SOUND
#include "hardware/hw3sound.h"
......@@ -326,7 +327,7 @@ void P_GiveEmerald(boolean spawnObj)
{
UINT8 em = P_GetNextEmerald();
S_StartSound(NULL, sfx_cgot); // Got the emerald!
S_StartSoundFromEverywhere(sfx_cgot); // Got the emerald!
emeralds |= (1 << em);
stagefailed = false;
......@@ -334,11 +335,11 @@ void P_GiveEmerald(boolean spawnObj)
{
// The Chaos Emerald begins to orbit us!
// Only visibly give it to ONE person!
UINT8 i, pnum = ((playeringame[consoleplayer]) && (!players[consoleplayer].spectator) && (players[consoleplayer].mo)) ? consoleplayer : 255;
UINT8 i, pnum = ((players[consoleplayer].ingame) && (!players[consoleplayer].spectator) && (players[consoleplayer].mo)) ? consoleplayer : 255;
for (i = 0; i < MAXPLAYERS; i++)
{
mobj_t *emmo;
if (!playeringame[i])
if (!players[i].ingame)
continue;
if (players[i].spectator)
continue;
......@@ -435,7 +436,7 @@ UINT8 P_FindLowestMare(void)
// to find the egg capsule with the lowest mare
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
mo2 = (mobj_t *)th;
......@@ -471,9 +472,9 @@ boolean P_TransferToNextMare(player_t *player)
thinker_t *th;
mobj_t *mo2;
mobj_t *closestaxis = NULL;
INT32 lowestaxisnum = -1;
INT32 lowestaxisnum = INT32_MAX;
UINT8 mare = P_FindLowestMare();
fixed_t dist1, dist2 = 0;
INT32 dist, closestdist = INT32_MAX;
if (mare == 255)
return false;
......@@ -488,7 +489,7 @@ boolean P_TransferToNextMare(player_t *player)
// to find the closest axis point
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
mo2 = (mobj_t *)th;
......@@ -499,22 +500,12 @@ boolean P_TransferToNextMare(player_t *player)
if (mo2->threshold != mare)
continue;
if (closestaxis == NULL)
{
closestaxis = mo2;
lowestaxisnum = mo2->health;
dist2 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y) - mo2->radius;
}
else if (mo2->health < lowestaxisnum)
{
dist1 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y) - mo2->radius;
if (dist1 < dist2)
dist = P_GetMobjLargeDistance2D(player->mo, mo2) - mo2->radius / FRACUNIT;
if (mo2->health < lowestaxisnum && dist < closestdist)
{
closestaxis = mo2;
lowestaxisnum = mo2->health;
dist2 = dist1;
}
closestdist = dist;
}
}
......@@ -539,7 +530,7 @@ static mobj_t *P_FindAxis(INT32 mare, INT32 axisnum)
// to find the closest axis point
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
mo2 = (mobj_t *)th;
......@@ -574,7 +565,7 @@ static mobj_t *P_FindAxisTransfer(INT32 mare, INT32 axisnum, mobjtype_t type)
// to find the closest axis point
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
mo2 = (mobj_t *)th;
......@@ -605,7 +596,7 @@ void P_TransferToAxis(player_t *player, INT32 axisnum)
mobj_t *mo2;
mobj_t *closestaxis;
INT32 mare = player->mare;
fixed_t dist1, dist2 = 0;
INT32 dist, closestdist = INT32_MAX;
CONS_Debug(DBG_NIGHTS, "Transferring to axis %d\nLeveltime: %u...\n", axisnum, leveltime);
......@@ -615,7 +606,7 @@ void P_TransferToAxis(player_t *player, INT32 axisnum)
// to find the closest axis point
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
mo2 = (mobj_t *)th;
......@@ -627,20 +618,11 @@ void P_TransferToAxis(player_t *player, INT32 axisnum)
if (mo2->threshold != mare)
continue;
if (closestaxis == NULL)
{
closestaxis = mo2;
dist2 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y) - mo2->radius;
}
else
{
dist1 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y) - mo2->radius;
if (dist1 < dist2)
dist = P_GetMobjLargeDistance2D(player->mo, mo2) - mo2->radius / FRACUNIT;
if (dist < closestdist)
{
closestaxis = mo2;
dist2 = dist1;
}
closestdist = dist;
}
}
......@@ -669,7 +651,7 @@ static void P_DeNightserizePlayer(player_t *player)
player->powers[pw_carry] = CR_NIGHTSFALL;
player->powers[pw_underwater] = 0;
player->pflags &= ~(PF_SPINDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_SHIELDDOWN|PF_STARTDASH|PF_GLIDING|PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED|PF_SPINNING|PF_DRILLING|PF_TRANSFERTOCLOSEST);
player->pflags &= ~(PF_SPINDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_STARTDASH|PF_GLIDING|PF_STARTJUMP|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED|PF_SPINNING|PF_DRILLING|PF_TRANSFERTOCLOSEST);
player->secondjump = 0;
player->homing = 0;
player->climbing = 0;
......@@ -704,7 +686,7 @@ static void P_DeNightserizePlayer(player_t *player)
{
INT32 i;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].powers[pw_carry] == CR_NIGHTSMODE)
if (players[i].ingame && players[i].powers[pw_carry] == CR_NIGHTSMODE)
players[i].nightstime = 1; // force everyone else to fall too.
player->exiting = 3*TICRATE;
......@@ -716,7 +698,7 @@ static void P_DeNightserizePlayer(player_t *player)
// Check to see if the player should be killed.
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
mo2 = (mobj_t *)th;
......@@ -802,7 +784,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
if (mapheaderinfo[gamemap-1]->nightstimer[newmare] > 0)
nighttime = mapheaderinfo[gamemap-1]->nightstimer[newmare];
player->pflags &= ~(PF_SPINDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_SHIELDDOWN|PF_STARTDASH|PF_GLIDING|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED|PF_SHIELDABILITY|PF_SPINNING|PF_DRILLING);
player->pflags &= ~(PF_SPINDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_STARTDASH|PF_GLIDING|PF_JUMPED|PF_NOJUMPDAMAGE|PF_THOKKED|PF_SHIELDABILITY|PF_SPINNING|PF_DRILLING);
player->homing = 0;
player->mo->fuse = 0;
player->speed = 0;
......@@ -859,7 +841,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
if (G_IsSpecialStage(gamemap))
{
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i]/* && players[i].powers[pw_carry] == CR_NIGHTSMODE*/)
if (players[i].ingame/* && players[i].powers[pw_carry] == CR_NIGHTSMODE*/)
{
total_spheres += players[i].spheres;
total_rings += players[i].rings;
......@@ -868,7 +850,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || !players[i].mo || players[i].spectator)
if (!players[i].ingame || !players[i].mo || players[i].spectator)
continue;
players[i].texttimer = (3 * TICRATE) - 10;
......@@ -968,6 +950,33 @@ pflags_t P_GetJumpFlags(player_t *player)
return PF_JUMPED;
}
// If the state is a custom state for the player's skin, retrieve its "canonical" state
// e.g. S_SKIN_BIGTHECAT_WALK => S_PLAY_WALK
statenum_t P_GetCanonicalPlayerState(player_t *player, statenum_t state)
{
skin_t *skin = skins[player->skin];
statenum_t mappedstate;
SIMPLEHASH_FIND_INT(skin->customtodefaultstate, hashentry_int32_int32_t, state, state, mappedstate)
return mappedstate;
}
boolean P_IsPlayerInState(player_t *player, statenum_t state)
{
return (P_GetCanonicalPlayerState(player, player->mo->state - states) == state);
}
boolean P_IsPlayerInSuperTransformationState(player_t *player)
{
statenum_t state = player->mo->state - states;
return (state >= S_PLAY_SUPER_TRANS1 && state <= S_PLAY_SUPER_TRANS6);
}
boolean P_IsPlayerInNightsTransformationState(player_t *player)
{
statenum_t state = player->mo->state - states;
return (state >= S_PLAY_NIGHTS_TRANS1 && state <= S_PLAY_NIGHTS_TRANS6);
}
//
// P_PlayerInPain
//
......@@ -976,11 +985,14 @@ pflags_t P_GetJumpFlags(player_t *player)
//
boolean P_PlayerInPain(player_t *player)
{
if (P_MobjWasRemoved(player->mo))
return false;
// no silly, sliding isn't pain
if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate] && player->powers[pw_flashing])
return true;
if (player->mo->state == &states[S_PLAY_STUN])
if (P_IsPlayerInState(player, S_PLAY_STUN))
return true;
return false;
......@@ -1004,7 +1016,7 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor)
fixed_t fallbackspeed;
P_ResetPlayer(player);
P_SetMobjState(player->mo, player->mo->info->painstate);
P_SetMobjState(player->mo, S_PLAY_PAIN);
if (player->mo->eflags & MFE_VERTICALFLIP)
player->mo->z--;
......@@ -1027,7 +1039,7 @@ void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor)
// to recover
if ((inflictor->flags2 & MF2_SCATTER) && source)
{
fixed_t dist = P_AproxDistance(P_AproxDistance(source->x-player->mo->x, source->y-player->mo->y), source->z-player->mo->z);
fixed_t dist = P_GetMobjDistance3D(source, player->mo);
dist = FixedMul(128*FRACUNIT, inflictor->scale) - dist/4;
......@@ -1089,6 +1101,13 @@ void P_ResetPlayer(player_t *player)
if (player->mo->tracer && !P_MobjWasRemoved(player->mo->tracer))
{
player->mo->tracer->flags |= MF_PUSHABLE;
// goose the mom a little bit to trigger gravity to process for a tic
if (player->mo->tracer->eflags & MFE_VERTICALFLIP)
player->mo->tracer->momz -= 1;
else
player->mo->tracer->momz += 1;
P_SetTarget(&player->mo->tracer->tracer, NULL);
}
P_SetTarget(&player->mo->tracer, NULL);
......@@ -1332,7 +1351,7 @@ void P_GiveCoopLives(player_t *player, INT32 numlives, boolean sound)
INT32 i;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
if (!players[i].ingame)
continue;
P_GivePlayerLives(&players[i], numlives);
......@@ -1352,6 +1371,8 @@ void P_DoSuperTransformation(player_t *player, boolean giverings)
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOSSMUSIC) && P_IsLocalPlayer(player))
P_PlayJingle(player, JT_SUPER);
S_StartSoundFromEverywhere(sfx_supert); //let all players hear it -mattw_cfi
player->mo->momx = player->mo->momy = player->mo->momz = player->cmomx = player->cmomy = player->rmomx = player->rmomy = 0;
// Transformation animation
......@@ -1368,11 +1389,8 @@ void P_DoSuperTransformation(player_t *player, boolean giverings)
player->powers[pw_sneakers] = 0;
}
if (G_CoopGametype())
S_StartSound(player->mo, sfx_supert); //only hear it near yourself in co-op
else
if (!G_CoopGametype())
{
S_StartSound(NULL, sfx_supert); //let all players hear it -mattw_cfi
HU_SetCEchoFlags(0);
HU_SetCEchoDuration(5);
HU_DoCEcho(va("%s\\is now super.\\\\\\\\", player_names[player-players]));
......@@ -1407,13 +1425,13 @@ void P_DoSuperDetransformation(player_t *player)
if (!G_CoopGametype())
player->powers[pw_flashing] = flashingtics-1;
if (player->mo->sprite2 & SPR2F_SUPER)
if (player->mo->sprite2 & FF_SPR2SUPER)
P_SetMobjState(player->mo, player->mo->state-states);
// Inform the netgame that the champion has fallen in the heat of battle.
if (!G_CoopGametype())
{
S_StartSound(NULL, sfx_s3k66); //let all players hear it.
S_StartSoundFromEverywhere(sfx_s3k66); //let all players hear it.
HU_SetCEchoFlags(0);
HU_SetCEchoDuration(5);
HU_DoCEcho(va("%s\\is no longer super.\\\\\\\\", player_names[player-players]));
......@@ -1446,7 +1464,7 @@ void P_AddPlayerScore(player_t *player, UINT32 amount)
{ // Pseudo-shared score for multiplayer special stages.
INT32 i;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].powers[pw_carry] == CR_NIGHTSMODE)
if (players[i].ingame && players[i].powers[pw_carry] == CR_NIGHTSMODE)
{
oldscore = players[i].marescore;
......@@ -1464,7 +1482,7 @@ void P_AddPlayerScore(player_t *player, UINT32 amount)
players[i].continues += 1;
players[i].gotcontinue = true;
if (P_IsLocalPlayer(player))
S_StartSound(NULL, sfx_s3kac);
S_StartSoundFromEverywhere(sfx_s3kac);
} */
}
}
......@@ -1484,7 +1502,7 @@ void P_AddPlayerScore(player_t *player, UINT32 amount)
player->continues += 1;
player->gotcontinue = true;
if (P_IsLocalPlayer(player))
S_StartSound(NULL, sfx_s3kac);
S_StartSoundFromEverywhere(sfx_s3kac);
}
}
......@@ -1565,9 +1583,9 @@ void P_PlayLivesJingle(player_t *player)
return;
if (mariomode)
S_StartSound(NULL, sfx_marioa);
S_StartSoundFromEverywhere(sfx_marioa);
else if (use1upSound || cv_1upsound.value)
S_StartSound(NULL, sfx_oneup);
S_StartSoundFromEverywhere(sfx_oneup);
else
{
P_PlayJingle(player, JT_1UP);
......@@ -1889,7 +1907,7 @@ void P_SpawnShieldOrb(player_t *player)
// blaze through the thinkers to see if an orb already exists!
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
shieldobj = (mobj_t *)th;
......@@ -2071,6 +2089,7 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
ghost->renderflags = mobj->renderflags;
ghost->blendmode = mobj->blendmode;
ghost->alpha = mobj->alpha;
ghost->spritexscale = mobj->spritexscale;
ghost->spriteyscale = mobj->spriteyscale;
......@@ -2372,7 +2391,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
if (dorollstuff)
{
if ((player->charability2 == CA2_SPINDASH) && !((player->pflags & (PF_SPINNING|PF_THOKKED)) == PF_THOKKED) && !(player->charability == CA_THOK && player->secondjump)
&& (player->cmd.buttons & BT_SPIN) && (FixedHypot(player->mo->momx, player->mo->momy) > (5*player->mo->scale)))
&& (player->cmd.buttons & BT_SPIN) && (FixedHypot(player->mo->momx, player->mo->momy) >= (5*player->mo->scale)))
player->pflags = (player->pflags|PF_SPINNING) & ~PF_THOKKED;
else if (!(player->pflags & PF_STARTDASH))
player->pflags &= ~PF_SPINNING;
......@@ -2380,7 +2399,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
if (player->pflags & PF_BOUNCING)
{
if (dorollstuff && player->mo->state-states != S_PLAY_BOUNCE_LANDING)
if (dorollstuff && !P_IsPlayerInState(player, S_PLAY_BOUNCE_LANDING))
{
P_MobjCheckWater(player->mo);
player->mo->momz *= -1;
......@@ -2401,7 +2420,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
&& player->panim != PA_ABILITY && player->panim != PA_ABILITY2)
{
P_SetMobjState(player->mo, S_PLAY_ROLL);
S_StartSound(player->mo, sfx_spin);
S_StartSoundFromMobj(player->mo, sfx_spin);
}
}
else if (player->pflags & PF_GLIDING) // ground gliding
......@@ -2417,9 +2436,9 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
player->pflags &= ~PF_GLIDING;
}
else if (player->charability == CA_GLIDEANDCLIMB && player->pflags & PF_THOKKED && !(player->pflags & (PF_JUMPED|PF_SHIELDABILITY))
&& (player->mo->floorz != player->mo->watertop) && player->mo->state-states == S_PLAY_FALL)
&& (player->mo->floorz != player->mo->watertop) && P_IsPlayerInState(player, S_PLAY_FALL))
{
if (player->mo->state-states != S_PLAY_GLIDE_LANDING)
if (!P_IsPlayerInState(player, S_PLAY_GLIDE_LANDING))
{
P_ResetPlayer(player);
P_SetMobjState(player->mo, S_PLAY_GLIDE_LANDING);
......@@ -2431,21 +2450,21 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
if (player->powers[pw_super])
{
P_Earthquake(player->mo, player->mo, 256*FRACUNIT);
S_StartSound(player->mo, sfx_s3k49);
S_StartSoundFromMobj(player->mo, sfx_s3k49);
}
else
S_StartSound(player->mo, sfx_s3k4c);
S_StartSoundFromMobj(player->mo, sfx_s3k4c);
}
}
else if (player->charability2 == CA2_MELEE
&& ((player->panim == PA_ABILITY2) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY && player->cmd.buttons & (BT_JUMP|BT_SPIN))))
{
if (player->mo->state-states != S_PLAY_MELEE_LANDING)
if (!P_IsPlayerInState(player, S_PLAY_MELEE_LANDING))
{
mobjtype_t type = player->revitem;
P_SetMobjState(player->mo, S_PLAY_MELEE_LANDING);
player->mo->tics = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS;
S_StartSound(player->mo, sfx_s3k8b);
S_StartSoundFromMobj(player->mo, sfx_s3k8b);
player->pflags |= PF_FULLSTASIS;
player->powers[pw_strong] = STR_MELEE;
......@@ -2484,11 +2503,11 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
throwang += ANG30;
}
if (mobjinfo[type].seesound && missile)
S_StartSound(missile, missile->info->seesound);
S_StartSoundFromMobj(missile, missile->info->seesound);
}
}
}
else if (player->charability == CA_GLIDEANDCLIMB && (player->mo->state-states == S_PLAY_GLIDE_LANDING))
else if (player->charability == CA_GLIDEANDCLIMB && (P_IsPlayerInState(player, S_PLAY_GLIDE_LANDING)))
;
else if (player->charability2 == CA2_GUNSLINGER && player->panim == PA_ABILITY2)
;
......@@ -2511,10 +2530,10 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
if (player->charflags & SF_DASHMODE && player->dashmode >= DASHMODE_THRESHOLD && player->panim != PA_DASH)
P_SetMobjState(player->mo, S_PLAY_DASH);
else if (player->speed >= runspd
&& (player->panim != PA_RUN || player->mo->state-states == S_PLAY_FLOAT_RUN))
&& (player->panim != PA_RUN || P_IsPlayerInState(player, S_PLAY_FLOAT_RUN)))
P_SetMobjState(player->mo, S_PLAY_RUN);
else if ((player->rmomx || player->rmomy)
&& (player->panim != PA_WALK || player->mo->state-states == S_PLAY_FLOAT))
&& (player->panim != PA_WALK || P_IsPlayerInState(player, S_PLAY_FLOAT)))
P_SetMobjState(player->mo, S_PLAY_WALK);
else if (!player->rmomx && !player->rmomy && player->panim != PA_IDLE)
P_SetMobjState(player->mo, S_PLAY_STND);
......@@ -2524,10 +2543,10 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
if (player->charflags & SF_DASHMODE && player->dashmode >= DASHMODE_THRESHOLD && player->panim != PA_DASH)
P_SetMobjState(player->mo, S_PLAY_DASH);
else if (player->speed >= runspd
&& (player->panim != PA_RUN || player->mo->state-states == S_PLAY_FLOAT_RUN))
&& (player->panim != PA_RUN || P_IsPlayerInState(player, S_PLAY_FLOAT_RUN)))
P_SetMobjState(player->mo, S_PLAY_RUN);
else if ((player->mo->momx || player->mo->momy)
&& (player->panim != PA_WALK || player->mo->state-states == S_PLAY_FLOAT))
&& (player->panim != PA_WALK || P_IsPlayerInState(player, S_PLAY_FLOAT)))
P_SetMobjState(player->mo, S_PLAY_WALK);
else if (!player->mo->momx && !player->mo->momy && player->panim != PA_IDLE)
P_SetMobjState(player->mo, S_PLAY_STND);
......@@ -2549,10 +2568,10 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) // Elemental shield's stomp attack.
{
if (player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) // play a blunt sound
S_StartSound(player->mo, sfx_s3k4c);
S_StartSoundFromMobj(player->mo, sfx_s3k4c);
else // create a fire pattern on the ground
{
S_StartSound(player->mo, sfx_s3k47);
S_StartSoundFromMobj(player->mo, sfx_s3k47);
P_ElementalFire(player, true);
}
P_SetObjectMomZ(player->mo,
......@@ -3039,11 +3058,11 @@ static void P_CheckUnderwaterAndSpaceTimer(player_t *player)
if (player->charflags & SF_MACHINE)
{
S_StartSound(player->mo, sfx_buzz1);
S_StartSoundFromMobj(player->mo, sfx_buzz1);
timeleft += 6;
}
else
S_StartSound(player->mo, sfx_dwnind);
S_StartSoundFromMobj(player->mo, sfx_dwnind);
if (!P_MobjWasRemoved(numbermobj))
{
......@@ -3088,7 +3107,7 @@ static void P_CheckUnderwaterAndSpaceTimer(player_t *player)
if ((player->powers[pw_underwater] == 25*TICRATE + 1)
|| (player->powers[pw_underwater] == 20*TICRATE + 1)
|| (player->powers[pw_underwater] == 15*TICRATE + 1))
S_StartSound(NULL, sfx_wtrdng);
S_StartSoundFromEverywhere(sfx_wtrdng);
if (player->powers[pw_underwater] == 11*TICRATE + 1
&& player == &players[consoleplayer])
......@@ -3170,7 +3189,7 @@ static void P_DoBubbleBreath(player_t *player)
z += (P_RandomKey(player->mo->height>>FRACBITS)<<FRACBITS);
bubble = P_SpawnMobj(x, y, z, MT_WATERZAP);
if (!P_MobjWasRemoved(bubble))
S_StartSound(bubble, sfx_beelec);
S_StartSoundFromMobj(bubble, sfx_beelec);
}
}
else
......@@ -3300,6 +3319,7 @@ static void P_DoPlayerHeadSigns(player_t *player)
sign->frame = 2|FF_FULLBRIGHT;
}
}
}
if (!P_MobjWasRemoved(sign) && splitscreen) // Hide the sign from yourself in splitscreen - In single-screen, it wouldn't get spawned if it shouldn't be visible
{
......@@ -3338,7 +3358,6 @@ static void P_DoPlayerHeadSigns(player_t *player)
#endif
}
}
}
//
// P_DoClimbing
......@@ -3647,7 +3666,7 @@ static void P_DoClimbing(player_t *player)
for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next)
{
if (think->function.acp1 != (actionf_p1)T_Scroll)
if (think->function != (actionf_p1)T_Scroll)
continue;
scroller = (scroll_t *)think;
......@@ -3701,9 +3720,9 @@ static void P_DoClimbing(player_t *player)
climb = false;
if (player->climbing && climb && (player->mo->momx || player->mo->momy || player->mo->momz)
&& player->mo->state-states != S_PLAY_CLIMB)
&& !P_IsPlayerInState(player, S_PLAY_CLIMB))
P_SetMobjState(player->mo, S_PLAY_CLIMB);
else if ((!(player->mo->momx || player->mo->momy || player->mo->momz) || !climb) && player->mo->state-states != S_PLAY_CLING)
else if ((!(player->mo->momx || player->mo->momy || player->mo->momz) || !climb) && !P_IsPlayerInState(player, S_PLAY_CLING))
P_SetMobjState(player->mo, S_PLAY_CLING);
if (!floorclimb)
......@@ -3736,9 +3755,9 @@ static void P_DoClimbing(player_t *player)
climb = false;
if (player->climbing && climb && (player->mo->momx || player->mo->momy || player->mo->momz)
&& player->mo->state-states != S_PLAY_CLIMB)
&& !P_IsPlayerInState(player, S_PLAY_CLIMB))
P_SetMobjState(player->mo, S_PLAY_CLIMB);
else if ((!(player->mo->momx || player->mo->momy || player->mo->momz) || !climb) && player->mo->state-states != S_PLAY_CLING)
else if ((!(player->mo->momx || player->mo->momy || player->mo->momz) || !climb) && !P_IsPlayerInState(player, S_PLAY_CLING))
P_SetMobjState(player->mo, S_PLAY_CLING);
if (cmd->buttons & BT_SPIN && !(player->pflags & PF_JUMPSTASIS))
......@@ -4115,7 +4134,7 @@ static void P_DoTeeter(player_t *player)
teeteryl = teeteryh = player->mo->y;
couldteeter = false;
solidteeter = teeter;
if (!P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_CheckSolidsTeeter))
if (!P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_CheckSolidsTeeter, tmthing))
goto teeterdone; // we've found something that stops us teetering at all
teeterdone:
teeter = solidteeter;
......@@ -4200,19 +4219,17 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd)
if (player->pflags & PF_ATTACKDOWN || player->climbing || (G_TagGametype() && !(player->pflags & PF_TAGIT)))
return;
// Fire a fireball if we have the Fire Flower powerup!
if (((player->powers[pw_shield] & SH_STACK) == SH_FIREFLOWER) && !(player->weapondelay))
{
player->pflags |= PF_ATTACKDOWN;
mo = P_SpawnPlayerMissile(player->mo, MT_FIREBALL, 0);
if (mo)
P_InstaThrust(mo, player->mo->angle, ((mo->info->speed>>FRACBITS)*player->mo->scale) + player->speed);
S_StartSound(player->mo, sfx_mario7);
S_StartSoundFromMobj(player->mo, sfx_mario7);
P_SetWeaponDelay(player, TICRATE); // Short delay between fireballs so you can't spam them everywhere
return;
}
// No ringslinging outside of ringslinger!
if (!G_RingSlingerGametype() || player->weapondelay)
return;
......@@ -4240,7 +4257,7 @@ static void P_DoFiring(player_t *player, ticcmd_t *cmd)
mo = P_SpawnPlayerMissile(player->mo, MT_REDRING, MF2_RAILRING|MF2_DONTDRAW);
// Rail has no unique thrown object, therefore its sound plays here.
S_StartSound(player->mo, sfx_rail1);
S_StartSoundFromMobj(player->mo, sfx_rail1);
}
// Automatic
else if (player->currentweapon == WEP_AUTO && player->powers[pw_automaticring])
......@@ -4365,7 +4382,7 @@ firenormal:
}
// Other rail sound plays at contact point.
S_StartSound(mo, sfx_rail2);
S_StartSoundFromMobj(mo, sfx_rail2);
}
}
}
......@@ -4391,7 +4408,34 @@ static void P_DoSuperStuff(player_t *player)
// If you're super and not Sonic, de-superize!
if (!(ALL7EMERALDS(emeralds) && player->charflags & SF_SUPER))
{
P_DoSuperDetransformation(player);
player->powers[pw_super] = 0;
P_SetMobjState(player->mo, S_PLAY_STND);
if (P_IsLocalPlayer(player))
{
music_stack_noposition = true; // HACK: Do not reposition next music
music_stack_fadeout = MUSICRATE/2; // HACK: Fade out current music
}
P_RestoreMusic(player);
P_SpawnShieldOrb(player);
// Restore color
if ((player->powers[pw_shield] & SH_STACK) == SH_FIREFLOWER)
{
player->mo->color = SKINCOLOR_WHITE;
G_GhostAddColor(GHC_FIREFLOWER);
}
else
{
player->mo->color = P_GetPlayerColor(player);
G_GhostAddColor(GHC_NORMAL);
}
if (!G_CoopGametype())
{
HU_SetCEchoFlags(0);
HU_SetCEchoDuration(5);
HU_DoCEcho(va("%s\\is no longer super.\\\\\\\\", player_names[player-players]));
}
return;
}
......@@ -4401,7 +4445,7 @@ static void P_DoSuperStuff(player_t *player)
G_GhostAddColor(GHC_SUPER);
if (player->mo->state == &states[S_PLAY_SUPER_TRANS6]) // stop here for now
if (P_IsPlayerInState(player, S_PLAY_SUPER_TRANS6)) // stop here for now
return;
// Deplete one ring every second while super
......@@ -4418,37 +4462,28 @@ static void P_DoSuperStuff(player_t *player)
// Ran out of rings while super!
if (player->rings <= 0 || player->exiting)
{
P_DoSuperDetransformation(player);
}
}
}
//
// P_SuperReady
//
// Returns true if player is ready to transform or detransform
// Returns true if player is ready to turn super, duh
//
boolean P_SuperReady(player_t *player, boolean transform)
boolean P_SuperReady(player_t *player)
{
if (!transform &&
(player->powers[pw_super] < TICRATE*3/2
|| !G_CoopGametype())) // No turning back in competitive!
return false;
else if (transform
&& (player->powers[pw_super]
|| !ALL7EMERALDS(emeralds)
|| !(player->rings >= 50)))
return false;
if (player->mo
if (!player->powers[pw_super]
&& !player->powers[pw_invulnerability]
&& !player->powers[pw_tailsfly]
&& !player->powers[pw_carry]
&& (player->charflags & SF_SUPER)
&& !P_PlayerInPain(player)
&& !player->climbing
&& !(player->pflags & (PF_JUMPSTASIS|PF_THOKKED|PF_STARTDASH|PF_GLIDING|PF_SLIDING|PF_SHIELDABILITY))
&& ((player->pflags & PF_JUMPED) || (P_IsObjectOnGround(player->mo) && (player->panim == PA_IDLE || player->panim == PA_EDGE
|| player->panim == PA_WALK || player->panim == PA_RUN || (player->charflags & SF_DASHMODE && player->panim == PA_DASH))))
&& !(maptol & TOL_NIGHTS))
&& (player->pflags & PF_JUMPED)
&& !(player->powers[pw_shield] & SH_NOSTACK)
&& !(maptol & TOL_NIGHTS)
&& ALL7EMERALDS(emeralds)
&& (player->rings >= 50))
return true;
return false;
......@@ -4506,7 +4541,7 @@ void P_DoJump(player_t *player, boolean soundandstate, boolean allowflip)
if (player->powers[pw_carry] == CR_PTERABYTE)
{
S_StartSound(player->mo, sfx_s3kd7s);
S_StartSoundFromMobj(player->mo, sfx_s3kd7s);
player->mo->tracer->cusval += 10; // attempting to break free
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);
......@@ -4546,6 +4581,13 @@ void P_DoJump(player_t *player, boolean soundandstate, boolean allowflip)
player->mo->momz += player->mo->tracer->momz;
if (!P_IsObjectOnGround(player->mo->tracer))
P_SetObjectMomZ(player->mo->tracer, -9*FRACUNIT, true);
// goose the mom a little bit to trigger gravity to process for a tic
if (player->mo->tracer->eflags & MFE_VERTICALFLIP)
player->mo->tracer->momz -= 1;
else
player->mo->tracer->momz += 1;
player->mo->tracer->flags |= MF_PUSHABLE;
P_SetTarget(&player->mo->tracer->tracer, NULL);
}
......@@ -4635,13 +4677,13 @@ void P_DoJump(player_t *player, boolean soundandstate, boolean allowflip)
if (allowflip && P_InJumpFlipSector(player->mo)) // Flip gravity on jump?
{
player->mo->flags2 ^= MF2_OBJECTFLIP;
S_StartSound(player->mo, sfx_s3k73); // Play gravity flip sound
S_StartSoundFromMobj(player->mo, sfx_s3k73); // Play gravity flip sound
}
if (soundandstate)
{
if (!player->spectator)
S_StartSound(player->mo, sfx_jump); // Play jump sound!
S_StartSoundFromMobj(player->mo, sfx_jump); // Play jump sound!
P_SetMobjState(player->mo, S_PLAY_JUMP);
}
......@@ -4686,7 +4728,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
{
boolean canstand = true; // can we stand on the ground? (mostly relevant for slopes)
if (player->pflags & PF_STASIS
&& (player->pflags & PF_JUMPSTASIS || player->mo->state-states != S_PLAY_GLIDE_LANDING))
&& (player->pflags & PF_JUMPSTASIS || !P_IsPlayerInState(player, S_PLAY_GLIDE_LANDING)))
return;
if (cmd->buttons & BT_SPIN)
......@@ -4706,7 +4748,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
{
case CA2_SPINDASH: // Spinning and Spindashing
// Start revving
if ((cmd->buttons & BT_SPIN) && (player->speed < FixedMul(5<<FRACBITS, player->mo->scale) || player->mo->state - states == S_PLAY_GLIDE_LANDING)
if ((cmd->buttons & BT_SPIN) && (player->speed < FixedMul(5<<FRACBITS, player->mo->scale) || P_IsPlayerInState(player, S_PLAY_GLIDE_LANDING))
&& !player->mo->momz && onground && !(player->pflags & (PF_SPINDOWN|PF_SPINNING))
&& canstand)
{
......@@ -4716,16 +4758,16 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
player->dashspeed = player->mindash;
P_SetMobjState(player->mo, S_PLAY_SPINDASH);
if (!player->spectator)
S_StartSound(player->mo, sfx_spndsh); // Make the rev sound!
S_StartSoundFromMobj(player->mo, sfx_spndsh); // Make the rev sound!
}
// Revving
else if ((cmd->buttons & BT_SPIN) && (player->pflags & PF_STARTDASH))
{
if (player->speed > 5*player->mo->scale)
if (player->speed >= 5*player->mo->scale)
{
player->pflags &= ~PF_STARTDASH;
P_SetMobjState(player->mo, S_PLAY_ROLL);
S_StartSound(player->mo, sfx_spin);
S_StartSoundFromMobj(player->mo, sfx_spin);
break;
}
if (player->dashspeed < player->mindash)
......@@ -4740,7 +4782,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
fixed_t soundcalculation = chargecalculation;
player->dashspeed += FRACUNIT;
if (!player->spectator && soundcalculation != chargecalculation)
S_StartSound(player->mo, sfx_spndsh); // Make the rev sound!
S_StartSoundFromMobj(player->mo, sfx_spndsh); // Make the rev sound!
#undef chargecalculation
}
if (player->revitem && !(leveltime % 5)) // Now spawn the color thok circle.
......@@ -4759,11 +4801,10 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
player->pflags |= (PF_SPINDOWN|PF_SPINNING);
P_SetMobjState(player->mo, S_PLAY_ROLL);
if (!player->spectator)
S_StartSound(player->mo, sfx_spin);
S_StartSoundFromMobj(player->mo, sfx_spin);
}
else
// Catapult the player from a spindash rev!
if (onground && !(player->pflags & PF_SPINDOWN) && (player->pflags & PF_STARTDASH) && (player->pflags & PF_SPINNING))
else if (onground && !(player->pflags & PF_SPINDOWN) && (player->pflags & PF_STARTDASH) && (player->pflags & PF_SPINNING))
{
player->pflags &= ~PF_STARTDASH;
if (player->powers[pw_carry] == CR_BRAKGOOP)
......@@ -4783,7 +4824,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
}
if (!player->spectator)
S_StartSound(player->mo, sfx_zoom);
S_StartSoundFromMobj(player->mo, sfx_zoom);
}
player->dashspeed = 0;
......@@ -4856,7 +4897,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
player->pflags &= ~PF_STARTJUMP;
player->mo->momz = FixedMul(player->mo->momz, 3*FRACUNIT/2); // NOT 1.5 times the jump height, but 2.25 times.
P_SetMobjState(player->mo, S_PLAY_TWINSPIN);
S_StartSound(player->mo, sfx_s3k8b);
S_StartSoundFromMobj(player->mo, sfx_s3k8b);
}
else
#endif
......@@ -4883,7 +4924,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd)
player->mo->momy += player->cmomy;
P_SetMobjState(player->mo, S_PLAY_MELEE);
player->powers[pw_strong] = STR_MELEE;
S_StartSound(player->mo, sfx_s3k42);
S_StartSoundFromMobj(player->mo, sfx_s3k42);
}
player->pflags |= PF_SPINDOWN;
}
......@@ -4958,13 +4999,13 @@ void P_DoJumpShield(player_t *player)
#undef numangles
player->pflags &= ~PF_NOJUMPDAMAGE;
P_SetMobjState(player->mo, S_PLAY_ROLL);
S_StartSound(player->mo, sfx_s3k45);
S_StartSoundFromMobj(player->mo, sfx_s3k45);
}
else
{
player->pflags |= PF_NOJUMPDAMAGE;
P_SetMobjState(player->mo, S_PLAY_FALL);
S_StartSound(player->mo, sfx_wdjump);
S_StartSoundFromMobj(player->mo, sfx_wdjump);
}
}
......@@ -4976,7 +5017,7 @@ void P_DoJumpShield(player_t *player)
void P_DoBubbleBounce(player_t *player)
{
player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE|PF_SHIELDABILITY);
S_StartSound(player->mo, sfx_s3k44);
S_StartSoundFromMobj(player->mo, sfx_s3k44);
P_MobjCheckWater(player->mo);
P_DoJump(player, false, false);
if (player->charflags & SF_NOJUMPSPIN)
......@@ -4996,7 +5037,7 @@ void P_DoBubbleBounce(player_t *player)
//
void P_DoAbilityBounce(player_t *player, boolean changemomz)
{
if (player->mo->state-states == S_PLAY_BOUNCE_LANDING)
if (P_IsPlayerInState(player, S_PLAY_BOUNCE_LANDING))
return;
if (changemomz)
......@@ -5018,7 +5059,7 @@ void P_DoAbilityBounce(player_t *player, boolean changemomz)
player->mo->momz = max(minmomz, (minmomz + prevmomz)/2);
}
S_StartSound(player->mo, sfx_boingf);
S_StartSoundFromMobj(player->mo, sfx_boingf);
P_SetMobjState(player->mo, S_PLAY_BOUNCE_LANDING);
player->pflags |= PF_BOUNCING|PF_THOKKED;
}
......@@ -5095,7 +5136,7 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
mo2 = (mobj_t *)th;
......@@ -5106,7 +5147,7 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range)
if (!((mo2->flags & MF_SHOOTABLE && mo2->flags & MF_ENEMY) || mo2->type == MT_EGGGUARD || mo2->player))
continue;
dist = P_AproxDistance(P_AproxDistance(player->mo->x-mo2->x, player->mo->y-mo2->y), player->mo->z-mo2->z);
dist = P_GetMobjDistance3D(player->mo, mo2);
if (range < dist)
continue;
......@@ -5133,7 +5174,7 @@ static void P_DoTwinSpin(player_t *player)
{
player->pflags &= ~(PF_NOJUMPDAMAGE|PF_SPINNING);
player->pflags |= P_GetJumpFlags(player) | PF_THOKKED;
S_StartSound(player->mo, sfx_s3k42);
S_StartSoundFromMobj(player->mo, sfx_s3k42);
player->mo->frame = 0;
P_SetMobjState(player->mo, S_PLAY_TWINSPIN);
player->powers[pw_strong] = STR_TWINSPIN;
......@@ -5147,7 +5188,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock
{
mobj_t *lockonshield = NULL;
if ((player->powers[pw_shield] & SH_NOSTACK) && !player->powers[pw_super] && !(player->pflags & PF_SHIELDDOWN)
if ((player->powers[pw_shield] & SH_NOSTACK) && !player->powers[pw_super] && !(player->pflags & PF_SPINDOWN)
&& ((!(player->pflags & PF_THOKKED) || (((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP || (player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT) && player->secondjump == UINT8_MAX) ))) // thokked is optional if you're bubblewrapped / 3dblasted
{
if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT && !(player->charflags & SF_NOSHIELDABILITY))
......@@ -5177,7 +5218,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock
}
}
}
if ((!(player->charflags & SF_NOSHIELDABILITY)) && (cmd->buttons & BT_SHIELD && !LUA_HookPlayer(player, HOOK(ShieldSpecial)))) // Shield button effects
if ((!(player->charflags & SF_NOSHIELDABILITY)) && (cmd->buttons & BT_SPIN && !LUA_HookPlayer(player, HOOK(ShieldSpecial)))) // Spin button effects
{
// Force stop
if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE)
......@@ -5185,7 +5226,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock
player->pflags |= PF_THOKKED|PF_SHIELDABILITY;
player->pflags &= ~PF_SPINNING;
player->mo->momx = player->mo->momy = player->mo->momz = 0;
S_StartSound(player->mo, sfx_ngskid);
S_StartSoundFromMobj(player->mo, sfx_ngskid);
}
else
{
......@@ -5213,11 +5254,11 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock
player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, lockonshield->x, lockonshield->y);
player->pflags &= ~PF_NOJUMPDAMAGE;
P_SetMobjState(player->mo, S_PLAY_ROLL);
S_StartSound(player->mo, sfx_s3k40);
S_StartSoundFromMobj(player->mo, sfx_s3k40);
player->homing = 3*TICRATE;
}
else
S_StartSound(player->mo, sfx_s3ka6);
S_StartSoundFromMobj(player->mo, sfx_s3ka6);
break;
// Elemental stomp/Bubble bounce
case SH_ELEMENTAL:
......@@ -5229,7 +5270,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock
if (elem)
{
player->mo->momx = player->mo->momy = 0;
S_StartSound(player->mo, sfx_s3k43);
S_StartSoundFromMobj(player->mo, sfx_s3k43);
}
else
{
......@@ -5237,7 +5278,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock
player->mo->momy -= (player->mo->momy/3);
player->pflags &= ~PF_NOJUMPDAMAGE;
P_SetMobjState(player->mo, S_PLAY_ROLL);
S_StartSound(player->mo, sfx_s3k44);
S_StartSoundFromMobj(player->mo, sfx_s3k44);
}
player->secondjump = 0;
P_SetObjectMomZ(player->mo, -24*FRACUNIT, false);
......@@ -5250,7 +5291,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock
player->drawangle = player->mo->angle;
player->pflags &= ~(PF_NOJUMPDAMAGE|PF_SPINNING);
P_SetMobjState(player->mo, S_PLAY_ROLL);
S_StartSound(player->mo, sfx_s3k43);
S_StartSoundFromMobj(player->mo, sfx_s3k43);
default:
break;
}
......@@ -5266,7 +5307,7 @@ static boolean P_PlayerShieldThink(player_t *player, ticcmd_t *cmd, mobj_t *lock
//
// Handles player jumping
//
static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd, boolean spinshieldhack)
static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd)
{
mobj_t *lockonthok = NULL, *visual = NULL;
......@@ -5299,13 +5340,12 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd, boolean spinshieldhac
;
else if (P_PlayerShieldThink(player, cmd, lockonthok, visual))
;
else if (cmd->buttons & BT_SPIN)
else if ((cmd->buttons & BT_SPIN))
{
if (spinshieldhack && !(player->pflags & PF_SPINDOWN) && P_SuperReady(player, true)
&& !player->powers[pw_invulnerability] && !(player->powers[pw_shield] & SH_NOSTACK)) // These two checks are no longer in P_SuperReady
if (!(player->pflags & PF_SPINDOWN) && P_SuperReady(player))
{
// If you're using two-button play, can turn Super and aren't already,
// and you don't have a shield, then turn Super!
// If you can turn super and aren't already,
// and you don't have a shield, do it!
P_DoSuperTransformation(player, false);
}
else if (!LUA_HookPlayer(player, HOOK(JumpSpinSpecial)))
......@@ -5408,6 +5448,12 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd, boolean spinshieldhac
}
else if (player->pflags & PF_SLIDING || ((gametyperules & GTR_TEAMFLAGS) && player->gotflag) || player->pflags & PF_SHIELDABILITY)
;
/*else if (P_SuperReady(player))
{
// If you can turn super and aren't already,
// and you don't have a shield, do it!
P_DoSuperTransformation(player, false);
}*/
else if (player->pflags & PF_JUMPED)
{
if (!LUA_HookPlayer(player, HOOK(AbilitySpecial)))
......@@ -5469,7 +5515,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd, boolean spinshieldhac
player->drawangle = player->mo->angle;
if (player->mo->info->attacksound && !player->spectator)
S_StartSound(player->mo, player->mo->info->attacksound); // Play the THOK sound
S_StartSoundFromMobj(player->mo, player->mo->info->attacksound); // Play the THOK sound
P_SpawnThokMobj(player);
......@@ -5584,7 +5630,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd, boolean spinshieldhac
player->flyangle = 56 + (60-(player->actionspd>>FRACBITS))/3;
player->pflags |= PF_THOKKED;
player->pflags &= ~PF_SPINNING;
S_StartSound(player->mo, sfx_spndsh);
S_StartSoundFromMobj(player->mo, sfx_spndsh);
}
break;
case CA_BOUNCE:
......@@ -6006,7 +6052,7 @@ static void P_3dMovement(player_t *player)
totalthrust.z = FRACUNIT*P_MobjFlip(player->mo)/3; // A bit of extra push-back on slopes
// Get the old momentum; this will be needed at the end of the function! -SH
oldMagnitude = R_PointToDist2(player->mo->momx - player->cmomx, player->mo->momy - player->cmomy, 0, 0);
oldMagnitude = GetDistance2D(player->mo->momx, player->mo->momy, player->cmomx, player->cmomy);
controlstyle = P_ControlStyle(player);
......@@ -6072,7 +6118,7 @@ static void P_3dMovement(player_t *player)
// When sliding, don't allow forward/back
if (player->pflags & PF_SLIDING)
cmd->forwardmove = 0;
else if (onground && player->mo->state == states+S_PLAY_PAIN)
else if (onground && P_IsPlayerInState(player, S_PLAY_PAIN))
P_SetMobjState(player->mo, S_PLAY_WALK);
player->aiming = cmd->aiming<<FRACBITS;
......@@ -6125,7 +6171,7 @@ static void P_3dMovement(player_t *player)
{
if (player->pflags & PF_BOUNCING)
{
if (player->mo->state-states == S_PLAY_BOUNCE_LANDING)
if (P_IsPlayerInState(player, S_PLAY_BOUNCE_LANDING))
{
thrustfactor = player->thrustfactor*8;
acceleration = player->accelstart/8 + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration/8;
......@@ -6283,7 +6329,7 @@ static void P_3dMovement(player_t *player)
// If "no" to 2, normalize to topspeed, so we can't suddenly run faster than it of our own accord.
// If "no" to 1, we're not reaching any limits yet, so ignore this entirely!
// -Shadow Hog
newMagnitude = R_PointToDist2(player->mo->momx - player->cmomx, player->mo->momy - player->cmomy, 0, 0);
newMagnitude = GetDistance2D(player->mo->momx, player->mo->momy, player->cmomx, player->cmomy);
if (newMagnitude > topspeed)
{
fixed_t tempmomx, tempmomy;
......@@ -6462,7 +6508,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad
// Find next waypoint
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
mo2 = (mobj_t *)th;
......@@ -6498,7 +6544,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad
{
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
mo2 = (mobj_t *)th;
......@@ -6527,7 +6573,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad
{
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
mo2 = (mobj_t *)th;
......@@ -6570,12 +6616,11 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad
//CONS_Debug(DBG_NIGHTS, "T1 is at %d, %d\n", transfer1->x>>FRACBITS, transfer1->y>>FRACBITS);
//CONS_Debug(DBG_NIGHTS, "T2 is at %d, %d\n", transfer2->x>>FRACBITS, transfer2->y>>FRACBITS);
//CONS_Debug(DBG_NIGHTS, "Distance from T1: %d\n", P_AproxDistance(transfer1->x - player->mo->x, transfer1->y - player->mo->y)>>FRACBITS);
//CONS_Debug(DBG_NIGHTS, "Distance from T2: %d\n", P_AproxDistance(transfer2->x - player->mo->x, transfer2->y - player->mo->y)>>FRACBITS);
//CONS_Debug(DBG_NIGHTS, "Distance from T1: %d\n", P_GetMobjDistance2D(transfer1, player->mo)>>FRACBITS);
//CONS_Debug(DBG_NIGHTS, "Distance from T2: %d\n", P_GetMobjDistance2D(transfer2, player->mo)>>FRACBITS);
// Transfer1 is closer to the player than transfer2
if (P_AproxDistance(transfer1->x - player->mo->x, transfer1->y - player->mo->y)>>FRACBITS
< P_AproxDistance(transfer2->x - player->mo->x, transfer2->y - player->mo->y)>>FRACBITS)
if (P_AreMobjsClose2D(transfer1, player->mo, P_GetMobjDistance2D(transfer2, player->mo)))
{
//CONS_Debug(DBG_NIGHTS, " must be < 0 to transfer\n");
......@@ -6619,7 +6664,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad
HU_SetCEchoDuration(1);
HU_DoCEcho("transfer!");
HU_SetCEchoDuration(5);
S_StartSound(NULL, sfx_strpst);
S_StartSoundFromEverywhere(sfx_strpst);
}
if (player->pflags & PF_TRANSFERTOCLOSEST)
{
......@@ -6675,7 +6720,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad
HU_SetCEchoDuration(1);
HU_DoCEcho("transfer!");
HU_SetCEchoDuration(5);
S_StartSound(NULL, sfx_strpst);
S_StartSoundFromEverywhere(sfx_strpst);
}
if (player->mo->target->health < transfer1->health)
{
......@@ -6741,7 +6786,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad
HU_SetCEchoDuration(1);
HU_DoCEcho("transfer!");
HU_SetCEchoDuration(5);
S_StartSound(NULL, sfx_strpst);
S_StartSoundFromEverywhere(sfx_strpst);
}
if (player->pflags & PF_TRANSFERTOCLOSEST)
{
......@@ -6807,7 +6852,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad
HU_SetCEchoDuration(1);
HU_DoCEcho("transfer!");
HU_SetCEchoDuration(5);
S_StartSound(NULL, sfx_strpst);
S_StartSoundFromEverywhere(sfx_strpst);
}
if (player->mo->target->health < transfer2->health)
{
......@@ -6878,12 +6923,12 @@ static void P_DoNiGHTSCapsule(player_t *player)
{
if (player->mo->momx || player->mo->momy || player->mo->momz)
{
if (player->mo->state != &states[S_PLAY_NIGHTS_PULL])
if (!P_IsPlayerInState(player, S_PLAY_NIGHTS_PULL))
P_SetMobjState(player->mo, S_PLAY_NIGHTS_PULL);
}
else if (player->mo->state != &states[S_PLAY_NIGHTS_ATTACK])
else if (!P_IsPlayerInState(player, S_PLAY_NIGHTS_ATTACK))
{
S_StartSound(player->mo, sfx_spin);
S_StartSoundFromMobj(player->mo, sfx_spin);
P_SetMobjState(player->mo, S_PLAY_NIGHTS_ATTACK);
}
}
......@@ -6897,7 +6942,7 @@ static void P_DoNiGHTSCapsule(player_t *player)
if (!(player->charflags & SF_NONIGHTSROTATION))
{
if ((player->mo->state == &states[S_PLAY_NIGHTS_PULL])
if ((P_IsPlayerInState(player, S_PLAY_NIGHTS_PULL))
&& (player->mo->sprite2 == SPR2_NPUL))
player->mo->spriteroll -= ANG30;
else
......@@ -6907,7 +6952,7 @@ static void P_DoNiGHTSCapsule(player_t *player)
if (G_IsSpecialStage(gamemap))
{ // In special stages, share rings. Everyone gives up theirs to the capsule player always, because we can't have any individualism here!
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && (&players[i] != player) && players[i].spheres > 0)
if (players[i].ingame && (&players[i] != player) && players[i].spheres > 0)
{
player->spheres += players[i].spheres;
players[i].spheres = 0;
......@@ -6981,7 +7026,7 @@ static void P_DoNiGHTSCapsule(player_t *player)
player->capsule->z + (player->capsule->height/2) + ((P_SignedRandom()/2)<<FRACBITS),
MT_SONIC3KBOSSEXPLODE);
if (!P_MobjWasRemoved(explodemo))
S_StartSound(explodemo,sfx_s3kb4);
S_StartSoundFromMobj(explodemo,sfx_s3kb4);
}
}
else
......@@ -7008,7 +7053,7 @@ static void P_DoNiGHTSCapsule(player_t *player)
tictimer = -1;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && !player->exiting && players[i].mare == player->mare)
if (players[i].ingame && !player->exiting && players[i].mare == player->mare)
{
players[i].bonustime = true;
players[i].texttimer = 4*TICRATE;
......@@ -7025,7 +7070,7 @@ static void P_DoNiGHTSCapsule(player_t *player)
/*for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator || !players[i].mo || !players[i].mo->tracer)
if (!players[i].ingame || players[i].spectator || !players[i].mo || !players[i].mo->tracer)
continue;
emmo = P_SpawnMobj(players[i].mo->x, players[i].mo->y, players[i].mo->z + players[i].mo->info->height, MT_GOTEMERALD);
......@@ -7053,7 +7098,7 @@ static void P_DoNiGHTSCapsule(player_t *player)
// Find the player with the lowest time remaining and award points based on that time instead.
lowest_time = player->finishedtime;
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].powers[pw_carry] == CR_NIGHTSMODE)
if (players[i].ingame && players[i].powers[pw_carry] == CR_NIGHTSMODE)
if (players[i].finishedtime < lowest_time)
lowest_time = players[i].finishedtime;
P_AddPlayerScore(player, (lowest_time/TICRATE) * 100);
......@@ -7086,7 +7131,7 @@ static void P_DoNiGHTSCapsule(player_t *player)
}
}
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mare == player->mare)
if (players[i].ingame && players[i].mare == player->mare)
P_SetTarget(&players[i].capsule, NULL); // Remove capsule from everyone now that it is dead!
S_StartScreamSound(player->mo, sfx_ngdone);
P_SwitchSpheresBonusMode(true);
......@@ -7209,18 +7254,14 @@ static void P_NiGHTSMovement(player_t *player)
boolean capsule = false;
// NiGHTS special stages have a pseudo-shared timer, so check if ANYONE is feeding the capsule.
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] /*&& players[i].powers[pw_carry] == CR_NIGHTSMODE*/
if (players[i].ingame /*&& players[i].powers[pw_carry] == CR_NIGHTSMODE*/
&& (players[i].capsule && players[i].capsule->reactiontime))
capsule = true;
if (!capsule
&& !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1]
&& player->mo->state <= &states[S_PLAY_NIGHTS_TRANS6])
&& !player->exiting)
if (!capsule && !P_IsPlayerInNightsTransformationState(player) && !player->exiting)
player->nightstime--;
}
else if (!(gametyperules & GTR_RACE)
&& !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1]
&& player->mo->state <= &states[S_PLAY_NIGHTS_TRANS6])
&& !P_IsPlayerInNightsTransformationState(player)
&& !(player->capsule && player->capsule->reactiontime)
&& !player->exiting)
player->nightstime--;
......@@ -7236,7 +7277,7 @@ static void P_NiGHTSMovement(player_t *player)
if (mapheaderinfo[gamemap-1]->levelflags & LF_MIXNIGHTSCOUNTDOWN)
{
S_FadeMusic(0, 10*MUSICRATE);
S_StartSound(NULL, sfx_timeup); // that creepy "out of time" music from NiGHTS.
S_StartSoundFromEverywhere(sfx_timeup); // that creepy "out of time" music from NiGHTS.
}
else
P_PlayJingle(player, ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) ? JT_NIGHTSTIMEOUT : JT_SSTIMEOUT);
......@@ -7253,13 +7294,13 @@ static void P_NiGHTSMovement(player_t *player)
if (!player->mo->target)
{
fixed_t dist1, dist2 = 0;
fixed_t dist, closestdist = INT32_MAX;
// scan the thinkers
// to find the closest axis point
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
mo2 = (mobj_t *)th;
......@@ -7269,20 +7310,11 @@ static void P_NiGHTSMovement(player_t *player)
if (mo2->threshold != player->mare)
continue;
if (closestaxis == NULL)
{
closestaxis = mo2;
dist2 = R_PointToDist2(newx, newy, mo2->x, mo2->y) - mo2->radius;
}
else
{
dist1 = R_PointToDist2(newx, newy, mo2->x, mo2->y) - mo2->radius;
if (dist1 < dist2)
dist = GetDistance2D(newx, newy, mo2->x, mo2->y) - mo2->radius;
if (dist < closestdist)
{
closestaxis = mo2;
dist2 = dist1;
}
closestdist = dist;
}
}
P_SetTarget(&player->mo->target, closestaxis);
......@@ -7312,7 +7344,7 @@ static void P_NiGHTSMovement(player_t *player)
if (!(player->pflags & PF_TRANSFERTOCLOSEST))
{
fixed_t realdist = R_PointToDist2(player->mo->x, player->mo->y, player->mo->target->x, player->mo->target->y);
fixed_t realdist = P_GetMobjDistance2D(player->mo, player->mo->target);
// teleport player to correct radius if neccessary
if (realdist>>FRACBITS != radius>>FRACBITS)
{
......@@ -7360,8 +7392,7 @@ static void P_NiGHTSMovement(player_t *player)
return;
}
if (player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1]
&& player->mo->state <= &states[S_PLAY_NIGHTS_TRANS6])
if (P_IsPlayerInNightsTransformationState(player))
{
player->mo->momx = player->mo->momy = player->mo->momz = 0;
player->mo->spriteroll = 0;
......@@ -7380,14 +7411,14 @@ static void P_NiGHTSMovement(player_t *player)
#if 0//def ROTSPRITE
if (!(player->charflags & SF_NONIGHTSROTATION) && player->mo->momz)
{
if (player->mo->state != &states[S_PLAY_NIGHTS_DRILL])
if (!P_IsPlayerInState(player, S_PLAY_NIGHTS_DRILL))
P_SetMobjState(player->mo, S_PLAY_NIGHTS_DRILL);
player->mo->spriteroll = ANGLE_90;
}
else
#endif
{
if (player->mo->state != &states[S_PLAY_NIGHTS_FLOAT])
if (!P_IsPlayerInState(player, S_PLAY_NIGHTS_FLOAT))
P_SetMobjState(player->mo, S_PLAY_NIGHTS_FLOAT);
player->drawangle += ANGLE_22h;
}
......@@ -7561,7 +7592,7 @@ static void P_NiGHTSMovement(player_t *player)
|| (cmd->buttons & BT_SPIN)))
{
if (!(player->pflags & PF_STARTDASH))
S_StartSound(player->mo, sfx_ngskid);
S_StartSoundFromMobj(player->mo, sfx_ngskid);
// You can tap the button to only slow down a bit,
// or hold it to slow to a crawl as before, your choice.
......@@ -7625,11 +7656,11 @@ static void P_NiGHTSMovement(player_t *player)
if (!P_MobjWasRemoved(water))
{
if (player->mo->eflags & MFE_GOOWATER)
S_StartSound(water, sfx_ghit);
S_StartSoundFromMobj(water, sfx_ghit);
else if (player->mo->eflags & MFE_TOUCHLAVA)
S_StartSound(water, sfx_splash);
S_StartSoundFromMobj(water, sfx_splash);
else
S_StartSound(water, sfx_wslap);
S_StartSoundFromMobj(water, sfx_wslap);
if (player->mo->eflags & MFE_VERTICALFLIP)
{
water->flags2 |= MF2_OBJECTFLIP;
......@@ -7663,7 +7694,7 @@ static void P_NiGHTSMovement(player_t *player)
else if (player->angle_pos > player->old_angle_pos)
neg = -1;
movingangle = R_PointToAngle2(0, 0, neg*R_PointToDist2(player->mo->momx, player->mo->momy, 0, 0), player->mo->momz);
movingangle = R_PointToAngle2(0, 0, neg*P_GetMobjMomentum2D(player->mo), player->mo->momz);
player->anotherflyangle = (movingangle >> ANGLETOFINESHIFT) * 360/FINEANGLES;
}
......@@ -7756,7 +7787,7 @@ static void P_NiGHTSMovement(player_t *player)
{
if (firstdrill)
{
S_StartSound(player->mo, sfx_drill1);
S_StartSoundFromMobj(player->mo, sfx_drill1);
player->drilltimer = 32;
}
else if (player->drilltimer == 32)
......@@ -7773,7 +7804,7 @@ static void P_NiGHTSMovement(player_t *player)
else if (player->drilltimer <= 0)
{
player->drilltimer = 10;
S_StartSound(player->mo, sfx_drill2);
S_StartSoundFromMobj(player->mo, sfx_drill2);
}
}
......@@ -7834,11 +7865,10 @@ static void P_PlayerDropWeapon(player_t *player)
void P_BlackOw(player_t *player)
{
INT32 i;
S_StartSound (player->mo, sfx_bkpoof); // Sound the BANG!
S_StartSoundFromMobj(player->mo, sfx_bkpoof); // Sound the BANG!
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && P_AproxDistance(player->mo->x - players[i].mo->x,
player->mo->y - players[i].mo->y) < 1536*FRACUNIT)
if (players[i].ingame && P_AreMobjsClose2D(player->mo, players[i].mo, 1536*FRACUNIT))
P_FlashPal(&players[i], PAL_NUKE, 10);
P_NukeEnemies(player->mo, player->mo, 1536*FRACUNIT); // Search for all nearby enemies and nuke their pants off!
......@@ -7972,7 +8002,7 @@ void P_SpawnSkidDust(player_t *player, fixed_t radius, boolean sound)
P_SetMobjState(particle, S_SPINDUST_FIRE1);
if (sound)
S_StartSound(mo, sfx_s3k7e); // the proper "Knuckles eats dirt" sfx.
S_StartSoundFromMobj(mo, sfx_s3k7e); // the proper "Knuckles eats dirt" sfx.
}
static void P_SkidStuff(player_t *player)
......@@ -8019,7 +8049,7 @@ static void P_SkidStuff(player_t *player)
// Spawn a particle every 3 tics.
if (!(player->skidtime % 3))
{
if (player->mo->state-states == S_PLAY_GLIDE_LANDING)
if (P_IsPlayerInState(player, S_PLAY_GLIDE_LANDING))
P_SpawnSkidDust(player, player->mo->radius, true);
else
P_SpawnSkidDust(player, 0, false);
......@@ -8039,10 +8069,10 @@ static void P_SkidStuff(player_t *player)
// If your push angle is more than this close to a full 180 degrees, trigger a skid.
if (dang > ANGLE_157h)
{
if (player->mo->state-states != S_PLAY_SKID)
if (!P_IsPlayerInState(player, S_PLAY_SKID))
P_SetMobjState(player->mo, S_PLAY_SKID);
player->mo->tics = player->skidtime = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS;
S_StartSound(player->mo, sfx_skid);
S_StartSoundFromMobj(player->mo, sfx_skid);
}
}
}
......@@ -8060,11 +8090,10 @@ void P_MovePlayer(player_t *player)
{
ticcmd_t *cmd;
INT32 i;
boolean spinshieldhack = false; // Hack: Is Spin and Shield bound to the same button (pressed on the same tic)?
fixed_t runspd;
if (player->mo->state >= &states[S_PLAY_SUPER_TRANS1] && player->mo->state <= &states[S_PLAY_SUPER_TRANS6])
if (P_IsPlayerInSuperTransformationState(player))
{
player->mo->momx = player->mo->momy = player->mo->momz = 0;
return;
......@@ -8085,7 +8114,7 @@ void P_MovePlayer(player_t *player)
if ((player->powers[pw_carry] == CR_BRAKGOOP)
|| (player->pflags & PF_GLIDING && player->skidtime)
|| (player->charability2 == CA2_GUNSLINGER && player->panim == PA_ABILITY2)
|| (player->charability2 == CA2_MELEE && player->mo->state-states == S_PLAY_MELEE_LANDING))
|| (player->charability2 == CA2_MELEE && P_IsPlayerInState(player, S_PLAY_MELEE_LANDING)))
player->pflags |= PF_FULLSTASIS;
else if (player->powers[pw_nocontrol])
{
......@@ -8094,7 +8123,7 @@ void P_MovePlayer(player_t *player)
player->pflags |= PF_JUMPSTASIS;
}
if (player->charability == CA_GLIDEANDCLIMB && player->mo->state-states == S_PLAY_GLIDE_LANDING)
if (player->charability == CA_GLIDEANDCLIMB && P_IsPlayerInState(player, S_PLAY_GLIDE_LANDING))
{
player->pflags |= PF_STASIS;
}
......@@ -8159,7 +8188,7 @@ void P_MovePlayer(player_t *player)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
mo2 = (mobj_t *)th;
......@@ -8200,9 +8229,9 @@ void P_MovePlayer(player_t *player)
if (G_IsSpecialStage(gamemap))
{
if (player == &players[displayplayer]) // only play the sound for yourself landing
S_StartSound(NULL, sfx_s3k6a);
S_StartSoundFromEverywhere(sfx_s3k6a);
for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i])
if (players[i].ingame)
players[i].exiting = (14*TICRATE)/5 + 1;
}
else {
......@@ -8312,9 +8341,9 @@ void P_MovePlayer(player_t *player)
// Correct floating when ending up on the ground.
if (onground)
{
if (player->mo->state-states == S_PLAY_FLOAT)
if (P_IsPlayerInState(player, S_PLAY_FLOAT))
P_SetMobjState(player->mo, S_PLAY_WALK);
else if (player->mo->state-states == S_PLAY_FLOAT_RUN)
else if (P_IsPlayerInState(player, S_PLAY_FLOAT_RUN))
P_SetMobjState(player->mo, S_PLAY_RUN);
}
......@@ -8380,7 +8409,7 @@ void P_MovePlayer(player_t *player)
fixed_t glidespeed = player->actionspd;
fixed_t momx = mo->momx - player->cmomx, momy = mo->momy - player->cmomy;
angle_t angle, moveangle = R_PointToAngle2(0, 0, momx, momy);
boolean swimming = mo->state - states == S_PLAY_SWIM;
boolean swimming = P_IsPlayerInState(player, S_PLAY_SWIM);
boolean in2d = mo->flags2 & MF2_TWOD || twodlevel;
if (player->powers[pw_super] || player->powers[pw_sneakers])
......@@ -8443,7 +8472,7 @@ void P_MovePlayer(player_t *player)
}
else
{
fixed_t newMagnitude, oldMagnitude = R_PointToDist2(momx, momy, 0, 0);
fixed_t newMagnitude, oldMagnitude = GetDistance2D(0, 0, momx, momy);
if (mo->eflags & MFE_UNDERWATER)
speed = FixedMul((glidespeed>>1) + player->glidetime*750, scale);
......@@ -8452,7 +8481,7 @@ void P_MovePlayer(player_t *player)
P_Thrust(mo, angle, FixedMul(accelfactor, scale));
newMagnitude = R_PointToDist2(player->mo->momx - player->cmomx, player->mo->momy - player->cmomy, 0, 0);
newMagnitude = GetDistance2D(player->mo->momx, player->mo->momy, player->cmomx, player->cmomy);
if (newMagnitude > speed)
{
fixed_t tempmomx, tempmomy;
......@@ -8527,7 +8556,7 @@ void P_MovePlayer(player_t *player)
}
}
}
else if (player->mo->state-states == S_PLAY_BOUNCE)
else if (P_IsPlayerInState(player, S_PLAY_BOUNCE))
P_SetMobjState(player->mo, S_PLAY_FALL);
// If you're running fast enough, you can create splashes as you run in shallow water.
......@@ -8543,11 +8572,11 @@ void P_MovePlayer(player_t *player)
if (!P_MobjWasRemoved(water))
{
if (player->mo->eflags & MFE_GOOWATER)
S_StartSound(water, sfx_ghit);
S_StartSoundFromMobj(water, sfx_ghit);
else if (player->mo->eflags & MFE_TOUCHLAVA)
S_StartSound(water, sfx_splash);
S_StartSoundFromMobj(water, sfx_splash);
else
S_StartSound(water, sfx_wslap);
S_StartSoundFromMobj(water, sfx_wslap);
if (player->mo->eflags & MFE_VERTICALFLIP)
{
water->flags2 |= MF2_OBJECTFLIP;
......@@ -8561,7 +8590,7 @@ void P_MovePlayer(player_t *player)
if ((player->mo->eflags & MFE_TOUCHWATER) && !(player->mo->eflags & MFE_UNDERWATER) && !player->spectator)
{
if (P_RandomChance(FRACUNIT/2) && leveltime % TICRATE == 0)
S_StartSound(player->mo, sfx_floush);
S_StartSoundFromMobj(player->mo, sfx_floush);
}
////////////////
......@@ -8571,7 +8600,7 @@ void P_MovePlayer(player_t *player)
if (!(player->charability == CA_FLY || player->charability == CA_SWIM)) // why are you flying when you cannot fly?!
{
if (player->powers[pw_tailsfly]
|| player->mo->state-states == S_PLAY_FLY_TIRED)
|| P_IsPlayerInState(player, S_PLAY_FLY_TIRED))
{
if (onground)
P_SetMobjState(player->mo, S_PLAY_WALK);
......@@ -8624,7 +8653,7 @@ void P_MovePlayer(player_t *player)
&& !(player->mo->eflags & MFE_UNDERWATER)
&& leveltime % 10 == 0
&& !player->spectator)
S_StartSound(player->mo, sfx_putput);
S_StartSoundFromMobj(player->mo, sfx_putput);
// Descend
if (cmd->buttons & BT_SPIN && !(player->pflags & PF_STASIS) && !player->exiting && !(player->mo->eflags & MFE_GOOWATER))
......@@ -8639,14 +8668,14 @@ void P_MovePlayer(player_t *player)
else
{
// Tails-gets-tired Stuff
if (player->panim == PA_ABILITY && player->mo->state-states != S_PLAY_FLY_TIRED)
if (player->panim == PA_ABILITY && !P_IsPlayerInState(player, S_PLAY_FLY_TIRED))
P_SetMobjState(player->mo, S_PLAY_FLY_TIRED);
if (player->charability == CA_FLY && (leveltime % 10 == 0)
&& player->mo->state-states == S_PLAY_FLY_TIRED
&& P_IsPlayerInState(player, S_PLAY_FLY_TIRED)
&& !(player->mo->eflags & MFE_UNDERWATER)
&& !player->spectator)
S_StartSound(player->mo, sfx_pudpud);
S_StartSoundFromMobj(player->mo, sfx_pudpud);
}
}
......@@ -8682,13 +8711,10 @@ void P_MovePlayer(player_t *player)
&& !(player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)))
P_ElementalFire(player, false);
if ((cmd->buttons & (BT_SPIN|BT_SHIELD)) == (BT_SPIN|BT_SHIELD) && !(player->pflags & (PF_SPINDOWN|PF_SHIELDDOWN)))
spinshieldhack = true; // Spin and Shield is bound to the same button (pressed on the same tic), so enable two-button play (Jump and Spin+Shield)
P_DoSpinAbility(player, cmd);
// jumping
P_DoJumpStuff(player, cmd, spinshieldhack);
P_DoJumpStuff(player, cmd);
// If you're not spinning, you'd better not be spindashing!
if (!(player->pflags & PF_SPINNING) && player->powers[pw_carry] != CR_NIGHTSMODE)
......@@ -8741,7 +8767,7 @@ void P_MovePlayer(player_t *player)
}
// Otherwise, face the direction you're travelling.
else if (player->panim == PA_WALK || player->panim == PA_RUN || player->panim == PA_DASH || player->panim == PA_ROLL || player->panim == PA_JUMP
|| (player->panim == PA_ABILITY && player->mo->state-states == S_PLAY_GLIDE))
|| (player->panim == PA_ABILITY && P_IsPlayerInState(player, S_PLAY_GLIDE)))
player->mo->angle = R_PointToAngle2(0, 0, player->rmomx, player->rmomy);
// Update the local angle control.
......@@ -8776,25 +8802,10 @@ void P_MovePlayer(player_t *player)
P_PlayerFlagBurst(player, true);
}
// Check for fire and shield buttons
// check for fire
if (!player->exiting)
{
P_DoFiring(player, cmd);
// Shield button behavior
// Check P_PlayerShieldThink for actual shields!
if ((cmd->buttons & BT_SHIELD) && !(player->pflags & PF_SHIELDDOWN) && !spinshieldhack)
{
// Transform into super if we can!
if (P_SuperReady(player, true))
P_DoSuperTransformation(player, false);
// Detransform from super if we can!
else if (P_SuperReady(player, false))
P_DoSuperDetransformation(player);
}
}
{
boolean atspinheight = false;
fixed_t oldheight = player->mo->height;
......@@ -8812,6 +8823,8 @@ void P_MovePlayer(player_t *player)
player->mo->height = P_GetPlayerSpinHeight(player);
atspinheight = true;
}
else if (player->powers[pw_carry] == CR_PLAYER || player->powers[pw_carry] == CR_PTERABYTE) // You're slightly shorter while being carried
player->mo->height = FixedDiv(P_GetPlayerHeight(player), FixedDiv(14*FRACUNIT,10*FRACUNIT));
else
player->mo->height = P_GetPlayerHeight(player);
......@@ -8848,7 +8861,7 @@ void P_MovePlayer(player_t *player)
fixed_t speed;
const fixed_t runnyspeed = 20*FRACUNIT;
speed = R_PointToDist2(player->rmomx, player->rmomy, 0, 0);
speed = GetDistance2D(0, 0, player->rmomx, player->rmomy);
if (speed > player->normalspeed-5*FRACUNIT)
speed = player->normalspeed-5*FRACUNIT;
......@@ -8901,7 +8914,7 @@ static void P_DoZoomTube(player_t *player)
speed = abs(player->speed);
// change slope
dist = P_AproxDistance(P_AproxDistance(player->mo->tracer->x - player->mo->x, player->mo->tracer->y - player->mo->y), player->mo->tracer->z - player->mo->z);
dist = P_GetMobjDistance3D(player->mo->tracer, player->mo);
if (dist < 1)
dist = 1;
......@@ -8942,7 +8955,7 @@ static void P_DoZoomTube(player_t *player)
// calculate MOMX/MOMY/MOMZ for next waypoint
// change slope
dist = P_AproxDistance(P_AproxDistance(player->mo->tracer->x - player->mo->x, player->mo->tracer->y - player->mo->y), player->mo->tracer->z - player->mo->z);
dist = P_GetMobjDistance3D(player->mo->tracer, player->mo);
if (dist < 1)
dist = 1;
......@@ -8986,7 +8999,7 @@ static void P_DoRopeHang(player_t *player)
// Play the 'clink' sound only if the player is moving.
if (!(leveltime & 7) && player->speed)
S_StartSound(player->mo, sfx_s3k55);
S_StartSoundFromMobj(player->mo, sfx_s3k55);
playerz = player->mo->z + player->mo->height;
......@@ -8995,7 +9008,7 @@ static void P_DoRopeHang(player_t *player)
sequence = player->mo->tracer->threshold;
// change slope
dist = P_AproxDistance(P_AproxDistance(player->mo->tracer->x - player->mo->x, player->mo->tracer->y - player->mo->y), player->mo->tracer->z - playerz);
dist = GetDistance3D(player->mo->tracer->x, player->mo->tracer->y, player->mo->tracer->z, player->mo->x, player->mo->y, playerz);
if (dist < 1)
dist = 1;
......@@ -9015,7 +9028,7 @@ static void P_DoRopeHang(player_t *player)
return;
}
if (player->mo->state-states != S_PLAY_RIDE)
if (!P_IsPlayerInState(player, S_PLAY_RIDE))
P_SetMobjState(player->mo, S_PLAY_RIDE);
// If not allowed to move, we're done here.
......@@ -9058,7 +9071,7 @@ static void P_DoRopeHang(player_t *player)
// calculate MOMX/MOMY/MOMZ for next waypoint
// change slope
dist = P_AproxDistance(P_AproxDistance(player->mo->tracer->x - player->mo->x, player->mo->tracer->y - player->mo->y), player->mo->tracer->z - playerz);
dist = GetDistance3D(player->mo->tracer->x, player->mo->tracer->y, player->mo->tracer->z, player->mo->x, player->mo->y, playerz);
if (dist < 1)
dist = 1;
......@@ -9097,7 +9110,7 @@ static void P_NukeAllPlayers(player_t *player)
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
if (!players[i].ingame)
continue;
if (players[i].spectator)
continue;
......@@ -9142,7 +9155,7 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius)
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (think->removing)
continue;
mo = (mobj_t *)think;
......@@ -9159,7 +9172,7 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius)
if (abs(inflictor->x - mo->x) > radius || abs(inflictor->y - mo->y) > radius || abs(inflictor->z - mo->z) > radius)
continue; // Workaround for possible integer overflow in the below -Red
if (P_AproxDistance(P_AproxDistance(inflictor->x - mo->x, inflictor->y - mo->y), inflictor->z - mo->z) > radius)
if (P_AreMobjsFar3D(inflictor, mo, radius))
continue;
if (mo->type == MT_MINUS && !(mo->flags & (MF_SPECIAL|MF_SHOOTABLE)))
......@@ -9240,7 +9253,7 @@ mobj_t *P_LookForFocusTarget(player_t *player, mobj_t *exclude, SINT8 direction,
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (think->removing)
continue;
mo = (mobj_t *)think;
......@@ -9288,14 +9301,18 @@ mobj_t *P_LookForFocusTarget(player_t *player, mobj_t *exclude, SINT8 direction,
continue; // not a valid object
}
// Early check to prevent integer overflow across large distances
if (P_AreMobjsFar2D(player->mo, mo, maxdist))
continue;
{
fixed_t xydist = P_GetMobjDistance2D(player->mo, mo);
fixed_t zdist = (player->mo->z + player->mo->height/2) - (mo->z + mo->height/2);
dist = P_AproxDistance(player->mo->x-mo->x, player->mo->y-mo->y);
if (abs(zdist) > dist)
if (abs(zdist) > xydist)
continue; // Don't home outside of desired angle!
dist = P_AproxDistance(dist, zdist);
dist = GetDistance2D(0, 0, xydist, zdist);
if (dist > maxdist)
continue; // out of range
}
......@@ -9359,7 +9376,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet)
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{
if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (think->removing)
continue;
mo = (mobj_t *)think;
......@@ -9385,9 +9402,13 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet)
if (!bullet && mo->type == MT_DETON) // Don't be STUPID, Sonic!
continue;
// Early check to prevent integer overflow across large distances
if (P_AreMobjsFar2D(player->mo, mo, maxdist))
continue;
{
fixed_t zdist = (player->mo->z + player->mo->height/2) - (mo->z + mo->height/2);
dist = R_PointToDist2(0, 0, player->mo->x-mo->x, player->mo->y-mo->y);
dist = P_GetMobjDistance2D(mo, player->mo);
if (bullet)
{
if ((R_PointToAngle2(0, 0, dist, zdist) + span) > span*2)
......@@ -9404,7 +9425,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet)
continue;
}
dist = R_PointToDist2(0, 0, dist, zdist);
dist = GetDistance2D(0, 0, dist, zdist);
if (dist > maxdist)
continue; // out of range
}
......@@ -9464,7 +9485,7 @@ boolean P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target
// change slope
zdist = ((P_MobjFlip(source) == -1) ? (enemy->z + enemy->height) - (source->z + source->height) : (enemy->z - source->z));
dist = P_AproxDistance(P_AproxDistance(enemy->x - source->x, enemy->y - source->y), zdist);
dist = GetDistance3D(0, 0, 0, enemy->x - source->x, enemy->y - source->y, zdist);
if (dist < 1)
dist = 1;
......@@ -9505,7 +9526,7 @@ void P_FindEmerald(void)
// to find all emeralds
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
mo2 = (mobj_t *)th;
......@@ -9550,7 +9571,7 @@ boolean P_GetLives(player_t *player)
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
if (!players[i].ingame)
continue;
if (players[i].lives > livescheck)
......@@ -9562,7 +9583,7 @@ boolean P_GetLives(player_t *player)
if (maxlivesplayer != -1 && &players[maxlivesplayer] != player)
{
if (cv_cooplives.value == 2 && (P_IsLocalPlayer(player) || P_IsLocalPlayer(&players[maxlivesplayer])))
S_StartSound(NULL, sfx_jshard); // placeholder
S_StartSoundFromEverywhere(sfx_jshard); // placeholder
if (players[maxlivesplayer].lives != INFLIVES)
players[maxlivesplayer].lives--;
player->lives++;
......@@ -9587,7 +9608,7 @@ static void P_ConsiderAllGone(void)
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
if (!players[i].ingame)
continue;
if (players[i].playerstate != PST_DEAD && !players[i].spectator && players[i].mo && players[i].mo->health)
......@@ -9667,7 +9688,7 @@ static void P_DeathThink(player_t *player)
{
for (j = 0; j < MAXPLAYERS; j++)
{
if (!playeringame[j])
if (!players[j].ingame)
continue;
if (players[j].lives > 1)
......@@ -9728,7 +9749,7 @@ static void P_DeathThink(player_t *player)
{
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i])
if (!players[i].ingame)
continue;
if (!players[i].exiting && players[i].lives)
break;
......@@ -9813,7 +9834,7 @@ static CV_PossibleValue_t campos_cons_t[] = { {INT32_MIN, "MIN"}, {INT32_MAX, "M
consvar_t cv_cam_dist = CVAR_INIT ("cam_curdist", "160", CV_FLOAT|CV_ALLOWLUA, campos_cons_t, NULL);
consvar_t cv_cam_height = CVAR_INIT ("cam_curheight", "25", CV_FLOAT|CV_ALLOWLUA, campos_cons_t, NULL);
consvar_t cv_cam_still = CVAR_INIT ("cam_still", "Off", CV_ALLOWLUA, CV_OnOff, NULL);
consvar_t cv_cam_speed = CVAR_INIT ("cam_speed", "0.3", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, CV_CamSpeed, NULL);
consvar_t cv_cam_speed = CVAR_INIT ("cam_speed", "0.4", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, CV_CamSpeed, NULL);
consvar_t cv_cam_rotate = CVAR_INIT ("cam_rotate", "0", CV_CALL|CV_NOINIT|CV_ALLOWLUA, CV_CamRotate, CV_CamRotate_OnChange);
consvar_t cv_cam_rotspeed = CVAR_INIT ("cam_rotspeed", "10", CV_SAVE|CV_ALLOWLUA, rotation_cons_t, NULL);
consvar_t cv_cam_turnmultiplier = CVAR_INIT ("cam_turnmultiplier", "0.75", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, multiplier_cons_t, NULL);
......@@ -9822,7 +9843,7 @@ consvar_t cv_cam_adjust = CVAR_INIT ("cam_adjust", "On", CV_SAVE|CV_ALLOWLUA, CV
consvar_t cv_cam2_dist = CVAR_INIT ("cam2_curdist", "160", CV_FLOAT|CV_ALLOWLUA, campos_cons_t, NULL);
consvar_t cv_cam2_height = CVAR_INIT ("cam2_curheight", "25", CV_FLOAT|CV_ALLOWLUA, campos_cons_t, NULL);
consvar_t cv_cam2_still = CVAR_INIT ("cam2_still", "Off", CV_ALLOWLUA, CV_OnOff, NULL);
consvar_t cv_cam2_speed = CVAR_INIT ("cam2_speed", "0.3", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, CV_CamSpeed, NULL);
consvar_t cv_cam2_speed = CVAR_INIT ("cam2_speed", "0.4", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, CV_CamSpeed, NULL);
consvar_t cv_cam2_rotate = CVAR_INIT ("cam2_rotate", "0", CV_CALL|CV_NOINIT|CV_ALLOWLUA, CV_CamRotate, CV_CamRotate2_OnChange);
consvar_t cv_cam2_rotspeed = CVAR_INIT ("cam2_rotspeed", "10", CV_SAVE|CV_ALLOWLUA, rotation_cons_t, NULL);
consvar_t cv_cam2_turnmultiplier = CVAR_INIT ("cam2_turnmultiplier", "0.75", CV_FLOAT|CV_SAVE|CV_ALLOWLUA, multiplier_cons_t, NULL);
......@@ -9929,7 +9950,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
boolean camstill, cameranoclip, camorbit;
mobj_t *mo, *sign = NULL;
subsector_t *newsubsec;
fixed_t f1, f2;
static fixed_t camsideshift[2] = {0, 0};
fixed_t shiftx = 0, shifty = 0;
......@@ -9952,9 +9972,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
&& !((gametyperules & GTR_FRIENDLY) && (netgame || multiplayer) && cv_exitmove.value)
&& !(twodlevel || (mo->flags2 & MF2_TWOD)))
sign = mo->target;
else if ((player->powers[pw_carry] == CR_NIGHTSMODE)
&& !(player->mo->state >= &states[S_PLAY_NIGHTS_TRANS1]
&& player->mo->state <= &states[S_PLAY_NIGHTS_TRANS6]))
else if (player->powers[pw_carry] == CR_NIGHTSMODE && !P_IsPlayerInNightsTransformationState(player))
{
P_CalcChasePostImg(player, thiscam);
return true;
......@@ -9965,15 +9983,42 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
if (!(player->climbing || (player->powers[pw_carry] == CR_NIGHTSMODE) || player->playerstate == PST_DEAD || tutorialmode))
{
if (player->spectator) // force cam off for spectators
return true;
if (player->spectator || !thiscam->chase)
{
// set the values to the player's values so they can still be used
thiscam->x = player->mo->x;
thiscam->y = player->mo->y;
thiscam->z = player->viewz;
thiscam->momx = player->mo->momx;
thiscam->momy = player->mo->momy;
thiscam->momz = player->mo->momz;
if (!cv_chasecam.value && thiscam == &camera)
return true;
if (thiscam == &camera)
{
// when not spectating, use local angles
if (&players[displayplayer] == &players[consoleplayer]) {
thiscam->angle = localangle;
thiscam->aiming = localaiming;
}
else
{
thiscam->angle = players[displayplayer].cmd.angleturn << 16;
thiscam->aiming = players[displayplayer].cmd.aiming << 16;
}
}
else if (thiscam == &camera2)
{
// i dont think secondarydisplayplayer changes, so we should be fine.
thiscam->angle = localangle2;
thiscam->aiming = localaiming2;
}
if (!cv_chasecam2.value && thiscam == &camera2)
thiscam->subsector = player->mo->subsector;
thiscam->floorz = player->mo->floorz;
thiscam->ceilingz = player->mo->ceilingz;
return true;
}
}
if (!thiscam->chase && !resetcalled)
{
......@@ -10539,9 +10584,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
}
// compute aming to look the viewed point
f1 = viewpointx-thiscam->x;
f2 = viewpointy-thiscam->y;
dist = FixedHypot(f1, f2);
dist = GetDistance2D(viewpointx, viewpointy, thiscam->x, thiscam->y);
if (mo->eflags & MFE_VERTICALFLIP)
angle = R_PointToAngle2(0, thiscam->z + thiscam->height, dist, (sign ? sign->ceilingz : mo->z + mo->height) - P_GetPlayerHeight(player));
......@@ -10570,8 +10613,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
}
/* check z distance too for orbital camera */
if (P_AproxDistance(P_AproxDistance(vx - mo->x, vy - mo->y),
vz - ( mo->z + mo->height / 2 )) < FixedMul(48*FRACUNIT, mo->scale))
if (ArePointsClose3D(vx, vy, vz, mo->x, mo->y, mo->z + mo->height / 2, FixedMul(48*FRACUNIT, mo->scale)))
mo->flags2 |= MF2_SHADOW;
else
mo->flags2 &= ~MF2_SHADOW;
......@@ -10625,7 +10667,7 @@ boolean P_SpectatorJoinGame(player_t *player)
//find a team by num players, score, or random if all else fails.
for (z = 0; z < MAXPLAYERS; ++z)
if (playeringame[z])
if (players[z].ingame)
{
if (players[z].ctfteam == 1)
++numplayersred;
......@@ -10836,7 +10878,7 @@ void P_DoPityCheck(player_t *player)
P_SwitchShield(player, SH_PITY);
if (player->pity > 0)
S_StartSound(player->mo, mobjinfo[MT_PITY_ICON].seesound);
S_StartSoundFromMobj(player->mo, mobjinfo[MT_PITY_ICON].seesound);
player->pity = 0;
}
......@@ -10906,7 +10948,7 @@ static mobj_t *P_GetAxis(INT32 num)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
mobj = (mobj_t *)th;
......@@ -10944,7 +10986,7 @@ static void P_GetAxisPosition(fixed_t x, fixed_t y, mobj_t *amo, fixed_t *newx,
y = ay;
else // Diagonal lines
{
fixed_t distance = R_PointToDist2(ax, ay, x, y);
fixed_t distance = GetDistance2D(ax, ay, x, y);
angle_t fad = ((R_PointToAngle2(ax, ay, x, y) - ang) >> ANGLETOFINESHIFT) & FINEMASK;
fixed_t cosine = FINECOSINE(fad);
angle_t fa = (ang >> ANGLETOFINESHIFT) & FINEMASK;
......@@ -10956,7 +10998,7 @@ static void P_GetAxisPosition(fixed_t x, fixed_t y, mobj_t *amo, fixed_t *newx,
else // Keep minecart to circle
{
fixed_t rad = amo->radius;
fixed_t distfactor = FixedDiv(rad, R_PointToDist2(ax, ay, x, y));
fixed_t distfactor = FixedDiv(rad, GetDistance2D(ax, ay, x, y));
gr = R_PointToAngle2(ax, ay, x, y);
ang = gr + ANGLE_90;
......@@ -10999,7 +11041,7 @@ static void P_SpawnSparks(mobj_t *mo, angle_t maindir)
static mobj_t *P_LookForRails(mobj_t* mobj, fixed_t c, fixed_t s, angle_t targetangle, fixed_t xcom, fixed_t ycom)
{
INT16 interval = 16;
INT16 fwooffset = FixedHypot(mobj->momx, mobj->momy) >> FRACBITS;
INT16 fwooffset = P_GetMobjMomentum2D(mobj) >> FRACBITS;
fixed_t x = mobj->x;
fixed_t y = mobj->y;
fixed_t z = mobj->z;
......@@ -11040,7 +11082,7 @@ static void P_ParabolicMove(mobj_t *mo, fixed_t x, fixed_t y, fixed_t z, fixed_t
fixed_t dx = x - mo->x;
fixed_t dy = y - mo->y;
fixed_t dz = z - mo->z;
fixed_t dh = P_AproxDistance(dx, dy);
fixed_t dh = P_AproxDistance(dx, dy); // LJ: Kept on purpose or the minecart doesn't always land on the track after jumping
fixed_t c = FixedDiv(dx, dh);
fixed_t s = FixedDiv(dy, dh);
fixed_t fixConst = FixedDiv(speed, g);
......@@ -11111,7 +11153,7 @@ static void P_MinecartThink(player_t *player)
if (minecart->eflags & MFE_JUSTHITFLOOR)
{
S_StopSound(minecart);
S_StartSound(minecart, sfx_s3k96);
S_StartSoundFromMobj(minecart, sfx_s3k96);
}
sec = P_GetMinecartSector(minecart->x, minecart->y, minecart->z, &dummy);
......@@ -11172,7 +11214,7 @@ static void P_MinecartThink(player_t *player)
}
// How fast are we going?
currentSpeed = FixedHypot(minecart->momx, minecart->momy);
currentSpeed = P_GetMobjMomentum2D(minecart);
angdiff = R_PointToAngle2(0, 0, minecart->momx, minecart->momy) - minecart->angle;
if (angdiff > ANGLE_90 && angdiff < ANGLE_270)
currentSpeed *= -1;
......@@ -11199,7 +11241,7 @@ static void P_MinecartThink(player_t *player)
else
minecart->momz = 10 * FRACUNIT;
S_StartSound(minecart, sfx_s3k51);
S_StartSoundFromMobj(minecart, sfx_s3k51);
jumped = true;
}
......@@ -11227,7 +11269,7 @@ static void P_MinecartThink(player_t *player)
if (minecart->movecount > 128*FRACUNIT)
{
minecart->movecount %= 128*FRACUNIT;
S_StartSound(minecart, minecart->info->activesound);
S_StartSoundFromMobj(minecart, minecart->info->activesound);
}
}
......@@ -11271,7 +11313,7 @@ static void P_MinecartThink(player_t *player)
}
}
if (player->mo->state-states != S_PLAY_STND)
if (!P_IsPlayerInState(player, S_PLAY_STND))
{
P_SetMobjState(player->mo, S_PLAY_STND);
player->mo->tics = -1;
......@@ -11349,12 +11391,12 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails)
}
else if (player->panim == PA_PAIN)
backwards /= 16;
else if (player->mo->state-states == S_PLAY_GASP)
else if (P_IsPlayerInState(player, S_PLAY_GASP))
{
backwards /= 16;
zoffs += 12*FRACUNIT;
}
else if (player->mo->state-states == S_PLAY_EDGE)
else if (P_IsPlayerInState(player, S_PLAY_EDGE))
{
backwards /= 16;
zoffs = 3*FRACUNIT;
......@@ -11383,13 +11425,13 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails)
}
else if (player->panim == PA_SPRING || player->panim == PA_JUMP)
chosenstate = S_TAILSOVERLAY_MINUS60DEGREES;
else if (player->panim == PA_FALL || player->mo->state-states == S_PLAY_RIDE)
else if (player->panim == PA_FALL || P_IsPlayerInState(player, S_PLAY_RIDE))
chosenstate = S_TAILSOVERLAY_PLUS60DEGREES;
else if (player->panim == PA_PAIN)
chosenstate = S_TAILSOVERLAY_PAIN;
else if (player->mo->state-states == S_PLAY_GASP)
else if (P_IsPlayerInState(player, S_PLAY_GASP))
chosenstate = S_TAILSOVERLAY_GASP;
else if (player->mo->state-states == S_PLAY_EDGE)
else if (P_IsPlayerInState(player, S_PLAY_EDGE))
chosenstate = S_TAILSOVERLAY_EDGE;
else if (player->panim == PA_DASH)
chosenstate = S_TAILSOVERLAY_DASH;
......@@ -11397,7 +11439,7 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails)
chosenstate = S_TAILSOVERLAY_RUN;
else if (player->panim == PA_WALK)
{
if (!smilesonground || player->mo->state-states == S_PLAY_SKID)
if (!smilesonground || P_IsPlayerInState(player, S_PLAY_SKID))
chosenstate = S_TAILSOVERLAY_PLUS30DEGREES;
else if (player->speed >= FixedMul(player->runspeed/2, player->mo->scale))
chosenstate = S_TAILSOVERLAY_0DEGREES;
......@@ -11439,7 +11481,7 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails)
#endif
// animation...
if (player->panim == PA_SPRING || player->panim == PA_FALL || player->mo->state-states == S_PLAY_RIDE)
if (player->panim == PA_SPRING || player->panim == PA_FALL || P_IsPlayerInState(player, S_PLAY_RIDE))
{
if (FixedDiv(abs(player->mo->momz), player->mo->scale) < 20<<FRACBITS)
ticnum = 2;
......@@ -11448,7 +11490,7 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails)
}
else if (player->panim == PA_PAIN)
ticnum = 2;
else if (player->mo->state-states == S_PLAY_GASP)
else if (P_IsPlayerInState(player, S_PLAY_GASP))
tails->tics = -1;
else if (player->mo->sprite2 == SPR2_TIRE)
ticnum = (doswim ? 2 : 4);
......@@ -11495,6 +11537,18 @@ void P_DoTailsOverlay(player_t *player, mobj_t *tails)
}
// Metal Sonic's jet fume
//
// The follow object's state is set to its spawn state when deactivated.
// When the player is on a moving animation, the follow object goes to its see state.
// When dash mode is entered, the follow object switches to its melee state.
//
// If MF2_FRET is set, the jet fume will flash during dash mode.
// MF2_AMBUSH can be used to enable Metal Sonic's skidding animation.
// MF2_JUSTATTACKED will enable the color cycling.
// If the follow item is MT_METALJETFUME, the above two effects are automatically applied.
//
// MF2_STRONGBOX is internally used to track if the jet fume is in its deactivated state or not.
// MF2_BOSSNOTRAP is internally used to instantly reset the jet fume's scale to its intended scale.
void P_DoMetalJetFume(player_t *player, mobj_t *fume)
{
static const UINT8 FUME_SKINCOLORS[] =
......@@ -11521,17 +11575,30 @@ void P_DoMetalJetFume(player_t *player, mobj_t *fume)
fixed_t heightoffset = ((mo->eflags & MFE_VERTICALFLIP) ? mo->height - (P_GetPlayerHeight(player) >> 1) : (P_GetPlayerHeight(player) >> 1));
panim_t panim = player->panim;
tic_t dashmode = min(player->dashmode, DASHMODE_MAX);
boolean ismetaljetfume = fume->type == MT_METALJETFUME;
boolean notmoving = panim != PA_WALK && panim != PA_RUN && panim != PA_DASH;
boolean underwater = mo->eflags & MFE_UNDERWATER;
statenum_t stat = fume->state-states;
boolean resetinterp = false;
if (panim != PA_WALK && panim != PA_RUN && panim != PA_DASH) // turn invisible when not in a coherent movement state
if (notmoving) // deactivate when not in a coherent movement state
{
if ((fume->flags2 & MF2_STRONGBOX) == 0)
{
if (stat != fume->info->spawnstate)
P_SetMobjState(fume, fume->info->spawnstate);
fume->flags2 |= MF2_STRONGBOX;
}
if (P_MobjWasRemoved(fume) || ismetaljetfume)
return;
}
// Rotate on skid animation if follow item is MT_METALJETFUME, or if MF2_AMBUSH is set
if (player->mo->sprite2 == SPR2_SKID)
{
if ((ismetaljetfume && (player->charflags & SF_JETFUME)) || (fume->flags2 & MF2_AMBUSH))
angle += ANGLE_90;
}
if (underwater) // No fume underwater; spawn bubbles instead!
{
fume->movedir += FixedAngle(FixedDiv(2 * player->speed, 3 * mo->scale));
......@@ -11567,54 +11634,82 @@ void P_DoMetalJetFume(player_t *player, mobj_t *fume)
if (panim == PA_WALK)
{
if (stat != fume->info->spawnstate)
if ((fume->flags2 & MF2_STRONGBOX) == 0)
{
fume->threshold = 0;
P_SetMobjState(fume, fume->info->spawnstate);
fume->threshold = 0;
fume->flags2 &= ~MF2_STRONGBOX;
}
if (P_MobjWasRemoved(fume) || ismetaljetfume)
return;
}
}
if (stat == fume->info->spawnstate) // If currently inivisble, activate!
// If currently deactivated, activate!
if (!notmoving && !underwater && (fume->flags2 & MF2_STRONGBOX))
{
P_SetMobjState(fume, (stat = fume->info->seestate));
if (P_MobjWasRemoved(fume))
return;
P_SetScale(fume, mo->scale, false);
fume->flags2 &= ~MF2_STRONGBOX;
resetinterp = true;
}
if (dashmode > DASHMODE_THRESHOLD && stat != fume->info->seestate) // If in dashmode, grow really big and flash
// If in dash mode, grow really big
if (dashmode > DASHMODE_THRESHOLD && stat != fume->info->meleestate)
{
fume->destscale = mo->scale;
fume->flags2 ^= MF2_DONTDRAW;
fume->flags2 |= mo->flags2 & MF2_DONTDRAW;
// Flash if follow item is MT_METALJETFUME, or if MF2_FRET is set
if (ismetaljetfume || (fume->flags2 & MF2_FRET))
fume->flags2 ^= MF2_DONTDRAW;
}
else // Otherwise, pick a size and color depending on speed and proximity to dashmode
{
if (dashmode == DASHMODE_THRESHOLD && dashmode > (tic_t)fume->movecount) // If just about to enter dashmode, play the startup animation again
// If just about to enter dash mode, play the startup animation again
if (dashmode == DASHMODE_THRESHOLD && dashmode > (tic_t)fume->movecount)
{
P_SetMobjState(fume, (stat = fume->info->seestate));
P_SetMobjState(fume, fume->info->meleestate);
if (P_MobjWasRemoved(fume))
return;
P_SetScale(fume, 2*mo->scale, true);
}
fume->flags2 = (fume->flags2 & ~MF2_DONTDRAW) | (mo->flags2 & MF2_DONTDRAW);
fume->destscale = (mo->scale + FixedDiv(player->speed, player->normalspeed)) / (underwater ? 6 : 3);
// Do color cycling if follow item is MT_METALJETFUME, or if MF2_JUSTATTACKED is set
if (ismetaljetfume || (fume->flags2 & MF2_JUSTATTACKED))
fume->color = FUME_SKINCOLORS[(dashmode * sizeof(FUME_SKINCOLORS)) / (DASHMODE_MAX + 1)];
if (underwater)
{
fume->frame = (fume->frame & FF_FRAMEMASK) | FF_ANIMATE | (P_RandomRange(0, 9) * FF_TRANS10);
fume->frame = (fume->frame & ~FF_TRANSMASK) | (P_RandomRange(0, 9) << FF_TRANSSHIFT);
fume->threshold = 1;
}
else if (fume->threshold)
{
fume->frame = (fume->frame & FF_FRAMEMASK) | fume->state->frame;
fume->frame = (fume->frame & FF_FRAMEMASK) | (fume->state->frame & ~FF_FRAMEMASK);
fume->threshold = 0;
}
}
fume->movecount = dashmode; // keeps track of previous dashmode value so we know whether Metal is entering or leaving it
fume->flags2 = (fume->flags2 & ~MF2_OBJECTFLIP) | (mo->flags2 & MF2_OBJECTFLIP); // Make sure to flip in reverse gravity!
fume->eflags = (fume->eflags & ~MFE_VERTICALFLIP) | (mo->eflags & MFE_VERTICALFLIP); // Make sure to flip in reverse gravity!
// keeps track of previous dash mode value so we know whether Metal is entering or leaving it
fume->movecount = dashmode;
// Make sure to flip in reverse gravity!
fume->flags2 = (fume->flags2 & ~MF2_OBJECTFLIP) | (mo->flags2 & MF2_OBJECTFLIP);
fume->eflags = (fume->eflags & ~MFE_VERTICALFLIP) | (mo->eflags & MFE_VERTICALFLIP);
// Set the appropriate scale at spawn
// This is... strange, but I had to choose a flag that a follow object would not ordinarily use.
if ((fume->flags2 & MF2_BOSSNOTRAP) == 0)
{
P_SetScale(fume, fume->destscale, true);
fume->flags2 |= MF2_BOSSNOTRAP;
}
// Finally, set its position
dist = -mo->radius - FixedMul(fume->info->radius, fume->destscale - mo->scale/3);
......@@ -11624,7 +11719,8 @@ void P_DoMetalJetFume(player_t *player, mobj_t *fume)
fume->y = mo->y + P_ReturnThrustY(fume, angle, dist);
fume->z = mo->z + heightoffset - (fume->height >> 1);
P_SetThingPosition(fume);
if (resetinterp) R_ResetMobjInterpolationState(fume);
if (resetinterp)
R_ResetMobjInterpolationState(fume);
// If dash mode is high enough, spawn a trail
if (player->normalspeed >= skins[player->skin]->normalspeed*2)
......@@ -11640,6 +11736,8 @@ void P_DoFollowMobj(player_t *player, mobj_t *followmobj)
{
if (LUA_HookFollowMobj(player, followmobj) || P_MobjWasRemoved(followmobj))
{;}
else if (player->charflags & SF_JETFUME)
P_DoMetalJetFume(player, followmobj);
else
{
switch (followmobj->type)
......@@ -11772,7 +11870,7 @@ void P_PlayerThink(player_t *player)
// Check if all the players in the race have finished. If so, end the level.
for (i = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i])
if (players[i].ingame)
{
if (!players[i].exiting && players[i].lives > 0)
break;
......@@ -11841,7 +11939,7 @@ void P_PlayerThink(player_t *player)
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator || players[i].bot)
if (!players[i].ingame || players[i].spectator || players[i].bot)
continue;
if (players[i].lives <= 0)
continue;
......@@ -11873,7 +11971,7 @@ void P_PlayerThink(player_t *player)
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator || players[i].bot)
if (!players[i].ingame || players[i].spectator || players[i].bot)
continue;
if (players[i].quittime > 30 * TICRATE)
continue;
......@@ -11988,7 +12086,7 @@ void P_PlayerThink(player_t *player)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
if (th->removing)
continue;
mo2 = (mobj_t *)th;
......@@ -12001,7 +12099,7 @@ void P_PlayerThink(player_t *player)
if (mo2->flags2 & MF2_NIGHTSPULL)
continue;
if (P_AproxDistance(P_AproxDistance(mo2->x - x, mo2->y - y), mo2->z - z) > FixedMul(128*FRACUNIT, player->mo->scale))
if (ArePointsFar3D(x, y, z, mo2->x, mo2->y, mo2->z, FixedMul(128*FRACUNIT, player->mo->scale)))
continue;
// Yay! The thing's in reach! Pull it in!
......@@ -12048,7 +12146,7 @@ void P_PlayerThink(player_t *player)
ticmiss++;
P_DoRopeHang(player);
P_DoJumpStuff(player, &player->cmd, false); // P_DoRopeHang would set PF_SPINDOWN, so no spinshieldhack here
P_DoJumpStuff(player, &player->cmd);
}
else //if (player->powers[pw_carry] == CR_ZOOMTUBE)
{
......@@ -12129,6 +12227,10 @@ void P_PlayerThink(player_t *player)
case CR_DUSTDEVIL:
player->drawangle += ANG20;
break;
case CR_FAN:
if (player->pflags & PF_ANALOGMODE) // Don't impact drawangle in any special way when on a fan
player->drawangle = player->mo->angle;
break;
/* -- in case we wanted to have the camera freely movable during zoom tubes
case CR_ZOOMTUBE:*/
case CR_ROPEHANG:
......@@ -12211,10 +12313,9 @@ void P_PlayerThink(player_t *player)
diff = InvAngle(diff);
if (diff > ANG10/2)
{
statenum_t stat = player->mo->state-states;
if (stat == S_PLAY_WAIT)
if (P_IsPlayerInState(player, S_PLAY_WAIT))
P_SetMobjState(player->mo, S_PLAY_STND);
else if (stat == S_PLAY_STND && player->mo->tics != -1)
else if (P_IsPlayerInState(player, S_PLAY_STND) && player->mo->tics != -1)
player->mo->tics++;
}
}
......@@ -12239,12 +12340,12 @@ void P_PlayerThink(player_t *player)
// fake skidding! see P_SkidStuff for reference on conditionals
else if (!player->skidtime && !(player->mo->eflags & MFE_GOOWATER) && !(player->pflags & (PF_JUMPED|PF_SPINNING|PF_SLIDING)) && !(player->charflags & SF_NOSKID) && P_AproxDistance(player->mo->momx, player->mo->momy) >= FixedMul(player->runspeed, player->mo->scale)) // modified from player->runspeed/2 'cuz the skid was just TOO frequent ngl
{
if (player->mo->state-states != S_PLAY_SKID)
if (!P_IsPlayerInState(player, S_PLAY_SKID))
P_SetMobjState(player->mo, S_PLAY_SKID);
player->mo->tics = player->skidtime = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS;
if (P_IsLocalPlayer(player)) // the sound happens way more frequently now, so give co-op players' ears a brake...
S_StartSound(player->mo, sfx_skid);
S_StartSoundFromMobj(player->mo, sfx_skid);
}
if (player->mo->movefactor != FRACUNIT) // Friction-scaled acceleration...
......@@ -12318,12 +12419,6 @@ void P_PlayerThink(player_t *player)
player->pflags &= ~PF_SPINDOWN;
}
// Check for Shield button
if (cmd->buttons & BT_SHIELD)
player->pflags |= PF_SHIELDDOWN;
else
player->pflags &= ~PF_SHIELDDOWN;
// IF PLAYER NOT HERE THEN FLASH END IF
if (player->quittime && player->powers[pw_flashing] < flashingtics - 1
&& !(G_TagGametype() && !(player->pflags & PF_TAGIT)) && !player->gotflag)
......@@ -12416,16 +12511,14 @@ void P_PlayerThink(player_t *player)
player->stronganim = 0;
//pw_super acts as a timer now
if (player->powers[pw_super]
&& (player->mo->state < &states[S_PLAY_SUPER_TRANS1]
|| player->mo->state > &states[S_PLAY_SUPER_TRANS6]))
if (player->powers[pw_super] && !P_IsPlayerInSuperTransformationState(player))
player->powers[pw_super]++;
if (player->powers[pw_carry] == CR_BRAKGOOP)
{
if (!player->powers[pw_flashing])
{
if (player->mo->state != &states[S_PLAY_STND])
if (!P_IsPlayerInState(player, S_PLAY_STND))
P_SetMobjState(player->mo, S_PLAY_STND);
else
player->mo->tics = 2;
......@@ -12474,8 +12567,6 @@ void P_PlayerThink(player_t *player)
else
player->mo->flags2 &= ~MF2_DONTDRAW;
player->pflags &= ~PF_SLIDING;
#define dashmode player->dashmode
// Dash mode - thanks be to VelocitOni
if ((player->charflags & SF_DASHMODE) && !player->gotflag && !player->powers[pw_carry] && !player->exiting && !(maptol & TOL_NIGHTS) && !metalrecording) // woo, dashmode! no nights tho.
......@@ -12489,7 +12580,7 @@ void P_PlayerThink(player_t *player)
if (dashmode < DASHMODE_MAX)
dashmode++; // Counter. Adds 1 to dash mode per tic in top speed.
if (dashmode == DASHMODE_THRESHOLD) // This isn't in the ">=" equation because it'd cause the sound to play infinitely.
S_StartSound(player->mo, (player->charflags & SF_MACHINE) ? sfx_kc4d : sfx_cdfm40); // If the player enters dashmode, play this sound on the the tic it starts.
S_StartSoundFromMobj(player->mo, (player->charflags & SF_MACHINE) ? sfx_kc4d : sfx_cdfm40); // If the player enters dashmode, play this sound on the the tic it starts.
}
else if ((!totallyradical || !floating) && !(player->pflags & PF_SPINNING))
{
......@@ -12497,7 +12588,7 @@ void P_PlayerThink(player_t *player)
{
dashmode -= 3; // Rather than lose it all, it gently counts back down!
if ((dashmode+3) >= DASHMODE_THRESHOLD && dashmode < DASHMODE_THRESHOLD)
S_StartSound(player->mo, sfx_kc65);
S_StartSoundFromMobj(player->mo, sfx_kc65);
}
else
dashmode = 0;
......@@ -12542,7 +12633,7 @@ void P_PlayerThink(player_t *player)
{
player->normalspeed = skins[player->skin]->normalspeed;
player->jumpfactor = skins[player->skin]->jumpfactor;
S_StartSound(player->mo, sfx_kc65);
S_StartSoundFromMobj(player->mo, sfx_kc65);
if (player->powers[pw_strong] & STR_DASH)
player->powers[pw_strong] = STR_NONE;
}
......@@ -12552,6 +12643,12 @@ void P_PlayerThink(player_t *player)
LUA_HookPlayer(player, HOOK(PlayerThink));
// Remove PF_SLIDING *AFTER* PlayerThink hooks, because
// no one wants to add a ThinkFrame just for detecting this (i'm also very lazy)
// This is such a trivial change, I doubt it'll change anything major
// -luigi budd
player->pflags &= ~PF_SLIDING;
/*
// Colormap verification
{
......@@ -12665,7 +12762,7 @@ void P_PlayerAfterThink(player_t *player)
// camera may still move when guy is dead
//if (!netgame)
{
if (thiscam && thiscam->chase)
if (thiscam)
P_MoveChaseCamera(player, thiscam, false);
}
if (player->followmobj)
......@@ -12787,10 +12884,10 @@ void P_PlayerAfterThink(player_t *player)
player->currentweapon = 0;
if (P_IsLocalPlayer(player) && (player->pflags & PF_WPNDOWN) && player->currentweapon != oldweapon)
S_StartSound(NULL, sfx_wepchg);
S_StartSoundFromEverywhere(sfx_wepchg);
if ((player->pflags & PF_SLIDING) && ((player->pflags & (PF_JUMPED|PF_NOJUMPDAMAGE)) != PF_JUMPED))
P_SetMobjState(player->mo, player->mo->info->painstate);
P_SetMobjState(player->mo, S_PLAY_PAIN);
/* if (player->powers[pw_carry] == CR_NONE && player->mo->tracer && !player->homing)
P_SetTarget(&player->mo->tracer, NULL);
......@@ -12829,9 +12926,9 @@ void P_PlayerAfterThink(player_t *player)
else
{
if (tails->player)
P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->player->drawangle, 4*FRACUNIT), tails->y + P_ReturnThrustY(tails, tails->player->drawangle, 4*FRACUNIT), true);
P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->player->drawangle, 4*tails->scale), tails->y + P_ReturnThrustY(tails, tails->player->drawangle, 4*tails->scale), true);
else
P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->angle, 4*FRACUNIT), tails->y + P_ReturnThrustY(tails, tails->angle, 4*FRACUNIT), true);
P_TryMove(player->mo, tails->x + P_ReturnThrustX(tails, tails->angle, 4*tails->scale), tails->y + P_ReturnThrustY(tails, tails->angle, 4*tails->scale), true);
player->mo->momx = tails->momx;
player->mo->momy = tails->momy;
player->mo->momz = tails->momz;
......@@ -12845,12 +12942,12 @@ void P_PlayerAfterThink(player_t *player)
P_SetPlayerAngle(player, player->mo->angle);
}
if (P_AproxDistance(player->mo->x - tails->x, player->mo->y - tails->y) > player->mo->radius)
if (P_AreMobjsFar2D(player->mo, tails, tails->radius))
player->powers[pw_carry] = CR_NONE;
if (player->powers[pw_carry] == CR_PLAYER)
{
if (player->mo->state-states != S_PLAY_RIDE)
if (!P_IsPlayerInState(player, S_PLAY_RIDE))
P_SetMobjState(player->mo, S_PLAY_RIDE);
if (tails->player && (tails->skin && ((skin_t *)(tails->skin))->sprites[SPR2_SWIM].numframes) && (tails->eflags & MFE_UNDERWATER))
tails->player->powers[pw_tailsfly] = 0;
......@@ -12875,7 +12972,7 @@ void P_PlayerAfterThink(player_t *player)
player->mo->z = item->z - FixedDiv(player->mo->height, 3*FRACUNIT/2);
player->mo->momx = player->mo->momy = player->mo->momz = 0;
P_SetThingPosition(player->mo);
if (player->mo->state-states != S_PLAY_RIDE)
if (!P_IsPlayerInState(player, S_PLAY_RIDE))
P_SetMobjState(player->mo, S_PLAY_RIDE);
// Controllable missile
......@@ -13066,14 +13163,14 @@ void P_PlayerAfterThink(player_t *player)
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)
if (P_AproxDistance(player->mo->x - ptera->x - ptera->watertop, player->mo->y - ptera->y - ptera->waterbottom) > ptera->radius)
goto dropoff;
ptera->watertop >>= 1;
ptera->waterbottom >>= 1;
ptera->cvmem >>= 1;
if (player->mo->state-states != S_PLAY_FALL)
if (!P_IsPlayerInState(player, S_PLAY_FALL))
P_SetMobjState(player->mo, S_PLAY_FALL);
break;
......@@ -13105,10 +13202,11 @@ void P_PlayerAfterThink(player_t *player)
player->viewz = player->mo->z + player->mo->height - player->viewheight;
else
player->viewz = player->mo->z + player->viewheight;
}
if (server || addedtogame)
P_MoveChaseCamera(player, thiscam, false); // calculate the camera movement
}
}
// spectator invisibility and nogravity.
if ((netgame || multiplayer) && player->spectator)
......@@ -13143,6 +13241,7 @@ void P_PlayerAfterThink(player_t *player)
player->followmobj->colorized = true;
break;
default:
if ((player->charflags & SF_JETFUME) == 0)
player->followmobj->flags2 |= MF2_LINKDRAW;
break;
}
......@@ -13219,9 +13318,9 @@ boolean P_PlayerCanEnterSpinGaps(player_t *player)
return false;
return ((player->pflags & (PF_SPINNING|PF_SLIDING|PF_GLIDING)) // players who are spinning, sliding, or gliding
|| (player->charability == CA_GLIDEANDCLIMB && player->mo->state-states == S_PLAY_GLIDE_LANDING) // players who are landing from a glide
|| (player->charability == CA_GLIDEANDCLIMB && P_IsPlayerInState(player, S_PLAY_GLIDE_LANDING)) // players who are landing from a glide
|| ((player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE)
&& player->dashmode >= DASHMODE_THRESHOLD && player->mo->state-states == S_PLAY_DASH) // machine players in dashmode
&& player->dashmode >= DASHMODE_THRESHOLD && P_IsPlayerInState(player, S_PLAY_DASH)) // machine players in dashmode
|| JUMPCURLED(player)); // players who are jumpcurled, but only if they would normally jump that way
}
......@@ -13229,13 +13328,13 @@ boolean P_PlayerCanEnterSpinGaps(player_t *player)
boolean P_PlayerShouldUseSpinHeight(player_t *player)
{
return ((player->pflags & (PF_SPINNING|PF_SLIDING|PF_GLIDING))
|| (player->mo->state == &states[player->mo->info->painstate])
|| P_IsPlayerInState(player, S_PLAY_PAIN)
|| (player->panim == PA_ROLL)
|| ((player->powers[pw_tailsfly] || (player->charability == CA_FLY && player->mo->state-states == S_PLAY_FLY_TIRED))
|| ((player->powers[pw_tailsfly] || (player->charability == CA_FLY && P_IsPlayerInState(player, S_PLAY_FLY_TIRED)))
&& !(player->charflags & SF_NOJUMPSPIN))
|| (player->charability == CA_GLIDEANDCLIMB && player->mo->state-states == S_PLAY_GLIDE_LANDING)
|| (player->charability == CA_GLIDEANDCLIMB && P_IsPlayerInState(player, S_PLAY_GLIDE_LANDING))
|| ((player->charflags & (SF_DASHMODE|SF_MACHINE)) == (SF_DASHMODE|SF_MACHINE)
&& player->dashmode >= DASHMODE_THRESHOLD && player->mo->state-states == S_PLAY_DASH)
&& player->dashmode >= DASHMODE_THRESHOLD && P_IsPlayerInState(player, S_PLAY_DASH))
|| JUMPCURLED(player));
}
......
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2025 by LJ Sonic
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file quaternion.c
/// \brief Fixed-point 3D vector
#include <string.h>
#include "quaternion.h"
#include "vector3d.h"
#include "matrix.h"
#include "r_main.h" // R_PointToDist2
quaternion_t *Quaternion_Set(quaternion_t *quat, fixed_t x, fixed_t y, fixed_t z, fixed_t w)
{
quat->x = x;
quat->y = y;
quat->z = z;
quat->w = w;
return quat;
}
quaternion_t *Quaternion_SetIdentity(quaternion_t *quat)
{
return Quaternion_Set(quat, 0, 0, 0, FRACUNIT);
}
quaternion_t *Quaternion_SetAxisRotation(quaternion_t *quat, vector3_t *axis, fixed_t angle)
{
fixed_t cosangle = FINECOSINE(((angle / 2) >> ANGLETOFINESHIFT) & FINEMASK);
fixed_t sinangle = FINESINE(((angle / 2) >> ANGLETOFINESHIFT) & FINEMASK);
vector3_t normaxis;
Vector3D_Normalize(&normaxis, axis);
return Quaternion_Set(quat,
FixedMul(normaxis.x, sinangle),
FixedMul(normaxis.y, sinangle),
FixedMul(normaxis.z, sinangle),
cosangle
);
}
quaternion_t *Quaternion_Copy(quaternion_t *out, quaternion_t *in)
{
return memcpy(out, in, sizeof(*out));
}
matrix_t *Quaternion_ToMatrix(matrix_t *mat, const quaternion_t *quat)
{
fixed_t x = quat->x, y = quat->y, z = quat->z, w = quat->w;
fixed_t xx2 = 2 * FixedMul(x, x);
fixed_t xy2 = 2 * FixedMul(x, y);
fixed_t xz2 = 2 * FixedMul(x, z);
fixed_t xw2 = 2 * FixedMul(x, w);
fixed_t yy2 = 2 * FixedMul(y, y);
fixed_t yz2 = 2 * FixedMul(y, z);
fixed_t yw2 = 2 * FixedMul(y, w);
fixed_t zz2 = 2 * FixedMul(z, z);
fixed_t zw2 = 2 * FixedMul(z, w);
Matrix_SetIdentity(mat);
mat->matrix[0][0] = FRACUNIT - yy2 - zz2;
mat->matrix[0][1] = xy2 - zw2;
mat->matrix[0][2] = xz2 + yw2;
mat->matrix[1][0] = xy2 + zw2;
mat->matrix[1][1] = FRACUNIT - xx2 - zz2;
mat->matrix[1][2] = yz2 - xw2;
mat->matrix[2][0] = xz2 - yw2;
mat->matrix[2][1] = yz2 + xw2;
mat->matrix[2][2] = FRACUNIT - xx2 - yy2;
mat->matrix[3][3] = FRACUNIT;
return mat;
}
quaternion_t *Quaternion_Normalize(quaternion_t *out, quaternion_t *in)
{
fixed_t sqlen =
FixedMul(in->x, in->x) +
FixedMul(in->y, in->y) +
FixedMul(in->z, in->z) +
FixedMul(in->w, in->w);
if (sqlen < FRACUNIT / 1024)
return Quaternion_Set(out, in->x, in->y, in->z, in->w);
fixed_t len = R_PointToDist2(0, 0, R_PointToDist2(0, 0, R_PointToDist2(0, 0, in->x, in->y), in->z), in->w);
return Quaternion_Set(out,
FixedDiv(in->x, len),
FixedDiv(in->y, len),
FixedDiv(in->z, len),
FixedDiv(in->w, len)
);
}
quaternion_t *Quaternion_Mul(quaternion_t *out, quaternion_t *a, quaternion_t *b)
{
fixed_t ax = a->x, ay = a->y, az = a->z, aw = a->w;
fixed_t bx = b->x, by = b->y, bz = b->z, bw = b->w;
return Quaternion_Normalize(out, Quaternion_Set(out,
FixedMul(aw, bx) + FixedMul(ax, bw) + FixedMul(ay, bz) - FixedMul(az, by),
FixedMul(aw, by) - FixedMul(ax, bz) + FixedMul(ay, bw) + FixedMul(az, bx),
FixedMul(aw, bz) + FixedMul(ax, by) - FixedMul(ay, bx) + FixedMul(az, bw),
FixedMul(aw, bw) - FixedMul(ax, bx) - FixedMul(ay, by) - FixedMul(az, bz)
));
}
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2025 by LJ Sonic
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file quaternion.c
/// \brief Fixed-point quaternion
#ifndef __QUATERNION__
#define __QUATERNION__
#include "m_fixed.h"
#include "matrix.h"
typedef struct
{
fixed_t x, y, z, w;
} quaternion_t;
quaternion_t *Quaternion_Set(quaternion_t *quat, fixed_t x, fixed_t y, fixed_t z, fixed_t w);
quaternion_t *Quaternion_SetIdentity(quaternion_t *quat);
quaternion_t *Quaternion_SetAxisRotation(quaternion_t *quat, vector3_t *axis, fixed_t angle);
quaternion_t *Quaternion_Copy(quaternion_t *out, quaternion_t *in);
matrix_t *Quaternion_ToMatrix(matrix_t *mat, const quaternion_t *quat);
quaternion_t *Quaternion_Normalize(quaternion_t *out, quaternion_t *in);
quaternion_t *Quaternion_Mul(quaternion_t *out, quaternion_t *a, quaternion_t *b);
#endif
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -230,6 +230,18 @@ static INT32 R_DoorClosed(void)
&& (backsector->floorheight <= frontsector->floorheight || curline->sidedef->bottomtexture);
}
static UINT8 R_FloorLightLevel(sector_t *sector, INT16 base_lightlevel)
{
return max(0, min(255, sector->floorlightlevel +
((sector->floorlightabsolute) ? 0 : base_lightlevel)));
}
static UINT8 R_CeilingLightLevel(sector_t *sector, INT16 base_lightlevel)
{
return max(0, min(255, sector->ceilinglightlevel +
((sector->ceilinglightabsolute) ? 0 : base_lightlevel)));
}
//
// If player's view height is underneath fake floor, lower the
// drawn ceiling to be just under the floor height, and replace
......@@ -968,11 +980,10 @@ static void R_Subsector(size_t num)
&& ((viewz < heightcheck && (rover->fofflags & FOF_BOTHPLANES || !(rover->fofflags & FOF_INVERTPLANES)))
|| (viewz > heightcheck && (rover->fofflags & FOF_BOTHPLANES || rover->fofflags & FOF_INVERTPLANES))))
{
light = R_GetPlaneLight(frontsector, planecenterz,
viewz < heightcheck);
light = R_GetPlaneLight(frontsector, planecenterz, viewz < heightcheck);
ffloor[numffloors].plane = R_FindPlane(rover->master->frontsector, *rover->bottomheight, *rover->bottompic,
*frontsector->lightlist[light].lightlevel, *rover->bottomxoffs, *rover->bottomyoffs,
R_FloorLightLevel(rover->master->frontsector, *frontsector->lightlist[light].lightlevel), *rover->bottomxoffs, *rover->bottomyoffs,
*rover->bottomxscale, *rover->bottomyscale, *rover->bottomangle,
*frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->b_slope, NULL);
......@@ -1002,7 +1013,7 @@ static void R_Subsector(size_t num)
light = R_GetPlaneLight(frontsector, planecenterz, viewz < heightcheck);
ffloor[numffloors].plane = R_FindPlane(rover->master->frontsector, *rover->topheight, *rover->toppic,
*frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs,
R_CeilingLightLevel(rover->master->frontsector, *frontsector->lightlist[light].lightlevel), *rover->topxoffs, *rover->topyoffs,
*rover->topxscale, *rover->topyscale, *rover->topangle,
*frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->t_slope, NULL);
......@@ -1315,7 +1326,7 @@ INT32 R_GetPlaneLight(sector_t *sector, fixed_t planeheight, boolean underside)
void R_RenderBSPNode(INT32 bspnum)
{
node_t *bsp;
bspnode_t *bsp;
INT32 side;
ps_numbspcalls.value.i++;
......
......@@ -2,7 +2,7 @@
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior.
// Copyright (C) 1999-2024 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
......@@ -426,9 +426,6 @@ void R_ClearColormaps(void)
{
// Purged by PU_LEVEL, just overwrite the pointer
extra_colormaps = R_CreateDefaultColormap(true);
#ifdef HWRENDER
HWR_ClearLightTables();
#endif
}
//
......@@ -849,6 +846,15 @@ void R_GenerateLightTable(extracolormap_t *extra_colormap, boolean uselookup)
}
}
void R_UpdateLightTable(extracolormap_t *extra_colormap, boolean uselookup)
{
R_GenerateLightTable(extra_colormap, uselookup);
#ifdef HWRENDER
extra_colormap->gl_lighttable.needs_update = true;
#endif
}
extracolormap_t *R_CreateColormapFromLinedef(char *p1, char *p2, char *p3)
{
// default values
......@@ -1266,7 +1272,7 @@ void R_PrecacheLevel(void)
if (spritepresent == NULL) I_Error("%s: Out of memory looking up sprites", "R_PrecacheLevel");
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
if (th->function.acp1 != (actionf_p1)P_RemoveThinkerDelayed)
if (th->function != (actionf_p1)P_RemoveThinkerDelayed)
spritepresent[((mobj_t *)th)->sprite] = 1;
spritememory = 0;
......