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
  • PacolaYes/SRB2
126 results
Select Git revision
  • 1392-2-2-15-attempting-to-draw-a-hud-graphic-with-the-same-lump-name-as-a-lua-script-crashes-the
  • 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
  • better-player-states
  • 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
  • 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
Show changes
Showing with 2439 additions and 2345 deletions
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team. // 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 // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -25,22 +25,18 @@ ...@@ -25,22 +25,18 @@
#ifdef _WIN32 #ifdef _WIN32
#define USE_WINSOCK #define USE_WINSOCK
#if defined (_WIN64) || defined (HAVE_IPV6)
#define USE_WINSOCK2
#else //_WIN64/HAVE_IPV6
#define USE_WINSOCK1
#endif
#endif //WIN32 OS #endif //WIN32 OS
#ifdef USE_WINSOCK2 #ifdef USE_WINSOCK
#include <ws2tcpip.h> #include <ws2tcpip.h>
#define addrinfo_t ADDRINFOA
#else
#define addrinfo_t struct addrinfo
#endif #endif
#include "../doomdef.h" #include "../doomdef.h"
#include "../z_zone.h"
#ifdef USE_WINSOCK1
#include <winsock.h>
#else
#ifndef USE_WINSOCK #ifndef USE_WINSOCK
#include <arpa/inet.h> #include <arpa/inet.h>
#ifdef __APPLE_CC__ #ifdef __APPLE_CC__
...@@ -60,7 +56,6 @@ ...@@ -60,7 +56,6 @@
#if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON) #if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON)
#include <sys/time.h> #include <sys/time.h>
#endif // UNIXCOMMON #endif // UNIXCOMMON
#endif
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
// some undefined under win32 // some undefined under win32
...@@ -87,6 +82,10 @@ ...@@ -87,6 +82,10 @@
#undef EHOSTUNREACH #undef EHOSTUNREACH
#endif #endif
#define EHOSTUNREACH WSAEHOSTUNREACH #define EHOSTUNREACH WSAEHOSTUNREACH
#ifdef ENETUNREACH
#undef ENETUNREACH
#endif
#define ENETUNREACH WSAENETUNREACH
#ifndef IOC_VENDOR #ifndef IOC_VENDOR
#define IOC_VENDOR 0x18000000 #define IOC_VENDOR 0x18000000
#endif #endif
...@@ -114,20 +113,12 @@ typedef union ...@@ -114,20 +113,12 @@ typedef union
} mysockaddr_t; } mysockaddr_t;
#ifdef HAVE_MINIUPNPC #ifdef HAVE_MINIUPNPC
#ifdef MINIUPNP_STATICLIB
#include "miniwget.h"
#include "miniupnpc.h"
#include "upnpcommands.h"
#else
#include "miniupnpc/miniwget.h" #include "miniupnpc/miniwget.h"
#include "miniupnpc/miniupnpc.h" #include "miniupnpc/miniupnpc.h"
#include "miniupnpc/upnpcommands.h" #include "miniupnpc/upnpcommands.h"
#endif
static boolean UPNP_support = true; static boolean UPNP_support = true;
#endif // HAVE_MINIUPNC #endif // HAVE_MINIUPNC
#define MAXBANS 100
#include "../i_system.h" #include "../i_system.h"
#include "i_net.h" #include "i_net.h"
#include "d_net.h" #include "d_net.h"
...@@ -145,8 +136,6 @@ typedef union ...@@ -145,8 +136,6 @@ typedef union
#define close closesocket #define close closesocket
#endif #endif
#include "i_addrinfo.h"
#define SELECTTEST
#define DEFAULTPORT "5029" #define DEFAULTPORT "5029"
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
...@@ -164,9 +153,6 @@ typedef union ...@@ -164,9 +153,6 @@ typedef union
#define IPV6_MULTICAST_ADDRESS "ff15::57e1:1a12" #define IPV6_MULTICAST_ADDRESS "ff15::57e1:1a12"
// define socklen_t in DOS/Windows if it is not already defined // define socklen_t in DOS/Windows if it is not already defined
#ifdef USE_WINSOCK1
typedef int socklen_t;
#endif
static SOCKET_TYPE mysockets[MAXNETNODES+1] = {ERRSOCKET}; static SOCKET_TYPE mysockets[MAXNETNODES+1] = {ERRSOCKET};
static size_t mysocketses = 0; static size_t mysocketses = 0;
static int myfamily[MAXNETNODES+1] = {0}; static int myfamily[MAXNETNODES+1] = {0};
...@@ -175,8 +161,8 @@ static mysockaddr_t clientaddress[MAXNETNODES+1]; ...@@ -175,8 +161,8 @@ static mysockaddr_t clientaddress[MAXNETNODES+1];
static mysockaddr_t broadcastaddress[MAXNETNODES+1]; static mysockaddr_t broadcastaddress[MAXNETNODES+1];
static size_t broadcastaddresses = 0; static size_t broadcastaddresses = 0;
static boolean nodeconnected[MAXNETNODES+1]; static boolean nodeconnected[MAXNETNODES+1];
static mysockaddr_t banned[MAXBANS]; static mysockaddr_t *banned;
static UINT8 bannedmask[MAXBANS]; static UINT8 *bannedmask;
static size_t numbans = 0; static size_t numbans = 0;
static boolean SOCK_bannednode[MAXNETNODES+1]; /// \note do we really need the +1? static boolean SOCK_bannednode[MAXNETNODES+1]; /// \note do we really need the +1?
...@@ -212,9 +198,8 @@ static char *get_WSAErrorStr(int e) ...@@ -212,9 +198,8 @@ static char *get_WSAErrorStr(int e)
#define strerror get_WSAErrorStr #define strerror get_WSAErrorStr
#endif #endif
#ifdef USE_WINSOCK2 #ifdef USE_WINSOCK
#define inet_ntop inet_ntopA #define inet_ntop inet_ntopA
#define HAVE_NTOP
static const char* inet_ntopA(short af, const void *cp, char *buf, socklen_t len) static const char* inet_ntopA(short af, const void *cp, char *buf, socklen_t len)
{ {
DWORD Dlen = len, AFlen = 0; DWORD Dlen = len, AFlen = 0;
...@@ -258,8 +243,6 @@ static const char* inet_ntopA(short af, const void *cp, char *buf, socklen_t len ...@@ -258,8 +243,6 @@ static const char* inet_ntopA(short af, const void *cp, char *buf, socklen_t len
return NULL; return NULL;
return buf; return buf;
} }
#elif !defined (USE_WINSOCK1)
#define HAVE_NTOP
#endif #endif
#ifdef HAVE_MINIUPNPC // based on old XChat patch #ifdef HAVE_MINIUPNPC // based on old XChat patch
...@@ -278,9 +261,18 @@ static void init_upnpc_once(struct upnpdata *upnpdata); ...@@ -278,9 +261,18 @@ static void init_upnpc_once(struct upnpdata *upnpdata);
static void I_InitUPnP(void) static void I_InitUPnP(void)
{ {
if (!I_can_thread())
{
UPNP_support = false;
return;
}
upnpuser = malloc(sizeof *upnpuser); upnpuser = malloc(sizeof *upnpuser);
upnpuser->upnpc_started = 0; upnpuser->upnpc_started = 0;
I_spawn_thread("init_upnpc_once", (I_thread_fn)init_upnpc_once, upnpuser); if (!I_spawn_thread("init_upnpc_once", (I_thread_fn)init_upnpc_once, upnpuser))
{
UPNP_support = false;
free(upnpuser);
}
} }
static void static void
...@@ -323,7 +315,11 @@ init_upnpc_once(struct upnpdata *upnpuserdata) ...@@ -323,7 +315,11 @@ init_upnpc_once(struct upnpdata *upnpuserdata)
I_OutputMsg(M_GetText("Found UPnP device:\n desc: %s\n st: %s\n"), I_OutputMsg(M_GetText("Found UPnP device:\n desc: %s\n st: %s\n"),
dev->descURL, dev->st); dev->descURL, dev->st);
#if (MINIUPNPC_API_VERSION >= 18)
UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr), NULL, 0);
#else
UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
#endif
I_OutputMsg(M_GetText("Local LAN IP address: %s\n"), lanaddr); I_OutputMsg(M_GetText("Local LAN IP address: %s\n"), lanaddr);
descXML = miniwget(dev->descURL, &descXMLsize, scope_id, &status_code); descXML = miniwget(dev->descURL, &descXMLsize, scope_id, &status_code);
if (descXML) if (descXML)
...@@ -379,13 +375,13 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk) ...@@ -379,13 +375,13 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk)
{ {
static char s[64]; // 255.255.255.255:65535 or static char s[64]; // 255.255.255.255:65535 or
// [ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535 // [ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]:65535
#ifdef HAVE_NTOP
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
int v6 = (sk->any.sa_family == AF_INET6); int v6 = (sk->any.sa_family == AF_INET6);
#else #else
int v6 = 0; int v6 = 0;
#endif #endif
void *addr; void *addr;
int e = 0; // save error code so it can't be modified later code and avoid calling WSAGetLastError() more then once
if(sk->any.sa_family == AF_INET) if(sk->any.sa_family == AF_INET)
addr = &sk->ip4.sin_addr; addr = &sk->ip4.sin_addr;
...@@ -399,7 +395,10 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk) ...@@ -399,7 +395,10 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk)
if(addr == NULL) if(addr == NULL)
sprintf(s, "No address"); sprintf(s, "No address");
else if(inet_ntop(sk->any.sa_family, addr, &s[v6], sizeof (s) - v6) == NULL) else if(inet_ntop(sk->any.sa_family, addr, &s[v6], sizeof (s) - v6) == NULL)
sprintf(s, "Unknown family type, error #%u", errno); {
e = errno;
sprintf(s, "Unknown family type, error #%u: %s", e, strerror(e));
}
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
else if(sk->any.sa_family == AF_INET6) else if(sk->any.sa_family == AF_INET6)
{ {
...@@ -413,15 +412,6 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk) ...@@ -413,15 +412,6 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk)
else if(sk->any.sa_family == AF_INET && sk->ip4.sin_port != 0) else if(sk->any.sa_family == AF_INET && sk->ip4.sin_port != 0)
strcat(s, va(":%d", ntohs(sk->ip4.sin_port))); strcat(s, va(":%d", ntohs(sk->ip4.sin_port)));
#else
if (sk->any.sa_family == AF_INET)
{
strcpy(s, inet_ntoa(sk->ip4.sin_addr));
if (sk->ip4.sin_port != 0) strcat(s, va(":%d", ntohs(sk->ip4.sin_port)));
}
else
sprintf(s, "Unknown type");
#endif
return s; return s;
} }
...@@ -456,6 +446,8 @@ static boolean SOCK_cmpipv6(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask) ...@@ -456,6 +446,8 @@ static boolean SOCK_cmpipv6(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask)
{ {
UINT8 bitmask; UINT8 bitmask;
I_Assert(mask <= 128); I_Assert(mask <= 128);
if (mask == 0)
mask = 128;
if (memcmp(&a->ip6.sin6_addr.s6_addr, &b->ip6.sin6_addr.s6_addr, mask / 8) != 0) if (memcmp(&a->ip6.sin6_addr.s6_addr, &b->ip6.sin6_addr.s6_addr, mask / 8) != 0)
return false; return false;
if (mask % 8 == 0) if (mask % 8 == 0)
...@@ -568,7 +560,7 @@ void Command_Numnodes(void) ...@@ -568,7 +560,7 @@ void Command_Numnodes(void)
#endif #endif
// Returns true if a packet was received from a new node, false in all other cases // Returns true if a packet was received from a new node, false in all other cases
static boolean SOCK_Get(void) static boolean SOCK_Get(doomcom_t *doomcom)
{ {
size_t i; size_t i;
int j; int j;
...@@ -591,7 +583,7 @@ static boolean SOCK_Get(void) ...@@ -591,7 +583,7 @@ static boolean SOCK_Get(void)
doomcom->remotenode = (INT16)j; // good packet from a game player doomcom->remotenode = (INT16)j; // good packet from a game player
doomcom->datalength = (INT16)c; doomcom->datalength = (INT16)c;
nodesocket[j] = mysockets[n]; nodesocket[j] = mysockets[n];
return false; return true;
} }
} }
// not found // not found
...@@ -630,64 +622,13 @@ static boolean SOCK_Get(void) ...@@ -630,64 +622,13 @@ static boolean SOCK_Get(void)
return false; return false;
} }
// check if we can send (do not go over the buffer) static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, doomcom_t *doomcom, mysockaddr_t *sockaddr)
static fd_set masterset;
#ifdef SELECTTEST
static boolean FD_CPY(fd_set *src, fd_set *dst, SOCKET_TYPE *fd, size_t len)
{
boolean testset = false;
FD_ZERO(dst);
for (size_t i = 0; i < len;i++)
{
if(fd[i] != (SOCKET_TYPE)ERRSOCKET &&
FD_ISSET(fd[i], src) && !FD_ISSET(fd[i], dst)) // no checking for dups
{
FD_SET(fd[i], dst);
testset = true;
}
}
return testset;
}
static boolean SOCK_CanSend(void)
{
struct timeval timeval_for_select = {0, 0};
fd_set tset;
int wselect;
if(!FD_CPY(&masterset, &tset, mysockets, mysocketses))
return false;
wselect = select(255, NULL, &tset, NULL, &timeval_for_select);
if (wselect >= 1)
return true;
return false;
}
static boolean SOCK_CanGet(void)
{
struct timeval timeval_for_select = {0, 0};
fd_set tset;
int rselect;
if(!FD_CPY(&masterset, &tset, mysockets, mysocketses))
return false;
rselect = select(255, &tset, NULL, NULL, &timeval_for_select);
if (rselect >= 1)
return true;
return false;
}
#endif
static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr)
{ {
socklen_t d4 = (socklen_t)sizeof(struct sockaddr_in); socklen_t d4 = (socklen_t)sizeof(struct sockaddr_in);
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
socklen_t d6 = (socklen_t)sizeof(struct sockaddr_in6); socklen_t d6 = (socklen_t)sizeof(struct sockaddr_in6);
#endif #endif
socklen_t d, da = (socklen_t)sizeof(mysockaddr_t); socklen_t d, da = (socklen_t)sizeof(mysockaddr_t);
ssize_t status;
switch (sockaddr->any.sa_family) switch (sockaddr->any.sa_family)
{ {
...@@ -698,17 +639,15 @@ static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr ...@@ -698,17 +639,15 @@ static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr
default: d = da; break; default: d = da; break;
} }
status = sendto(socket, (char *)&doomcom->data, doomcom->datalength, 0, &sockaddr->any, d); return sendto(socket, (char *)&doomcom->data, doomcom->datalength, 0, &sockaddr->any, d);
if (status == -1)
{
CONS_Alert(CONS_WARNING, "Unable to send packet to %s: %s\n", SOCK_AddrToStr(sockaddr), strerror(errno));
}
return status;
} }
static void SOCK_Send(void) #define ALLOWEDERROR(x) ((x) == ECONNREFUSED || (x) == EWOULDBLOCK || (x) == EHOSTUNREACH || (x) == ENETUNREACH || (x) == EADDRNOTAVAIL)
static void SOCK_Send(doomcom_t *doomcom)
{ {
ssize_t c = ERRSOCKET; ssize_t c = ERRSOCKET;
int e = 0; // save error code so it can't be modified later code and avoid calling WSAGetLastError() more then once
if (!nodeconnected[doomcom->remotenode]) if (!nodeconnected[doomcom->remotenode])
return; return;
...@@ -720,34 +659,53 @@ static void SOCK_Send(void) ...@@ -720,34 +659,53 @@ static void SOCK_Send(void)
for (size_t j = 0; j < broadcastaddresses; j++) for (size_t j = 0; j < broadcastaddresses; j++)
{ {
if (myfamily[i] == broadcastaddress[j].any.sa_family) if (myfamily[i] == broadcastaddress[j].any.sa_family)
SOCK_SendToAddr(mysockets[i], &broadcastaddress[j]); {
c = SOCK_SendToAddr(mysockets[i], doomcom, &broadcastaddress[j]);
if (c == ERRSOCKET)
{
e = errno;
if (!ALLOWEDERROR(e))
break;
}
}
} }
} }
return;
} }
else if (nodesocket[doomcom->remotenode] == (SOCKET_TYPE)ERRSOCKET) else if (nodesocket[doomcom->remotenode] == (SOCKET_TYPE)ERRSOCKET)
{ {
for (size_t i = 0; i < mysocketses; i++) for (size_t i = 0; i < mysocketses; i++)
{ {
if (myfamily[i] == clientaddress[doomcom->remotenode].any.sa_family) if (myfamily[i] == clientaddress[doomcom->remotenode].any.sa_family)
SOCK_SendToAddr(mysockets[i], &clientaddress[doomcom->remotenode]); {
c = SOCK_SendToAddr(mysockets[i], doomcom, &clientaddress[doomcom->remotenode]);
if (c == ERRSOCKET)
{
e = errno;
if (!ALLOWEDERROR(e))
break;
}
}
} }
return;
} }
else else
{ {
c = SOCK_SendToAddr(nodesocket[doomcom->remotenode], &clientaddress[doomcom->remotenode]); c = SOCK_SendToAddr(nodesocket[doomcom->remotenode], doomcom, &clientaddress[doomcom->remotenode]);
if (c == ERRSOCKET)
{
e = errno;
}
} }
if (c == ERRSOCKET) if (c == ERRSOCKET && e != 0) // 0 means no socket for the address family was found
{ {
int e = errno; // save error code so it can't be modified later if (!ALLOWEDERROR(e))
if (e != ECONNREFUSED && e != EWOULDBLOCK && e != EHOSTUNREACH) I_Error("SOCK_Send, error sending to node %d (%s) #%u, %s", doomcom->remotenode,
I_Error("SOCK_Send, error sending to node %d (%s) #%u: %s", doomcom->remotenode,
SOCK_GetNodeAddress(doomcom->remotenode), e, strerror(e)); SOCK_GetNodeAddress(doomcom->remotenode), e, strerror(e));
} }
} }
#undef ALLOWEDERROR
static void SOCK_FreeNodenum(INT32 numnode) static void SOCK_FreeNodenum(INT32 numnode)
{ {
// can't disconnect from self :) // can't disconnect from self :)
...@@ -772,6 +730,8 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen ...@@ -772,6 +730,8 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
{ {
SOCKET_TYPE s = socket(family, SOCK_DGRAM, IPPROTO_UDP); SOCKET_TYPE s = socket(family, SOCK_DGRAM, IPPROTO_UDP);
int opt; int opt;
int rc;
int e = 0; // save error code so it can't be modified later code and avoid calling WSAGetLastError() more then once
socklen_t opts; socklen_t opts;
#ifdef FIONBIO #ifdef FIONBIO
unsigned long trueval = true; unsigned long trueval = true;
...@@ -783,15 +743,15 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen ...@@ -783,15 +743,15 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
return (SOCKET_TYPE)ERRSOCKET; return (SOCKET_TYPE)ERRSOCKET;
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
{ // Alam_GBC: disable the new UDP connection reset behavior for Win2k and up { // Alam_GBC: disable the new UDP connection reset behavior for Win2k and up
#ifdef USE_WINSOCK2
DWORD dwBytesReturned = 0; DWORD dwBytesReturned = 0;
BOOL bfalse = FALSE; BOOL bfalse = FALSE;
WSAIoctl(s, SIO_UDP_CONNRESET, &bfalse, sizeof(bfalse), rc = WSAIoctl(s, SIO_UDP_CONNRESET, &bfalse, sizeof(bfalse),
NULL, 0, &dwBytesReturned, NULL, NULL); NULL, 0, &dwBytesReturned, NULL, NULL);
#else if (rc == -1)
unsigned long falseval = false; {
ioctl(s, SIO_UDP_CONNRESET, &falseval); e = errno;
#endif I_OutputMsg("SIO_UDP_CONNRESET failed: #%u, %s\n", e, strerror(e));
}
} }
#endif #endif
...@@ -804,14 +764,22 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen ...@@ -804,14 +764,22 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
{ {
opt = true; opt = true;
opts = (socklen_t)sizeof(opt); opts = (socklen_t)sizeof(opt);
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, opts); rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, opts);
if (rc <= -1)
{
e = errno;
I_OutputMsg("setting SO_REUSEADDR failed: #%u, %s\n", e, strerror(e));
}
} }
// make it broadcastable // make it broadcastable
opt = true; opt = true;
opts = (socklen_t)sizeof(opt); opts = (socklen_t)sizeof(opt);
if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&opt, opts)) rc = setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&opt, opts);
if (rc <= -1)
{ {
e = errno;
CONS_Alert(CONS_WARNING, M_GetText("Could not get broadcast rights\n")); // I do not care anymore CONS_Alert(CONS_WARNING, M_GetText("Could not get broadcast rights\n")); // I do not care anymore
I_OutputMsg("setting SO_BROADCAST failed: #%u, %s\n", e, strerror(e));
} }
} }
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
...@@ -821,24 +789,34 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen ...@@ -821,24 +789,34 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
{ {
opt = true; opt = true;
opts = (socklen_t)sizeof(opt); opts = (socklen_t)sizeof(opt);
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, opts); rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, opts);
if (rc <= -1)
{
e = errno;
I_OutputMsg("setting SO_REUSEADDR failed: #%u, %s\n", e, strerror(e));
}
} }
#ifdef IPV6_V6ONLY #ifdef IPV6_V6ONLY
// make it IPv6 ony // make it IPv6 ony
opt = true; opt = true;
opts = (socklen_t)sizeof(opt); opts = (socklen_t)sizeof(opt);
if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&opt, opts)) rc = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&opt, opts);
if (rc <= -1)
{ {
e = errno;
CONS_Alert(CONS_WARNING, M_GetText("Could not limit IPv6 bind\n")); // I do not care anymore CONS_Alert(CONS_WARNING, M_GetText("Could not limit IPv6 bind\n")); // I do not care anymore
I_OutputMsg("setting IPV6_V6ONLY failed: #%u, %s\n", e, strerror(e));
} }
#endif #endif
} }
#endif #endif
if (bind(s, addr, addrlen) == ERRSOCKET) rc = bind(s, addr, addrlen);
if (rc == ERRSOCKET)
{ {
e = errno;
close(s); close(s);
I_OutputMsg("Binding failed\n"); I_OutputMsg("Binding failed: #%u, %s\n", e, strerror(e));
return (SOCKET_TYPE)ERRSOCKET; return (SOCKET_TYPE)ERRSOCKET;
} }
...@@ -852,9 +830,18 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen ...@@ -852,9 +830,18 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
inet_pton(AF_INET6, IPV6_MULTICAST_ADDRESS, &maddr.ipv6mr_multiaddr); inet_pton(AF_INET6, IPV6_MULTICAST_ADDRESS, &maddr.ipv6mr_multiaddr);
maddr.ipv6mr_interface = 0; maddr.ipv6mr_interface = 0;
if (setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, (const char *)&maddr, sizeof(maddr)) != 0) rc = setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, (const char *)&maddr, sizeof(maddr));
if (rc <= -1)
{ {
e = errno;
CONS_Alert(CONS_WARNING, M_GetText("Could not register multicast address\n")); CONS_Alert(CONS_WARNING, M_GetText("Could not register multicast address\n"));
if (e == ENODEV)
{
close(s);
I_OutputMsg("Binding failed: no IPv6 device\n");
return (SOCKET_TYPE)ERRSOCKET;
}
I_OutputMsg("setting IPV6_JOIN_GROUP failed: #%u, %s \n", e, strerror(e));
} }
} }
} }
...@@ -862,33 +849,56 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen ...@@ -862,33 +849,56 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
#ifdef FIONBIO #ifdef FIONBIO
// make it non blocking // make it non blocking
opt = true; rc = ioctl(s, FIONBIO, &trueval);
if (ioctl(s, FIONBIO, &trueval) != 0) if (rc == -1)
{ {
e = errno;
close(s); close(s);
I_OutputMsg("Seting FIOBIO on failed\n"); I_OutputMsg("FIOBIO failed: #%u, %s\n", e, strerror(e));
return (SOCKET_TYPE)ERRSOCKET; return (SOCKET_TYPE)ERRSOCKET;
} }
#endif #endif
opt = 0;
opts = (socklen_t)sizeof(opt); opts = (socklen_t)sizeof(opt);
getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&opt, &opts); rc = getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&opt, &opts);
if (rc <= -1)
{
e = errno;
I_OutputMsg("getting SO_RCVBUF failed: #%u, %s\n", e, strerror(e));
}
CONS_Printf(M_GetText("Network system buffer: %dKb\n"), opt>>10); CONS_Printf(M_GetText("Network system buffer: %dKb\n"), opt>>10);
if (opt < 64<<10) // 64k if (opt < 64<<10) // 64k
{ {
opt = 64<<10; opt = 64<<10;
opts = (socklen_t)sizeof(opt); opts = (socklen_t)sizeof(opt);
setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&opt, opts); rc = setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&opt, opts);
getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&opt, &opts); if (rc <= -1)
if (opt < 64<<10) {
e = errno;
I_OutputMsg("setting SO_RCVBUF failed: #%u, %s\n", e, strerror(e));
}
opt = 0;
rc = getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&opt, &opts);
if (rc <= -1)
{
e = errno;
I_OutputMsg("getting SO_RCVBUF failed: #%u, %s\n", e, strerror(e));
}
if (opt <= 64<<10)
CONS_Alert(CONS_WARNING, M_GetText("Can't set buffer length to 64k, file transfer will be bad\n")); CONS_Alert(CONS_WARNING, M_GetText("Can't set buffer length to 64k, file transfer will be bad\n"));
else else
CONS_Printf(M_GetText("Network system buffer set to: %dKb\n"), opt>>10); CONS_Printf(M_GetText("Network system buffer set to: %dKb\n"), opt>>10);
} }
if (getsockname(s, &straddr.any, &len) == -1) rc = getsockname(s, &straddr.any, &len);
if (rc != 0)
{
e = errno;
CONS_Alert(CONS_WARNING, M_GetText("Failed to get port number\n")); CONS_Alert(CONS_WARNING, M_GetText("Failed to get port number\n"));
I_OutputMsg("getsockname failed: #%u, %s\n", e, strerror(e));
}
else else
{ {
if (family == AF_INET) if (family == AF_INET)
...@@ -905,11 +915,12 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen ...@@ -905,11 +915,12 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
static boolean UDP_Socket(void) static boolean UDP_Socket(void)
{ {
size_t s; size_t s;
struct my_addrinfo *ai, *runp, hints; addrinfo_t *ai, *runp, hints;
int gaie; int gaie;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
const INT32 b_ipv6 = !M_CheckParm("-noipv6"); const INT32 b_ipv6 = !M_CheckParm("-noipv6");
#endif #endif
const INT32 b_ipv4 = !M_CheckParm("-noipv4");
const char *serv; const char *serv;
...@@ -917,7 +928,6 @@ static boolean UDP_Socket(void) ...@@ -917,7 +928,6 @@ static boolean UDP_Socket(void)
mysockets[s] = ERRSOCKET; mysockets[s] = ERRSOCKET;
for (s = 0; s < MAXNETNODES+1; s++) for (s = 0; s < MAXNETNODES+1; s++)
nodesocket[s] = ERRSOCKET; nodesocket[s] = ERRSOCKET;
FD_ZERO(&masterset);
s = 0; s = 0;
memset(&hints, 0x00, sizeof (hints)); memset(&hints, 0x00, sizeof (hints));
...@@ -926,16 +936,25 @@ static boolean UDP_Socket(void) ...@@ -926,16 +936,25 @@ static boolean UDP_Socket(void)
hints.ai_socktype = SOCK_DGRAM; hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP; hints.ai_protocol = IPPROTO_UDP;
#ifdef HAVE_IPV6
if (!b_ipv6)
I_OutputMsg("Disabling IPv6 support at runtime\n");
#else
I_OutputMsg("Compiled without IPv6 support\n");
#endif
if (serverrunning) if (serverrunning)
serv = serverport_name; serv = serverport_name;
else else
serv = clientport_name; serv = clientport_name;
if (b_ipv4)
{
if (M_CheckParm("-bindaddr")) if (M_CheckParm("-bindaddr"))
{ {
while (M_IsNextParm()) while (M_IsNextParm())
{ {
gaie = I_getaddrinfo(M_GetNextParm(), serv, &hints, &ai); gaie = getaddrinfo(M_GetNextParm(), serv, &hints, &ai);
if (gaie == 0) if (gaie == 0)
{ {
runp = ai; runp = ai;
...@@ -944,19 +963,18 @@ static boolean UDP_Socket(void) ...@@ -944,19 +963,18 @@ static boolean UDP_Socket(void)
mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen); mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen);
if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET) if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET)
{ {
FD_SET(mysockets[s], &masterset);
myfamily[s] = hints.ai_family; myfamily[s] = hints.ai_family;
s++; s++;
} }
runp = runp->ai_next; runp = runp->ai_next;
} }
I_freeaddrinfo(ai); freeaddrinfo(ai);
} }
} }
} }
else else
{ {
gaie = I_getaddrinfo("0.0.0.0", serv, &hints, &ai); gaie = getaddrinfo("0.0.0.0", serv, &hints, &ai);
if (gaie == 0) if (gaie == 0)
{ {
runp = ai; runp = ai;
...@@ -965,7 +983,6 @@ static boolean UDP_Socket(void) ...@@ -965,7 +983,6 @@ static boolean UDP_Socket(void)
mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen); mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen);
if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET) if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET)
{ {
FD_SET(mysockets[s], &masterset);
myfamily[s] = hints.ai_family; myfamily[s] = hints.ai_family;
s++; s++;
#ifdef HAVE_MINIUPNPC #ifdef HAVE_MINIUPNPC
...@@ -978,7 +995,8 @@ static boolean UDP_Socket(void) ...@@ -978,7 +995,8 @@ static boolean UDP_Socket(void)
} }
runp = runp->ai_next; runp = runp->ai_next;
} }
I_freeaddrinfo(ai); freeaddrinfo(ai);
}
} }
} }
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
...@@ -989,7 +1007,7 @@ static boolean UDP_Socket(void) ...@@ -989,7 +1007,7 @@ static boolean UDP_Socket(void)
{ {
while (M_IsNextParm()) while (M_IsNextParm())
{ {
gaie = I_getaddrinfo(M_GetNextParm(), serv, &hints, &ai); gaie = getaddrinfo(M_GetNextParm(), serv, &hints, &ai);
if (gaie == 0) if (gaie == 0)
{ {
runp = ai; runp = ai;
...@@ -998,19 +1016,18 @@ static boolean UDP_Socket(void) ...@@ -998,19 +1016,18 @@ static boolean UDP_Socket(void)
mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen); mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen);
if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET) if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET)
{ {
FD_SET(mysockets[s], &masterset);
myfamily[s] = hints.ai_family; myfamily[s] = hints.ai_family;
s++; s++;
} }
runp = runp->ai_next; runp = runp->ai_next;
} }
I_freeaddrinfo(ai); freeaddrinfo(ai);
} }
} }
} }
else else
{ {
gaie = I_getaddrinfo("::", serv, &hints, &ai); gaie = getaddrinfo("::", serv, &hints, &ai);
if (gaie == 0) if (gaie == 0)
{ {
runp = ai; runp = ai;
...@@ -1019,13 +1036,12 @@ static boolean UDP_Socket(void) ...@@ -1019,13 +1036,12 @@ static boolean UDP_Socket(void)
mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen); mysockets[s] = UDP_Bind(runp->ai_family, runp->ai_addr, (socklen_t)runp->ai_addrlen);
if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET) if (mysockets[s] != (SOCKET_TYPE)ERRSOCKET)
{ {
FD_SET(mysockets[s], &masterset);
myfamily[s] = hints.ai_family; myfamily[s] = hints.ai_family;
s++; s++;
} }
runp = runp->ai_next; runp = runp->ai_next;
} }
I_freeaddrinfo(ai); freeaddrinfo(ai);
} }
} }
} }
...@@ -1047,11 +1063,14 @@ static boolean UDP_Socket(void) ...@@ -1047,11 +1063,14 @@ static boolean UDP_Socket(void)
s = 0; s = 0;
if (b_ipv4)
{
// setup broadcast adress to BROADCASTADDR entry // setup broadcast adress to BROADCASTADDR entry
broadcastaddress[s].any.sa_family = AF_INET; broadcastaddress[s].any.sa_family = AF_INET;
broadcastaddress[s].ip4.sin_port = htons(atoi(DEFAULTPORT)); broadcastaddress[s].ip4.sin_port = htons(atoi(DEFAULTPORT));
broadcastaddress[s].ip4.sin_addr.s_addr = htonl(INADDR_BROADCAST); broadcastaddress[s].ip4.sin_addr.s_addr = htonl(INADDR_BROADCAST);
s++; s++;
}
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
if (b_ipv6) if (b_ipv6)
...@@ -1067,7 +1086,7 @@ static boolean UDP_Socket(void) ...@@ -1067,7 +1086,7 @@ static boolean UDP_Socket(void)
broadcastaddresses = s; broadcastaddresses = s;
doomcom->extratics = 1; // internet is very high ping extratics = 1; // internet is very high ping
return true; return true;
} }
...@@ -1075,14 +1094,16 @@ static boolean UDP_Socket(void) ...@@ -1075,14 +1094,16 @@ static boolean UDP_Socket(void)
boolean I_InitTcpDriver(void) boolean I_InitTcpDriver(void)
{ {
boolean tcp_was_up = init_tcp_driver; boolean tcp_was_up = init_tcp_driver;
#ifdef __EMSCRIPTEN__
I_OutputMsg("Compiled without networking support\n");
return false;
#endif
if (!init_tcp_driver) if (!init_tcp_driver)
{ {
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
#ifdef USE_WINSOCK2
const WORD VerNeed = MAKEWORD(2,2); const WORD VerNeed = MAKEWORD(2,2);
#else
const WORD VerNeed = MAKEWORD(1,1);
#endif
WSADATA WSAData; WSADATA WSAData;
const int WSAresult = WSAStartup(VerNeed, &WSAData); const int WSAresult = WSAStartup(VerNeed, &WSAData);
if (WSAresult != 0) if (WSAresult != 0)
...@@ -1109,21 +1130,12 @@ boolean I_InitTcpDriver(void) ...@@ -1109,21 +1130,12 @@ boolean I_InitTcpDriver(void)
if (WSAresult != WSAVERNOTSUPPORTED) if (WSAresult != WSAVERNOTSUPPORTED)
CONS_Debug(DBG_NETPLAY, "WinSock(TCP/IP) error: %s\n",WSError); CONS_Debug(DBG_NETPLAY, "WinSock(TCP/IP) error: %s\n",WSError);
} }
#ifdef USE_WINSOCK2
if(LOBYTE(WSAData.wVersion) != 2 || if(LOBYTE(WSAData.wVersion) != 2 ||
HIBYTE(WSAData.wVersion) != 2) HIBYTE(WSAData.wVersion) != 2)
{ {
WSACleanup(); WSACleanup();
CONS_Debug(DBG_NETPLAY, "No WinSock(TCP/IP) 2.2 driver detected\n"); CONS_Debug(DBG_NETPLAY, "No WinSock(TCP/IP) 2.2 driver detected\n");
} }
#else
if (LOBYTE(WSAData.wVersion) != 1 ||
HIBYTE(WSAData.wVersion) != 1)
{
WSACleanup();
CONS_Debug(DBG_NETPLAY, "No WinSock(TCP/IP) 1.1 driver detected\n");
}
#endif
CONS_Debug(DBG_NETPLAY, "WinSock description: %s\n",WSAData.szDescription); CONS_Debug(DBG_NETPLAY, "WinSock description: %s\n",WSAData.szDescription);
CONS_Debug(DBG_NETPLAY, "WinSock System Status: %s\n",WSAData.szSystemStatus); CONS_Debug(DBG_NETPLAY, "WinSock System Status: %s\n",WSAData.szSystemStatus);
#endif #endif
...@@ -1134,10 +1146,10 @@ boolean I_InitTcpDriver(void) ...@@ -1134,10 +1146,10 @@ boolean I_InitTcpDriver(void)
{ {
I_AddExitFunc(I_ShutdownTcpDriver); I_AddExitFunc(I_ShutdownTcpDriver);
#ifdef HAVE_MINIUPNPC #ifdef HAVE_MINIUPNPC
if (M_CheckParm("-useUPnP")) if (M_CheckParm("-noUPnP"))
I_InitUPnP();
else
UPNP_support = false; UPNP_support = false;
else
I_InitUPnP();
#endif #endif
} }
return init_tcp_driver; return init_tcp_driver;
...@@ -1145,16 +1157,13 @@ boolean I_InitTcpDriver(void) ...@@ -1145,16 +1157,13 @@ boolean I_InitTcpDriver(void)
static void SOCK_CloseSocket(void) static void SOCK_CloseSocket(void)
{ {
for (size_t i=0; i < MAXNETNODES+1; i++) for (size_t i=0; i < mysocketses; i++)
{
if (mysockets[i] != (SOCKET_TYPE)ERRSOCKET
&& FD_ISSET(mysockets[i], &masterset))
{ {
FD_CLR(mysockets[i], &masterset); if (mysockets[i] != (SOCKET_TYPE)ERRSOCKET)
close(mysockets[i]); close(mysockets[i]);
}
mysockets[i] = ERRSOCKET; mysockets[i] = ERRSOCKET;
} }
mysocketses = 0;
} }
void I_ShutdownTcpDriver(void) void I_ShutdownTcpDriver(void)
...@@ -1163,7 +1172,6 @@ void I_ShutdownTcpDriver(void) ...@@ -1163,7 +1172,6 @@ void I_ShutdownTcpDriver(void)
CONS_Printf("I_ShutdownTcpDriver: "); CONS_Printf("I_ShutdownTcpDriver: ");
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
WS_addrinfocleanup();
WSACleanup(); WSACleanup();
#endif #endif
CONS_Printf("shut down\n"); CONS_Printf("shut down\n");
...@@ -1173,7 +1181,7 @@ void I_ShutdownTcpDriver(void) ...@@ -1173,7 +1181,7 @@ void I_ShutdownTcpDriver(void)
static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port) static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port)
{ {
SINT8 newnode = -1; SINT8 newnode = -1;
struct my_addrinfo *ai = NULL, *runp, hints; addrinfo_t *ai = NULL, *runp, hints;
int gaie; int gaie;
size_t i; size_t i;
...@@ -1183,19 +1191,19 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port) ...@@ -1183,19 +1191,19 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port)
DEBFILE(va("Creating new node: %s@%s\n", address, port)); DEBFILE(va("Creating new node: %s@%s\n", address, port));
memset (&hints, 0x00, sizeof (hints)); memset (&hints, 0x00, sizeof (hints));
hints.ai_flags = 0; hints.ai_flags = AI_ADDRCONFIG;
hints.ai_family = AF_UNSPEC; hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM; hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP; hints.ai_protocol = IPPROTO_UDP;
gaie = I_getaddrinfo(address, port, &hints, &ai); gaie = getaddrinfo(address, port, &hints, &ai);
if (gaie == 0) if (gaie != 0)
{ return -1;
newnode = getfreenode(); newnode = getfreenode();
}
if (newnode == -1) if (newnode == -1)
{ {
I_freeaddrinfo(ai); freeaddrinfo(ai);
return -1; return -1;
} }
else else
...@@ -1206,23 +1214,19 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port) ...@@ -1206,23 +1214,19 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port)
// test ip address of server // test ip address of server
for (i = 0; i < mysocketses; ++i) for (i = 0; i < mysocketses; ++i)
{ {
/* sendto tests that there is a network to this if (runp->ai_addr->sa_family == myfamily[i])
address */
if (runp->ai_addr->sa_family == myfamily[i] &&
sendto(mysockets[i], NULL, 0, 0,
runp->ai_addr, runp->ai_addrlen) == 0)
{ {
memcpy(&clientaddress[newnode], runp->ai_addr, runp->ai_addrlen); memcpy(&clientaddress[newnode], runp->ai_addr, runp->ai_addrlen);
break; break;
} }
} }
if (i < mysocketses) if (i >= mysocketses)
runp = runp->ai_next; runp = runp->ai_next;
else else
break; break;
} }
I_freeaddrinfo(ai); freeaddrinfo(ai);
return newnode; return newnode;
} }
...@@ -1240,12 +1244,6 @@ static boolean SOCK_OpenSocket(void) ...@@ -1240,12 +1244,6 @@ static boolean SOCK_OpenSocket(void)
I_NetFreeNodenum = SOCK_FreeNodenum; I_NetFreeNodenum = SOCK_FreeNodenum;
I_NetMakeNodewPort = SOCK_NetMakeNodewPort; I_NetMakeNodewPort = SOCK_NetMakeNodewPort;
#ifdef SELECTTEST
// seem like not work with libsocket : (
I_NetCanSend = SOCK_CanSend;
I_NetCanGet = SOCK_CanGet;
#endif
// build the socket but close it first // build the socket but close it first
SOCK_CloseSocket(); SOCK_CloseSocket();
return UDP_Socket(); return UDP_Socket();
...@@ -1255,9 +1253,9 @@ static boolean SOCK_Ban(INT32 node) ...@@ -1255,9 +1253,9 @@ static boolean SOCK_Ban(INT32 node)
{ {
if (node > MAXNETNODES) if (node > MAXNETNODES)
return false; return false;
if (numbans == MAXBANS)
return false;
banned = Z_Realloc(banned, sizeof(*banned) * (numbans+1), PU_STATIC, NULL);
bannedmask = Z_Realloc(bannedmask, sizeof(*bannedmask) * (numbans+1), PU_STATIC, NULL);
M_Memcpy(&banned[numbans], &clientaddress[node], sizeof (mysockaddr_t)); M_Memcpy(&banned[numbans], &clientaddress[node], sizeof (mysockaddr_t));
if (banned[numbans].any.sa_family == AF_INET) if (banned[numbans].any.sa_family == AF_INET)
{ {
...@@ -1268,7 +1266,7 @@ static boolean SOCK_Ban(INT32 node) ...@@ -1268,7 +1266,7 @@ static boolean SOCK_Ban(INT32 node)
else if (banned[numbans].any.sa_family == AF_INET6) else if (banned[numbans].any.sa_family == AF_INET6)
{ {
banned[numbans].ip6.sin6_port = 0; banned[numbans].ip6.sin6_port = 0;
bannedmask[numbans] = 128; bannedmask[numbans] = 64;
} }
#endif #endif
numbans++; numbans++;
...@@ -1277,10 +1275,10 @@ static boolean SOCK_Ban(INT32 node) ...@@ -1277,10 +1275,10 @@ static boolean SOCK_Ban(INT32 node)
static boolean SOCK_SetBanAddress(const char *address, const char *mask) static boolean SOCK_SetBanAddress(const char *address, const char *mask)
{ {
struct my_addrinfo *ai, *runp, hints; addrinfo_t *ai, *runp, hints;
int gaie; int gaie;
if (numbans == MAXBANS || !address) if (!address)
return false; return false;
memset(&hints, 0x00, sizeof(hints)); memset(&hints, 0x00, sizeof(hints));
...@@ -1289,21 +1287,23 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask) ...@@ -1289,21 +1287,23 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask)
hints.ai_socktype = SOCK_DGRAM; hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP; hints.ai_protocol = IPPROTO_UDP;
gaie = I_getaddrinfo(address, "0", &hints, &ai); gaie = getaddrinfo(address, "0", &hints, &ai);
if (gaie != 0) if (gaie != 0)
return false; return false;
runp = ai; runp = ai;
while(runp != NULL && numbans != MAXBANS) while(runp != NULL)
{ {
banned = Z_Realloc(banned, sizeof(*banned) * (numbans+1), PU_STATIC, NULL);
bannedmask = Z_Realloc(bannedmask, sizeof(*bannedmask) * (numbans+1), PU_STATIC, NULL);
memcpy(&banned[numbans], runp->ai_addr, runp->ai_addrlen); memcpy(&banned[numbans], runp->ai_addr, runp->ai_addrlen);
if (mask) if (mask)
bannedmask[numbans] = (UINT8)atoi(mask); bannedmask[numbans] = (UINT8)atoi(mask);
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
else if (runp->ai_family == AF_INET6) else if (runp->ai_family == AF_INET6)
bannedmask[numbans] = 128; bannedmask[numbans] = 64;
#endif #endif
else else
bannedmask[numbans] = 32; bannedmask[numbans] = 32;
...@@ -1312,13 +1312,13 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask) ...@@ -1312,13 +1312,13 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask)
bannedmask[numbans] = 32; bannedmask[numbans] = 32;
#ifdef HAVE_IPV6 #ifdef HAVE_IPV6
else if (bannedmask[numbans] > 128 && runp->ai_family == AF_INET6) else if (bannedmask[numbans] > 128 && runp->ai_family == AF_INET6)
bannedmask[numbans] = 128; bannedmask[numbans] = 64;
#endif #endif
numbans++; numbans++;
runp = runp->ai_next; runp = runp->ai_next;
} }
I_freeaddrinfo(ai); freeaddrinfo(ai);
return true; return true;
} }
...@@ -1326,6 +1326,10 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask) ...@@ -1326,6 +1326,10 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask)
static void SOCK_ClearBans(void) static void SOCK_ClearBans(void)
{ {
numbans = 0; numbans = 0;
Z_Free(banned);
banned = NULL;
Z_Free(bannedmask);
bannedmask = NULL;
} }
boolean I_InitTcpNetwork(void) boolean I_InitTcpNetwork(void)
...@@ -1362,25 +1366,24 @@ boolean I_InitTcpNetwork(void) ...@@ -1362,25 +1366,24 @@ boolean I_InitTcpNetwork(void)
// in-game. // in-game.
// Since Boris has implemented join in-game, there is no actual need for specifying a // Since Boris has implemented join in-game, there is no actual need for specifying a
// particular number here. // particular number here.
// FIXME: for dedicated server, numnodes needs to be set to 0 upon start // FIXME: for dedicated server, numnetnodes needs to be set to 0 upon start
if (dedicated) if (dedicated)
doomcom->numnodes = 0; numnetnodes = 0;
/* else if (M_IsNextParm()) /* else if (M_IsNextParm())
doomcom->numnodes = (INT16)atoi(M_GetNextParm());*/ numnetnodes = (INT16)atoi(M_GetNextParm());*/
else else
doomcom->numnodes = 1; numnetnodes = 1;
if (doomcom->numnodes < 0) if (numnetnodes < 0)
doomcom->numnodes = 0; numnetnodes = 0;
if (doomcom->numnodes > MAXNETNODES) if (numnetnodes > MAXNETNODES)
doomcom->numnodes = MAXNETNODES; numnetnodes = MAXNETNODES;
// server // server
servernode = 0; servernode = 0;
// FIXME: // FIXME:
// ??? and now ? // ??? and now ?
// server on a big modem ??? 4*isdn // server on a big modem ??? 4*isdn
net_bandwidth = 16000;
hardware_MAXPACKETLENGTH = INETPACKETLENGTH; hardware_MAXPACKETLENGTH = INETPACKETLENGTH;
ret = true; ret = true;
...@@ -1409,7 +1412,6 @@ boolean I_InitTcpNetwork(void) ...@@ -1409,7 +1412,6 @@ boolean I_InitTcpNetwork(void)
// so we're on a LAN // so we're on a LAN
COM_BufAddText("connect any\n"); COM_BufAddText("connect any\n");
net_bandwidth = 800000;
hardware_MAXPACKETLENGTH = MAXPACKETLENGTH; hardware_MAXPACKETLENGTH = MAXPACKETLENGTH;
} }
} }
...@@ -1434,5 +1436,3 @@ boolean Net_IsNodeIPv6(INT32 node) ...@@ -1434,5 +1436,3 @@ boolean Net_IsNodeIPv6(INT32 node)
return clientaddress[node].any.sa_family == AF_INET6; return clientaddress[node].any.sa_family == AF_INET6;
#endif #endif
} }
#include "i_addrinfo.c"
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team. // Copyright (C) 1998-2000 by DooM Legacy Team.
// Copyright (C) 1999-2023 by Sonic Team Junior. // Copyright (C) 1999-2024 by Sonic Team Junior.
// Copyright (C) 2020-2023 by James R. // Copyright (C) 2020-2023 by James R.
// //
// This program is free software distributed under the // This program is free software distributed under the
...@@ -35,24 +35,22 @@ static boolean MSUpdateAgain; ...@@ -35,24 +35,22 @@ static boolean MSUpdateAgain;
static time_t MSLastPing; static time_t MSLastPing;
#ifdef HAVE_THREADS
static I_mutex MSMutex; static I_mutex MSMutex;
static I_cond MSCond; static I_cond MSCond;
# define Lock_state() I_lock_mutex (&MSMutex) # define Lock_state() I_lock_mutex (&MSMutex)
# define Unlock_state() I_unlock_mutex (MSMutex) # define Unlock_state() I_unlock_mutex (MSMutex)
#else/*HAVE_THREADS*/
# define Lock_state()
# define Unlock_state()
#endif/*HAVE_THREADS*/
static void Command_Listserv_f(void); static void Command_Listserv_f(void);
#endif/*MASTERSERVER*/ #endif/*MASTERSERVER*/
static boolean ServerName_CanChange (const char*);
static void Update_parameters (void); static void Update_parameters (void);
static void MasterServer_OnChange(void); static void MasterServer_OnChange(void);
static void RoomId_OnChange(void);
static CV_PossibleValue_t masterserver_update_rate_cons_t[] = { static CV_PossibleValue_t masterserver_update_rate_cons_t[] = {
{2, "MIN"}, {2, "MIN"},
...@@ -61,19 +59,19 @@ static CV_PossibleValue_t masterserver_update_rate_cons_t[] = { ...@@ -61,19 +59,19 @@ static CV_PossibleValue_t masterserver_update_rate_cons_t[] = {
}; };
consvar_t cv_masterserver = CVAR_INIT ("masterserver", "https://ds.ms.srb2.org/MS/0", CV_SAVE|CV_CALL, NULL, MasterServer_OnChange); consvar_t cv_masterserver = CVAR_INIT ("masterserver", "https://ds.ms.srb2.org/MS/0", CV_SAVE|CV_CALL, NULL, MasterServer_OnChange);
consvar_t cv_servername = CVAR_INIT ("servername", "SRB2 server", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, NULL, Update_parameters); consvar_t cv_servername = CVAR_INIT_WITH_CALLBACKS ("servername", "SRB2 server", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT|CV_ALLOWLUA, NULL, Update_parameters, ServerName_CanChange);
consvar_t cv_masterserver_update_rate = CVAR_INIT ("masterserver_update_rate", "15", CV_SAVE|CV_CALL|CV_NOINIT, masterserver_update_rate_cons_t, Update_parameters); consvar_t cv_masterserver_update_rate = CVAR_INIT ("masterserver_update_rate", "15", CV_SAVE|CV_CALL|CV_NOINIT, masterserver_update_rate_cons_t, Update_parameters);
CV_PossibleValue_t cv_masterserver_room_values[] = {{-1, "MIN"}, {999999999, "MAX"}, {0, NULL}};
consvar_t cv_masterserver_room_id = CVAR_INIT ("masterserver_room_id", "-1", CV_CALL, cv_masterserver_room_values, RoomId_OnChange);
INT16 ms_RoomId = -1; static INT16 ms_RoomId = -1;
#if defined (MASTERSERVER) && defined (HAVE_THREADS)
int ms_QueryId; int ms_QueryId;
I_mutex ms_QueryId_mutex; I_mutex ms_QueryId_mutex;
msg_server_t *ms_ServerList; msg_server_t *ms_ServerList;
I_mutex ms_ServerList_mutex; I_mutex ms_ServerList_mutex;
#endif
UINT16 current_port = 0; UINT16 current_port = 0;
...@@ -90,6 +88,7 @@ void AddMServCommands(void) ...@@ -90,6 +88,7 @@ void AddMServCommands(void)
{ {
CV_RegisterVar(&cv_masterserver); CV_RegisterVar(&cv_masterserver);
CV_RegisterVar(&cv_masterserver_update_rate); CV_RegisterVar(&cv_masterserver_update_rate);
CV_RegisterVar(&cv_masterserver_room_id);
CV_RegisterVar(&cv_masterserver_timeout); CV_RegisterVar(&cv_masterserver_timeout);
CV_RegisterVar(&cv_masterserver_debug); CV_RegisterVar(&cv_masterserver_debug);
CV_RegisterVar(&cv_masterserver_token); CV_RegisterVar(&cv_masterserver_token);
...@@ -104,13 +103,9 @@ void AddMServCommands(void) ...@@ -104,13 +103,9 @@ void AddMServCommands(void)
static void WarnGUI (void) static void WarnGUI (void)
{ {
#ifdef HAVE_THREADS
I_lock_mutex(&m_menu_mutex); I_lock_mutex(&m_menu_mutex);
#endif
M_StartMessage(M_GetText("There was a problem connecting to\nthe Master Server\n\nCheck the console for details.\n"), NULL, MM_NOTHING); M_StartMessage(M_GetText("There was a problem connecting to\nthe Master Server\n\nCheck the console for details.\n"), NULL, MM_NOTHING);
#ifdef HAVE_THREADS
I_unlock_mutex(m_menu_mutex); I_unlock_mutex(m_menu_mutex);
#endif
} }
#define NUM_LIST_SERVER MAXSERVERLIST #define NUM_LIST_SERVER MAXSERVERLIST
...@@ -154,14 +149,12 @@ char *GetMODVersion(int id) ...@@ -154,14 +149,12 @@ char *GetMODVersion(int id)
c = HMS_compare_mod_version(buffer, 16); c = HMS_compare_mod_version(buffer, 16);
#ifdef HAVE_THREADS
I_lock_mutex(&ms_QueryId_mutex); I_lock_mutex(&ms_QueryId_mutex);
{ {
if (id != ms_QueryId) if (id != ms_QueryId)
c = -1; c = -1;
} }
I_unlock_mutex(ms_QueryId_mutex); I_unlock_mutex(ms_QueryId_mutex);
#endif
if (c > 0) if (c > 0)
return buffer; return buffer;
...@@ -234,7 +227,8 @@ Finish_update (void) ...@@ -234,7 +227,8 @@ Finish_update (void)
if (registered) if (registered)
{ {
if (HMS_update()) // ms is idempotent, so register and update is the same thing
if (HMS_register())
{ {
Lock_state(); Lock_state();
{ {
...@@ -288,9 +282,7 @@ Finish_unlist (void) ...@@ -288,9 +282,7 @@ Finish_unlist (void)
} }
Unlock_state(); Unlock_state();
#ifdef HAVE_THREADS
I_wake_all_cond(&MSCond); I_wake_all_cond(&MSCond);
#endif
} }
Lock_state(); Lock_state();
...@@ -301,7 +293,6 @@ Finish_unlist (void) ...@@ -301,7 +293,6 @@ Finish_unlist (void)
Unlock_state(); Unlock_state();
} }
#ifdef HAVE_THREADS
static int * static int *
Server_id (void) Server_id (void)
{ {
...@@ -396,55 +387,69 @@ Change_masterserver_thread (char *api) ...@@ -396,55 +387,69 @@ Change_masterserver_thread (char *api)
HMS_set_api(api); HMS_set_api(api);
} }
#endif/*HAVE_THREADS*/
void RegisterServer(void) void RegisterServer(void)
{ {
#ifdef MASTERSERVER if (I_can_thread())
#ifdef HAVE_THREADS {
I_spawn_thread( void *nsid = New_server_id();
if (!I_spawn_thread(
"register-server", "register-server",
(I_thread_fn)Register_server_thread, (I_thread_fn)Register_server_thread,
New_server_id() nsid
); ))
#else {
free(nsid);
}
}
else
{
Finish_registration(); Finish_registration();
#endif }
#endif/*MASTERSERVER*/
} }
static void UpdateServer(void) static void UpdateServer(void)
{ {
#ifdef HAVE_THREADS if (I_can_thread())
I_spawn_thread( {
void *sid = Server_id();
if (!I_spawn_thread(
"update-server", "update-server",
(I_thread_fn)Update_server_thread, (I_thread_fn)Update_server_thread,
Server_id() sid
); ))
#else {
free(sid);
}
}
else
{
Finish_update(); Finish_update();
#endif }
} }
void UnregisterServer(void) void UnregisterServer(void)
{ {
#ifdef MASTERSERVER if (I_can_thread())
#ifdef HAVE_THREADS {
I_spawn_thread( if (!I_spawn_thread(
"unlist-server", "unlist-server",
(I_thread_fn)Unlist_server_thread, (I_thread_fn)Unlist_server_thread,
Server_id() Server_id()
); ))
#else {
;
}
}
else
{
Finish_unlist(); Finish_unlist();
#endif }
#endif/*MASTERSERVER*/
} }
static boolean static boolean Online(void)
Online (void)
{ {
return ( serverrunning && ms_RoomId > 0 ); return ( serverrunning && cv_masterserver_room_id.value > 0 );
} }
static inline void SendPingToMasterServer(void) static inline void SendPingToMasterServer(void)
...@@ -476,26 +481,44 @@ static inline void SendPingToMasterServer(void) ...@@ -476,26 +481,44 @@ static inline void SendPingToMasterServer(void)
void MasterClient_Ticker(void) void MasterClient_Ticker(void)
{ {
#ifdef MASTERSERVER
SendPingToMasterServer(); SendPingToMasterServer();
#endif
} }
static void static void
Set_api (const char *api) Set_api (const char *api)
{ {
#ifdef HAVE_THREADS char *dapi = strdup(api);
I_spawn_thread( if (I_can_thread())
{
if (!I_spawn_thread(
"change-masterserver", "change-masterserver",
(I_thread_fn)Change_masterserver_thread, (I_thread_fn)Change_masterserver_thread,
strdup(api) dapi
); ))
#else {
HMS_set_api(strdup(api)); free(dapi);
#endif }
} }
else
{
HMS_set_api(dapi);
}
}
#else /*MASTERSERVER*/
#endif/*MASTERSERVER*/ void RegisterServer(void) {}
void UnregisterServer(void) {}
#endif
static boolean ServerName_CanChange(const char* newvalue)
{
if (strlen(newvalue) < MAXSERVERNAME)
return true;
CONS_Alert(CONS_NOTICE, "The server name must be shorter than %d characters\n", MAXSERVERNAME);
return false;
}
static void static void
Update_parameters (void) Update_parameters (void)
...@@ -523,6 +546,12 @@ Update_parameters (void) ...@@ -523,6 +546,12 @@ Update_parameters (void)
#endif/*MASTERSERVER*/ #endif/*MASTERSERVER*/
} }
static void RoomId_OnChange(void)
{
if (ms_RoomId != cv_masterserver_room_id.value)
UpdateServer();
}
static void MasterServer_OnChange(void) static void MasterServer_OnChange(void)
{ {
#ifdef MASTERSERVER #ifdef MASTERSERVER
......
...@@ -66,22 +66,16 @@ typedef struct ...@@ -66,22 +66,16 @@ typedef struct
extern consvar_t cv_masterserver, cv_servername; extern consvar_t cv_masterserver, cv_servername;
extern consvar_t cv_masterserver_update_rate; extern consvar_t cv_masterserver_update_rate;
extern consvar_t cv_masterserver_room_id;
extern consvar_t cv_masterserver_timeout; extern consvar_t cv_masterserver_timeout;
extern consvar_t cv_masterserver_debug; extern consvar_t cv_masterserver_debug;
extern consvar_t cv_masterserver_token; extern consvar_t cv_masterserver_token;
// < 0 to not connect (usually -1) (offline mode)
// == 0 to show all rooms, not a valid hosting room
// anything else is whatever room the MS assigns to that number (online mode)
extern INT16 ms_RoomId;
#ifdef HAVE_THREADS
extern int ms_QueryId; extern int ms_QueryId;
extern I_mutex ms_QueryId_mutex; extern I_mutex ms_QueryId_mutex;
extern msg_server_t *ms_ServerList; extern msg_server_t *ms_ServerList;
extern I_mutex ms_ServerList_mutex; extern I_mutex ms_ServerList_mutex;
#endif
void RegisterServer(void); void RegisterServer(void);
void UnregisterServer(void); void UnregisterServer(void);
...@@ -103,7 +97,6 @@ void HMS_set_api (char *api); ...@@ -103,7 +97,6 @@ void HMS_set_api (char *api);
int HMS_fetch_rooms (int joining, int id); int HMS_fetch_rooms (int joining, int id);
int HMS_register (void); int HMS_register (void);
int HMS_unlist (void); int HMS_unlist (void);
int HMS_update (void);
void HMS_list_servers (void); void HMS_list_servers (void);
msg_server_t * HMS_fetch_servers (msg_server_t *list, int room, int id); msg_server_t * HMS_fetch_servers (msg_server_t *list, int room, int id);
int HMS_compare_mod_version (char *buffer, size_t size_of_buffer); int HMS_compare_mod_version (char *buffer, size_t size_of_buffer);
......
...@@ -21,6 +21,16 @@ ...@@ -21,6 +21,16 @@
#include "../z_zone.h" #include "../z_zone.h"
#include "../doomtype.h" #include "../doomtype.h"
typedef struct textcmdbuf_s textcmdbuf_t;
struct textcmdbuf_s
{
textcmdbuf_t *next;
UINT8 cmd[MAXTEXTCMD];
};
static textcmdbuf_t *textcmdbuf;
static textcmdbuf_t *textcmdbuf2;
textcmdtic_t *textcmds[TEXTCMD_HASH_SIZE] = {NULL}; textcmdtic_t *textcmds[TEXTCMD_HASH_SIZE] = {NULL};
UINT8 localtextcmd[MAXTEXTCMD]; UINT8 localtextcmd[MAXTEXTCMD];
UINT8 localtextcmd2[MAXTEXTCMD]; // splitscreen UINT8 localtextcmd2[MAXTEXTCMD]; // splitscreen
...@@ -37,21 +47,57 @@ void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum)) ...@@ -37,21 +47,57 @@ void RegisterNetXCmd(netxcmd_t id, void (*cmd_f)(UINT8 **p, INT32 playernum))
listnetxcmd[id] = cmd_f; listnetxcmd[id] = cmd_f;
} }
static void WriteNetXCmd(UINT8 *cmd, netxcmd_t id, const void *param, size_t nparam)
{
cmd[0]++;
cmd[cmd[0]] = (UINT8)id;
if (param && nparam)
{
M_Memcpy(&cmd[cmd[0]+1], param, nparam);
cmd[0] = (UINT8)(cmd[0] + (UINT8)nparam);
}
}
void SendNetXCmd(netxcmd_t id, const void *param, size_t nparam) void SendNetXCmd(netxcmd_t id, const void *param, size_t nparam)
{ {
if (localtextcmd[0]+2+nparam > MAXTEXTCMD) if (localtextcmd[0]+2+nparam > MAXTEXTCMD)
{ {
textcmdbuf_t *buf = textcmdbuf;
if (2+nparam > MAXTEXTCMD)
{
CONS_Alert(CONS_ERROR, M_GetText("packet too large to fit NetXCmd, cannot add netcmd %d! (size: %s, max: %d)\n"), id, sizeu1(2+nparam), MAXTEXTCMD);
return;
}
// for future reference: if (cv_debug) != debug disabled. // for future reference: if (cv_debug) != debug disabled.
CONS_Alert(CONS_ERROR, M_GetText("NetXCmd buffer full, cannot add netcmd %d! (size: %d, needed: %s)\n"), id, localtextcmd[0], sizeu1(nparam)); CONS_Alert(CONS_NOTICE, M_GetText("NetXCmd buffer full, delaying netcmd %d... (size: %d, needed: %s)\n"), id, localtextcmd[0], sizeu1(nparam));
if (buf == NULL)
{
textcmdbuf = Z_Malloc(sizeof(textcmdbuf_t), PU_STATIC, NULL);
textcmdbuf->cmd[0] = 0;
textcmdbuf->next = NULL;
WriteNetXCmd(textcmdbuf->cmd, id, param, nparam);
return; return;
} }
localtextcmd[0]++;
localtextcmd[localtextcmd[0]] = (UINT8)id; while (buf->next != NULL)
if (param && nparam) buf = buf->next;
if (buf->cmd[0]+2+nparam > MAXTEXTCMD)
{
buf->next = Z_Malloc(sizeof(textcmdbuf_t), PU_STATIC, NULL);
buf->next->cmd[0] = 0;
buf->next->next = NULL;
WriteNetXCmd(buf->next->cmd, id, param, nparam);
}
else
{ {
M_Memcpy(&localtextcmd[localtextcmd[0]+1], param, nparam); WriteNetXCmd(buf->cmd, id, param, nparam);
localtextcmd[0] = (UINT8)(localtextcmd[0] + (UINT8)nparam); }
return;
} }
WriteNetXCmd(localtextcmd, id, param, nparam);
} }
// splitscreen player // splitscreen player
...@@ -59,16 +105,42 @@ void SendNetXCmd2(netxcmd_t id, const void *param, size_t nparam) ...@@ -59,16 +105,42 @@ void SendNetXCmd2(netxcmd_t id, const void *param, size_t nparam)
{ {
if (localtextcmd2[0]+2+nparam > MAXTEXTCMD) if (localtextcmd2[0]+2+nparam > MAXTEXTCMD)
{ {
I_Error("No more place in the buffer for netcmd %d\n",id); textcmdbuf_t *buf = textcmdbuf2;
if (2+nparam > MAXTEXTCMD)
{
CONS_Alert(CONS_ERROR, M_GetText("packet too large to fit NetXCmd, cannot add netcmd %d! (size: %s, max: %d)\n"), id, sizeu1(2+nparam), MAXTEXTCMD);
return; return;
} }
localtextcmd2[0]++;
localtextcmd2[localtextcmd2[0]] = (UINT8)id; // for future reference: if (cv_debug) != debug disabled.
if (param && nparam) CONS_Alert(CONS_NOTICE, M_GetText("NetXCmd buffer full, delaying netcmd %d... (size: %d, needed: %s)\n"), id, localtextcmd2[0], sizeu1(nparam));
if (buf == NULL)
{
textcmdbuf2 = Z_Malloc(sizeof(textcmdbuf_t), PU_STATIC, NULL);
textcmdbuf2->cmd[0] = 0;
textcmdbuf2->next = NULL;
WriteNetXCmd(textcmdbuf2->cmd, id, param, nparam);
return;
}
while (buf->next != NULL)
buf = buf->next;
if (buf->cmd[0]+2+nparam > MAXTEXTCMD)
{
buf->next = Z_Malloc(sizeof(textcmdbuf_t), PU_STATIC, NULL);
buf->next->cmd[0] = 0;
buf->next->next = NULL;
WriteNetXCmd(buf->next->cmd, id, param, nparam);
}
else
{ {
M_Memcpy(&localtextcmd2[localtextcmd2[0]+1], param, nparam); WriteNetXCmd(buf->cmd, id, param, nparam);
localtextcmd2[0] = (UINT8)(localtextcmd2[0] + (UINT8)nparam); }
return;
} }
WriteNetXCmd(localtextcmd2, id, param, nparam);
} }
UINT8 GetFreeXCmdSize(void) UINT8 GetFreeXCmdSize(void)
...@@ -95,16 +167,9 @@ void D_FreeTextcmd(tic_t tic) ...@@ -95,16 +167,9 @@ void D_FreeTextcmd(tic_t tic)
*tctprev = textcmdtic->next; *tctprev = textcmdtic->next;
// Free all players. // Free all players.
for (INT32 i = 0; i < TEXTCMD_HASH_SIZE; i++) for (INT32 i = 0; i < MAXPLAYERS; i++)
{
textcmdplayer_t *textcmdplayer = textcmdtic->playercmds[i];
while (textcmdplayer)
{ {
textcmdplayer_t *tcpnext = textcmdplayer->next; Z_Free(textcmdtic->playercmds[i]);
Z_Free(textcmdplayer);
textcmdplayer = tcpnext;
}
} }
// Free this tic's own memory. // Free this tic's own memory.
...@@ -121,10 +186,8 @@ UINT8* D_GetExistingTextcmd(tic_t tic, INT32 playernum) ...@@ -121,10 +186,8 @@ UINT8* D_GetExistingTextcmd(tic_t tic, INT32 playernum)
// Do we have an entry for the tic? If so, look for player. // Do we have an entry for the tic? If so, look for player.
if (textcmdtic) if (textcmdtic)
{ {
textcmdplayer_t *textcmdplayer = textcmdtic->playercmds[playernum & (TEXTCMD_HASH_SIZE - 1)]; UINT8 *cmd = textcmdtic->playercmds[playernum];
while (textcmdplayer && textcmdplayer->playernum != playernum) textcmdplayer = textcmdplayer->next; if (cmd) return cmd;
if (textcmdplayer) return textcmdplayer->cmd;
} }
return NULL; return NULL;
...@@ -135,7 +198,6 @@ UINT8* D_GetTextcmd(tic_t tic, INT32 playernum) ...@@ -135,7 +198,6 @@ UINT8* D_GetTextcmd(tic_t tic, INT32 playernum)
{ {
textcmdtic_t *textcmdtic = textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; textcmdtic_t *textcmdtic = textcmds[tic & (TEXTCMD_HASH_SIZE - 1)];
textcmdtic_t **tctprev = &textcmds[tic & (TEXTCMD_HASH_SIZE - 1)]; textcmdtic_t **tctprev = &textcmds[tic & (TEXTCMD_HASH_SIZE - 1)];
textcmdplayer_t *textcmdplayer, **tcpprev;
// Look for the tic. // Look for the tic.
while (textcmdtic && textcmdtic->tic != tic) while (textcmdtic && textcmdtic->tic != tic)
...@@ -151,30 +213,17 @@ UINT8* D_GetTextcmd(tic_t tic, INT32 playernum) ...@@ -151,30 +213,17 @@ UINT8* D_GetTextcmd(tic_t tic, INT32 playernum)
textcmdtic->tic = tic; textcmdtic->tic = tic;
} }
tcpprev = &textcmdtic->playercmds[playernum & (TEXTCMD_HASH_SIZE - 1)];
textcmdplayer = *tcpprev;
// Look for the player.
while (textcmdplayer && textcmdplayer->playernum != playernum)
{
tcpprev = &textcmdplayer->next;
textcmdplayer = textcmdplayer->next;
}
// If we don't have an entry for the player, make it. // If we don't have an entry for the player, make it.
if (!textcmdplayer) if (!textcmdtic->playercmds[playernum])
{ textcmdtic->playercmds[playernum] = Z_Calloc(MAXTEXTCMD, PU_STATIC, NULL);
textcmdplayer = *tcpprev = Z_Calloc(sizeof (textcmdplayer_t), PU_STATIC, NULL);
textcmdplayer->playernum = playernum;
}
return textcmdplayer->cmd; return textcmdtic->playercmds[playernum];
} }
void ExtraDataTicker(void) void ExtraDataTicker(void)
{ {
for (INT32 i = 0; i < MAXPLAYERS; i++) for (INT32 i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] || i == 0) if (players[i].ingame || i == 0)
{ {
UINT8 *bufferstart = D_GetExistingTextcmd(gametic, i); UINT8 *bufferstart = D_GetExistingTextcmd(gametic, i);
...@@ -223,15 +272,17 @@ size_t TotalTextCmdPerTic(tic_t tic) ...@@ -223,15 +272,17 @@ size_t TotalTextCmdPerTic(tic_t tic)
for (INT32 i = 0; i < MAXPLAYERS; i++) for (INT32 i = 0; i < MAXPLAYERS; i++)
{ {
UINT8 *textcmd = D_GetExistingTextcmd(tic, i); UINT8 *textcmd = D_GetExistingTextcmd(tic, i);
if ((!i || playeringame[i]) && textcmd) if ((!i || players[i].ingame) && textcmd)
total += 2 + textcmd[0]; // "+2" for size and playernum total += 2 + textcmd[0]; // "+2" for size and playernum
} }
return total; return total;
} }
void PT_TextCmd(SINT8 node, INT32 netconsole) void PT_TextCmd(doomcom_t *doomcom, INT32 netconsole)
{ {
UINT8 node = doomcom->remotenode;
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
if (client) if (client)
return; return;
...@@ -269,10 +320,10 @@ void PT_TextCmd(SINT8 node, INT32 netconsole) ...@@ -269,10 +320,10 @@ void PT_TextCmd(SINT8 node, INT32 netconsole)
} }
// check if tic that we are making isn't too large else we cannot send it :( // check if tic that we are making isn't too large else we cannot send it :(
// doomcom->numslots+1 "+1" since doomcom->numslots can change within this time and sent time // numslots+1 "+1" since numslots can change within this time and sent time
j = software_MAXPACKETLENGTH j = software_MAXPACKETLENGTH
- (netbuffer->u.textcmd[0]+2+BASESERVERTICSSIZE - (netbuffer->u.textcmd[0]+2+BASESERVERTICSSIZE
+ (doomcom->numslots+1)*sizeof(ticcmd_t)); + (numslots+1)*sizeof(ticcmd_t));
// search a tic that have enougth space in the ticcmd // search a tic that have enougth space in the ticcmd
while ((textcmd = D_GetExistingTextcmd(tic, netconsole)), while ((textcmd = D_GetExistingTextcmd(tic, netconsole)),
...@@ -311,7 +362,7 @@ void SV_WriteNetCommandsForTic(tic_t tic, UINT8 **buf) ...@@ -311,7 +362,7 @@ void SV_WriteNetCommandsForTic(tic_t tic, UINT8 **buf)
UINT8 *cmd = D_GetExistingTextcmd(tic, i); UINT8 *cmd = D_GetExistingTextcmd(tic, i);
INT32 size = cmd ? cmd[0] : 0; INT32 size = cmd ? cmd[0] : 0;
if ((!i || playeringame[i]) && size) if ((!i || players[i].ingame) && size)
{ {
(*numcmds)++; (*numcmds)++;
WRITEUINT8(*buf, i); WRITEUINT8(*buf, i);
...@@ -329,6 +380,11 @@ void CL_CopyNetCommandsFromServerPacket(tic_t tic, UINT8 **buf) ...@@ -329,6 +380,11 @@ void CL_CopyNetCommandsFromServerPacket(tic_t tic, UINT8 **buf)
{ {
INT32 playernum = *(*buf)++; // playernum INT32 playernum = *(*buf)++; // playernum
size_t size = (*buf)[0]+1; size_t size = (*buf)[0]+1;
if (playernum < 0 || playernum >= MAXPLAYERS)
{
CONS_Alert(CONS_WARNING, "Got bogus NetXCmd packet targetting player %d\n", playernum);
return;
}
if (tic >= gametic) // Don't copy old net commands if (tic >= gametic) // Don't copy old net commands
M_Memcpy(D_GetTextcmd(tic, playernum), *buf, size); M_Memcpy(D_GetTextcmd(tic, playernum), *buf, size);
...@@ -341,21 +397,41 @@ void CL_SendNetCommands(void) ...@@ -341,21 +397,41 @@ void CL_SendNetCommands(void)
// Send extra data if needed // Send extra data if needed
if (localtextcmd[0]) if (localtextcmd[0])
{ {
netbuffer->packettype = PT_TEXTCMD; doomcom_t *doomcom = D_NewPacket(PT_TEXTCMD, servernode, localtextcmd[0]+1);
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
M_Memcpy(netbuffer->u.textcmd,localtextcmd, localtextcmd[0]+1); M_Memcpy(netbuffer->u.textcmd,localtextcmd, localtextcmd[0]+1);
// All extra data have been sent // All extra data have been sent
if (HSendPacket(servernode, true, 0, localtextcmd[0]+1)) // Send can fail... if (HSendPacket(doomcom, true, 0)) // Send can fail...
{
localtextcmd[0] = 0; localtextcmd[0] = 0;
if (textcmdbuf != NULL)
{
textcmdbuf_t *buf = textcmdbuf;
M_Memcpy(localtextcmd, textcmdbuf->cmd, textcmdbuf->cmd[0]+1);
textcmdbuf = textcmdbuf->next;
Z_Free(buf);
}
}
} }
// Send extra data if needed for player 2 (splitscreen) // Send extra data if needed for player 2 (splitscreen)
if (localtextcmd2[0]) if (localtextcmd2[0])
{ {
netbuffer->packettype = PT_TEXTCMD2; doomcom_t *doomcom = D_NewPacket(PT_TEXTCMD2, servernode, localtextcmd2[0]+1);
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
M_Memcpy(netbuffer->u.textcmd, localtextcmd2, localtextcmd2[0]+1); M_Memcpy(netbuffer->u.textcmd, localtextcmd2, localtextcmd2[0]+1);
// All extra data have been sent // All extra data have been sent
if (HSendPacket(servernode, true, 0, localtextcmd2[0]+1)) // Send can fail... if (HSendPacket(doomcom, true, 0)) // Send can fail...
{
localtextcmd2[0] = 0; localtextcmd2[0] = 0;
if (textcmdbuf2 != NULL)
{
textcmdbuf_t *buf = textcmdbuf2;
M_Memcpy(localtextcmd2, textcmdbuf2->cmd, textcmdbuf2->cmd[0]+1);
textcmdbuf2 = textcmdbuf2->next;
Z_Free(buf);
}
}
} }
} }
...@@ -377,6 +453,6 @@ void SendKicksForNode(SINT8 node, UINT8 msg) ...@@ -377,6 +453,6 @@ void SendKicksForNode(SINT8 node, UINT8 msg)
return; return;
for (INT32 playernum = netnodes[node].player; playernum != -1; playernum = netnodes[node].player2) for (INT32 playernum = netnodes[node].player; playernum != -1; playernum = netnodes[node].player2)
if (playernum != -1 && playeringame[playernum]) if (playernum != -1 && players[playernum].ingame)
SendKick(playernum, msg); SendKick(playernum, msg);
} }
...@@ -19,17 +19,10 @@ ...@@ -19,17 +19,10 @@
// Must be a power of two // Must be a power of two
#define TEXTCMD_HASH_SIZE 4 #define TEXTCMD_HASH_SIZE 4
typedef struct textcmdplayer_s
{
INT32 playernum;
UINT8 cmd[MAXTEXTCMD];
struct textcmdplayer_s *next;
} textcmdplayer_t;
typedef struct textcmdtic_s typedef struct textcmdtic_s
{ {
tic_t tic; tic_t tic;
textcmdplayer_t *playercmds[TEXTCMD_HASH_SIZE]; UINT8 *playercmds[MAXPLAYERS];
struct textcmdtic_s *next; struct textcmdtic_s *next;
} textcmdtic_t; } textcmdtic_t;
...@@ -56,7 +49,7 @@ void ExtraDataTicker(void); ...@@ -56,7 +49,7 @@ void ExtraDataTicker(void);
// used at txtcmds received to check packetsize bound // used at txtcmds received to check packetsize bound
size_t TotalTextCmdPerTic(tic_t tic); size_t TotalTextCmdPerTic(tic_t tic);
void PT_TextCmd(SINT8 node, INT32 netconsole); void PT_TextCmd(doomcom_t *doomcom, INT32 netconsole);
void SV_WriteNetCommandsForTic(tic_t tic, UINT8 **buf); void SV_WriteNetCommandsForTic(tic_t tic, UINT8 **buf);
void CL_CopyNetCommandsFromServerPacket(tic_t tic, UINT8 **buf); void CL_CopyNetCommandsFromServerPacket(tic_t tic, UINT8 **buf);
void CL_SendNetCommands(void); void CL_SendNetCommands(void);
......
...@@ -89,6 +89,8 @@ typedef enum ...@@ -89,6 +89,8 @@ typedef enum
PT_CLIENTJOIN, // Client wants to join; used in start game. PT_CLIENTJOIN, // Client wants to join; used in start game.
PT_LOGIN, // Login attempt from the client. PT_LOGIN, // Login attempt from the client.
PT_LOGINCHALLENGE,// Challenge request sent to the client.
PT_LOGINAUTH, // Challenge response from the client.
PT_TELLFILESNEEDED, // Client, to server: "what other files do I need starting from this number?" PT_TELLFILESNEEDED, // Client, to server: "what other files do I need starting from this number?"
PT_MOREFILESNEEDED, // Server, to client: "you need these (+ more on top of those)" PT_MOREFILESNEEDED, // Server, to client: "you need these (+ more on top of those)"
...@@ -133,23 +135,6 @@ typedef struct ...@@ -133,23 +135,6 @@ typedef struct
ticcmd_t cmds[45]; ticcmd_t cmds[45];
} ATTRPACK servertics_pak; } ATTRPACK servertics_pak;
typedef struct
{
// Server launch stuffs
UINT8 serverplayer;
UINT8 totalslotnum; // "Slots": highest player number in use plus one.
tic_t gametic;
UINT8 clientnode;
UINT8 gamestate;
UINT8 gametype;
UINT8 modifiedgame;
UINT8 usedCheats;
char server_context[8]; // Unique context id, generated at server startup.
} ATTRPACK serverconfig_pak;
typedef struct typedef struct
{ {
UINT8 fileid; UINT8 fileid;
...@@ -284,6 +269,12 @@ typedef struct ...@@ -284,6 +269,12 @@ typedef struct
UINT8 files[MAXFILENEEDED]; // is filled with writexxx (byteptr.h) UINT8 files[MAXFILENEEDED]; // is filled with writexxx (byteptr.h)
} ATTRPACK filesneededconfig_pak; } ATTRPACK filesneededconfig_pak;
typedef struct
{
UINT32 ping[MAXPLAYERS+1];
UINT32 pl[MAXPLAYERS];
} pingtable_pak;
// //
// Network packet data // Network packet data
// //
...@@ -294,19 +285,20 @@ typedef struct ...@@ -294,19 +285,20 @@ typedef struct
UINT8 ackreturn; // The return of the ack number UINT8 ackreturn; // The return of the ack number
UINT8 packettype; UINT8 packettype;
UINT8 reserved; // Padding UINT8 packetindex;
union union
{ {
clientcmd_pak clientpak; clientcmd_pak clientpak;
client2cmd_pak client2pak; client2cmd_pak client2pak;
servertics_pak serverpak; servertics_pak serverpak;
serverconfig_pak servercfg;
UINT8 textcmd[MAXTEXTCMD+1]; UINT8 textcmd[MAXTEXTCMD+1];
filetx_pak filetxpak; filetx_pak filetxpak;
fileack_pak fileack; fileack_pak fileack;
UINT8 filereceived; UINT8 filereceived;
clientconfig_pak clientcfg; clientconfig_pak clientcfg;
char salt[9];
UINT8 md5sum[16]; UINT8 md5sum[16];
UINT8 sha256sum[32];
serverinfo_pak serverinfo; serverinfo_pak serverinfo;
serverrefuse_pak serverrefuse; serverrefuse_pak serverrefuse;
askinfo_pak askinfo; askinfo_pak askinfo;
...@@ -315,7 +307,7 @@ typedef struct ...@@ -315,7 +307,7 @@ typedef struct
plrconfig_pak playerconfig[MAXPLAYERS]; plrconfig_pak playerconfig[MAXPLAYERS];
INT32 filesneedednum; INT32 filesneedednum;
filesneededconfig_pak filesneededcfg; filesneededconfig_pak filesneededcfg;
UINT32 pingtable[MAXPLAYERS+1]; pingtable_pak pingtable;
} u; // This is needed to pack diff packet types data together } u; // This is needed to pack diff packet types data together
} ATTRPACK doomdata_t; } ATTRPACK doomdata_t;
......
...@@ -70,7 +70,7 @@ static INT32 FindRejoinerNum(SINT8 node) ...@@ -70,7 +70,7 @@ static INT32 FindRejoinerNum(SINT8 node)
// Check if any player matches the stripped address // Check if any player matches the stripped address
for (INT32 i = 0; i < MAXPLAYERS; i++) for (INT32 i = 0; i < MAXPLAYERS; i++)
{ {
if (playeringame[i] && playeraddress[i][0] && playernode[i] == UINT8_MAX if (players[i].ingame && playeraddress[i][0] && playernode[i] == UINT8_MAX
&& !strcmp(playeraddress[i], strippednodeaddress)) && !strcmp(playeraddress[i], strippednodeaddress))
return i; return i;
} }
...@@ -95,9 +95,10 @@ GetRefuseReason (INT32 node) ...@@ -95,9 +95,10 @@ GetRefuseReason (INT32 node)
static void SV_SendServerInfo(INT32 node, tic_t servertime) static void SV_SendServerInfo(INT32 node, tic_t servertime)
{ {
doomcom_t *doomcom = D_NewPacket(PT_SERVERINFO, node, 0);
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
UINT8 *p; UINT8 *p;
netbuffer->packettype = PT_SERVERINFO;
netbuffer->u.serverinfo._255 = 255; netbuffer->u.serverinfo._255 = 255;
netbuffer->u.serverinfo.packetversion = PACKETVERSION; netbuffer->u.serverinfo.packetversion = PACKETVERSION;
netbuffer->u.serverinfo.version = VERSION; netbuffer->u.serverinfo.version = VERSION;
...@@ -166,14 +167,16 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime) ...@@ -166,14 +167,16 @@ static void SV_SendServerInfo(INT32 node, tic_t servertime)
netbuffer->u.serverinfo.httpsource[MAX_MIRROR_LENGTH-1] = '\0'; netbuffer->u.serverinfo.httpsource[MAX_MIRROR_LENGTH-1] = '\0';
p = PutFileNeeded(0); p = PutFileNeeded(netbuffer, 0);
HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u)); doomcom->datalength = p - ((UINT8 *)&netbuffer->u);
HSendPacket(doomcom, false, 0);
} }
static void SV_SendPlayerInfo(INT32 node) static void SV_SendPlayerInfo(INT32 node)
{ {
netbuffer->packettype = PT_PLAYERINFO; doomcom_t *doomcom = D_NewPacket(PT_PLAYERINFO, node, sizeof(plrinfo_pak) * MAXPLAYERS);
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
for (UINT8 i = 0; i < MAXPLAYERS; i++) for (UINT8 i = 0; i < MAXPLAYERS; i++)
{ {
...@@ -229,7 +232,7 @@ static void SV_SendPlayerInfo(INT32 node) ...@@ -229,7 +232,7 @@ static void SV_SendPlayerInfo(INT32 node)
netbuffer->u.playerinfo[i].data |= 0x80; netbuffer->u.playerinfo[i].data |= 0x80;
} }
HSendPacket(node, false, 0, sizeof(plrinfo_pak) * MAXPLAYERS); HSendPacket(doomcom, false, 0);
} }
/** Sends a PT_SERVERCFG packet /** Sends a PT_SERVERCFG packet
...@@ -240,33 +243,32 @@ static void SV_SendPlayerInfo(INT32 node) ...@@ -240,33 +243,32 @@ static void SV_SendPlayerInfo(INT32 node)
*/ */
static boolean SV_SendServerConfig(INT32 node) static boolean SV_SendServerConfig(INT32 node)
{ {
doomcom_t *doomcom = D_NewPacket(PT_SERVERCFG, node, 0);
char *data = doomcom->data + 8;
boolean waspacketsent; boolean waspacketsent;
netbuffer->packettype = PT_SERVERCFG; WRITEUINT8(data, serverplayer);
WRITEUINT8(data, numslots);
netbuffer->u.servercfg.serverplayer = (UINT8)serverplayer; WRITEUINT32(data, gametic);
netbuffer->u.servercfg.totalslotnum = (UINT8)(doomcom->numslots); WRITEUINT8(data, node);
netbuffer->u.servercfg.gametic = (tic_t)LONG(gametic); WRITEUINT8(data, gamestate);
netbuffer->u.servercfg.clientnode = (UINT8)node; WRITEUINT8(data, gametype);
netbuffer->u.servercfg.gamestate = (UINT8)gamestate; WRITEUINT8(data, modifiedgame);
netbuffer->u.servercfg.gametype = (UINT8)gametype; WRITEUINT8(data, usedCheats);
netbuffer->u.servercfg.modifiedgame = (UINT8)modifiedgame; WRITEMEM(data, server_context, 8);
netbuffer->u.servercfg.usedCheats = (UINT8)usedCheats;
memcpy(netbuffer->u.servercfg.server_context, server_context, 8);
{ {
const size_t len = sizeof (serverconfig_pak); doomcom->datalength = data - doomcom->data - 8;
#ifdef DEBUGFILE #ifdef DEBUGFILE
if (debugfile) if (debugfile)
{ {
fprintf(debugfile, "ServerConfig Packet about to be sent, size of packet:%s to node:%d\n", fprintf(debugfile, "ServerConfig Packet about to be sent, size of packet:%s to node:%d\n",
sizeu1(len), node); sizeu1(doomcom->datalength), node);
} }
#endif #endif
waspacketsent = HSendPacket(node, true, 0, len); waspacketsent = HSendPacket(doomcom, true, 0);
} }
#ifdef DEBUGFILE #ifdef DEBUGFILE
...@@ -308,10 +310,10 @@ static void SV_AddPlayer(SINT8 node, const char *name) ...@@ -308,10 +310,10 @@ static void SV_AddPlayer(SINT8 node, const char *name)
if (newplayernum == -1) if (newplayernum == -1)
{ {
// search for a free playernum // search for a free playernum
// we can't use playeringame since it is not updated here // we can't use players since it is not updated here
for (newplayernum = dedicated ? 1 : 0; newplayernum < MAXPLAYERS; newplayernum++) for (newplayernum = dedicated ? 1 : 0; newplayernum < MAXPLAYERS; newplayernum++)
{ {
if (playeringame[newplayernum]) if (players[newplayernum].ingame)
continue; continue;
for (n = 0; n < MAXNETNODES; n++) for (n = 0; n < MAXNETNODES; n++)
if (netnodes[n].player == newplayernum || netnodes[n].player2 == newplayernum) if (netnodes[n].player == newplayernum || netnodes[n].player2 == newplayernum)
...@@ -349,16 +351,18 @@ static void SV_AddPlayer(SINT8 node, const char *name) ...@@ -349,16 +351,18 @@ static void SV_AddPlayer(SINT8 node, const char *name)
static void SV_SendRefuse(INT32 node, const char *reason) static void SV_SendRefuse(INT32 node, const char *reason)
{ {
strcpy(netbuffer->u.serverrefuse.reason, reason); doomcom_t *doomcom = D_NewPacket(PT_SERVERREFUSE, node, strlen(reason)+1);
strcpy(doomcom->data+8, reason);
netbuffer->packettype = PT_SERVERREFUSE; HSendPacket(doomcom, true, 0);
HSendPacket(node, true, 0, strlen(netbuffer->u.serverrefuse.reason) + 1);
Net_CloseConnection(node); Net_CloseConnection(node);
} }
static const char * static const char *
GetRefuseMessage (SINT8 node, INT32 rejoinernum) GetRefuseMessage (doomcom_t *doomcom, INT32 rejoinernum)
{ {
UINT8 node = doomcom->remotenode;
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
clientconfig_pak *cc = &netbuffer->u.clientcfg; clientconfig_pak *cc = &netbuffer->u.clientcfg;
boolean rejoining = (rejoinernum != -1); boolean rejoining = (rejoinernum != -1);
...@@ -433,8 +437,10 @@ GetRefuseMessage (SINT8 node, INT32 rejoinernum) ...@@ -433,8 +437,10 @@ GetRefuseMessage (SINT8 node, INT32 rejoinernum)
* \param node The packet sender * \param node The packet sender
* *
*/ */
void PT_ClientJoin(SINT8 node) void PT_ClientJoin(doomcom_t *doomcom)
{ {
UINT8 node = doomcom->remotenode;
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME + 1]; char names[MAXSPLITSCREENPLAYERS][MAXPLAYERNAME + 1];
INT32 numplayers = netbuffer->u.clientcfg.localplayers; INT32 numplayers = netbuffer->u.clientcfg.localplayers;
INT32 rejoinernum; INT32 rejoinernum;
...@@ -445,7 +451,7 @@ void PT_ClientJoin(SINT8 node) ...@@ -445,7 +451,7 @@ void PT_ClientJoin(SINT8 node)
rejoinernum = FindRejoinerNum(node); rejoinernum = FindRejoinerNum(node);
const char *refuse = GetRefuseMessage(node, rejoinernum); const char *refuse = GetRefuseMessage(doomcom, rejoinernum);
if (refuse) if (refuse)
{ {
SV_SendRefuse(node, refuse); SV_SendRefuse(node, refuse);
...@@ -487,32 +493,38 @@ void PT_ClientJoin(SINT8 node) ...@@ -487,32 +493,38 @@ void PT_ClientJoin(SINT8 node)
joindelay += cv_joindelay.value * TICRATE; joindelay += cv_joindelay.value * TICRATE;
} }
void PT_AskInfoViaMS(SINT8 node) void PT_AskInfoViaMS(doomcom_t *doomcom)
{ {
Net_CloseConnection(node); Net_CloseConnection(doomcom->remotenode);
} }
void PT_TellFilesNeeded(SINT8 node) void PT_TellFilesNeeded(doomcom_t *doomcom)
{ {
UINT8 node = doomcom->remotenode;
if (server && serverrunning) if (server && serverrunning)
{ {
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
UINT8 *p; UINT8 *p;
INT32 firstfile = netbuffer->u.filesneedednum; INT32 firstfile = netbuffer->u.filesneedednum;
doomcom = D_NewPacket(PT_MOREFILESNEEDED, node, 0);
netbuffer = DOOMCOM_DATA(doomcom);
netbuffer->packettype = PT_MOREFILESNEEDED;
netbuffer->u.filesneededcfg.first = firstfile; netbuffer->u.filesneededcfg.first = firstfile;
netbuffer->u.filesneededcfg.more = 0; netbuffer->u.filesneededcfg.more = 0;
p = PutFileNeeded(firstfile); p = PutFileNeeded(netbuffer, firstfile);
HSendPacket(node, false, 0, p - ((UINT8 *)&netbuffer->u)); doomcom->datalength = p - (UINT8 *)&netbuffer->u;
HSendPacket(doomcom, false, 0);
} }
else // Shouldn't get this if you aren't the server...? else // Shouldn't get this if you aren't the server...?
Net_CloseConnection(node); Net_CloseConnection(node);
} }
void PT_AskInfo(SINT8 node) void PT_AskInfo(doomcom_t *doomcom)
{ {
UINT8 node = doomcom->remotenode;
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
if (server && serverrunning) if (server && serverrunning)
{ {
SV_SendServerInfo(node, (tic_t)LONG(netbuffer->u.askinfo.time)); SV_SendServerInfo(node, (tic_t)LONG(netbuffer->u.askinfo.time));
......
...@@ -13,14 +13,15 @@ ...@@ -13,14 +13,15 @@
#ifndef __D_SERVER_CONNECTION__ #ifndef __D_SERVER_CONNECTION__
#define __D_SERVER_CONNECTION__ #define __D_SERVER_CONNECTION__
#include "i_net.h"
#include "../command.h" #include "../command.h"
#include "../doomdef.h" #include "../doomdef.h"
#include "../doomtype.h" #include "../doomtype.h"
void PT_ClientJoin(SINT8 node); void PT_ClientJoin(doomcom_t *doomcom);
void PT_AskInfoViaMS(SINT8 node); void PT_AskInfoViaMS(doomcom_t *doomcom);
void PT_TellFilesNeeded(SINT8 node); void PT_TellFilesNeeded(doomcom_t *doomcom);
void PT_AskInfo(SINT8 node); void PT_AskInfo(doomcom_t *doomcom);
extern tic_t jointimeout; extern tic_t jointimeout;
extern tic_t joindelay; extern tic_t joindelay;
......
...@@ -30,6 +30,7 @@ ticcmd_t localcmds; ...@@ -30,6 +30,7 @@ ticcmd_t localcmds;
ticcmd_t localcmds2; ticcmd_t localcmds2;
boolean cl_packetmissed; boolean cl_packetmissed;
ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS]; ticcmd_t netcmds[BACKUPTICS][MAXPLAYERS];
static ticcmd_t playercmds[MAXPLAYERS];
static inline void *G_DcpyTiccmd(void* dest, const ticcmd_t* src, const size_t n) static inline void *G_DcpyTiccmd(void* dest, const ticcmd_t* src, const size_t n)
{ {
...@@ -112,7 +113,7 @@ static void CheckTiccmdHacks(INT32 playernum, tic_t tic) ...@@ -112,7 +113,7 @@ static void CheckTiccmdHacks(INT32 playernum, tic_t tic)
} }
// Check player consistancy during the level // Check player consistancy during the level
static void CheckConsistancy(SINT8 nodenum, tic_t tic) static void CheckConsistancy(doomdata_t *netbuffer, SINT8 nodenum, tic_t tic)
{ {
netnode_t *node = &netnodes[nodenum]; netnode_t *node = &netnodes[nodenum];
INT16 neededconsistancy = consistancy[tic%BACKUPTICS]; INT16 neededconsistancy = consistancy[tic%BACKUPTICS];
...@@ -126,8 +127,8 @@ static void CheckConsistancy(SINT8 nodenum, tic_t tic) ...@@ -126,8 +127,8 @@ static void CheckConsistancy(SINT8 nodenum, tic_t tic)
if (cv_resynchattempts.value) if (cv_resynchattempts.value)
{ {
// Tell the client we are about to resend them the gamestate // Tell the client we are about to resend them the gamestate
netbuffer->packettype = PT_WILLRESENDGAMESTATE; doomcom_t *doomcom = D_NewPacket(PT_WILLRESENDGAMESTATE, nodenum, 0);
HSendPacket(nodenum, true, 0, 0); HSendPacket(doomcom, true, 0);
node->resendingsavegame = true; node->resendingsavegame = true;
...@@ -148,9 +149,11 @@ static void CheckConsistancy(SINT8 nodenum, tic_t tic) ...@@ -148,9 +149,11 @@ static void CheckConsistancy(SINT8 nodenum, tic_t tic)
} }
} }
void PT_ClientCmd(SINT8 nodenum, INT32 netconsole) void PT_ClientCmd(doomcom_t *doomcom, INT32 netconsole)
{ {
UINT8 nodenum = doomcom->remotenode;
netnode_t *node = &netnodes[nodenum]; netnode_t *node = &netnodes[nodenum];
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
tic_t realend, realstart; tic_t realend, realstart;
if (client) if (client)
...@@ -191,28 +194,24 @@ void PT_ClientCmd(SINT8 nodenum, INT32 netconsole) ...@@ -191,28 +194,24 @@ void PT_ClientCmd(SINT8 nodenum, INT32 netconsole)
|| netbuffer->packettype == PT_NODEKEEPALIVEMIS) || netbuffer->packettype == PT_NODEKEEPALIVEMIS)
return; return;
// If we've alredy received a ticcmd for this tic, just submit it for the next one.
tic_t faketic = maketic;
if ((!!(netcmds[maketic % BACKUPTICS][netconsole].angleturn & TICCMD_RECEIVED))
&& (maketic - firstticstosend < BACKUPTICS - 1))
faketic++;
// Copy ticcmd // Copy ticcmd
G_MoveTiccmd(&netcmds[faketic%BACKUPTICS][netconsole], &netbuffer->u.clientpak.cmd, 1); // store it in an internal buffer so the last packet takes precedence, which minimizes input lag
G_MoveTiccmd(&playercmds[netconsole], &netbuffer->u.clientpak.cmd, 1);
// Splitscreen cmd // Splitscreen cmd
if ((netbuffer->packettype == PT_CLIENT2CMD || netbuffer->packettype == PT_CLIENT2MIS) if ((netbuffer->packettype == PT_CLIENT2CMD || netbuffer->packettype == PT_CLIENT2MIS)
&& node->player2 >= 0) && node->player2 >= 0)
G_MoveTiccmd(&netcmds[faketic%BACKUPTICS][(UINT8)node->player2], G_MoveTiccmd(&playercmds[(UINT8)node->player2], &netbuffer->u.client2pak.cmd2, 1);
&netbuffer->u.client2pak.cmd2, 1);
CheckTiccmdHacks(netconsole, faketic); CheckTiccmdHacks(netconsole, maketic);
CheckConsistancy(nodenum, realstart); CheckConsistancy(netbuffer, nodenum, realstart);
} }
void PT_ServerTics(SINT8 node, INT32 netconsole) void PT_ServerTics(doomcom_t *doomcom, INT32 netconsole)
{ {
UINT8 node = doomcom->remotenode;
tic_t realend, realstart; tic_t realend, realstart;
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
servertics_pak *packet = &netbuffer->u.serverpak; servertics_pak *packet = &netbuffer->u.serverpak;
if (!netnodes[node].ingame) if (!netnodes[node].ingame)
...@@ -238,7 +237,6 @@ void PT_ServerTics(SINT8 node, INT32 netconsole) ...@@ -238,7 +237,6 @@ void PT_ServerTics(SINT8 node, INT32 netconsole)
realstart = packet->starttic; realstart = packet->starttic;
realend = realstart + packet->numtics; realend = realstart + packet->numtics;
realend = min(realend, gametic + CLIENTBACKUPTICS);
cl_packetmissed = realstart > neededtic; cl_packetmissed = realstart > neededtic;
if (realstart <= neededtic && realend > neededtic) if (realstart <= neededtic && realend > neededtic)
...@@ -269,8 +267,9 @@ void PT_ServerTics(SINT8 node, INT32 netconsole) ...@@ -269,8 +267,9 @@ void PT_ServerTics(SINT8 node, INT32 netconsole)
// send the client packet to the server // send the client packet to the server
void CL_SendClientCmd(void) void CL_SendClientCmd(void)
{ {
size_t packetsize = 0;
boolean mis = false; boolean mis = false;
doomcom_t *doomcom = D_NewPacket(0, servernode, 0);
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
netbuffer->packettype = PT_CLIENTCMD; netbuffer->packettype = PT_CLIENTCMD;
...@@ -287,12 +286,12 @@ void CL_SendClientCmd(void) ...@@ -287,12 +286,12 @@ void CL_SendClientCmd(void)
{ {
// Send PT_NODEKEEPALIVE packet // Send PT_NODEKEEPALIVE packet
netbuffer->packettype = (mis ? PT_NODEKEEPALIVEMIS : PT_NODEKEEPALIVE); netbuffer->packettype = (mis ? PT_NODEKEEPALIVEMIS : PT_NODEKEEPALIVE);
packetsize = sizeof (clientcmd_pak) - sizeof (ticcmd_t) - sizeof (INT16); doomcom->datalength = sizeof (clientcmd_pak) - sizeof (ticcmd_t) - sizeof (INT16);
HSendPacket(servernode, false, 0, packetsize); HSendPacket(doomcom, false, 0);
} }
else if (gamestate != GS_NULL && (addedtogame || dedicated)) else if (gamestate != GS_NULL && (addedtogame || dedicated))
{ {
packetsize = sizeof (clientcmd_pak); doomcom->datalength = sizeof (clientcmd_pak);
G_MoveTiccmd(&netbuffer->u.clientpak.cmd, &localcmds, 1); G_MoveTiccmd(&netbuffer->u.clientpak.cmd, &localcmds, 1);
netbuffer->u.clientpak.consistancy = SHORT(consistancy[gametic%BACKUPTICS]); netbuffer->u.clientpak.consistancy = SHORT(consistancy[gametic%BACKUPTICS]);
...@@ -300,11 +299,11 @@ void CL_SendClientCmd(void) ...@@ -300,11 +299,11 @@ void CL_SendClientCmd(void)
if (splitscreen || botingame) if (splitscreen || botingame)
{ {
netbuffer->packettype = (mis ? PT_CLIENT2MIS : PT_CLIENT2CMD); netbuffer->packettype = (mis ? PT_CLIENT2MIS : PT_CLIENT2CMD);
packetsize = sizeof (client2cmd_pak); doomcom->datalength = sizeof (client2cmd_pak);
G_MoveTiccmd(&netbuffer->u.client2pak.cmd2, &localcmds2, 1); G_MoveTiccmd(&netbuffer->u.client2pak.cmd2, &localcmds2, 1);
} }
HSendPacket(servernode, false, 0, packetsize); HSendPacket(doomcom, false, 0);
} }
if (cl_mode == CL_CONNECTED || dedicated) if (cl_mode == CL_CONNECTED || dedicated)
...@@ -320,7 +319,7 @@ static tic_t SV_CalculateNumTicsForPacket(SINT8 nodenum, tic_t firsttic, tic_t l ...@@ -320,7 +319,7 @@ static tic_t SV_CalculateNumTicsForPacket(SINT8 nodenum, tic_t firsttic, tic_t l
for (tic_t tic = firsttic; tic < lasttic; tic++) for (tic_t tic = firsttic; tic < lasttic; tic++)
{ {
size += sizeof (ticcmd_t) * doomcom->numslots; size += sizeof (ticcmd_t) * numslots;
size += TotalTextCmdPerTic(tic); size += TotalTextCmdPerTic(tic);
if (size > software_MAXPACKETLENGTH) if (size > software_MAXPACKETLENGTH)
...@@ -337,7 +336,7 @@ static tic_t SV_CalculateNumTicsForPacket(SINT8 nodenum, tic_t firsttic, tic_t l ...@@ -337,7 +336,7 @@ static tic_t SV_CalculateNumTicsForPacket(SINT8 nodenum, tic_t firsttic, tic_t l
if (size > MAXPACKETLENGTH) if (size > MAXPACKETLENGTH)
I_Error("Too many players: can't send %s data for %d players to node %d\n" I_Error("Too many players: can't send %s data for %d players to node %d\n"
"Well sorry nobody is perfect....\n", "Well sorry nobody is perfect....\n",
sizeu1(size), doomcom->numslots, nodenum); sizeu1(size), numslots, nodenum);
else else
{ {
lasttic++; // send it anyway! lasttic++; // send it anyway!
...@@ -363,29 +362,14 @@ void SV_SendTics(void) ...@@ -363,29 +362,14 @@ void SV_SendTics(void)
for (INT32 n = 1; n < MAXNETNODES; n++) for (INT32 n = 1; n < MAXNETNODES; n++)
if (netnodes[n].ingame) if (netnodes[n].ingame)
{ {
doomcom_t *doomcom = D_NewPacket(PT_SERVERTICS, n, 0);
doomdata_t *netbuffer = DOOMCOM_DATA(doomcom);
netnode_t *node = &netnodes[n]; netnode_t *node = &netnodes[n];
// assert node->supposedtic>=node->tic // assert node->supposedtic>=node->tic
realfirsttic = node->supposedtic; realfirsttic = node->supposedtic;
lasttictosend = min(maketic, node->tic + CLIENTBACKUPTICS); lasttictosend = min(maketic, node->tic + CLIENTBACKUPTICS);
if (realfirsttic >= lasttictosend)
{
// Well, we have sent all the tics, so we will use extra bandwidth
// to resend packets that are supposed lost.
// This is necessary since lost packet detection
// works when we receive a packet with firsttic > neededtic (PT_SERVERTICS)
DEBFILE(va("Nothing to send node %u mak=%u sup=%u net=%u \n",
n, maketic, node->supposedtic, node->tic));
realfirsttic = node->tic;
if (realfirsttic >= lasttictosend || (I_GetTime() + n)&3)
// All tics are Ok
continue;
DEBFILE(va("Sent %d anyway\n", realfirsttic));
}
realfirsttic = max(realfirsttic, firstticstosend); realfirsttic = max(realfirsttic, firstticstosend);
lasttictosend = realfirsttic + SV_CalculateNumTicsForPacket(n, realfirsttic, lasttictosend); lasttictosend = realfirsttic + SV_CalculateNumTicsForPacket(n, realfirsttic, lasttictosend);
...@@ -394,20 +378,20 @@ void SV_SendTics(void) ...@@ -394,20 +378,20 @@ void SV_SendTics(void)
netbuffer->packettype = PT_SERVERTICS; netbuffer->packettype = PT_SERVERTICS;
netbuffer->u.serverpak.starttic = realfirsttic; netbuffer->u.serverpak.starttic = realfirsttic;
netbuffer->u.serverpak.numtics = (UINT8)(lasttictosend - realfirsttic); netbuffer->u.serverpak.numtics = (UINT8)(lasttictosend - realfirsttic);
netbuffer->u.serverpak.numslots = (UINT8)SHORT(doomcom->numslots); netbuffer->u.serverpak.numslots = (UINT8)SHORT(numslots);
// Fill and send the packet // Fill and send the packet
UINT8 *bufpos = (UINT8 *)&netbuffer->u.serverpak.cmds; UINT8 *bufpos = (UINT8 *)&netbuffer->u.serverpak.cmds;
for (tic_t i = realfirsttic; i < lasttictosend; i++) for (tic_t i = realfirsttic; i < lasttictosend; i++)
bufpos = G_DcpyTiccmd(bufpos, netcmds[i%BACKUPTICS], doomcom->numslots * sizeof (ticcmd_t)); bufpos = G_DcpyTiccmd(bufpos, netcmds[i%BACKUPTICS], numslots * sizeof (ticcmd_t));
for (tic_t i = realfirsttic; i < lasttictosend; i++) for (tic_t i = realfirsttic; i < lasttictosend; i++)
SV_WriteNetCommandsForTic(i, &bufpos); SV_WriteNetCommandsForTic(i, &bufpos);
size_t packsize = bufpos - (UINT8 *)&(netbuffer->u); doomcom->datalength = bufpos - (UINT8 *)&(netbuffer->u);
HSendPacket(n, false, 0, packsize); HSendPacket(doomcom, false, 0);
// When tics are too large, only one tic is sent so don't go backwards! // When tics are too large, only one tic is sent so don't go backwards!
if (lasttictosend-doomcom->extratics > realfirsttic) if (lasttictosend-extratics > realfirsttic)
node->supposedtic = lasttictosend-doomcom->extratics; node->supposedtic = lasttictosend-extratics;
else else
node->supposedtic = lasttictosend; node->supposedtic = lasttictosend;
node->supposedtic = max(node->supposedtic, node->tic); node->supposedtic = max(node->supposedtic, node->tic);
...@@ -437,17 +421,18 @@ void Local_Maketic(INT32 realtics) ...@@ -437,17 +421,18 @@ void Local_Maketic(INT32 realtics)
// create missed tic // create missed tic
void SV_Maketic(void) void SV_Maketic(void)
{ {
for (INT32 i = 0; i < MAXPLAYERS; i++) INT32 i;
for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i]) if (!players[i].ingame)
continue; continue;
// We didn't receive this tic
if ((netcmds[maketic % BACKUPTICS][i].angleturn & TICCMD_RECEIVED) == 0) if ((netcmds[maketic % BACKUPTICS][i].angleturn & TICCMD_RECEIVED) == 0)
{ {
ticcmd_t * ticcmd = &netcmds[(maketic ) % BACKUPTICS][i]; ticcmd_t * ticcmd = &netcmds[(maketic ) % BACKUPTICS][i];
ticcmd_t *prevticcmd = &netcmds[(maketic - 1) % BACKUPTICS][i]; ticcmd_t *prevticcmd = &netcmds[(maketic - 1) % BACKUPTICS][i];
// We didn't receive this tic
if (players[i].quittime) if (players[i].quittime)
{ {
// Copy the angle/aiming from the previous tic // Copy the angle/aiming from the previous tic
...@@ -466,6 +451,6 @@ void SV_Maketic(void) ...@@ -466,6 +451,6 @@ void SV_Maketic(void)
} }
} }
// All tics have been processed, make the next G_MoveTiccmd(netcmds[maketic % BACKUPTICS], playercmds, MAXPLAYERS);
maketic++; maketic++;
} }
...@@ -31,8 +31,8 @@ tic_t ExpandTics(INT32 low, INT32 node); ...@@ -31,8 +31,8 @@ tic_t ExpandTics(INT32 low, INT32 node);
void D_Clearticcmd(tic_t tic); void D_Clearticcmd(tic_t tic);
void D_ResetTiccmds(void); void D_ResetTiccmds(void);
void PT_ClientCmd(SINT8 nodenum, INT32 netconsole); void PT_ClientCmd(doomcom_t *doomcom, INT32 netconsole);
void PT_ServerTics(SINT8 node, INT32 netconsole); void PT_ServerTics(doomcom_t *doomcom, INT32 netconsole);
// send the client packet to the server // send the client packet to the server
void CL_SendClientCmd(void); void CL_SendClientCmd(void);
......
...@@ -181,9 +181,8 @@ void T_CrushCeiling(ceiling_t *ceiling) ...@@ -181,9 +181,8 @@ void T_CrushCeiling(ceiling_t *ceiling)
if (res == pastdest) if (res == pastdest)
{ {
mobj_t *mp = (void *)&ceiling->sector->soundorg;
ceiling->sector->soundorg.z = ceiling->sector->floorheight; ceiling->sector->soundorg.z = ceiling->sector->floorheight;
S_StartSound(mp,sfx_pstop); S_StartSoundFromSector(ceiling->sector,sfx_pstop);
ceiling->direction = 1; ceiling->direction = 1;
ceiling->speed = lines[ceiling->sourceline].args[3] << (FRACBITS - 2); ceiling->speed = lines[ceiling->sourceline].args[3] << (FRACBITS - 2);
...@@ -224,7 +223,7 @@ INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type) ...@@ -224,7 +223,7 @@ INT32 EV_DoCeiling(mtag_t tag, line_t *line, ceiling_e type)
ceiling = Z_Calloc(sizeof (*ceiling), PU_LEVSPEC, NULL); ceiling = Z_Calloc(sizeof (*ceiling), PU_LEVSPEC, NULL);
P_AddThinker(THINK_MAIN, &ceiling->thinker); P_AddThinker(THINK_MAIN, &ceiling->thinker);
sec->ceilingdata = ceiling; sec->ceilingdata = ceiling;
ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling; ceiling->thinker.function = (actionf_p1)T_MoveCeiling;
ceiling->sector = sec; ceiling->sector = sec;
ceiling->crush = false; ceiling->crush = false;
ceiling->sourceline = (INT32)(line-lines); ceiling->sourceline = (INT32)(line-lines);
...@@ -370,7 +369,7 @@ INT32 EV_DoCrush(mtag_t tag, line_t *line, ceiling_e type) ...@@ -370,7 +369,7 @@ INT32 EV_DoCrush(mtag_t tag, line_t *line, ceiling_e type)
ceiling = Z_Calloc(sizeof (*ceiling), PU_LEVSPEC, NULL); ceiling = Z_Calloc(sizeof (*ceiling), PU_LEVSPEC, NULL);
P_AddThinker(THINK_MAIN, &ceiling->thinker); P_AddThinker(THINK_MAIN, &ceiling->thinker);
sec->ceilingdata = ceiling; sec->ceilingdata = ceiling;
ceiling->thinker.function.acp1 = (actionf_p1)T_CrushCeiling; ceiling->thinker.function = (actionf_p1)T_CrushCeiling;
ceiling->sector = sec; ceiling->sector = sec;
ceiling->crush = true; ceiling->crush = true;
ceiling->sourceline = (INT32)(line-lines); ceiling->sourceline = (INT32)(line-lines);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // 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 // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -54,276 +54,6 @@ static dirtype_t diags[] = ...@@ -54,276 +54,6 @@ static dirtype_t diags[] =
DI_NORTHWEST, DI_NORTHEAST, DI_SOUTHWEST, DI_SOUTHEAST DI_NORTHWEST, DI_NORTHEAST, DI_SOUTHWEST, DI_SOUTHEAST
}; };
//Real Prototypes to A_*
void A_Fall(mobj_t *actor);
void A_Look(mobj_t *actor);
void A_Chase(mobj_t *actor);
void A_FaceStabChase(mobj_t *actor);
void A_FaceStabRev(mobj_t *actor);
void A_FaceStabHurl(mobj_t *actor);
void A_FaceStabMiss(mobj_t *actor);
void A_StatueBurst(mobj_t *actor);
void A_JetJawRoam(mobj_t *actor);
void A_JetJawChomp(mobj_t *actor);
void A_PointyThink(mobj_t *actor);
void A_CheckBuddy(mobj_t *actor);
void A_HoodFire(mobj_t *actor);
void A_HoodThink(mobj_t *actor);
void A_HoodFall(mobj_t *actor);
void A_ArrowBonks(mobj_t *actor);
void A_SnailerThink(mobj_t *actor);
void A_SharpChase(mobj_t *actor);
void A_SharpSpin(mobj_t *actor);
void A_SharpDecel(mobj_t *actor);
void A_CrushstaceanWalk(mobj_t *actor);
void A_CrushstaceanPunch(mobj_t *actor);
void A_CrushclawAim(mobj_t *actor);
void A_CrushclawLaunch(mobj_t *actor);
void A_VultureVtol(mobj_t *actor);
void A_VultureCheck(mobj_t *actor);
void A_VultureHover(mobj_t *actor);
void A_VultureBlast(mobj_t *actor);
void A_VultureFly(mobj_t *actor);
void A_SkimChase(mobj_t *actor);
void A_FaceTarget(mobj_t *actor);
void A_FaceTracer(mobj_t *actor);
void A_LobShot(mobj_t *actor);
void A_FireShot(mobj_t *actor);
void A_SuperFireShot(mobj_t *actor);
void A_BossFireShot(mobj_t *actor);
void A_Boss7FireMissiles(mobj_t *actor);
void A_Boss1Laser(mobj_t *actor);
void A_FocusTarget(mobj_t *actor);
void A_Boss4Reverse(mobj_t *actor);
void A_Boss4SpeedUp(mobj_t *actor);
void A_Boss4Raise(mobj_t *actor);
void A_SkullAttack(mobj_t *actor);
void A_BossZoom(mobj_t *actor);
void A_BossScream(mobj_t *actor);
void A_Scream(mobj_t *actor);
void A_Pain(mobj_t *actor);
void A_1upThinker(mobj_t *actor);
void A_MonitorPop(mobj_t *actor);
void A_GoldMonitorPop(mobj_t *actor);
void A_GoldMonitorRestore(mobj_t *actor);
void A_GoldMonitorSparkle(mobj_t *actor);
void A_Explode(mobj_t *actor);
void A_BossDeath(mobj_t *actor);
void A_SetShadowScale(mobj_t *actor);
void A_ShadowScream(mobj_t *actor);
void A_CustomPower(mobj_t *actor);
void A_GiveWeapon(mobj_t *actor);
void A_RingBox(mobj_t *actor);
void A_Invincibility(mobj_t *actor);
void A_SuperSneakers(mobj_t *actor);
void A_AwardScore(mobj_t *actor);
void A_ExtraLife(mobj_t *actor);
void A_GiveShield(mobj_t *actor);
void A_GravityBox(mobj_t *actor);
void A_ScoreRise(mobj_t *actor);
void A_BunnyHop(mobj_t *actor);
void A_BubbleSpawn(mobj_t *actor);
void A_FanBubbleSpawn(mobj_t *actor);
void A_BubbleRise(mobj_t *actor);
void A_BubbleCheck(mobj_t *actor);
void A_AttractChase(mobj_t *actor);
void A_DropMine(mobj_t *actor);
void A_FishJump(mobj_t *actor);
void A_ThrownRing(mobj_t *actor);
void A_SetSolidSteam(mobj_t *actor);
void A_UnsetSolidSteam(mobj_t *actor);
void A_SignSpin(mobj_t *actor);
void A_SignPlayer(mobj_t *actor);
void A_OverlayThink(mobj_t *actor);
void A_JetChase(mobj_t *actor);
void A_JetbThink(mobj_t *actor);
void A_JetgShoot(mobj_t *actor);
void A_JetgThink(mobj_t *actor);
void A_ShootBullet(mobj_t *actor);
void A_MinusDigging(mobj_t *actor);
void A_MinusPopup(mobj_t *actor);
void A_MinusCheck(mobj_t *actor);
void A_ChickenCheck(mobj_t *actor);
void A_MouseThink(mobj_t *actor);
void A_DetonChase(mobj_t *actor);
void A_CapeChase(mobj_t *actor);
void A_RotateSpikeBall(mobj_t *actor);
void A_SlingAppear(mobj_t *actor);
void A_UnidusBall(mobj_t *actor);
void A_RockSpawn(mobj_t *actor);
void A_SetFuse(mobj_t *actor);
void A_CrawlaCommanderThink(mobj_t *actor);
void A_RingExplode(mobj_t *actor);
void A_OldRingExplode(mobj_t *actor);
void A_MixUp(mobj_t *actor);
void A_RecyclePowers(mobj_t *actor);
void A_Boss2TakeDamage(mobj_t *actor);
void A_Boss7Chase(mobj_t *actor);
void A_GoopSplat(mobj_t *actor);
void A_Boss2PogoSFX(mobj_t *actor);
void A_Boss2PogoTarget(mobj_t *actor);
void A_EggmanBox(mobj_t *actor);
void A_TurretFire(mobj_t *actor);
void A_SuperTurretFire(mobj_t *actor);
void A_TurretStop(mobj_t *actor);
void A_SparkFollow(mobj_t *actor);
void A_BuzzFly(mobj_t *actor);
void A_GuardChase(mobj_t *actor);
void A_EggShield(mobj_t *actor);
void A_SetReactionTime(mobj_t *actor);
void A_Boss1Spikeballs(mobj_t *actor);
void A_Boss3TakeDamage(mobj_t *actor);
void A_Boss3Path(mobj_t *actor);
void A_Boss3ShockThink(mobj_t *actor);
void A_Shockwave(mobj_t *actor);
void A_LinedefExecute(mobj_t *actor);
void A_LinedefExecuteFromArg(mobj_t *actor);
void A_PlaySeeSound(mobj_t *actor);
void A_PlayAttackSound(mobj_t *actor);
void A_PlayActiveSound(mobj_t *actor);
void A_SmokeTrailer(mobj_t *actor);
void A_SpawnObjectAbsolute(mobj_t *actor);
void A_SpawnObjectRelative(mobj_t *actor);
void A_ChangeAngleRelative(mobj_t *actor);
void A_ChangeAngleAbsolute(mobj_t *actor);
void A_RollAngle(mobj_t *actor);
void A_ChangeRollAngleRelative(mobj_t *actor);
void A_ChangeRollAngleAbsolute(mobj_t *actor);
void A_PlaySound(mobj_t *actor);
void A_FindTarget(mobj_t *actor);
void A_FindTracer(mobj_t *actor);
void A_SetTics(mobj_t *actor);
void A_SetRandomTics(mobj_t *actor);
void A_ChangeColorRelative(mobj_t *actor);
void A_ChangeColorAbsolute(mobj_t *actor);
void A_Dye(mobj_t *actor);
void A_SetTranslation(mobj_t *actor);
void A_MoveRelative(mobj_t *actor);
void A_MoveAbsolute(mobj_t *actor);
void A_Thrust(mobj_t *actor);
void A_ZThrust(mobj_t *actor);
void A_SetTargetsTarget(mobj_t *actor);
void A_SetObjectFlags(mobj_t *actor);
void A_SetObjectFlags2(mobj_t *actor);
void A_RandomState(mobj_t *actor);
void A_RandomStateRange(mobj_t *actor);
void A_StateRangeByAngle(mobj_t *actor);
void A_StateRangeByParameter(mobj_t *actor);
void A_DualAction(mobj_t *actor);
void A_RemoteAction(mobj_t *actor);
void A_ToggleFlameJet(mobj_t *actor);
void A_OrbitNights(mobj_t *actor);
void A_GhostMe(mobj_t *actor);
void A_SetObjectState(mobj_t *actor);
void A_SetObjectTypeState(mobj_t *actor);
void A_KnockBack(mobj_t *actor);
void A_PushAway(mobj_t *actor);
void A_RingDrain(mobj_t *actor);
void A_SplitShot(mobj_t *actor);
void A_MissileSplit(mobj_t *actor);
void A_MultiShot(mobj_t *actor);
void A_InstaLoop(mobj_t *actor);
void A_Custom3DRotate(mobj_t *actor);
void A_SearchForPlayers(mobj_t *actor);
void A_CheckRandom(mobj_t *actor);
void A_CheckTargetRings(mobj_t *actor);
void A_CheckRings(mobj_t *actor);
void A_CheckTotalRings(mobj_t *actor);
void A_CheckHealth(mobj_t *actor);
void A_CheckRange(mobj_t *actor);
void A_CheckHeight(mobj_t *actor);
void A_CheckTrueRange(mobj_t *actor);
void A_CheckThingCount(mobj_t *actor);
void A_CheckAmbush(mobj_t *actor);
void A_CheckCustomValue(mobj_t *actor);
void A_CheckCusValMemo(mobj_t *actor);
void A_SetCustomValue(mobj_t *actor);
void A_UseCusValMemo(mobj_t *actor);
void A_RelayCustomValue(mobj_t *actor);
void A_CusValAction(mobj_t *actor);
void A_ForceStop(mobj_t *actor);
void A_ForceWin(mobj_t *actor);
void A_SpikeRetract(mobj_t *actor);
void A_InfoState(mobj_t *actor);
void A_Repeat(mobj_t *actor);
void A_SetScale(mobj_t *actor);
void A_RemoteDamage(mobj_t *actor);
void A_HomingChase(mobj_t *actor);
void A_TrapShot(mobj_t *actor);
void A_Boss1Chase(mobj_t *actor);
void A_Boss2Chase(mobj_t *actor);
void A_Boss2Pogo(mobj_t *actor);
void A_BossJetFume(mobj_t *actor);
void A_VileTarget(mobj_t *actor);
void A_VileAttack(mobj_t *actor);
void A_VileFire(mobj_t *actor);
void A_BrakChase(mobj_t *actor);
void A_BrakFireShot(mobj_t *actor);
void A_BrakLobShot(mobj_t *actor);
void A_NapalmScatter(mobj_t *actor);
void A_SpawnFreshCopy(mobj_t *actor);
void A_FlickySpawn(mobj_t *actor);
void A_FlickyCenter(mobj_t *actor);
void A_FlickyAim(mobj_t *actor);
void A_FlickyFly(mobj_t *actor);
void A_FlickySoar(mobj_t *actor);
void A_FlickyCoast(mobj_t *actor);
void A_FlickyHop(mobj_t *actor);
void A_FlickyFlounder(mobj_t *actor);
void A_FlickyCheck(mobj_t *actor);
void A_FlickyHeightCheck(mobj_t *actor);
void A_FlickyFlutter(mobj_t *actor);
void A_FlameParticle(mobj_t *actor);
void A_FadeOverlay(mobj_t *actor);
void A_Boss5Jump(mobj_t *actor);
void A_LightBeamReset(mobj_t *actor);
void A_MineExplode(mobj_t *actor);
void A_MineRange(mobj_t *actor);
void A_ConnectToGround(mobj_t *actor);
void A_SpawnParticleRelative(mobj_t *actor);
void A_MultiShotDist(mobj_t *actor);
void A_WhoCaresIfYourSonIsABee(mobj_t *actor);
void A_ParentTriesToSleep(mobj_t *actor);
void A_CryingToMomma(mobj_t *actor);
void A_CheckFlags2(mobj_t *actor);
void A_Boss5FindWaypoint(mobj_t *actor);
void A_DoNPCSkid(mobj_t *actor);
void A_DoNPCPain(mobj_t *actor);
void A_PrepareRepeat(mobj_t *actor);
void A_Boss5ExtraRepeat(mobj_t *actor);
void A_Boss5Calm(mobj_t *actor);
void A_Boss5CheckOnGround(mobj_t *actor);
void A_Boss5CheckFalling(mobj_t *actor);
void A_Boss5PinchShot(mobj_t *actor);
void A_Boss5MakeItRain(mobj_t *actor);
void A_Boss5MakeJunk(mobj_t *actor);
void A_LookForBetter(mobj_t *actor);
void A_Boss5BombExplode(mobj_t *actor);
void A_DustDevilThink(mobj_t *actor);
void A_TNTExplode(mobj_t *actor);
void A_DebrisRandom(mobj_t *actor);
void A_TrainCameo(mobj_t *actor);
void A_TrainCameo2(mobj_t *actor);
void A_CanarivoreGas(mobj_t *actor);
void A_KillSegments(mobj_t *actor);
void A_SnapperSpawn(mobj_t *actor);
void A_SnapperThinker(mobj_t *actor);
void A_SaloonDoorSpawn(mobj_t *actor);
void A_MinecartSparkThink(mobj_t *actor);
void A_ModuloToState(mobj_t *actor);
void A_LavafallRocks(mobj_t *actor);
void A_LavafallLava(mobj_t *actor);
void A_FallingLavaCheck(mobj_t *actor);
void A_FireShrink(mobj_t *actor);
void A_SpawnPterabytes(mobj_t *actor);
void A_PterabyteHover(mobj_t *actor);
void A_RolloutSpawn(mobj_t *actor);
void A_RolloutRock(mobj_t *actor);
void A_DragonbomberSpawn(mobj_t *actor);
void A_DragonWing(mobj_t *actor);
void A_DragonSegment(mobj_t *actor);
void A_ChangeHeight(mobj_t *actor);
//for p_enemy.c //for p_enemy.c
// //
...@@ -338,15 +68,13 @@ void A_ChangeHeight(mobj_t *actor); ...@@ -338,15 +68,13 @@ void A_ChangeHeight(mobj_t *actor);
boolean P_CheckMeleeRange(mobj_t *actor) boolean P_CheckMeleeRange(mobj_t *actor)
{ {
mobj_t *pl; mobj_t *pl;
fixed_t dist;
if (!actor->target) if (!actor->target)
return false; return false;
pl = actor->target; pl = actor->target;
dist = P_AproxDistance(pl->x-actor->x, pl->y-actor->y);
if (dist >= FixedMul(MELEERANGE - 20*FRACUNIT, actor->scale) + pl->radius) if (P_AreMobjsFar2D(actor, pl, FixedMul(MELEERANGE - 20*FRACUNIT, actor->scale) + pl->radius))
return false; return false;
// check height now, so that damn crawlas cant attack // check height now, so that damn crawlas cant attack
...@@ -364,15 +92,13 @@ boolean P_CheckMeleeRange(mobj_t *actor) ...@@ -364,15 +92,13 @@ boolean P_CheckMeleeRange(mobj_t *actor)
boolean P_JetbCheckMeleeRange(mobj_t *actor) boolean P_JetbCheckMeleeRange(mobj_t *actor)
{ {
mobj_t *pl; mobj_t *pl;
fixed_t dist;
if (!actor->target) if (!actor->target)
return false; return false;
pl = actor->target; pl = actor->target;
dist = P_AproxDistance(pl->x-actor->x, pl->y-actor->y);
if (dist >= (actor->radius + pl->radius)*2) if (P_AreMobjsFar2D(actor, pl, (actor->radius + pl->radius) * 2))
return false; return false;
if (actor->eflags & MFE_VERTICALFLIP) if (actor->eflags & MFE_VERTICALFLIP)
...@@ -393,15 +119,13 @@ boolean P_JetbCheckMeleeRange(mobj_t *actor) ...@@ -393,15 +119,13 @@ boolean P_JetbCheckMeleeRange(mobj_t *actor)
boolean P_FaceStabCheckMeleeRange(mobj_t *actor) boolean P_FaceStabCheckMeleeRange(mobj_t *actor)
{ {
mobj_t *pl; mobj_t *pl;
fixed_t dist;
if (!actor->target) if (!actor->target)
return false; return false;
pl = actor->target; pl = actor->target;
dist = P_AproxDistance(pl->x-actor->x, pl->y-actor->y);
if (dist >= (actor->radius + pl->radius)*4) if (P_AreMobjsFar2D(actor, pl, (actor->radius + pl->radius) * 4))
return false; return false;
if ((pl->z > actor->z + actor->height) || (actor->z > pl->z + pl->height)) if ((pl->z > actor->z + actor->height) || (actor->z > pl->z + pl->height))
...@@ -417,15 +141,13 @@ boolean P_FaceStabCheckMeleeRange(mobj_t *actor) ...@@ -417,15 +141,13 @@ boolean P_FaceStabCheckMeleeRange(mobj_t *actor)
boolean P_SkimCheckMeleeRange(mobj_t *actor) boolean P_SkimCheckMeleeRange(mobj_t *actor)
{ {
mobj_t *pl; mobj_t *pl;
fixed_t dist;
if (!actor->target) if (!actor->target)
return false; return false;
pl = actor->target; pl = actor->target;
dist = P_AproxDistance(pl->x-actor->x, pl->y-actor->y);
if (dist >= FixedMul(MELEERANGE - 20*FRACUNIT, actor->scale) + pl->radius) if (P_AreMobjsFar2D(actor, pl, FixedMul(MELEERANGE - 20*FRACUNIT, actor->scale) + pl->radius))
return false; return false;
if (actor->eflags & MFE_VERTICALFLIP) if (actor->eflags & MFE_VERTICALFLIP)
...@@ -459,7 +181,7 @@ boolean P_CheckMissileRange(mobj_t *actor) ...@@ -459,7 +181,7 @@ boolean P_CheckMissileRange(mobj_t *actor)
return false; return false;
// OPTIMIZE: get this from a global checksight // OPTIMIZE: get this from a global checksight
dist = P_AproxDistance(actor->x-actor->target->x, actor->y-actor->target->y) - FixedMul(64*FRACUNIT, actor->scale); dist = P_GetMobjDistance2D(actor, actor->target) - FixedMul(64*FRACUNIT, actor->scale);
if (!actor->info->meleestate) if (!actor->info->meleestate)
dist -= FixedMul(128*FRACUNIT, actor->scale); // no melee attack, so fire more dist -= FixedMul(128*FRACUNIT, actor->scale); // no melee attack, so fire more
...@@ -734,7 +456,7 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed ...@@ -734,7 +456,7 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed
if (actor->lastlook == stop) if (actor->lastlook == stop)
return false; return false;
if (!playeringame[actor->lastlook]) if (!players[actor->lastlook].ingame)
continue; continue;
if (c++ == 2) if (c++ == 2)
...@@ -760,8 +482,7 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed ...@@ -760,8 +482,7 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed
if (player->quittime) if (player->quittime)
continue; // Ignore uncontrolled bodies continue; // Ignore uncontrolled bodies
if (dist > 0 if (dist > 0 && P_AreMobjsFar3D(actor, player->mo, dist))
&& P_AproxDistance(P_AproxDistance(player->mo->x - actor->x, player->mo->y - actor->y), player->mo->z - actor->z) > dist)
continue; // Too far away continue; // Too far away
if (!allaround) if (!allaround)
...@@ -769,9 +490,8 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed ...@@ -769,9 +490,8 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed
an = R_PointToAngle2(actor->x, actor->y, player->mo->x, player->mo->y) - actor->angle; an = R_PointToAngle2(actor->x, actor->y, player->mo->x, player->mo->y) - actor->angle;
if (an > ANGLE_90 && an < ANGLE_270) if (an > ANGLE_90 && an < ANGLE_270)
{ {
dist = P_AproxDistance(player->mo->x - actor->x, player->mo->y - actor->y);
// if real close, react anyway // if real close, react anyway
if (dist > FixedMul(MELEERANGE, actor->scale)) if (P_AreMobjsFar2D(actor, player->mo, FixedMul(MELEERANGE, actor->scale)))
continue; // behind back continue; // behind back
} }
} }
...@@ -815,7 +535,7 @@ static boolean P_LookForShield(mobj_t *actor) ...@@ -815,7 +535,7 @@ static boolean P_LookForShield(mobj_t *actor)
if (actor->lastlook == stop) if (actor->lastlook == stop)
return false; return false;
if (!playeringame[actor->lastlook]) if (!players[actor->lastlook].ingame)
continue; continue;
if (c++ == 2) if (c++ == 2)
...@@ -832,7 +552,7 @@ static boolean P_LookForShield(mobj_t *actor) ...@@ -832,7 +552,7 @@ static boolean P_LookForShield(mobj_t *actor)
continue; continue;
if ((player->powers[pw_shield] & SH_PROTECTELECTRIC) if ((player->powers[pw_shield] & SH_PROTECTELECTRIC)
&& (R_PointToDist2(0, 0, R_PointToDist2(0, 0, actor->x-player->mo->x, actor->y-player->mo->y), actor->z-player->mo->z) < FixedMul(RING_DIST, player->mo->scale))) && (P_AreMobjsClose3D(player->mo, actor, FixedMul(RING_DIST, player->mo->scale))))
{ {
P_SetTarget(&actor->tracer, player->mo); P_SetTarget(&actor->tracer, player->mo);
...@@ -987,8 +707,9 @@ for (i = cvar.value; i; --i) spawnchance[numchoices++] = type ...@@ -987,8 +707,9 @@ for (i = cvar.value; i; --i) spawnchance[numchoices++] = type
// upper 16 bits = distance limit // upper 16 bits = distance limit
// var2 = If 1, only change to seestate. If 2, only play seesound. If 0, do both. // var2 = If 1, only change to seestate. If 2, only play seesound. If 0, do both.
// //
void A_Look(mobj_t *actor) void A_Look(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -1020,8 +741,9 @@ void A_Look(mobj_t *actor) ...@@ -1020,8 +741,9 @@ void A_Look(mobj_t *actor)
// 3 = don't check meleestate and missilestate // 3 = don't check meleestate and missilestate
// var2 = unused // var2 = unused
// //
void A_Chase(mobj_t *actor) void A_Chase(void *data)
{ {
mobj_t *actor = data;
INT32 delta; INT32 delta;
INT32 locvar1 = var1; INT32 locvar1 = var1;
...@@ -1112,8 +834,9 @@ nomissile: ...@@ -1112,8 +834,9 @@ nomissile:
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_FaceStabChase(mobj_t *actor) void A_FaceStabChase(void *data)
{ {
mobj_t *actor = data;
INT32 delta; INT32 delta;
if (LUA_CallAction(A_FACESTABCHASE, actor)) if (LUA_CallAction(A_FACESTABCHASE, actor))
...@@ -1236,8 +959,9 @@ static void P_FaceStabFlume(mobj_t *actor) ...@@ -1236,8 +959,9 @@ static void P_FaceStabFlume(mobj_t *actor)
// var1 = effective duration // var1 = effective duration
// var2 = effective nextstate // var2 = effective nextstate
// //
void A_FaceStabRev(mobj_t *actor) void A_FaceStabRev(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -1255,13 +979,13 @@ void A_FaceStabRev(mobj_t *actor) ...@@ -1255,13 +979,13 @@ void A_FaceStabRev(mobj_t *actor)
if (!actor->reactiontime) if (!actor->reactiontime)
{ {
actor->reactiontime = locvar1; actor->reactiontime = locvar1;
S_StartSound(actor, actor->info->activesound); S_StartSoundFromMobj(actor, actor->info->activesound);
} }
else else
{ {
if ((--actor->reactiontime) == 0) if ((--actor->reactiontime) == 0)
{ {
S_StartSound(actor, actor->info->attacksound); S_StartSoundFromMobj(actor, actor->info->attacksound);
P_SetMobjState(actor, locvar2); P_SetMobjState(actor, locvar2);
} }
else else
...@@ -1280,8 +1004,9 @@ void A_FaceStabRev(mobj_t *actor) ...@@ -1280,8 +1004,9 @@ void A_FaceStabRev(mobj_t *actor)
// var1 = homing strength (recommended strength between 0-8) // var1 = homing strength (recommended strength between 0-8)
// var2 = effective nextstate // var2 = effective nextstate
// //
void A_FaceStabHurl(mobj_t *actor) void A_FaceStabHurl(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -1391,8 +1116,9 @@ void A_FaceStabHurl(mobj_t *actor) ...@@ -1391,8 +1116,9 @@ void A_FaceStabHurl(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = effective nextstate // var2 = effective nextstate
// //
void A_FaceStabMiss(mobj_t *actor) void A_FaceStabMiss(void *data)
{ {
mobj_t *actor = data;
INT32 locvar2 = var2; INT32 locvar2 = var2;
if (LUA_CallAction(A_FACESTABMISS, actor)) if (LUA_CallAction(A_FACESTABMISS, actor))
...@@ -1402,7 +1128,7 @@ void A_FaceStabMiss(mobj_t *actor) ...@@ -1402,7 +1128,7 @@ void A_FaceStabMiss(mobj_t *actor)
{ {
actor->extravalue2 -= 2; actor->extravalue2 -= 2;
actor->extravalue1 = 0; actor->extravalue1 = 0;
S_StartSound(actor, sfx_s3k47); S_StartSoundFromMobj(actor, sfx_s3k47);
P_SharpDust(actor, MT_SPINDUST, actor->angle); P_SharpDust(actor, MT_SPINDUST, actor->angle);
} }
...@@ -1425,8 +1151,9 @@ void A_FaceStabMiss(mobj_t *actor) ...@@ -1425,8 +1151,9 @@ void A_FaceStabMiss(mobj_t *actor)
// var1 = object to create // var1 = object to create
// var2 = effective nextstate for created object // var2 = effective nextstate for created object
// //
void A_StatueBurst(mobj_t *actor) void A_StatueBurst(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
mobjtype_t chunktype = (mobjtype_t)actor->info->raisestate; mobjtype_t chunktype = (mobjtype_t)actor->info->raisestate;
...@@ -1447,9 +1174,9 @@ void A_StatueBurst(mobj_t *actor) ...@@ -1447,9 +1174,9 @@ void A_StatueBurst(mobj_t *actor)
P_SetMobjState(new, (statenum_t)locvar2); P_SetMobjState(new, (statenum_t)locvar2);
if (P_MobjWasRemoved(new)) if (P_MobjWasRemoved(new))
return; return;
S_StartSound(new, new->info->attacksound); S_StartSoundFromMobj(new, new->info->attacksound);
S_StopSound(actor); S_StopSound(actor);
S_StartSound(actor, sfx_s3k96); S_StartSoundFromMobj(actor, sfx_s3k96);
{ {
fixed_t a, b; fixed_t a, b;
...@@ -1487,8 +1214,9 @@ void A_StatueBurst(mobj_t *actor) ...@@ -1487,8 +1214,9 @@ void A_StatueBurst(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_JetJawRoam(mobj_t *actor) void A_JetJawRoam(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_JETJAWROAM, actor)) if (LUA_CallAction(A_JETJAWROAM, actor))
return; return;
...@@ -1514,8 +1242,9 @@ void A_JetJawRoam(mobj_t *actor) ...@@ -1514,8 +1242,9 @@ void A_JetJawRoam(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_JetJawChomp(mobj_t *actor) void A_JetJawChomp(void *data)
{ {
mobj_t *actor = data;
INT32 delta; INT32 delta;
if (LUA_CallAction(A_JETJAWCHOMP, actor)) if (LUA_CallAction(A_JETJAWCHOMP, actor))
...@@ -1553,12 +1282,13 @@ void A_JetJawChomp(mobj_t *actor) ...@@ -1553,12 +1282,13 @@ void A_JetJawChomp(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_PointyThink(mobj_t *actor) void A_PointyThink(void *data)
{ {
mobj_t *actor = data;
INT32 i; INT32 i;
player_t *player = NULL; player_t *player = NULL;
mobj_t *ball; mobj_t *ball;
matrix_t m; oldmatrix_t m;
vector4_t v; vector4_t v;
vector4_t res; vector4_t res;
angle_t fa; angle_t fa;
...@@ -1574,7 +1304,7 @@ void A_PointyThink(mobj_t *actor) ...@@ -1574,7 +1304,7 @@ void A_PointyThink(mobj_t *actor)
// Find nearest player // Find nearest player
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i] || players[i].spectator) if (!players[i].ingame || players[i].spectator)
continue; continue;
if (!players[i].mo) if (!players[i].mo)
...@@ -1591,10 +1321,8 @@ void A_PointyThink(mobj_t *actor) ...@@ -1591,10 +1321,8 @@ void A_PointyThink(mobj_t *actor)
firsttime = false; firsttime = false;
player = &players[i]; player = &players[i];
} }
else else if (P_AreMobjsClose2D(players[i].mo, actor, P_GetMobjDistance2D(player->mo, actor)))
{ {
if (P_AproxDistance(players[i].mo->x - actor->x, players[i].mo->y - actor->y) <
P_AproxDistance(player->mo->x - actor->x, player->mo->y - actor->y))
player = &players[i]; player = &players[i];
} }
} }
...@@ -1608,7 +1336,7 @@ void A_PointyThink(mobj_t *actor) ...@@ -1608,7 +1336,7 @@ void A_PointyThink(mobj_t *actor)
if (P_MobjWasRemoved(actor)) if (P_MobjWasRemoved(actor))
return; return;
if (P_AproxDistance(player->mo->x - actor->x, player->mo->y - actor->y) < P_AproxDistance(player->mo->x + player->mo->momx - actor->x, player->mo->y + player->mo->momy - actor->y)) if (P_AreMobjsClose2D(player->mo, actor, GetDistance2D(actor->x, actor->y, player->mo->x + player->mo->momx, player->mo->y + player->mo->momy)))
sign = -1; // Player is moving away sign = -1; // Player is moving away
else else
sign = 1; // Player is moving closer sign = 1; // Player is moving closer
...@@ -1667,8 +1395,9 @@ void A_PointyThink(mobj_t *actor) ...@@ -1667,8 +1395,9 @@ void A_PointyThink(mobj_t *actor)
// 1 = tracer // 1 = tracer
// var2 = unused // var2 = unused
// //
void A_CheckBuddy(mobj_t *actor) void A_CheckBuddy(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
if (LUA_CallAction(A_CHECKBUDDY, actor)) if (LUA_CallAction(A_CHECKBUDDY, actor))
...@@ -1690,7 +1419,7 @@ static void P_ParabolicMove(mobj_t *actor, fixed_t x, fixed_t y, fixed_t z, fixe ...@@ -1690,7 +1419,7 @@ static void P_ParabolicMove(mobj_t *actor, fixed_t x, fixed_t y, fixed_t z, fixe
y -= actor->y; y -= actor->y;
z -= actor->z; z -= actor->z;
dh = P_AproxDistance(x, y); dh = GetDistance2D(0, 0, x, y);
actor->momx = FixedMul(FixedDiv(x, dh), speed); actor->momx = FixedMul(FixedDiv(x, dh), speed);
actor->momy = FixedMul(FixedDiv(y, dh), speed); actor->momy = FixedMul(FixedDiv(y, dh), speed);
...@@ -1709,8 +1438,9 @@ static void P_ParabolicMove(mobj_t *actor, fixed_t x, fixed_t y, fixed_t z, fixe ...@@ -1709,8 +1438,9 @@ static void P_ParabolicMove(mobj_t *actor, fixed_t x, fixed_t y, fixed_t z, fixe
// var1 = object type to fire // var1 = object type to fire
// var2 = unused // var2 = unused
// //
void A_HoodFire(mobj_t *actor) void A_HoodFire(void *data)
{ {
mobj_t *actor = data;
mobj_t *arrow; mobj_t *arrow;
INT32 locvar1 = var1; INT32 locvar1 = var1;
...@@ -1743,8 +1473,9 @@ void A_HoodFire(mobj_t *actor) ...@@ -1743,8 +1473,9 @@ void A_HoodFire(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_HoodThink(mobj_t *actor) void A_HoodThink(void *data)
{ {
mobj_t *actor = data;
fixed_t dx, dy, dz, dm; fixed_t dx, dy, dz, dm;
boolean checksight; boolean checksight;
...@@ -1760,11 +1491,11 @@ void A_HoodThink(mobj_t *actor) ...@@ -1760,11 +1491,11 @@ void A_HoodThink(mobj_t *actor)
} }
dx = (actor->target->x - actor->x), dy = (actor->target->y - actor->y), dz = (actor->target->z - actor->z); dx = (actor->target->x - actor->x), dy = (actor->target->y - actor->y), dz = (actor->target->z - actor->z);
dm = P_AproxDistance(dx, dy); dm = GetDistance2D(0, 0, dx, dy);
// Target dangerously close to robohood, retreat then. // Target dangerously close to robohood, retreat then.
if ((dm < 256<<FRACBITS) && (abs(dz) < 128<<FRACBITS) && !(actor->flags2 & MF2_AMBUSH)) if ((dm < 256<<FRACBITS) && (abs(dz) < 128<<FRACBITS) && !(actor->flags2 & MF2_AMBUSH))
{ {
S_StartSound(actor, actor->info->attacksound); S_StartSoundFromMobj(actor, actor->info->attacksound);
P_SetMobjState(actor, actor->info->raisestate); P_SetMobjState(actor, actor->info->raisestate);
return; return;
} }
...@@ -1803,6 +1534,10 @@ void A_HoodThink(mobj_t *actor) ...@@ -1803,6 +1534,10 @@ void A_HoodThink(mobj_t *actor)
P_SetMobjState(actor, actor->info->missilestate); P_SetMobjState(actor, actor->info->missilestate);
return; return;
} }
else
{
P_SetTarget(&actor->target, NULL);
}
} }
} }
...@@ -1813,8 +1548,9 @@ void A_HoodThink(mobj_t *actor) ...@@ -1813,8 +1548,9 @@ void A_HoodThink(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_HoodFall(mobj_t *actor) void A_HoodFall(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_HOODFALL, actor)) if (LUA_CallAction(A_HOODFALL, actor))
return; return;
...@@ -1833,8 +1569,9 @@ void A_HoodFall(mobj_t *actor) ...@@ -1833,8 +1569,9 @@ void A_HoodFall(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_ArrowBonks(mobj_t *actor) void A_ArrowBonks(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_ARROWBONKS, actor)) if (LUA_CallAction(A_ARROWBONKS, actor))
return; return;
...@@ -1856,8 +1593,9 @@ void A_ArrowBonks(mobj_t *actor) ...@@ -1856,8 +1593,9 @@ void A_ArrowBonks(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_SnailerThink(mobj_t *actor) void A_SnailerThink(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_SNAILERTHINK, actor)) if (LUA_CallAction(A_SNAILERTHINK, actor))
return; return;
...@@ -1888,7 +1626,7 @@ void A_SnailerThink(mobj_t *actor) ...@@ -1888,7 +1626,7 @@ void A_SnailerThink(mobj_t *actor)
fixed_t dist; fixed_t dist;
fixed_t dx, dy; fixed_t dx, dy;
dist = P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y); dist = P_GetMobjDistance2D(actor, actor->target);
if (an > ANGLE_45 && an <= ANGLE_90) // fire at 45 degrees to the left if (an > ANGLE_45 && an <= ANGLE_90) // fire at 45 degrees to the left
{ {
...@@ -1929,8 +1667,9 @@ void A_SnailerThink(mobj_t *actor) ...@@ -1929,8 +1667,9 @@ void A_SnailerThink(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_SharpChase(mobj_t *actor) void A_SharpChase(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_SHARPCHASE, actor)) if (LUA_CallAction(A_SHARPCHASE, actor))
return; return;
...@@ -1971,7 +1710,7 @@ void A_SharpChase(mobj_t *actor) ...@@ -1971,7 +1710,7 @@ void A_SharpChase(mobj_t *actor)
actor->threshold = actor->info->painchance; actor->threshold = actor->info->painchance;
P_SetMobjState(actor, actor->info->missilestate); P_SetMobjState(actor, actor->info->missilestate);
if (!P_MobjWasRemoved(actor)) if (!P_MobjWasRemoved(actor))
S_StartSound(actor, actor->info->attacksound); S_StartSoundFromMobj(actor, actor->info->attacksound);
} }
} }
...@@ -1982,8 +1721,9 @@ void A_SharpChase(mobj_t *actor) ...@@ -1982,8 +1721,9 @@ void A_SharpChase(mobj_t *actor)
// var1 = object # to spawn as dust (if not provided not done) // var1 = object # to spawn as dust (if not provided not done)
// var2 = if nonzero, do the old-style spinning using this as the angle difference // var2 = if nonzero, do the old-style spinning using this as the angle difference
// //
void A_SharpSpin(mobj_t *actor) void A_SharpSpin(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
angle_t oldang = actor->angle; angle_t oldang = actor->angle;
...@@ -2001,7 +1741,7 @@ void A_SharpSpin(mobj_t *actor) ...@@ -2001,7 +1741,7 @@ void A_SharpSpin(mobj_t *actor)
actor->angle = ang; actor->angle = ang;
actor->threshold--; actor->threshold--;
if (leveltime & 1) if (leveltime & 1)
S_StartSound(actor, actor->info->painsound); S_StartSoundFromMobj(actor, actor->info->painsound);
} }
else else
{ {
...@@ -2019,8 +1759,9 @@ void A_SharpSpin(mobj_t *actor) ...@@ -2019,8 +1759,9 @@ void A_SharpSpin(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_SharpDecel(mobj_t *actor) void A_SharpDecel(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_SHARPDECEL, actor)) if (LUA_CallAction(A_SHARPDECEL, actor))
return; return;
...@@ -2040,8 +1781,9 @@ void A_SharpDecel(mobj_t *actor) ...@@ -2040,8 +1781,9 @@ void A_SharpDecel(mobj_t *actor)
// var1 = speed (actor info's speed if 0) // var1 = speed (actor info's speed if 0)
// var2 = state to switch to when blocked (spawnstate if 0) // var2 = state to switch to when blocked (spawnstate if 0)
// //
void A_CrushstaceanWalk(mobj_t *actor) void A_CrushstaceanWalk(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = (var1 ? var1 : (INT32)actor->info->speed); INT32 locvar1 = (var1 ? var1 : (INT32)actor->info->speed);
INT32 locvar2 = (var2 ? var2 : (INT32)actor->info->spawnstate); INT32 locvar2 = (var2 ? var2 : (INT32)actor->info->spawnstate);
angle_t ang = actor->angle + ((actor->flags2 & MF2_AMBUSH) ? ANGLE_90 : ANGLE_270); angle_t ang = actor->angle + ((actor->flags2 & MF2_AMBUSH) ? ANGLE_90 : ANGLE_270);
...@@ -2073,8 +1815,9 @@ void A_CrushstaceanWalk(mobj_t *actor) ...@@ -2073,8 +1815,9 @@ void A_CrushstaceanWalk(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = state to go to if unsuccessful (spawnstate if 0) // var2 = state to go to if unsuccessful (spawnstate if 0)
// //
void A_CrushstaceanPunch(mobj_t *actor) void A_CrushstaceanPunch(void *data)
{ {
mobj_t *actor = data;
INT32 locvar2 = (var2 ? var2 : (INT32)actor->info->spawnstate); INT32 locvar2 = (var2 ? var2 : (INT32)actor->info->spawnstate);
if (LUA_CallAction(A_CRUSHSTACEANPUNCH, actor)) if (LUA_CallAction(A_CRUSHSTACEANPUNCH, actor))
...@@ -2092,7 +1835,7 @@ void A_CrushstaceanPunch(mobj_t *actor) ...@@ -2092,7 +1835,7 @@ void A_CrushstaceanPunch(mobj_t *actor)
actor->tracer->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); actor->tracer->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y);
P_SetMobjState(actor->tracer, actor->tracer->info->missilestate); P_SetMobjState(actor->tracer, actor->tracer->info->missilestate);
actor->tracer->extravalue1 = actor->tracer->extravalue2 = 0; actor->tracer->extravalue1 = actor->tracer->extravalue2 = 0;
S_StartSound(actor, actor->info->attacksound); S_StartSoundFromMobj(actor, actor->info->attacksound);
} }
// Function: A_CrushclawAim // Function: A_CrushclawAim
...@@ -2102,8 +1845,9 @@ void A_CrushstaceanPunch(mobj_t *actor) ...@@ -2102,8 +1845,9 @@ void A_CrushstaceanPunch(mobj_t *actor)
// var1 = sideways offset // var1 = sideways offset
// var2 = vertical offset // var2 = vertical offset
// //
void A_CrushclawAim(mobj_t *actor) void A_CrushclawAim(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
mobj_t *crab = actor->tracer; mobj_t *crab = actor->tracer;
...@@ -2151,7 +1895,7 @@ void A_CrushclawAim(mobj_t *actor) ...@@ -2151,7 +1895,7 @@ void A_CrushclawAim(mobj_t *actor)
if (!crab->target || !crab->info->missilestate || (statenum_t)(crab->state-states) == crab->info->missilestate) if (!crab->target || !crab->info->missilestate || (statenum_t)(crab->state-states) == crab->info->missilestate)
return; return;
if (((ang + ANG1) < ANG2) || P_AproxDistance(crab->x - crab->target->x, crab->y - crab->target->y) < 333*crab->scale) if (((ang + ANG1) < ANG2) || P_AreMobjsClose2D(crab, crab->target, 333*crab->scale))
P_SetMobjState(crab, crab->info->missilestate); P_SetMobjState(crab, crab->info->missilestate);
} }
...@@ -2164,8 +1908,9 @@ void A_CrushclawAim(mobj_t *actor) ...@@ -2164,8 +1908,9 @@ void A_CrushclawAim(mobj_t *actor)
// anything else - backwards // anything else - backwards
// var2 = state to change to when done // var2 = state to change to when done
// //
void A_CrushclawLaunch(mobj_t *actor) void A_CrushclawLaunch(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
mobj_t *crab = actor->tracer; mobj_t *crab = actor->tracer;
...@@ -2187,7 +1932,7 @@ void A_CrushclawLaunch(mobj_t *actor) ...@@ -2187,7 +1932,7 @@ void A_CrushclawLaunch(mobj_t *actor)
if (!actor->extravalue1) if (!actor->extravalue1)
{ {
S_StartSound(actor, actor->info->activesound); S_StartSoundFromMobj(actor, actor->info->activesound);
actor->extravalue1 = ((locvar1) ? -1 : 32); actor->extravalue1 = ((locvar1) ? -1 : 32);
} }
else if (actor->extravalue1 != 1) else if (actor->extravalue1 != 1)
...@@ -2243,10 +1988,10 @@ void A_CrushclawLaunch(mobj_t *actor) ...@@ -2243,10 +1988,10 @@ void A_CrushclawLaunch(mobj_t *actor)
if (P_MobjWasRemoved(actor)) if (P_MobjWasRemoved(actor))
return; return;
actor->extravalue1 = 0; actor->extravalue1 = 0;
actor->extravalue2 = FixedHypot(actor->x - actor->target->x, actor->y - actor->target->y)>>FRACBITS; actor->extravalue2 = P_GetMobjDistance2D(actor, actor->target)>>FRACBITS;
P_SetMobjState(actor, locvar2); P_SetMobjState(actor, locvar2);
S_StopSound(actor); S_StopSound(actor);
S_StartSound(actor, sfx_s3k49); S_StartSoundFromMobj(actor, sfx_s3k49);
} }
else else
{ {
...@@ -2274,7 +2019,7 @@ void A_CrushclawLaunch(mobj_t *actor) ...@@ -2274,7 +2019,7 @@ void A_CrushclawLaunch(mobj_t *actor)
P_SetMobjState(actor, locvar2); P_SetMobjState(actor, locvar2);
S_StopSound(actor); S_StopSound(actor);
if (!locvar1) if (!locvar1)
S_StartSound(actor, sfx_s3k64); S_StartSoundFromMobj(actor, sfx_s3k64);
} }
} }
...@@ -2305,8 +2050,9 @@ void A_CrushclawLaunch(mobj_t *actor) ...@@ -2305,8 +2050,9 @@ void A_CrushclawLaunch(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_VultureVtol(mobj_t *actor) void A_VultureVtol(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_VULTUREVTOL, actor)) if (LUA_CallAction(A_VULTUREVTOL, actor))
return; return;
...@@ -2331,7 +2077,7 @@ void A_VultureVtol(mobj_t *actor) ...@@ -2331,7 +2077,7 @@ void A_VultureVtol(mobj_t *actor)
// Attack! // Attack!
actor->momz = 0; actor->momz = 0;
P_SetMobjState(actor, actor->info->missilestate); P_SetMobjState(actor, actor->info->missilestate);
S_StartSound(actor, actor->info->activesound); S_StartSoundFromMobj(actor, actor->info->activesound);
} }
} }
...@@ -2342,8 +2088,9 @@ void A_VultureVtol(mobj_t *actor) ...@@ -2342,8 +2088,9 @@ void A_VultureVtol(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_VultureCheck(mobj_t *actor) void A_VultureCheck(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_VULTURECHECK, actor)) if (LUA_CallAction(A_VULTURECHECK, actor))
return; return;
...@@ -2396,8 +2143,9 @@ static void P_VultureHoverParticle(mobj_t *actor) ...@@ -2396,8 +2143,9 @@ static void P_VultureHoverParticle(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_VultureHover(mobj_t *actor) void A_VultureHover(void *data)
{ {
mobj_t *actor = data;
fixed_t targetz; fixed_t targetz;
fixed_t distdif; fixed_t distdif;
fixed_t memz = actor->z; fixed_t memz = actor->z;
...@@ -2461,8 +2209,9 @@ void A_VultureHover(mobj_t *actor) ...@@ -2461,8 +2209,9 @@ void A_VultureHover(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_VultureBlast(mobj_t *actor) void A_VultureBlast(void *data)
{ {
mobj_t *actor = data;
mobj_t *dust; mobj_t *dust;
UINT8 i; UINT8 i;
angle_t faa; angle_t faa;
...@@ -2471,7 +2220,7 @@ void A_VultureBlast(mobj_t *actor) ...@@ -2471,7 +2220,7 @@ void A_VultureBlast(mobj_t *actor)
if (LUA_CallAction(A_VULTUREBLAST, actor)) if (LUA_CallAction(A_VULTUREBLAST, actor))
return; return;
S_StartSound(actor, actor->info->attacksound); S_StartSoundFromMobj(actor, actor->info->attacksound);
faa = (actor->angle >> ANGLETOFINESHIFT) & FINEMASK; faa = (actor->angle >> ANGLETOFINESHIFT) & FINEMASK;
faacos = FINECOSINE(faa); faacos = FINECOSINE(faa);
...@@ -2501,8 +2250,9 @@ void A_VultureBlast(mobj_t *actor) ...@@ -2501,8 +2250,9 @@ void A_VultureBlast(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_VultureFly(mobj_t *actor) void A_VultureFly(void *data)
{ {
mobj_t *actor = data;
fixed_t speedmax = 18*FRACUNIT; fixed_t speedmax = 18*FRACUNIT;
angle_t angledif; angle_t angledif;
fixed_t dx, dy, dz, dxy, dm; fixed_t dx, dy, dz, dxy, dm;
...@@ -2522,10 +2272,10 @@ void A_VultureFly(mobj_t *actor) ...@@ -2522,10 +2272,10 @@ void A_VultureFly(mobj_t *actor)
dx = actor->target->x - actor->x; dx = actor->target->x - actor->x;
dy = actor->target->y - actor->y; dy = actor->target->y - actor->y;
dz = actor->target->z - actor->z; dz = actor->target->z - actor->z;
dxy = FixedHypot(dx, dy); dxy = GetDistance2D(0, 0, dx, dy);
if (leveltime % 4 == 0) if (leveltime % 4 == 0)
S_StartSound(actor, actor->info->activesound); S_StartSoundFromMobj(actor, actor->info->activesound);
if (angledif > ANGLE_180) if (angledif > ANGLE_180)
angledif = InvAngle(angledif); angledif = InvAngle(angledif);
...@@ -2547,7 +2297,7 @@ void A_VultureFly(mobj_t *actor) ...@@ -2547,7 +2297,7 @@ void A_VultureFly(mobj_t *actor)
dz = max(P_FloorzAtPos(actor->target->x, actor->target->y, actor->target->z, 0) - actor->z + 232*FRACUNIT, dz); dz = max(P_FloorzAtPos(actor->target->x, actor->target->y, actor->target->z, 0) - actor->z + 232*FRACUNIT, dz);
} }
dm = FixedHypot(dz, dxy); dm = GetDistance2D(0, 0, dz, dxy);
P_VultureHoverParticle(actor); P_VultureHoverParticle(actor);
...@@ -2564,7 +2314,7 @@ void A_VultureFly(mobj_t *actor) ...@@ -2564,7 +2314,7 @@ void A_VultureFly(mobj_t *actor)
actor->momy += FixedDiv(dy, dm)*2; actor->momy += FixedDiv(dy, dm)*2;
actor->momz += FixedDiv(dz, dm)*2; actor->momz += FixedDiv(dz, dm)*2;
momm = FixedHypot(actor->momz, FixedHypot(actor->momx, actor->momy)); momm = GetDistance3D(0, 0, 0, actor->momx, actor->momy, actor->momz);
if (momm > speedmax/2 && actor->reactiontime == 0) if (momm > speedmax/2 && actor->reactiontime == 0)
{ {
...@@ -2578,7 +2328,7 @@ void A_VultureFly(mobj_t *actor) ...@@ -2578,7 +2328,7 @@ void A_VultureFly(mobj_t *actor)
actor->flags &= ~MF_NOGRAVITY; actor->flags &= ~MF_NOGRAVITY;
P_SetMobjState(actor, actor->info->painstate); P_SetMobjState(actor, actor->info->painstate);
S_StopSound(actor); S_StopSound(actor);
S_StartSound(actor, actor->info->painsound); S_StartSoundFromMobj(actor, actor->info->painsound);
return; return;
} }
actor->extravalue1 = momm; actor->extravalue1 = momm;
...@@ -2600,8 +2350,9 @@ void A_VultureFly(mobj_t *actor) ...@@ -2600,8 +2350,9 @@ void A_VultureFly(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_SkimChase(mobj_t *actor) void A_SkimChase(void *data)
{ {
mobj_t *actor = data;
INT32 delta; INT32 delta;
if (LUA_CallAction(A_SKIMCHASE, actor)) if (LUA_CallAction(A_SKIMCHASE, actor))
...@@ -2688,8 +2439,9 @@ nomissile: ...@@ -2688,8 +2439,9 @@ nomissile:
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_FaceTarget(mobj_t *actor) void A_FaceTarget(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_FACETARGET, actor)) if (LUA_CallAction(A_FACETARGET, actor))
return; return;
...@@ -2706,8 +2458,9 @@ void A_FaceTarget(mobj_t *actor) ...@@ -2706,8 +2458,9 @@ void A_FaceTarget(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_FaceTracer(mobj_t *actor) void A_FaceTracer(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_FACETRACER, actor)) if (LUA_CallAction(A_FACETRACER, actor))
return; return;
...@@ -2726,8 +2479,9 @@ void A_FaceTracer(mobj_t *actor) ...@@ -2726,8 +2479,9 @@ void A_FaceTracer(mobj_t *actor)
// var2 >> 16 = height offset // var2 >> 16 = height offset
// var2 & 65535 = airtime // var2 & 65535 = airtime
// //
void A_LobShot(mobj_t *actor) void A_LobShot(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2 >> 16; INT32 locvar2 = var2 >> 16;
mobj_t *shot; mobj_t *shot;
...@@ -2772,7 +2526,7 @@ void A_LobShot(mobj_t *actor) ...@@ -2772,7 +2526,7 @@ void A_LobShot(mobj_t *actor)
shot->angle = an = actor->angle; shot->angle = an = actor->angle;
an >>= ANGLETOFINESHIFT; an >>= ANGLETOFINESHIFT;
dist = P_AproxDistance(actor->target->x - shot->x, actor->target->y - shot->y); dist = P_GetMobjDistance2D(actor->target, shot);
horizontal = dist / airtime; horizontal = dist / airtime;
vertical = FixedMul((gravity*airtime)/2, shot->scale); vertical = FixedMul((gravity*airtime)/2, shot->scale);
...@@ -2790,7 +2544,7 @@ void A_LobShot(mobj_t *actor) ...@@ -2790,7 +2544,7 @@ void A_LobShot(mobj_t *actor)
diff = actor->z - actor->target->z; diff = actor->z - actor->target->z;
{ {
launchhyp = P_AproxDistance(horizontal, vertical); launchhyp = GetDistance2D(0, 0, horizontal, vertical);
orig = FixedMul(FixedDiv(vertical, horizontal), diff); orig = FixedMul(FixedDiv(vertical, horizontal), diff);
...@@ -2806,7 +2560,7 @@ void A_LobShot(mobj_t *actor) ...@@ -2806,7 +2560,7 @@ void A_LobShot(mobj_t *actor)
*/ */
if (shot->info->seesound) if (shot->info->seesound)
S_StartSound(shot, shot->info->seesound); S_StartSoundFromMobj(shot, shot->info->seesound);
if (!(actor->flags & MF_BOSS)) if (!(actor->flags & MF_BOSS))
{ {
...@@ -2824,8 +2578,9 @@ void A_LobShot(mobj_t *actor) ...@@ -2824,8 +2578,9 @@ void A_LobShot(mobj_t *actor)
// var1 = object # to shoot // var1 = object # to shoot
// var2 = height offset // var2 = height offset
// //
void A_FireShot(mobj_t *actor) void A_FireShot(void *data)
{ {
mobj_t *actor = data;
fixed_t z; fixed_t z;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -2863,8 +2618,9 @@ void A_FireShot(mobj_t *actor) ...@@ -2863,8 +2618,9 @@ void A_FireShot(mobj_t *actor)
// var1 = object # to shoot // var1 = object # to shoot
// var2 = height offset // var2 = height offset
// //
void A_SuperFireShot(mobj_t *actor) void A_SuperFireShot(void *data)
{ {
mobj_t *actor = data;
fixed_t z; fixed_t z;
mobj_t *mo; mobj_t *mo;
INT32 locvar1 = var1; INT32 locvar1 = var1;
...@@ -2912,8 +2668,9 @@ void A_SuperFireShot(mobj_t *actor) ...@@ -2912,8 +2668,9 @@ void A_SuperFireShot(mobj_t *actor)
// 4 - Boss 3 Right side upper // 4 - Boss 3 Right side upper
// 5 - Boss 3 Right side lower // 5 - Boss 3 Right side lower
// //
void A_BossFireShot(mobj_t *actor) void A_BossFireShot(void *data)
{ {
mobj_t *actor = data;
fixed_t x, y, z; fixed_t x, y, z;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -2999,8 +2756,9 @@ void A_BossFireShot(mobj_t *actor) ...@@ -2999,8 +2756,9 @@ void A_BossFireShot(mobj_t *actor)
// var1 = object # to shoot // var1 = object # to shoot
// var2 = firing sound // var2 = firing sound
// //
void A_Boss7FireMissiles(mobj_t *actor) void A_Boss7FireMissiles(void *data)
{ {
mobj_t *actor = data;
mobj_t dummymo; mobj_t dummymo;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -3018,7 +2776,7 @@ void A_Boss7FireMissiles(mobj_t *actor) ...@@ -3018,7 +2776,7 @@ void A_Boss7FireMissiles(mobj_t *actor)
if (P_MobjWasRemoved(actor)) if (P_MobjWasRemoved(actor))
return; return;
S_StartSound(NULL, locvar2); S_StartSoundFromEverywhere(locvar2);
// set dummymo's coordinates // set dummymo's coordinates
dummymo.x = actor->target->x; dummymo.x = actor->target->x;
...@@ -3058,8 +2816,9 @@ void A_Boss7FireMissiles(mobj_t *actor) ...@@ -3058,8 +2816,9 @@ void A_Boss7FireMissiles(mobj_t *actor)
// 3 - Boss 1 Middle // 3 - Boss 1 Middle
// >=3 - Generic middle // >=3 - Generic middle
// //
void A_Boss1Laser(mobj_t *actor) void A_Boss1Laser(void *data)
{ {
mobj_t *actor = data;
fixed_t x, y, z, floorz, speed; fixed_t x, y, z, floorz, speed;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = (var2 & 65535); INT32 locvar2 = (var2 & 65535);
...@@ -3141,7 +2900,7 @@ void A_Boss1Laser(mobj_t *actor) ...@@ -3141,7 +2900,7 @@ void A_Boss1Laser(mobj_t *actor)
{ {
actor->angle = R_PointToAngle2(x, y, actor->target->x, actor->target->y); actor->angle = R_PointToAngle2(x, y, actor->target->x, actor->target->y);
if (mobjinfo[locvar1].seesound) if (mobjinfo[locvar1].seesound)
S_StartSound(actor, mobjinfo[locvar1].seesound); S_StartSoundFromMobj(actor, mobjinfo[locvar1].seesound);
point = P_SpawnMobj(x + P_ReturnThrustX(actor, actor->angle, actor->radius), y + P_ReturnThrustY(actor, actor->angle, actor->radius), actor->z - actor->height / 2, MT_EGGMOBILE_TARGET); point = P_SpawnMobj(x + P_ReturnThrustX(actor, actor->angle, actor->radius), y + P_ReturnThrustY(actor, actor->angle, actor->radius), actor->z - actor->height / 2, MT_EGGMOBILE_TARGET);
if (!P_MobjWasRemoved(point)) if (!P_MobjWasRemoved(point))
...@@ -3153,7 +2912,7 @@ void A_Boss1Laser(mobj_t *actor) ...@@ -3153,7 +2912,7 @@ void A_Boss1Laser(mobj_t *actor)
} }
} }
angle = R_PointToAngle2(z + (mobjinfo[locvar1].height>>1), 0, actor->target->z, R_PointToDist2(x, y, actor->target->x, actor->target->y)); angle = R_PointToAngle2(z + (mobjinfo[locvar1].height>>1), 0, actor->target->z, GetDistance2D(x, y, actor->target->x, actor->target->y));
point = P_SpawnMobj(x, y, z, locvar1); point = P_SpawnMobj(x, y, z, locvar1);
if (P_MobjWasRemoved(point)) if (P_MobjWasRemoved(point))
...@@ -3226,7 +2985,7 @@ void A_Boss1Laser(mobj_t *actor) ...@@ -3226,7 +2985,7 @@ void A_Boss1Laser(mobj_t *actor)
P_SetObjectMomZ(steam, FRACUNIT + 2*P_RandomFixed(), true); P_SetObjectMomZ(steam, FRACUNIT + 2*P_RandomFixed(), true);
P_InstaThrust(steam, FixedAngle(P_RandomKey(360)*FRACUNIT), 2*P_RandomFixed()); P_InstaThrust(steam, FixedAngle(P_RandomKey(360)*FRACUNIT), 2*P_RandomFixed());
if (point->info->painsound) if (point->info->painsound)
S_StartSound(steam, point->info->painsound); S_StartSoundFromMobj(steam, point->info->painsound);
} }
} }
else else
...@@ -3238,7 +2997,7 @@ void A_Boss1Laser(mobj_t *actor) ...@@ -3238,7 +2997,7 @@ void A_Boss1Laser(mobj_t *actor)
&& P_TryMove(point, point->x + distx, point->y + disty, false)) && P_TryMove(point, point->x + distx, point->y + disty, false))
{ {
if (point->info->seesound) if (point->info->seesound)
S_StartSound(point, point->info->seesound); S_StartSoundFromMobj(point, point->info->seesound);
} }
else else
P_RemoveMobj(point); P_RemoveMobj(point);
...@@ -3265,8 +3024,9 @@ void A_Boss1Laser(mobj_t *actor) ...@@ -3265,8 +3024,9 @@ void A_Boss1Laser(mobj_t *actor)
// & 1 - change horizontal angle // & 1 - change horizontal angle
// & 2 - change vertical angle // & 2 - change vertical angle
// //
void A_FocusTarget(mobj_t *actor) void A_FocusTarget(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -3276,7 +3036,7 @@ void A_FocusTarget(mobj_t *actor) ...@@ -3276,7 +3036,7 @@ void A_FocusTarget(mobj_t *actor)
if (actor->target) if (actor->target)
{ {
fixed_t speed = FixedMul(actor->info->speed, actor->scale); fixed_t speed = FixedMul(actor->info->speed, actor->scale);
fixed_t dist = (locvar2 ? R_PointToDist2(actor->x, actor->y, actor->target->x, actor->target->y) : speed+1); fixed_t dist = (locvar2 ? GetDistance2D(actor->x, actor->y, actor->target->x, actor->target->y) : speed+1);
angle_t hangle = ((locvar2 & 1) ? R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) : actor->angle); angle_t hangle = ((locvar2 & 1) ? R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) : actor->angle);
angle_t vangle = ((locvar2 & 2) ? R_PointToAngle2(actor->z , 0, actor->target->z + (actor->target->height>>1), dist) : ANGLE_90); angle_t vangle = ((locvar2 & 2) ? R_PointToAngle2(actor->z , 0, actor->target->z + (actor->target->height>>1), dist) : ANGLE_90);
switch(locvar1) switch(locvar1)
...@@ -3316,8 +3076,9 @@ void A_FocusTarget(mobj_t *actor) ...@@ -3316,8 +3076,9 @@ void A_FocusTarget(mobj_t *actor)
// var1 = sfx to play // var1 = sfx to play
// var2 = sfx to play in pinch // var2 = sfx to play in pinch
// //
void A_Boss4Reverse(mobj_t *actor) void A_Boss4Reverse(void *data)
{ {
mobj_t *actor = data;
sfxenum_t locvar1 = (sfxenum_t)var1; sfxenum_t locvar1 = (sfxenum_t)var1;
sfxenum_t locvar2 = (sfxenum_t)var2; sfxenum_t locvar2 = (sfxenum_t)var2;
...@@ -3327,7 +3088,7 @@ void A_Boss4Reverse(mobj_t *actor) ...@@ -3327,7 +3088,7 @@ void A_Boss4Reverse(mobj_t *actor)
actor->reactiontime = 0; actor->reactiontime = 0;
if (actor->movedir < 3) if (actor->movedir < 3)
{ {
S_StartSound(NULL, locvar1); S_StartSoundFromEverywhere(locvar1);
if (actor->movedir == 1) if (actor->movedir == 1)
actor->movedir = 2; actor->movedir = 2;
else else
...@@ -3335,7 +3096,7 @@ void A_Boss4Reverse(mobj_t *actor) ...@@ -3335,7 +3096,7 @@ void A_Boss4Reverse(mobj_t *actor)
} }
else else
{ {
S_StartSound(NULL, locvar2); S_StartSoundFromEverywhere(locvar2);
if (actor->movedir == 4) if (actor->movedir == 4)
actor->movedir = 5; actor->movedir = 5;
else else
...@@ -3352,14 +3113,15 @@ void A_Boss4Reverse(mobj_t *actor) ...@@ -3352,14 +3113,15 @@ void A_Boss4Reverse(mobj_t *actor)
// var1 = sfx to play // var1 = sfx to play
// var2 = unused // var2 = unused
// //
void A_Boss4SpeedUp(mobj_t *actor) void A_Boss4SpeedUp(void *data)
{ {
mobj_t *actor = data;
sfxenum_t locvar1 = (sfxenum_t)var1; sfxenum_t locvar1 = (sfxenum_t)var1;
if (LUA_CallAction(A_BOSS4SPEEDUP, actor)) if (LUA_CallAction(A_BOSS4SPEEDUP, actor))
return; return;
S_StartSound(NULL, locvar1); S_StartSoundFromEverywhere(locvar1);
actor->reactiontime = 2; actor->reactiontime = 2;
} }
...@@ -3370,14 +3132,15 @@ void A_Boss4SpeedUp(mobj_t *actor) ...@@ -3370,14 +3132,15 @@ void A_Boss4SpeedUp(mobj_t *actor)
// var1 = sfx to play // var1 = sfx to play
// var2 = unused // var2 = unused
// //
void A_Boss4Raise(mobj_t *actor) void A_Boss4Raise(void *data)
{ {
mobj_t *actor = data;
sfxenum_t locvar1 = (sfxenum_t)var1; sfxenum_t locvar1 = (sfxenum_t)var1;
if (LUA_CallAction(A_BOSS4RAISE, actor)) if (LUA_CallAction(A_BOSS4RAISE, actor))
return; return;
S_StartSound(NULL, locvar1); S_StartSoundFromEverywhere(locvar1);
actor->reactiontime = 1; actor->reactiontime = 1;
} }
...@@ -3396,8 +3159,9 @@ void A_Boss4Raise(mobj_t *actor) ...@@ -3396,8 +3159,9 @@ void A_Boss4Raise(mobj_t *actor)
// //
#define SKULLSPEED (20*FRACUNIT) #define SKULLSPEED (20*FRACUNIT)
void A_SkullAttack(mobj_t *actor) void A_SkullAttack(void *data)
{ {
mobj_t *actor = data;
mobj_t *dest; mobj_t *dest;
angle_t an; angle_t an;
INT32 dist; INT32 dist;
...@@ -3416,12 +3180,12 @@ void A_SkullAttack(mobj_t *actor) ...@@ -3416,12 +3180,12 @@ void A_SkullAttack(mobj_t *actor)
dest = actor->target; dest = actor->target;
actor->flags2 |= MF2_SKULLFLY; actor->flags2 |= MF2_SKULLFLY;
if (actor->info->activesound) if (actor->info->activesound)
S_StartSound(actor, actor->info->activesound); S_StartSoundFromMobj(actor, actor->info->activesound);
A_FaceTarget(actor); A_FaceTarget(actor);
if (P_MobjWasRemoved(actor)) if (P_MobjWasRemoved(actor))
return; return;
dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y); dist = P_GetMobjDistance2D(dest, actor);
if (locvar1 == 1) if (locvar1 == 1)
actor->angle += ANGLE_180; actor->angle += ANGLE_180;
...@@ -3514,8 +3278,9 @@ void A_SkullAttack(mobj_t *actor) ...@@ -3514,8 +3278,9 @@ void A_SkullAttack(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_BossZoom(mobj_t *actor) void A_BossZoom(void *data)
{ {
mobj_t *actor = data;
mobj_t *dest; mobj_t *dest;
angle_t an; angle_t an;
INT32 dist; INT32 dist;
...@@ -3537,7 +3302,7 @@ void A_BossZoom(mobj_t *actor) ...@@ -3537,7 +3302,7 @@ void A_BossZoom(mobj_t *actor)
an = actor->angle >> ANGLETOFINESHIFT; an = actor->angle >> ANGLETOFINESHIFT;
actor->momx = FixedMul(FixedMul(actor->info->speed*5*FRACUNIT, actor->scale), FINECOSINE(an)); actor->momx = FixedMul(FixedMul(actor->info->speed*5*FRACUNIT, actor->scale), FINECOSINE(an));
actor->momy = FixedMul(FixedMul(actor->info->speed*5*FRACUNIT, actor->scale), FINESINE(an)); actor->momy = FixedMul(FixedMul(actor->info->speed*5*FRACUNIT, actor->scale), FINESINE(an));
dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y); dist = P_GetMobjDistance2D(dest, actor);
dist = dist / FixedMul(actor->info->speed*5*FRACUNIT, actor->scale); dist = dist / FixedMul(actor->info->speed*5*FRACUNIT, actor->scale);
if (dist < 1) if (dist < 1)
...@@ -3554,8 +3319,9 @@ void A_BossZoom(mobj_t *actor) ...@@ -3554,8 +3319,9 @@ void A_BossZoom(mobj_t *actor)
// & 2 - Use entire vertical range of object to spawn // & 2 - Use entire vertical range of object to spawn
// var2 = Object to spawn. Default is MT_SONIC3KBOSSEXPLODE. // var2 = Object to spawn. Default is MT_SONIC3KBOSSEXPLODE.
// //
void A_BossScream(mobj_t *actor) void A_BossScream(void *data)
{ {
mobj_t *actor = data;
mobj_t *mo; mobj_t *mo;
fixed_t x, y, z; fixed_t x, y, z;
angle_t fa; angle_t fa;
...@@ -3597,7 +3363,7 @@ void A_BossScream(mobj_t *actor) ...@@ -3597,7 +3363,7 @@ void A_BossScream(mobj_t *actor)
mo->flags2 |= MF2_OBJECTFLIP; mo->flags2 |= MF2_OBJECTFLIP;
P_SetScale(mo, actor->scale, true); P_SetScale(mo, actor->scale, true);
if (actor->info->deathsound) if (actor->info->deathsound)
S_StartSound(mo, actor->info->deathsound); S_StartSoundFromMobj(mo, actor->info->deathsound);
} }
// Function: A_Scream // Function: A_Scream
...@@ -3607,8 +3373,9 @@ void A_BossScream(mobj_t *actor) ...@@ -3607,8 +3373,9 @@ void A_BossScream(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_Scream(mobj_t *actor) void A_Scream(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_SCREAM, actor)) if (LUA_CallAction(A_SCREAM, actor))
return; return;
...@@ -3623,13 +3390,14 @@ void A_Scream(mobj_t *actor) ...@@ -3623,13 +3390,14 @@ void A_Scream(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_Pain(mobj_t *actor) void A_Pain(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_PAIN, actor)) if (LUA_CallAction(A_PAIN, actor))
return; return;
if (actor->info->painsound) if (actor->info->painsound)
S_StartSound(actor, actor->info->painsound); S_StartSoundFromMobj(actor, actor->info->painsound);
actor->flags2 &= ~MF2_FIRING; actor->flags2 &= ~MF2_FIRING;
actor->flags2 &= ~MF2_SUPERFIRE; actor->flags2 &= ~MF2_SUPERFIRE;
...@@ -3642,8 +3410,9 @@ void A_Pain(mobj_t *actor) ...@@ -3642,8 +3410,9 @@ void A_Pain(mobj_t *actor)
// var1 = value to set repeat to if nonzero // var1 = value to set repeat to if nonzero
// var2 = unused // var2 = unused
// //
void A_Fall(mobj_t *actor) void A_Fall(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
if (LUA_CallAction(A_FALL, actor)) if (LUA_CallAction(A_FALL, actor))
...@@ -3671,11 +3440,12 @@ void A_Fall(mobj_t *actor) ...@@ -3671,11 +3440,12 @@ void A_Fall(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_1upThinker(mobj_t *actor) void A_1upThinker(void *data)
{ {
mobj_t *actor = data;
INT32 i; INT32 i;
fixed_t dist = INT32_MAX; INT32 closestdist = INT32_MAX;
fixed_t temp; INT32 dist;
INT32 closestplayer = -1; INT32 closestplayer = -1;
if (LUA_CallAction(A_1UPTHINKER, actor)) if (LUA_CallAction(A_1UPTHINKER, actor))
...@@ -3683,7 +3453,7 @@ void A_1upThinker(mobj_t *actor) ...@@ -3683,7 +3453,7 @@ void A_1upThinker(mobj_t *actor)
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i] || players[i].bot == BOT_2PAI || players[i].bot == BOT_2PHUMAN || players[i].spectator) if (!players[i].ingame || players[i].bot == BOT_2PAI || players[i].bot == BOT_2PHUMAN || players[i].spectator)
continue; continue;
if (!players[i].mo) if (!players[i].mo)
...@@ -3692,12 +3462,12 @@ void A_1upThinker(mobj_t *actor) ...@@ -3692,12 +3462,12 @@ void A_1upThinker(mobj_t *actor)
if ((netgame || multiplayer) && players[i].playerstate != PST_LIVE) if ((netgame || multiplayer) && players[i].playerstate != PST_LIVE)
continue; continue;
temp = P_AproxDistance(players[i].mo->x-actor->x, players[i].mo->y-actor->y); dist = P_GetMobjLargeDistance2D(actor, players[i].mo);
if (temp < dist) if (dist < closestdist)
{ {
closestplayer = i; closestplayer = i;
dist = temp; closestdist = dist;
} }
} }
...@@ -3742,8 +3512,9 @@ void A_1upThinker(mobj_t *actor) ...@@ -3742,8 +3512,9 @@ void A_1upThinker(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_MonitorPop(mobj_t *actor) void A_MonitorPop(void *data)
{ {
mobj_t *actor = data;
mobjtype_t item = 0; mobjtype_t item = 0;
mobj_t *newmobj; mobj_t *newmobj;
...@@ -3752,7 +3523,7 @@ void A_MonitorPop(mobj_t *actor) ...@@ -3752,7 +3523,7 @@ void A_MonitorPop(mobj_t *actor)
// Spawn the "pop" explosion. // Spawn the "pop" explosion.
if (actor->info->deathsound) if (actor->info->deathsound)
S_StartSound(actor, actor->info->deathsound); S_StartSoundFromMobj(actor, actor->info->deathsound);
P_SpawnMobjFromMobj(actor, 0, 0, actor->height/4, MT_EXPLODE); P_SpawnMobjFromMobj(actor, 0, 0, actor->height/4, MT_EXPLODE);
// We're dead now. De-solidify. // We're dead now. De-solidify.
...@@ -3833,8 +3604,9 @@ void A_MonitorPop(mobj_t *actor) ...@@ -3833,8 +3604,9 @@ void A_MonitorPop(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_GoldMonitorPop(mobj_t *actor) void A_GoldMonitorPop(void *data)
{ {
mobj_t *actor = data;
mobjtype_t item = 0; mobjtype_t item = 0;
mobj_t *newmobj; mobj_t *newmobj;
...@@ -3843,7 +3615,7 @@ void A_GoldMonitorPop(mobj_t *actor) ...@@ -3843,7 +3615,7 @@ void A_GoldMonitorPop(mobj_t *actor)
// Don't spawn the "pop" explosion, because the monitor isn't broken. // Don't spawn the "pop" explosion, because the monitor isn't broken.
if (actor->info->deathsound) if (actor->info->deathsound)
S_StartSound(actor, actor->info->deathsound); S_StartSoundFromMobj(actor, actor->info->deathsound);
//P_SpawnMobjFromMobj(actor, 0, 0, actor.height/4, MT_EXPLODE); //P_SpawnMobjFromMobj(actor, 0, 0, actor.height/4, MT_EXPLODE);
// Remove our flags for a bit. // Remove our flags for a bit.
...@@ -3924,8 +3696,9 @@ void A_GoldMonitorPop(mobj_t *actor) ...@@ -3924,8 +3696,9 @@ void A_GoldMonitorPop(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_GoldMonitorRestore(mobj_t *actor) void A_GoldMonitorRestore(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_GOLDMONITORRESTORE, actor)) if (LUA_CallAction(A_GOLDMONITORRESTORE, actor))
return; return;
...@@ -3940,8 +3713,9 @@ void A_GoldMonitorRestore(mobj_t *actor) ...@@ -3940,8 +3713,9 @@ void A_GoldMonitorRestore(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_GoldMonitorSparkle(mobj_t *actor) void A_GoldMonitorSparkle(void *data)
{ {
mobj_t *actor = data;
fixed_t i, ngangle, xofs, yofs; fixed_t i, ngangle, xofs, yofs;
if (LUA_CallAction(A_GOLDMONITORSPARKLE, actor)) if (LUA_CallAction(A_GOLDMONITORSPARKLE, actor))
...@@ -3968,8 +3742,9 @@ void A_GoldMonitorSparkle(mobj_t *actor) ...@@ -3968,8 +3742,9 @@ void A_GoldMonitorSparkle(mobj_t *actor)
// var1 = damagetype // var1 = damagetype
// var2 = unused // var2 = unused
// //
void A_Explode(mobj_t *actor) void A_Explode(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
if (LUA_CallAction(A_EXPLODE, actor)) if (LUA_CallAction(A_EXPLODE, actor))
...@@ -3994,9 +3769,7 @@ static mobj_t *P_FindBossFlyPoint(mobj_t *mo, INT32 tag) ...@@ -3994,9 +3769,7 @@ static mobj_t *P_FindBossFlyPoint(mobj_t *mo, INT32 tag)
continue; continue;
// If this one's further than the last one, don't go for it. // If this one's further than the last one, don't go for it.
if (closest && if (closest && P_AreMobjsFar3D(mo2, mo, P_GetMobjDistance3D(closest, mo)))
P_AproxDistance(P_AproxDistance(mo->x - mo2->x, mo->y - mo2->y), mo->z - mo2->z) >
P_AproxDistance(P_AproxDistance(mo->x - closest->x, mo->y - closest->y), mo->z - closest->z))
continue; continue;
closest = mo2; closest = mo2;
...@@ -4014,7 +3787,7 @@ static void P_DoBossVictory(mobj_t *mo) ...@@ -4014,7 +3787,7 @@ static void P_DoBossVictory(mobj_t *mo)
// scan the remaining thinkers to see if all bosses are dead // scan the remaining thinkers to see if all bosses are dead
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) 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; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -4037,7 +3810,7 @@ static void P_DoBossVictory(mobj_t *mo) ...@@ -4037,7 +3810,7 @@ static void P_DoBossVictory(mobj_t *mo)
{ {
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i]) if (!players[i].ingame)
continue; continue;
P_DoPlayerExit(&players[i], true); P_DoPlayerExit(&players[i], true);
} }
...@@ -4156,11 +3929,11 @@ static void P_DoCybrakdemonDeath(mobj_t *mo) ...@@ -4156,11 +3929,11 @@ static void P_DoCybrakdemonDeath(mobj_t *mo)
mo->flags |= MF_NOCLIP; mo->flags |= MF_NOCLIP;
mo->flags &= ~(MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT); mo->flags &= ~(MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT);
S_StartSound(NULL, sfx_bedie2); S_StartSoundFromEverywhere(sfx_bedie2);
P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_CYBRAKDEMON_VILE_EXPLOSION); P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_CYBRAKDEMON_VILE_EXPLOSION);
mo->z += P_MobjFlip(mo); mo->z += P_MobjFlip(mo);
P_SetObjectMomZ(mo, 12*FRACUNIT, false); P_SetObjectMomZ(mo, 12*FRACUNIT, false);
S_StartSound(mo, sfx_bgxpld); S_StartSoundFromMobj(mo, sfx_bgxpld);
if (mo->spawnpoint && !(mo->spawnpoint->args[6] & TMB_NODEATHFLING)) if (mo->spawnpoint && !(mo->spawnpoint->args[6] & TMB_NODEATHFLING))
P_InstaThrust(mo, R_PointToAngle2(0, 0, mo->x, mo->y), 14*FRACUNIT); P_InstaThrust(mo, R_PointToAngle2(0, 0, mo->x, mo->y), 14*FRACUNIT);
} }
...@@ -4179,7 +3952,7 @@ static void P_DoBoss5Death(mobj_t *mo) ...@@ -4179,7 +3952,7 @@ static void P_DoBoss5Death(mobj_t *mo)
mo->momx = ((16 - 1)*mo->momx)/16; mo->momx = ((16 - 1)*mo->momx)/16;
mo->momy = ((16 - 1)*mo->momy)/16; mo->momy = ((16 - 1)*mo->momy)/16;
{ {
const fixed_t time = FixedHypot(mo->tracer->x - mo->x, mo->tracer->y - mo->y)/FixedHypot(mo->momx, mo->momy); const fixed_t time = P_GetMobjDistance2D(mo->tracer, mo)/P_GetMobjMomentum2D(mo);
const fixed_t speed = 64*FRACUNIT; const fixed_t speed = 64*FRACUNIT;
mobj_t *pole = P_SpawnMobj( mobj_t *pole = P_SpawnMobj(
mo->tracer->x - P_ReturnThrustX(mo->tracer, mo->tracer->angle, speed*time), mo->tracer->x - P_ReturnThrustX(mo->tracer, mo->tracer->angle, speed*time),
...@@ -4189,8 +3962,10 @@ static void P_DoBoss5Death(mobj_t *mo) ...@@ -4189,8 +3962,10 @@ static void P_DoBoss5Death(mobj_t *mo)
if (!P_MobjWasRemoved(pole)) if (!P_MobjWasRemoved(pole))
{ {
P_SetScale(pole, 2*FRACUNIT, true); P_SetScale(pole, 2*FRACUNIT, true);
pole->angle = mo->tracer->angle;
pole->momx = P_ReturnThrustX(pole, pole->angle, speed); pole->momx = P_ReturnThrustX(pole, pole->angle, speed);
pole->momy = P_ReturnThrustY(pole, pole->angle, speed); pole->momy = P_ReturnThrustY(pole, pole->angle, speed);
P_SetTarget(&pole->tracer, P_SpawnMobj( P_SetTarget(&pole->tracer, P_SpawnMobj(
pole->x, pole->y, pole->x, pole->y,
pole->z - 256*FRACUNIT, pole->z - 256*FRACUNIT,
...@@ -4199,7 +3974,7 @@ static void P_DoBoss5Death(mobj_t *mo) ...@@ -4199,7 +3974,7 @@ static void P_DoBoss5Death(mobj_t *mo)
{ {
pole->tracer->flags |= MF_NOCLIPTHING; pole->tracer->flags |= MF_NOCLIPTHING;
P_SetScale(pole->tracer, 2*FRACUNIT, true); P_SetScale(pole->tracer, 2*FRACUNIT, true);
pole->angle = pole->tracer->angle = mo->tracer->angle; pole->tracer->angle = mo->tracer->angle;
pole->tracer->momx = pole->momx; pole->tracer->momx = pole->momx;
pole->tracer->momy = pole->momy; pole->tracer->momy = pole->momy;
...@@ -4266,70 +4041,71 @@ static void P_DoBossDefaultDeath(mobj_t *mo) ...@@ -4266,70 +4041,71 @@ static void P_DoBossDefaultDeath(mobj_t *mo)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_BossDeath(mobj_t *mo) void A_BossDeath(void *data)
{ {
mobj_t *actor = data;
INT32 i; INT32 i;
if (LUA_CallAction(A_BOSSDEATH, mo)) if (LUA_CallAction(A_BOSSDEATH, actor))
return; return;
if (mo->spawnpoint && mo->spawnpoint->args[2]) if (actor->spawnpoint && actor->spawnpoint->args[2])
P_LinedefExecute(mo->spawnpoint->args[2], mo, NULL); P_LinedefExecute(actor->spawnpoint->args[2], actor, NULL);
mo->health = 0; actor->health = 0;
// Boss is dead (but not necessarily fleeing...) // Boss is dead (but not necessarily fleeing...)
// Lua may use this to ignore bosses after they start fleeing // Lua may use this to ignore bosses after they start fleeing
mo->flags2 |= MF2_BOSSDEAD; actor->flags2 |= MF2_BOSSDEAD;
// make sure there is a player alive for victory // make sure there is a player alive for victory
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && ((players[i].mo && players[i].mo->health) if (players[i].ingame && ((players[i].mo && players[i].mo->health)
|| ((netgame || multiplayer) && (players[i].lives || players[i].continues)))) || ((netgame || multiplayer) && (players[i].lives || players[i].continues))))
break; break;
if (i == MAXPLAYERS) if (i == MAXPLAYERS)
return; // no one left alive, so do not end game return; // no one left alive, so do not end game
P_DoBossVictory(mo); P_DoBossVictory(actor);
if (LUA_HookMobj(mo, MOBJ_HOOK(BossDeath))) if (LUA_HookMobj(actor, MOBJ_HOOK(BossDeath)))
return; return;
else if (P_MobjWasRemoved(mo)) else if (P_MobjWasRemoved(actor))
return; return;
// Spawn your junk // Spawn your junk
switch (mo->type) switch (actor->type)
{ {
default: default:
break; break;
case MT_EGGMOBILE: // twin laser pods case MT_EGGMOBILE: // twin laser pods
P_SpawnBoss1Junk(mo); P_SpawnBoss1Junk(actor);
break; break;
case MT_EGGMOBILE2: // twin tanks + spigot case MT_EGGMOBILE2: // twin tanks + spigot
P_SpawnBoss2Junk(mo); P_SpawnBoss2Junk(actor);
break; break;
case MT_EGGMOBILE3: case MT_EGGMOBILE3:
P_SpawnBoss3Junk(mo); P_SpawnBoss3Junk(actor);
break; break;
} }
// now do another switch case for escaping // now do another switch case for escaping
switch (mo->type) switch (actor->type)
{ {
case MT_BLACKEGGMAN: case MT_BLACKEGGMAN:
mo->flags |= MF_NOCLIP; actor->flags |= MF_NOCLIP;
mo->flags &= ~MF_SPECIAL; actor->flags &= ~MF_SPECIAL;
S_StartSound(NULL, sfx_befall); S_StartSoundFromEverywhere(sfx_befall);
break; break;
case MT_CYBRAKDEMON: case MT_CYBRAKDEMON:
P_DoCybrakdemonDeath(mo); P_DoCybrakdemonDeath(actor);
break; break;
case MT_FANG: case MT_FANG:
P_DoBoss5Death(mo); P_DoBoss5Death(actor);
break; break;
default: //eggmobiles default: //eggmobiles
P_DoBossDefaultDeath(mo); P_DoBossDefaultDeath(actor);
break; break;
} }
} }
...@@ -4341,8 +4117,9 @@ void A_BossDeath(mobj_t *mo) ...@@ -4341,8 +4117,9 @@ void A_BossDeath(mobj_t *mo)
// var1 = new fixed_t shadowscale (default = FRACUNIT) // var1 = new fixed_t shadowscale (default = FRACUNIT)
// var2 = unused // var2 = unused
// //
void A_SetShadowScale(mobj_t *actor) void A_SetShadowScale(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
if (LUA_CallAction(A_SETSHADOWSCALE, actor)) if (LUA_CallAction(A_SETSHADOWSCALE, actor))
...@@ -4359,8 +4136,9 @@ void A_SetShadowScale(mobj_t *actor) ...@@ -4359,8 +4136,9 @@ void A_SetShadowScale(mobj_t *actor)
// var1 = new fixed_t shadowscale (default = FRACUNIT) // var1 = new fixed_t shadowscale (default = FRACUNIT)
// var2 = unused // var2 = unused
// //
void A_ShadowScream(mobj_t *actor) void A_ShadowScream(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_SHADOWSCREAM, actor)) if (LUA_CallAction(A_SHADOWSCREAM, actor))
return; return;
...@@ -4376,8 +4154,9 @@ void A_ShadowScream(mobj_t *actor) ...@@ -4376,8 +4154,9 @@ void A_ShadowScream(mobj_t *actor)
// var1 = Power index # // var1 = Power index #
// var2 = Power duration in tics // var2 = Power duration in tics
// //
void A_CustomPower(mobj_t *actor) void A_CustomPower(void *data)
{ {
mobj_t *actor = data;
player_t *player; player_t *player;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -4402,7 +4181,7 @@ void A_CustomPower(mobj_t *actor) ...@@ -4402,7 +4181,7 @@ void A_CustomPower(mobj_t *actor)
P_SetPower(player, locvar1, locvar2); P_SetPower(player, locvar1, locvar2);
if (actor->info->seesound) if (actor->info->seesound)
S_StartSound(player->mo, actor->info->seesound); S_StartSoundFromMobj(player->mo, actor->info->seesound);
} }
// Function: A_GiveWeapon // Function: A_GiveWeapon
...@@ -4412,8 +4191,9 @@ void A_CustomPower(mobj_t *actor) ...@@ -4412,8 +4191,9 @@ void A_CustomPower(mobj_t *actor)
// var1 = Weapon index # // var1 = Weapon index #
// var2 = unused // var2 = unused
// //
void A_GiveWeapon(mobj_t *actor) void A_GiveWeapon(void *data)
{ {
mobj_t *actor = data;
player_t *player; player_t *player;
INT32 locvar1 = var1; INT32 locvar1 = var1;
...@@ -4436,7 +4216,7 @@ void A_GiveWeapon(mobj_t *actor) ...@@ -4436,7 +4216,7 @@ void A_GiveWeapon(mobj_t *actor)
player->ringweapons |= locvar1; player->ringweapons |= locvar1;
if (actor->info->seesound) if (actor->info->seesound)
S_StartSound(player->mo, actor->info->seesound); S_StartSoundFromMobj(player->mo, actor->info->seesound);
} }
// Function: A_RingBox // Function: A_RingBox
...@@ -4446,8 +4226,9 @@ void A_GiveWeapon(mobj_t *actor) ...@@ -4446,8 +4226,9 @@ void A_GiveWeapon(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_RingBox(mobj_t *actor) void A_RingBox(void *data)
{ {
mobj_t *actor = data;
player_t *player; player_t *player;
if (LUA_CallAction(A_RINGBOX, actor)) if (LUA_CallAction(A_RINGBOX, actor))
...@@ -4463,7 +4244,7 @@ void A_RingBox(mobj_t *actor) ...@@ -4463,7 +4244,7 @@ void A_RingBox(mobj_t *actor)
P_GivePlayerRings(player, actor->info->reactiontime); P_GivePlayerRings(player, actor->info->reactiontime);
if (actor->info->seesound) if (actor->info->seesound)
S_StartSound(player->mo, actor->info->seesound); S_StartSoundFromMobj(player->mo, actor->info->seesound);
} }
// Function: A_Invincibility // Function: A_Invincibility
...@@ -4473,8 +4254,9 @@ void A_RingBox(mobj_t *actor) ...@@ -4473,8 +4254,9 @@ void A_RingBox(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_Invincibility(mobj_t *actor) void A_Invincibility(void *data)
{ {
mobj_t *actor = data;
player_t *player; player_t *player;
if (LUA_CallAction(A_INVINCIBILITY, actor)) if (LUA_CallAction(A_INVINCIBILITY, actor))
...@@ -4506,8 +4288,9 @@ void A_Invincibility(mobj_t *actor) ...@@ -4506,8 +4288,9 @@ void A_Invincibility(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_SuperSneakers(mobj_t *actor) void A_SuperSneakers(void *data)
{ {
mobj_t *actor = data;
player_t *player; player_t *player;
if (LUA_CallAction(A_SUPERSNEAKERS, actor)) if (LUA_CallAction(A_SUPERSNEAKERS, actor))
...@@ -4541,8 +4324,9 @@ void A_SuperSneakers(mobj_t *actor) ...@@ -4541,8 +4324,9 @@ void A_SuperSneakers(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_AwardScore(mobj_t *actor) void A_AwardScore(void *data)
{ {
mobj_t *actor = data;
player_t *player; player_t *player;
if (LUA_CallAction(A_AWARDSCORE, actor)) if (LUA_CallAction(A_AWARDSCORE, actor))
...@@ -4558,7 +4342,7 @@ void A_AwardScore(mobj_t *actor) ...@@ -4558,7 +4342,7 @@ void A_AwardScore(mobj_t *actor)
P_AddPlayerScore(player, actor->info->reactiontime); P_AddPlayerScore(player, actor->info->reactiontime);
if (actor->info->seesound) if (actor->info->seesound)
S_StartSound(player->mo, actor->info->seesound); S_StartSoundFromMobj(player->mo, actor->info->seesound);
} }
// Function: A_ExtraLife // Function: A_ExtraLife
...@@ -4568,8 +4352,9 @@ void A_AwardScore(mobj_t *actor) ...@@ -4568,8 +4352,9 @@ void A_AwardScore(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_ExtraLife(mobj_t *actor) void A_ExtraLife(void *data)
{ {
mobj_t *actor = data;
player_t *player; player_t *player;
if (LUA_CallAction(A_EXTRALIFE, actor)) if (LUA_CallAction(A_EXTRALIFE, actor))
...@@ -4591,7 +4376,7 @@ void A_ExtraLife(mobj_t *actor) ...@@ -4591,7 +4376,7 @@ void A_ExtraLife(mobj_t *actor)
if (ultimatemode) //I don't THINK so! if (ultimatemode) //I don't THINK so!
{ {
S_StartSound(player->mo, sfx_lose); S_StartSoundFromMobj(player->mo, sfx_lose);
return; return;
} }
...@@ -4605,8 +4390,9 @@ void A_ExtraLife(mobj_t *actor) ...@@ -4605,8 +4390,9 @@ void A_ExtraLife(mobj_t *actor)
// var1 = Shield type (make with SH_ constants) // var1 = Shield type (make with SH_ constants)
// var2 = unused // var2 = unused
// //
void A_GiveShield(mobj_t *actor) void A_GiveShield(void *data)
{ {
mobj_t *actor = data;
player_t *player; player_t *player;
UINT16 locvar1 = var1; UINT16 locvar1 = var1;
...@@ -4622,7 +4408,7 @@ void A_GiveShield(mobj_t *actor) ...@@ -4622,7 +4408,7 @@ void A_GiveShield(mobj_t *actor)
player = actor->target->player; player = actor->target->player;
P_SwitchShield(player, locvar1); P_SwitchShield(player, locvar1);
S_StartSound(player->mo, actor->info->seesound); S_StartSoundFromMobj(player->mo, actor->info->seesound);
} }
// Function: A_GravityBox // Function: A_GravityBox
...@@ -4632,8 +4418,9 @@ void A_GiveShield(mobj_t *actor) ...@@ -4632,8 +4418,9 @@ void A_GiveShield(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_GravityBox(mobj_t *actor) void A_GravityBox(void *data)
{ {
mobj_t *actor = data;
player_t *player; player_t *player;
if (LUA_CallAction(A_GRAVITYBOX, actor)) if (LUA_CallAction(A_GRAVITYBOX, actor))
...@@ -4647,7 +4434,7 @@ void A_GravityBox(mobj_t *actor) ...@@ -4647,7 +4434,7 @@ void A_GravityBox(mobj_t *actor)
player = actor->target->player; player = actor->target->player;
S_StartSound(player, actor->info->activesound); S_StartSoundFromMobj(player->mo, actor->info->activesound);
player->powers[pw_gravityboots] = (UINT16)(actor->info->reactiontime + 1); player->powers[pw_gravityboots] = (UINT16)(actor->info->reactiontime + 1);
} }
...@@ -4659,8 +4446,9 @@ void A_GravityBox(mobj_t *actor) ...@@ -4659,8 +4446,9 @@ void A_GravityBox(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_ScoreRise(mobj_t *actor) void A_ScoreRise(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_SCORERISE, actor)) if (LUA_CallAction(A_SCORERISE, actor))
return; return;
...@@ -4675,8 +4463,9 @@ void A_ScoreRise(mobj_t *actor) ...@@ -4675,8 +4463,9 @@ void A_ScoreRise(mobj_t *actor)
// var1 = jump strength // var1 = jump strength
// var2 = horizontal movement // var2 = horizontal movement
// //
void A_BunnyHop(mobj_t *actor) void A_BunnyHop(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -4698,8 +4487,9 @@ void A_BunnyHop(mobj_t *actor) ...@@ -4698,8 +4487,9 @@ void A_BunnyHop(mobj_t *actor)
// var1 = Distance to look for players. If no player is in this distance, bubbles aren't spawned. (Ambush overrides) // var1 = Distance to look for players. If no player is in this distance, bubbles aren't spawned. (Ambush overrides)
// var2 = unused // var2 = unused
// //
void A_BubbleSpawn(mobj_t *actor) void A_BubbleSpawn(void *data)
{ {
mobj_t *actor = data;
INT32 i, locvar1 = var1; INT32 i, locvar1 = var1;
UINT8 prandom; UINT8 prandom;
mobj_t *bubble = NULL; mobj_t *bubble = NULL;
...@@ -4720,8 +4510,8 @@ void A_BubbleSpawn(mobj_t *actor) ...@@ -4720,8 +4510,8 @@ void A_BubbleSpawn(mobj_t *actor)
// Quick! Look through players! // Quick! Look through players!
// Don't spawn bubbles unless a player is relatively close by (var1). // Don't spawn bubbles unless a player is relatively close by (var1).
for (i = 0; i < MAXPLAYERS; ++i) for (i = 0; i < MAXPLAYERS; ++i)
if (playeringame[i] && players[i].mo if (players[i].ingame && players[i].mo
&& P_AproxDistance(actor->x - players[i].mo->x, actor->y - players[i].mo->y) < (locvar1<<FRACBITS)) && P_AreMobjsClose2D(actor, players[i].mo, locvar1<<FRACBITS))
break; // Stop looking. break; // Stop looking.
if (i == MAXPLAYERS) if (i == MAXPLAYERS)
return; // don't make bubble! return; // don't make bubble!
...@@ -4747,8 +4537,9 @@ void A_BubbleSpawn(mobj_t *actor) ...@@ -4747,8 +4537,9 @@ void A_BubbleSpawn(mobj_t *actor)
// var1 = Distance to look for players. If no player is in this distance, bubbles aren't spawned. (Ambush overrides) // var1 = Distance to look for players. If no player is in this distance, bubbles aren't spawned. (Ambush overrides)
// var2 = unused // var2 = unused
// //
void A_FanBubbleSpawn(mobj_t *actor) void A_FanBubbleSpawn(void *data)
{ {
mobj_t *actor = data;
INT32 i, locvar1 = var1; INT32 i, locvar1 = var1;
UINT8 prandom; UINT8 prandom;
mobj_t *bubble = NULL; mobj_t *bubble = NULL;
...@@ -4765,8 +4556,8 @@ void A_FanBubbleSpawn(mobj_t *actor) ...@@ -4765,8 +4556,8 @@ void A_FanBubbleSpawn(mobj_t *actor)
// Quick! Look through players! // Quick! Look through players!
// Don't spawn bubbles unless a player is relatively close by (var2). // Don't spawn bubbles unless a player is relatively close by (var2).
for (i = 0; i < MAXPLAYERS; ++i) for (i = 0; i < MAXPLAYERS; ++i)
if (playeringame[i] && players[i].mo if (players[i].ingame && players[i].mo
&& P_AproxDistance(actor->x - players[i].mo->x, actor->y - players[i].mo->y) < (locvar1<<FRACBITS)) && P_AreMobjsClose2D(actor, players[i].mo, locvar1<<FRACBITS))
break; // Stop looking. break; // Stop looking.
if (i == MAXPLAYERS) if (i == MAXPLAYERS)
return; // don't make bubble! return; // don't make bubble!
...@@ -4792,8 +4583,9 @@ void A_FanBubbleSpawn(mobj_t *actor) ...@@ -4792,8 +4583,9 @@ void A_FanBubbleSpawn(mobj_t *actor)
// 1 = Rise straight up // 1 = Rise straight up
// var2 = rising speed // var2 = rising speed
// //
void A_BubbleRise(mobj_t *actor) void A_BubbleRise(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -4831,8 +4623,9 @@ void A_BubbleRise(mobj_t *actor) ...@@ -4831,8 +4623,9 @@ void A_BubbleRise(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_BubbleCheck(mobj_t *actor) void A_BubbleCheck(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_BUBBLECHECK, actor)) if (LUA_CallAction(A_BUBBLECHECK, actor))
return; return;
...@@ -4849,8 +4642,9 @@ void A_BubbleCheck(mobj_t *actor) ...@@ -4849,8 +4642,9 @@ void A_BubbleCheck(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_AttractChase(mobj_t *actor) void A_AttractChase(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_ATTRACTCHASE, actor)) if (LUA_CallAction(A_ATTRACTCHASE, actor))
return; return;
...@@ -4863,7 +4657,7 @@ void A_AttractChase(mobj_t *actor) ...@@ -4863,7 +4657,7 @@ void A_AttractChase(mobj_t *actor)
else else
actor->flags2 &= ~MF2_DONTDRAW; actor->flags2 &= ~MF2_DONTDRAW;
// Turn flingrings back into regular rings if attracted. // Turn rings into flingrings if shield is lost or out of range
if (actor->tracer && actor->tracer->player if (actor->tracer && actor->tracer->player
&& !(actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRIC) && actor->info->reactiontime && actor->type != (mobjtype_t)actor->info->reactiontime) && !(actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRIC) && actor->info->reactiontime && actor->type != (mobjtype_t)actor->info->reactiontime)
{ {
...@@ -4895,8 +4689,9 @@ void A_AttractChase(mobj_t *actor) ...@@ -4895,8 +4689,9 @@ void A_AttractChase(mobj_t *actor)
// If a FlingRing gets attracted by a shield, change it into a normal ring. // If a FlingRing gets attracted by a shield, change it into a normal ring.
if (actor->type == (mobjtype_t)actor->info->reactiontime) if (actor->type == (mobjtype_t)actor->info->reactiontime)
{ {
P_SpawnMobj(actor->x, actor->y, actor->z, actor->info->painchance); actor->type = mobjinfo[actor->type].painchance; // Become the regular version of the fling object.
P_RemoveMobj(actor); actor->flags = mobjinfo[actor->type].flags; // Reset actor flags.
P_SetMobjState(actor, actor->info->spawnstate); // Go to regular object's spawn state.
return; return;
} }
...@@ -4918,8 +4713,9 @@ void A_AttractChase(mobj_t *actor) ...@@ -4918,8 +4713,9 @@ void A_AttractChase(mobj_t *actor)
// lower 16 bits = proximity check distance (0 disables) // lower 16 bits = proximity check distance (0 disables)
// upper 16 bits = 0 to check proximity with target, 1 for tracer // upper 16 bits = 0 to check proximity with target, 1 for tracer
// //
void A_DropMine(mobj_t *actor) void A_DropMine(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
fixed_t z; fixed_t z;
...@@ -4930,7 +4726,6 @@ void A_DropMine(mobj_t *actor) ...@@ -4930,7 +4726,6 @@ void A_DropMine(mobj_t *actor)
if (locvar2 & 65535) if (locvar2 & 65535)
{ {
fixed_t dist;
mobj_t *target; mobj_t *target;
if (locvar2 >> 16) if (locvar2 >> 16)
...@@ -4941,9 +4736,7 @@ void A_DropMine(mobj_t *actor) ...@@ -4941,9 +4736,7 @@ void A_DropMine(mobj_t *actor)
if (!target) if (!target)
return; return;
dist = P_AproxDistance(actor->x-target->x, actor->y-target->y)>>FRACBITS; if (P_AreMobjsFar2D(actor, target, FixedMul((locvar2 & 65535), actor->scale) << FRACBITS))
if (dist > FixedMul((locvar2 & 65535), actor->scale))
return; return;
} }
...@@ -4961,7 +4754,7 @@ void A_DropMine(mobj_t *actor) ...@@ -4961,7 +4754,7 @@ void A_DropMine(mobj_t *actor)
mine->momz = actor->momz + actor->pmomz; mine->momz = actor->momz + actor->pmomz;
} }
S_StartSound(actor, actor->info->attacksound); S_StartSoundFromMobj(actor, actor->info->attacksound);
} }
// Function: A_FishJump // Function: A_FishJump
...@@ -4971,8 +4764,9 @@ void A_DropMine(mobj_t *actor) ...@@ -4971,8 +4764,9 @@ void A_DropMine(mobj_t *actor)
// var1 = Jump strength (in FRACBITS), if specified. Otherwise, uses the angle value. // var1 = Jump strength (in FRACBITS), if specified. Otherwise, uses the angle value.
// var2 = Trail object to spawn, if desired. // var2 = Trail object to spawn, if desired.
// //
void A_FishJump(mobj_t *actor) void A_FishJump(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -4984,8 +4778,8 @@ void A_FishJump(mobj_t *actor) ...@@ -4984,8 +4778,8 @@ void A_FishJump(mobj_t *actor)
UINT8 i; UINT8 i;
// Don't spawn trail unless a player is nearby. // Don't spawn trail unless a player is nearby.
for (i = 0; i < MAXPLAYERS; ++i) for (i = 0; i < MAXPLAYERS; ++i)
if (playeringame[i] && players[i].mo if (players[i].ingame && players[i].mo
&& P_AproxDistance(actor->x - players[i].mo->x, actor->y - players[i].mo->y) < (actor->info->speed)) && P_AreMobjsClose2D(actor, players[i].mo, actor->info->speed))
break; // Stop looking. break; // Stop looking.
if (i < MAXPLAYERS) if (i < MAXPLAYERS)
{ {
...@@ -5026,8 +4820,9 @@ void A_FishJump(mobj_t *actor) ...@@ -5026,8 +4820,9 @@ void A_FishJump(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_ThrownRing(mobj_t *actor) void A_ThrownRing(void *data)
{ {
mobj_t *actor = data;
INT32 c = 0; INT32 c = 0;
INT32 stop; INT32 stop;
player_t *player; player_t *player;
...@@ -5063,7 +4858,7 @@ void A_ThrownRing(mobj_t *actor) ...@@ -5063,7 +4858,7 @@ void A_ThrownRing(mobj_t *actor)
// A_GrenadeRing beeping lives once moooooore -SH // A_GrenadeRing beeping lives once moooooore -SH
if (actor->type == MT_THROWNGRENADE && actor->fuse % TICRATE == 0) if (actor->type == MT_THROWNGRENADE && actor->fuse % TICRATE == 0)
S_StartSound(actor, actor->info->attacksound); S_StartSoundFromMobj(actor, actor->info->attacksound);
// decrement bounce ring time // decrement bounce ring time
if (actor->flags2 & MF2_BOUNCERING) if (actor->flags2 & MF2_BOUNCERING)
...@@ -5095,8 +4890,7 @@ void A_ThrownRing(mobj_t *actor) ...@@ -5095,8 +4890,7 @@ void A_ThrownRing(mobj_t *actor)
// magnetic player. If he gets too far away, make // magnetic player. If he gets too far away, make
// sure to stop the attraction! // sure to stop the attraction!
if ((!actor->tracer->health) || (actor->tracer->player && (actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRIC) if ((!actor->tracer->health) || (actor->tracer->player && (actor->tracer->player->powers[pw_shield] & SH_PROTECTELECTRIC)
&& P_AproxDistance(P_AproxDistance(actor->tracer->x-actor->x, && P_AreMobjsFar3D(actor, actor->tracer, FixedMul(RING_DIST/4, actor->tracer->scale))))
actor->tracer->y-actor->y), actor->tracer->z-actor->z) > FixedMul(RING_DIST/4, actor->tracer->scale)))
{ {
P_SetTarget(&actor->tracer, NULL); P_SetTarget(&actor->tracer, NULL);
} }
...@@ -5126,7 +4920,7 @@ void A_ThrownRing(mobj_t *actor) ...@@ -5126,7 +4920,7 @@ void A_ThrownRing(mobj_t *actor)
if (actor->lastlook == stop) if (actor->lastlook == stop)
return; return;
if (!playeringame[actor->lastlook]) if (!players[actor->lastlook].ingame)
continue; continue;
if (c++ == 2) if (c++ == 2)
...@@ -5154,8 +4948,7 @@ void A_ThrownRing(mobj_t *actor) ...@@ -5154,8 +4948,7 @@ void A_ThrownRing(mobj_t *actor)
continue; continue;
} }
dist = P_AproxDistance(P_AproxDistance(player->mo->x-actor->x, dist = P_GetMobjDistance3D(player->mo, actor);
player->mo->y-actor->y), player->mo->z-actor->z);
// check distance // check distance
if (actor->flags2 & MF2_RAILRING) if (actor->flags2 & MF2_RAILRING)
...@@ -5186,24 +4979,25 @@ void A_ThrownRing(mobj_t *actor) ...@@ -5186,24 +4979,25 @@ void A_ThrownRing(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_SetSolidSteam(mobj_t *actor) void A_SetSolidSteam(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_SETSOLIDSTEAM, actor)) if (LUA_CallAction(A_SETSOLIDSTEAM, actor))
return; return;
actor->flags &= ~MF_NOCLIP; actor->flags &= ~MF_NOCLIP;
actor->flags |= MF_SOLID; actor->flags |= MF_SPECIAL;
if (!(actor->flags2 & MF2_AMBUSH)) if (!(actor->flags2 & MF2_AMBUSH))
{ {
if (P_RandomChance(FRACUNIT/8)) if (P_RandomChance(FRACUNIT/8))
{ {
if (actor->info->deathsound) if (actor->info->deathsound)
S_StartSound(actor, actor->info->deathsound); // Hiss! S_StartSoundFromMobj(actor, actor->info->deathsound); // Hiss!
} }
else else
{ {
if (actor->info->painsound) if (actor->info->painsound)
S_StartSound(actor, actor->info->painsound); S_StartSoundFromMobj(actor, actor->info->painsound);
} }
} }
...@@ -5217,12 +5011,13 @@ void A_SetSolidSteam(mobj_t *actor) ...@@ -5217,12 +5011,13 @@ void A_SetSolidSteam(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_UnsetSolidSteam(mobj_t *actor) void A_UnsetSolidSteam(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_UNSETSOLIDSTEAM, actor)) if (LUA_CallAction(A_UNSETSOLIDSTEAM, actor))
return; return;
actor->flags &= ~MF_SOLID; actor->flags &= ~MF_SPECIAL;
actor->flags |= MF_NOCLIP; actor->flags |= MF_NOCLIP;
} }
...@@ -5233,8 +5028,9 @@ void A_UnsetSolidSteam(mobj_t *actor) ...@@ -5233,8 +5028,9 @@ void A_UnsetSolidSteam(mobj_t *actor)
// var1 = degrees to rotate object (must be positive, because I'm lazy) // var1 = degrees to rotate object (must be positive, because I'm lazy)
// var2 = unused // var2 = unused
// //
void A_SignSpin(mobj_t *actor) void A_SignSpin(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT16 i; INT16 i;
angle_t rotateangle = FixedAngle(locvar1 << FRACBITS); angle_t rotateangle = FixedAngle(locvar1 << FRACBITS);
...@@ -5246,7 +5042,7 @@ void A_SignSpin(mobj_t *actor) ...@@ -5246,7 +5042,7 @@ void A_SignSpin(mobj_t *actor)
{ {
if (actor->flags2 & MF2_BOSSFLEE) if (actor->flags2 & MF2_BOSSFLEE)
{ {
S_StartSound(actor, actor->info->deathsound); S_StartSoundFromMobj(actor, actor->info->deathsound);
actor->flags2 &= ~MF2_BOSSFLEE; actor->flags2 &= ~MF2_BOSSFLEE;
} }
if (actor->spawnpoint) if (actor->spawnpoint)
...@@ -5273,7 +5069,7 @@ void A_SignSpin(mobj_t *actor) ...@@ -5273,7 +5069,7 @@ void A_SignSpin(mobj_t *actor)
{ {
if (!(actor->flags2 & MF2_BOSSFLEE)) if (!(actor->flags2 & MF2_BOSSFLEE))
{ {
S_StartSound(actor, actor->info->painsound); S_StartSoundFromMobj(actor, actor->info->painsound);
actor->flags2 |= MF2_BOSSFLEE; actor->flags2 |= MF2_BOSSFLEE;
} }
actor->movedir = rotateangle; actor->movedir = rotateangle;
...@@ -5328,8 +5124,9 @@ static boolean SignSkinCheck(player_t *player, INT32 num) ...@@ -5328,8 +5124,9 @@ static boolean SignSkinCheck(player_t *player, INT32 num)
// var1 = number of skin to display (e.g. 2 = Knuckles; special cases: -1 = target's skin, -2 = skin roulette, -3 = Eggman) // var1 = number of skin to display (e.g. 2 = Knuckles; special cases: -1 = target's skin, -2 = skin roulette, -3 = Eggman)
// var2 = custom sign color, if desired. // var2 = custom sign color, if desired.
// //
void A_SignPlayer(mobj_t *actor) void A_SignPlayer(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
skin_t *skin = NULL; skin_t *skin = NULL;
...@@ -5457,8 +5254,9 @@ void A_SignPlayer(mobj_t *actor) ...@@ -5457,8 +5254,9 @@ void A_SignPlayer(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = invert, z offset // var2 = invert, z offset
// //
void A_OverlayThink(mobj_t *actor) void A_OverlayThink(void *data)
{ {
mobj_t *actor = data;
fixed_t destx, desty; fixed_t destx, desty;
if (LUA_CallAction(A_OVERLAYTHINK, actor)) if (LUA_CallAction(A_OVERLAYTHINK, actor))
...@@ -5509,8 +5307,9 @@ void A_OverlayThink(mobj_t *actor) ...@@ -5509,8 +5307,9 @@ void A_OverlayThink(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_JetChase(mobj_t *actor) void A_JetChase(void *data)
{ {
mobj_t *actor = data;
fixed_t thefloor; fixed_t thefloor;
if (LUA_CallAction(A_JETCHASE, actor)) if (LUA_CallAction(A_JETCHASE, actor))
...@@ -5568,8 +5367,7 @@ void A_JetChase(mobj_t *actor) ...@@ -5568,8 +5367,7 @@ void A_JetChase(mobj_t *actor)
return; // got a new target return; // got a new target
// If the player is over 3072 fracunits away, then look for another player // If the player is over 3072 fracunits away, then look for another player
if (P_AproxDistance(P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y), if (P_AreMobjsFar3D(actor->target, actor, FixedMul(3072*FRACUNIT, actor->scale)) && P_LookForPlayers(actor, true, false, FixedMul(3072*FRACUNIT, actor->scale)))
actor->target->z - actor->z) > FixedMul(3072*FRACUNIT, actor->scale) && P_LookForPlayers(actor, true, false, FixedMul(3072*FRACUNIT, actor->scale)))
{ {
return; // got a new target return; // got a new target
} }
...@@ -5604,8 +5402,9 @@ void A_JetChase(mobj_t *actor) ...@@ -5604,8 +5402,9 @@ void A_JetChase(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_JetbThink(mobj_t *actor) void A_JetbThink(void *data)
{ {
mobj_t *actor = data;
sector_t *nextsector; sector_t *nextsector;
fixed_t thefloor; fixed_t thefloor;
...@@ -5638,7 +5437,7 @@ void A_JetbThink(mobj_t *actor) ...@@ -5638,7 +5437,7 @@ void A_JetbThink(mobj_t *actor)
P_SetTarget(&bomb->target, actor); P_SetTarget(&bomb->target, actor);
P_SetScale(bomb, actor->scale, true); P_SetScale(bomb, actor->scale, true);
actor->reactiontime = TICRATE; // one second actor->reactiontime = TICRATE; // one second
S_StartSound(actor, actor->info->attacksound); S_StartSoundFromMobj(actor, actor->info->attacksound);
} }
} }
} }
...@@ -5671,8 +5470,9 @@ void A_JetbThink(mobj_t *actor) ...@@ -5671,8 +5470,9 @@ void A_JetbThink(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_JetgShoot(mobj_t *actor) void A_JetgShoot(void *data)
{ {
mobj_t *actor = data;
fixed_t dist; fixed_t dist;
if (LUA_CallAction(A_JETGSHOOT, actor)) if (LUA_CallAction(A_JETGSHOOT, actor))
...@@ -5684,7 +5484,7 @@ void A_JetgShoot(mobj_t *actor) ...@@ -5684,7 +5484,7 @@ void A_JetgShoot(mobj_t *actor)
if (actor->reactiontime) if (actor->reactiontime)
return; return;
dist = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y); dist = P_GetMobjDistance2D(actor->target, actor);
if (dist > FixedMul(actor->info->painchance*FRACUNIT, actor->scale)) if (dist > FixedMul(actor->info->painchance*FRACUNIT, actor->scale))
return; return;
...@@ -5704,7 +5504,7 @@ void A_JetgShoot(mobj_t *actor) ...@@ -5704,7 +5504,7 @@ void A_JetgShoot(mobj_t *actor)
actor->reactiontime = actor->info->reactiontime*TICRATE*2; actor->reactiontime = actor->info->reactiontime*TICRATE*2;
if (actor->info->attacksound) if (actor->info->attacksound)
S_StartSound(actor, actor->info->attacksound); S_StartSoundFromMobj(actor, actor->info->attacksound);
} }
// Function: A_ShootBullet // Function: A_ShootBullet
...@@ -5714,8 +5514,9 @@ void A_JetgShoot(mobj_t *actor) ...@@ -5714,8 +5514,9 @@ void A_JetgShoot(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_ShootBullet(mobj_t *actor) void A_ShootBullet(void *data)
{ {
mobj_t *actor = data;
fixed_t dist; fixed_t dist;
if (LUA_CallAction(A_SHOOTBULLET, actor)) if (LUA_CallAction(A_SHOOTBULLET, actor))
...@@ -5724,7 +5525,7 @@ void A_ShootBullet(mobj_t *actor) ...@@ -5724,7 +5525,7 @@ void A_ShootBullet(mobj_t *actor)
if (!actor->target) if (!actor->target)
return; return;
dist = P_AproxDistance(P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y), actor->target->z - actor->z); dist = P_GetMobjDistance3D(actor->target, actor);
if (dist > FixedMul(actor->info->painchance*FRACUNIT, actor->scale)) if (dist > FixedMul(actor->info->painchance*FRACUNIT, actor->scale))
return; return;
...@@ -5736,7 +5537,7 @@ void A_ShootBullet(mobj_t *actor) ...@@ -5736,7 +5537,7 @@ void A_ShootBullet(mobj_t *actor)
P_SpawnMissile(actor, actor->target, (mobjtype_t)actor->info->raisestate); P_SpawnMissile(actor, actor->target, (mobjtype_t)actor->info->raisestate);
if (actor->info->attacksound) if (actor->info->attacksound)
S_StartSound(actor, actor->info->attacksound); S_StartSoundFromMobj(actor, actor->info->attacksound);
} }
static mobj_t *minus; static mobj_t *minus;
...@@ -5752,7 +5553,7 @@ static boolean PIT_MinusCarry(mobj_t *thing) ...@@ -5752,7 +5553,7 @@ static boolean PIT_MinusCarry(mobj_t *thing)
if (!(thing->flags & (MF_PUSHABLE|MF_ENEMY))) if (!(thing->flags & (MF_PUSHABLE|MF_ENEMY)))
return true; return true;
if (P_AproxDistance(minus->x - thing->x, minus->y - thing->y) >= minus->radius*3) if (P_AreMobjsFar2D(minus, thing, minus->radius*3))
return true; return true;
if (abs(thing->z - minus->z) > minus->height) if (abs(thing->z - minus->z) > minus->height)
...@@ -5770,8 +5571,9 @@ static boolean PIT_MinusCarry(mobj_t *thing) ...@@ -5770,8 +5571,9 @@ static boolean PIT_MinusCarry(mobj_t *thing)
// var1 = If 1, play digging sound. // var1 = If 1, play digging sound.
// var2 = unused // var2 = unused
// //
void A_MinusDigging(mobj_t *actor) void A_MinusDigging(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 rad = 32; INT32 rad = 32;
angle_t fa = (actor->angle >> ANGLETOFINESHIFT) & FINEMASK; angle_t fa = (actor->angle >> ANGLETOFINESHIFT) & FINEMASK;
...@@ -5799,7 +5601,7 @@ void A_MinusDigging(mobj_t *actor) ...@@ -5799,7 +5601,7 @@ void A_MinusDigging(mobj_t *actor)
} }
// If close enough, prepare to attack // If close enough, prepare to attack
if (P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) < actor->radius*2) if (P_AreMobjsClose2D(actor, actor->target, actor->radius*2))
{ {
P_SetMobjState(actor, actor->info->meleestate); P_SetMobjState(actor, actor->info->meleestate);
if (P_MobjWasRemoved(actor)) if (P_MobjWasRemoved(actor))
...@@ -5807,7 +5609,7 @@ void A_MinusDigging(mobj_t *actor) ...@@ -5807,7 +5609,7 @@ void A_MinusDigging(mobj_t *actor)
P_TryMove(actor, actor->target->x, actor->target->y, false); P_TryMove(actor, actor->target->x, actor->target->y, false);
if (P_MobjWasRemoved(actor)) if (P_MobjWasRemoved(actor))
return; return;
S_StartSound(actor, actor->info->attacksound); S_StartSoundFromMobj(actor, actor->info->attacksound);
// Spawn growing dirt pile. // Spawn growing dirt pile.
par = P_SpawnMobj(actor->x, actor->y, mz, MT_MINUSDIRT); par = P_SpawnMobj(actor->x, actor->y, mz, MT_MINUSDIRT);
...@@ -5849,7 +5651,7 @@ void A_MinusDigging(mobj_t *actor) ...@@ -5849,7 +5651,7 @@ void A_MinusDigging(mobj_t *actor)
minus = actor; minus = actor;
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_MinusCarry); P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_MinusCarry, minus);
} }
else else
{ {
...@@ -5867,8 +5669,9 @@ void A_MinusDigging(mobj_t *actor) ...@@ -5867,8 +5669,9 @@ void A_MinusDigging(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_MinusPopup(mobj_t *actor) void A_MinusPopup(void *data)
{ {
mobj_t *actor = data;
INT32 num = 6; INT32 num = 6;
angle_t ani = FixedAngle(FRACUNIT*360/num); angle_t ani = FixedAngle(FRACUNIT*360/num);
INT32 i; INT32 i;
...@@ -5881,7 +5684,7 @@ void A_MinusPopup(mobj_t *actor) ...@@ -5881,7 +5684,7 @@ void A_MinusPopup(mobj_t *actor)
else else
actor->momz = 10*FRACUNIT; actor->momz = 10*FRACUNIT;
S_StartSound(actor, sfx_s3k82); S_StartSoundFromMobj(actor, sfx_s3k82);
for (i = 1; i <= num; i++) for (i = 1; i <= num; i++)
{ {
mobj_t *rock = P_SpawnMobjFromMobj(actor, 0, 0, actor->height/4, MT_ROCKCRUMBLE1); mobj_t *rock = P_SpawnMobjFromMobj(actor, 0, 0, actor->height/4, MT_ROCKCRUMBLE1);
...@@ -5906,8 +5709,9 @@ void A_MinusPopup(mobj_t *actor) ...@@ -5906,8 +5709,9 @@ void A_MinusPopup(mobj_t *actor)
// var1 = State to switch to (if 0, use seestate). // var1 = State to switch to (if 0, use seestate).
// var2 = If not 0, spawn debris when hitting the floor. // var2 = If not 0, spawn debris when hitting the floor.
// //
void A_MinusCheck(mobj_t *actor) void A_MinusCheck(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -5943,8 +5747,9 @@ void A_MinusCheck(mobj_t *actor) ...@@ -5943,8 +5747,9 @@ void A_MinusCheck(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_ChickenCheck(mobj_t *actor) void A_ChickenCheck(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_CHICKENCHECK, actor)) if (LUA_CallAction(A_CHICKENCHECK, actor))
return; return;
...@@ -5970,8 +5775,9 @@ void A_ChickenCheck(mobj_t *actor) ...@@ -5970,8 +5775,9 @@ void A_ChickenCheck(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_JetgThink(mobj_t *actor) void A_JetgThink(void *data)
{ {
mobj_t *actor = data;
sector_t *nextsector; sector_t *nextsector;
fixed_t thefloor; fixed_t thefloor;
...@@ -6024,8 +5830,9 @@ void A_JetgThink(mobj_t *actor) ...@@ -6024,8 +5830,9 @@ void A_JetgThink(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_MouseThink(mobj_t *actor) void A_MouseThink(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_MOUSETHINK, actor)) if (LUA_CallAction(A_MOUSETHINK, actor))
return; return;
...@@ -6058,10 +5865,11 @@ void A_MouseThink(mobj_t *actor) ...@@ -6058,10 +5865,11 @@ void A_MouseThink(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_DetonChase(mobj_t *actor) void A_DetonChase(void *data)
{ {
mobj_t *actor = data;
angle_t exact; angle_t exact;
fixed_t xydist, dist; fixed_t xydist;
if (LUA_CallAction(A_DETONCHASE, actor)) if (LUA_CallAction(A_DETONCHASE, actor))
return; return;
...@@ -6105,7 +5913,7 @@ void A_DetonChase(mobj_t *actor) ...@@ -6105,7 +5913,7 @@ void A_DetonChase(mobj_t *actor)
} }
}*/ }*/
// movedir is up/down angle: how much it has to go up as it goes over to the player // movedir is up/down angle: how much it has to go up as it goes over to the player
xydist = P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y); xydist = P_GetMobjDistance2D(actor->tracer, actor);
exact = R_PointToAngle2(0, 0, xydist, actor->tracer->z - actor->z); exact = R_PointToAngle2(0, 0, xydist, actor->tracer->z - actor->z);
actor->movedir = exact; actor->movedir = exact;
/*if (exact != actor->movedir) /*if (exact != actor->movedir)
...@@ -6127,7 +5935,7 @@ void A_DetonChase(mobj_t *actor) ...@@ -6127,7 +5935,7 @@ void A_DetonChase(mobj_t *actor)
// check for melee attack // check for melee attack
if (actor->tracer) if (actor->tracer)
{ {
if (P_AproxDistance(actor->tracer->x-actor->x, actor->tracer->y-actor->y) < actor->radius+actor->tracer->radius) if (P_AreMobjsClose2D(actor->tracer, actor, actor->radius + actor->tracer->radius))
{ {
if (!((actor->tracer->z > actor->z + actor->height) || (actor->z > actor->tracer->z + actor->tracer->height))) if (!((actor->tracer->z > actor->z + actor->height) || (actor->z > actor->tracer->z + actor->tracer->height)))
{ {
...@@ -6138,8 +5946,7 @@ void A_DetonChase(mobj_t *actor) ...@@ -6138,8 +5946,7 @@ void A_DetonChase(mobj_t *actor)
} }
// chase towards player // chase towards player
if ((dist = P_AproxDistance(xydist, actor->tracer->z-actor->z)) if (P_AreMobjsFar3D(actor->tracer, actor, FixedMul((actor->info->painchance << FRACBITS), actor->scale)))
> FixedMul((actor->info->painchance << FRACBITS), actor->scale))
{ {
P_SetTarget(&actor->tracer, NULL); // Too far away P_SetTarget(&actor->tracer, NULL); // Too far away
return; return;
...@@ -6185,13 +5992,13 @@ void A_DetonChase(mobj_t *actor) ...@@ -6185,13 +5992,13 @@ void A_DetonChase(mobj_t *actor)
actor->momy = FixedMul(xyspeed, FINESINE(exact)); actor->momy = FixedMul(xyspeed, FINESINE(exact));
// Variable re-use // Variable re-use
xyspeed = (P_AproxDistance(actor->tracer->x - actor->x, P_AproxDistance(actor->tracer->y - actor->y, actor->tracer->z - actor->z))>>(FRACBITS+6)); xyspeed = P_GetMobjDistance3D(actor->tracer, actor)>>(FRACBITS+6);
if (xyspeed < 1) if (xyspeed < 1)
xyspeed = 1; xyspeed = 1;
if (leveltime % xyspeed == 0) if (leveltime % xyspeed == 0)
S_StartSound(actor, sfx_deton); S_StartSoundFromMobj(actor, sfx_deton);
} }
} }
...@@ -6207,8 +6014,9 @@ void A_DetonChase(mobj_t *actor) ...@@ -6207,8 +6014,9 @@ void A_DetonChase(mobj_t *actor)
// upper 16 bits = forward/backward offset // upper 16 bits = forward/backward offset
// lower 16 bits = sideways offset // lower 16 bits = sideways offset
// //
void A_CapeChase(mobj_t *actor) void A_CapeChase(void *data)
{ {
mobj_t *actor = data;
mobj_t *chaser; mobj_t *chaser;
fixed_t foffsetx, foffsety, boffsetx, boffsety; fixed_t foffsetx, foffsety, boffsetx, boffsety;
INT32 locvar1 = var1; INT32 locvar1 = var1;
...@@ -6270,8 +6078,9 @@ void A_CapeChase(mobj_t *actor) ...@@ -6270,8 +6078,9 @@ void A_CapeChase(mobj_t *actor)
// 1 = Use tracer // 1 = Use tracer
// var2 = unused // var2 = unused
// //
void A_RotateSpikeBall(mobj_t *actor) void A_RotateSpikeBall(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
const fixed_t radius = FixedMul(12*actor->info->speed, actor->scale); const fixed_t radius = FixedMul(12*actor->info->speed, actor->scale);
...@@ -6321,8 +6130,9 @@ void A_RotateSpikeBall(mobj_t *actor) ...@@ -6321,8 +6130,9 @@ void A_RotateSpikeBall(mobj_t *actor)
// 2 = Throw when target leaves MF2_SKULLFLY. // 2 = Throw when target leaves MF2_SKULLFLY.
// var2 = unused // var2 = unused
// //
void A_UnidusBall(mobj_t *actor) void A_UnidusBall(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
boolean canthrow = false; boolean canthrow = false;
...@@ -6333,7 +6143,7 @@ void A_UnidusBall(mobj_t *actor) ...@@ -6333,7 +6143,7 @@ void A_UnidusBall(mobj_t *actor)
if (actor->movecount) if (actor->movecount)
{ {
if (P_AproxDistance(actor->momx, actor->momy) < FixedMul(actor->info->damage/2, actor->scale)) if (P_GetMobjMomentum2D(actor) < FixedMul(actor->info->damage/2, actor->scale))
P_ExplodeMissile(actor); P_ExplodeMissile(actor);
return; return;
} }
...@@ -6365,7 +6175,7 @@ void A_UnidusBall(mobj_t *actor) ...@@ -6365,7 +6175,7 @@ void A_UnidusBall(mobj_t *actor)
if (locvar1 == 1 && canthrow) if (locvar1 == 1 && canthrow)
{ {
if (P_AproxDistance(actor->target->target->x - actor->target->x, actor->target->target->y - actor->target->y) > FixedMul(MISSILERANGE>>1, actor->scale) if (P_AreMobjsFar2D(actor->target->target, actor->target, FixedMul(MISSILERANGE>>1, actor->scale))
|| !P_CheckSight(actor, actor->target->target)) || !P_CheckSight(actor, actor->target->target))
return; return;
...@@ -6376,7 +6186,7 @@ void A_UnidusBall(mobj_t *actor) ...@@ -6376,7 +6186,7 @@ void A_UnidusBall(mobj_t *actor)
else if (locvar1 == 2) else if (locvar1 == 2)
{ {
boolean skull = (actor->target->flags2 & MF2_SKULLFLY) == MF2_SKULLFLY; boolean skull = (actor->target->flags2 & MF2_SKULLFLY) == MF2_SKULLFLY;
if (actor->target->state == &states[actor->target->info->painstate]) if (P_IsMobjInPainState(actor->target))
{ {
P_KillMobj(actor, NULL, NULL, 0); P_KillMobj(actor, NULL, NULL, 0);
return; return;
...@@ -6414,8 +6224,9 @@ void A_UnidusBall(mobj_t *actor) ...@@ -6414,8 +6224,9 @@ void A_UnidusBall(mobj_t *actor)
// //
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
void A_RockSpawn(mobj_t *actor) void A_RockSpawn(void *data)
{ {
mobj_t *actor = data;
mobj_t *mo; mobj_t *mo;
mobjtype_t type; mobjtype_t type;
fixed_t dist; fixed_t dist;
...@@ -6459,8 +6270,9 @@ void A_RockSpawn(mobj_t *actor) ...@@ -6459,8 +6270,9 @@ void A_RockSpawn(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_SlingAppear(mobj_t *actor) void A_SlingAppear(void *data)
{ {
mobj_t *actor = data;
UINT8 mlength = 4; UINT8 mlength = 4;
mobj_t *spawnee, *hprev; mobj_t *spawnee, *hprev;
...@@ -6514,8 +6326,9 @@ void A_SlingAppear(mobj_t *actor) ...@@ -6514,8 +6326,9 @@ void A_SlingAppear(mobj_t *actor)
// lower 16 bits = if > 0, state to change to when fuse = 1 // lower 16 bits = if > 0, state to change to when fuse = 1
// upper 16 bits: 0 = (default) don't set fuse unless 0, 1 = force change, 2 = force no change // upper 16 bits: 0 = (default) don't set fuse unless 0, 1 = force change, 2 = force no change
// //
void A_SetFuse(mobj_t *actor) void A_SetFuse(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -6539,8 +6352,9 @@ void A_SetFuse(mobj_t *actor) ...@@ -6539,8 +6352,9 @@ void A_SetFuse(mobj_t *actor)
// var1 = shoot bullets? // var1 = shoot bullets?
// var2 = "pogo mode" speed // var2 = "pogo mode" speed
// //
void A_CrawlaCommanderThink(mobj_t *actor) void A_CrawlaCommanderThink(void *data)
{ {
mobj_t *actor = data;
fixed_t dist; fixed_t dist;
sector_t *nextsector; sector_t *nextsector;
fixed_t thefloor; fixed_t thefloor;
...@@ -6560,7 +6374,7 @@ void A_CrawlaCommanderThink(mobj_t *actor) ...@@ -6560,7 +6374,7 @@ void A_CrawlaCommanderThink(mobj_t *actor)
if (!actor->fuse && actor->flags2 & MF2_FRET) if (!actor->fuse && actor->flags2 & MF2_FRET)
{ {
if (actor->info->painsound) if (actor->info->painsound)
S_StartSound(actor, actor->info->painsound); S_StartSoundFromMobj(actor, actor->info->painsound);
actor->fuse = TICRATE/2; actor->fuse = TICRATE/2;
actor->momz = 0; actor->momz = 0;
...@@ -6599,7 +6413,7 @@ void A_CrawlaCommanderThink(mobj_t *actor) ...@@ -6599,7 +6413,7 @@ void A_CrawlaCommanderThink(mobj_t *actor)
return; return;
} }
dist = P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y); dist = P_GetMobjDistance2D(actor, actor->target);
if (actor->target->player && (!hovermode || actor->reactiontime <= 2*TICRATE)) if (actor->target->player && (!hovermode || actor->reactiontime <= 2*TICRATE))
{ {
...@@ -6636,7 +6450,7 @@ void A_CrawlaCommanderThink(mobj_t *actor) ...@@ -6636,7 +6450,7 @@ void A_CrawlaCommanderThink(mobj_t *actor)
{ {
fixed_t mom; fixed_t mom;
P_Thrust(actor, actor->angle, 2*actor->scale); P_Thrust(actor, actor->angle, 2*actor->scale);
mom = P_AproxDistance(actor->momx, actor->momy); mom = P_GetMobjMomentum2D(actor);
if (mom > 20*actor->scale) if (mom > 20*actor->scale)
{ {
mom += 20*actor->scale; mom += 20*actor->scale;
...@@ -6655,7 +6469,7 @@ void A_CrawlaCommanderThink(mobj_t *actor) ...@@ -6655,7 +6469,7 @@ void A_CrawlaCommanderThink(mobj_t *actor)
P_InstaThrust(actor, actor->angle, FixedMul(40*FRACUNIT, actor->scale)); P_InstaThrust(actor, actor->angle, FixedMul(40*FRACUNIT, actor->scale));
actor->threshold = 1; actor->threshold = 1;
if (actor->info->attacksound) if (actor->info->attacksound)
S_StartSound(actor, actor->info->attacksound); S_StartSoundFromMobj(actor, actor->info->attacksound);
} }
} }
actor->reactiontime = 3*TICRATE + (P_RandomByte()>>2); actor->reactiontime = 3*TICRATE + (P_RandomByte()>>2);
...@@ -6668,7 +6482,7 @@ void A_CrawlaCommanderThink(mobj_t *actor) ...@@ -6668,7 +6482,7 @@ void A_CrawlaCommanderThink(mobj_t *actor)
if (!hovermode && actor->z <= actor->floorz) if (!hovermode && actor->z <= actor->floorz)
{ {
if (actor->info->activesound) if (actor->info->activesound)
S_StartSound(actor, actor->info->activesound); S_StartSoundFromMobj(actor, actor->info->activesound);
if (dist < FixedMul(256*FRACUNIT, actor->scale)) if (dist < FixedMul(256*FRACUNIT, actor->scale))
{ {
...@@ -6700,8 +6514,9 @@ void A_CrawlaCommanderThink(mobj_t *actor) ...@@ -6700,8 +6514,9 @@ void A_CrawlaCommanderThink(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_RingExplode(mobj_t *actor) void A_RingExplode(void *data)
{ {
mobj_t *actor = data;
mobj_t *mo2; mobj_t *mo2;
thinker_t *th; thinker_t *th;
angle_t d; angle_t d;
...@@ -6712,11 +6527,11 @@ void A_RingExplode(mobj_t *actor) ...@@ -6712,11 +6527,11 @@ void A_RingExplode(mobj_t *actor)
for (d = 0; d < 16; d++) for (d = 0; d < 16; d++)
P_SpawnParaloop(actor->x, actor->y, actor->z + actor->height, FixedMul(actor->info->painchance, actor->scale), 16, MT_NIGHTSPARKLE, S_NULL, d*(ANGLE_22h), true); P_SpawnParaloop(actor->x, actor->y, actor->z + actor->height, FixedMul(actor->info->painchance, actor->scale), 16, MT_NIGHTSPARKLE, S_NULL, d*(ANGLE_22h), true);
S_StartSound(actor, sfx_prloop); S_StartSoundFromMobj(actor, sfx_prloop);
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) 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; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -6724,7 +6539,7 @@ void A_RingExplode(mobj_t *actor) ...@@ -6724,7 +6539,7 @@ void A_RingExplode(mobj_t *actor)
if (mo2 == actor) // Don't explode yourself! Endless loop! if (mo2 == actor) // Don't explode yourself! Endless loop!
continue; continue;
if (P_AproxDistance(P_AproxDistance(mo2->x - actor->x, mo2->y - actor->y), mo2->z - actor->z) > FixedMul(actor->info->painchance, actor->scale)) if (P_AreMobjsFar3D(actor, mo2, FixedMul(actor->info->painchance, actor->scale)))
continue; continue;
if (mo2->flags & MF_SHOOTABLE) if (mo2->flags & MF_SHOOTABLE)
...@@ -6744,7 +6559,9 @@ void A_RingExplode(mobj_t *actor) ...@@ -6744,7 +6559,9 @@ void A_RingExplode(mobj_t *actor)
// var1 = object # to explode as debris // var1 = object # to explode as debris
// var2 = unused // var2 = unused
// //
void A_OldRingExplode(mobj_t *actor) { void A_OldRingExplode(void *data)
{
mobj_t *actor = data;
UINT8 i; UINT8 i;
mobj_t *mo; mobj_t *mo;
const fixed_t ns = FixedMul(20 * FRACUNIT, actor->scale); const fixed_t ns = FixedMul(20 * FRACUNIT, actor->scale);
...@@ -6828,8 +6645,9 @@ void A_OldRingExplode(mobj_t *actor) { ...@@ -6828,8 +6645,9 @@ void A_OldRingExplode(mobj_t *actor) {
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_MixUp(mobj_t *actor) void A_MixUp(void *data)
{ {
mobj_t *actor = data;
boolean teleported[MAXPLAYERS]; boolean teleported[MAXPLAYERS];
INT32 i, numplayers = 0, prandom = 0; INT32 i, numplayers = 0, prandom = 0;
...@@ -6843,7 +6661,7 @@ void A_MixUp(mobj_t *actor) ...@@ -6843,7 +6661,7 @@ void A_MixUp(mobj_t *actor)
// The random factor is okay for other game modes, but in these, it is cripplingly unfair. // The random factor is okay for other game modes, but in these, it is cripplingly unfair.
if (gametype == GT_HIDEANDSEEK || gametype == GT_RACE) if (gametype == GT_HIDEANDSEEK || gametype == GT_RACE)
{ {
S_StartSound(actor, sfx_lose); S_StartSoundFromMobj(actor, sfx_lose);
return; return;
} }
...@@ -6853,7 +6671,7 @@ void A_MixUp(mobj_t *actor) ...@@ -6853,7 +6671,7 @@ void A_MixUp(mobj_t *actor)
// Count the number of players in the game // Count the number of players in the game
// and grab their xyz coords // and grab their xyz coords
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && players[i].mo->health > 0 && players[i].playerstate == PST_LIVE if (players[i].ingame && players[i].mo && players[i].mo->health > 0 && players[i].playerstate == PST_LIVE
&& !players[i].exiting && !players[i].powers[pw_super] && players[i].powers[pw_carry] != CR_NIGHTSMODE) && !players[i].exiting && !players[i].powers[pw_super] && players[i].powers[pw_carry] != CR_NIGHTSMODE)
{ {
if ((netgame || multiplayer) && players[i].spectator) // Ignore spectators if ((netgame || multiplayer) && players[i].spectator) // Ignore spectators
...@@ -6864,7 +6682,7 @@ void A_MixUp(mobj_t *actor) ...@@ -6864,7 +6682,7 @@ void A_MixUp(mobj_t *actor)
if (numplayers <= 1) // Not enough players to mix up. if (numplayers <= 1) // Not enough players to mix up.
{ {
S_StartSound(actor, sfx_lose); S_StartSoundFromMobj(actor, sfx_lose);
return; return;
} }
else if (numplayers == 2) // Special case -- simple swap else if (numplayers == 2) // Special case -- simple swap
...@@ -6888,7 +6706,7 @@ void A_MixUp(mobj_t *actor) ...@@ -6888,7 +6706,7 @@ void A_MixUp(mobj_t *actor)
INT32 mflags2; INT32 mflags2;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && players[i].mo->health > 0 && players[i].playerstate == PST_LIVE if (players[i].ingame && players[i].mo && players[i].mo->health > 0 && players[i].playerstate == PST_LIVE
&& !players[i].exiting && !players[i].powers[pw_super]) && !players[i].exiting && !players[i].powers[pw_super])
{ {
if ((netgame || multiplayer) && players[i].spectator) // Ignore spectators if ((netgame || multiplayer) && players[i].spectator) // Ignore spectators
...@@ -6983,7 +6801,7 @@ void A_MixUp(mobj_t *actor) ...@@ -6983,7 +6801,7 @@ void A_MixUp(mobj_t *actor)
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (playeringame[i] && players[i].playerstate == PST_LIVE if (players[i].ingame && players[i].playerstate == PST_LIVE
&& players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super] && players[i].powers[pw_carry] != CR_NIGHTSMODE) && players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super] && players[i].powers[pw_carry] != CR_NIGHTSMODE)
{ {
if ((netgame || multiplayer) && players[i].spectator)// Ignore spectators if ((netgame || multiplayer) && players[i].spectator)// Ignore spectators
...@@ -7035,7 +6853,7 @@ void A_MixUp(mobj_t *actor) ...@@ -7035,7 +6853,7 @@ void A_MixUp(mobj_t *actor)
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (playeringame[i] && players[i].playerstate == PST_LIVE if (players[i].ingame && players[i].playerstate == PST_LIVE
&& players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super] && players[i].powers[pw_carry] != CR_NIGHTSMODE) && players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super] && players[i].powers[pw_carry] != CR_NIGHTSMODE)
{ {
if ((netgame || multiplayer) && players[i].spectator)// Ignore spectators if ((netgame || multiplayer) && players[i].spectator)// Ignore spectators
...@@ -7067,7 +6885,7 @@ void A_MixUp(mobj_t *actor) ...@@ -7067,7 +6885,7 @@ void A_MixUp(mobj_t *actor)
{ {
if (teleported[i]) if (teleported[i])
{ {
if (playeringame[i] && players[i].playerstate == PST_LIVE if (players[i].ingame && players[i].playerstate == PST_LIVE
&& players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super] && players[i].powers[pw_carry] != CR_NIGHTSMODE) && players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super] && players[i].powers[pw_carry] != CR_NIGHTSMODE)
{ {
if ((netgame || multiplayer) && players[i].spectator)// Ignore spectators if ((netgame || multiplayer) && players[i].spectator)// Ignore spectators
...@@ -7084,7 +6902,7 @@ void A_MixUp(mobj_t *actor) ...@@ -7084,7 +6902,7 @@ void A_MixUp(mobj_t *actor)
} }
// Play the 'bowrwoosh!' sound // Play the 'bowrwoosh!' sound
S_StartSound(NULL, sfx_mixup); S_StartSoundFromEverywhere(sfx_mixup);
} }
// Function: A_RecyclePowers // Function: A_RecyclePowers
...@@ -7094,8 +6912,9 @@ void A_MixUp(mobj_t *actor) ...@@ -7094,8 +6912,9 @@ void A_MixUp(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_RecyclePowers(mobj_t *actor) void A_RecyclePowers(void *data)
{ {
mobj_t *actor = data;
INT32 i, j, k, numplayers = 0; INT32 i, j, k, numplayers = 0;
#ifdef WEIGHTEDRECYCLER #ifdef WEIGHTEDRECYCLER
...@@ -7113,7 +6932,7 @@ void A_RecyclePowers(mobj_t *actor) ...@@ -7113,7 +6932,7 @@ void A_RecyclePowers(mobj_t *actor)
if (!multiplayer) if (!multiplayer)
{ {
S_StartSound(actor, sfx_lose); S_StartSoundFromMobj(actor, sfx_lose);
return; return;
} }
...@@ -7122,7 +6941,7 @@ void A_RecyclePowers(mobj_t *actor) ...@@ -7122,7 +6941,7 @@ void A_RecyclePowers(mobj_t *actor)
// Count the number of players in the game // Count the number of players in the game
for (i = 0, j = 0; i < MAXPLAYERS; i++) for (i = 0, j = 0; i < MAXPLAYERS; i++)
{ {
if (playeringame[i] && players[i].mo && players[i].mo->health > 0 && players[i].playerstate == PST_LIVE if (players[i].ingame && players[i].mo && players[i].mo->health > 0 && players[i].playerstate == PST_LIVE
&& !players[i].exiting && !((netgame || multiplayer) && players[i].spectator)) && !players[i].exiting && !((netgame || multiplayer) && players[i].spectator))
{ {
#ifndef WEIGHTEDRECYCLER #ifndef WEIGHTEDRECYCLER
...@@ -7152,7 +6971,7 @@ void A_RecyclePowers(mobj_t *actor) ...@@ -7152,7 +6971,7 @@ void A_RecyclePowers(mobj_t *actor)
if (numplayers <= 1) if (numplayers <= 1)
{ {
S_StartSound(actor, sfx_lose); S_StartSoundFromMobj(actor, sfx_lose);
return; //nobody to touch! return; //nobody to touch!
} }
...@@ -7176,7 +6995,8 @@ void A_RecyclePowers(mobj_t *actor) ...@@ -7176,7 +6995,8 @@ void A_RecyclePowers(mobj_t *actor)
#ifdef WEIGHTEDRECYCLER #ifdef WEIGHTEDRECYCLER
//the joys of qsort... //the joys of qsort...
if (beneficiary != 255) { if (beneficiary != 255)
{
qsort(playerslist, numplayers, sizeof(UINT8), P_RecycleCompare); qsort(playerslist, numplayers, sizeof(UINT8), P_RecycleCompare);
// now, make sure the benificiary is in the best slot // now, make sure the benificiary is in the best slot
...@@ -7225,7 +7045,7 @@ void A_RecyclePowers(mobj_t *actor) ...@@ -7225,7 +7045,7 @@ void A_RecyclePowers(mobj_t *actor)
P_FlashPal(&players[recv_pl], PAL_RECYCLE, 10); P_FlashPal(&players[recv_pl], PAL_RECYCLE, 10);
} }
S_StartSound(NULL, sfx_gravch); //heh, the sound effect I used is already in S_StartSoundFromEverywhere(sfx_gravch); //heh, the sound effect I used is already in
} }
// Function: A_Boss1Chase // Function: A_Boss1Chase
...@@ -7235,8 +7055,9 @@ void A_RecyclePowers(mobj_t *actor) ...@@ -7235,8 +7055,9 @@ void A_RecyclePowers(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_Boss1Chase(mobj_t *actor) void A_Boss1Chase(void *data)
{ {
mobj_t *actor = data;
INT32 delta; INT32 delta;
if (LUA_CallAction(A_BOSS1CHASE, actor)) if (LUA_CallAction(A_BOSS1CHASE, actor))
...@@ -7327,7 +7148,7 @@ nomissile: ...@@ -7327,7 +7148,7 @@ nomissile:
} }
// chase towards player // chase towards player
if (P_AproxDistance(actor->target->x-actor->x, actor->target->y-actor->y) > actor->radius+actor->target->radius) if (P_AreMobjsFar2D(actor->target, actor, actor->radius+actor->target->radius))
{ {
if (--actor->movecount < 0 || (!P_Move(actor, actor->info->speed) && !P_MobjWasRemoved(actor))) if (--actor->movecount < 0 || (!P_Move(actor, actor->info->speed) && !P_MobjWasRemoved(actor)))
P_NewChaseDir(actor); P_NewChaseDir(actor);
...@@ -7354,8 +7175,9 @@ nomissile: ...@@ -7354,8 +7175,9 @@ nomissile:
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_Boss2Chase(mobj_t *actor) void A_Boss2Chase(void *data)
{ {
mobj_t *actor = data;
fixed_t radius; fixed_t radius;
boolean reverse = false; boolean reverse = false;
INT32 speedvar; INT32 speedvar;
...@@ -7487,8 +7309,9 @@ void A_Boss2Chase(mobj_t *actor) ...@@ -7487,8 +7309,9 @@ void A_Boss2Chase(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_Boss2Pogo(mobj_t *actor) void A_Boss2Pogo(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_BOSS2POGO, actor)) if (LUA_CallAction(A_BOSS2POGO, actor))
return; return;
...@@ -7535,8 +7358,9 @@ void A_Boss2Pogo(mobj_t *actor) ...@@ -7535,8 +7358,9 @@ void A_Boss2Pogo(mobj_t *actor)
// var1 = Invincibility duration // var1 = Invincibility duration
// var2 = unused // var2 = unused
// //
void A_Boss2TakeDamage(mobj_t *actor) void A_Boss2TakeDamage(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
if (LUA_CallAction(A_BOSS2TAKEDAMAGE, actor)) if (LUA_CallAction(A_BOSS2TAKEDAMAGE, actor))
...@@ -7557,8 +7381,9 @@ void A_Boss2TakeDamage(mobj_t *actor) ...@@ -7557,8 +7381,9 @@ void A_Boss2TakeDamage(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_Boss7Chase(mobj_t *actor) void A_Boss7Chase(void *data)
{ {
mobj_t *actor = data;
INT32 delta; INT32 delta;
INT32 i; INT32 i;
...@@ -7571,14 +7396,14 @@ void A_Boss7Chase(mobj_t *actor) ...@@ -7571,14 +7396,14 @@ void A_Boss7Chase(mobj_t *actor)
// Self-adjust if stuck on the edge // Self-adjust if stuck on the edge
if (actor->tracer) if (actor->tracer)
{ {
if (P_AproxDistance(actor->x - actor->tracer->x, actor->y - actor->tracer->y) > 128*FRACUNIT - actor->radius) if (P_AreMobjsFar2D(actor, actor->tracer, 128*FRACUNIT - actor->radius))
P_InstaThrust(actor, R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y), FRACUNIT); P_InstaThrust(actor, R_PointToAngle2(actor->x, actor->y, actor->tracer->x, actor->tracer->y), FRACUNIT);
} }
if (actor->flags2 & MF2_FRET) if (actor->flags2 & MF2_FRET)
{ {
P_SetMobjState(actor, S_BLACKEGG_DESTROYPLAT1); P_SetMobjState(actor, S_BLACKEGG_DESTROYPLAT1);
S_StartSound(0, sfx_s3k53); S_StartSoundFromEverywhere(sfx_s3k53);
actor->flags2 &= ~MF2_FRET; actor->flags2 &= ~MF2_FRET;
return; return;
} }
...@@ -7598,7 +7423,7 @@ void A_Boss7Chase(mobj_t *actor) ...@@ -7598,7 +7423,7 @@ void A_Boss7Chase(mobj_t *actor)
// Is a player on top of us? // Is a player on top of us?
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i] || players[i].spectator) if (!players[i].ingame || players[i].spectator)
continue; continue;
if (!players[i].mo) if (!players[i].mo)
...@@ -7607,7 +7432,7 @@ void A_Boss7Chase(mobj_t *actor) ...@@ -7607,7 +7432,7 @@ void A_Boss7Chase(mobj_t *actor)
if (players[i].mo->health <= 0) if (players[i].mo->health <= 0)
continue; continue;
if (P_AproxDistance(players[i].mo->x - actor->x, players[i].mo->y - actor->y) > actor->radius) if (P_AreMobjsFar2D(players[i].mo, actor, actor->radius))
continue; continue;
if (players[i].mo->z > actor->z + actor->height - 2*FRACUNIT if (players[i].mo->z > actor->z + actor->height - 2*FRACUNIT
...@@ -7615,7 +7440,7 @@ void A_Boss7Chase(mobj_t *actor) ...@@ -7615,7 +7440,7 @@ void A_Boss7Chase(mobj_t *actor)
{ {
// Punch him! // Punch him!
P_SetMobjState(actor, actor->info->meleestate); P_SetMobjState(actor, actor->info->meleestate);
S_StartSound(0, sfx_begrnd); // warning sound S_StartSoundFromEverywhere(sfx_begrnd); // warning sound
return; return;
} }
} }
...@@ -7669,7 +7494,7 @@ void A_Boss7Chase(mobj_t *actor) ...@@ -7669,7 +7494,7 @@ void A_Boss7Chase(mobj_t *actor)
if (P_MobjWasRemoved(actor)) if (P_MobjWasRemoved(actor))
return; return;
P_SetMobjState(actor, actor->info->missilestate); P_SetMobjState(actor, actor->info->missilestate);
S_StartSound(0, sfx_beflap); S_StartSoundFromEverywhere(sfx_beflap);
break; break;
} }
...@@ -7698,8 +7523,9 @@ void A_Boss7Chase(mobj_t *actor) ...@@ -7698,8 +7523,9 @@ void A_Boss7Chase(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_GoopSplat(mobj_t *actor) void A_GoopSplat(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_GOOPSPLAT, actor)) if (LUA_CallAction(A_GOOPSPLAT, actor))
return; return;
...@@ -7720,8 +7546,9 @@ void A_GoopSplat(mobj_t *actor) ...@@ -7720,8 +7546,9 @@ void A_GoopSplat(mobj_t *actor)
// var1 = pogo jump strength // var1 = pogo jump strength
// var2 = idle pogo speed // var2 = idle pogo speed
// //
void A_Boss2PogoSFX(mobj_t *actor) void A_Boss2PogoSFX(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -7738,7 +7565,7 @@ void A_Boss2PogoSFX(mobj_t *actor) ...@@ -7738,7 +7565,7 @@ void A_Boss2PogoSFX(mobj_t *actor)
} }
// Boing! // Boing!
if (P_AproxDistance(actor->x-actor->target->x, actor->y-actor->target->y) < FixedMul(256*FRACUNIT, actor->scale)) if (P_AreMobjsClose2D(actor, actor->target, FixedMul(256*FRACUNIT, actor->scale)))
{ {
actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y);
P_InstaThrust(actor, actor->angle, FixedMul(actor->info->speed, actor->scale)); P_InstaThrust(actor, actor->angle, FixedMul(actor->info->speed, actor->scale));
...@@ -7750,7 +7577,7 @@ void A_Boss2PogoSFX(mobj_t *actor) ...@@ -7750,7 +7577,7 @@ void A_Boss2PogoSFX(mobj_t *actor)
actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_RandomChance(FRACUNIT/2) ? -prandom : +prandom); actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) + (P_RandomChance(FRACUNIT/2) ? -prandom : +prandom);
P_InstaThrust(actor, actor->angle, FixedMul(FixedMul(actor->info->speed,(locvar2)), actor->scale)); P_InstaThrust(actor, actor->angle, FixedMul(FixedMul(actor->info->speed,(locvar2)), actor->scale));
} }
if (actor->info->activesound) S_StartSound(actor, actor->info->activesound); if (actor->info->activesound) S_StartSoundFromMobj(actor, actor->info->activesound);
actor->momz = FixedMul(locvar1, actor->scale); // Bounce up in air actor->momz = FixedMul(locvar1, actor->scale); // Bounce up in air
actor->reactiontime = 1; actor->reactiontime = 1;
} }
...@@ -7762,8 +7589,9 @@ void A_Boss2PogoSFX(mobj_t *actor) ...@@ -7762,8 +7589,9 @@ void A_Boss2PogoSFX(mobj_t *actor)
// var1 = pogo jump strength // var1 = pogo jump strength
// var2 = idle pogo speed // var2 = idle pogo speed
// //
void A_Boss2PogoTarget(mobj_t *actor) void A_Boss2PogoTarget(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -7771,7 +7599,7 @@ void A_Boss2PogoTarget(mobj_t *actor) ...@@ -7771,7 +7599,7 @@ void A_Boss2PogoTarget(mobj_t *actor)
return; return;
if (!actor->target || !(actor->target->flags & MF_SHOOTABLE) || (actor->target->player && actor->target->player->powers[pw_flashing]) if (!actor->target || !(actor->target->flags & MF_SHOOTABLE) || (actor->target->player && actor->target->player->powers[pw_flashing])
|| P_AproxDistance(actor->x-actor->target->x, actor->y-actor->target->y) >= FixedMul(512*FRACUNIT, actor->scale)) || P_AreMobjsFar2D(actor, actor->target, FixedMul(512*FRACUNIT, actor->scale)))
{ {
// look for a new target // look for a new target
if (P_LookForPlayers(actor, true, false, 512*FRACUNIT)) if (P_LookForPlayers(actor, true, false, 512*FRACUNIT))
...@@ -7792,7 +7620,7 @@ void A_Boss2PogoTarget(mobj_t *actor) ...@@ -7792,7 +7620,7 @@ void A_Boss2PogoTarget(mobj_t *actor)
P_InstaThrust(actor, actor->angle+ANGLE_180, FixedMul(FixedMul(actor->info->speed,(locvar2)), actor->scale)); // Move at wandering speed P_InstaThrust(actor, actor->angle+ANGLE_180, FixedMul(FixedMul(actor->info->speed,(locvar2)), actor->scale)); // Move at wandering speed
} }
// Try to land on top of the player. // Try to land on top of the player.
else if (P_AproxDistance(actor->x-actor->target->x, actor->y-actor->target->y) < FixedMul(512*FRACUNIT, actor->scale)) else if (P_AreMobjsClose2D(actor, actor->target, FixedMul(512*FRACUNIT, actor->scale)))
{ {
fixed_t airtime, gravityadd, zoffs, height; fixed_t airtime, gravityadd, zoffs, height;
...@@ -7826,7 +7654,7 @@ void A_Boss2PogoTarget(mobj_t *actor) ...@@ -7826,7 +7654,7 @@ void A_Boss2PogoTarget(mobj_t *actor)
airtime = FixedDiv((-actor->momz - FixedSqrt(FixedMul(actor->momz,actor->momz)+zoffs)), gravityadd)<<1; // to try and land on their head rather than on their feet airtime = FixedDiv((-actor->momz - FixedSqrt(FixedMul(actor->momz,actor->momz)+zoffs)), gravityadd)<<1; // to try and land on their head rather than on their feet
actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y);
P_InstaThrust(actor, actor->angle, FixedDiv(P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y), airtime)); P_InstaThrust(actor, actor->angle, FixedDiv(P_GetMobjDistance2D(actor, actor->target), airtime));
} }
// Wander semi-randomly towards the player to get closer. // Wander semi-randomly towards the player to get closer.
else else
...@@ -7838,7 +7666,7 @@ void A_Boss2PogoTarget(mobj_t *actor) ...@@ -7838,7 +7666,7 @@ void A_Boss2PogoTarget(mobj_t *actor)
P_InstaThrust(actor, actor->angle, FixedMul(FixedMul(actor->info->speed,(locvar2)), actor->scale)); // Move at wandering speed P_InstaThrust(actor, actor->angle, FixedMul(FixedMul(actor->info->speed,(locvar2)), actor->scale)); // Move at wandering speed
} }
// Boing! // Boing!
if (actor->info->activesound) S_StartSound(actor, actor->info->activesound); if (actor->info->activesound) S_StartSoundFromMobj(actor, actor->info->activesound);
if (actor->info->missilestate) // spawn the pogo stick collision box if (actor->info->missilestate) // spawn the pogo stick collision box
{ {
...@@ -7857,8 +7685,9 @@ void A_Boss2PogoTarget(mobj_t *actor) ...@@ -7857,8 +7685,9 @@ void A_Boss2PogoTarget(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_EggmanBox(mobj_t *actor) void A_EggmanBox(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_EGGMANBOX, actor)) if (LUA_CallAction(A_EGGMANBOX, actor))
return; return;
...@@ -7878,8 +7707,9 @@ void A_EggmanBox(mobj_t *actor) ...@@ -7878,8 +7707,9 @@ void A_EggmanBox(mobj_t *actor)
// var1 = object # to repeatedly fire // var1 = object # to repeatedly fire
// var2 = distance threshold // var2 = distance threshold
// //
void A_TurretFire(mobj_t *actor) void A_TurretFire(void *data)
{ {
mobj_t *actor = data;
INT32 count = 0; INT32 count = 0;
fixed_t dist; fixed_t dist;
INT32 locvar1 = var1; INT32 locvar1 = var1;
...@@ -7898,7 +7728,7 @@ void A_TurretFire(mobj_t *actor) ...@@ -7898,7 +7728,7 @@ void A_TurretFire(mobj_t *actor)
while (P_SupermanLook4Players(actor) && count < MAXPLAYERS) while (P_SupermanLook4Players(actor) && count < MAXPLAYERS)
{ {
if (P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) < dist) if (P_AreMobjsClose2D(actor, actor->target, dist))
{ {
actor->flags2 |= MF2_FIRING; actor->flags2 |= MF2_FIRING;
actor->extravalue1 = locvar1; actor->extravalue1 = locvar1;
...@@ -7916,8 +7746,9 @@ void A_TurretFire(mobj_t *actor) ...@@ -7916,8 +7746,9 @@ void A_TurretFire(mobj_t *actor)
// var1 = object # to repeatedly fire // var1 = object # to repeatedly fire
// var2 = distance threshold // var2 = distance threshold
// //
void A_SuperTurretFire(mobj_t *actor) void A_SuperTurretFire(void *data)
{ {
mobj_t *actor = data;
INT32 count = 0; INT32 count = 0;
fixed_t dist; fixed_t dist;
INT32 locvar1 = var1; INT32 locvar1 = var1;
...@@ -7936,7 +7767,7 @@ void A_SuperTurretFire(mobj_t *actor) ...@@ -7936,7 +7767,7 @@ void A_SuperTurretFire(mobj_t *actor)
while (P_SupermanLook4Players(actor) && count < MAXPLAYERS) while (P_SupermanLook4Players(actor) && count < MAXPLAYERS)
{ {
if (P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) < dist) if (P_AreMobjsClose2D(actor, actor->target, dist))
{ {
actor->flags2 |= MF2_FIRING; actor->flags2 |= MF2_FIRING;
actor->flags2 |= MF2_SUPERFIRE; actor->flags2 |= MF2_SUPERFIRE;
...@@ -7955,8 +7786,9 @@ void A_SuperTurretFire(mobj_t *actor) ...@@ -7955,8 +7786,9 @@ void A_SuperTurretFire(mobj_t *actor)
// var1 = Don't play activesound? // var1 = Don't play activesound?
// var2 = unused // var2 = unused
// //
void A_TurretStop(mobj_t *actor) void A_TurretStop(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
if (LUA_CallAction(A_TURRETSTOP, actor)) if (LUA_CallAction(A_TURRETSTOP, actor))
...@@ -7966,7 +7798,7 @@ void A_TurretStop(mobj_t *actor) ...@@ -7966,7 +7798,7 @@ void A_TurretStop(mobj_t *actor)
actor->flags2 &= ~MF2_SUPERFIRE; actor->flags2 &= ~MF2_SUPERFIRE;
if (actor->target && actor->info->activesound && !locvar1) if (actor->target && actor->info->activesound && !locvar1)
S_StartSound(actor, actor->info->activesound); S_StartSoundFromMobj(actor, actor->info->activesound);
} }
// Function: A_SparkFollow // Function: A_SparkFollow
...@@ -7976,8 +7808,9 @@ void A_TurretStop(mobj_t *actor) ...@@ -7976,8 +7808,9 @@ void A_TurretStop(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_SparkFollow(mobj_t *actor) void A_SparkFollow(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_SPARKFOLLOW, actor)) if (LUA_CallAction(A_SPARKFOLLOW, actor))
return; return;
...@@ -8009,8 +7842,9 @@ void A_SparkFollow(mobj_t *actor) ...@@ -8009,8 +7842,9 @@ void A_SparkFollow(mobj_t *actor)
// var1 = sfx to play // var1 = sfx to play
// var2 = length of sfx, set to threshold if played // var2 = length of sfx, set to threshold if played
// //
void A_BuzzFly(mobj_t *actor) void A_BuzzFly(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -8057,8 +7891,7 @@ void A_BuzzFly(mobj_t *actor) ...@@ -8057,8 +7891,7 @@ void A_BuzzFly(mobj_t *actor)
} }
// If the player is over 3072 fracunits away, then look for another player // If the player is over 3072 fracunits away, then look for another player
if (P_AproxDistance(P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y), if (P_AreMobjsFar3D(actor->target, actor, FixedMul(3072*FRACUNIT, actor->scale)))
actor->target->z - actor->z) > FixedMul(3072*FRACUNIT, actor->scale))
{ {
if (multiplayer || netgame) if (multiplayer || netgame)
P_LookForPlayers(actor, true, false, FixedMul(3072*FRACUNIT, actor->scale)); // maybe get a new target P_LookForPlayers(actor, true, false, FixedMul(3072*FRACUNIT, actor->scale)); // maybe get a new target
...@@ -8076,8 +7909,7 @@ void A_BuzzFly(mobj_t *actor) ...@@ -8076,8 +7909,7 @@ void A_BuzzFly(mobj_t *actor)
else else
realspeed = FixedMul(actor->info->speed, actor->scale); realspeed = FixedMul(actor->info->speed, actor->scale);
dist = P_AproxDistance(P_AproxDistance(actor->target->x - actor->x, dist = P_GetMobjDistance3D(actor->target, actor);
actor->target->y - actor->y), actor->target->z - actor->z);
if (dist < 1) if (dist < 1)
dist = 1; dist = 1;
...@@ -8097,7 +7929,7 @@ void A_BuzzFly(mobj_t *actor) ...@@ -8097,7 +7929,7 @@ void A_BuzzFly(mobj_t *actor)
if (locvar1 != sfx_None && !actor->threshold) if (locvar1 != sfx_None && !actor->threshold)
{ {
S_StartSound(actor, locvar1); S_StartSoundFromMobj(actor, locvar1);
actor->threshold = locvar2; actor->threshold = locvar2;
} }
} }
...@@ -8109,8 +7941,9 @@ void A_BuzzFly(mobj_t *actor) ...@@ -8109,8 +7941,9 @@ void A_BuzzFly(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_GuardChase(mobj_t *actor) void A_GuardChase(void *data)
{ {
mobj_t *actor = data;
INT32 delta; INT32 delta;
if (LUA_CallAction(A_GUARDCHASE, actor)) if (LUA_CallAction(A_GUARDCHASE, actor))
...@@ -8212,10 +8045,10 @@ void A_GuardChase(mobj_t *actor) ...@@ -8212,10 +8045,10 @@ void A_GuardChase(mobj_t *actor)
// Now that we've moved, its time for our shield to move! // Now that we've moved, its time for our shield to move!
// Otherwise it'll never act as a proper overlay. // Otherwise it'll never act as a proper overlay.
if (actor->tracer && actor->tracer->state if (actor->tracer && actor->tracer->state
&& actor->tracer->state->action.acp1) && actor->tracer->state->action)
{ {
var1 = actor->tracer->state->var1, var2 = actor->tracer->state->var2; var1 = actor->tracer->state->var1, var2 = actor->tracer->state->var2;
actor->tracer->state->action.acp1(actor->tracer); actor->tracer->state->action(actor->tracer);
} }
} }
...@@ -8226,8 +8059,9 @@ void A_GuardChase(mobj_t *actor) ...@@ -8226,8 +8059,9 @@ void A_GuardChase(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_EggShield(mobj_t *actor) void A_EggShield(void *data)
{ {
mobj_t *actor = data;
INT32 i; INT32 i;
player_t *player; player_t *player;
fixed_t blockdist; fixed_t blockdist;
...@@ -8277,7 +8111,7 @@ void A_EggShield(mobj_t *actor) ...@@ -8277,7 +8111,7 @@ void A_EggShield(mobj_t *actor)
// Search for players to push // Search for players to push
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i] || players[i].spectator) if (!players[i].ingame || players[i].spectator)
continue; continue;
player = &players[i]; player = &players[i];
...@@ -8316,8 +8150,9 @@ void A_EggShield(mobj_t *actor) ...@@ -8316,8 +8150,9 @@ void A_EggShield(mobj_t *actor)
// var1 = 1 (use value in var2); 0 (use info table value) // var1 = 1 (use value in var2); 0 (use info table value)
// var2 = if var1 = 1, then value to set // var2 = if var1 = 1, then value to set
// //
void A_SetReactionTime(mobj_t *actor) void A_SetReactionTime(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_SETREACTIONTIME, actor)) if (LUA_CallAction(A_SETREACTIONTIME, actor))
return; return;
...@@ -8334,8 +8169,9 @@ void A_SetReactionTime(mobj_t *actor) ...@@ -8334,8 +8169,9 @@ void A_SetReactionTime(mobj_t *actor)
// var1 = ball number // var1 = ball number
// var2 = total balls // var2 = total balls
// //
void A_Boss1Spikeballs(mobj_t *actor) void A_Boss1Spikeballs(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
mobj_t *ball; mobj_t *ball;
...@@ -8350,9 +8186,9 @@ void A_Boss1Spikeballs(mobj_t *actor) ...@@ -8350,9 +8186,9 @@ void A_Boss1Spikeballs(mobj_t *actor)
ball->movedir = FixedAngle(FixedMul(FixedDiv(locvar1<<FRACBITS, locvar2<<FRACBITS), 360<<FRACBITS)); ball->movedir = FixedAngle(FixedMul(FixedDiv(locvar1<<FRACBITS, locvar2<<FRACBITS), 360<<FRACBITS));
ball->threshold = ball->radius + actor->radius + ball->info->painchance; ball->threshold = ball->radius + actor->radius + ball->info->painchance;
S_StartSound(ball, ball->info->seesound); S_StartSoundFromMobj(ball, ball->info->seesound);
var1 = ball->state->var1, var2 = ball->state->var2; var1 = ball->state->var1, var2 = ball->state->var2;
ball->state->action.acp1(ball); ball->state->action(ball);
} }
// Function: A_Boss3TakeDamage // Function: A_Boss3TakeDamage
...@@ -8362,8 +8198,9 @@ void A_Boss1Spikeballs(mobj_t *actor) ...@@ -8362,8 +8198,9 @@ void A_Boss1Spikeballs(mobj_t *actor)
// var1 = movecount value // var1 = movecount value
// var2 = unused // var2 = unused
// //
void A_Boss3TakeDamage(mobj_t *actor) void A_Boss3TakeDamage(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_BOSS3TAKEDAMAGE, actor)) if (LUA_CallAction(A_BOSS3TAKEDAMAGE, actor))
return; return;
...@@ -8378,8 +8215,9 @@ void A_Boss3TakeDamage(mobj_t *actor) ...@@ -8378,8 +8215,9 @@ void A_Boss3TakeDamage(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_Boss3Path(mobj_t *actor) void A_Boss3Path(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_BOSS3PATH, actor)) if (LUA_CallAction(A_BOSS3PATH, actor))
return; return;
...@@ -8447,7 +8285,7 @@ void A_Boss3Path(mobj_t *actor) ...@@ -8447,7 +8285,7 @@ void A_Boss3Path(mobj_t *actor)
if (actor->target->x == actor->x && actor->target->y == actor->y) if (actor->target->x == actor->x && actor->target->y == actor->y)
{ {
dist = P_AproxDistance(P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y), actor->target->z + actor->movefactor - actor->z); dist = GetDistance3D(actor->target->x, actor->target->y, actor->target->z + actor->movefactor, actor->x, actor->y, actor->z);
if (dist < 1) if (dist < 1)
dist = 1; dist = 1;
...@@ -8502,8 +8340,9 @@ void A_Boss3Path(mobj_t *actor) ...@@ -8502,8 +8340,9 @@ void A_Boss3Path(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_Boss3ShockThink(mobj_t *actor) void A_Boss3ShockThink(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_BOSS3SHOCKTHINK, actor)) if (LUA_CallAction(A_BOSS3SHOCKTHINK, actor))
return; return;
...@@ -8517,7 +8356,7 @@ void A_Boss3ShockThink(mobj_t *actor) ...@@ -8517,7 +8356,7 @@ void A_Boss3ShockThink(mobj_t *actor)
fixed_t x0, y0, x1, y1; fixed_t x0, y0, x1, y1;
// Break the link if movements are too different // Break the link if movements are too different
if (R_PointToDist2(0, 0, snext->momx - actor->momx, snext->momy - actor->momy) > 12*actor->scale) if (GetDistance2D(actor->momx, actor->momy, snext->momx, snext->momy) > 12*actor->scale)
{ {
P_SetTarget(&actor->hnext, NULL); P_SetTarget(&actor->hnext, NULL);
return; return;
...@@ -8528,7 +8367,7 @@ void A_Boss3ShockThink(mobj_t *actor) ...@@ -8528,7 +8367,7 @@ void A_Boss3ShockThink(mobj_t *actor)
y0 = actor->y; y0 = actor->y;
x1 = snext->x; x1 = snext->x;
y1 = snext->y; y1 = snext->y;
if (R_PointToDist2(0, 0, x1 - x0, y1 - y0) > 2*actor->radius) if (GetDistance2D(x0, y0, x1, y1) > 2*actor->radius)
{ {
snew = P_SpawnMobj((x0 >> 1) + (x1 >> 1), snew = P_SpawnMobj((x0 >> 1) + (x1 >> 1),
(y0 >> 1) + (y1 >> 1), (y0 >> 1) + (y1 >> 1),
...@@ -8560,8 +8399,9 @@ void A_Boss3ShockThink(mobj_t *actor) ...@@ -8560,8 +8399,9 @@ void A_Boss3ShockThink(mobj_t *actor)
// var1 = object spawned // var1 = object spawned
// var2 = amount of objects spawned // var2 = amount of objects spawned
// //
void A_Shockwave(mobj_t *actor) void A_Shockwave(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
INT32 i; INT32 i;
...@@ -8600,7 +8440,7 @@ void A_Shockwave(mobj_t *actor) ...@@ -8600,7 +8440,7 @@ void A_Shockwave(mobj_t *actor)
sprev = shock; sprev = shock;
} }
S_StartSound(actor, shock->info->seesound); S_StartSoundFromMobj(actor, shock->info->seesound);
} }
// Function: A_LinedefExecute // Function: A_LinedefExecute
...@@ -8610,8 +8450,9 @@ void A_Shockwave(mobj_t *actor) ...@@ -8610,8 +8450,9 @@ void A_Shockwave(mobj_t *actor)
// var1 = tag // var1 = tag
// var2 = add angle to tag (optional) // var2 = add angle to tag (optional)
// //
void A_LinedefExecute(mobj_t *actor) void A_LinedefExecute(void *data)
{ {
mobj_t *actor = data;
INT32 tagnum; INT32 tagnum;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -8638,8 +8479,9 @@ void A_LinedefExecute(mobj_t *actor) ...@@ -8638,8 +8479,9 @@ void A_LinedefExecute(mobj_t *actor)
// var1 = mapthing arg to take tag from // var1 = mapthing arg to take tag from
// var2 = unused // var2 = unused
// //
void A_LinedefExecuteFromArg(mobj_t *actor) void A_LinedefExecuteFromArg(void *data)
{ {
mobj_t *actor = data;
INT32 tagnum; INT32 tagnum;
INT32 locvar1 = var1; INT32 locvar1 = var1;
...@@ -8670,8 +8512,9 @@ void A_LinedefExecuteFromArg(mobj_t *actor) ...@@ -8670,8 +8512,9 @@ void A_LinedefExecuteFromArg(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_PlaySeeSound(mobj_t *actor) void A_PlaySeeSound(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_PLAYSEESOUND, actor)) if (LUA_CallAction(A_PLAYSEESOUND, actor))
return; return;
...@@ -8689,8 +8532,9 @@ void A_PlaySeeSound(mobj_t *actor) ...@@ -8689,8 +8532,9 @@ void A_PlaySeeSound(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_PlayAttackSound(mobj_t *actor) void A_PlayAttackSound(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_PLAYATTACKSOUND, actor)) if (LUA_CallAction(A_PLAYATTACKSOUND, actor))
return; return;
...@@ -8705,13 +8549,14 @@ void A_PlayAttackSound(mobj_t *actor) ...@@ -8705,13 +8549,14 @@ void A_PlayAttackSound(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_PlayActiveSound(mobj_t *actor) void A_PlayActiveSound(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_PLAYACTIVESOUND, actor)) if (LUA_CallAction(A_PLAYACTIVESOUND, actor))
return; return;
if (actor->info->activesound) if (actor->info->activesound)
S_StartSound(actor, actor->info->activesound); S_StartSoundFromMobj(actor, actor->info->activesound);
} }
// Function: A_SmokeTrailer // Function: A_SmokeTrailer
...@@ -8721,8 +8566,9 @@ void A_PlayActiveSound(mobj_t *actor) ...@@ -8721,8 +8566,9 @@ void A_PlayActiveSound(mobj_t *actor)
// var1 = object # to spawn as smoke // var1 = object # to spawn as smoke
// var2 = unused // var2 = unused
// //
void A_SmokeTrailer(mobj_t *actor) void A_SmokeTrailer(void *data)
{ {
mobj_t *actor = data;
mobj_t *th; mobj_t *th;
INT32 locvar1 = var1; INT32 locvar1 = var1;
...@@ -8761,8 +8607,9 @@ void A_SmokeTrailer(mobj_t *actor) ...@@ -8761,8 +8607,9 @@ void A_SmokeTrailer(mobj_t *actor)
// var2 >> 16 = z // var2 >> 16 = z
// var2 & 65535 = type // var2 & 65535 = type
// //
void A_SpawnObjectAbsolute(mobj_t *actor) void A_SpawnObjectAbsolute(void *data)
{ {
mobj_t *actor = data;
INT16 x, y, z; // Want to be sure we can use negative values INT16 x, y, z; // Want to be sure we can use negative values
mobjtype_t type; mobjtype_t type;
mobj_t *mo; mobj_t *mo;
...@@ -8799,8 +8646,9 @@ void A_SpawnObjectAbsolute(mobj_t *actor) ...@@ -8799,8 +8646,9 @@ void A_SpawnObjectAbsolute(mobj_t *actor)
// var2 >> 16 = z // var2 >> 16 = z
// var2 & 65535 = type // var2 & 65535 = type
// //
void A_SpawnObjectRelative(mobj_t *actor) void A_SpawnObjectRelative(void *data)
{ {
mobj_t *actor = data;
INT16 x, y, z; // Want to be sure we can use negative values INT16 x, y, z; // Want to be sure we can use negative values
mobjtype_t type; mobjtype_t type;
mobj_t *mo; mobj_t *mo;
...@@ -8840,8 +8688,9 @@ void A_SpawnObjectRelative(mobj_t *actor) ...@@ -8840,8 +8688,9 @@ void A_SpawnObjectRelative(mobj_t *actor)
// var1 = min // var1 = min
// var2 = max // var2 = max
// //
void A_ChangeAngleRelative(mobj_t *actor) void A_ChangeAngleRelative(void *data)
{ {
mobj_t *actor = data;
// Oh god, the old code /sucked/. Changed this and the absolute version to get a random range using amin and amax instead of // Oh god, the old code /sucked/. Changed this and the absolute version to get a random range using amin and amax instead of
// getting a random angle from the _entire_ spectrum and then clipping. While we're at it, do the angle conversion to the result // getting a random angle from the _entire_ spectrum and then clipping. While we're at it, do the angle conversion to the result
// rather than the ranges, so <0 and >360 work as possible values. -Red // rather than the ranges, so <0 and >360 work as possible values. -Red
...@@ -8876,8 +8725,9 @@ void A_ChangeAngleRelative(mobj_t *actor) ...@@ -8876,8 +8725,9 @@ void A_ChangeAngleRelative(mobj_t *actor)
// var1 = min // var1 = min
// var2 = max // var2 = max
// //
void A_ChangeAngleAbsolute(mobj_t *actor) void A_ChangeAngleAbsolute(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
//angle_t angle = (P_RandomByte()+1)<<24; //angle_t angle = (P_RandomByte()+1)<<24;
...@@ -8909,8 +8759,9 @@ void A_ChangeAngleAbsolute(mobj_t *actor) ...@@ -8909,8 +8759,9 @@ void A_ChangeAngleAbsolute(mobj_t *actor)
// var1 = angle // var1 = angle
// var2 = relative? (default) // var2 = relative? (default)
// //
void A_RollAngle(mobj_t *actor) void A_RollAngle(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
const angle_t angle = FixedAngle(locvar1*FRACUNIT); const angle_t angle = FixedAngle(locvar1*FRACUNIT);
...@@ -8933,8 +8784,9 @@ void A_RollAngle(mobj_t *actor) ...@@ -8933,8 +8784,9 @@ void A_RollAngle(mobj_t *actor)
// var1 = min // var1 = min
// var2 = max // var2 = max
// //
void A_ChangeRollAngleRelative(mobj_t *actor) void A_ChangeRollAngleRelative(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
const fixed_t amin = locvar1*FRACUNIT; const fixed_t amin = locvar1*FRACUNIT;
...@@ -8958,8 +8810,9 @@ void A_ChangeRollAngleRelative(mobj_t *actor) ...@@ -8958,8 +8810,9 @@ void A_ChangeRollAngleRelative(mobj_t *actor)
// var1 = min // var1 = min
// var2 = max // var2 = max
// //
void A_ChangeRollAngleAbsolute(mobj_t *actor) void A_ChangeRollAngleAbsolute(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
const fixed_t amin = locvar1*FRACUNIT; const fixed_t amin = locvar1*FRACUNIT;
...@@ -8985,8 +8838,9 @@ void A_ChangeRollAngleAbsolute(mobj_t *actor) ...@@ -8985,8 +8838,9 @@ void A_ChangeRollAngleAbsolute(mobj_t *actor)
// lower 16 bits = If 1, play sound using calling object as origin. If 0, play sound without an origin // lower 16 bits = If 1, play sound using calling object as origin. If 0, play sound without an origin
// upper 16 bits = If 1, do not play sound during preticker. // upper 16 bits = If 1, do not play sound during preticker.
// //
void A_PlaySound(mobj_t *actor) void A_PlaySound(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -8996,7 +8850,7 @@ void A_PlaySound(mobj_t *actor) ...@@ -8996,7 +8850,7 @@ void A_PlaySound(mobj_t *actor)
if (leveltime < 2 && (locvar2 >> 16)) if (leveltime < 2 && (locvar2 >> 16))
return; return;
S_StartSound((locvar2 & 65535) ? actor : NULL, locvar1); S_StartSoundFromMobj((locvar2 & 65535) ? actor : NULL, locvar1);
} }
// Function: A_FindTarget // Function: A_FindTarget
...@@ -9006,14 +8860,15 @@ void A_PlaySound(mobj_t *actor) ...@@ -9006,14 +8860,15 @@ void A_PlaySound(mobj_t *actor)
// var1 = mobj type // var1 = mobj type
// var2 = if (0) nearest; else furthest; // var2 = if (0) nearest; else furthest;
// //
void A_FindTarget(mobj_t *actor) void A_FindTarget(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
mobj_t *targetedmobj = NULL; mobj_t *targetedmobj = NULL;
thinker_t *th; thinker_t *th;
mobj_t *mo2; mobj_t *mo2;
fixed_t dist1 = 0, dist2 = 0; INT32 dist = 0, bestdist = 0;
if (LUA_CallAction(A_FINDTARGET, actor)) if (LUA_CallAction(A_FINDTARGET, actor))
return; return;
...@@ -9023,7 +8878,7 @@ void A_FindTarget(mobj_t *actor) ...@@ -9023,7 +8878,7 @@ void A_FindTarget(mobj_t *actor)
// scan the thinkers // scan the thinkers
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) 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; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -9037,16 +8892,16 @@ void A_FindTarget(mobj_t *actor) ...@@ -9037,16 +8892,16 @@ void A_FindTarget(mobj_t *actor)
if (targetedmobj == NULL) if (targetedmobj == NULL)
{ {
targetedmobj = mo2; targetedmobj = mo2;
dist2 = R_PointToDist2(actor->x, actor->y, mo2->x, mo2->y); bestdist = P_GetMobjLargeDistance2D(actor, mo2);
} }
else else
{ {
dist1 = R_PointToDist2(actor->x, actor->y, mo2->x, mo2->y); dist = P_GetMobjLargeDistance2D(actor, mo2);
if ((!locvar2 && dist1 < dist2) || (locvar2 && dist1 > dist2)) if ((!locvar2 && dist < bestdist) || (locvar2 && dist > bestdist))
{ {
targetedmobj = mo2; targetedmobj = mo2;
dist2 = dist1; bestdist = dist;
} }
} }
} }
...@@ -9070,14 +8925,15 @@ void A_FindTarget(mobj_t *actor) ...@@ -9070,14 +8925,15 @@ void A_FindTarget(mobj_t *actor)
// var1 = mobj type // var1 = mobj type
// var2 = if (0) nearest; else furthest; // var2 = if (0) nearest; else furthest;
// //
void A_FindTracer(mobj_t *actor) void A_FindTracer(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
mobj_t *targetedmobj = NULL; mobj_t *targetedmobj = NULL;
thinker_t *th; thinker_t *th;
mobj_t *mo2; mobj_t *mo2;
fixed_t dist1 = 0, dist2 = 0; INT32 dist = 0, bestdist = 0;
if (LUA_CallAction(A_FINDTRACER, actor)) if (LUA_CallAction(A_FINDTRACER, actor))
return; return;
...@@ -9087,7 +8943,7 @@ void A_FindTracer(mobj_t *actor) ...@@ -9087,7 +8943,7 @@ void A_FindTracer(mobj_t *actor)
// scan the thinkers // scan the thinkers
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) 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; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -9101,16 +8957,16 @@ void A_FindTracer(mobj_t *actor) ...@@ -9101,16 +8957,16 @@ void A_FindTracer(mobj_t *actor)
if (targetedmobj == NULL) if (targetedmobj == NULL)
{ {
targetedmobj = mo2; targetedmobj = mo2;
dist2 = R_PointToDist2(actor->x, actor->y, mo2->x, mo2->y); bestdist = P_GetMobjLargeDistance2D(actor, mo2);
} }
else else
{ {
dist1 = R_PointToDist2(actor->x, actor->y, mo2->x, mo2->y); dist = P_GetMobjLargeDistance2D(actor, mo2);
if ((!locvar2 && dist1 < dist2) || (locvar2 && dist1 > dist2)) if ((!locvar2 && dist < bestdist) || (locvar2 && dist > bestdist))
{ {
targetedmobj = mo2; targetedmobj = mo2;
dist2 = dist1; bestdist = dist;
} }
} }
} }
...@@ -9134,8 +8990,9 @@ void A_FindTracer(mobj_t *actor) ...@@ -9134,8 +8990,9 @@ void A_FindTracer(mobj_t *actor)
// var1 = tics to set to // var1 = tics to set to
// var2 = if this is set, and no var1 is supplied, the mobj's threshold value will be used. // var2 = if this is set, and no var1 is supplied, the mobj's threshold value will be used.
// //
void A_SetTics(mobj_t *actor) void A_SetTics(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -9155,8 +9012,9 @@ void A_SetTics(mobj_t *actor) ...@@ -9155,8 +9012,9 @@ void A_SetTics(mobj_t *actor)
// var1 = lower bound // var1 = lower bound
// var2 = upper bound // var2 = upper bound
// //
void A_SetRandomTics(mobj_t *actor) void A_SetRandomTics(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -9173,8 +9031,9 @@ void A_SetRandomTics(mobj_t *actor) ...@@ -9173,8 +9031,9 @@ void A_SetRandomTics(mobj_t *actor)
// var1 = if (var1 > 0), find target and add its color value to yours // var1 = if (var1 > 0), find target and add its color value to yours
// var2 = if (var1 = 0), color value to add // var2 = if (var1 = 0), color value to add
// //
void A_ChangeColorRelative(mobj_t *actor) void A_ChangeColorRelative(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -9198,8 +9057,9 @@ void A_ChangeColorRelative(mobj_t *actor) ...@@ -9198,8 +9057,9 @@ void A_ChangeColorRelative(mobj_t *actor)
// var1 = if (var1 > 0), set your color to your target's color // var1 = if (var1 > 0), set your color to your target's color
// var2 = if (var1 = 0), color value to set to // var2 = if (var1 = 0), color value to set to
// //
void A_ChangeColorAbsolute(mobj_t *actor) void A_ChangeColorAbsolute(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -9222,8 +9082,9 @@ void A_ChangeColorAbsolute(mobj_t *actor) ...@@ -9222,8 +9082,9 @@ void A_ChangeColorAbsolute(mobj_t *actor)
// var1 = if (var1 != 0), dye your target instead of yourself // var1 = if (var1 != 0), dye your target instead of yourself
// var2 = color value to dye // var2 = color value to dye
// //
void A_Dye(mobj_t *actor) void A_Dye(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -9257,8 +9118,9 @@ void A_Dye(mobj_t *actor) ...@@ -9257,8 +9118,9 @@ void A_Dye(mobj_t *actor)
// var1 = translation ID // var1 = translation ID
// var2 = unused // var2 = unused
// //
void A_SetTranslation(mobj_t *actor) void A_SetTranslation(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
if (LUA_CallAction(A_SETTRANSLATION, actor)) if (LUA_CallAction(A_SETTRANSLATION, actor))
...@@ -9277,8 +9139,9 @@ void A_SetTranslation(mobj_t *actor) ...@@ -9277,8 +9139,9 @@ void A_SetTranslation(mobj_t *actor)
// var1 = angle // var1 = angle
// var2 = force // var2 = force
// //
void A_MoveRelative(mobj_t *actor) void A_MoveRelative(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -9295,8 +9158,9 @@ void A_MoveRelative(mobj_t *actor) ...@@ -9295,8 +9158,9 @@ void A_MoveRelative(mobj_t *actor)
// var1 = angle // var1 = angle
// var2 = force // var2 = force
// //
void A_MoveAbsolute(mobj_t *actor) void A_MoveAbsolute(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -9313,8 +9177,9 @@ void A_MoveAbsolute(mobj_t *actor) ...@@ -9313,8 +9177,9 @@ void A_MoveAbsolute(mobj_t *actor)
// var1 = amount of force // var1 = amount of force
// var2 = If 1, xy momentum is lost. If 0, xy momentum is kept // var2 = If 1, xy momentum is lost. If 0, xy momentum is kept
// //
void A_Thrust(mobj_t *actor) void A_Thrust(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -9339,8 +9204,9 @@ void A_Thrust(mobj_t *actor) ...@@ -9339,8 +9204,9 @@ void A_Thrust(mobj_t *actor)
// lower 16 bits = If 1, xy momentum is lost. If 0, xy momentum is kept // lower 16 bits = If 1, xy momentum is lost. If 0, xy momentum is kept
// upper 16 bits = If 1, z momentum is lost. If 0, z momentum is kept // upper 16 bits = If 1, z momentum is lost. If 0, z momentum is kept
// //
void A_ZThrust(mobj_t *actor) void A_ZThrust(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -9372,8 +9238,9 @@ void A_ZThrust(mobj_t *actor) ...@@ -9372,8 +9238,9 @@ void A_ZThrust(mobj_t *actor)
// 0 = target/tracer's target // 0 = target/tracer's target
// 1 = target/tracer's tracer // 1 = target/tracer's tracer
// //
void A_SetTargetsTarget(mobj_t *actor) void A_SetTargetsTarget(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
mobj_t *oldtarg = NULL, *newtarg = NULL; mobj_t *oldtarg = NULL, *newtarg = NULL;
...@@ -9416,8 +9283,9 @@ void A_SetTargetsTarget(mobj_t *actor) ...@@ -9416,8 +9283,9 @@ void A_SetTargetsTarget(mobj_t *actor)
// else if var2 == 1, remove the flag from the current flags // else if var2 == 1, remove the flag from the current flags
// else if var2 == 0, set the flags to the exact value // else if var2 == 0, set the flags to the exact value
// //
void A_SetObjectFlags(mobj_t *actor) void A_SetObjectFlags(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
boolean unlinkthings = false; boolean unlinkthings = false;
...@@ -9433,7 +9301,8 @@ void A_SetObjectFlags(mobj_t *actor) ...@@ -9433,7 +9301,8 @@ void A_SetObjectFlags(mobj_t *actor)
if ((UINT32)(locvar1 & (MF_NOBLOCKMAP|MF_NOSECTOR)) != (actor->flags & (MF_NOBLOCKMAP|MF_NOSECTOR))) // Blockmap/sector status has changed, so reset the links if ((UINT32)(locvar1 & (MF_NOBLOCKMAP|MF_NOSECTOR)) != (actor->flags & (MF_NOBLOCKMAP|MF_NOSECTOR))) // Blockmap/sector status has changed, so reset the links
unlinkthings = true; unlinkthings = true;
if (unlinkthings) { if (unlinkthings)
{
P_UnsetThingPosition(actor); P_UnsetThingPosition(actor);
if (sector_list) if (sector_list)
{ {
...@@ -9458,8 +9327,9 @@ void A_SetObjectFlags(mobj_t *actor) ...@@ -9458,8 +9327,9 @@ void A_SetObjectFlags(mobj_t *actor)
// else if var2 == 1, remove the flag from the current flags // else if var2 == 1, remove the flag from the current flags
// else if var2 == 0, set the flags to the exact value // else if var2 == 0, set the flags to the exact value
// //
void A_SetObjectFlags2(mobj_t *actor) void A_SetObjectFlags2(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -9485,8 +9355,9 @@ void A_SetObjectFlags2(mobj_t *actor) ...@@ -9485,8 +9355,9 @@ void A_SetObjectFlags2(mobj_t *actor)
// 3 - Boss 4 jet flame // 3 - Boss 4 jet flame
// var2 = unused // var2 = unused
// //
void A_BossJetFume(mobj_t *actor) void A_BossJetFume(void *data)
{ {
mobj_t *actor = data;
mobj_t *filler; mobj_t *filler;
INT32 locvar1 = var1; INT32 locvar1 = var1;
...@@ -9633,8 +9504,9 @@ void A_BossJetFume(mobj_t *actor) ...@@ -9633,8 +9504,9 @@ void A_BossJetFume(mobj_t *actor)
// var1 = state number 1 // var1 = state number 1
// var2 = state number 2 // var2 = state number 2
// //
void A_RandomState(mobj_t *actor) void A_RandomState(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -9651,8 +9523,9 @@ void A_RandomState(mobj_t *actor) ...@@ -9651,8 +9523,9 @@ void A_RandomState(mobj_t *actor)
// var1 = Minimum state number to choose. // var1 = Minimum state number to choose.
// var2 = Maximum state number to use. // var2 = Maximum state number to use.
// //
void A_RandomStateRange(mobj_t *actor) void A_RandomStateRange(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -9669,8 +9542,9 @@ void A_RandomStateRange(mobj_t *actor) ...@@ -9669,8 +9542,9 @@ void A_RandomStateRange(mobj_t *actor)
// var1 = Minimum state number to use. // var1 = Minimum state number to use.
// var2 = Maximum state number to use. The difference will act as a modulo operator. // var2 = Maximum state number to use. The difference will act as a modulo operator.
// //
void A_StateRangeByAngle(mobj_t *actor) void A_StateRangeByAngle(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -9690,8 +9564,9 @@ void A_StateRangeByAngle(mobj_t *actor) ...@@ -9690,8 +9564,9 @@ void A_StateRangeByAngle(mobj_t *actor)
// var1 = Minimum state number to use. // var1 = Minimum state number to use.
// var2 = Maximum state number to use. The difference will act as a modulo operator. // var2 = Maximum state number to use. The difference will act as a modulo operator.
// //
void A_StateRangeByParameter(mobj_t *actor) void A_StateRangeByParameter(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
UINT8 parameter = (actor->spawnpoint ? actor->spawnpoint->extrainfo : 0); UINT8 parameter = (actor->spawnpoint ? actor->spawnpoint->extrainfo : 0);
...@@ -9712,8 +9587,9 @@ void A_StateRangeByParameter(mobj_t *actor) ...@@ -9712,8 +9587,9 @@ void A_StateRangeByParameter(mobj_t *actor)
// var1 = state # to use 1st action from // var1 = state # to use 1st action from
// var2 = state # to use 2nd action from // var2 = state # to use 2nd action from
// //
void A_DualAction(mobj_t *actor) void A_DualAction(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -9727,14 +9603,14 @@ void A_DualAction(mobj_t *actor) ...@@ -9727,14 +9603,14 @@ void A_DualAction(mobj_t *actor)
astate = &states[locvar1]; astate = &states[locvar1];
CONS_Debug(DBG_GAMELOGIC, "A_DualAction: Calling First Action (state %d)...\n", locvar1); CONS_Debug(DBG_GAMELOGIC, "A_DualAction: Calling First Action (state %d)...\n", locvar1);
states[locvar1].action.acp1(actor); states[locvar1].action(actor);
var1 = states[locvar2].var1; var1 = states[locvar2].var1;
var2 = states[locvar2].var2; var2 = states[locvar2].var2;
astate = &states[locvar2]; astate = &states[locvar2];
CONS_Debug(DBG_GAMELOGIC, "A_DualAction: Calling Second Action (state %d)...\n", locvar2); CONS_Debug(DBG_GAMELOGIC, "A_DualAction: Calling Second Action (state %d)...\n", locvar2);
states[locvar2].action.acp1(actor); states[locvar2].action(actor);
} }
// Function: A_RemoteAction // Function: A_RemoteAction
...@@ -9744,8 +9620,9 @@ void A_DualAction(mobj_t *actor) ...@@ -9744,8 +9620,9 @@ void A_DualAction(mobj_t *actor)
// var1 = remote object (-2 uses tracer, -1 uses target) // var1 = remote object (-2 uses tracer, -1 uses target)
// var2 = state reference for calling an action // var2 = state reference for calling an action
// //
void A_RemoteAction(mobj_t *actor) void A_RemoteAction(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
mobj_t *originaltarget = actor->target; // Hold on to the target for later. mobj_t *originaltarget = actor->target; // Hold on to the target for later.
...@@ -9760,12 +9637,12 @@ void A_RemoteAction(mobj_t *actor) ...@@ -9760,12 +9637,12 @@ void A_RemoteAction(mobj_t *actor)
mobj_t *targetedmobj = NULL; mobj_t *targetedmobj = NULL;
thinker_t *th; thinker_t *th;
mobj_t *mo2; mobj_t *mo2;
fixed_t dist1 = 0, dist2 = 0; INT32 dist = 0, bestdist = 0;
// scan the thinkers // scan the thinkers
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) 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; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -9775,16 +9652,16 @@ void A_RemoteAction(mobj_t *actor) ...@@ -9775,16 +9652,16 @@ void A_RemoteAction(mobj_t *actor)
if (targetedmobj == NULL) if (targetedmobj == NULL)
{ {
targetedmobj = mo2; targetedmobj = mo2;
dist2 = R_PointToDist2(actor->x, actor->y, mo2->x, mo2->y); bestdist = P_GetMobjLargeDistance2D(actor, mo2);
} }
else else
{ {
dist1 = R_PointToDist2(actor->x, actor->y, mo2->x, mo2->y); dist = P_GetMobjLargeDistance2D(actor, mo2);
if ((locvar2 && dist1 < dist2) || (!locvar2 && dist1 > dist2)) if ((locvar2 && dist < bestdist) || (!locvar2 && dist > bestdist))
{ {
targetedmobj = mo2; targetedmobj = mo2;
dist2 = dist1; bestdist = dist;
} }
} }
} }
...@@ -9817,7 +9694,7 @@ void A_RemoteAction(mobj_t *actor) ...@@ -9817,7 +9694,7 @@ void A_RemoteAction(mobj_t *actor)
CONS_Debug(DBG_GAMELOGIC, "A_RemoteAction: Calling action on %p\n" CONS_Debug(DBG_GAMELOGIC, "A_RemoteAction: Calling action on %p\n"
"var1 is %d\nvar2 is %d\n", actor->target, var1, var2); "var1 is %d\nvar2 is %d\n", actor->target, var1, var2);
states[locvar2].action.acp1(actor->target); states[locvar2].action(actor->target);
} }
P_SetTarget(&actor->target, originaltarget); // Restore the original target. P_SetTarget(&actor->target, originaltarget); // Restore the original target.
...@@ -9830,8 +9707,9 @@ void A_RemoteAction(mobj_t *actor) ...@@ -9830,8 +9707,9 @@ void A_RemoteAction(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_ToggleFlameJet(mobj_t* actor) void A_ToggleFlameJet(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_TOGGLEFLAMEJET, actor)) if (LUA_CallAction(A_TOGGLEFLAMEJET, actor))
return; return;
...@@ -9873,8 +9751,9 @@ void A_ToggleFlameJet(mobj_t* actor) ...@@ -9873,8 +9751,9 @@ void A_ToggleFlameJet(mobj_t* actor)
// Bits 1-10: X factor // Bits 1-10: X factor
// Bits 11-20: Y factor // Bits 11-20: Y factor
// Bits 21-30: Z factor // Bits 21-30: Z factor
void A_OrbitNights(mobj_t* actor) void A_OrbitNights(void *data)
{ {
mobj_t *actor = data;
INT32 ofs = (var2 & 0x3FF); INT32 ofs = (var2 & 0x3FF);
boolean ishelper = (var2 & 0x10000); boolean ishelper = (var2 & 0x10000);
boolean donotrescale = (var2 & 0x40000); boolean donotrescale = (var2 & 0x40000);
...@@ -9951,8 +9830,9 @@ void A_OrbitNights(mobj_t* actor) ...@@ -9951,8 +9830,9 @@ void A_OrbitNights(mobj_t* actor)
// var1 = duration in tics // var1 = duration in tics
// var2 = unused // var2 = unused
// //
void A_GhostMe(mobj_t *actor) void A_GhostMe(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
mobj_t *ghost; mobj_t *ghost;
...@@ -9973,8 +9853,9 @@ void A_GhostMe(mobj_t *actor) ...@@ -9973,8 +9853,9 @@ void A_GhostMe(mobj_t *actor)
// 0 = target // 0 = target
// 1 = tracer // 1 = tracer
// //
void A_SetObjectState(mobj_t *actor) void A_SetObjectState(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
mobj_t *target; mobj_t *target;
...@@ -10012,8 +9893,9 @@ void A_SetObjectState(mobj_t *actor) ...@@ -10012,8 +9893,9 @@ void A_SetObjectState(mobj_t *actor)
// lower 16 bits = type // lower 16 bits = type
// upper 16 bits = range (if == 0, across whole map) // upper 16 bits = range (if == 0, across whole map)
// //
void A_SetObjectTypeState(mobj_t *actor) void A_SetObjectTypeState(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
const UINT16 loc2lw = (UINT16)(locvar2 & 65535); const UINT16 loc2lw = (UINT16)(locvar2 & 65535);
...@@ -10021,29 +9903,26 @@ void A_SetObjectTypeState(mobj_t *actor) ...@@ -10021,29 +9903,26 @@ void A_SetObjectTypeState(mobj_t *actor)
thinker_t *th; thinker_t *th;
mobj_t *mo2; mobj_t *mo2;
fixed_t dist = 0;
if (LUA_CallAction(A_SETOBJECTTYPESTATE, actor)) if (LUA_CallAction(A_SETOBJECTTYPESTATE, actor))
return; return;
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) 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; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == (mobjtype_t)loc2lw) if (mo2->type == (mobjtype_t)loc2lw)
{ {
dist = P_AproxDistance(mo2->x - actor->x, mo2->y - actor->y);
if (mo2->health > 0) if (mo2->health > 0)
{ {
if (loc2up == 0) if (loc2up == 0)
P_SetMobjState(mo2, locvar1); P_SetMobjState(mo2, locvar1);
else else
{ {
if (dist <= FixedMul(loc2up*FRACUNIT, actor->scale)) if (P_AreMobjsClose2D(mo2, actor, FixedMul(loc2up*FRACUNIT, actor->scale)))
P_SetMobjState(mo2, locvar1); P_SetMobjState(mo2, locvar1);
} }
} }
...@@ -10060,8 +9939,9 @@ void A_SetObjectTypeState(mobj_t *actor) ...@@ -10060,8 +9939,9 @@ void A_SetObjectTypeState(mobj_t *actor)
// 1 = tracer // 1 = tracer
// var2 = unused // var2 = unused
// //
void A_KnockBack(mobj_t *actor) void A_KnockBack(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
mobj_t *target; mobj_t *target;
...@@ -10093,8 +9973,9 @@ void A_KnockBack(mobj_t *actor) ...@@ -10093,8 +9973,9 @@ void A_KnockBack(mobj_t *actor)
// lower 16 bits = If 1, xy momentum is lost. If 0, xy momentum is kept // lower 16 bits = If 1, xy momentum is lost. If 0, xy momentum is kept
// upper 16 bits = 0 - target, 1 - tracer // upper 16 bits = 0 - target, 1 - tracer
// //
void A_PushAway(mobj_t *actor) void A_PushAway(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
mobj_t *target; // target mobj_t *target; // target
...@@ -10129,8 +10010,9 @@ void A_PushAway(mobj_t *actor) ...@@ -10129,8 +10010,9 @@ void A_PushAway(mobj_t *actor)
// var1 = ammount of drained rings // var1 = ammount of drained rings
// var2 = unused // var2 = unused
// //
void A_RingDrain(mobj_t *actor) void A_RingDrain(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
player_t *player; player_t *player;
...@@ -10157,8 +10039,9 @@ void A_RingDrain(mobj_t *actor) ...@@ -10157,8 +10039,9 @@ void A_RingDrain(mobj_t *actor)
// lower 16 bits = missile type // lower 16 bits = missile type
// upper 16 bits = height offset // upper 16 bits = height offset
// //
void A_SplitShot(mobj_t *actor) void A_SplitShot(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
const UINT16 loc2lw = (UINT16)(locvar2 & 65535); const UINT16 loc2lw = (UINT16)(locvar2 & 65535);
...@@ -10200,8 +10083,9 @@ void A_SplitShot(mobj_t *actor) ...@@ -10200,8 +10083,9 @@ void A_SplitShot(mobj_t *actor)
// var1 = splitting missile type // var1 = splitting missile type
// var2 = splitting angle // var2 = splitting angle
// //
void A_MissileSplit(mobj_t *actor) void A_MissileSplit(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -10223,8 +10107,9 @@ void A_MissileSplit(mobj_t *actor) ...@@ -10223,8 +10107,9 @@ void A_MissileSplit(mobj_t *actor)
// upper 16 bits = missile type # // upper 16 bits = missile type #
// var2 = height offset // var2 = height offset
// //
void A_MultiShot(mobj_t *actor) void A_MultiShot(void *data)
{ {
mobj_t *actor = data;
fixed_t z, xr, yr; fixed_t z, xr, yr;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -10286,8 +10171,9 @@ void A_MultiShot(mobj_t *actor) ...@@ -10286,8 +10171,9 @@ void A_MultiShot(mobj_t *actor)
// upper 16 bits = maximum step # // upper 16 bits = maximum step #
// var2 = force // var2 = force
// //
void A_InstaLoop(mobj_t *actor) void A_InstaLoop(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
fixed_t force = max(locvar2, 1)*FRACUNIT; // defaults to 1 if var2 < 1 fixed_t force = max(locvar2, 1)*FRACUNIT; // defaults to 1 if var2 < 1
...@@ -10315,8 +10201,9 @@ void A_InstaLoop(mobj_t *actor) ...@@ -10315,8 +10201,9 @@ void A_InstaLoop(mobj_t *actor)
// lower 16 bits = vertical rotation speed in 1/10 fracunits per tic // lower 16 bits = vertical rotation speed in 1/10 fracunits per tic
// upper 16 bits = horizontal rotation speed in 1/10 fracunits per tic // upper 16 bits = horizontal rotation speed in 1/10 fracunits per tic
// //
void A_Custom3DRotate(mobj_t *actor) void A_Custom3DRotate(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -10385,8 +10272,9 @@ void A_Custom3DRotate(mobj_t *actor) ...@@ -10385,8 +10272,9 @@ void A_Custom3DRotate(mobj_t *actor)
// else, do not call a specific state if no players are available // else, do not call a specific state if no players are available
// var2 = state number // var2 = state number
// //
void A_SearchForPlayers(mobj_t *actor) void A_SearchForPlayers(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -10416,8 +10304,9 @@ void A_SearchForPlayers(mobj_t *actor) ...@@ -10416,8 +10304,9 @@ void A_SearchForPlayers(mobj_t *actor)
// upper 16 bits = numerator (defaults to 1 if zero) // upper 16 bits = numerator (defaults to 1 if zero)
// var2 = state number // var2 = state number
// //
void A_CheckRandom(mobj_t *actor) void A_CheckRandom(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
fixed_t chance = FRACUNIT; fixed_t chance = FRACUNIT;
...@@ -10444,8 +10333,9 @@ void A_CheckRandom(mobj_t *actor) ...@@ -10444,8 +10333,9 @@ void A_CheckRandom(mobj_t *actor)
// var1 = if player rings >= var1 call state // var1 = if player rings >= var1 call state
// var2 = state number // var2 = state number
// //
void A_CheckTargetRings(mobj_t *actor) void A_CheckTargetRings(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -10466,8 +10356,9 @@ void A_CheckTargetRings(mobj_t *actor) ...@@ -10466,8 +10356,9 @@ void A_CheckTargetRings(mobj_t *actor)
// var1 = if player rings >= var1 call state // var1 = if player rings >= var1 call state
// var2 = state number // var2 = state number
// //
void A_CheckRings(mobj_t *actor) void A_CheckRings(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
INT32 i, cntr = 0; INT32 i, cntr = 0;
...@@ -10489,8 +10380,9 @@ void A_CheckRings(mobj_t *actor) ...@@ -10489,8 +10380,9 @@ void A_CheckRings(mobj_t *actor)
// var1 = if total player rings >= var1 call state // var1 = if total player rings >= var1 call state
// var2 = state number // var2 = state number
// //
void A_CheckTotalRings(mobj_t *actor) void A_CheckTotalRings(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -10513,8 +10405,9 @@ void A_CheckTotalRings(mobj_t *actor) ...@@ -10513,8 +10405,9 @@ void A_CheckTotalRings(mobj_t *actor)
// var1 = if health <= var1 call state // var1 = if health <= var1 call state
// var2 = state number // var2 = state number
// //
void A_CheckHealth(mobj_t *actor) void A_CheckHealth(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -10534,24 +10427,20 @@ void A_CheckHealth(mobj_t *actor) ...@@ -10534,24 +10427,20 @@ void A_CheckHealth(mobj_t *actor)
// upper 16 bits = 0 - target, 1 - tracer // upper 16 bits = 0 - target, 1 - tracer
// var2 = state number // var2 = state number
// //
void A_CheckRange(mobj_t *actor) void A_CheckRange(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
fixed_t dist; mobj_t *target = (locvar1 >> 16) ? actor->tracer : actor->target;
if (LUA_CallAction(A_CHECKRANGE, actor)) if (LUA_CallAction(A_CHECKRANGE, actor))
return; return;
if ((!(locvar1 >> 16) && !actor->target) || ((locvar1 >> 16) && !actor->tracer)) if (!target)
return; return;
if (!(locvar1 >> 16)) //target if (P_AreMobjsClose2D(target, actor, FixedMul((locvar1 & 65535)*FRACUNIT, actor->scale)))
dist = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y);
else //tracer
dist = P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y);
if (dist <= FixedMul((locvar1 & 65535)*FRACUNIT, actor->scale))
P_SetMobjState(actor, locvar2); P_SetMobjState(actor, locvar2);
} }
...@@ -10564,8 +10453,9 @@ void A_CheckRange(mobj_t *actor) ...@@ -10564,8 +10453,9 @@ void A_CheckRange(mobj_t *actor)
// upper 16 bits = 0 - target, 1 - tracer // upper 16 bits = 0 - target, 1 - tracer
// var2 = state number // var2 = state number
// //
void A_CheckHeight(mobj_t *actor) void A_CheckHeight(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
fixed_t height; fixed_t height;
...@@ -10594,37 +10484,21 @@ void A_CheckHeight(mobj_t *actor) ...@@ -10594,37 +10484,21 @@ void A_CheckHeight(mobj_t *actor)
// upper 16 bits = 0 - target, 1 - tracer // upper 16 bits = 0 - target, 1 - tracer
// var2 = state number // var2 = state number
// //
void A_CheckTrueRange(mobj_t *actor) void A_CheckTrueRange(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
fixed_t height; // vertical range mobj_t *target = (locvar1 >> 16) ? actor->tracer : actor->target;
fixed_t dist; // horizontal range
fixed_t l; // true range
if (LUA_CallAction(A_CHECKTRUERANGE, actor)) if (LUA_CallAction(A_CHECKTRUERANGE, actor))
return; return;
if ((!(locvar1 >> 16) && !actor->target) || ((locvar1 >> 16) && !actor->tracer)) if (!target)
return; return;
if (!(locvar1 >> 16)) // target if (P_AreMobjsClose3D(target, actor, FixedMul((locvar1 & 65535) * FRACUNIT, actor->scale)))
{
height = actor->target->z - actor->z;
dist = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y);
}
else // tracer
{
height = actor->tracer->z - actor->z;
dist = P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y);
}
l = P_AproxDistance(dist, height);
if (l <= FixedMul((locvar1 & 65535)*FRACUNIT, actor->scale))
P_SetMobjState(actor, locvar2); P_SetMobjState(actor, locvar2);
} }
// Function: A_CheckThingCount // Function: A_CheckThingCount
...@@ -10638,8 +10512,9 @@ void A_CheckTrueRange(mobj_t *actor) ...@@ -10638,8 +10512,9 @@ void A_CheckTrueRange(mobj_t *actor)
// lower 16 bits = state to call // lower 16 bits = state to call
// upper 16 bits = range (if == 0, check whole map) // upper 16 bits = range (if == 0, check whole map)
// //
void A_CheckThingCount(mobj_t *actor) void A_CheckThingCount(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -10651,27 +10526,24 @@ void A_CheckThingCount(mobj_t *actor) ...@@ -10651,27 +10526,24 @@ void A_CheckThingCount(mobj_t *actor)
INT32 count = 0; INT32 count = 0;
thinker_t *th; thinker_t *th;
mobj_t *mo2; mobj_t *mo2;
fixed_t dist = 0;
if (LUA_CallAction(A_CHECKTHINGCOUNT, actor)) if (LUA_CallAction(A_CHECKTHINGCOUNT, actor))
return; return;
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) 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; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == (mobjtype_t)loc1up) if (mo2->type == (mobjtype_t)loc1up)
{ {
dist = P_AproxDistance(mo2->x - actor->x, mo2->y - actor->y);
if (loc2up == 0) if (loc2up == 0)
count++; count++;
else else
{ {
if (dist <= FixedMul(loc2up*FRACUNIT, actor->scale)) if (P_AreMobjsClose2D(mo2, actor, FixedMul(loc2up*FRACUNIT, actor->scale)))
count++; count++;
} }
} }
...@@ -10690,8 +10562,9 @@ void A_CheckThingCount(mobj_t *actor) ...@@ -10690,8 +10562,9 @@ void A_CheckThingCount(mobj_t *actor)
// 1 = tracer // 1 = tracer
// var2 = state number // var2 = state number
// //
void A_CheckAmbush(mobj_t *actor) void A_CheckAmbush(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
angle_t at; // angle target is currently facing angle_t at; // angle target is currently facing
...@@ -10731,8 +10604,9 @@ void A_CheckAmbush(mobj_t *actor) ...@@ -10731,8 +10604,9 @@ void A_CheckAmbush(mobj_t *actor)
// var1 = if custom value >= var1, call state // var1 = if custom value >= var1, call state
// var2 = state number // var2 = state number
// //
void A_CheckCustomValue(mobj_t *actor) void A_CheckCustomValue(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -10750,8 +10624,9 @@ void A_CheckCustomValue(mobj_t *actor) ...@@ -10750,8 +10624,9 @@ void A_CheckCustomValue(mobj_t *actor)
// var1 = if memory value >= var1, call state // var1 = if memory value >= var1, call state
// var2 = state number // var2 = state number
// //
void A_CheckCusValMemo(mobj_t *actor) void A_CheckCusValMemo(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -10775,8 +10650,9 @@ void A_CheckCusValMemo(mobj_t *actor) ...@@ -10775,8 +10650,9 @@ void A_CheckCusValMemo(mobj_t *actor)
// else if var2 == 1, substract var1 from the custom value // else if var2 == 1, substract var1 from the custom value
// else if var2 == 0, replace the custom value with var1 // else if var2 == 0, replace the custom value with var1
// //
void A_SetCustomValue(mobj_t *actor) void A_SetCustomValue(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -10822,8 +10698,9 @@ void A_SetCustomValue(mobj_t *actor) ...@@ -10822,8 +10698,9 @@ void A_SetCustomValue(mobj_t *actor)
// else if var2 == 1, mem -= cv || cv -= mem // else if var2 == 1, mem -= cv || cv -= mem
// else mem = cv || cv = mem // else mem = cv || cv = mem
// //
void A_UseCusValMemo(mobj_t *actor) void A_UseCusValMemo(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -10885,8 +10762,9 @@ void A_UseCusValMemo(mobj_t *actor) ...@@ -10885,8 +10762,9 @@ void A_UseCusValMemo(mobj_t *actor)
// else if var2 == 1, substract var1 from the target's custom value // else if var2 == 1, substract var1 from the target's custom value
// else if var2 == 0, replace the target's custom value with var1 // else if var2 == 0, replace the target's custom value with var1
// //
void A_RelayCustomValue(mobj_t *actor) void A_RelayCustomValue(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -10947,8 +10825,9 @@ void A_RelayCustomValue(mobj_t *actor) ...@@ -10947,8 +10825,9 @@ void A_RelayCustomValue(mobj_t *actor)
// else if var2 == 1, only replace new action's var2 with custom value // else if var2 == 1, only replace new action's var2 with custom value
// else if var2 == 0, only replace new action's var1 with custom value // else if var2 == 0, only replace new action's var1 with custom value
// //
void A_CusValAction(mobj_t *actor) void A_CusValAction(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -10987,7 +10866,7 @@ void A_CusValAction(mobj_t *actor) ...@@ -10987,7 +10866,7 @@ void A_CusValAction(mobj_t *actor)
} }
astate = &states[locvar1]; astate = &states[locvar1];
states[locvar1].action.acp1(actor); states[locvar1].action(actor);
} }
// Function: A_ForceStop // Function: A_ForceStop
...@@ -10999,8 +10878,9 @@ void A_CusValAction(mobj_t *actor) ...@@ -10999,8 +10878,9 @@ void A_CusValAction(mobj_t *actor)
// else, stop x-y-movement only // else, stop x-y-movement only
// var2 = unused // var2 = unused
// //
void A_ForceStop(mobj_t *actor) void A_ForceStop(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
if (LUA_CallAction(A_FORCESTOP, actor)) if (LUA_CallAction(A_FORCESTOP, actor))
...@@ -11018,8 +10898,9 @@ void A_ForceStop(mobj_t *actor) ...@@ -11018,8 +10898,9 @@ void A_ForceStop(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_ForceWin(mobj_t *actor) void A_ForceWin(void *data)
{ {
mobj_t *actor = data;
INT32 i; INT32 i;
if (LUA_CallAction(A_FORCEWIN, actor)) if (LUA_CallAction(A_FORCEWIN, actor))
...@@ -11027,7 +10908,7 @@ void A_ForceWin(mobj_t *actor) ...@@ -11027,7 +10908,7 @@ void A_ForceWin(mobj_t *actor)
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (playeringame[i] && ((players[i].mo && players[i].mo->health) if (players[i].ingame && ((players[i].mo && players[i].mo->health)
|| ((netgame || multiplayer) && (players[i].lives || players[i].continues)))) || ((netgame || multiplayer) && (players[i].lives || players[i].continues))))
break; break;
} }
...@@ -11037,7 +10918,7 @@ void A_ForceWin(mobj_t *actor) ...@@ -11037,7 +10918,7 @@ void A_ForceWin(mobj_t *actor)
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i]) if (!players[i].ingame)
continue; continue;
P_DoPlayerExit(&players[i], true); P_DoPlayerExit(&players[i], true);
} }
...@@ -11052,8 +10933,9 @@ void A_ForceWin(mobj_t *actor) ...@@ -11052,8 +10933,9 @@ void A_ForceWin(mobj_t *actor)
// else, actor solid // else, actor solid
// var2 = unused // var2 = unused
// //
void A_SpikeRetract(mobj_t *actor) void A_SpikeRetract(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
if (LUA_CallAction(A_SPIKERETRACT, actor)) if (LUA_CallAction(A_SPIKERETRACT, actor))
...@@ -11090,8 +10972,9 @@ void A_SpikeRetract(mobj_t *actor) ...@@ -11090,8 +10972,9 @@ void A_SpikeRetract(mobj_t *actor)
// else if var1 == 6, set actor to raisestate // else if var1 == 6, set actor to raisestate
// var2 = unused // var2 = unused
// //
void A_InfoState(mobj_t *actor) void A_InfoState(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
switch (locvar1) switch (locvar1)
{ {
...@@ -11135,8 +11018,9 @@ void A_InfoState(mobj_t *actor) ...@@ -11135,8 +11018,9 @@ void A_InfoState(mobj_t *actor)
// var1 = repeat count // var1 = repeat count
// var2 = state to return to if extravalue2 > 0 // var2 = state to return to if extravalue2 > 0
// //
void A_Repeat(mobj_t *actor) void A_Repeat(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -11159,8 +11043,9 @@ void A_Repeat(mobj_t *actor) ...@@ -11159,8 +11043,9 @@ void A_Repeat(mobj_t *actor)
// upper 16 bits: 0 = actor, 1 = target, 2 = tracer // upper 16 bits: 0 = actor, 1 = target, 2 = tracer
// lower 16 bits: 0 = instant change, 1 = smooth change // lower 16 bits: 0 = instant change, 1 = smooth change
// //
void A_SetScale(mobj_t *actor) void A_SetScale(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
mobj_t *target; mobj_t *target;
...@@ -11202,8 +11087,9 @@ void A_SetScale(mobj_t *actor) ...@@ -11202,8 +11087,9 @@ void A_SetScale(mobj_t *actor)
// var1 = Mobj affected: 0 - actor, 1 - target, 2 - tracer // var1 = Mobj affected: 0 - actor, 1 - target, 2 - tracer
// var2 = Action: 0 - Damage, 1 - Kill, 2 - Remove // var2 = Action: 0 - Damage, 1 - Kill, 2 - Remove
// //
void A_RemoteDamage(mobj_t *actor) void A_RemoteDamage(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
mobj_t *target; // we MUST have a target mobj_t *target; // we MUST have a target
...@@ -11254,8 +11140,9 @@ void A_RemoteDamage(mobj_t *actor) ...@@ -11254,8 +11140,9 @@ void A_RemoteDamage(mobj_t *actor)
// var1 = speed multiple // var1 = speed multiple
// var2 = destination: 0 = target, 1 = tracer // var2 = destination: 0 = target, 1 = tracer
// //
void A_HomingChase(mobj_t *actor) void A_HomingChase(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
mobj_t *dest; mobj_t *dest;
...@@ -11275,7 +11162,7 @@ void A_HomingChase(mobj_t *actor) ...@@ -11275,7 +11162,7 @@ void A_HomingChase(mobj_t *actor)
actor->angle = R_PointToAngle2(actor->x, actor->y, dest->x, dest->y); actor->angle = R_PointToAngle2(actor->x, actor->y, dest->x, dest->y);
dist = P_AproxDistance(P_AproxDistance(dest->x - actor->x, dest->y - actor->y), dest->z - actor->z); dist = P_GetMobjDistance3D(dest, actor);
if (dist < 1) if (dist < 1)
dist = 1; dist = 1;
...@@ -11303,8 +11190,9 @@ void A_HomingChase(mobj_t *actor) ...@@ -11303,8 +11190,9 @@ void A_HomingChase(mobj_t *actor)
// use vertical angle variable as horizontal distance to cover during momz calculation // use vertical angle variable as horizontal distance to cover during momz calculation
// upper 16 bits = height offset // upper 16 bits = height offset
// //
void A_TrapShot(mobj_t *actor) void A_TrapShot(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
boolean oldstyle = (locvar2 & 32768) ? true : false; boolean oldstyle = (locvar2 & 32768) ? true : false;
...@@ -11339,7 +11227,7 @@ void A_TrapShot(mobj_t *actor) ...@@ -11339,7 +11227,7 @@ void A_TrapShot(mobj_t *actor)
P_SetScale(missile, actor->scale, true); P_SetScale(missile, actor->scale, true);
if (missile->info->seesound) if (missile->info->seesound)
S_StartSound(missile, missile->info->seesound); S_StartSoundFromMobj(missile, missile->info->seesound);
P_SetTarget(&missile->target, actor); P_SetTarget(&missile->target, actor);
missile->angle = actor->angle; missile->angle = actor->angle;
...@@ -11373,8 +11261,9 @@ void A_TrapShot(mobj_t *actor) ...@@ -11373,8 +11261,9 @@ void A_TrapShot(mobj_t *actor)
// var1 = mobj to spawn // var1 = mobj to spawn
// var2 = If 0, target only the actor's target. Else, target every player, period. // var2 = If 0, target only the actor's target. Else, target every player, period.
// //
void A_VileTarget(mobj_t *actor) void A_VileTarget(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
mobj_t *fog; mobj_t *fog;
...@@ -11423,7 +11312,7 @@ void A_VileTarget(mobj_t *actor) ...@@ -11423,7 +11312,7 @@ void A_VileTarget(mobj_t *actor)
// Our "Archvile" here is actually Oprah. "YOU GET A TARGET! YOU GET A TARGET! YOU ALL GET A TARGET!" // Our "Archvile" here is actually Oprah. "YOU GET A TARGET! YOU GET A TARGET! YOU ALL GET A TARGET!"
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i] || players[i].spectator) if (!players[i].ingame || players[i].spectator)
continue; continue;
if (!players[i].mo) if (!players[i].mo)
...@@ -11465,8 +11354,9 @@ void A_VileTarget(mobj_t *actor) ...@@ -11465,8 +11354,9 @@ void A_VileTarget(mobj_t *actor)
// Lower 16 bits = optional explosion object // Lower 16 bits = optional explosion object
// Upper 16 bits = If 0, attack only the actor's target. Else, attack all the players. All of them. // Upper 16 bits = If 0, attack only the actor's target. Else, attack all the players. All of them.
// //
void A_VileAttack(mobj_t *actor) void A_VileAttack(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
sfxenum_t soundtoplay; sfxenum_t soundtoplay;
...@@ -11494,11 +11384,12 @@ void A_VileAttack(mobj_t *actor) ...@@ -11494,11 +11384,12 @@ void A_VileAttack(mobj_t *actor)
explosionType = (mobjtype_t)(locvar2 & 0xFFFF); explosionType = (mobjtype_t)(locvar2 & 0xFFFF);
} }
if (!(locvar2 & 0xFFFF0000)) { if (!(locvar2 & 0xFFFF0000))
{
if (!P_CheckSight(actor, actor->target)) if (!P_CheckSight(actor, actor->target))
return; return;
S_StartSound(actor, soundtoplay); S_StartSoundFromMobj(actor, soundtoplay);
P_DamageMobj(actor->target, actor, actor, 1, 0); P_DamageMobj(actor->target, actor, actor, 1, 0);
//actor->target->momz = 1000*FRACUNIT/actor->target->info->mass; // How id did it //actor->target->momz = 1000*FRACUNIT/actor->target->info->mass; // How id did it
actor->target->momz += FixedMul(10*FRACUNIT, actor->scale)*P_MobjFlip(actor->target); // How we're doing it actor->target->momz += FixedMul(10*FRACUNIT, actor->scale)*P_MobjFlip(actor->target); // How we're doing it
...@@ -11527,7 +11418,7 @@ void A_VileAttack(mobj_t *actor) ...@@ -11527,7 +11418,7 @@ void A_VileAttack(mobj_t *actor)
// Oprahvile strikes again, but this time, she brings HOT PAIN // Oprahvile strikes again, but this time, she brings HOT PAIN
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i] || players[i].spectator) if (!players[i].ingame || players[i].spectator)
continue; continue;
if (!players[i].mo) if (!players[i].mo)
...@@ -11539,7 +11430,7 @@ void A_VileAttack(mobj_t *actor) ...@@ -11539,7 +11430,7 @@ void A_VileAttack(mobj_t *actor)
if (!P_CheckSight(actor, players[i].mo)) if (!P_CheckSight(actor, players[i].mo))
continue; continue;
S_StartSound(actor, soundtoplay); S_StartSoundFromMobj(actor, soundtoplay);
P_DamageMobj(players[i].mo, actor, actor, 1, 0); P_DamageMobj(players[i].mo, actor, actor, 1, 0);
//actor->target->momz = 1000*FRACUNIT/actor->target->info->mass; // How id did it //actor->target->momz = 1000*FRACUNIT/actor->target->info->mass; // How id did it
players[i].mo->momz += FixedMul(10*FRACUNIT, actor->scale)*P_MobjFlip(players[i].mo); // How we're doing it players[i].mo->momz += FixedMul(10*FRACUNIT, actor->scale)*P_MobjFlip(players[i].mo); // How we're doing it
...@@ -11582,8 +11473,9 @@ void A_VileAttack(mobj_t *actor) ...@@ -11582,8 +11473,9 @@ void A_VileAttack(mobj_t *actor)
// Lower 16 bits = mobj to spawn (0 doesn't spawn a line at all) // Lower 16 bits = mobj to spawn (0 doesn't spawn a line at all)
// Upper 16 bits = # to spawn (default is 8) // Upper 16 bits = # to spawn (default is 8)
// //
void A_VileFire(mobj_t *actor) void A_VileFire(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
mobj_t *dest; mobj_t *dest;
...@@ -11621,7 +11513,7 @@ void A_VileFire(mobj_t *actor) ...@@ -11621,7 +11513,7 @@ void A_VileFire(mobj_t *actor)
// Play sound, if one's specified // Play sound, if one's specified
if (locvar1 > 0 && locvar1 < NUMSFX) if (locvar1 > 0 && locvar1 < NUMSFX)
S_StartSound(actor, (sfxenum_t)locvar1); S_StartSoundFromMobj(actor, (sfxenum_t)locvar1);
// Now draw the line to the actor's target // Now draw the line to the actor's target
if (locvar2 & 0xFFFF) if (locvar2 & 0xFFFF)
...@@ -11635,7 +11527,8 @@ void A_VileFire(mobj_t *actor) ...@@ -11635,7 +11527,8 @@ void A_VileFire(mobj_t *actor)
lineMobj = (mobjtype_t)(locvar2 & 0xFFFF); lineMobj = (mobjtype_t)(locvar2 & 0xFFFF);
numLineMobjs = (UINT16)(locvar2 >> 16); numLineMobjs = (UINT16)(locvar2 >> 16);
if (numLineMobjs == 0) { if (numLineMobjs == 0)
{
numLineMobjs = 8; numLineMobjs = 8;
} }
...@@ -11666,8 +11559,9 @@ void A_VileFire(mobj_t *actor) ...@@ -11666,8 +11559,9 @@ void A_VileFire(mobj_t *actor)
// var1 = lower-bound of frame length, in tics // var1 = lower-bound of frame length, in tics
// var2 = optional sound to play // var2 = optional sound to play
// //
void A_BrakChase(mobj_t *actor) void A_BrakChase(void *data)
{ {
mobj_t *actor = data;
INT32 delta; INT32 delta;
INT32 lowerbound; INT32 lowerbound;
INT32 newtics; INT32 newtics;
...@@ -11696,7 +11590,7 @@ void A_BrakChase(mobj_t *actor) ...@@ -11696,7 +11590,7 @@ void A_BrakChase(mobj_t *actor)
{ {
actor->reactiontime--; actor->reactiontime--;
if (actor->reactiontime == 0 && actor->type == MT_CYBRAKDEMON) if (actor->reactiontime == 0 && actor->type == MT_CYBRAKDEMON)
S_StartSound(0, sfx_bewar1 + P_RandomKey(4)); S_StartSoundFromEverywhere(sfx_bewar1 + P_RandomKey(4));
} }
// modify target threshold // modify target threshold
...@@ -11778,12 +11672,12 @@ void A_BrakChase(mobj_t *actor) ...@@ -11778,12 +11672,12 @@ void A_BrakChase(mobj_t *actor)
// Optionally play a sound effect // Optionally play a sound effect
if (locvar2 > 0 && locvar2 < NUMSFX) if (locvar2 > 0 && locvar2 < NUMSFX)
S_StartSound(actor, (sfxenum_t)locvar2); S_StartSoundFromMobj(actor, (sfxenum_t)locvar2);
// make active sound // make active sound
if (actor->type != MT_CYBRAKDEMON && actor->info->activesound && P_RandomChance(3*FRACUNIT/256)) if (actor->type != MT_CYBRAKDEMON && actor->info->activesound && P_RandomChance(3*FRACUNIT/256))
{ {
S_StartSound(actor, actor->info->activesound); S_StartSoundFromMobj(actor, actor->info->activesound);
} }
} }
...@@ -11795,8 +11689,9 @@ void A_BrakChase(mobj_t *actor) ...@@ -11795,8 +11689,9 @@ void A_BrakChase(mobj_t *actor)
// var1 = object # to shoot // var1 = object # to shoot
// var2 = unused // var2 = unused
// //
void A_BrakFireShot(mobj_t *actor) void A_BrakFireShot(void *data)
{ {
mobj_t *actor = data;
fixed_t x, y, z; fixed_t x, y, z;
INT32 locvar1 = var1; INT32 locvar1 = var1;
...@@ -11845,8 +11740,9 @@ void A_BrakFireShot(mobj_t *actor) ...@@ -11845,8 +11740,9 @@ void A_BrakFireShot(mobj_t *actor)
// Upper 16 bits: if 0, aim 1/3 of the way. Else, aim directly at target. // Upper 16 bits: if 0, aim 1/3 of the way. Else, aim directly at target.
// //
void A_BrakLobShot(mobj_t *actor) void A_BrakLobShot(void *data)
{ {
mobj_t *actor = data;
fixed_t v; // Velocity to shoot object fixed_t v; // Velocity to shoot object
fixed_t a1, a2, aToUse; // Velocity squared fixed_t a1, a2, aToUse; // Velocity squared
fixed_t g; // Gravity fixed_t g; // Gravity
...@@ -11875,14 +11771,14 @@ void A_BrakLobShot(mobj_t *actor) ...@@ -11875,14 +11771,14 @@ void A_BrakLobShot(mobj_t *actor)
g = FixedMul(gravity, P_GetSectorGravityFactor(actor->subsector->sector)); g = FixedMul(gravity, P_GetSectorGravityFactor(actor->subsector->sector));
// Look up distance between actor and its target // Look up distance between actor and its target
x = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y); x = P_GetMobjDistance2D(actor->target, actor);
if (!aimDirect) if (!aimDirect)
{ {
// Distance should actually be a third of the way over // Distance should actually be a third of the way over
x = FixedDiv(x, 3<<FRACBITS); x = FixedDiv(x, 3<<FRACBITS);
newTargetX = actor->x + P_ReturnThrustX(actor, actor->angle, x); newTargetX = actor->x + P_ReturnThrustX(actor, actor->angle, x);
newTargetY = actor->y + P_ReturnThrustY(actor, actor->angle, x); newTargetY = actor->y + P_ReturnThrustY(actor, actor->angle, x);
x = P_AproxDistance(newTargetX - actor->x, newTargetY - actor->y); x = GetDistance2D(actor->x, actor->y, newTargetX, newTargetY);
// Look up height difference between actor and the ground 1/3 of the way to its target // Look up height difference between actor and the ground 1/3 of the way to its target
y = P_FloorzAtPos(newTargetX, newTargetY, actor->target->z, actor->target->height) - (actor->z + FixedMul(locvar2*FRACUNIT, actor->scale)); y = P_FloorzAtPos(newTargetX, newTargetY, actor->target->z, actor->target->height) - (actor->z + FixedMul(locvar2*FRACUNIT, actor->scale));
} }
...@@ -11936,7 +11832,7 @@ void A_BrakLobShot(mobj_t *actor) ...@@ -11936,7 +11832,7 @@ void A_BrakLobShot(mobj_t *actor)
if (P_MobjWasRemoved(shot)) if (P_MobjWasRemoved(shot))
return; return;
if (shot->info->seesound) if (shot->info->seesound)
S_StartSound(shot, shot->info->seesound); S_StartSoundFromMobj(shot, shot->info->seesound);
P_SetTarget(&shot->target, actor); // where it came from P_SetTarget(&shot->target, actor); // where it came from
shot->angle = actor->angle; shot->angle = actor->angle;
...@@ -11961,8 +11857,9 @@ void A_BrakLobShot(mobj_t *actor) ...@@ -11961,8 +11857,9 @@ void A_BrakLobShot(mobj_t *actor)
// Lower 16 bits: distance to toss them (No default - 0 does just that - but negatives will revert to 128) // Lower 16 bits: distance to toss them (No default - 0 does just that - but negatives will revert to 128)
// Upper 16 bits: airtime in tics (default 16) // Upper 16 bits: airtime in tics (default 16)
// //
void A_NapalmScatter(mobj_t *actor) void A_NapalmScatter(void *data)
{ {
mobj_t *actor = data;
mobjtype_t typeOfShot = var1 & 0x0000FFFF; // Type mobjtype_t typeOfShot = var1 & 0x0000FFFF; // Type
INT32 numToShoot = (var1 & 0xFFFF0000) >> 16; // How many INT32 numToShoot = (var1 & 0xFFFF0000) >> 16; // How many
fixed_t distance = (var2 & 0x0000FFFF) << FRACBITS; // How far fixed_t distance = (var2 & 0x0000FFFF) << FRACBITS; // How far
...@@ -12020,8 +11917,9 @@ void A_NapalmScatter(mobj_t *actor) ...@@ -12020,8 +11917,9 @@ void A_NapalmScatter(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_SpawnFreshCopy(mobj_t *actor) void A_SpawnFreshCopy(void *data)
{ {
mobj_t *actor = data;
mobj_t *newObject; mobj_t *newObject;
if (LUA_CallAction(A_SPAWNFRESHCOPY, actor)) if (LUA_CallAction(A_SPAWNFRESHCOPY, actor))
...@@ -12037,7 +11935,7 @@ void A_SpawnFreshCopy(mobj_t *actor) ...@@ -12037,7 +11935,7 @@ void A_SpawnFreshCopy(mobj_t *actor)
P_SetTarget(&newObject->tracer, actor->tracer); P_SetTarget(&newObject->tracer, actor->tracer);
if (newObject->info->seesound) if (newObject->info->seesound)
S_StartSound(newObject, newObject->info->seesound); S_StartSoundFromMobj(newObject, newObject->info->seesound);
} }
// Internal Flicky spawning function. // Internal Flicky spawning function.
...@@ -12097,8 +11995,9 @@ mobj_t *P_InternalFlickySpawn(mobj_t *actor, mobjtype_t flickytype, fixed_t momz ...@@ -12097,8 +11995,9 @@ mobj_t *P_InternalFlickySpawn(mobj_t *actor, mobjtype_t flickytype, fixed_t momz
// bit 19: if 1, spawn flicky slightly backward from spawn position. doesn't stack with 18. // bit 19: if 1, spawn flicky slightly backward from spawn position. doesn't stack with 18.
// var2 = upwards thrust for spawned flicky. If zero, default value is provided. // var2 = upwards thrust for spawned flicky. If zero, default value is provided.
// //
void A_FlickySpawn(mobj_t *actor) void A_FlickySpawn(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1 & 65535; INT32 locvar1 = var1 & 65535;
INT32 locvar2 = var2; INT32 locvar2 = var2;
INT32 test = (var1 >> 16); INT32 test = (var1 >> 16);
...@@ -12164,8 +12063,9 @@ void P_InternalFlickySetColor(mobj_t *actor, UINT8 color) ...@@ -12164,8 +12063,9 @@ void P_InternalFlickySetColor(mobj_t *actor, UINT8 color)
// If TMFF_STATIONARY (MF_GRENADEBOUNCE): Flickies stand in-place without gravity (unless they hop, then gravity is applied.) // If TMFF_STATIONARY (MF_GRENADEBOUNCE): Flickies stand in-place without gravity (unless they hop, then gravity is applied.)
// If TMFF_HOP (MF_NOCLIPTHING): is flagged, Flickies hop. // If TMFF_HOP (MF_NOCLIPTHING): is flagged, Flickies hop.
// //
void A_FlickyCenter(mobj_t *actor) void A_FlickyCenter(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
UINT16 flickytype = (locvar1 & 0xFFFF); UINT16 flickytype = (locvar1 & 0xFFFF);
...@@ -12251,7 +12151,7 @@ void A_FlickyCenter(mobj_t *actor) ...@@ -12251,7 +12151,7 @@ void A_FlickyCenter(mobj_t *actor)
P_LookForPlayers(actor, true, false, actor->extravalue1); P_LookForPlayers(actor, true, false, actor->extravalue1);
if (actor->target && P_AproxDistance(actor->target->x - originx, actor->target->y - originy) < actor->extravalue1) if (actor->target && GetDistance2D(actor->target->x, actor->target->y, originx, originy) < actor->extravalue1)
{ {
actor->extravalue2 = 1; actor->extravalue2 = 1;
P_SetOrigin(actor, actor->target->x, actor->target->y, actor->target->z); P_SetOrigin(actor, actor->target->x, actor->target->y, actor->target->z);
...@@ -12297,8 +12197,9 @@ void P_InternalFlickyBubble(mobj_t *actor) ...@@ -12297,8 +12197,9 @@ void P_InternalFlickyBubble(mobj_t *actor)
// var1 = how far around the target (in angle constants) the flicky should look // var1 = how far around the target (in angle constants) the flicky should look
// var2 = distance from target to aim for // var2 = distance from target to aim for
// //
void A_FlickyAim(mobj_t *actor) void A_FlickyAim(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
boolean flickyhitwall = false; boolean flickyhitwall = false;
...@@ -12309,7 +12210,7 @@ void A_FlickyAim(mobj_t *actor) ...@@ -12309,7 +12210,7 @@ void A_FlickyAim(mobj_t *actor)
if ((actor->momx == actor->momy && actor->momy == 0) if ((actor->momx == actor->momy && actor->momy == 0)
|| (actor->target && P_IsFlickyCenter(actor->target->type) || (actor->target && P_IsFlickyCenter(actor->target->type)
&& actor->target->extravalue1 && (actor->target->flags & MF_SLIDEME) && actor->target->extravalue1 && (actor->target->flags & MF_SLIDEME)
&& P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) >= actor->target->extravalue1)) && P_AreMobjsFar2D(actor, actor->target, actor->target->extravalue1)))
flickyhitwall = true; flickyhitwall = true;
P_InternalFlickyBubble(actor); P_InternalFlickyBubble(actor);
...@@ -12331,12 +12232,12 @@ void A_FlickyAim(mobj_t *actor) ...@@ -12331,12 +12232,12 @@ void A_FlickyAim(mobj_t *actor)
actor->movedir *= -1; actor->movedir *= -1;
posvar = ((R_PointToAngle2(actor->target->x, actor->target->y, actor->x, actor->y) + actor->movedir*locvar1) >> ANGLETOFINESHIFT) & FINEMASK; posvar = ((R_PointToAngle2(actor->target->x, actor->target->y, actor->x, actor->y) + actor->movedir*locvar1) >> ANGLETOFINESHIFT) & FINEMASK;
chasevar = FixedSqrt(max(FRACUNIT, P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y) - locvar2)) + locvar2; chasevar = FixedSqrt(max(FRACUNIT, P_GetMobjDistance2D(actor->target, actor) - locvar2)) + locvar2;
chasex = actor->target->x + FixedMul(FINECOSINE(posvar), chasevar); chasex = actor->target->x + FixedMul(FINECOSINE(posvar), chasevar);
chasey = actor->target->y + FixedMul(FINESINE(posvar), chasevar); chasey = actor->target->y + FixedMul(FINESINE(posvar), chasevar);
if (P_AproxDistance(chasex - actor->x, chasey - actor->y)) if (GetDistance2D(chasex, chasey, actor->x, actor->y))
actor->angle = R_PointToAngle2(actor->x, actor->y, chasex, chasey); actor->angle = R_PointToAngle2(actor->x, actor->y, chasex, chasey);
} }
else if (flickyhitwall) else if (flickyhitwall)
...@@ -12378,7 +12279,7 @@ void P_InternalFlickyFly(mobj_t *actor, fixed_t flyspeed, fixed_t targetdist, fi ...@@ -12378,7 +12279,7 @@ void P_InternalFlickyFly(mobj_t *actor, fixed_t flyspeed, fixed_t targetdist, fi
targetdist = 16*FRACUNIT; //Default! targetdist = 16*FRACUNIT; //Default!
if (actor->target && abs(chasez - actor->z) > targetdist) if (actor->target && abs(chasez - actor->z) > targetdist)
targetdist = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y); targetdist = P_GetMobjDistance2D(actor->target, actor);
if (actor->target if (actor->target
&& P_IsFlickyCenter(actor->target->type) && P_IsFlickyCenter(actor->target->type)
...@@ -12398,8 +12299,9 @@ void P_InternalFlickyFly(mobj_t *actor, fixed_t flyspeed, fixed_t targetdist, fi ...@@ -12398,8 +12299,9 @@ void P_InternalFlickyFly(mobj_t *actor, fixed_t flyspeed, fixed_t targetdist, fi
// var1 = how fast to fly // var1 = how fast to fly
// var2 = how far ahead the target should be considered // var2 = how far ahead the target should be considered
// //
void A_FlickyFly(mobj_t *actor) void A_FlickyFly(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -12418,8 +12320,9 @@ void A_FlickyFly(mobj_t *actor) ...@@ -12418,8 +12320,9 @@ void A_FlickyFly(mobj_t *actor)
// var1 = how fast to fly // var1 = how fast to fly
// var2 = how far ahead the target should be considered // var2 = how far ahead the target should be considered
// //
void A_FlickySoar(mobj_t *actor) void A_FlickySoar(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -12442,8 +12345,9 @@ void A_FlickySoar(mobj_t *actor) ...@@ -12442,8 +12345,9 @@ void A_FlickySoar(mobj_t *actor)
// var2 = state to change to upon slowing down // var2 = state to change to upon slowing down
// the spawnstate of the mobj = state to change to when above water // the spawnstate of the mobj = state to change to when above water
// //
void A_FlickyCoast(mobj_t *actor) void A_FlickyCoast(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -12456,7 +12360,7 @@ void A_FlickyCoast(mobj_t *actor) ...@@ -12456,7 +12360,7 @@ void A_FlickyCoast(mobj_t *actor)
actor->momy = (11*actor->momy)/12; actor->momy = (11*actor->momy)/12;
actor->momz = (11*actor->momz)/12; actor->momz = (11*actor->momz)/12;
if (P_AproxDistance(P_AproxDistance(actor->momx, actor->momy), actor->momz) < locvar1) if (GetDistance3D(0, 0, 0, actor->momx, actor->momy, actor->momz) < locvar1)
P_SetMobjState(actor, locvar2); P_SetMobjState(actor, locvar2);
return; return;
...@@ -12489,8 +12393,9 @@ void P_InternalFlickyHop(mobj_t *actor, fixed_t momz, fixed_t momh, angle_t angl ...@@ -12489,8 +12393,9 @@ void P_InternalFlickyHop(mobj_t *actor, fixed_t momz, fixed_t momh, angle_t angl
// var1 = vertical thrust // var1 = vertical thrust
// var2 = horizontal thrust // var2 = horizontal thrust
// //
void A_FlickyHop(mobj_t *actor) void A_FlickyHop(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -12507,8 +12412,9 @@ void A_FlickyHop(mobj_t *actor) ...@@ -12507,8 +12412,9 @@ void A_FlickyHop(mobj_t *actor)
// var1 = intended vertical thrust // var1 = intended vertical thrust
// var2 = intended horizontal thrust // var2 = intended horizontal thrust
// //
void A_FlickyFlounder(mobj_t *actor) void A_FlickyFlounder(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
angle_t hopangle; angle_t hopangle;
...@@ -12530,8 +12436,9 @@ void A_FlickyFlounder(mobj_t *actor) ...@@ -12530,8 +12436,9 @@ void A_FlickyFlounder(mobj_t *actor)
// var2 = state to change to upon falling // var2 = state to change to upon falling
// the meleestate of the mobj = state to change to when underwater // the meleestate of the mobj = state to change to when underwater
// //
void A_FlickyCheck(mobj_t *actor) void A_FlickyCheck(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -12567,8 +12474,9 @@ void A_FlickyCheck(mobj_t *actor) ...@@ -12567,8 +12474,9 @@ void A_FlickyCheck(mobj_t *actor)
// var1 = state to change to when falling below height relative to target // var1 = state to change to when falling below height relative to target
// var2 = height relative to target to change state at // var2 = height relative to target to change state at
// //
void A_FlickyHeightCheck(mobj_t *actor) void A_FlickyHeightCheck(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -12602,8 +12510,9 @@ void A_FlickyHeightCheck(mobj_t *actor) ...@@ -12602,8 +12510,9 @@ void A_FlickyHeightCheck(mobj_t *actor)
// var2 = state to change to upon falling // var2 = state to change to upon falling
// the meleestate of the mobj = state to change to when underwater // the meleestate of the mobj = state to change to when underwater
// //
void A_FlickyFlutter(mobj_t *actor) void A_FlickyFlutter(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -12632,8 +12541,9 @@ void A_FlickyFlutter(mobj_t *actor) ...@@ -12632,8 +12541,9 @@ void A_FlickyFlutter(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_FlameParticle(mobj_t *actor) void A_FlameParticle(void *data)
{ {
mobj_t *actor = data;
mobjtype_t type = (mobjtype_t)(mobjinfo[actor->type].painchance); mobjtype_t type = (mobjtype_t)(mobjinfo[actor->type].painchance);
fixed_t rad, hei; fixed_t rad, hei;
mobj_t *particle; mobj_t *particle;
...@@ -12662,8 +12572,9 @@ void A_FlameParticle(mobj_t *actor) ...@@ -12662,8 +12572,9 @@ void A_FlameParticle(mobj_t *actor)
// var1 = bit 1 = bit 1 = don't make fast, bit 2 = don't set tracer // var1 = bit 1 = bit 1 = don't make fast, bit 2 = don't set tracer
// var2 = unused // var2 = unused
// //
void A_FadeOverlay(mobj_t *actor) void A_FadeOverlay(void *data)
{ {
mobj_t *actor = data;
mobj_t *fade; mobj_t *fade;
INT32 locvar1 = var1; INT32 locvar1 = var1;
...@@ -12695,8 +12606,9 @@ void A_FadeOverlay(mobj_t *actor) ...@@ -12695,8 +12606,9 @@ void A_FadeOverlay(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_Boss5Jump(mobj_t *actor) void A_Boss5Jump(void *data)
{ {
mobj_t *actor = data;
fixed_t v; // Velocity to jump at fixed_t v; // Velocity to jump at
fixed_t a1, a2, aToUse; // Velocity squared fixed_t a1, a2, aToUse; // Velocity squared
fixed_t g; // Gravity fixed_t g; // Gravity
...@@ -12720,7 +12632,7 @@ void A_Boss5Jump(mobj_t *actor) ...@@ -12720,7 +12632,7 @@ void A_Boss5Jump(mobj_t *actor)
g = FixedMul(gravity, P_GetSectorGravityFactor(actor->subsector->sector)); g = FixedMul(gravity, P_GetSectorGravityFactor(actor->subsector->sector));
// Look up distance between actor and its tracer // Look up distance between actor and its tracer
x = P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y); x = P_GetMobjDistance2D(actor->tracer, actor);
// Look up height difference between actor and its tracer // Look up height difference between actor and its tracer
y = actor->tracer->z - actor->z; y = actor->tracer->z - actor->z;
...@@ -12779,8 +12691,9 @@ void A_Boss5Jump(mobj_t *actor) ...@@ -12779,8 +12691,9 @@ void A_Boss5Jump(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_LightBeamReset(mobj_t *actor) void A_LightBeamReset(void *data)
{ {
mobj_t *actor = data;
// INT32 locvar1 = var1; // INT32 locvar1 = var1;
// INT32 locvar2 = var2; // INT32 locvar2 = var2;
...@@ -12808,8 +12721,9 @@ void A_LightBeamReset(mobj_t *actor) ...@@ -12808,8 +12721,9 @@ void A_LightBeamReset(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_MineExplode(mobj_t *actor) void A_MineExplode(void *data)
{ {
mobj_t *actor = data;
// INT32 locvar1 = var1; // INT32 locvar1 = var1;
// INT32 locvar2 = var2; // INT32 locvar2 = var2;
...@@ -12831,7 +12745,7 @@ void A_MineExplode(mobj_t *actor) ...@@ -12831,7 +12745,7 @@ void A_MineExplode(mobj_t *actor)
#define dist 64 #define dist 64
UINT8 i; UINT8 i;
mobjtype_t type = ((actor->eflags & MFE_UNDERWATER) ? MT_UWEXPLODE : MT_SONIC3KBOSSEXPLODE); mobjtype_t type = ((actor->eflags & MFE_UNDERWATER) ? MT_UWEXPLODE : MT_SONIC3KBOSSEXPLODE);
S_StartSound(actor, ((actor->eflags & MFE_UNDERWATER) ? sfx_s3k57 : sfx_s3k4e)); S_StartSoundFromMobj(actor, ((actor->eflags & MFE_UNDERWATER) ? sfx_s3k57 : sfx_s3k4e));
P_SpawnMobj(actor->x, actor->y, actor->z, type); P_SpawnMobj(actor->x, actor->y, actor->z, type);
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
{ {
...@@ -12842,7 +12756,7 @@ void A_MineExplode(mobj_t *actor) ...@@ -12842,7 +12756,7 @@ void A_MineExplode(mobj_t *actor)
if (P_MobjWasRemoved(b)) if (P_MobjWasRemoved(b))
continue; continue;
fixed_t dx = b->x - actor->x, dy = b->y - actor->y, dz = b->z - actor->z; fixed_t dx = b->x - actor->x, dy = b->y - actor->y, dz = b->z - actor->z;
fixed_t dm = P_AproxDistance(dz, P_AproxDistance(dy, dx)); fixed_t dm = GetDistance3D(0, 0, 0, dx, dy, dz);
b->momx = FixedDiv(dx, dm)*3; b->momx = FixedDiv(dx, dm)*3;
b->momy = FixedDiv(dy, dm)*3; b->momy = FixedDiv(dy, dm)*3;
b->momz = FixedDiv(dz, dm)*3; b->momz = FixedDiv(dz, dm)*3;
...@@ -12862,8 +12776,9 @@ void A_MineExplode(mobj_t *actor) ...@@ -12862,8 +12776,9 @@ void A_MineExplode(mobj_t *actor)
// var1 = Distance to alert at // var1 = Distance to alert at
// var2 = unused // var2 = unused
// //
void A_MineRange(mobj_t *actor) void A_MineRange(void *data)
{ {
mobj_t *actor = data;
fixed_t dm; fixed_t dm;
INT32 locvar1 = var1; INT32 locvar1 = var1;
// INT32 locvar2 = var2; // INT32 locvar2 = var2;
...@@ -12874,7 +12789,7 @@ void A_MineRange(mobj_t *actor) ...@@ -12874,7 +12789,7 @@ void A_MineRange(mobj_t *actor)
if (!actor->target) if (!actor->target)
return; return;
dm = P_AproxDistance(actor->z - actor->target->z, P_AproxDistance(actor->y - actor->target->y, actor->x - actor->target->x)); dm = P_GetMobjDistance3D(actor, actor->target);
if ((dm>>FRACBITS) < locvar1) if ((dm>>FRACBITS) < locvar1)
P_SetMobjState(actor, actor->info->meleestate); P_SetMobjState(actor, actor->info->meleestate);
} }
...@@ -12885,8 +12800,9 @@ void A_MineRange(mobj_t *actor) ...@@ -12885,8 +12800,9 @@ void A_MineRange(mobj_t *actor)
// var1 = Object type to connect to ground // var1 = Object type to connect to ground
// var2 = Object type to place on ground // var2 = Object type to place on ground
// //
void A_ConnectToGround(mobj_t *actor) void A_ConnectToGround(void *data)
{ {
mobj_t *actor = data;
mobj_t *work; mobj_t *work;
fixed_t endz; fixed_t endz;
angle_t ang; angle_t ang;
...@@ -12948,8 +12864,9 @@ void A_ConnectToGround(mobj_t *actor) ...@@ -12948,8 +12864,9 @@ void A_ConnectToGround(mobj_t *actor)
// var2 >> 16 = z // var2 >> 16 = z
// var2 & 65535 = state // var2 & 65535 = state
// //
void A_SpawnParticleRelative(mobj_t *actor) void A_SpawnParticleRelative(void *data)
{ {
mobj_t *actor = data;
INT16 x, y, z; // Want to be sure we can use negative values INT16 x, y, z; // Want to be sure we can use negative values
statenum_t state; statenum_t state;
mobj_t *mo; mobj_t *mo;
...@@ -12991,8 +12908,9 @@ void A_SpawnParticleRelative(mobj_t *actor) ...@@ -12991,8 +12908,9 @@ void A_SpawnParticleRelative(mobj_t *actor)
// var1 = same as A_MultiShot // var1 = same as A_MultiShot
// var2 = same as A_MultiShot // var2 = same as A_MultiShot
// //
void A_MultiShotDist(mobj_t *actor) void A_MultiShotDist(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -13004,8 +12922,8 @@ void A_MultiShotDist(mobj_t *actor) ...@@ -13004,8 +12922,8 @@ void A_MultiShotDist(mobj_t *actor)
// Quick! Look through players! // Quick! Look through players!
// Don't spawn dust unless a player is relatively close by (var1). // Don't spawn dust unless a player is relatively close by (var1).
for (i = 0; i < MAXPLAYERS; ++i) for (i = 0; i < MAXPLAYERS; ++i)
if (playeringame[i] && players[i].mo if (players[i].ingame && players[i].mo
&& P_AproxDistance(actor->x - players[i].mo->x, actor->y - players[i].mo->y) < (1600<<FRACBITS)) && P_AreMobjsClose2D(actor, players[i].mo, 1600<<FRACBITS))
break; // Stop looking. break; // Stop looking.
if (i == MAXPLAYERS) if (i == MAXPLAYERS)
return; // don't make bubble! return; // don't make bubble!
...@@ -13027,8 +12945,9 @@ void A_MultiShotDist(mobj_t *actor) ...@@ -13027,8 +12945,9 @@ void A_MultiShotDist(mobj_t *actor)
// var2 >> 16 = forward offset // var2 >> 16 = forward offset
// var2 & 65535 = vertical offset // var2 & 65535 = vertical offset
// //
void A_WhoCaresIfYourSonIsABee(mobj_t *actor) void A_WhoCaresIfYourSonIsABee(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
fixed_t foffsetx; fixed_t foffsetx;
...@@ -13046,7 +12965,7 @@ void A_WhoCaresIfYourSonIsABee(mobj_t *actor) ...@@ -13046,7 +12965,7 @@ void A_WhoCaresIfYourSonIsABee(mobj_t *actor)
actor->extravalue1--; actor->extravalue1--;
if (actor->info->attacksound) if (actor->info->attacksound)
S_StartSound(actor, actor->info->attacksound); S_StartSoundFromMobj(actor, actor->info->attacksound);
foffsetx = P_ReturnThrustX(actor, actor->angle, FixedMul((locvar2 >> 16)*FRACUNIT, actor->scale)); foffsetx = P_ReturnThrustX(actor, actor->angle, FixedMul((locvar2 >> 16)*FRACUNIT, actor->scale));
foffsety = P_ReturnThrustY(actor, actor->angle, FixedMul((locvar2 >> 16)*FRACUNIT, actor->scale)); foffsety = P_ReturnThrustY(actor, actor->angle, FixedMul((locvar2 >> 16)*FRACUNIT, actor->scale));
...@@ -13067,8 +12986,9 @@ void A_WhoCaresIfYourSonIsABee(mobj_t *actor) ...@@ -13067,8 +12986,9 @@ void A_WhoCaresIfYourSonIsABee(mobj_t *actor)
// var1 = state to go to when extravalue1 // var1 = state to go to when extravalue1
// var2 = unused // var2 = unused
// //
void A_ParentTriesToSleep(mobj_t *actor) void A_ParentTriesToSleep(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
if (LUA_CallAction(A_PARENTTRIESTOSLEEP, actor)) if (LUA_CallAction(A_PARENTTRIESTOSLEEP, actor))
...@@ -13077,7 +12997,7 @@ void A_ParentTriesToSleep(mobj_t *actor) ...@@ -13077,7 +12997,7 @@ void A_ParentTriesToSleep(mobj_t *actor)
if (actor->extravalue1) if (actor->extravalue1)
{ {
if (actor->info->seesound) if (actor->info->seesound)
S_StartSound(actor, actor->info->seesound); S_StartSoundFromMobj(actor, actor->info->seesound);
actor->reactiontime = 0; actor->reactiontime = 0;
P_SetMobjState(actor, locvar1); P_SetMobjState(actor, locvar1);
} }
...@@ -13085,7 +13005,7 @@ void A_ParentTriesToSleep(mobj_t *actor) ...@@ -13085,7 +13005,7 @@ void A_ParentTriesToSleep(mobj_t *actor)
{ {
actor->reactiontime = 1; actor->reactiontime = 1;
if (actor->info->activesound) // more like INactivesound doy hoy hoy if (actor->info->activesound) // more like INactivesound doy hoy hoy
S_StartSound(actor, actor->info->activesound); S_StartSoundFromMobj(actor, actor->info->activesound);
} }
} }
...@@ -13097,8 +13017,9 @@ void A_ParentTriesToSleep(mobj_t *actor) ...@@ -13097,8 +13017,9 @@ void A_ParentTriesToSleep(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_CryingToMomma(mobj_t *actor) void A_CryingToMomma(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_CRYINGTOMOMMA, actor)) if (LUA_CallAction(A_CRYINGTOMOMMA, actor))
return; return;
...@@ -13124,8 +13045,9 @@ void A_CryingToMomma(mobj_t *actor) ...@@ -13124,8 +13045,9 @@ void A_CryingToMomma(mobj_t *actor)
// var1 = mask // var1 = mask
// var2 = state to go // var2 = state to go
// //
void A_CheckFlags2(mobj_t *actor) void A_CheckFlags2(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -13143,8 +13065,9 @@ void A_CheckFlags2(mobj_t *actor) ...@@ -13143,8 +13065,9 @@ void A_CheckFlags2(mobj_t *actor)
// var1 = if 1, always go to ambush-marked waypoint. if 2, go to MT_BOSSFLYPOINT. // var1 = if 1, always go to ambush-marked waypoint. if 2, go to MT_BOSSFLYPOINT.
// var2 = unused // var2 = unused
// //
void A_Boss5FindWaypoint(mobj_t *actor) void A_Boss5FindWaypoint(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
boolean avoidcenter; boolean avoidcenter;
INT32 i; INT32 i;
...@@ -13221,7 +13144,7 @@ void A_Boss5FindWaypoint(mobj_t *actor) ...@@ -13221,7 +13144,7 @@ void A_Boss5FindWaypoint(mobj_t *actor)
{ {
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i]) if (!players[i].ingame)
continue; continue;
if (!players[i].mo) if (!players[i].mo)
continue; continue;
...@@ -13278,7 +13201,7 @@ void A_Boss5FindWaypoint(mobj_t *actor) ...@@ -13278,7 +13201,7 @@ void A_Boss5FindWaypoint(mobj_t *actor)
{ {
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i]) if (!players[i].ingame)
continue; continue;
if (!players[i].mo) if (!players[i].mo)
continue; continue;
...@@ -13333,8 +13256,9 @@ nowaypoints: ...@@ -13333,8 +13256,9 @@ nowaypoints:
// var1 = state to change to upon being slow enough // var1 = state to change to upon being slow enough
// var2 = minimum speed // var2 = minimum speed
// //
void A_DoNPCSkid(mobj_t *actor) void A_DoNPCSkid(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
fixed_t x, y, z; fixed_t x, y, z;
...@@ -13349,7 +13273,7 @@ void A_DoNPCSkid(mobj_t *actor) ...@@ -13349,7 +13273,7 @@ void A_DoNPCSkid(mobj_t *actor)
if (!locvar2) if (!locvar2)
locvar2 = FRACUNIT/2; locvar2 = FRACUNIT/2;
if ((FixedHypot(actor->momx, actor->momy) < locvar2) if ((P_GetMobjMomentum2D(actor) < locvar2)
|| !P_TryMove(actor, actor->x + actor->momx, actor->y + actor->momy, false)) || !P_TryMove(actor, actor->x + actor->momx, actor->y + actor->momy, false))
{ {
if (P_MobjWasRemoved(actor)) if (P_MobjWasRemoved(actor))
...@@ -13393,8 +13317,9 @@ void A_DoNPCSkid(mobj_t *actor) ...@@ -13393,8 +13317,9 @@ void A_DoNPCSkid(mobj_t *actor)
// Otherwise, vertical and horizontal speed // Otherwise, vertical and horizontal speed
// will be multiplied by this. // will be multiplied by this.
// //
void A_DoNPCPain(mobj_t *actor) void A_DoNPCPain(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
fixed_t vspeed = 0; fixed_t vspeed = 0;
...@@ -13444,8 +13369,9 @@ void A_DoNPCPain(mobj_t *actor) ...@@ -13444,8 +13369,9 @@ void A_DoNPCPain(mobj_t *actor)
// var1 = value to set extravalue2 to // var1 = value to set extravalue2 to
// var2 = unused // var2 = unused
// //
void A_PrepareRepeat(mobj_t *actor) void A_PrepareRepeat(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
if (LUA_CallAction(A_PREPAREREPEAT, actor)) if (LUA_CallAction(A_PREPAREREPEAT, actor))
...@@ -13461,8 +13387,9 @@ void A_PrepareRepeat(mobj_t *actor) ...@@ -13461,8 +13387,9 @@ void A_PrepareRepeat(mobj_t *actor)
// var1 = maximum value to setextravalue2 to (normally) // var1 = maximum value to setextravalue2 to (normally)
// var2 = pinch annoyance // var2 = pinch annoyance
// //
void A_Boss5ExtraRepeat(mobj_t *actor) void A_Boss5ExtraRepeat(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
INT32 calc; INT32 calc;
...@@ -13499,8 +13426,9 @@ void A_Boss5ExtraRepeat(mobj_t *actor) ...@@ -13499,8 +13426,9 @@ void A_Boss5ExtraRepeat(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_Boss5Calm(mobj_t *actor) void A_Boss5Calm(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_BOSS5CALM, actor)) if (LUA_CallAction(A_BOSS5CALM, actor))
return; return;
...@@ -13515,8 +13443,9 @@ void A_Boss5Calm(mobj_t *actor) ...@@ -13515,8 +13443,9 @@ void A_Boss5Calm(mobj_t *actor)
// var1 = state to change to upon hitting ground. // var1 = state to change to upon hitting ground.
// var2 = state to change to upon hitting ground if health == pinchhealth, assuming it exists // var2 = state to change to upon hitting ground if health == pinchhealth, assuming it exists
// //
void A_Boss5CheckOnGround(mobj_t *actor) void A_Boss5CheckOnGround(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -13532,7 +13461,7 @@ void A_Boss5CheckOnGround(mobj_t *actor) ...@@ -13532,7 +13461,7 @@ void A_Boss5CheckOnGround(mobj_t *actor)
P_SetMobjState(actor, locvar1); P_SetMobjState(actor, locvar1);
} }
if (actor->tracer && P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y) < 2*actor->radius) if (actor->tracer && P_AreMobjsClose2D(actor->tracer, actor, 2*actor->radius))
{ {
actor->momx = (4*actor->momx)/5; actor->momx = (4*actor->momx)/5;
actor->momy = (4*actor->momy)/5; actor->momy = (4*actor->momy)/5;
...@@ -13546,8 +13475,9 @@ void A_Boss5CheckOnGround(mobj_t *actor) ...@@ -13546,8 +13475,9 @@ void A_Boss5CheckOnGround(mobj_t *actor)
// var1 = state to change to when hitting ground. // var1 = state to change to when hitting ground.
// var2 = state to change to when falling. // var2 = state to change to when falling.
// //
void A_Boss5CheckFalling(mobj_t *actor) void A_Boss5CheckFalling(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -13573,8 +13503,9 @@ void A_Boss5CheckFalling(mobj_t *actor) ...@@ -13573,8 +13503,9 @@ void A_Boss5CheckFalling(mobj_t *actor)
// var1 = object # to shoot // var1 = object # to shoot
// var2 = height offset (from default of +48 FU) // var2 = height offset (from default of +48 FU)
// //
void A_Boss5PinchShot(mobj_t *actor) void A_Boss5PinchShot(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
fixed_t zoffset; fixed_t zoffset;
...@@ -13608,8 +13539,9 @@ void A_Boss5PinchShot(mobj_t *actor) ...@@ -13608,8 +13539,9 @@ void A_Boss5PinchShot(mobj_t *actor)
// var1 = object # to shoot // var1 = object # to shoot
// var2 = height offset (from default of +48 FU) // var2 = height offset (from default of +48 FU)
// //
void A_Boss5MakeItRain(mobj_t *actor) void A_Boss5MakeItRain(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
INT32 offset = (48 + locvar2)<<16; // upper 16 bits, not fixed_t! INT32 offset = (48 + locvar2)<<16; // upper 16 bits, not fixed_t!
...@@ -13643,8 +13575,9 @@ void A_Boss5MakeItRain(mobj_t *actor) ...@@ -13643,8 +13575,9 @@ void A_Boss5MakeItRain(mobj_t *actor)
// var1 = state # to set on MT_BROKENROBOT (if 0 do nothing, if -1 go to if colorized) // var1 = state # to set on MT_BROKENROBOT (if 0 do nothing, if -1 go to if colorized)
// var2 = mode (-1 = spin, 0 = make 1, & 1 make 8, & 2 alart mode) // var2 = mode (-1 = spin, 0 = make 1, & 1 make 8, & 2 alart mode)
// //
void A_Boss5MakeJunk(mobj_t *actor) void A_Boss5MakeJunk(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
mobj_t *broked = NULL; mobj_t *broked = NULL;
...@@ -13660,7 +13593,7 @@ void A_Boss5MakeJunk(mobj_t *actor) ...@@ -13660,7 +13593,7 @@ void A_Boss5MakeJunk(mobj_t *actor)
P_SpawnMobjFromMobj(actor, 0, 0, 0, MT_PROJECTORLIGHT); P_SpawnMobjFromMobj(actor, 0, 0, 0, MT_PROJECTORLIGHT);
actor->z += P_MobjFlip(actor)*actor->height; actor->z += P_MobjFlip(actor)*actor->height;
actor->flags |= MF_NOGRAVITY; actor->flags |= MF_NOGRAVITY;
S_StartSound(actor, sfx_vwre); S_StartSoundFromMobj(actor, sfx_vwre);
actor->extravalue2 = 49; actor->extravalue2 = 49;
P_SetMobjState(actor, -locvar1); P_SetMobjState(actor, -locvar1);
actor->extravalue2 = curextravalue2; actor->extravalue2 = curextravalue2;
...@@ -13726,7 +13659,7 @@ void A_Boss5MakeJunk(mobj_t *actor) ...@@ -13726,7 +13659,7 @@ void A_Boss5MakeJunk(mobj_t *actor)
broked = P_SpawnMobjFromMobj(actor, 0, 0, 64<<FRACBITS, MT_GHOST); broked = P_SpawnMobjFromMobj(actor, 0, 0, 64<<FRACBITS, MT_GHOST);
if (!P_MobjWasRemoved(broked)) if (!P_MobjWasRemoved(broked))
{ {
S_StartSound(broked, sfx_alart); S_StartSoundFromMobj(broked, sfx_alart);
broked->fuse = states[S_FANG_INTRO12].tics+10; broked->fuse = states[S_FANG_INTRO12].tics+10;
P_SetMobjState(broked, S_ALART1); P_SetMobjState(broked, S_ALART1);
} }
...@@ -13735,11 +13668,11 @@ void A_Boss5MakeJunk(mobj_t *actor) ...@@ -13735,11 +13668,11 @@ void A_Boss5MakeJunk(mobj_t *actor)
{ {
if (!P_MobjWasRemoved(broked)) if (!P_MobjWasRemoved(broked))
broked->z += broked->momz; broked->z += broked->momz;
S_StartSound(actor, sfx_s3kccs); S_StartSoundFromMobj(actor, sfx_s3kccs);
actor->flags &= ~MF_NOCLIPTHING; actor->flags &= ~MF_NOCLIPTHING;
} }
else else
S_StartSound(actor, sfx_s3kd3s); S_StartSoundFromMobj(actor, sfx_s3kd3s);
} }
// Function: A_LookForBetter // Function: A_LookForBetter
...@@ -13750,8 +13683,9 @@ void A_Boss5MakeJunk(mobj_t *actor) ...@@ -13750,8 +13683,9 @@ void A_Boss5MakeJunk(mobj_t *actor)
// var1 upper 16 bits = distance limit // var1 upper 16 bits = distance limit
// var2 = unused // var2 = unused
// //
void A_LookForBetter(mobj_t *actor) void A_LookForBetter(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
if (LUA_CallAction(A_LOOKFORBETTER, actor)) if (LUA_CallAction(A_LOOKFORBETTER, actor))
...@@ -13812,8 +13746,9 @@ static void P_DustRing(mobjtype_t mobjtype, UINT32 div, fixed_t x, fixed_t y, fi ...@@ -13812,8 +13746,9 @@ static void P_DustRing(mobjtype_t mobjtype, UINT32 div, fixed_t x, fixed_t y, fi
// var1 = Thing type to spawn as dust // var1 = Thing type to spawn as dust
// var2 = unused // var2 = unused
// //
void A_Boss5BombExplode(mobj_t *actor) void A_Boss5BombExplode(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
if (LUA_CallAction(A_BOSS5BOMBEXPLODE, actor)) if (LUA_CallAction(A_BOSS5BOMBEXPLODE, actor))
...@@ -13860,7 +13795,8 @@ static boolean PIT_DustDevilLaunch(mobj_t *thing) ...@@ -13860,7 +13795,8 @@ static boolean PIT_DustDevilLaunch(mobj_t *thing)
if (abs(thing->x - dustdevil->x) > dustdevil->radius || abs(thing->y - dustdevil->y) > dustdevil->radius) if (abs(thing->x - dustdevil->x) > dustdevil->radius || abs(thing->y - dustdevil->y) > dustdevil->radius)
return true; return true;
if (thing->z + thing->height >= dustdevil->z && dustdevil->z + dustdevil->height >= thing->z) { if (thing->z + thing->height >= dustdevil->z && dustdevil->z + dustdevil->height >= thing->z)
{
fixed_t pos = thing->z - dustdevil->z; fixed_t pos = thing->z - dustdevil->z;
fixed_t thrust = max(FixedDiv(pos, dustdevil->height) * 20, 8 * FRACUNIT); fixed_t thrust = max(FixedDiv(pos, dustdevil->height) * 20, 8 * FRACUNIT);
angle_t fa = R_PointToAngle2(thing->x, thing->y, dustdevil->x, dustdevil->y) >> ANGLETOFINESHIFT; angle_t fa = R_PointToAngle2(thing->x, thing->y, dustdevil->x, dustdevil->y) >> ANGLETOFINESHIFT;
...@@ -13871,7 +13807,7 @@ static boolean PIT_DustDevilLaunch(mobj_t *thing) ...@@ -13871,7 +13807,7 @@ static boolean PIT_DustDevilLaunch(mobj_t *thing)
//Player in the swirl part. //Player in the swirl part.
if (dustdevil->height - pos > thresh) if (dustdevil->height - pos > thresh)
{ {
fixed_t dist = FixedHypot(thing->x - dustdevil->x, thing->y - dustdevil->y); fixed_t dist = P_GetMobjDistance2D(thing, dustdevil);
fixed_t dragamount = player->speed; fixed_t dragamount = player->speed;
fixed_t x, y; fixed_t x, y;
...@@ -13907,7 +13843,7 @@ static boolean PIT_DustDevilLaunch(mobj_t *thing) ...@@ -13907,7 +13843,7 @@ static boolean PIT_DustDevilLaunch(mobj_t *thing)
player->powers[pw_carry] = CR_NONE; player->powers[pw_carry] = CR_NONE;
player->powers[pw_nocontrol] = 0; player->powers[pw_nocontrol] = 0;
P_SetTarget(&thing->tracer, NULL); P_SetTarget(&thing->tracer, NULL);
S_StartSound(thing, sfx_wdjump); S_StartSoundFromMobj(thing, sfx_wdjump);
P_SetMobjState(thing, S_PLAY_FALL); P_SetMobjState(thing, S_PLAY_FALL);
} }
...@@ -13924,8 +13860,9 @@ static boolean PIT_DustDevilLaunch(mobj_t *thing) ...@@ -13924,8 +13860,9 @@ static boolean PIT_DustDevilLaunch(mobj_t *thing)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_DustDevilThink(mobj_t *actor) void A_DustDevilThink(void *data)
{ {
mobj_t *actor = data;
fixed_t scale = actor->scale; fixed_t scale = actor->scale;
mobj_t *layer = actor->tracer; mobj_t *layer = actor->tracer;
INT32 xl, xh, yl, yh; INT32 xl, xh, yl, yh;
...@@ -13935,7 +13872,8 @@ void A_DustDevilThink(mobj_t *actor) ...@@ -13935,7 +13872,8 @@ void A_DustDevilThink(mobj_t *actor)
return; return;
//Chained thinker for the spiralling dust column. //Chained thinker for the spiralling dust column.
while (layer && !P_MobjWasRemoved(layer)) { while (layer && !P_MobjWasRemoved(layer))
{
angle_t fa = layer->angle >> ANGLETOFINESHIFT; angle_t fa = layer->angle >> ANGLETOFINESHIFT;
P_MoveOrigin(layer, layer->x + 5 * FixedMul(scale, FINECOSINE(fa)), layer->y + 5 * FixedMul(scale, FINESINE(fa)), layer->z); P_MoveOrigin(layer, layer->x + 5 * FixedMul(scale, FINECOSINE(fa)), layer->y + 5 * FixedMul(scale, FINESINE(fa)), layer->z);
P_SetScale(layer, scale, true); P_SetScale(layer, scale, true);
...@@ -13947,7 +13885,8 @@ void A_DustDevilThink(mobj_t *actor) ...@@ -13947,7 +13885,8 @@ void A_DustDevilThink(mobj_t *actor)
} }
//Spawn random dust around the column on the base. //Spawn random dust around the column on the base.
if (P_IsObjectOnGround(actor)) { if (P_IsObjectOnGround(actor))
{
angle_t dustang = ((P_RandomRange(0, 7)*ANGLE_45)>>ANGLETOFINESHIFT) & FINEMASK; angle_t dustang = ((P_RandomRange(0, 7)*ANGLE_45)>>ANGLETOFINESHIFT) & FINEMASK;
mobj_t *dust = P_SpawnMobj(actor->x + 96 * FixedMul(scale, FINECOSINE(dustang)), actor->y + 96 * FixedMul(scale, FINESINE(dustang)), actor->z, MT_ARIDDUST); mobj_t *dust = P_SpawnMobj(actor->x + 96 * FixedMul(scale, FINECOSINE(dustang)), actor->y + 96 * FixedMul(scale, FINESINE(dustang)), actor->z, MT_ARIDDUST);
if (!P_MobjWasRemoved(dust)) if (!P_MobjWasRemoved(dust))
...@@ -13958,12 +13897,14 @@ void A_DustDevilThink(mobj_t *actor) ...@@ -13958,12 +13897,14 @@ void A_DustDevilThink(mobj_t *actor)
} }
actor->extravalue1++; actor->extravalue1++;
if (actor->extravalue1 == 12) { if (actor->extravalue1 == 12)
{
size_t i = 0; size_t i = 0;
actor->extravalue1 = 0; actor->extravalue1 = 0;
//Create a set of items for the rising dust column //Create a set of items for the rising dust column
for (; i <= 3; i++) { for (; i <= 3; i++)
{
fixed_t fa = (ANGLE_90*i) >> ANGLETOFINESHIFT; fixed_t fa = (ANGLE_90*i) >> ANGLETOFINESHIFT;
fixed_t px = actor->x + 70 * FixedMul(scale, FINECOSINE(fa)); fixed_t px = actor->x + 70 * FixedMul(scale, FINECOSINE(fa));
fixed_t py = actor->y + 70 * FixedMul(scale, FINESINE(fa)); fixed_t py = actor->y + 70 * FixedMul(scale, FINESINE(fa));
...@@ -13993,11 +13934,11 @@ void A_DustDevilThink(mobj_t *actor) ...@@ -13993,11 +13934,11 @@ void A_DustDevilThink(mobj_t *actor)
dustdevil = actor; dustdevil = actor;
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_DustDevilLaunch); P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_DustDevilLaunch, dustdevil);
//Whirlwind sound effect. //Whirlwind sound effect.
if (leveltime % 70 == 0) if (leveltime % 70 == 0)
S_StartSound(actor, sfx_s3kcel); S_StartSoundFromMobj(actor, sfx_s3kcel);
} }
// stuff used by A_TNTExplode // stuff used by A_TNTExplode
...@@ -14016,7 +13957,7 @@ static boolean PIT_TNTExplode(mobj_t *nearby) ...@@ -14016,7 +13957,7 @@ static boolean PIT_TNTExplode(mobj_t *nearby)
dx = nearby->x - barrel->x; dx = nearby->x - barrel->x;
dy = nearby->y - barrel->y; dy = nearby->y - barrel->y;
dz = nearby->z - barrel->z + (nearby->height - barrel->height/2)/2; dz = nearby->z - barrel->z + (nearby->height - barrel->height/2)/2;
dm = P_AproxDistance(P_AproxDistance(dx, dy), dz); dm = GetDistance3D(0, 0, 0, dx, dy, dz);
if (dm >= exploderadius || !P_CheckSight(barrel, nearby)) // out of range or not visible if (dm >= exploderadius || !P_CheckSight(barrel, nearby)) // out of range or not visible
return true; return true;
...@@ -14026,7 +13967,7 @@ static boolean PIT_TNTExplode(mobj_t *nearby) ...@@ -14026,7 +13967,7 @@ static boolean PIT_TNTExplode(mobj_t *nearby)
if (nearby->state == &states[nearby->info->spawnstate]) if (nearby->state == &states[nearby->info->spawnstate])
{ {
if (barrel->info->attacksound) if (barrel->info->attacksound)
S_StartSound(nearby, barrel->info->attacksound); S_StartSoundFromMobj(nearby, barrel->info->attacksound);
nearby->momx = FixedMul(FixedDiv(dx, dm), explodethrust); nearby->momx = FixedMul(FixedDiv(dx, dm), explodethrust);
nearby->momy = FixedMul(FixedDiv(dy, dm), explodethrust); nearby->momy = FixedMul(FixedDiv(dy, dm), explodethrust);
nearby->momz = FixedMul(FixedDiv(dz, dm), explodethrust); nearby->momz = FixedMul(FixedDiv(dz, dm), explodethrust);
...@@ -14070,8 +14011,9 @@ static boolean PIT_TNTExplode(mobj_t *nearby) ...@@ -14070,8 +14011,9 @@ static boolean PIT_TNTExplode(mobj_t *nearby)
// var1 = Thing type to spawn as dust. // var1 = Thing type to spawn as dust.
// var2 = unused // var2 = unused
// //
void A_TNTExplode(mobj_t *actor) void A_TNTExplode(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 xl, xh, yl, yh; INT32 xl, xh, yl, yh;
static mappoint_t epicenter = {0,0,0}; static mappoint_t epicenter = {0,0,0};
...@@ -14095,7 +14037,7 @@ void A_TNTExplode(mobj_t *actor) ...@@ -14095,7 +14037,7 @@ void A_TNTExplode(mobj_t *actor)
P_SetThingPosition(actor); P_SetThingPosition(actor);
actor->flags2 = MF2_EXPLOSION; actor->flags2 = MF2_EXPLOSION;
if (actor->info->deathsound) if (actor->info->deathsound)
S_StartSound(actor, actor->info->deathsound); S_StartSoundFromMobj(actor, actor->info->deathsound);
explodethrust = 32*FRACUNIT; explodethrust = 32*FRACUNIT;
exploderadius = 256*FRACUNIT; exploderadius = 256*FRACUNIT;
...@@ -14109,7 +14051,7 @@ void A_TNTExplode(mobj_t *actor) ...@@ -14109,7 +14051,7 @@ void A_TNTExplode(mobj_t *actor)
barrel = actor; barrel = actor;
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_TNTExplode); P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_TNTExplode, barrel);
// cause a quake -- P_StartQuake does not exist yet // cause a quake -- P_StartQuake does not exist yet
epicenter.x = actor->x; epicenter.x = actor->x;
...@@ -14136,8 +14078,9 @@ void A_TNTExplode(mobj_t *actor) ...@@ -14136,8 +14078,9 @@ void A_TNTExplode(mobj_t *actor)
// var1 = Frame range. // var1 = Frame range.
// var2 = unused // var2 = unused
// //
void A_DebrisRandom(mobj_t *actor) void A_DebrisRandom(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
if (LUA_CallAction(A_DEBRISRANDOM, actor)) if (LUA_CallAction(A_DEBRISRANDOM, actor))
...@@ -14170,8 +14113,9 @@ static mobj_t *P_TrainSeg(mobj_t *src, fixed_t x, fixed_t y, fixed_t z, angle_t ...@@ -14170,8 +14113,9 @@ static mobj_t *P_TrainSeg(mobj_t *src, fixed_t x, fixed_t y, fixed_t z, angle_t
// var1 = Train width. // var1 = Train width.
// var2 = Train length. // var2 = Train length.
// //
void A_TrainCameo(mobj_t *actor) void A_TrainCameo(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
fixed_t x = actor->x; fixed_t x = actor->x;
...@@ -14209,8 +14153,9 @@ void A_TrainCameo(mobj_t *actor) ...@@ -14209,8 +14153,9 @@ void A_TrainCameo(mobj_t *actor)
// var1 = Train width. // var1 = Train width.
// var2 = Train length. // var2 = Train length.
// //
void A_TrainCameo2(mobj_t *actor) void A_TrainCameo2(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
fixed_t x = actor->x; fixed_t x = actor->x;
...@@ -14243,8 +14188,9 @@ void A_TrainCameo2(mobj_t *actor) ...@@ -14243,8 +14188,9 @@ void A_TrainCameo2(mobj_t *actor)
// var1 = Mobj type. // var1 = Mobj type.
// var2 = Unused // var2 = Unused
// //
void A_CanarivoreGas(mobj_t *actor) void A_CanarivoreGas(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
if (LUA_CallAction(A_CANARIVOREGAS, actor)) if (LUA_CallAction(A_CANARIVOREGAS, actor))
...@@ -14262,8 +14208,9 @@ void A_CanarivoreGas(mobj_t *actor) ...@@ -14262,8 +14208,9 @@ void A_CanarivoreGas(mobj_t *actor)
// var1 = Fuse (if 0, default to TICRATE/2). // var1 = Fuse (if 0, default to TICRATE/2).
// var2 = Unused // var2 = Unused
// //
void A_KillSegments(mobj_t *actor) void A_KillSegments(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
mobj_t *seg = actor->tracer; mobj_t *seg = actor->tracer;
INT32 fuse = locvar1 ? locvar1 : TICRATE/2; INT32 fuse = locvar1 ? locvar1 : TICRATE/2;
...@@ -14347,8 +14294,9 @@ static void P_SnapperLegPlace(mobj_t *mo) ...@@ -14347,8 +14294,9 @@ static void P_SnapperLegPlace(mobj_t *mo)
// var1 = Leg mobj type. // var1 = Leg mobj type.
// var2 = Head mobj type. // var2 = Head mobj type.
// //
void A_SnapperSpawn(mobj_t *actor) void A_SnapperSpawn(void *data)
{ {
mobj_t *actor = data;
mobjtype_t legtype = (mobjtype_t)var1; mobjtype_t legtype = (mobjtype_t)var1;
mobjtype_t headtype = (mobjtype_t)var2; mobjtype_t headtype = (mobjtype_t)var2;
mobj_t *ptr = actor; mobj_t *ptr = actor;
...@@ -14404,8 +14352,9 @@ void A_SnapperSpawn(mobj_t *actor) ...@@ -14404,8 +14352,9 @@ void A_SnapperSpawn(mobj_t *actor)
// var1 = Unused // var1 = Unused
// var2 = Unused // var2 = Unused
// //
void A_SnapperThinker(mobj_t *actor) void A_SnapperThinker(void *data)
{ {
mobj_t *actor = data;
fixed_t x0 = actor->x; fixed_t x0 = actor->x;
fixed_t y0 = actor->y; fixed_t y0 = actor->y;
fixed_t xs, ys; fixed_t xs, ys;
...@@ -14430,7 +14379,7 @@ void A_SnapperThinker(mobj_t *actor) ...@@ -14430,7 +14379,7 @@ void A_SnapperThinker(mobj_t *actor)
// Look for nearby, valid players to chase angrily at. // Look for nearby, valid players to chase angrily at.
if ((actor->target || P_LookForPlayers(actor, true, false, 1024*FRACUNIT)) if ((actor->target || P_LookForPlayers(actor, true, false, 1024*FRACUNIT))
&& P_AproxDistance(actor->target->x - xs, actor->target->y - ys) < 2048*FRACUNIT && ArePointsClose2D(xs, ys, actor->target->x, actor->target->y, 2048*FRACUNIT)
&& abs(actor->target->z - actor->z) < 80*FRACUNIT && abs(actor->target->z - actor->z) < 80*FRACUNIT
&& P_CheckSight(actor, actor->target)) && P_CheckSight(actor, actor->target))
{ {
...@@ -14445,7 +14394,7 @@ void A_SnapperThinker(mobj_t *actor) ...@@ -14445,7 +14394,7 @@ void A_SnapperThinker(mobj_t *actor)
y1 = ys; y1 = ys;
} }
dist = P_AproxDistance(x1 - x0, y1 - y0); dist = GetDistance2D(x0, y0, x1, y1);
// The snapper either chases what it considers to be a nearby player, or instead decides to go back to its spawnpoint. // The snapper either chases what it considers to be a nearby player, or instead decides to go back to its spawnpoint.
if (chasing || dist > 32*FRACUNIT) if (chasing || dist > 32*FRACUNIT)
...@@ -14515,6 +14464,10 @@ void A_SnapperThinker(mobj_t *actor) ...@@ -14515,6 +14464,10 @@ void A_SnapperThinker(mobj_t *actor)
actor->extravalue1 -= speed; actor->extravalue1 -= speed;
} }
} }
else
{
P_SetTarget(&actor->target, NULL);
}
P_SnapperLegPlace(actor); P_SnapperLegPlace(actor);
} }
...@@ -14526,8 +14479,9 @@ void A_SnapperThinker(mobj_t *actor) ...@@ -14526,8 +14479,9 @@ void A_SnapperThinker(mobj_t *actor)
// var1 = mobjtype for sides // var1 = mobjtype for sides
// var2 = distance sides should be placed apart // var2 = distance sides should be placed apart
// //
void A_SaloonDoorSpawn(mobj_t *actor) void A_SaloonDoorSpawn(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
angle_t ang = actor->angle; angle_t ang = actor->angle;
...@@ -14567,8 +14521,9 @@ void A_SaloonDoorSpawn(mobj_t *actor) ...@@ -14567,8 +14521,9 @@ void A_SaloonDoorSpawn(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_MinecartSparkThink(mobj_t *actor) void A_MinecartSparkThink(void *data)
{ {
mobj_t *actor = data;
fixed_t dx = actor->momx; fixed_t dx = actor->momx;
fixed_t dy = actor->momy; fixed_t dy = actor->momy;
fixed_t dz, dm; fixed_t dz, dm;
...@@ -14581,7 +14536,7 @@ void A_MinecartSparkThink(mobj_t *actor) ...@@ -14581,7 +14536,7 @@ void A_MinecartSparkThink(mobj_t *actor)
actor->momz = P_RandomRange(2, 4)*FRACUNIT; actor->momz = P_RandomRange(2, 4)*FRACUNIT;
dz = actor->momz; dz = actor->momz;
dm = FixedHypot(FixedHypot(dx, dy), dz); dm = GetDistance3D(0, 0, 0, dx, dy, dz);
dx = FixedDiv(dx, dm); dx = FixedDiv(dx, dm);
dy = FixedDiv(dy, dm); dy = FixedDiv(dy, dm);
dz = FixedDiv(dz, dm); dz = FixedDiv(dz, dm);
...@@ -14604,8 +14559,9 @@ void A_MinecartSparkThink(mobj_t *actor) ...@@ -14604,8 +14559,9 @@ void A_MinecartSparkThink(mobj_t *actor)
// var1 = Modulo // var1 = Modulo
// var2 = State // var2 = State
// //
void A_ModuloToState(mobj_t *actor) void A_ModuloToState(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -14624,8 +14580,9 @@ void A_ModuloToState(mobj_t *actor) ...@@ -14624,8 +14580,9 @@ void A_ModuloToState(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_LavafallRocks(mobj_t *actor) void A_LavafallRocks(void *data)
{ {
mobj_t *actor = data;
UINT8 i; UINT8 i;
if (LUA_CallAction(A_LAVAFALLROCKS, actor)) if (LUA_CallAction(A_LAVAFALLROCKS, actor))
...@@ -14633,8 +14590,8 @@ void A_LavafallRocks(mobj_t *actor) ...@@ -14633,8 +14590,8 @@ void A_LavafallRocks(mobj_t *actor)
// Don't spawn rocks unless a player is relatively close by. // Don't spawn rocks unless a player is relatively close by.
for (i = 0; i < MAXPLAYERS; ++i) for (i = 0; i < MAXPLAYERS; ++i)
if (playeringame[i] && players[i].mo if (players[i].ingame && players[i].mo
&& P_AproxDistance(actor->x - players[i].mo->x, actor->y - players[i].mo->y) < (actor->info->speed >> 1)) && P_AreMobjsClose2D(actor, players[i].mo, actor->info->speed >> 1))
break; // Stop looking. break; // Stop looking.
if (i < MAXPLAYERS) if (i < MAXPLAYERS)
...@@ -14654,21 +14611,22 @@ void A_LavafallRocks(mobj_t *actor) ...@@ -14654,21 +14611,22 @@ void A_LavafallRocks(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_LavafallLava(mobj_t *actor) void A_LavafallLava(void *data)
{ {
mobj_t *actor = data;
mobj_t *lavafall; mobj_t *lavafall;
UINT8 i; UINT8 i;
if (LUA_CallAction(A_LAVAFALLLAVA, actor)) if (LUA_CallAction(A_LAVAFALLLAVA, actor))
return; return;
if ((40 - actor->fuse) % (2*(actor->scale >> FRACBITS))) if ((40 - actor->fuse) % max(2*(actor->scale >> FRACBITS), 1)) // avoid crashes if actor->scale < FRACUNIT
return; return;
// Don't spawn lava unless a player is nearby. // Don't spawn lava unless a player is nearby.
for (i = 0; i < MAXPLAYERS; ++i) for (i = 0; i < MAXPLAYERS; ++i)
if (playeringame[i] && players[i].mo if (players[i].ingame && players[i].mo
&& P_AproxDistance(actor->x - players[i].mo->x, actor->y - players[i].mo->y) < (actor->info->speed)) && P_AreMobjsClose2D(actor, players[i].mo, actor->info->speed))
break; // Stop looking. break; // Stop looking.
if (i >= MAXPLAYERS) if (i >= MAXPLAYERS)
...@@ -14686,8 +14644,9 @@ void A_LavafallLava(mobj_t *actor) ...@@ -14686,8 +14644,9 @@ void A_LavafallLava(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_FallingLavaCheck(mobj_t *actor) void A_FallingLavaCheck(void *data)
{ {
mobj_t *actor = data;
if (LUA_CallAction(A_FALLINGLAVACHECK, actor)) if (LUA_CallAction(A_FALLINGLAVACHECK, actor))
return; return;
...@@ -14708,8 +14667,9 @@ void A_FallingLavaCheck(mobj_t *actor) ...@@ -14708,8 +14667,9 @@ void A_FallingLavaCheck(mobj_t *actor)
// var1 = Scale to shrink to // var1 = Scale to shrink to
// var2 = Shrinking speed // var2 = Shrinking speed
// //
void A_FireShrink(mobj_t *actor) void A_FireShrink(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -14735,8 +14695,9 @@ void A_FireShrink(mobj_t *actor) ...@@ -14735,8 +14695,9 @@ void A_FireShrink(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_SpawnPterabytes(mobj_t *actor) void A_SpawnPterabytes(void *data)
{ {
mobj_t *actor = data;
mobj_t *waypoint, *ptera; mobj_t *waypoint, *ptera;
fixed_t c, s; fixed_t c, s;
fixed_t rad = 280*FRACUNIT; fixed_t rad = 280*FRACUNIT;
...@@ -14785,8 +14746,9 @@ void A_SpawnPterabytes(mobj_t *actor) ...@@ -14785,8 +14746,9 @@ void A_SpawnPterabytes(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_PterabyteHover(mobj_t *actor) void A_PterabyteHover(void *data)
{ {
mobj_t *actor = data;
angle_t ang, fa; angle_t ang, fa;
if (LUA_CallAction(A_PTERABYTEHOVER, actor)) if (LUA_CallAction(A_PTERABYTEHOVER, actor))
...@@ -14806,8 +14768,9 @@ void A_PterabyteHover(mobj_t *actor) ...@@ -14806,8 +14768,9 @@ void A_PterabyteHover(mobj_t *actor)
// var1 = Distance currently spawned rock should travel before spawning a new one // var1 = Distance currently spawned rock should travel before spawning a new one
// var2 = Object type to spawn // var2 = Object type to spawn
// //
void A_RolloutSpawn(mobj_t *actor) void A_RolloutSpawn(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
...@@ -14816,7 +14779,7 @@ void A_RolloutSpawn(mobj_t *actor) ...@@ -14816,7 +14779,7 @@ void A_RolloutSpawn(mobj_t *actor)
if (!(actor->target) if (!(actor->target)
|| P_MobjWasRemoved(actor->target) || P_MobjWasRemoved(actor->target)
|| P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) > locvar1) || P_AreMobjsFar2D(actor, actor->target, locvar1))
{ {
P_SetTarget(&actor->target, P_SpawnMobj(actor->x, actor->y, actor->z, locvar2)); P_SetTarget(&actor->target, P_SpawnMobj(actor->x, actor->y, actor->z, locvar2));
if (!P_MobjWasRemoved(actor->target)) if (!P_MobjWasRemoved(actor->target))
...@@ -14840,14 +14803,15 @@ void A_RolloutSpawn(mobj_t *actor) ...@@ -14840,14 +14803,15 @@ void A_RolloutSpawn(mobj_t *actor)
// var1 = Drag // var1 = Drag
// var2 = Vertical bobbing speed factor // var2 = Vertical bobbing speed factor
// //
void A_RolloutRock(mobj_t *actor) void A_RolloutRock(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
UINT8 maxframes = actor->info->reactiontime; // number of frames the mobj cycles through UINT8 maxframes = actor->info->reactiontime; // number of frames the mobj cycles through
fixed_t pi = (22*FRACUNIT/7); fixed_t pi = (22*FRACUNIT/7);
fixed_t circumference = FixedMul(2 * pi, actor->radius); // used to calculate when to change frame fixed_t circumference = FixedMul(2 * pi, actor->radius); // used to calculate when to change frame
fixed_t speed = P_AproxDistance(actor->momx, actor->momy), topspeed = FixedMul(actor->info->speed, actor->scale); fixed_t speed = P_GetMobjMomentum2D(actor), topspeed = FixedMul(actor->info->speed, actor->scale);
boolean inwater = actor->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER); boolean inwater = actor->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER);
if (LUA_CallAction(A_ROLLOUTROCK, actor)) if (LUA_CallAction(A_ROLLOUTROCK, actor))
...@@ -14855,16 +14819,22 @@ void A_RolloutRock(mobj_t *actor) ...@@ -14855,16 +14819,22 @@ void A_RolloutRock(mobj_t *actor)
if (!actor->tracer || P_MobjWasRemoved(actor->tracer) || !actor->tracer->health) if (!actor->tracer || P_MobjWasRemoved(actor->tracer) || !actor->tracer->health)
actor->flags |= MF_PUSHABLE; actor->flags |= MF_PUSHABLE;
else if (actor->tracer->eflags & MFE_VERTICALFLIP)
{
actor->flags2 |= MF2_OBJECTFLIP;
actor->eflags |= MFE_VERTICALFLIP;
}
else else
{ {
actor->flags2 = (actor->flags2 & ~MF2_OBJECTFLIP) | (actor->tracer->flags2 & MF2_OBJECTFLIP); actor->flags2 &= ~MF2_OBJECTFLIP;
actor->eflags = (actor->eflags & ~MFE_VERTICALFLIP) | (actor->tracer->eflags & MFE_VERTICALFLIP); actor->eflags &= ~MFE_VERTICALFLIP;
} }
actor->friction = FRACUNIT; // turns out riding on solids sucks, so let's just make it easier on ourselves actor->friction = FRACUNIT; // turns out riding on solids sucks, so let's just make it easier on ourselves
if (actor->eflags & MFE_JUSTHITFLOOR) if (actor->eflags & MFE_JUSTHITFLOOR)
S_StartSound(actor, actor->info->painsound); S_StartSoundFromMobj(actor, actor->info->painsound);
if (actor->threshold) if (actor->threshold)
actor->threshold--; actor->threshold--;
...@@ -14878,9 +14848,9 @@ void A_RolloutRock(mobj_t *actor) ...@@ -14878,9 +14848,9 @@ void A_RolloutRock(mobj_t *actor)
if (flip*prevmomz < 0 && flip*actor->momz >= 0 && !actor->threshold) if (flip*prevmomz < 0 && flip*actor->momz >= 0 && !actor->threshold)
{ {
if (actor->eflags & MFE_UNDERWATER) if (actor->eflags & MFE_UNDERWATER)
S_StartSound(actor, sfx_splash); S_StartSoundFromMobj(actor, sfx_splash);
else if (!actor->threshold) else if (!actor->threshold)
S_StartSound(actor, sfx_splish); S_StartSoundFromMobj(actor, sfx_splish);
actor->threshold = max((topspeed - speed) >> FRACBITS, 8); actor->threshold = max((topspeed - speed) >> FRACBITS, 8);
} }
} }
...@@ -14897,7 +14867,7 @@ void A_RolloutRock(mobj_t *actor) ...@@ -14897,7 +14867,7 @@ void A_RolloutRock(mobj_t *actor)
actor->momy = FixedMul(actor->momy, locvar1); actor->momy = FixedMul(actor->momy, locvar1);
} }
speed = P_AproxDistance(actor->momx, actor->momy); // recalculate speed for visual rolling speed = P_GetMobjMomentum2D(actor); // recalculate speed for visual rolling
if (((actor->flags & MF_PUSHABLE) || !(actor->flags2 & MF2_STRONGBOX)) if (((actor->flags & MF_PUSHABLE) || !(actor->flags2 & MF2_STRONGBOX))
&& speed < actor->scale) // stop moving if speed is insignificant && speed < actor->scale) // stop moving if speed is insignificant
...@@ -14934,8 +14904,9 @@ void A_RolloutRock(mobj_t *actor) ...@@ -14934,8 +14904,9 @@ void A_RolloutRock(mobj_t *actor)
// var1 = Tail segments to spawn // var1 = Tail segments to spawn
// var2 = unused // var2 = unused
// //
void A_DragonbomberSpawn(mobj_t *actor) void A_DragonbomberSpawn(void *data)
{ {
mobj_t *actor = data;
UINT8 i; UINT8 i;
mobj_t *mo = actor; mobj_t *mo = actor;
...@@ -14974,8 +14945,9 @@ void A_DragonbomberSpawn(mobj_t *actor) ...@@ -14974,8 +14945,9 @@ void A_DragonbomberSpawn(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_DragonWing(mobj_t *actor) void A_DragonWing(void *data)
{ {
mobj_t *actor = data;
mobj_t *target = actor->target; mobj_t *target = actor->target;
fixed_t x, y; fixed_t x, y;
...@@ -15000,8 +14972,9 @@ void A_DragonWing(mobj_t *actor) ...@@ -15000,8 +14972,9 @@ void A_DragonWing(mobj_t *actor)
// var1 = unused // var1 = unused
// var2 = unused // var2 = unused
// //
void A_DragonSegment(mobj_t *actor) void A_DragonSegment(void *data)
{ {
mobj_t *actor = data;
mobj_t *target = actor->target; mobj_t *target = actor->target;
fixed_t dist; fixed_t dist;
fixed_t radius; fixed_t radius;
...@@ -15021,7 +14994,7 @@ void A_DragonSegment(mobj_t *actor) ...@@ -15021,7 +14994,7 @@ void A_DragonSegment(mobj_t *actor)
return; return;
} }
dist = P_AproxDistance(P_AproxDistance(actor->x - target->x, actor->y - target->y), actor->z - target->z); dist = P_GetMobjDistance3D(target, actor);
radius = actor->radius + target->radius; radius = actor->radius + target->radius;
hangle = R_PointToAngle2(target->x, target->y, actor->x, actor->y); hangle = R_PointToAngle2(target->x, target->y, actor->x, actor->y);
zangle = R_PointToAngle2(0, target->z, dist, actor->z); zangle = R_PointToAngle2(0, target->z, dist, actor->z);
...@@ -15043,8 +15016,9 @@ void A_DragonSegment(mobj_t *actor) ...@@ -15043,8 +15016,9 @@ void A_DragonSegment(mobj_t *actor)
// &1: height is absolute // &1: height is absolute
// &2: scale with actor's scale // &2: scale with actor's scale
// //
void A_ChangeHeight(mobj_t *actor) void A_ChangeHeight(void *data)
{ {
mobj_t *actor = data;
INT32 locvar1 = var1; INT32 locvar1 = var1;
INT32 locvar2 = var2; INT32 locvar2 = var2;
fixed_t height = locvar1; fixed_t height = locvar1;
......
...@@ -228,7 +228,7 @@ void T_MoveFloor(floormove_t *movefloor) ...@@ -228,7 +228,7 @@ void T_MoveFloor(floormove_t *movefloor)
movefloor->direction = -1; movefloor->direction = -1;
movefloor->speed = lines[movefloor->sourceline].args[3] << (FRACBITS - 2); movefloor->speed = lines[movefloor->sourceline].args[3] << (FRACBITS - 2);
movefloor->sector->soundorg.z = movefloor->sector->floorheight; movefloor->sector->soundorg.z = movefloor->sector->floorheight;
S_StartSound(&movefloor->sector->soundorg, sfx_pstop); S_StartSoundFromSector(movefloor->sector, sfx_pstop);
remove = false; remove = false;
} }
else else
...@@ -408,7 +408,7 @@ void T_MoveElevator(elevator_t *elevator) ...@@ -408,7 +408,7 @@ void T_MoveElevator(elevator_t *elevator)
/* /*
// make floor move sound // make floor move sound
if (!(leveltime&7)) if (!(leveltime&7))
S_StartSound(&elevator->sector->soundorg, sfx_stnmov); S_StartSoundFromMobj(&elevator->sector->soundorg, sfx_stnmov);
*/ */
if (res == pastdest || res == crushed) // if destination height acheived if (res == pastdest || res == crushed) // if destination height acheived
{ {
...@@ -486,7 +486,7 @@ void T_MoveElevator(elevator_t *elevator) ...@@ -486,7 +486,7 @@ void T_MoveElevator(elevator_t *elevator)
dontupdate = true; dontupdate = true;
} }
// make floor stop sound // make floor stop sound
// S_StartSound(&elevator->sector->soundorg, sfx_pstop); // S_StartSoundFromMobj(&elevator->sector->soundorg, sfx_pstop);
} }
if (!dontupdate) if (!dontupdate)
{ {
...@@ -677,9 +677,8 @@ void T_BounceCheese(bouncecheese_t *bouncer) ...@@ -677,9 +677,8 @@ void T_BounceCheese(bouncecheese_t *bouncer)
bouncer->low = !bouncer->low; bouncer->low = !bouncer->low;
if (abs(bouncer->speed) > 6*FRACUNIT) if (abs(bouncer->speed) > 6*FRACUNIT)
{ {
mobj_t *mp = (void *)&actionsector->soundorg;
actionsector->soundorg.z = bouncer->sector->floorheight; actionsector->soundorg.z = bouncer->sector->floorheight;
S_StartSound(mp, sfx_splash); S_StartSoundFromSector(actionsector, sfx_splash);
} }
} }
...@@ -1096,7 +1095,7 @@ void T_ThwompSector(thwomp_t *thwomp) ...@@ -1096,7 +1095,7 @@ void T_ThwompSector(thwomp_t *thwomp)
if (players[i].mo->z > thwomp->sector->ceilingheight) if (players[i].mo->z > thwomp->sector->ceilingheight)
continue; continue;
if (P_AproxDistance(thwompx - players[i].mo->x, thwompy - players[i].mo->y) > 96*FRACUNIT) if (ArePointsFar2D(thwompx, thwompy, players[i].mo->x, players[i].mo->y, 96*FRACUNIT))
continue; continue;
thwomp->direction = -1; thwomp->direction = -1;
...@@ -1178,7 +1177,7 @@ void T_ThwompSector(thwomp_t *thwomp) ...@@ -1178,7 +1177,7 @@ void T_ThwompSector(thwomp_t *thwomp)
if (res == pastdest) if (res == pastdest)
{ {
if (rover->fofflags & FOF_EXISTS) if (rover->fofflags & FOF_EXISTS)
S_StartSound((void *)&actionsector->soundorg, thwomp->sound); S_StartSoundFromSector(actionsector, thwomp->sound);
thwomp->direction = 1; // start heading back up thwomp->direction = 1; // start heading back up
thwomp->delay = TICRATE; // but only after a small delay thwomp->delay = TICRATE; // but only after a small delay
...@@ -1625,7 +1624,7 @@ void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype) ...@@ -1625,7 +1624,7 @@ void EV_DoFloor(mtag_t tag, line_t *line, floor_e floortype)
sec->floordata = dofloor; sec->floordata = dofloor;
// set up some generic aspects of the floormove_t // set up some generic aspects of the floormove_t
dofloor->thinker.function.acp1 = (actionf_p1)T_MoveFloor; dofloor->thinker.function = (actionf_p1)T_MoveFloor;
dofloor->type = floortype; dofloor->type = floortype;
dofloor->crush = false; // default: types that crush will change this dofloor->crush = false; // default: types that crush will change this
dofloor->sector = sec; dofloor->sector = sec;
...@@ -1760,7 +1759,7 @@ void EV_DoElevator(mtag_t tag, line_t *line, elevator_e elevtype) ...@@ -1760,7 +1759,7 @@ void EV_DoElevator(mtag_t tag, line_t *line, elevator_e elevtype)
P_AddThinker(THINK_MAIN, &elevator->thinker); P_AddThinker(THINK_MAIN, &elevator->thinker);
sec->floordata = elevator; sec->floordata = elevator;
sec->ceilingdata = elevator; sec->ceilingdata = elevator;
elevator->thinker.function.acp1 = (actionf_p1)T_MoveElevator; elevator->thinker.function = (actionf_p1)T_MoveElevator;
elevator->type = elevtype; elevator->type = elevtype;
elevator->sourceline = line; elevator->sourceline = line;
elevator->distance = 1; // Always crush unless otherwise elevator->distance = 1; // Always crush unless otherwise
...@@ -1884,7 +1883,7 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover) ...@@ -1884,7 +1883,7 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
} }
sec->soundorg.z = (controlsec->floorheight + controlsec->ceilingheight)/2; sec->soundorg.z = (controlsec->floorheight + controlsec->ceilingheight)/2;
S_StartSound(&sec->soundorg, mobjinfo[type].activesound); S_StartSoundFromSector(sec, mobjinfo[type].activesound);
#undef controlsec #undef controlsec
...@@ -1941,7 +1940,7 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover) ...@@ -1941,7 +1940,7 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover)
if (fromcenter) if (fromcenter)
{ {
P_InstaThrust(spawned, R_PointToAngle2(sec->soundorg.x, sec->soundorg.y, a, b), FixedDiv(P_AproxDistance(a - sec->soundorg.x, b - sec->soundorg.y), widthfactor)); P_InstaThrust(spawned, R_PointToAngle2(sec->soundorg.x, sec->soundorg.y, a, b), FixedDiv(GetDistance2D(a, b, sec->soundorg.x, sec->soundorg.y), widthfactor));
P_SetObjectMomZ(spawned, FixedDiv((c - bottomz), heightfactor), false); P_SetObjectMomZ(spawned, FixedDiv((c - bottomz), heightfactor), false);
} }
...@@ -1970,7 +1969,7 @@ void EV_BounceSector(sector_t *sec, fixed_t momz, line_t *sourceline) ...@@ -1970,7 +1969,7 @@ void EV_BounceSector(sector_t *sec, fixed_t momz, line_t *sourceline)
bouncer = Z_Calloc(sizeof (*bouncer), PU_LEVSPEC, NULL); bouncer = Z_Calloc(sizeof (*bouncer), PU_LEVSPEC, NULL);
P_AddThinker(THINK_MAIN, &bouncer->thinker); P_AddThinker(THINK_MAIN, &bouncer->thinker);
sec->ceilingdata = bouncer; sec->ceilingdata = bouncer;
bouncer->thinker.function.acp1 = (actionf_p1)T_BounceCheese; bouncer->thinker.function = (actionf_p1)T_BounceCheese;
// set up the fields according to the type of elevator action // set up the fields according to the type of elevator action
bouncer->sourceline = sourceline; bouncer->sourceline = sourceline;
...@@ -1996,7 +1995,7 @@ void EV_DoContinuousFall(sector_t *sec, sector_t *backsector, fixed_t spd, boole ...@@ -1996,7 +1995,7 @@ void EV_DoContinuousFall(sector_t *sec, sector_t *backsector, fixed_t spd, boole
// create and initialize new thinker // create and initialize new thinker
faller = Z_Calloc(sizeof (*faller), PU_LEVSPEC, NULL); faller = Z_Calloc(sizeof (*faller), PU_LEVSPEC, NULL);
P_AddThinker(THINK_MAIN, &faller->thinker); P_AddThinker(THINK_MAIN, &faller->thinker);
faller->thinker.function.acp1 = (actionf_p1)T_ContinuousFalling; faller->thinker.function = (actionf_p1)T_ContinuousFalling;
// set up the fields // set up the fields
faller->sector = sec; faller->sector = sec;
...@@ -2032,7 +2031,7 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating, ...@@ -2032,7 +2031,7 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
// create and initialize new crumble thinker // create and initialize new crumble thinker
crumble = Z_Calloc(sizeof (*crumble), PU_LEVSPEC, NULL); crumble = Z_Calloc(sizeof (*crumble), PU_LEVSPEC, NULL);
P_AddThinker(THINK_MAIN, &crumble->thinker); P_AddThinker(THINK_MAIN, &crumble->thinker);
crumble->thinker.function.acp1 = (actionf_p1)T_StartCrumble; crumble->thinker.function = (actionf_p1)T_StartCrumble;
// set up the fields // set up the fields
crumble->sector = sec; crumble->sector = sec;
...@@ -2098,7 +2097,7 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher) ...@@ -2098,7 +2097,7 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
thing = SearchMarioNode(roversec->touching_thinglist); thing = SearchMarioNode(roversec->touching_thinglist);
if (!thing) if (!thing)
S_StartSound(puncher, sfx_mario1); // "Thunk!" sound - puncher is "close enough". S_StartSoundFromMobj(puncher, sfx_mario1); // "Thunk!" sound - puncher is "close enough".
else // Found something! else // Found something!
{ {
const boolean itsamonitor = (thing->flags & MF_MONITOR) == MF_MONITOR; const boolean itsamonitor = (thing->flags & MF_MONITOR) == MF_MONITOR;
...@@ -2108,7 +2107,7 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher) ...@@ -2108,7 +2107,7 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
P_AddThinker(THINK_MAIN, &block->thinker); P_AddThinker(THINK_MAIN, &block->thinker);
roversec->floordata = block; roversec->floordata = block;
roversec->ceilingdata = block; roversec->ceilingdata = block;
block->thinker.function.acp1 = (actionf_p1)T_MarioBlock; block->thinker.function = (actionf_p1)T_MarioBlock;
// Set up the fields // Set up the fields
block->sector = roversec; block->sector = roversec;
...@@ -2142,12 +2141,12 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher) ...@@ -2142,12 +2141,12 @@ void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
thing->momz = FixedMul(3*FRACUNIT, thing->scale); thing->momz = FixedMul(3*FRACUNIT, thing->scale);
P_TouchSpecialThing(thing, puncher, false); P_TouchSpecialThing(thing, puncher, false);
// "Thunk!" sound // "Thunk!" sound
S_StartSound(puncher, sfx_mario1); // Puncher is "close enough" S_StartSoundFromMobj(puncher, sfx_mario1); // Puncher is "close enough"
} }
else else
{ {
// "Powerup rise" sound // "Powerup rise" sound
S_StartSound(puncher, sfx_mario9); // Puncher is "close enough" S_StartSoundFromMobj(puncher, sfx_mario9); // Puncher is "close enough"
} }
if (itsamonitor && thing) if (itsamonitor && thing)
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // 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 // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -101,7 +101,7 @@ void P_ClearStarPost(INT32 postnum) ...@@ -101,7 +101,7 @@ void P_ClearStarPost(INT32 postnum)
// scan the thinkers // scan the thinkers
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) 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; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -130,7 +130,7 @@ void P_ResetStarposts(void) ...@@ -130,7 +130,7 @@ void P_ResetStarposts(void)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) 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; continue;
post = (mobj_t *)th; post = (mobj_t *)th;
...@@ -242,7 +242,7 @@ void P_DoNightsScore(player_t *player) ...@@ -242,7 +242,7 @@ void P_DoNightsScore(player_t *player)
{ {
INT32 i; INT32 i;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i]) if (players[i].ingame)
{ {
if (++players[i].linkcount > players[i].maxlink) if (++players[i].linkcount > players[i].maxlink)
players[i].maxlink = players[i].linkcount; players[i].maxlink = players[i].linkcount;
...@@ -319,7 +319,7 @@ void P_DoMatchSuper(player_t *player) ...@@ -319,7 +319,7 @@ void P_DoMatchSuper(player_t *player)
// Check everyone else on your team for emeralds, and turn those helpful assisting players invincible too. // Check everyone else on your team for emeralds, and turn those helpful assisting players invincible too.
if (doteams) if (doteams)
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].ctfteam == player->ctfteam if (players[i].ingame && players[i].ctfteam == player->ctfteam
&& players[i].powers[pw_emeralds] != 0) && players[i].powers[pw_emeralds] != 0)
{ {
players[i].powers[pw_emeralds] = 0; players[i].powers[pw_emeralds] = 0;
...@@ -392,17 +392,50 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -392,17 +392,50 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
} }
} }
// Ignore multihits in "ouchie" mode
if (special->flags & (MF_ENEMY | MF_BOSS) && special->flags2 & MF2_FRET)
return;
player = toucher->player; player = toucher->player;
I_Assert(player != NULL); // Only players can touch stuff!
if (player)
{
if (player->spectator) if (player->spectator)
return; return;
// Ignore multihits in "ouchie" mode // Some hooks may assume that the toucher is a player, so we keep it in here.
if (special->flags & (MF_ENEMY|MF_BOSS) && special->flags2 & MF2_FRET) if (LUA_HookTouchSpecial(special, toucher) || P_MobjWasRemoved(special))
return; return;
}
if (LUA_HookTouchSpecial(special, toucher) || P_MobjWasRemoved(special)) if (player || (toucher->flags & MF_PUSHABLE)) // Special area for objects that are interactable by both player AND MF_PUSHABLE.
{
if (special->type == MT_STEAM)
{
if (player && P_IsPlayerInState(player, S_PLAY_PAIN)) // can't use gas jets when player is in pain!
return;
fixed_t speed = special->info->mass; // gas jets use this for the vertical thrust
SINT8 flipval = P_MobjFlip(special); // virtually everything here centers around the thruster's gravity, not the object's!
if (special->state != &states[S_STEAM1]) // Only when it bursts
return;
toucher->eflags |= MFE_SPRUNG;
toucher->momz = flipval * FixedMul(speed, FixedSqrt(FixedMul(special->scale, toucher->scale))); // scale the speed with both objects' scales, just like with springs!
if (player)
{
P_ResetPlayer(player);
if (player->panim != PA_FALL)
P_SetMobjState(toucher, S_PLAY_FALL);
}
return; // Don't collect it!
}
}
if (!player) // Only players can touch stuff!
return; return;
// 0 = none, 1 = elemental pierce, 2 = bubble bounce // 0 = none, 1 = elemental pierce, 2 = bubble bounce
...@@ -433,7 +466,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -433,7 +466,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
toucher->momz /= -8; toucher->momz /= -8;
special->flags &= ~MF_SPECIAL; special->flags &= ~MF_SPECIAL;
if (special->info->activesound) if (special->info->activesound)
S_StartSound(special, special->info->activesound); S_StartSoundFromMobj(special, special->info->activesound);
P_SetTarget(&special->tracer, toucher); P_SetTarget(&special->tracer, toucher);
player->homing = 0; player->homing = 0;
return; return;
...@@ -670,7 +703,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -670,7 +703,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (!(gametyperules & GTR_SPECIALSTAGES) || modeattacking) // score only? if (!(gametyperules & GTR_SPECIALSTAGES) || modeattacking) // score only?
{ {
S_StartSound(toucher, sfx_chchng); S_StartSoundFromMobj(toucher, sfx_chchng);
break; break;
} }
...@@ -683,20 +716,20 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -683,20 +716,20 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
player->continues += 1; player->continues += 1;
player->gotcontinue = true; player->gotcontinue = true;
if (P_IsLocalPlayer(player)) if (P_IsLocalPlayer(player))
S_StartSound(NULL, sfx_s3kac); S_StartSoundFromEverywhere(sfx_s3kac);
else else
S_StartSound(toucher, sfx_chchng); S_StartSoundFromMobj(toucher, sfx_chchng);
} }
else else
{ {
P_GiveCoopLives(player, 1, true); // if continues are disabled, a life is a reasonable substitute P_GiveCoopLives(player, 1, true); // if continues are disabled, a life is a reasonable substitute
S_StartSound(toucher, sfx_chchng); S_StartSoundFromMobj(toucher, sfx_chchng);
} }
} }
else else
{ {
token++; token++;
S_StartSound(toucher, sfx_token); S_StartSoundFromMobj(toucher, sfx_token);
} }
break; break;
...@@ -717,12 +750,11 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -717,12 +750,11 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
{ {
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i] || players[i].spectator) if (!players[i].ingame || players[i].spectator)
continue; continue;
P_DoPlayerExit(&players[i], true);
players[i].exiting = (14*TICRATE)/5 + 1;
} }
//S_StartSound(NULL, sfx_lvpass); //S_StartSoundFromEverywhere(sfx_lvpass);
} }
break; break;
...@@ -803,6 +835,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -803,6 +835,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
{ {
clientGamedata->collected[special->health-1] = true; clientGamedata->collected[special->health-1] = true;
M_UpdateUnlockablesAndExtraEmblems(clientGamedata); M_UpdateUnlockablesAndExtraEmblems(clientGamedata);
if (!prevCollected) // don't thrash the disk and wreak performance.
G_SaveGameData(clientGamedata); G_SaveGameData(clientGamedata);
} }
...@@ -815,7 +848,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -815,7 +848,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (prevCollected == false && P_EmblemWasCollected(special->health - 1) == true) if (prevCollected == false && P_EmblemWasCollected(special->health - 1) == true)
{ {
// Play the sound if it was collected. // Play the sound if it was collected.
S_StartSound((shareEmblems ? NULL : special), special->info->deathsound); S_StartSoundFromMobj((shareEmblems ? NULL : special), special->info->deathsound);
} }
else else
{ {
...@@ -888,7 +921,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -888,7 +921,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// The fuse code plays this sound effect // The fuse code plays this sound effect
//if (players[consoleplayer].ctfteam == player->ctfteam) //if (players[consoleplayer].ctfteam == player->ctfteam)
// S_StartSound(NULL, sfx_hoop1); // S_StartSoundFromEverywhere(sfx_hoop1);
} }
} }
} }
...@@ -931,7 +964,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -931,7 +964,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
else // Make sure that SOMEONE has the emerald, at least! else // Make sure that SOMEONE has the emerald, at least!
{ {
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].playerstate == PST_LIVE if (players[i].ingame && players[i].playerstate == PST_LIVE
&& players[i].mo->tracer && players[i].mo->tracer
&& players[i].mo->tracer->type == MT_GOTEMERALD) && players[i].mo->tracer->type == MT_GOTEMERALD)
return; return;
...@@ -941,14 +974,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -941,14 +974,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// Don't play Ideya sound in special stage mode // Don't play Ideya sound in special stage mode
} }
else else
S_StartSound(toucher, special->info->activesound); S_StartSoundFromMobj(toucher, special->info->activesound);
} }
else //Initial transformation. Don't allow second chances in special stages! else //Initial transformation. Don't allow second chances in special stages!
{ {
if (player->powers[pw_carry] == CR_NIGHTSMODE) if (player->powers[pw_carry] == CR_NIGHTSMODE)
return; return;
S_StartSound(toucher, sfx_supert); S_StartSoundFromMobj(toucher, sfx_supert);
} }
P_SwitchSpheresBonusMode(false); P_SwitchSpheresBonusMode(false);
if (!(netgame || multiplayer) && !(player->powers[pw_carry] == CR_NIGHTSMODE)) if (!(netgame || multiplayer) && !(player->powers[pw_carry] == CR_NIGHTSMODE))
...@@ -969,7 +1002,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -969,7 +1002,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// scan the thinkers to find the corresponding anchorpoint // scan the thinkers to find the corresponding anchorpoint
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) 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; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -1035,7 +1068,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1035,7 +1068,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
else if (player->mo->tracer && player->mare) else if (player->mo->tracer && player->mare)
{ {
P_KillMobj(toucher->tracer, NULL, NULL, 0); // No emerald for you just yet! P_KillMobj(toucher->tracer, NULL, NULL, 0); // No emerald for you just yet!
S_StartSound(NULL, sfx_ghosty); S_StartSoundFromEverywhere(sfx_ghosty);
special->flags2 |= MF2_DONTDRAW; special->flags2 |= MF2_DONTDRAW;
} }
...@@ -1063,7 +1096,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1063,7 +1096,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// scan the remaining thinkers // scan the remaining thinkers
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) 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; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -1092,7 +1125,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1092,7 +1125,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
x = (x/count)<<FRACBITS; x = (x/count)<<FRACBITS;
y = (y/count)<<FRACBITS; y = (y/count)<<FRACBITS;
z = (z/count)<<FRACBITS; z = (z/count)<<FRACBITS;
gatherradius = P_AproxDistance(P_AproxDistance(special->x - x, special->y - y), special->z - z); gatherradius = GetDistance3D(x, y, z, special->x, special->y, special->z);
P_RemoveMobj(special); P_RemoveMobj(special);
if (player->powers[pw_nights_superloop]) if (player->powers[pw_nights_superloop])
...@@ -1107,18 +1140,18 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1107,18 +1140,18 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
for (d = 0; d < 16; d++) for (d = 0; d < 16; d++)
P_SpawnParaloop(x, y, z, gatherradius, 16, MT_NIGHTSPARKLE, sparklestate, d*ANGLE_22h, false); P_SpawnParaloop(x, y, z, gatherradius, 16, MT_NIGHTSPARKLE, sparklestate, d*ANGLE_22h, false);
S_StartSound(toucher, sfx_prloop); S_StartSoundFromMobj(toucher, sfx_prloop);
// Now we RE-scan all the thinkers to find close objects to pull // Now we RE-scan all the thinkers to find close objects to pull
// in from the paraloop. Isn't this just so efficient? // in from the paraloop. Isn't this just so efficient?
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) 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; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (P_AproxDistance(P_AproxDistance(mo2->x - x, mo2->y - y), mo2->z - z) > gatherradius) if (GetDistance3D(x, y, z, mo2->x, mo2->y, mo2->z) > gatherradius)
continue; continue;
if (mo2->flags & MF_SHOOTABLE) if (mo2->flags & MF_SHOOTABLE)
...@@ -1140,7 +1173,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1140,7 +1173,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
mo2->flags2 &= ~MF2_DONTDRAW; mo2->flags2 &= ~MF2_DONTDRAW;
mo2->flags |= MF_SPECIAL; mo2->flags |= MF_SPECIAL;
mo2->flags &= ~MF_NIGHTSITEM; mo2->flags &= ~MF_NIGHTSITEM;
S_StartSound(toucher, sfx_hidden); S_StartSoundFromMobj(toucher, sfx_hidden);
continue; continue;
} }
} }
...@@ -1181,7 +1214,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1181,7 +1214,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (G_IsSpecialStage(gamemap) && !player->exiting) if (G_IsSpecialStage(gamemap) && !player->exiting)
{ // In special stages, share spheres. Everyone gives up theirs to the player who touched the capsule { // In special stages, share spheres. Everyone gives up theirs to the player who touched the capsule
for (i = 0; i < MAXPLAYERS; i++) 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; player->spheres += players[i].spheres;
players[i].spheres = 0; players[i].spheres = 0;
...@@ -1206,7 +1239,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1206,7 +1239,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (player->bumpertime <= (TICRATE/2)-5) if (player->bumpertime <= (TICRATE/2)-5)
{ {
S_StartSound(toucher, special->info->seesound); S_StartSoundFromMobj(toucher, special->info->seesound);
if (player->powers[pw_carry] == CR_NIGHTSMODE) if (player->powers[pw_carry] == CR_NIGHTSMODE)
{ {
player->bumpertime = TICRATE/2; player->bumpertime = TICRATE/2;
...@@ -1261,10 +1294,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1261,10 +1294,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
else else
{ {
for (i = 0; i < MAXPLAYERS; 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].powers[pw_nights_superloop] = (UINT16)special->info->speed; players[i].powers[pw_nights_superloop] = (UINT16)special->info->speed;
if (special->info->deathsound != sfx_None) if (special->info->deathsound != sfx_None)
S_StartSound(NULL, special->info->deathsound); S_StartSoundFromEverywhere(special->info->deathsound);
} }
// CECHO showing you what this item is // CECHO showing you what this item is
...@@ -1283,10 +1316,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1283,10 +1316,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
else else
{ {
for (i = 0; i < MAXPLAYERS; 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].drillmeter = special->info->speed; players[i].drillmeter = special->info->speed;
if (special->info->deathsound != sfx_None) if (special->info->deathsound != sfx_None)
S_StartSound(NULL, special->info->deathsound); S_StartSoundFromEverywhere(special->info->deathsound);
} }
// CECHO showing you what this item is // CECHO showing you what this item is
...@@ -1313,14 +1346,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1313,14 +1346,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
{ {
mobj_t *flickyobj; mobj_t *flickyobj;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo && players[i].powers[pw_carry] == CR_NIGHTSMODE) { if (players[i].ingame && players[i].mo && players[i].powers[pw_carry] == CR_NIGHTSMODE) {
players[i].powers[pw_nights_helper] = (UINT16)special->info->speed; players[i].powers[pw_nights_helper] = (UINT16)special->info->speed;
flickyobj = P_SpawnMobj(players[i].mo->x, players[i].mo->y, players[i].mo->z + players[i].mo->info->height, MT_NIGHTOPIANHELPER); flickyobj = P_SpawnMobj(players[i].mo->x, players[i].mo->y, players[i].mo->z + players[i].mo->info->height, MT_NIGHTOPIANHELPER);
if (!P_MobjWasRemoved(flickyobj)) if (!P_MobjWasRemoved(flickyobj))
P_SetTarget(&flickyobj->target, players[i].mo); P_SetTarget(&flickyobj->target, players[i].mo);
} }
if (special->info->deathsound != sfx_None) if (special->info->deathsound != sfx_None)
S_StartSound(NULL, special->info->deathsound); S_StartSoundFromEverywhere(special->info->deathsound);
} }
// CECHO showing you what this item is // CECHO showing you what this item is
...@@ -1332,7 +1365,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1332,7 +1365,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
} }
break; break;
case MT_NIGHTSEXTRATIME: case MT_NIGHTSEXTRATIME:
if ((player->bot && player->bot != BOT_MPAI) || !(player->powers[pw_carry] == CR_NIGHTSMODE)) if ((player->bot && player->bot != BOT_MPAI) || !(player->powers[pw_carry] == CR_NIGHTSMODE || (G_IsSpecialStage(gamemap) && !(maptol & TOL_NIGHTS))))
return; return;
if (!G_IsSpecialStage(gamemap)) if (!G_IsSpecialStage(gamemap))
{ {
...@@ -1344,7 +1377,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1344,7 +1377,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
else else
{ {
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].powers[pw_carry] == CR_NIGHTSMODE) if (players[i].ingame && (player->powers[pw_carry] == CR_NIGHTSMODE || (G_IsSpecialStage(gamemap) && !(maptol & TOL_NIGHTS))))
{ {
players[i].nightstime += special->info->speed; players[i].nightstime += special->info->speed;
players[i].startedtime += special->info->speed; players[i].startedtime += special->info->speed;
...@@ -1352,7 +1385,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1352,7 +1385,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
P_RestoreMusic(&players[i]); P_RestoreMusic(&players[i]);
} }
if (special->info->deathsound != sfx_None) if (special->info->deathsound != sfx_None)
S_StartSound(NULL, special->info->deathsound); S_StartSoundFromEverywhere(special->info->deathsound);
} }
// CECHO showing you what this item is // CECHO showing you what this item is
...@@ -1374,13 +1407,13 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1374,13 +1407,13 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
else else
{ {
for (i = 0; i < MAXPLAYERS; 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].powers[pw_nights_linkfreeze] += (UINT16)special->info->speed; players[i].powers[pw_nights_linkfreeze] += (UINT16)special->info->speed;
players[i].linktimer = nightslinktics; players[i].linktimer = nightslinktics;
} }
if (special->info->deathsound != sfx_None) if (special->info->deathsound != sfx_None)
S_StartSound(NULL, special->info->deathsound); S_StartSoundFromEverywhere(special->info->deathsound);
} }
// CECHO showing you what this item is // CECHO showing you what this item is
...@@ -1424,7 +1457,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1424,7 +1457,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (G_IsSpecialStage(gamemap)) if (G_IsSpecialStage(gamemap))
{ {
for (i = 0; i < MAXPLAYERS; 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].drillmeter += TICRATE/2; players[i].drillmeter += TICRATE/2;
} }
else if (player->bot && player->bot != BOT_MPAI) else if (player->bot && player->bot != BOT_MPAI)
...@@ -1434,11 +1467,11 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1434,11 +1467,11 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// Play hoop sound -- pick one depending on the current link. // Play hoop sound -- pick one depending on the current link.
if (player->linkcount <= 5) if (player->linkcount <= 5)
S_StartSound(toucher, sfx_hoop1); S_StartSoundFromMobj(toucher, sfx_hoop1);
else if (player->linkcount <= 10) else if (player->linkcount <= 10)
S_StartSound(toucher, sfx_hoop2); S_StartSoundFromMobj(toucher, sfx_hoop2);
else else
S_StartSound(toucher, sfx_hoop3); S_StartSoundFromMobj(toucher, sfx_hoop3);
return; return;
// ***** // // ***** //
...@@ -1453,7 +1486,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1453,7 +1486,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
{ {
// Stop it! // Stop it!
special->momx = special->momy = 0; special->momx = special->momy = 0;
S_StartSound(toucher, sfx_mario2); S_StartSoundFromMobj(toucher, sfx_mario2);
P_SetTarget(&special->target, NULL); P_SetTarget(&special->target, NULL);
special->threshold = TICRATE - 1; special->threshold = TICRATE - 1;
toucher->momz = -toucher->momz; toucher->momz = -toucher->momz;
...@@ -1466,7 +1499,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1466,7 +1499,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// Kick that sucker around! // Kick that sucker around!
special->movedir = ((special->movedir == 1) ? -1 : 1); special->movedir = ((special->movedir == 1) ? -1 : 1);
P_InstaThrust(special, toucher->angle, (special->info->speed*special->scale)); P_InstaThrust(special, toucher->angle, (special->info->speed*special->scale));
S_StartSound(toucher, sfx_mario2); S_StartSoundFromMobj(toucher, sfx_mario2);
P_SetTarget(&special->target, toucher); P_SetTarget(&special->target, toucher);
special->threshold = (3*TICRATE)/2; special->threshold = (3*TICRATE)/2;
if (bounceon) if (bounceon)
...@@ -1488,7 +1521,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1488,7 +1521,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// scan the remaining thinkers to find koopa // scan the remaining thinkers to find koopa
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) 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; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -1516,7 +1549,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1516,7 +1549,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (player->bot && player->bot != BOT_MPAI) if (player->bot && player->bot != BOT_MPAI)
return; return;
S_StartSound(toucher, sfx_mario3); S_StartSoundFromMobj(toucher, sfx_mario3);
player->powers[pw_shield] = (player->powers[pw_shield] & SH_NOSTACK)|SH_FIREFLOWER; player->powers[pw_shield] = (player->powers[pw_shield] & SH_NOSTACK)|SH_FIREFLOWER;
...@@ -1540,8 +1573,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1540,8 +1573,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
fixed_t touchx, touchy, touchspeed; fixed_t touchx, touchy, touchspeed;
angle_t angle; angle_t angle;
if (P_AproxDistance(toucher->x-special->x, toucher->y-special->y) > if (P_AreMobjsFar2D(toucher, special, GetDistance2D(toucher->x - toucher->momx, toucher->y - toucher->momy, special->x, special->y)))
P_AproxDistance((toucher->x-toucher->momx)-special->x, (toucher->y-toucher->momy)-special->y))
{ {
touchx = toucher->x + toucher->momx; touchx = toucher->x + toucher->momx;
touchy = toucher->y + toucher->momy; touchy = toucher->y + toucher->momy;
...@@ -1553,7 +1585,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1553,7 +1585,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
} }
angle = R_PointToAngle2(special->x, special->y, touchx, touchy); angle = R_PointToAngle2(special->x, special->y, touchx, touchy);
touchspeed = P_AproxDistance(toucher->momx, toucher->momy); touchspeed = P_GetMobjMomentum2D(toucher);
toucher->momx = P_ReturnThrustX(special, angle, touchspeed); toucher->momx = P_ReturnThrustX(special, angle, touchspeed);
toucher->momy = P_ReturnThrustY(special, angle, touchspeed); toucher->momy = P_ReturnThrustY(special, angle, touchspeed);
...@@ -1569,7 +1601,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1569,7 +1601,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
player->homing = 0; player->homing = 0;
// Play a bounce sound? // Play a bounce sound?
S_StartSound(toucher, special->info->painsound); S_StartSoundFromMobj(toucher, special->info->painsound);
} }
return; return;
...@@ -1599,7 +1631,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1599,7 +1631,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
case MT_EGGSHIELD: case MT_EGGSHIELD:
{ {
angle_t angle = R_PointToAngle2(special->x, special->y, toucher->x, toucher->y) - special->angle; angle_t angle = R_PointToAngle2(special->x, special->y, toucher->x, toucher->y) - special->angle;
fixed_t touchspeed = P_AproxDistance(toucher->momx, toucher->momy); fixed_t touchspeed = P_GetMobjMomentum2D(toucher);
if (touchspeed < special->scale) if (touchspeed < special->scale)
touchspeed = special->scale; touchspeed = special->scale;
...@@ -1620,7 +1652,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1620,7 +1652,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
player->homing = 0; player->homing = 0;
// Play a bounce sound? // Play a bounce sound?
S_StartSound(toucher, special->info->painsound); S_StartSoundFromMobj(toucher, special->info->painsound);
// experimental bounce // experimental bounce
if (special->target) if (special->target)
...@@ -1670,7 +1702,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1670,7 +1702,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
P_SetPlayerAngle(player, toucher->angle); P_SetPlayerAngle(player, toucher->angle);
#endif #endif
S_StartSound(toucher, special->info->attacksound); // home run S_StartSoundFromMobj(toucher, special->info->attacksound); // home run
return; return;
...@@ -1680,7 +1712,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1680,7 +1712,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
{ {
special->momx = toucher->momx; special->momx = toucher->momx;
special->momy = toucher->momy; special->momy = toucher->momy;
special->momz = P_AproxDistance(toucher->momx, toucher->momy)/4; special->momz = P_GetMobjMomentum2D(toucher)/4;
if (toucher->momz > 0) if (toucher->momz > 0)
special->momz += toucher->momz/8; special->momz += toucher->momz/8;
...@@ -1726,7 +1758,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1726,7 +1758,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (macespin) if (macespin)
{ {
player->powers[pw_carry] = CR_MACESPIN; player->powers[pw_carry] = CR_MACESPIN;
S_StartSound(toucher, sfx_spin); S_StartSoundFromMobj(toucher, sfx_spin);
P_SetMobjState(toucher, S_PLAY_ROLL); P_SetMobjState(toucher, S_PLAY_ROLL);
} }
else else
...@@ -1750,7 +1782,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1750,7 +1782,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
special->target->momz = 0; special->target->momz = 0;
special->target->flags |= MF_NOGRAVITY; special->target->flags |= MF_NOGRAVITY;
P_SetMobjState(special->target, special->info->raisestate); P_SetMobjState(special->target, special->info->raisestate);
S_StartSound(special->target, special->info->activesound); S_StartSoundFromMobj(special->target, special->info->activesound);
P_RemoveMobj(special); P_RemoveMobj(special);
} }
return; return;
...@@ -1786,8 +1818,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1786,8 +1818,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (!player->climbing) if (!player->climbing)
{ {
if (player->bot && player->bot != BOT_MPAI && toucher->state-states != S_PLAY_GASP) if (player->bot && player->bot != BOT_MPAI && !P_IsPlayerInState(player, S_PLAY_GASP))
S_StartSound(toucher, special->info->deathsound); // Force it to play a sound for bots S_StartSoundFromMobj(toucher, special->info->deathsound); // Force it to play a sound for bots
P_SetMobjState(toucher, S_PLAY_GASP); P_SetMobjState(toucher, S_PLAY_GASP);
P_ResetPlayer(player); P_ResetPlayer(player);
} }
...@@ -1806,7 +1838,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1806,7 +1838,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
special->momz = 0; special->momz = 0;
special->flags |= MF_NOGRAVITY; special->flags |= MF_NOGRAVITY;
P_SetMobjState(special, special->info->deathstate); P_SetMobjState(special, special->info->deathstate);
S_StartSound (special, special->info->deathsound+(P_RandomKey(special->info->mass))); S_StartSoundFromMobj(special, special->info->deathsound+(P_RandomKey(special->info->mass)));
} }
return; return;
...@@ -1855,7 +1887,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1855,7 +1887,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
toucher->momx = toucher->tracer->momx/2; toucher->momx = toucher->tracer->momx/2;
toucher->momy = toucher->tracer->momy/2; toucher->momy = toucher->tracer->momy/2;
toucher->momz = toucher->tracer->momz + P_AproxDistance(toucher->tracer->momx, toucher->tracer->momy)/2; toucher->momz = toucher->tracer->momz + P_GetMobjMomentum2D(toucher->tracer)/2;
P_ResetPlayer(player); P_ResetPlayer(player);
player->pflags &= ~PF_APPLYAUTOBRAKE; player->pflags &= ~PF_APPLYAUTOBRAKE;
P_SetMobjState(toucher, S_PLAY_FALL); P_SetMobjState(toucher, S_PLAY_FALL);
...@@ -1881,6 +1913,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1881,6 +1913,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
toucher->tracer->flags2 = (toucher->tracer->flags2 & ~MF2_AMBUSH) | destambush; toucher->tracer->flags2 = (toucher->tracer->flags2 & ~MF2_AMBUSH) | destambush;
} }
return; return;
default: // SOC or script pickup default: // SOC or script pickup
if (player->bot && player->bot != BOT_MPAI) if (player->bot && player->bot != BOT_MPAI)
return; return;
...@@ -1889,7 +1922,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) ...@@ -1889,7 +1922,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
} }
} }
S_StartSound(toucher, special->info->deathsound); // was NULL, but changed to player so you could hear others pick up rings S_StartSoundFromMobj(toucher, special->info->deathsound); // was NULL, but changed to player so you could hear others pick up rings
P_KillMobj(special, NULL, toucher, 0); P_KillMobj(special, NULL, toucher, 0);
special->shadowscale = 0; special->shadowscale = 0;
} }
...@@ -1914,7 +1947,7 @@ void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost) ...@@ -1914,7 +1947,7 @@ void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost)
{ {
// blatant reuse of a variable that's normally unused in circuit // blatant reuse of a variable that's normally unused in circuit
if (!player->tossdelay) if (!player->tossdelay)
S_StartSound(toucher, sfx_lose); S_StartSoundFromMobj(toucher, sfx_lose);
player->tossdelay = 3; player->tossdelay = 3;
return; return;
} }
...@@ -1933,7 +1966,7 @@ void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost) ...@@ -1933,7 +1966,7 @@ void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost)
{ {
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (playeringame[i]) if (players[i].ingame)
{ {
if (players[i].bot) // ignore dumb, stupid tails if (players[i].bot) // ignore dumb, stupid tails
continue; continue;
...@@ -1955,7 +1988,7 @@ void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost) ...@@ -1955,7 +1988,7 @@ void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost)
P_SpectatorJoinGame(&players[i]); //players[i].playerstate = PST_REBORN; P_SpectatorJoinGame(&players[i]); //players[i].playerstate = PST_REBORN;
} }
} }
S_StartSound(NULL, post->info->painsound); S_StartSoundFromEverywhere(post->info->painsound);
} }
else else
{ {
...@@ -1972,7 +2005,7 @@ void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost) ...@@ -1972,7 +2005,7 @@ void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost)
player->starpostz += post->height>>FRACBITS; player->starpostz += post->height>>FRACBITS;
} }
player->starpostnum = post->health; player->starpostnum = post->health;
S_StartSound(toucher, post->info->painsound); S_StartSoundFromMobj(toucher, post->info->painsound);
} }
P_ClearStarPost(post->health); P_ClearStarPost(post->health);
...@@ -1985,7 +2018,7 @@ void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost) ...@@ -1985,7 +2018,7 @@ void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) 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; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -2237,7 +2270,7 @@ void P_CheckTimeLimit(void) ...@@ -2237,7 +2270,7 @@ void P_CheckTimeLimit(void)
{ {
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i] || players[i].spectator if (!players[i].ingame || players[i].spectator
|| (players[i].pflags & PF_GAMETYPEOVER) || (players[i].pflags & PF_TAGIT)) || (players[i].pflags & PF_GAMETYPEOVER) || (players[i].pflags & PF_TAGIT))
continue; continue;
...@@ -2261,7 +2294,7 @@ void P_CheckTimeLimit(void) ...@@ -2261,7 +2294,7 @@ void P_CheckTimeLimit(void)
//Figure out if we have enough participating players to care. //Figure out if we have enough participating players to care.
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (playeringame[i] && players[i].spectator) if (players[i].ingame && players[i].spectator)
spectators++; spectators++;
} }
...@@ -2269,7 +2302,7 @@ void P_CheckTimeLimit(void) ...@@ -2269,7 +2302,7 @@ void P_CheckTimeLimit(void)
{ {
// Play the starpost sfx after the first second of overtime. // Play the starpost sfx after the first second of overtime.
if (gamestate == GS_LEVEL && (leveltime == (timelimitintics + TICRATE))) if (gamestate == GS_LEVEL && (leveltime == (timelimitintics + TICRATE)))
S_StartSound(NULL, sfx_strpst); S_StartSoundFromEverywhere(sfx_strpst);
// Normal Match // Normal Match
if (!G_GametypeHasTeams()) if (!G_GametypeHasTeams())
...@@ -2277,7 +2310,7 @@ void P_CheckTimeLimit(void) ...@@ -2277,7 +2310,7 @@ void P_CheckTimeLimit(void)
//Store the nodes of participating players in an array. //Store the nodes of participating players in an array.
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (playeringame[i] && !players[i].spectator) if (players[i].ingame && !players[i].spectator)
{ {
playerarray[playercount] = i; playerarray[playercount] = i;
playercount++; playercount++;
...@@ -2350,7 +2383,7 @@ void P_CheckPointLimit(void) ...@@ -2350,7 +2383,7 @@ void P_CheckPointLimit(void)
{ {
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i] || players[i].spectator) if (!players[i].ingame || players[i].spectator)
continue; continue;
if ((UINT32)cv_pointlimit.value <= players[i].score) if ((UINT32)cv_pointlimit.value <= players[i].score)
...@@ -2379,7 +2412,7 @@ void P_CheckSurvivors(void) ...@@ -2379,7 +2412,7 @@ void P_CheckSurvivors(void)
for (i=0; i < MAXPLAYERS; i++) //figure out counts of taggers, survivors and spectators. for (i=0; i < MAXPLAYERS; i++) //figure out counts of taggers, survivors and spectators.
{ {
if (playeringame[i]) if (players[i].ingame)
{ {
if (players[i].spectator) if (players[i].spectator)
spectators++; spectators++;
...@@ -2456,7 +2489,7 @@ boolean P_CheckRacers(void) ...@@ -2456,7 +2489,7 @@ boolean P_CheckRacers(void)
// Check if all the players in the race have finished. If so, end the level. // Check if all the players in the race have finished. If so, end the level.
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (playeringame[i] && !players[i].exiting && players[i].lives > 0) if (players[i].ingame && !players[i].exiting && players[i].lives > 0)
break; break;
} }
...@@ -2669,7 +2702,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget ...@@ -2669,7 +2702,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
INT32 i; INT32 i;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i]) if (!players[i].ingame)
continue; continue;
if (players[i].lives > 0) if (players[i].lives > 0)
...@@ -2766,7 +2799,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget ...@@ -2766,7 +2799,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
case MT_BUGGLE: case MT_BUGGLE:
if (inflictor && inflictor->player // did a player kill you? Spawn relative to the player so they're bound to get it if (inflictor && inflictor->player // did a player kill you? Spawn relative to the player so they're bound to get it
&& P_AproxDistance(inflictor->x - target->x, inflictor->y - target->y) <= inflictor->radius + target->radius + FixedMul(8*FRACUNIT, inflictor->scale) // close enough? && P_AreMobjsClose2D(inflictor, target, inflictor->radius + target->radius + FixedMul(8*FRACUNIT, inflictor->scale)) // close enough?
&& inflictor->z <= target->z + target->height + FixedMul(8*FRACUNIT, inflictor->scale) && inflictor->z <= target->z + target->height + FixedMul(8*FRACUNIT, inflictor->scale)
&& inflictor->z + inflictor->height >= target->z - FixedMul(8*FRACUNIT, inflictor->scale)) && inflictor->z + inflictor->height >= target->z - FixedMul(8*FRACUNIT, inflictor->scale))
mo = P_SpawnMobj(inflictor->x + inflictor->momx, inflictor->y + inflictor->momy, inflictor->z + (inflictor->height / 2) + inflictor->momz, MT_EXTRALARGEBUBBLE); mo = P_SpawnMobj(inflictor->x + inflictor->momx, inflictor->y + inflictor->momy, inflictor->z + (inflictor->height / 2) + inflictor->momz, MT_EXTRALARGEBUBBLE);
...@@ -2835,7 +2868,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget ...@@ -2835,7 +2868,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
// scan the thinkers to make sure all the old pinch dummies are gone on death // scan the thinkers to make sure all the old pinch dummies are gone on death
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) 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; continue;
mo = (mobj_t *)th; mo = (mobj_t *)th;
...@@ -2860,7 +2893,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget ...@@ -2860,7 +2893,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
if (++i == 2) // we've already removed 2 of these, let's stop now if (++i == 2) // we've already removed 2 of these, let's stop now
break; break;
else else
S_StartSound(mo, mo->info->deathsound); // done once to prevent sound stacking S_StartSoundFromMobj(mo, mo->info->deathsound); // done once to prevent sound stacking
} }
} }
break; break;
...@@ -2869,7 +2902,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget ...@@ -2869,7 +2902,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
if (inflictor) if (inflictor)
{ {
fixed_t dx = target->x - inflictor->x, dy = target->y - inflictor->y, dz = target->z - inflictor->z; fixed_t dx = target->x - inflictor->x, dy = target->y - inflictor->y, dz = target->z - inflictor->z;
fixed_t dm = FixedHypot(dz, FixedHypot(dy, dx)); fixed_t dm = GetDistance3D(0, 0, 0, dy, dx, dz);
target->momx = FixedDiv(FixedDiv(dx, dm), dm)*512; target->momx = FixedDiv(FixedDiv(dx, dm), dm)*512;
target->momy = FixedDiv(FixedDiv(dy, dm), dm)*512; target->momy = FixedDiv(FixedDiv(dy, dm), dm)*512;
target->momz = FixedDiv(FixedDiv(dz, dm), dm)*512; target->momz = FixedDiv(FixedDiv(dz, dm), dm)*512;
...@@ -2911,16 +2944,16 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget ...@@ -2911,16 +2944,16 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
{ {
target->movedir = damagetype; // we're MOVING the Damage Into anotheR function... Okay, this is a bit of a hack. target->movedir = damagetype; // we're MOVING the Damage Into anotheR function... Okay, this is a bit of a hack.
if (target->player->charflags & SF_MACHINE) if (target->player->charflags & SF_MACHINE)
S_StartSound(target, sfx_fizzle); S_StartSoundFromMobj(target, sfx_fizzle);
else else
S_StartSound(target, sfx_drown); S_StartSoundFromMobj(target, sfx_drown);
// Don't jump up when drowning // Don't jump up when drowning
} }
else else
{ {
P_SetObjectMomZ(target, 14*FRACUNIT, false); P_SetObjectMomZ(target, 14*FRACUNIT, false);
if (damagetype == DMG_SPIKE) // Spikes if (damagetype == DMG_SPIKE) // Spikes
S_StartSound(target, sfx_spkdth); S_StartSoundFromMobj(target, sfx_spkdth);
else else
P_PlayDeathSound(target); P_PlayDeathSound(target);
} }
...@@ -2946,7 +2979,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget ...@@ -2946,7 +2979,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
mobj_t *chunk; mobj_t *chunk;
fixed_t momz; fixed_t momz;
S_StartSound(target, target->info->deathsound); S_StartSoundFromMobj(target, target->info->deathsound);
if (target->info->xdeathstate != S_NULL) if (target->info->xdeathstate != S_NULL)
{ {
...@@ -3023,7 +3056,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget ...@@ -3023,7 +3056,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
mobj_t *chunk; mobj_t *chunk;
boolean sprflip; boolean sprflip;
S_StartSound(target, target->info->deathsound); S_StartSoundFromMobj(target, target->info->deathsound);
if (!P_MobjWasRemoved(target->tracer)) if (!P_MobjWasRemoved(target->tracer))
P_RemoveMobj(target->tracer); P_RemoveMobj(target->tracer);
...@@ -3154,7 +3187,7 @@ static void P_NiGHTSDamage(mobj_t *target, mobj_t *source) ...@@ -3154,7 +3187,7 @@ static void P_NiGHTSDamage(mobj_t *target, mobj_t *source)
player->powers[pw_flashing] = flashingtics; player->powers[pw_flashing] = flashingtics;
P_SetMobjState(target, S_PLAY_NIGHTS_STUN); P_SetMobjState(target, S_PLAY_NIGHTS_STUN);
S_StartSound(target, sfx_nghurt); S_StartSoundFromMobj(target, sfx_nghurt);
player->mo->spriteroll = 0; player->mo->spriteroll = 0;
...@@ -3169,7 +3202,7 @@ static void P_NiGHTSDamage(mobj_t *target, mobj_t *source) ...@@ -3169,7 +3202,7 @@ static void P_NiGHTSDamage(mobj_t *target, mobj_t *source)
) )
{ {
S_FadeMusic(0, 10*MUSICRATE); 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 else
P_PlayJingle(player, ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) ? JT_NIGHTSTIMEOUT : JT_SSTIMEOUT); P_PlayJingle(player, ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) ? JT_NIGHTSTIMEOUT : JT_SSTIMEOUT);
...@@ -3191,15 +3224,15 @@ static boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, IN ...@@ -3191,15 +3224,15 @@ static boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, IN
return false; return false;
// Ignore IT players shooting each other, unless friendlyfire is on. // Ignore IT players shooting each other, unless friendlyfire is on.
if ((player->pflags & PF_TAGIT && !((cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE) || (damagetype & DMG_CANHURTSELF)) && if ((player->pflags & PF_TAGIT && source && source->player && !(((cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE)) || ((damagetype & DMG_CANHURTSELF) && source->player == player)) &&
source && source->player && source->player->pflags & PF_TAGIT))) source->player->pflags & PF_TAGIT)))
{ {
if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK))
{ {
if (player->revitem != MT_LHRT && player->spinitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers. if (player->revitem != MT_LHRT && player->spinitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers.
{ {
P_SwitchShield(player, SH_PINK); P_SwitchShield(player, SH_PINK);
S_StartSound(target, mobjinfo[MT_PITY_ICON].seesound); S_StartSoundFromMobj(target, mobjinfo[MT_PITY_ICON].seesound);
} }
} }
return false; return false;
...@@ -3207,14 +3240,15 @@ static boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, IN ...@@ -3207,14 +3240,15 @@ static boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, IN
// Don't allow players on the same team to hurt one another, // Don't allow players on the same team to hurt one another,
// unless cv_friendlyfire is on. // unless cv_friendlyfire is on.
if (!(cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE) || (damagetype & DMG_CANHURTSELF)) && (player->pflags & PF_TAGIT) == (source->player->pflags & PF_TAGIT)) if (source && source->player && !((cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE)) || ((damagetype & DMG_CANHURTSELF) && source->player == player)) &&
(player->pflags & PF_TAGIT) == (source->player->pflags & PF_TAGIT))
{ {
if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK))
{ {
if (player->revitem != MT_LHRT && player->spinitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers. if (player->revitem != MT_LHRT && player->spinitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers.
{ {
P_SwitchShield(player, SH_PINK); P_SwitchShield(player, SH_PINK);
S_StartSound(target, mobjinfo[MT_PITY_ICON].seesound); S_StartSoundFromMobj(target, mobjinfo[MT_PITY_ICON].seesound);
} }
} }
else if (!(inflictor->flags & MF_FIRE)) else if (!(inflictor->flags & MF_FIRE))
...@@ -3254,7 +3288,7 @@ static boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, IN ...@@ -3254,7 +3288,7 @@ static boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, IN
if (player->powers[pw_shield]) if (player->powers[pw_shield])
{ {
P_RemoveShield(player); P_RemoveShield(player);
S_StartSound(target, sfx_shldls); S_StartSoundFromMobj(target, sfx_shldls);
return true; return true;
} }
...@@ -3299,7 +3333,7 @@ static boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *sou ...@@ -3299,7 +3333,7 @@ static boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *sou
if (player->revitem != MT_LHRT && player->spinitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers. if (player->revitem != MT_LHRT && player->spinitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers.
{ {
P_SwitchShield(player, SH_PINK); P_SwitchShield(player, SH_PINK);
S_StartSound(target, mobjinfo[MT_PITY_ICON].seesound); S_StartSoundFromMobj(target, mobjinfo[MT_PITY_ICON].seesound);
} }
} }
return false; return false;
...@@ -3309,7 +3343,7 @@ static boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *sou ...@@ -3309,7 +3343,7 @@ static boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *sou
// Tag handling // Tag handling
if (G_TagGametype()) if (G_TagGametype())
return P_TagDamage(target, inflictor, source, damage, damagetype); return P_TagDamage(target, inflictor, source, damage, damagetype);
else if (damagetype & DMG_CANHURTSELF) else if ((damagetype & DMG_CANHURTSELF) && source && source->player && source->player == player)
return true; return true;
else if (G_GametypeHasTeams()) // CTF + Team Match else if (G_GametypeHasTeams()) // CTF + Team Match
{ {
...@@ -3322,7 +3356,7 @@ static boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *sou ...@@ -3322,7 +3356,7 @@ static boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *sou
if (player->revitem != MT_LHRT && player->spinitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers. if (player->revitem != MT_LHRT && player->spinitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers.
{ {
P_SwitchShield(player, SH_PINK); P_SwitchShield(player, SH_PINK);
S_StartSound(target, mobjinfo[MT_PITY_ICON].seesound); S_StartSoundFromMobj(target, mobjinfo[MT_PITY_ICON].seesound);
} }
} }
else if (!(inflictor->flags & MF_FIRE)) else if (!(inflictor->flags & MF_FIRE))
...@@ -3378,24 +3412,26 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage) ...@@ -3378,24 +3412,26 @@ static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage)
if ((gametyperules & GTR_TEAMFLAGS) && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) if ((gametyperules & GTR_TEAMFLAGS) && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
{ {
P_PlayerFlagBurst(player, false); P_PlayerFlagBurst(player, false);
if (source && source->player) if (source && source->player && source->player != player) // Don't score points against yourself
{ {
// Award no points when players shoot each other when cv_friendlyfire is on. // Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo)) if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
P_AddPlayerScore(source->player, 25); P_AddPlayerScore(source->player, 25);
} }
} }
if (source && source->player && !player->powers[pw_super]) //don't score points against super players if (source && source->player && source->player != player && !player->powers[pw_super]) //don't score points against super players or yourself
{ {
// Award no points when players shoot each other when cv_friendlyfire is on. // Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo)) if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
{
P_AddPlayerScore(source->player, 100); P_AddPlayerScore(source->player, 100);
} }
}
// If the player was super, tell them he/she ain't so super nomore. // If the player was super, tell them he/she ain't so super nomore.
if (!G_CoopGametype() && player->powers[pw_super]) if (!G_CoopGametype() && player->powers[pw_super])
{ {
S_StartSound(NULL, sfx_s3k66); //let all players hear it. S_StartSoundFromEverywhere(sfx_s3k66); //let all players hear it.
HU_SetCEchoFlags(0); HU_SetCEchoFlags(0);
HU_SetCEchoDuration(5); HU_SetCEchoDuration(5);
HU_DoCEcho(va("%s\\is no longer super.\\\\\\\\", player_names[player-players])); HU_DoCEcho(va("%s\\is no longer super.\\\\\\\\", player_names[player-players]));
...@@ -3425,7 +3461,7 @@ static void P_SuperDamage(player_t *player, mobj_t *inflictor, mobj_t *source, I ...@@ -3425,7 +3461,7 @@ static void P_SuperDamage(player_t *player, mobj_t *inflictor, mobj_t *source, I
// to recover // to recover
if (inflictor->flags2 & MF2_SCATTER && source) 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; dist = FixedMul(128*FRACUNIT, inflictor->scale) - dist/4;
...@@ -3496,21 +3532,21 @@ static void P_ShieldDamage(player_t *player, mobj_t *inflictor, mobj_t *source, ...@@ -3496,21 +3532,21 @@ static void P_ShieldDamage(player_t *player, mobj_t *inflictor, mobj_t *source,
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2); P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
if (damagetype == DMG_SPIKE) // spikes if (damagetype == DMG_SPIKE) // spikes
S_StartSound(player->mo, sfx_spkdth); S_StartSoundFromMobj(player->mo, sfx_spkdth);
else else
S_StartSound (player->mo, sfx_shldls); // Ba-Dum! Shield loss. S_StartSoundFromMobj(player->mo, sfx_shldls); // Ba-Dum! Shield loss.
if ((gametyperules & GTR_TEAMFLAGS) && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) if ((gametyperules & GTR_TEAMFLAGS) && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
{ {
P_PlayerFlagBurst(player, false); P_PlayerFlagBurst(player, false);
if (source && source->player) if (source && source->player && source->player != player) // Don't score points against yourself
{ {
// Award no points when players shoot each other when cv_friendlyfire is on. // Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo)) if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
P_AddPlayerScore(source->player, 25); P_AddPlayerScore(source->player, 25);
} }
} }
if (source && source->player && !player->powers[pw_super]) //don't score points against super players if (source && source->player && source->player != player && !player->powers[pw_super]) //don't score points against super players or yourself
{ {
// Award no points when players shoot each other when cv_friendlyfire is on. // Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo)) if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
...@@ -3525,9 +3561,9 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN ...@@ -3525,9 +3561,9 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN
P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2); P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2);
if (damagetype == DMG_SPIKE) // spikes if (damagetype == DMG_SPIKE) // spikes
S_StartSound(player->mo, sfx_spkdth); S_StartSoundFromMobj(player->mo, sfx_spkdth);
if (source && source->player && !player->powers[pw_super]) //don't score points against super players if (source && source->player && source->player != player && !player->powers[pw_super]) //don't score points against super players
{ {
// Award no points when players shoot each other when cv_friendlyfire is on. // Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo)) if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
...@@ -3537,7 +3573,7 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN ...@@ -3537,7 +3573,7 @@ static void P_RingDamage(player_t *player, mobj_t *inflictor, mobj_t *source, IN
if ((gametyperules & GTR_TEAMFLAGS) && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) if ((gametyperules & GTR_TEAMFLAGS) && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
{ {
P_PlayerFlagBurst(player, false); P_PlayerFlagBurst(player, false);
if (source && source->player) if (source && source->player && source->player != player) // Don't score points against yourself
{ {
// Award no points when players shoot each other when cv_friendlyfire is on. // Award no points when players shoot each other when cv_friendlyfire is on.
if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo)) if (!G_GametypeHasTeams() || !(source->player->ctfteam == player->ctfteam && source != player->mo))
...@@ -3584,7 +3620,7 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source) ...@@ -3584,7 +3620,7 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source)
if (player->revitem != MT_LHRT && player->spinitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers. if (player->revitem != MT_LHRT && player->spinitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers.
{ {
P_SwitchShield(player, SH_PINK); P_SwitchShield(player, SH_PINK);
S_StartSound(player->mo, mobjinfo[MT_PITY_ICON].seesound); S_StartSoundFromMobj(player->mo, mobjinfo[MT_PITY_ICON].seesound);
} }
} }
...@@ -3598,15 +3634,15 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source) ...@@ -3598,15 +3634,15 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source)
if (player->powers[pw_shield] || (player->bot && player->bot != BOT_MPAI)) //If One-Hit Shield if (player->powers[pw_shield] || (player->bot && player->bot != BOT_MPAI)) //If One-Hit Shield
{ {
P_RemoveShield(player); P_RemoveShield(player);
S_StartSound(player->mo, sfx_shldls); // Ba-Dum! Shield loss. S_StartSoundFromMobj(player->mo, sfx_shldls); // Ba-Dum! Shield loss.
} }
else else
{ {
S_StartSound(player->mo, sfx_nghurt); S_StartSoundFromMobj(player->mo, sfx_nghurt);
if (player->nightstime > 5*TICRATE) if (player->nightstime > 5*TICRATE)
player->nightstime -= 5*TICRATE; player->nightstime -= 5*TICRATE;
else else
player->nightstime = 0; player->nightstime = 1;
} }
P_DoPlayerPain(player, inflictor, source); P_DoPlayerPain(player, inflictor, source);
...@@ -3620,7 +3656,7 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source) ...@@ -3620,7 +3656,7 @@ void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source)
if (mapheaderinfo[gamemap-1]->levelflags & LF_MIXNIGHTSCOUNTDOWN) if (mapheaderinfo[gamemap-1]->levelflags & LF_MIXNIGHTSCOUNTDOWN)
{ {
S_FadeMusic(0, 10*MUSICRATE); 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 else
S_ChangeMusicInternal((((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) ? "_ntime" : "_drown"), false); S_ChangeMusicInternal((((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)) ? "_ntime" : "_drown"), false);
...@@ -3752,6 +3788,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da ...@@ -3752,6 +3788,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (player->powers[pw_carry] == CR_NIGHTSMODE) // NiGHTS damage handling if (player->powers[pw_carry] == CR_NIGHTSMODE) // NiGHTS damage handling
{ {
if (player->powers[pw_flashing])
return false;
if (!force) if (!force)
{ {
if (source == target) if (source == target)
...@@ -3769,6 +3807,10 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da ...@@ -3769,6 +3807,10 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (G_IsSpecialStage(gamemap) && !(damagetype & DMG_DEATHMASK)) if (G_IsSpecialStage(gamemap) && !(damagetype & DMG_DEATHMASK))
{ {
if (player->powers[pw_flashing])
return false;
if (LUA_HookMobjDamage(target, inflictor, source, damage, damagetype))
return true;
P_SpecialStageDamage(player, inflictor, source); P_SpecialStageDamage(player, inflictor, source);
return true; return true;
} }
...@@ -3844,7 +3886,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da ...@@ -3844,7 +3886,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
// To reduce griefing potential, don't allow players to be killed // To reduce griefing potential, don't allow players to be killed
// by friendly fire. Spilling their rings and other items is enough. // by friendly fire. Spilling their rings and other items is enough.
else if (!force && G_GametypeHasTeams() else if (!force && G_GametypeHasTeams()
&& source && source->player && (source->player->ctfteam == player->ctfteam) && source && source->player && source->player != player && (source->player->ctfteam == player->ctfteam)
&& (cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE))) && (cv_friendlyfire.value || (gametyperules & GTR_FRIENDLYFIRE)))
{ {
damage = 0; damage = 0;
......
...@@ -78,7 +78,7 @@ fireflicker_t *P_SpawnAdjustableFireFlicker(sector_t *sector, INT16 lighta, INT1 ...@@ -78,7 +78,7 @@ fireflicker_t *P_SpawnAdjustableFireFlicker(sector_t *sector, INT16 lighta, INT1
P_AddThinker(THINK_MAIN, &flick->thinker); P_AddThinker(THINK_MAIN, &flick->thinker);
flick->thinker.function.acp1 = (actionf_p1)T_FireFlicker; flick->thinker.function = (actionf_p1)T_FireFlicker;
flick->sector = sector; flick->sector = sector;
flick->maxlight = max(lighta, lightb); flick->maxlight = max(lighta, lightb);
flick->minlight = min(lighta, lightb); flick->minlight = min(lighta, lightb);
...@@ -136,7 +136,7 @@ void P_SpawnLightningFlash(sector_t *sector) ...@@ -136,7 +136,7 @@ void P_SpawnLightningFlash(sector_t *sector)
if (sector->lightingdata) if (sector->lightingdata)
{ {
if (((lightflash_t *)sector->lightingdata)->thinker.function.acp1 if (((lightflash_t *)sector->lightingdata)->thinker.function
== (actionf_p1)T_LightningFlash) == (actionf_p1)T_LightningFlash)
{ {
// lightning was already flashing in this sector // lightning was already flashing in this sector
...@@ -153,7 +153,7 @@ void P_SpawnLightningFlash(sector_t *sector) ...@@ -153,7 +153,7 @@ void P_SpawnLightningFlash(sector_t *sector)
P_AddThinker(THINK_MAIN, &flash->thinker); P_AddThinker(THINK_MAIN, &flash->thinker);
flash->thinker.function.acp1 = (actionf_p1)T_LightningFlash; flash->thinker.function = (actionf_p1)T_LightningFlash;
flash->sector = sector; flash->sector = sector;
flash->maxlight = 255; flash->maxlight = 255;
flash->minlight = minlight; flash->minlight = minlight;
...@@ -215,7 +215,7 @@ strobe_t *P_SpawnAdjustableStrobeFlash(sector_t *sector, INT16 lighta, INT16 lig ...@@ -215,7 +215,7 @@ strobe_t *P_SpawnAdjustableStrobeFlash(sector_t *sector, INT16 lighta, INT16 lig
flash->sector = sector; flash->sector = sector;
flash->darktime = darktime; flash->darktime = darktime;
flash->brighttime = brighttime; flash->brighttime = brighttime;
flash->thinker.function.acp1 = (actionf_p1)T_StrobeFlash; flash->thinker.function = (actionf_p1)T_StrobeFlash;
flash->maxlight = max(lighta, lightb); flash->maxlight = max(lighta, lightb);
flash->minlight = min(lighta, lightb); flash->minlight = min(lighta, lightb);
...@@ -285,7 +285,7 @@ glow_t *P_SpawnAdjustableGlowingLight(sector_t *sector, INT16 lighta, INT16 ligh ...@@ -285,7 +285,7 @@ glow_t *P_SpawnAdjustableGlowingLight(sector_t *sector, INT16 lighta, INT16 ligh
g->sector = sector; g->sector = sector;
g->minlight = min(lighta, lightb); g->minlight = min(lighta, lightb);
g->maxlight = max(lighta, lightb); g->maxlight = max(lighta, lightb);
g->thinker.function.acp1 = (actionf_p1)T_Glow; g->thinker.function = (actionf_p1)T_Glow;
g->direction = 1; g->direction = 1;
g->speed = (INT16)(length/4); g->speed = (INT16)(length/4);
if (g->speed > (g->maxlight - g->minlight)/2) // don't make it ridiculous speed if (g->speed > (g->maxlight - g->minlight)/2) // don't make it ridiculous speed
...@@ -333,7 +333,7 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean ...@@ -333,7 +333,7 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean
} }
ll = Z_Calloc(sizeof (*ll), PU_LEVSPEC, NULL); ll = Z_Calloc(sizeof (*ll), PU_LEVSPEC, NULL);
ll->thinker.function.acp1 = (actionf_p1)T_LightFade; ll->thinker.function = (actionf_p1)T_LightFade;
sector->lightingdata = ll; // set it to the lightlevel_t sector->lightingdata = ll; // set it to the lightlevel_t
P_AddThinker(THINK_MAIN, &ll->thinker); // add thinker P_AddThinker(THINK_MAIN, &ll->thinker); // add thinker
...@@ -368,7 +368,7 @@ void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, bool ...@@ -368,7 +368,7 @@ void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed, boolean ticbased, bool
{ {
if (!force && ticbased // always let speed fader execute if (!force && ticbased // always let speed fader execute
&& sectors[i].lightingdata && sectors[i].lightingdata
&& ((lightlevel_t*)sectors[i].lightingdata)->thinker.function.acp1 == (actionf_p1)T_LightFade) && ((lightlevel_t*)sectors[i].lightingdata)->thinker.function == (actionf_p1)T_LightFade)
// && ((lightlevel_t*)sectors[i].lightingdata)->timer > 2) // && ((lightlevel_t*)sectors[i].lightingdata)->timer > 2)
{ {
CONS_Debug(DBG_GAMELOGIC, "Line type 420 Executor: Fade light thinker already exists, timer: %d\n", ((lightlevel_t*)sectors[i].lightingdata)->timer); CONS_Debug(DBG_GAMELOGIC, "Line type 420 Executor: Fade light thinker already exists, timer: %d\n", ((lightlevel_t*)sectors[i].lightingdata)->timer);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // 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 // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -39,11 +39,6 @@ ...@@ -39,11 +39,6 @@
// Convenience macro to fix issue with collision along bottom/left edges of blockmap -Red // Convenience macro to fix issue with collision along bottom/left edges of blockmap -Red
#define BMBOUNDFIX(xl, xh, yl, yh) {if (xl > xh) xl = 0; if (yl > yh) yl = 0;} #define BMBOUNDFIX(xl, xh, yl, yh) {if (xl > xh) xl = 0; if (yl > yh) yl = 0;}
// MAXRADIUS is for precalculated sector block boxes
// the spider demon is larger,
// but we do not have any moving sectors nearby
#define MAXRADIUS (32*FRACUNIT)
// max Z move up or down without jumping // max Z move up or down without jumping
// above this, a height difference is considered as a 'dropoff' // above this, a height difference is considered as a 'dropoff'
#define MAXSTEPMOVE (24*FRACUNIT) #define MAXSTEPMOVE (24*FRACUNIT)
...@@ -63,10 +58,10 @@ ...@@ -63,10 +58,10 @@
typedef enum typedef enum
{ {
THINK_DYNSLOPE,
THINK_POLYOBJ, THINK_POLYOBJ,
THINK_MAIN, THINK_MAIN,
THINK_MOBJ, THINK_MOBJ,
THINK_DYNSLOPE,
THINK_PRECIP, THINK_PRECIP,
NUM_THINKERLISTS NUM_THINKERLISTS
} thinklistnum_t; /**< Thinker lists. */ } thinklistnum_t; /**< Thinker lists. */
...@@ -135,6 +130,10 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam); ...@@ -135,6 +130,10 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam);
void P_SlideCameraMove(camera_t *thiscam); void P_SlideCameraMove(camera_t *thiscam);
boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcalled); boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcalled);
pflags_t P_GetJumpFlags(player_t *player); pflags_t P_GetJumpFlags(player_t *player);
statenum_t P_GetCanonicalPlayerState(player_t *player, statenum_t state);
boolean P_IsPlayerInState(player_t *player, statenum_t state);
boolean P_IsPlayerInSuperTransformationState(player_t *player);
boolean P_IsPlayerInNightsTransformationState(player_t *player);
boolean P_PlayerInPain(player_t *player); boolean P_PlayerInPain(player_t *player);
void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor); void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor);
void P_ResetPlayer(player_t *player); void P_ResetPlayer(player_t *player);
...@@ -203,7 +202,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet); ...@@ -203,7 +202,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet);
void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius); void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius);
void P_Earthquake(mobj_t *inflictor, mobj_t *source, fixed_t radius); void P_Earthquake(mobj_t *inflictor, mobj_t *source, fixed_t radius);
boolean P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user boolean P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user
boolean P_SuperReady(player_t *player, boolean transform); boolean P_SuperReady(player_t *player);
void P_DoJump(player_t *player, boolean soundandstate, boolean allowflip); void P_DoJump(player_t *player, boolean soundandstate, boolean allowflip);
void P_DoSpinDashDust(player_t *player); void P_DoSpinDashDust(player_t *player);
#define P_AnalogMove(player) (P_ControlStyle(player) == CS_LMAOGALOG) #define P_AnalogMove(player) (P_ControlStyle(player) == CS_LMAOGALOG)
...@@ -221,9 +220,9 @@ void P_DoMetalJetFume(player_t *player, mobj_t *fume); ...@@ -221,9 +220,9 @@ void P_DoMetalJetFume(player_t *player, mobj_t *fume);
void P_DoFollowMobj(player_t *player, mobj_t *followmobj); void P_DoFollowMobj(player_t *player, mobj_t *followmobj);
void P_PlayLivesJingle(player_t *player); void P_PlayLivesJingle(player_t *player);
#define P_PlayRinglossSound(s) S_StartSound(s, (mariomode) ? sfx_mario8 : sfx_altow1 + P_RandomKey(4)); #define P_PlayRinglossSound(s) S_StartSoundFromMobj(s, (mariomode) ? sfx_mario8 : sfx_altow1 + P_RandomKey(4));
#define P_PlayDeathSound(s) S_StartSound(s, sfx_altdi1 + P_RandomKey(4)); #define P_PlayDeathSound(s) S_StartSoundFromMobj(s, sfx_altdi1 + P_RandomKey(4));
#define P_PlayVictorySound(s) S_StartSound(s, sfx_victr1 + P_RandomKey(4)); #define P_PlayVictorySound(s) S_StartSoundFromMobj(s, sfx_victr1 + P_RandomKey(4));
boolean P_GetLives(player_t *player); boolean P_GetLives(player_t *player);
boolean P_SpectatorJoinGame(player_t *player); boolean P_SpectatorJoinGame(player_t *player);
...@@ -294,7 +293,6 @@ void P_RecalcPrecipInSector(sector_t *sector); ...@@ -294,7 +293,6 @@ void P_RecalcPrecipInSector(sector_t *sector);
void P_PrecipitationEffects(void); void P_PrecipitationEffects(void);
void P_RemoveMobj(mobj_t *th); void P_RemoveMobj(mobj_t *th);
boolean P_MobjWasRemoved(mobj_t *th);
void P_RemoveSavegameMobj(mobj_t *th); void P_RemoveSavegameMobj(mobj_t *th);
boolean P_SetMobjState(mobj_t *mobj, statenum_t state); boolean P_SetMobjState(mobj_t *mobj, statenum_t state);
void P_RunShields(void); void P_RunShields(void);
...@@ -306,22 +304,26 @@ boolean P_CheckSkyHit(mobj_t *mo, line_t *line); ...@@ -306,22 +304,26 @@ boolean P_CheckSkyHit(mobj_t *mo, line_t *line);
void P_PushableThinker(mobj_t *mobj); void P_PushableThinker(mobj_t *mobj);
void P_SceneryThinker(mobj_t *mobj); void P_SceneryThinker(mobj_t *mobj);
// This does not need to be added to Lua.
fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect); // To test it in Lua, check mobj.valid
fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect); FUNCINLINE static ATTRINLINE boolean P_MobjWasRemoved(mobj_t *mobj)
#define P_GetFloorZ(mobj, sector, x, y, line) P_MobjFloorZ(mobj, sector, NULL, x, y, line, false, false) {
#define P_GetCeilingZ(mobj, sector, x, y, line) P_MobjCeilingZ(mobj, sector, NULL, x, y, line, true, false) return mobj == NULL || mobj->thinker.function != (actionf_p1)P_MobjThinker;
#define P_GetFOFTopZ(mobj, sector, fof, x, y, line) P_MobjCeilingZ(mobj, sectors + fof->secnum, sector, x, y, line, false, false) }
#define P_GetFOFBottomZ(mobj, sector, fof, x, y, line) P_MobjFloorZ(mobj, sectors + fof->secnum, sector, x, y, line, true, false)
#define P_GetSpecialBottomZ(mobj, src, bound) P_MobjFloorZ(mobj, src, bound, mobj->x, mobj->y, NULL, src != bound, true) fixed_t P_MobjFloorZ(sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, fixed_t radius, line_t *line, boolean lowest, boolean perfect);
#define P_GetSpecialTopZ(mobj, src, bound) P_MobjCeilingZ(mobj, src, bound, mobj->x, mobj->y, NULL, src == bound, true) fixed_t P_MobjCeilingZ(sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, fixed_t radius, line_t *line, boolean lowest, boolean perfect);
#define P_GetFloorZ(mobj, sector, x, y, line) P_MobjFloorZ(sector, NULL, x, y, mobj->radius, line, false, false)
fixed_t P_CameraFloorZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect); #define P_GetCeilingZ(mobj, sector, x, y, line) P_MobjCeilingZ(sector, NULL, x, y, mobj->radius, line, true, false)
fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect); #define P_GetFOFTopZ(mobj, sector, fof, x, y, line) P_MobjCeilingZ(sectors + fof->secnum, sector, x, y, mobj->radius, line, false, false)
#define P_CameraGetFloorZ(mobj, sector, x, y, line) P_CameraFloorZ(mobj, sector, NULL, x, y, line, false, false) #define P_GetFOFBottomZ(mobj, sector, fof, x, y, line) P_MobjFloorZ(sectors + fof->secnum, sector, x, y, mobj->radius, line, true, false)
#define P_CameraGetCeilingZ(mobj, sector, x, y, line) P_CameraCeilingZ(mobj, sector, NULL, x, y, line, true, false) #define P_GetSpecialBottomZ(mobj, src, bound) P_MobjFloorZ(src, bound, mobj->x, mobj->y, mobj->radius, NULL, src != bound, true)
#define P_CameraGetFOFTopZ(mobj, sector, fof, x, y, line) P_CameraCeilingZ(mobj, sectors + fof->secnum, sector, x, y, line, false, false) #define P_GetSpecialTopZ(mobj, src, bound) P_MobjCeilingZ(src, bound, mobj->x, mobj->y, mobj->radius, NULL, src == bound, true)
#define P_CameraGetFOFBottomZ(mobj, sector, fof, x, y, line) P_CameraFloorZ(mobj, sectors + fof->secnum, sector, x, y, line, true, false)
#define P_CameraGetFloorZ(mobj, sector, x, y, line) P_MobjFloorZ(sector, NULL, x, y, mobj->radius, line, false, false)
#define P_CameraGetCeilingZ(mobj, sector, x, y, line) P_MobjCeilingZ(sector, NULL, x, y, mobj->radius, line, true, false)
#define P_CameraGetFOFTopZ(mobj, sector, fof, x, y, line) P_MobjCeilingZ(sectors + fof->secnum, sector, x, y, mobj->radius, line, false, false)
#define P_CameraGetFOFBottomZ(mobj, sector, fof, x, y, line) P_MobjFloorZ(sectors + fof->secnum, sector, x, y, mobj->radius, line, true, false)
boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover); boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover);
boolean P_CheckDeathPitCollide(mobj_t *mo); boolean P_CheckDeathPitCollide(mobj_t *mo);
...@@ -555,5 +557,17 @@ void P_DoSuperDetransformation(player_t *player); ...@@ -555,5 +557,17 @@ void P_DoSuperDetransformation(player_t *player);
void P_ExplodeMissile(mobj_t *mo); void P_ExplodeMissile(mobj_t *mo);
void P_CheckGravity(mobj_t *mo, boolean affect); void P_CheckGravity(mobj_t *mo, boolean affect);
void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope); void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope);
boolean P_IsMobjInPainState(mobj_t *mobj);
fixed_t P_GetMobjDistance2D(mobj_t *mobj1, mobj_t *mobj2);
fixed_t P_GetMobjDistance3D(mobj_t *mobj1, mobj_t *mobj2);
INT32 P_GetMobjLargeDistance2D(mobj_t *mobj1, mobj_t *mobj2);
INT32 P_GetMobjLargeDistance3D(mobj_t *mobj1, mobj_t *mobj2);
boolean P_AreMobjsClose2D(mobj_t *mobj1, mobj_t *mobj2, fixed_t maxdist);
boolean P_AreMobjsClose3D(mobj_t *mobj1, mobj_t *mobj2, fixed_t maxdist);
boolean P_AreMobjsFar2D(mobj_t *mobj1, mobj_t *mobj2, fixed_t mindist);
boolean P_AreMobjsFar3D(mobj_t *mobj1, mobj_t *mobj2, fixed_t mindist);
fixed_t P_GetMobjMomentum2D(mobj_t *mobj);
fixed_t P_GetMobjMomentum3D(mobj_t *mobj);
#endif // __P_LOCAL__ #endif // __P_LOCAL__
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // 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 // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -36,6 +36,9 @@ ...@@ -36,6 +36,9 @@
#include "m_perfstats.h" // ps_checkposition_calls #include "m_perfstats.h" // ps_checkposition_calls
// Formerly called MAXRADIUS
#define MAXTRYMOVE (32*FRACUNIT)
fixed_t tmbbox[4]; fixed_t tmbbox[4];
mobj_t *tmthing; mobj_t *tmthing;
static INT32 tmflags; static INT32 tmflags;
...@@ -389,7 +392,6 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) ...@@ -389,7 +392,6 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
{ {
INT32 pflags; INT32 pflags;
UINT8 secondjump; UINT8 secondjump;
boolean washoming;
if (spring->flags & MF_ENEMY) // Spring shells if (spring->flags & MF_ENEMY) // Spring shells
P_SetTarget(&spring->target, object); P_SetTarget(&spring->target, object);
...@@ -412,7 +414,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) ...@@ -412,7 +414,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
{ {
pflags = PF_SPINNING; pflags = PF_SPINNING;
P_SetMobjState(object, S_PLAY_ROLL); P_SetMobjState(object, S_PLAY_ROLL);
S_StartSound(object, sfx_spin); S_StartSoundFromMobj(object, sfx_spin);
} }
else else
P_SetMobjState(object, S_PLAY_ROLL); P_SetMobjState(object, S_PLAY_ROLL);
...@@ -421,7 +423,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) ...@@ -421,7 +423,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
{ {
boolean wasSpindashing = object->player->dashspeed > 0 && (object->player->charability2 == CA2_SPINDASH); boolean wasSpindashing = object->player->dashspeed > 0 && (object->player->charability2 == CA2_SPINDASH);
pflags = object->player->pflags & (PF_STARTJUMP | PF_JUMPED | PF_NOJUMPDAMAGE | PF_SPINNING | PF_THOKKED | PF_BOUNCING); // I still need these. pflags = object->player->pflags & (PF_STARTJUMP | PF_JUMPED | PF_NOJUMPDAMAGE | PF_SPINNING | PF_BOUNCING); // I still need these.
if (wasSpindashing) // Ensure we're in the rolling state, and not spindash. if (wasSpindashing) // Ensure we're in the rolling state, and not spindash.
P_SetMobjState(object, S_PLAY_ROLL); P_SetMobjState(object, S_PLAY_ROLL);
...@@ -433,7 +435,6 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) ...@@ -433,7 +435,6 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
} }
} }
secondjump = object->player->secondjump; secondjump = object->player->secondjump;
washoming = object->player->homing;
P_ResetPlayer(object->player); P_ResetPlayer(object->player);
if (spring->info->painchance == 1) // For all those ancient, SOC'd abilities. if (spring->info->painchance == 1) // For all those ancient, SOC'd abilities.
...@@ -445,8 +446,6 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) ...@@ -445,8 +446,6 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
{ {
object->player->pflags |= (pflags &~ PF_STARTJUMP); object->player->pflags |= (pflags &~ PF_STARTJUMP);
object->player->secondjump = secondjump; object->player->secondjump = secondjump;
if (washoming)
object->player->pflags &= ~PF_THOKKED;
} }
else if (!vertispeed) else if (!vertispeed)
{ {
...@@ -495,79 +494,63 @@ springstate: ...@@ -495,79 +494,63 @@ springstate:
{ {
if (object->player->charability == CA_TWINSPIN || object->player->charability2 == CA2_MELEE) if (object->player->charability == CA_TWINSPIN || object->player->charability2 == CA2_MELEE)
P_TwinSpinRejuvenate(object->player, (object->player->charability == CA_TWINSPIN ? object->player->thokitem : object->player->revitem)); P_TwinSpinRejuvenate(object->player, (object->player->charability == CA_TWINSPIN ? object->player->thokitem : object->player->revitem));
S_StartSound(object, sfx_sprong); // strong spring. sprong. S_StartSoundFromMobj(object, sfx_sprong); // strong spring. sprong.
} }
} }
return final; return final;
} }
static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object) static void P_DoFan(mobj_t *fan, mobj_t *object)
{ {
player_t *p = object->player; // will be NULL if not a player player_t *p = object->player; // will be NULL if not a player
fixed_t zdist; // distance between bottoms fixed_t zdist; // distance between bottoms
fixed_t speed = spring->info->mass; // conveniently, both fans and gas jets use this for the vertical thrust fixed_t speed = fan->info->mass; // fans use this for the vertical thrust
SINT8 flipval = P_MobjFlip(spring); // virtually everything here centers around the thruster's gravity, not the object's! SINT8 flipval = P_MobjFlip(fan); // virtually everything here centers around the thruster's gravity, not the object's!
if (p && object->state == &states[object->info->painstate]) // can't use fans and gas jets when player is in pain! if (p && P_IsPlayerInState(p, S_PLAY_PAIN)) // can't use fans when player is in pain!
return; return;
// is object's top below thruster's position? if not, calculate distance between their bottoms // is object's top below thruster's position? if not, calculate distance between their bottoms
if (spring->eflags & MFE_VERTICALFLIP) if (fan->eflags & MFE_VERTICALFLIP)
{ {
if (object->z > spring->z + spring->height) if (object->z > fan->z + fan->height)
return; return;
zdist = (spring->z + spring->height) - (object->z + object->height); zdist = (fan->z + fan->height) - (object->z + object->height);
} }
else else
{ {
if (object->z + object->height < spring->z) if (object->z + object->height < fan->z)
return; return;
zdist = object->z - spring->z; zdist = object->z - fan->z;
} }
object->standingslope = NULL; // No launching off at silly angles for you. object->standingslope = NULL; // No launching off at silly angles for you.
switch (spring->type) switch (fan->type)
{ {
case MT_FAN: // fan case MT_FAN: // fan
if (zdist > (spring->health << FRACBITS)) // max z distance determined by health (set by map thing args[0]) if (zdist > (fan->health << FRACBITS)) // max z distance determined by health (set by map thing args[0])
break; break;
if (flipval*object->momz >= FixedMul(speed, spring->scale)) // if object's already moving faster than your best, don't bother if (flipval*object->momz >= FixedMul(speed, fan->scale)) // if object's already moving faster than your best, don't bother
break; break;
if (p && (p->climbing || p->pflags & PF_GLIDING)) // doesn't affect Knux when he's using his abilities! if (p && (p->climbing || p->pflags & PF_GLIDING)) // doesn't affect Knux when he's using his abilities!
break; break;
object->momz += flipval*FixedMul(speed/4, spring->scale); object->momz += flipval*FixedMul(speed/4, fan->scale);
// limit the speed if too high // limit the speed if too high
if (flipval*object->momz > FixedMul(speed, spring->scale)) if (flipval*object->momz > FixedMul(speed, fan->scale))
object->momz = flipval*FixedMul(speed, spring->scale); object->momz = flipval*FixedMul(speed, fan->scale);
if (p && !p->powers[pw_tailsfly] && !p->powers[pw_carry]) // doesn't reset anim for Tails' flight if (p && !p->powers[pw_tailsfly] && !p->powers[pw_carry]) // doesn't reset anim for Tails' flight
{ {
P_ResetPlayer(p); P_ResetPlayer(p);
P_SetMobjState(object, S_PLAY_FALL); P_SetMobjState(object, S_PLAY_FALL);
P_SetTarget(&object->tracer, spring); P_SetTarget(&object->tracer, fan);
p->powers[pw_carry] = CR_FAN; p->powers[pw_carry] = CR_FAN;
} }
break; break;
case MT_STEAM: // Steam
if (zdist > FixedMul(16*FRACUNIT, spring->scale))
break;
if (spring->state != &states[S_STEAM1]) // Only when it bursts
break;
object->eflags |= MFE_SPRUNG;
object->momz = flipval*FixedMul(speed, FixedSqrt(FixedMul(spring->scale, object->scale))); // scale the speed with both objects' scales, just like with springs!
if (p)
{
P_ResetPlayer(p);
if (p->panim != PA_FALL)
P_SetMobjState(object, S_PLAY_FALL);
}
break;
default: default:
break; break;
} }
...@@ -602,7 +585,7 @@ static void P_DoPterabyteCarry(player_t *player, mobj_t *ptera) ...@@ -602,7 +585,7 @@ static void P_DoPterabyteCarry(player_t *player, mobj_t *ptera)
P_SetTarget(&player->mo->tracer, ptera); P_SetTarget(&player->mo->tracer, ptera);
player->pflags &= ~PF_APPLYAUTOBRAKE; player->pflags &= ~PF_APPLYAUTOBRAKE;
player->powers[pw_carry] = CR_PTERABYTE; player->powers[pw_carry] = CR_PTERABYTE;
S_StartSound(player->mo, sfx_s3k4a); S_StartSoundFromMobj(player->mo, sfx_s3k4a);
P_UnsetThingPosition(player->mo); P_UnsetThingPosition(player->mo);
player->mo->x = ptera->x; player->mo->x = ptera->x;
player->mo->y = ptera->y; player->mo->y = ptera->y;
...@@ -642,7 +625,7 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails) ...@@ -642,7 +625,7 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails)
// Search in case another player is already being carried by this fox. // Search in case another player is already being carried by this fox.
for (p = 0; p < MAXPLAYERS; p++) for (p = 0; p < MAXPLAYERS; p++)
if (playeringame[p] && players[p].mo if (players[p].ingame && players[p].mo
&& players[p].powers[pw_carry] == CR_PLAYER && players[p].mo->tracer == tails->mo) && players[p].powers[pw_carry] == CR_PLAYER && players[p].mo->tracer == tails->mo)
return; return;
...@@ -671,7 +654,7 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails) ...@@ -671,7 +654,7 @@ static void P_DoTailsCarry(player_t *sonic, player_t *tails)
P_ResetPlayer(sonic); P_ResetPlayer(sonic);
P_SetTarget(&sonic->mo->tracer, tails->mo); P_SetTarget(&sonic->mo->tracer, tails->mo);
sonic->powers[pw_carry] = CR_PLAYER; sonic->powers[pw_carry] = CR_PLAYER;
S_StartSound(sonic->mo, sfx_s3k4a); S_StartSoundFromMobj(sonic->mo, sfx_s3k4a);
P_UnsetThingPosition(sonic->mo); P_UnsetThingPosition(sonic->mo);
sonic->mo->x = tails->mo->x; sonic->mo->x = tails->mo->x;
sonic->mo->y = tails->mo->y; sonic->mo->y = tails->mo->y;
...@@ -716,7 +699,7 @@ static void P_SlapStick(mobj_t *fang, mobj_t *pole) ...@@ -716,7 +699,7 @@ static void P_SlapStick(mobj_t *fang, mobj_t *pole)
var1 = var2 = 0; var1 = var2 = 0;
A_Scream(pole->tracer->tracer); A_Scream(pole->tracer->tracer);
S_StartSound(fang, sfx_altdi1); S_StartSoundFromMobj(fang, sfx_altdi1);
P_SetTarget(&pole->tracer->tracer, NULL); P_SetTarget(&pole->tracer->tracer, NULL);
P_SetMobjState(pole->tracer, pole->info->xdeathstate); P_SetMobjState(pole->tracer, pole->info->xdeathstate);
...@@ -827,9 +810,9 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) ...@@ -827,9 +810,9 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
{ {
mobj_t *iter; mobj_t *iter;
if (thing->flags & MF_SOLID) if (thing->flags & MF_SOLID)
S_StartSound(tmthing, thing->info->deathsound); S_StartSoundFromMobj(tmthing, thing->info->deathsound);
for (iter = thing->subsector->sector->thinglist; iter; iter = iter->snext) for (iter = thing->subsector->sector->thinglist; iter; iter = iter->snext)
if (iter->type == thing->type && iter->health > 0 && iter->flags & MF_SOLID && (iter == thing || P_AproxDistance(P_AproxDistance(thing->x - iter->x, thing->y - iter->y), thing->z - iter->z) < 56*thing->scale))//FixedMul(56*FRACUNIT, thing->scale)) if (iter->type == thing->type && iter->health > 0 && iter->flags & MF_SOLID && (iter == thing || P_AreMobjsClose3D(thing, iter, 56*thing->scale)))//FixedMul(56*FRACUNIT, thing->scale))
P_KillMobj(iter, tmthing, tmthing, 0); P_KillMobj(iter, tmthing, tmthing, 0);
} }
else else
...@@ -854,9 +837,9 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) ...@@ -854,9 +837,9 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
return CHECKTHING_NOCOLLIDE; // underneath return CHECKTHING_NOCOLLIDE; // underneath
if (thing->flags & MF_SOLID) if (thing->flags & MF_SOLID)
S_StartSound(tmthing, thing->info->deathsound); S_StartSoundFromMobj(tmthing, thing->info->deathsound);
for (iter = thing->subsector->sector->thinglist; iter; iter = iter->snext) for (iter = thing->subsector->sector->thinglist; iter; iter = iter->snext)
if (iter->type == thing->type && iter->health > 0 && iter->flags & MF_SOLID && (iter == thing || P_AproxDistance(P_AproxDistance(thing->x - iter->x, thing->y - iter->y), thing->z - iter->z) < 56*thing->scale))//FixedMul(56*FRACUNIT, thing->scale)) if (iter->type == thing->type && iter->health > 0 && iter->flags & MF_SOLID && (iter == thing || P_AreMobjsClose3D(thing, iter, 56*thing->scale)))//FixedMul(56*FRACUNIT, thing->scale))
P_KillMobj(iter, tmthing, tmthing, 0); P_KillMobj(iter, tmthing, tmthing, 0);
return CHECKTHING_COLLIDE; return CHECKTHING_COLLIDE;
} }
...@@ -1018,10 +1001,10 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) ...@@ -1018,10 +1001,10 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
if (((thing->flags2 & MF2_AMBUSH) && (tmthing->z <= thing->z + thing->height) && (tmthing->z + tmthing->height >= thing->z)) if (((thing->flags2 & MF2_AMBUSH) && (tmthing->z <= thing->z + thing->height) && (tmthing->z + tmthing->height >= thing->z))
|| ref != tmthing) || ref != tmthing)
{ {
fixed_t dm = min(FixedHypot(ref->momx, ref->momy), 16*FRACUNIT); fixed_t dm = min(P_GetMobjMomentum2D(ref), 16*FRACUNIT);
angle_t ang = R_PointToAngle2(0, 0, ref->momx, ref->momy) - thing->angle; angle_t ang = R_PointToAngle2(0, 0, ref->momx, ref->momy) - thing->angle;
fixed_t s = FINESINE((ang >> ANGLETOFINESHIFT) & FINEMASK); fixed_t s = FINESINE((ang >> ANGLETOFINESHIFT) & FINEMASK);
S_StartSound(tmthing, thing->info->activesound); S_StartSoundFromMobj(tmthing, thing->info->activesound);
thing->extravalue2 += 2*FixedMul(s, dm)/3; thing->extravalue2 += 2*FixedMul(s, dm)/3;
return CHECKTHING_COLLIDE; return CHECKTHING_COLLIDE;
} }
...@@ -1043,7 +1026,6 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) ...@@ -1043,7 +1026,6 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
if ((thing->flags & MF_PUSHABLE) // not carrying a player if ((thing->flags & MF_PUSHABLE) // not carrying a player
&& (tmthing->player->powers[pw_carry] == CR_NONE) // player is not already riding something && (tmthing->player->powers[pw_carry] == CR_NONE) // player is not already riding something
&& !(tmthing->player->powers[pw_ignorelatch] & (1<<15)) && !(tmthing->player->powers[pw_ignorelatch] & (1<<15))
&& ((tmthing->eflags & MFE_VERTICALFLIP) == (thing->eflags & MFE_VERTICALFLIP))
&& (P_MobjFlip(tmthing)*tmthing->momz <= 0) && (P_MobjFlip(tmthing)*tmthing->momz <= 0)
&& ((!(tmthing->eflags & MFE_VERTICALFLIP) && abs(thing->z + thing->height - tmthing->z) < (thing->height>>2)) && ((!(tmthing->eflags & MFE_VERTICALFLIP) && abs(thing->z + thing->height - tmthing->z) < (thing->height>>2))
|| (tmthing->eflags & MFE_VERTICALFLIP && abs(tmthing->z + tmthing->height - thing->z) < (thing->height>>2)))) || (tmthing->eflags & MFE_VERTICALFLIP && abs(tmthing->z + tmthing->height - thing->z) < (thing->height>>2))))
...@@ -1057,6 +1039,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) ...@@ -1057,6 +1039,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
P_SetTarget(&tmthing->tracer, thing); P_SetTarget(&tmthing->tracer, thing);
if (!P_IsObjectOnGround(thing)) if (!P_IsObjectOnGround(thing))
thing->momz += tmthing->momz; thing->momz += tmthing->momz;
return CHECKTHING_COLLIDE; return CHECKTHING_COLLIDE;
} }
} }
...@@ -1087,7 +1070,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) ...@@ -1087,7 +1070,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
thing->momy = tmthing->momy; thing->momy = tmthing->momy;
tmthing->momx = tempmomx; tmthing->momx = tempmomx;
tmthing->momy = tempmomy; tmthing->momy = tempmomy;
S_StartSound(thing, thing->info->painsound); S_StartSoundFromMobj(thing, thing->info->painsound);
} }
} }
...@@ -1102,7 +1085,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) ...@@ -1102,7 +1085,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
fixed_t dx = thing->x - tmthing->x; fixed_t dx = thing->x - tmthing->x;
fixed_t dy = thing->y - tmthing->y; fixed_t dy = thing->y - tmthing->y;
fixed_t dz = thing->z - tmthing->z; fixed_t dz = thing->z - tmthing->z;
fixed_t dm = FixedHypot(dz, FixedHypot(dx, dy)); fixed_t dm = GetDistance3D(0, 0, 0, dx, dy, dz);
thing->momx += FixedDiv(dx, dm); thing->momx += FixedDiv(dx, dm);
thing->momy += FixedDiv(dy, dm); thing->momy += FixedDiv(dy, dm);
thing->momz += FixedDiv(dz, dm); thing->momz += FixedDiv(dz, dm);
...@@ -1143,7 +1126,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) ...@@ -1143,7 +1126,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
tmthing->momy /= -8; tmthing->momy /= -8;
tmthing->momz /= -8; tmthing->momz /= -8;
if (thing->info->activesound) if (thing->info->activesound)
S_StartSound(thing, thing->info->activesound); S_StartSoundFromMobj(thing, thing->info->activesound);
P_SetMobjState(thing, thing->info->meleestate); P_SetMobjState(thing, thing->info->meleestate);
P_SetTarget(&thing->tracer, tmthing->tracer); P_SetTarget(&thing->tracer, tmthing->tracer);
return CHECKTHING_COLLIDE; return CHECKTHING_COLLIDE;
...@@ -1162,7 +1145,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) ...@@ -1162,7 +1145,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
thing->momx = P_ReturnThrustX(tmthing, tmthing->angle, 2*tmthing->extravalue1*tmthing->scale/3); thing->momx = P_ReturnThrustX(tmthing, tmthing->angle, 2*tmthing->extravalue1*tmthing->scale/3);
thing->momy = P_ReturnThrustY(tmthing, tmthing->angle, 2*tmthing->extravalue1*tmthing->scale/3); thing->momy = P_ReturnThrustY(tmthing, tmthing->angle, 2*tmthing->extravalue1*tmthing->scale/3);
if (thing->info->activesound) if (thing->info->activesound)
S_StartSound(thing, thing->info->activesound); S_StartSoundFromMobj(thing, thing->info->activesound);
P_SetMobjState(thing, thing->info->meleestate); P_SetMobjState(thing, thing->info->meleestate);
if (tmthing->tracer) if (tmthing->tracer)
P_SetTarget(&thing->tracer, tmthing->tracer->target); P_SetTarget(&thing->tracer, tmthing->tracer->target);
...@@ -1200,7 +1183,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) ...@@ -1200,7 +1183,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
if (!damagetype && thing->flags & MF_FIRE) // BURN! if (!damagetype && thing->flags & MF_FIRE) // BURN!
damagetype = DMG_FIRE; damagetype = DMG_FIRE;
if (P_DamageMobj(tmthing, thing, thing, 1, damagetype) && (damagetype = (thing->info->mass>>8))) if (P_DamageMobj(tmthing, thing, thing, 1, damagetype) && (damagetype = (thing->info->mass>>8)))
S_StartSound(thing, damagetype); S_StartSoundFromMobj(thing, damagetype);
return CHECKTHING_COLLIDE; return CHECKTHING_COLLIDE;
} }
return CHECKTHING_NOCOLLIDE; return CHECKTHING_NOCOLLIDE;
...@@ -1218,7 +1201,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) ...@@ -1218,7 +1201,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
if (!damagetype && tmthing->flags & MF_FIRE) // BURN! if (!damagetype && tmthing->flags & MF_FIRE) // BURN!
damagetype = DMG_FIRE; damagetype = DMG_FIRE;
if (P_DamageMobj(thing, tmthing, tmthing, 1, damagetype) && (damagetype = (tmthing->info->mass>>8))) if (P_DamageMobj(thing, tmthing, tmthing, 1, damagetype) && (damagetype = (tmthing->info->mass>>8)))
S_StartSound(tmthing, damagetype); S_StartSoundFromMobj(tmthing, damagetype);
return CHECKTHING_COLLIDE; return CHECKTHING_COLLIDE;
} }
return CHECKTHING_NOCOLLIDE; return CHECKTHING_NOCOLLIDE;
...@@ -1278,8 +1261,9 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) ...@@ -1278,8 +1261,9 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
if (tmthing->type != MT_SHELL && tmthing->target && tmthing->target->type == thing->type) if (tmthing->type != MT_SHELL && tmthing->target && tmthing->target->type == thing->type)
{ {
// Don't hit same species as originator. // Don't hit yourself, and if a player, don't hit bots
if (thing == tmthing->target) if (thing == tmthing->target
|| (thing->player && tmthing->target->player && (thing->player->bot == BOT_2PAI || thing->player->bot == BOT_2PHUMAN)))
return CHECKTHING_IGNORE; return CHECKTHING_IGNORE;
if (thing->type != MT_PLAYER) if (thing->type != MT_PLAYER)
...@@ -1442,7 +1426,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) ...@@ -1442,7 +1426,7 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
} }
if (thing->type != MT_GARGOYLE || P_IsObjectOnGround(thing)) if (thing->type != MT_GARGOYLE || P_IsObjectOnGround(thing))
S_StartSound(thing, thing->info->activesound); S_StartSoundFromMobj(thing, thing->info->activesound);
P_SetTarget(&thing->target, tmthing); P_SetTarget(&thing->target, tmthing);
} }
...@@ -1484,13 +1468,13 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) ...@@ -1484,13 +1468,13 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
} }
// check for special pickup // check for special pickup
if (thing->flags & MF_SPECIAL && tmthing->player) if (thing->flags & MF_SPECIAL && (tmthing->player || (tmthing->flags & MF_PUSHABLE))) // MF_PUSHABLE added for steam jets
{ {
P_TouchSpecialThing(thing, tmthing, true); // can remove thing P_TouchSpecialThing(thing, tmthing, true); // can remove thing
return CHECKTHING_COLLIDE; return CHECKTHING_COLLIDE;
} }
// check again for special pickup // check again for special pickup
if (tmthing->flags & MF_SPECIAL && thing->player) if (tmthing->flags & MF_SPECIAL && (thing->player || (thing->flags & MF_PUSHABLE))) // MF_PUSHABLE added for steam jets
{ {
P_TouchSpecialThing(tmthing, thing, true); // can remove thing P_TouchSpecialThing(tmthing, thing, true); // can remove thing
return CHECKTHING_COLLIDE; return CHECKTHING_COLLIDE;
...@@ -1578,15 +1562,15 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) ...@@ -1578,15 +1562,15 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
if (thing->flags & MF_PUSHABLE) if (thing->flags & MF_PUSHABLE)
{ {
if (tmthing->type == MT_FAN || tmthing->type == MT_STEAM) if (tmthing->type == MT_FAN)
P_DoFanAndGasJet(tmthing, thing); P_DoFan(tmthing, thing);
} }
if (tmthing->flags & MF_PUSHABLE) if (tmthing->flags & MF_PUSHABLE)
{ {
if (thing->type == MT_FAN || thing->type == MT_STEAM) if (thing->type == MT_FAN)
{ {
P_DoFanAndGasJet(thing, tmthing); P_DoFan(thing, tmthing);
return CHECKTHING_COLLIDE; return CHECKTHING_COLLIDE;
} }
else if (thing->flags & MF_SPRING) else if (thing->flags & MF_SPRING)
...@@ -1679,8 +1663,8 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) ...@@ -1679,8 +1663,8 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
} }
} }
if (tmthing->type == MT_FAN || tmthing->type == MT_STEAM) if (tmthing->type == MT_FAN)
P_DoFanAndGasJet(tmthing, thing); P_DoFan(tmthing, thing);
} }
if (tmthing->player) // Is the moving/interacting object the player? if (tmthing->player) // Is the moving/interacting object the player?
...@@ -1688,8 +1672,8 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) ...@@ -1688,8 +1672,8 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
if (!tmthing->health) if (!tmthing->health)
return CHECKTHING_IGNORE; return CHECKTHING_IGNORE;
if (thing->type == MT_FAN || thing->type == MT_STEAM) if (thing->type == MT_FAN)
P_DoFanAndGasJet(thing, tmthing); P_DoFan(thing, tmthing);
else if (thing->flags & MF_SPRING && tmthing->player->powers[pw_carry] != CR_MINECART) else if (thing->flags & MF_SPRING && tmthing->player->powers[pw_carry] != CR_MINECART)
{ {
if ( thing->z <= tmthing->z + tmthing->height if ( thing->z <= tmthing->z + tmthing->height
...@@ -1755,8 +1739,8 @@ static unsigned PIT_DoCheckThing(mobj_t *thing) ...@@ -1755,8 +1739,8 @@ static unsigned PIT_DoCheckThing(mobj_t *thing)
// not solid not blocked // not solid not blocked
unsigned collide = CHECKTHING_NOCOLLIDE; unsigned collide = CHECKTHING_NOCOLLIDE;
if ((tmthing->flags & MF_SPRING || tmthing->type == MT_STEAM || tmthing->type == MT_SPIKE || tmthing->type == MT_WALLSPIKE) && (thing->player)) if ((tmthing->flags & MF_SPRING || tmthing->type == MT_SPIKE || tmthing->type == MT_WALLSPIKE) && (thing->player))
; // springs, gas jets and springs should never be able to step up onto a player ; // springs and spikes should never be able to step up onto a player
// z checking at last // z checking at last
// Treat noclip things as non-solid! // Treat noclip things as non-solid!
else if ((thing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID else if ((thing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID
...@@ -2184,15 +2168,10 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) ...@@ -2184,15 +2168,10 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
} }
} }
// The bounding box is extended by MAXRADIUS xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
// because mobj_ts are grouped into mapblocks xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
// based on their origin point, and can overlap yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
// into adjacent blocks by up to MAXRADIUS units. yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
yh = (unsigned)(tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
BMBOUNDFIX(xl, xh, yl, yh); BMBOUNDFIX(xl, xh, yl, yh);
...@@ -2283,7 +2262,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) ...@@ -2283,7 +2262,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
for (bx = xl; bx <= xh; bx++) for (bx = xl; bx <= xh; bx++)
for (by = yl; by <= yh; by++) for (by = yl; by <= yh; by++)
{ {
if (!P_BlockThingsIterator(bx, by, PIT_CheckThing)) if (!P_BlockThingsIterator(bx, by, PIT_CheckThing, tmthing))
blockval = false; blockval = false;
else else
tmhitthing = tmfloorthing; tmhitthing = tmfloorthing;
...@@ -2314,7 +2293,7 @@ void P_CheckHoopPosition(mobj_t *hoopthing, fixed_t x, fixed_t y, fixed_t z, fix ...@@ -2314,7 +2293,7 @@ void P_CheckHoopPosition(mobj_t *hoopthing, fixed_t x, fixed_t y, fixed_t z, fix
(void)radius; //unused (void)radius; //unused
for (i = 0; i < MAXPLAYERS; i++) 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; continue;
if (abs(players[i].mo->x - x) >= hoopblockdist || if (abs(players[i].mo->x - x) >= hoopblockdist ||
...@@ -2412,11 +2391,6 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) ...@@ -2412,11 +2391,6 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam)
} }
} }
// The bounding box is extended by MAXRADIUS
// because mobj_ts are grouped into mapblocks
// based on their origin point, and can overlap
// into adjacent blocks by up to MAXRADIUS units.
xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; xl = (unsigned)(tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; xh = (unsigned)(tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; yl = (unsigned)(tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
...@@ -2521,6 +2495,9 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) ...@@ -2521,6 +2495,9 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam)
floatok = false; floatok = false;
if (dedicated) // this crashes so don't even try it
return false;
if (twodlevel if (twodlevel
|| (thiscam == &camera && players[displayplayer].mo && (players[displayplayer].mo->flags2 & MF2_TWOD)) || (thiscam == &camera && players[displayplayer].mo && (players[displayplayer].mo->flags2 & MF2_TWOD))
|| (thiscam == &camera2 && players[secondarydisplayplayer].mo && (players[secondarydisplayplayer].mo->flags2 & MF2_TWOD))) || (thiscam == &camera2 && players[secondarydisplayplayer].mo && (players[secondarydisplayplayer].mo->flags2 & MF2_TWOD)))
...@@ -2544,16 +2521,16 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) ...@@ -2544,16 +2521,16 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam)
} }
do { do {
if (x-tryx > MAXRADIUS) if (x-tryx > MAXTRYMOVE)
tryx += MAXRADIUS; tryx += MAXTRYMOVE;
else if (x-tryx < -MAXRADIUS) else if (x-tryx < -MAXTRYMOVE)
tryx -= MAXRADIUS; tryx -= MAXTRYMOVE;
else else
tryx = x; tryx = x;
if (y-tryy > MAXRADIUS) if (y-tryy > MAXTRYMOVE)
tryy += MAXRADIUS; tryy += MAXTRYMOVE;
else if (y-tryy < -MAXRADIUS) else if (y-tryy < -MAXTRYMOVE)
tryy -= MAXRADIUS; tryy -= MAXTRYMOVE;
else else
tryy = y; tryy = y;
...@@ -2699,7 +2676,7 @@ increment_move ...@@ -2699,7 +2676,7 @@ increment_move
floatok = false; floatok = false;
// This makes sure that there are no freezes from computing extremely small movements. // This makes sure that there are no freezes from computing extremely small movements.
// Originally was MAXRADIUS/2, but that can cause some bad inconsistencies for small players. // Originally was MAXTRYMOVE/2, but that can cause some bad inconsistencies for small players.
radius = max(radius, thing->scale); radius = max(radius, thing->scale);
// And we also have to prevent Big Large (tm) movements, as those can skip too far // And we also have to prevent Big Large (tm) movements, as those can skip too far
...@@ -2888,10 +2865,10 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) ...@@ -2888,10 +2865,10 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
{ {
INT32 xl, xh, yl, yh; INT32 xl, xh, yl, yh;
yh = (unsigned)(thing->y + MAXRADIUS - bmaporgy)>>MAPBLOCKSHIFT; yh = (unsigned)(thing->y + thing->radius - bmaporgy)>>MAPBLOCKSHIFT;
yl = (unsigned)(thing->y - MAXRADIUS - bmaporgy)>>MAPBLOCKSHIFT; yl = (unsigned)(thing->y - thing->radius - bmaporgy)>>MAPBLOCKSHIFT;
xh = (unsigned)(thing->x + MAXRADIUS - bmaporgx)>>MAPBLOCKSHIFT; xh = (unsigned)(thing->x + thing->radius - bmaporgx)>>MAPBLOCKSHIFT;
xl = (unsigned)(thing->x - MAXRADIUS - bmaporgx)>>MAPBLOCKSHIFT; xl = (unsigned)(thing->x - thing->radius - bmaporgx)>>MAPBLOCKSHIFT;
BMBOUNDFIX(xl, xh, yl, yh); BMBOUNDFIX(xl, xh, yl, yh);
...@@ -2899,7 +2876,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) ...@@ -2899,7 +2876,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
standx = x; standx = x;
standy = y; standy = y;
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_PushableMoved); P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_PushableMoved, stand);
} }
// Link the thing into its new position // Link the thing into its new position
...@@ -2963,16 +2940,16 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y) ...@@ -2963,16 +2940,16 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y)
tryx = thing->x; tryx = thing->x;
tryy = thing->y; tryy = thing->y;
do { do {
if (x-tryx > MAXRADIUS) if (x-tryx > MAXTRYMOVE)
tryx += MAXRADIUS; tryx += MAXTRYMOVE;
else if (x-tryx < -MAXRADIUS) else if (x-tryx < -MAXTRYMOVE)
tryx -= MAXRADIUS; tryx -= MAXTRYMOVE;
else else
tryx = x; tryx = x;
if (y-tryy > MAXRADIUS) if (y-tryy > MAXTRYMOVE)
tryy += MAXRADIUS; tryy += MAXTRYMOVE;
else if (y-tryy < -MAXRADIUS) else if (y-tryy < -MAXTRYMOVE)
tryy -= MAXRADIUS; tryy -= MAXTRYMOVE;
else else
tryy = y; tryy = y;
...@@ -3056,7 +3033,7 @@ static boolean P_ThingHeightClip(mobj_t *thing) ...@@ -3056,7 +3033,7 @@ static boolean P_ThingHeightClip(mobj_t *thing)
if (tmfloorz > oldfloorz+thing->height) if (tmfloorz > oldfloorz+thing->height)
return true; return true;
bouncing = thing->player && thing->state-states == S_PLAY_BOUNCE_LANDING && P_IsObjectOnGround(thing); bouncing = thing->player && P_IsPlayerInState(thing->player, S_PLAY_BOUNCE_LANDING) && P_IsObjectOnGround(thing);
if ((onfloor || bouncing) && !(thing->flags & MF_NOGRAVITY) && floormoved) if ((onfloor || bouncing) && !(thing->flags & MF_NOGRAVITY) && floormoved)
{ {
...@@ -3156,7 +3133,7 @@ static void P_HitCameraSlideLine(line_t *ld, camera_t *thiscam) ...@@ -3156,7 +3133,7 @@ static void P_HitCameraSlideLine(line_t *ld, camera_t *thiscam)
lineangle >>= ANGLETOFINESHIFT; lineangle >>= ANGLETOFINESHIFT;
deltaangle >>= ANGLETOFINESHIFT; deltaangle >>= ANGLETOFINESHIFT;
movelen = P_AproxDistance(tmxmove, tmymove); movelen = GetDistance2D(0, 0, tmxmove, tmymove);
newlen = FixedMul(movelen, FINECOSINE(deltaangle)); newlen = FixedMul(movelen, FINECOSINE(deltaangle));
tmxmove = FixedMul(newlen, FINECOSINE(lineangle)); tmxmove = FixedMul(newlen, FINECOSINE(lineangle));
...@@ -3202,7 +3179,7 @@ static void P_HitSlideLine(line_t *ld) ...@@ -3202,7 +3179,7 @@ static void P_HitSlideLine(line_t *ld)
lineangle >>= ANGLETOFINESHIFT; lineangle >>= ANGLETOFINESHIFT;
deltaangle >>= ANGLETOFINESHIFT; deltaangle >>= ANGLETOFINESHIFT;
movelen = R_PointToDist2(0, 0, tmxmove, tmymove); movelen = GetDistance2D(0, 0, tmxmove, tmymove);
newlen = FixedMul(movelen, FINECOSINE(deltaangle)); newlen = FixedMul(movelen, FINECOSINE(deltaangle));
tmxmove = FixedMul(newlen, FINECOSINE(lineangle)); tmxmove = FixedMul(newlen, FINECOSINE(lineangle));
...@@ -3242,7 +3219,7 @@ static void P_HitBounceLine(line_t *ld) ...@@ -3242,7 +3219,7 @@ static void P_HitBounceLine(line_t *ld)
lineangle >>= ANGLETOFINESHIFT; lineangle >>= ANGLETOFINESHIFT;
deltaangle >>= ANGLETOFINESHIFT; deltaangle >>= ANGLETOFINESHIFT;
movelen = P_AproxDistance(tmxmove, tmymove); movelen = GetDistance2D(0, 0, tmxmove, tmymove);
tmxmove = FixedMul(movelen, FINECOSINE(deltaangle)); tmxmove = FixedMul(movelen, FINECOSINE(deltaangle));
tmymove = FixedMul(movelen, FINESINE(deltaangle)); tmymove = FixedMul(movelen, FINESINE(deltaangle));
...@@ -3499,12 +3476,12 @@ static void PTR_GlideClimbTraverse(line_t *li) ...@@ -3499,12 +3476,12 @@ static void PTR_GlideClimbTraverse(line_t *li)
if (!slidemo->player->climbing) if (!slidemo->player->climbing)
{ {
S_StartSound(slidemo, sfx_s3k4a); S_StartSoundFromMobj(slidemo, sfx_s3k4a);
slidemo->player->climbing = 5; slidemo->player->climbing = 5;
if (slidemo->player->powers[pw_super]) if (slidemo->player->powers[pw_super])
{ {
P_Earthquake(slidemo, slidemo, 256*FRACUNIT); P_Earthquake(slidemo, slidemo, 256*FRACUNIT);
S_StartSound(slidemo, sfx_s3k49); S_StartSoundFromMobj(slidemo, sfx_s3k49);
} }
} }
...@@ -3980,23 +3957,25 @@ papercollision: ...@@ -3980,23 +3957,25 @@ papercollision:
mo->momy = tmymove; mo->momy = tmymove;
} }
const fixed_t tmradius = mo->radius > 8 ? mo->radius : 8;
do { do {
if (tmxmove > mo->radius) { if (tmxmove > tmradius) {
newx = mo->x + mo->radius; newx = mo->x + tmradius;
tmxmove -= mo->radius; tmxmove -= tmradius;
} else if (tmxmove < -mo->radius) { } else if (tmxmove < -tmradius) {
newx = mo->x - mo->radius; newx = mo->x - tmradius;
tmxmove += mo->radius; tmxmove += tmradius;
} else { } else {
newx = mo->x + tmxmove; newx = mo->x + tmxmove;
tmxmove = 0; tmxmove = 0;
} }
if (tmymove > mo->radius) { if (tmymove > tmradius) {
newy = mo->y + mo->radius; newy = mo->y + tmradius;
tmymove -= mo->radius; tmymove -= tmradius;
} else if (tmymove < -mo->radius) { } else if (tmymove < -tmradius) {
newy = mo->y - mo->radius; newy = mo->y - tmradius;
tmymove += mo->radius; tmymove += tmradius;
} else { } else {
newy = mo->y + tmymove; newy = mo->y + tmymove;
tmymove = 0; tmymove = 0;
...@@ -4197,7 +4176,7 @@ static boolean PIT_RadiusAttack(mobj_t *thing) ...@@ -4197,7 +4176,7 @@ static boolean PIT_RadiusAttack(mobj_t *thing)
dy = abs(thing->y - bombspot->y); dy = abs(thing->y - bombspot->y);
dz = abs(thing->z + (thing->height>>1) - bombspot->z); dz = abs(thing->z + (thing->height>>1) - bombspot->z);
dist = P_AproxDistance(P_AproxDistance(dx, dy), dz); dist = GetDistance3D(0, 0, 0, dx, dy, dz);
dist -= thing->radius; dist -= thing->radius;
if (dist < 0) if (dist < 0)
...@@ -4229,7 +4208,8 @@ void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 dama ...@@ -4229,7 +4208,8 @@ void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 dama
INT32 xl, xh, yl, yh; INT32 xl, xh, yl, yh;
fixed_t dist; fixed_t dist;
dist = FixedMul(damagedist, spot->scale) + MAXRADIUS; dist = FixedMul(damagedist, spot->scale);
yh = (unsigned)(spot->y + dist - bmaporgy)>>MAPBLOCKSHIFT; yh = (unsigned)(spot->y + dist - bmaporgy)>>MAPBLOCKSHIFT;
yl = (unsigned)(spot->y - dist - bmaporgy)>>MAPBLOCKSHIFT; yl = (unsigned)(spot->y - dist - bmaporgy)>>MAPBLOCKSHIFT;
xh = (unsigned)(spot->x + dist - bmaporgx)>>MAPBLOCKSHIFT; xh = (unsigned)(spot->x + dist - bmaporgx)>>MAPBLOCKSHIFT;
...@@ -4243,7 +4223,7 @@ void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 dama ...@@ -4243,7 +4223,7 @@ void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 dama
bombdamagetype = damagetype; bombdamagetype = damagetype;
bombsightcheck = sightcheck; bombsightcheck = sightcheck;
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_RadiusAttack); P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_RadiusAttack, bombspot);
} }
// //
...@@ -4330,7 +4310,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush, boolean crunch ...@@ -4330,7 +4310,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush, boolean crunch
{ {
crumble_t *crumbler; crumble_t *crumbler;
if (think->function.acp1 != (actionf_p1)T_StartCrumble) if (think->function != (actionf_p1)T_StartCrumble)
continue; continue;
crumbler = (crumble_t *)think; crumbler = (crumble_t *)think;
...@@ -4399,15 +4379,15 @@ static boolean P_CheckSectorPolyObjects(sector_t *sector, boolean realcrush, boo ...@@ -4399,15 +4379,15 @@ static boolean P_CheckSectorPolyObjects(sector_t *sector, boolean realcrush, boo
{ {
mobj_t *mo; mobj_t *mo;
blocknode_t *block; blocknode_t *block;
blocknode_t *next = NULL;
if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
continue; continue;
block = blocklinks[y * bmapwidth + x]; for (block = blocklinks[y * bmapwidth + x]; block != NULL; block = next)
for (; block; block = block->mnext)
{ {
mo = block->mobj; mo = block->mobj;
next = block->mnext;
// Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect // Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect
if (!P_MobjInsidePolyobj(po, mo)) if (!P_MobjInsidePolyobj(po, mo))
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // 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 // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -63,7 +63,7 @@ void P_ClosestPointOnLine(fixed_t x, fixed_t y, line_t *line, vertex_t *result) ...@@ -63,7 +63,7 @@ void P_ClosestPointOnLine(fixed_t x, fixed_t y, line_t *line, vertex_t *result)
vy = dy; vy = dy;
//Normalize (&V, &V); //Normalize (&V, &V);
magnitude = R_PointToDist2(line->v2->x, line->v2->y, startx, starty); magnitude = GetDistance2D(line->v2->x, line->v2->y, startx, starty);
vx = FixedDiv(vx, magnitude); vx = FixedDiv(vx, magnitude);
vy = FixedDiv(vy, magnitude); vy = FixedDiv(vy, magnitude);
...@@ -89,7 +89,7 @@ void P_ClosestPointOnLine3D(const vector3_t *p, const vector3_t *Line, vector3_t ...@@ -89,7 +89,7 @@ void P_ClosestPointOnLine3D(const vector3_t *p, const vector3_t *Line, vector3_t
FV3_SubEx(v2, v1, &V); FV3_SubEx(v2, v1, &V);
FV3_SubEx(p, v1, &c); FV3_SubEx(p, v1, &c);
d = R_PointToDist2(0, v2->z, R_PointToDist2(v2->x, v2->y, v1->x, v1->y), v1->z); d = GetDistance3D(v2->x, v2->y, v2->z, v1->x, v1->y, v1->z);
FV3_Copy(&n, &V); FV3_Copy(&n, &V);
FV3_Divide(&n, d); FV3_Divide(&n, d);
...@@ -500,8 +500,24 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) ...@@ -500,8 +500,24 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
INT32 texnum = R_GetTextureNum(side->midtexture); // make sure the texture is actually valid INT32 texnum = R_GetTextureNum(side->midtexture); // make sure the texture is actually valid
if (texnum) { if (texnum) {
fixed_t scaley = abs(side->scaley_mid);
fixed_t offsetvalue = FixedDiv(side->rowoffset + side->offsety_mid, scaley);
fixed_t midopentop, midopenbottom;
if (linedef->flags & ML_NOSKEW)
{
// Use the sector's actual heights if the midtexture is not skewed
midopentop = min(front->ceilingheight, back->ceilingheight);
midopenbottom = max(front->floorheight, back->floorheight);
}
else
{
midopentop = opentop;
midopenbottom = openbottom;
}
// Get the midtexture's height // Get the midtexture's height
texheight = textures[texnum]->height << FRACBITS; texheight = FixedDiv(textureheight[texnum], scaley);
// Set texbottom and textop to the Z coordinates of the texture's boundaries // Set texbottom and textop to the Z coordinates of the texture's boundaries
#if 0 #if 0
...@@ -509,26 +525,26 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) ...@@ -509,26 +525,26 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
// on non-solid polyobjects should NEVER happen in the future // on non-solid polyobjects should NEVER happen in the future
if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) { if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) {
if (linedef->flags & ML_WRAPMIDTEX && !side->repeatcnt) { // "infinite" repeat if (linedef->flags & ML_WRAPMIDTEX && !side->repeatcnt) { // "infinite" repeat
texbottom = back->floorheight + side->rowoffset + side->offsety_mid; texbottom = back->floorheight + offsetvalue;
textop = back->ceilingheight + side->rowoffset + side->offsety_mid; textop = back->ceilingheight + offsetvalue;
} else if (linedef->flags & ML_MIDTEX) { } else if (linedef->flags & ML_MIDTEX) {
texbottom = back->floorheight + side->rowoffset + side->offsety_mid; texbottom = back->floorheight + offsetvalue;
textop = texbottom + texheight*(side->repeatcnt+1); textop = texbottom + texheight*(side->repeatcnt+1);
} else { } else {
textop = back->ceilingheight + side->rowoffset + side->offsety_mid; textop = back->ceilingheight + offsetvalue;
texbottom = textop - texheight*(side->repeatcnt+1); texbottom = textop - texheight*(side->repeatcnt+1);
} }
} else } else
#endif #endif
{ {
if (linedef->flags & ML_WRAPMIDTEX && !side->repeatcnt) { // "infinite" repeat if (linedef->flags & ML_WRAPMIDTEX && !side->repeatcnt) { // "infinite" repeat
texbottom = openbottom + side->rowoffset + side->offsety_mid; texbottom = midopenbottom + offsetvalue;
textop = opentop + side->rowoffset + side->offsety_mid; textop = midopentop + offsetvalue;
} else if (linedef->flags & ML_MIDPEG) { } else if (linedef->flags & ML_MIDPEG) {
texbottom = openbottom + side->rowoffset + side->offsety_mid; texbottom = midopenbottom + offsetvalue;
textop = texbottom + texheight*(side->repeatcnt+1); textop = texbottom + texheight*(side->repeatcnt+1);
} else { } else {
textop = opentop + side->rowoffset + side->offsety_mid; textop = midopentop + offsetvalue;
texbottom = textop - texheight*(side->repeatcnt+1); texbottom = textop - texheight*(side->repeatcnt+1);
} }
} }
...@@ -539,11 +555,21 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) ...@@ -539,11 +555,21 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
delta2 = abs(thingtop - texmid); delta2 = abs(thingtop - texmid);
if (delta1 > delta2) { // Below if (delta1 > delta2) { // Below
if (opentop > texbottom) if (opentop > texbottom) {
opentop = texbottom; opentop = texbottom;
if (linedef->flags & ML_NOSKEW)
opentopslope = NULL; // Object is not actually on a slope
else
opentopslope = linedef->midtexslope;
}
} else { // Above } else { // Above
if (openbottom < textop) if (openbottom < textop) {
openbottom = textop; openbottom = textop;
if (linedef->flags & ML_NOSKEW)
openbottomslope = NULL; // Object is not actually on a slope
else
openbottomslope = linedef->midtexslope;
}
} }
} }
} }
...@@ -1024,35 +1050,39 @@ boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean (*func)(line_t *)) ...@@ -1024,35 +1050,39 @@ boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean (*func)(line_t *))
// //
// P_BlockThingsIterator // P_BlockThingsIterator
// //
boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean (*func)(mobj_t *)) boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean (*func)(mobj_t *), mobj_t *thing)
{ {
mobj_t *mobj; blocknode_t *block, *next = NULL;
blocknode_t *block;
boolean checkthing = false;
if (thing)
checkthing = true;
if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight)
return true; return true;
// Check interaction with the objects in the blockmap. // Check interaction with the objects in the blockmap.
for (block = blocklinks[y*bmapwidth + x]; block; block = block->mnext) for (block = blocklinks[y*bmapwidth + x]; block != NULL; block = next)
{ {
mobj = block->mobj; next = block->mnext; // We want to note our reference to mnext here!
if (!func(mobj)) if (!func(block->mobj))
return false; return false;
if (P_MobjWasRemoved(tmthing)) // func just broke blockmap chain, cannot continue.
if (checkthing && P_MobjWasRemoved(thing)) // func just popped our tmthing, cannot continue.
return true; return true;
} }
return true; return true;
} }
boolean P_DoBlockThingsIterate(int x1, int y1, int x2, int y2, boolean (*func)(mobj_t *)) boolean P_DoBlockThingsIterate(int x1, int y1, int x2, int y2, boolean (*func)(mobj_t *), mobj_t *thing)
{ {
boolean status = true; boolean status = true;
for (INT32 bx = x1; bx <= x2; bx++) for (INT32 bx = x1; bx <= x2; bx++)
for (INT32 by = y1; by <= y2; by++) for (INT32 by = y1; by <= y2; by++)
if (!P_BlockThingsIterator(bx, by, func)) if (!P_BlockThingsIterator(bx, by, func, thing))
status = false; status = false;
return status; return status;
...@@ -1425,7 +1455,7 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2, ...@@ -1425,7 +1455,7 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2,
INT32 flags, traverser_t trav) INT32 flags, traverser_t trav)
{ {
fixed_t xt1, yt1, xt2, yt2; fixed_t xt1, yt1, xt2, yt2;
fixed_t xstep, ystep, partial, xintercept, yintercept; fixed_t xstep, ystep, partialx, partialy, xintercept, yintercept;
INT32 mapx, mapy, mapxstep, mapystep, count; INT32 mapx, mapy, mapxstep, mapystep, count;
earlyout = flags & PT_EARLYOUT; earlyout = flags & PT_EARLYOUT;
...@@ -1444,56 +1474,82 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2, ...@@ -1444,56 +1474,82 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2,
trace.dx = px2 - px1; trace.dx = px2 - px1;
trace.dy = py2 - py1; trace.dy = py2 - py1;
px1 -= bmaporgx; xt1 = px1>>MAPBLOCKSHIFT;
py1 -= bmaporgy; yt1 = py1>>MAPBLOCKSHIFT;
xt1 = (unsigned)px1>>MAPBLOCKSHIFT; px1 = (unsigned)(px1 - bmaporgx);
yt1 = (unsigned)py1>>MAPBLOCKSHIFT; py1 = (unsigned)(py1 - bmaporgy);
px2 -= bmaporgx; xt2 = px2>>MAPBLOCKSHIFT;
py2 -= bmaporgy; yt2 = py2>>MAPBLOCKSHIFT;
xt2 = (unsigned)px2>>MAPBLOCKSHIFT; px2 = (unsigned)(px2 - bmaporgx);
yt2 = (unsigned)py2>>MAPBLOCKSHIFT; py2 = (unsigned)(py2 - bmaporgy);
if (xt2 > xt1) if (xt2 > xt1)
{ {
mapxstep = 1; mapxstep = 1;
partial = FRACUNIT - ((px1>>MAPBTOFRAC) & FRACMASK); partialx = FRACUNIT - (((unsigned)px1>>MAPBTOFRAC) & FRACMASK);
ystep = FixedDiv(py2 - py1, abs(px2 - px1)); ystep = FixedDiv(py2 - py1, abs(px2 - px1));
} }
else if (xt2 < xt1) else if (xt2 < xt1)
{ {
mapxstep = -1; mapxstep = -1;
partial = (px1>>MAPBTOFRAC) & FRACMASK; partialx = ((unsigned)px1>>MAPBTOFRAC) & FRACMASK;
ystep = FixedDiv(py2 - py1, abs(px2 - px1)); ystep = FixedDiv(py2 - py1, abs(px2 - px1));
} }
else else
{ {
mapxstep = 0; mapxstep = 0;
partial = FRACUNIT; partialx = FRACUNIT;
ystep = 256*FRACUNIT; ystep = 256*FRACUNIT;
} }
yintercept = (py1>>MAPBTOFRAC) + FixedMul(partial, ystep); yintercept = ((unsigned)py1>>MAPBTOFRAC) + FixedMul(partialx, ystep);
if (yt2 > yt1) if (yt2 > yt1)
{ {
mapystep = 1; mapystep = 1;
partial = FRACUNIT - ((py1>>MAPBTOFRAC) & FRACMASK); partialy = FRACUNIT - (((unsigned)py1>>MAPBTOFRAC) & FRACMASK);
xstep = FixedDiv(px2 - px1, abs(py2 - py1)); xstep = FixedDiv(px2 - px1, abs(py2 - py1));
} }
else if (yt2 < yt1) else if (yt2 < yt1)
{ {
mapystep = -1; mapystep = -1;
partial = (py1>>MAPBTOFRAC) & FRACMASK; partialy = ((unsigned)py1>>MAPBTOFRAC) & FRACMASK;
xstep = FixedDiv(px2 - px1, abs(py2 - py1)); xstep = FixedDiv(px2 - px1, abs(py2 - py1));
} }
else else
{ {
mapystep = 0; mapystep = 0;
partial = FRACUNIT; partialy = FRACUNIT;
xstep = 256*FRACUNIT; xstep = 256*FRACUNIT;
} }
xintercept = (px1>>MAPBTOFRAC) + FixedMul(partial, xstep); xintercept = ((unsigned)px1>>MAPBTOFRAC) + FixedMul(partialy, xstep);
// [RH] Fix for traces that pass only through blockmap corners. In that case,
// xintercept and yintercept can both be set ahead of mapx and mapy, so the
// for loop would never advance anywhere.
if (abs(xstep) == 1 && abs(ystep) == 1)
{
if (ystep < 0)
{
partialx = FRACUNIT - partialx;
}
if (xstep < 0)
{
partialy = FRACUNIT - partialy;
}
if (partialx == partialy)
{
xintercept = xt1;
yintercept = yt1;
}
}
xt1 = (unsigned)px1>>MAPBLOCKSHIFT;
yt1 = (unsigned)py1>>MAPBLOCKSHIFT;
xt2 = (unsigned)px2>>MAPBLOCKSHIFT;
yt2 = (unsigned)py2>>MAPBLOCKSHIFT;
// Step through map blocks. // Step through map blocks.
// Count is present to prevent a round off error // Count is present to prevent a round off error
...@@ -1508,23 +1564,67 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2, ...@@ -1508,23 +1564,67 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2,
return false; // early out return false; // early out
if (flags & PT_ADDTHINGS) if (flags & PT_ADDTHINGS)
if (!P_BlockThingsIterator(mapx, mapy, PIT_AddThingIntercepts)) if (!P_BlockThingsIterator(mapx, mapy, PIT_AddThingIntercepts, NULL))
return false; // early out return false; // early out
if (mapx == xt2 && mapy == yt2) // both coordinates reached the end, so end the traversing.
if ((mapxstep | mapystep) == 0)
break; break;
if ((yintercept >> FRACBITS) == mapy) // [RH] Handle corner cases properly instead of pretending they don't exist.
switch ((((yintercept >> FRACBITS) == mapy) << 1) | ((xintercept >> FRACBITS) == mapx))
{ {
case 0: // neither xintercept nor yintercept match!
count = 64; // Stop traversing, because somebody screwed up.
break;
case 1: // xintercept matches
xintercept += xstep;
mapy += mapystep;
if (mapy == yt2)
mapystep = 0;
break;
case 2: // yintercept matches
yintercept += ystep; yintercept += ystep;
mapx += mapxstep; mapx += mapxstep;
if (mapx == xt2)
mapxstep = 0;
break;
case 3: // xintercept and yintercept both match
// The trace is exiting a block through its corner. Not only does the block
// being entered need to be checked (which will happen when this loop
// continues), but the other two blocks adjacent to the corner also need to
// be checked.
if (flags & PT_ADDLINES)
{
if (!P_BlockLinesIterator(mapx + mapxstep, mapy, PIT_AddLineIntercepts))
return false; // early out
if (!P_BlockLinesIterator(mapx, mapy + mapystep, PIT_AddLineIntercepts))
return false; // early out
} }
else if ((xintercept >> FRACBITS) == mapx)
if (flags & PT_ADDTHINGS)
{ {
if (!P_BlockThingsIterator(mapx + mapxstep, mapy, PIT_AddThingIntercepts, NULL))
return false; // early out
if (!P_BlockThingsIterator(mapx, mapy + mapystep, PIT_AddThingIntercepts, NULL))
return false; // early out
}
xintercept += xstep; xintercept += xstep;
yintercept += ystep;
mapx += mapxstep;
mapy += mapystep; mapy += mapystep;
if (mapx == xt2)
mapxstep = 0;
if (mapy == yt2)
mapystep = 0;
break;
} }
} }
// Go through the sorted list // Go through the sorted list
return P_TraverseIntercepts(trav, FRACUNIT); return P_TraverseIntercepts(trav, FRACUNIT);
} }
......
// SONIC ROBO BLAST 2 // SONIC ROBO BLAST 2
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1998-2000 by DooM Legacy Team. // 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 // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -61,7 +61,7 @@ extern ffloor_t *openfloorrover, *openceilingrover; ...@@ -61,7 +61,7 @@ extern ffloor_t *openfloorrover, *openceilingrover;
void P_LineOpening(line_t *plinedef, mobj_t *mobj); void P_LineOpening(line_t *plinedef, mobj_t *mobj);
boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean(*func)(line_t *)); boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean(*func)(line_t *));
boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean(*func)(mobj_t *)); boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean(*func)(mobj_t *), mobj_t *thing);
void P_ClearBlockNodes(void); void P_ClearBlockNodes(void);
...@@ -94,7 +94,7 @@ typedef struct bthingit_s ...@@ -94,7 +94,7 @@ typedef struct bthingit_s
bthingit_t *P_NewBlockThingsIterator(int x1, int y1, int x2, int y2); bthingit_t *P_NewBlockThingsIterator(int x1, int y1, int x2, int y2);
mobj_t *P_BlockThingsIteratorNext(bthingit_t *it, boolean centeronly); mobj_t *P_BlockThingsIteratorNext(bthingit_t *it, boolean centeronly);
void P_FreeBlockThingsIterator(bthingit_t *it); void P_FreeBlockThingsIterator(bthingit_t *it);
boolean P_DoBlockThingsIterate(int x1, int y1, int x2, int y2, boolean (*func)(mobj_t *)); boolean P_DoBlockThingsIterate(int x1, int y1, int x2, int y2, boolean (*func)(mobj_t *), mobj_t *thing);
#define PT_ADDLINES 1 #define PT_ADDLINES 1
#define PT_ADDTHINGS 2 #define PT_ADDTHINGS 2
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team. // 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 // This program is free software distributed under the
// terms of the GNU General Public License, version 2. // terms of the GNU General Public License, version 2.
...@@ -36,10 +36,11 @@ ...@@ -36,10 +36,11 @@
#include "p_slopes.h" #include "p_slopes.h"
#include "f_finale.h" #include "f_finale.h"
#include "m_cond.h" #include "m_cond.h"
#include "simple_hashmap.h"
#include "netcode/net_command.h" #include "netcode/net_command.h"
static CV_PossibleValue_t CV_BobSpeed[] = {{0, "MIN"}, {4*FRACUNIT, "MAX"}, {0, NULL}}; static CV_PossibleValue_t CV_BobSpeed[] = {{0, "MIN"}, {4*FRACUNIT, "MAX"}, {0, NULL}};
consvar_t cv_movebob = CVAR_INIT ("movebob", "1.0", CV_FLOAT|CV_SAVE, CV_BobSpeed, NULL); consvar_t cv_movebob = CVAR_INIT ("movebob", "0.25", CV_FLOAT|CV_SAVE, CV_BobSpeed, NULL);
actioncache_t actioncachehead; actioncache_t actioncachehead;
...@@ -63,7 +64,7 @@ void P_RunCachedActions(void) ...@@ -63,7 +64,7 @@ void P_RunCachedActions(void)
var2 = states[ac->statenum].var2; var2 = states[ac->statenum].var2;
astate = &states[ac->statenum]; astate = &states[ac->statenum];
if (ac->mobj && !P_MobjWasRemoved(ac->mobj)) // just in case... if (ac->mobj && !P_MobjWasRemoved(ac->mobj)) // just in case...
states[ac->statenum].action.acp1(ac->mobj); states[ac->statenum].action(ac->mobj);
next = ac->next; next = ac->next;
Z_Free(ac); Z_Free(ac);
} }
...@@ -90,17 +91,21 @@ static void P_SetupStateAnimation(mobj_t *mobj, state_t *st) ...@@ -90,17 +91,21 @@ static void P_SetupStateAnimation(mobj_t *mobj, state_t *st)
if (mobj->sprite == SPR_PLAY && mobj->skin) if (mobj->sprite == SPR_PLAY && mobj->skin)
{ {
spritedef_t *spritedef = P_GetSkinSpritedef(mobj->skin, mobj->sprite2); spritedef_t *spritedef = P_GetSkinSpritedef(mobj->skin, mobj->sprite2);
animlength = (INT32)(spritedef->numframes); animlength = (INT32)(spritedef->numframes) - 1;
} }
else else
animlength = st->var1; animlength = st->var1;
if (!(st->frame & FF_ANIMATE)) if (!(st->frame & FF_ANIMATE))
{
mobj->anim_duration = 0;
return; return;
}
if (animlength <= 0 || st->var2 == 0) if (animlength <= 0 || st->var2 == 0)
{ {
mobj->frame &= ~FF_ANIMATE; mobj->frame &= ~FF_ANIMATE;
mobj->anim_duration = 0;
return; // Crash/stupidity prevention return; // Crash/stupidity prevention
} }
...@@ -174,24 +179,58 @@ static void P_CycleMobjState(mobj_t *mobj) ...@@ -174,24 +179,58 @@ static void P_CycleMobjState(mobj_t *mobj)
} }
} }
// static panim_t GetPlayerAnimationFromState(player_t *player, statenum_t state)
// P_CycleMobjState for players.
//
static void P_CyclePlayerMobjState(mobj_t *mobj)
{ {
// state animations switch(P_GetCanonicalPlayerState(player, state))
P_CycleStateAnimation(mobj);
// cycle through states,
// calling action functions at transitions
if (mobj->tics != -1)
{ {
mobj->tics--; case S_PLAY_STND:
case S_PLAY_WAIT:
// you can cycle through multiple states in a tic case S_PLAY_NIGHTS_STAND:
if (!mobj->tics && mobj->state) return PA_IDLE;
if (!P_SetMobjState(mobj, mobj->state->nextstate)) case S_PLAY_EDGE:
return; // freed itself return PA_EDGE;
case S_PLAY_WALK:
case S_PLAY_SKID:
case S_PLAY_FLOAT:
return PA_WALK;
case S_PLAY_RUN:
case S_PLAY_FLOAT_RUN:
return PA_RUN;
case S_PLAY_DASH:
return PA_DASH;
case S_PLAY_PAIN:
case S_PLAY_STUN:
return PA_PAIN;
case S_PLAY_ROLL:
//case S_PLAY_SPINDASH: -- everyone can ROLL thanks to zoom tubes...
case S_PLAY_NIGHTS_ATTACK:
return PA_ROLL;
case S_PLAY_JUMP:
return PA_JUMP;
case S_PLAY_SPRING:
return PA_SPRING;
case S_PLAY_FALL:
case S_PLAY_NIGHTS_FLOAT:
return PA_FALL;
case S_PLAY_FLY:
case S_PLAY_FLY_TIRED:
case S_PLAY_SWIM:
case S_PLAY_GLIDE:
case S_PLAY_BOUNCE:
case S_PLAY_BOUNCE_LANDING:
case S_PLAY_TWINSPIN:
return PA_ABILITY;
case S_PLAY_SPINDASH: // ...but the act of SPINDASHING is charability2 specific.
case S_PLAY_FIRE:
case S_PLAY_FIRE_FINISH:
case S_PLAY_MELEE:
case S_PLAY_MELEE_FINISH:
case S_PLAY_MELEE_LANDING:
return PA_ABILITY2;
case S_PLAY_RIDE:
return PA_RIDE;
default:
return PA_ETC;
} }
} }
...@@ -218,6 +257,12 @@ static boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) ...@@ -218,6 +257,12 @@ static boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
I_Error("P_SetPlayerMobjState used for non-player mobj. Use P_SetMobjState instead!\n(Mobj type: %d, State: %d)", mobj->type, state); I_Error("P_SetPlayerMobjState used for non-player mobj. Use P_SetMobjState instead!\n(Mobj type: %d, State: %d)", mobj->type, state);
#endif #endif
// If the state has been overriden for this skin, use the replacement instead
statenum_t customskinstate;
SIMPLEHASH_FIND_INT(skins[player->skin]->defaulttocustomstate, hashentry_int32_int32_t, state, S_NULL, customskinstate)
if (customskinstate)
state = customskinstate;
// Catch falling for nojumpspin // Catch falling for nojumpspin
if ((state == S_PLAY_JUMP) && (player->charflags & SF_NOJUMPSPIN) && (P_MobjFlip(mobj)*mobj->momz < 0)) if ((state == S_PLAY_JUMP) && (player->charflags & SF_NOJUMPSPIN) && (P_MobjFlip(mobj)*mobj->momz < 0))
return P_SetPlayerMobjState(mobj, S_PLAY_FALL); return P_SetPlayerMobjState(mobj, S_PLAY_FALL);
...@@ -239,88 +284,24 @@ static boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) ...@@ -239,88 +284,24 @@ static boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
{ {
if (state == S_PLAY_JUMP) if (state == S_PLAY_JUMP)
{ {
if (player->mo->state-states == S_PLAY_WALK) if (P_IsPlayerInState(player, S_PLAY_WALK))
return P_SetPlayerMobjState(mobj, S_PLAY_FLOAT); return P_SetPlayerMobjState(mobj, S_PLAY_FLOAT);
return true; return true;
} }
else if (player->mo->state-states == S_PLAY_FLOAT && state == S_PLAY_STND) else if (P_IsPlayerInState(player, S_PLAY_FLOAT) && state == S_PLAY_STND)
return true; return true;
} }
// You were in pain state after taking a hit, and you're moving out of pain state now? // You were in pain state after taking a hit, and you're moving out of pain state now?
else if (mobj->state == &states[mobj->info->painstate] && player->powers[pw_flashing] == flashingtics && state != mobj->info->painstate) else if (P_IsPlayerInState(player, S_PLAY_PAIN)
&& player->powers[pw_flashing] == flashingtics
&& P_GetCanonicalPlayerState(player, state) != S_PLAY_PAIN)
{ {
// Start flashing, since you've landed. // Start flashing, since you've landed.
player->powers[pw_flashing] = flashingtics-1; player->powers[pw_flashing] = flashingtics-1;
P_DoPityCheck(player); P_DoPityCheck(player);
} }
// Set animation state player->panim = GetPlayerAnimationFromState(player, state);
// The pflags version of this was just as convoluted.
switch(state)
{
case S_PLAY_STND:
case S_PLAY_WAIT:
case S_PLAY_NIGHTS_STAND:
player->panim = PA_IDLE;
break;
case S_PLAY_EDGE:
player->panim = PA_EDGE;
break;
case S_PLAY_WALK:
case S_PLAY_SKID:
case S_PLAY_FLOAT:
player->panim = PA_WALK;
break;
case S_PLAY_RUN:
case S_PLAY_FLOAT_RUN:
player->panim = PA_RUN;
break;
case S_PLAY_DASH:
player->panim = PA_DASH;
break;
case S_PLAY_PAIN:
case S_PLAY_STUN:
player->panim = PA_PAIN;
break;
case S_PLAY_ROLL:
//case S_PLAY_SPINDASH: -- everyone can ROLL thanks to zoom tubes...
case S_PLAY_NIGHTS_ATTACK:
player->panim = PA_ROLL;
break;
case S_PLAY_JUMP:
player->panim = PA_JUMP;
break;
case S_PLAY_SPRING:
player->panim = PA_SPRING;
break;
case S_PLAY_FALL:
case S_PLAY_NIGHTS_FLOAT:
player->panim = PA_FALL;
break;
case S_PLAY_FLY:
case S_PLAY_FLY_TIRED:
case S_PLAY_SWIM:
case S_PLAY_GLIDE:
case S_PLAY_BOUNCE:
case S_PLAY_BOUNCE_LANDING:
case S_PLAY_TWINSPIN:
player->panim = PA_ABILITY;
break;
case S_PLAY_SPINDASH: // ...but the act of SPINDASHING is charability2 specific.
case S_PLAY_FIRE:
case S_PLAY_FIRE_FINISH:
case S_PLAY_MELEE:
case S_PLAY_MELEE_FINISH:
case S_PLAY_MELEE_LANDING:
player->panim = PA_ABILITY2;
break;
case S_PLAY_RIDE:
player->panim = PA_RIDE;
break;
default:
player->panim = PA_ETC;
break;
}
if (recursion++) // if recursion detected, if (recursion++) // if recursion detected,
memset(seenstate = tempstate, 0, sizeof tempstate); // clear state table memset(seenstate = tempstate, 0, sizeof tempstate); // clear state table
...@@ -340,8 +321,10 @@ static boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) ...@@ -340,8 +321,10 @@ static boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
mobj->state = st; mobj->state = st;
mobj->tics = st->tics; mobj->tics = st->tics;
// Adjust the player's animation speed to match their velocity. // Adjust the player's animation speed
if (player->panim == PA_EDGE && (player->charflags & SF_FASTEDGE)) if (state == S_PLAY_WAIT && (player->charflags & SF_FASTWAIT))
mobj->tics = 5;
else if (player->panim == PA_EDGE && (player->charflags & SF_FASTEDGE))
mobj->tics = 2; mobj->tics = 2;
else if (!(disableSpeedAdjust || player->charflags & SF_NOSPEEDADJUST)) else if (!(disableSpeedAdjust || player->charflags & SF_NOSPEEDADJUST))
{ {
...@@ -487,12 +470,12 @@ static boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) ...@@ -487,12 +470,12 @@ static boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
// Modified handling. // Modified handling.
// Call action functions when the state is set // Call action functions when the state is set
if (st->action.acp1) if (st->action)
{ {
var1 = st->var1; var1 = st->var1;
var2 = st->var2; var2 = st->var2;
astate = st; astate = st;
st->action.acp1(mobj); st->action(mobj);
// woah. a player was removed by an action. // woah. a player was removed by an action.
// this sounds like a VERY BAD THING, but there's nothing we can do now... // this sounds like a VERY BAD THING, but there's nothing we can do now...
...@@ -629,12 +612,12 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state) ...@@ -629,12 +612,12 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state)
// Modified handling. // Modified handling.
// Call action functions when the state is set // Call action functions when the state is set
if (st->action.acp1) if (st->action)
{ {
var1 = st->var1; var1 = st->var1;
var2 = st->var2; var2 = st->var2;
astate = st; astate = st;
st->action.acp1(mobj); st->action(mobj);
if (P_MobjWasRemoved(mobj)) if (P_MobjWasRemoved(mobj))
return false; return false;
} }
...@@ -765,7 +748,7 @@ void P_EmeraldManager(void) ...@@ -765,7 +748,7 @@ void P_EmeraldManager(void)
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) 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; continue;
mo = (mobj_t *)think; mo = (mobj_t *)think;
...@@ -793,7 +776,7 @@ void P_EmeraldManager(void) ...@@ -793,7 +776,7 @@ void P_EmeraldManager(void)
// But wait! We need to check all the players too, to see if anyone has some of the emeralds. // But wait! We need to check all the players too, to see if anyone has some of the emeralds.
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i] || players[i].spectator) if (!players[i].ingame || players[i].spectator)
continue; continue;
if (!players[i].mo) if (!players[i].mo)
...@@ -937,7 +920,7 @@ void P_ExplodeMissile(mobj_t *mo) ...@@ -937,7 +920,7 @@ void P_ExplodeMissile(mobj_t *mo)
explodemo->destscale = mo->destscale; explodemo->destscale = mo->destscale;
explodemo->momx += (P_RandomByte() % 32) * FixedMul(FRACUNIT/8, explodemo->scale); explodemo->momx += (P_RandomByte() % 32) * FixedMul(FRACUNIT/8, explodemo->scale);
explodemo->momy += (P_RandomByte() % 32) * FixedMul(FRACUNIT/8, explodemo->scale); explodemo->momy += (P_RandomByte() % 32) * FixedMul(FRACUNIT/8, explodemo->scale);
S_StartSound(explodemo, sfx_pop); S_StartSoundFromMobj(explodemo, sfx_pop);
} }
explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE); explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE);
if (!P_MobjWasRemoved(explodemo)) if (!P_MobjWasRemoved(explodemo))
...@@ -946,7 +929,7 @@ void P_ExplodeMissile(mobj_t *mo) ...@@ -946,7 +929,7 @@ void P_ExplodeMissile(mobj_t *mo)
explodemo->destscale = mo->destscale; explodemo->destscale = mo->destscale;
explodemo->momx += (P_RandomByte() % 64) * FixedMul(FRACUNIT/8, explodemo->scale); explodemo->momx += (P_RandomByte() % 64) * FixedMul(FRACUNIT/8, explodemo->scale);
explodemo->momy -= (P_RandomByte() % 64) * FixedMul(FRACUNIT/8, explodemo->scale); explodemo->momy -= (P_RandomByte() % 64) * FixedMul(FRACUNIT/8, explodemo->scale);
S_StartSound(explodemo, sfx_dmpain); S_StartSoundFromMobj(explodemo, sfx_dmpain);
} }
explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE); explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE);
if (!P_MobjWasRemoved(explodemo)) if (!P_MobjWasRemoved(explodemo))
...@@ -955,7 +938,7 @@ void P_ExplodeMissile(mobj_t *mo) ...@@ -955,7 +938,7 @@ void P_ExplodeMissile(mobj_t *mo)
explodemo->destscale = mo->destscale; explodemo->destscale = mo->destscale;
explodemo->momx -= (P_RandomByte() % 128) * FixedMul(FRACUNIT/8, explodemo->scale); explodemo->momx -= (P_RandomByte() % 128) * FixedMul(FRACUNIT/8, explodemo->scale);
explodemo->momy += (P_RandomByte() % 128) * FixedMul(FRACUNIT/8, explodemo->scale); explodemo->momy += (P_RandomByte() % 128) * FixedMul(FRACUNIT/8, explodemo->scale);
S_StartSound(explodemo, sfx_pop); S_StartSoundFromMobj(explodemo, sfx_pop);
} }
explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE); explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE);
if (!P_MobjWasRemoved(explodemo)) if (!P_MobjWasRemoved(explodemo))
...@@ -964,7 +947,7 @@ void P_ExplodeMissile(mobj_t *mo) ...@@ -964,7 +947,7 @@ void P_ExplodeMissile(mobj_t *mo)
explodemo->destscale = mo->destscale; explodemo->destscale = mo->destscale;
explodemo->momx -= (P_RandomByte() % 96) * FixedMul(FRACUNIT/8, explodemo->scale); explodemo->momx -= (P_RandomByte() % 96) * FixedMul(FRACUNIT/8, explodemo->scale);
explodemo->momy -= (P_RandomByte() % 96) * FixedMul(FRACUNIT/8, explodemo->scale); explodemo->momy -= (P_RandomByte() % 96) * FixedMul(FRACUNIT/8, explodemo->scale);
S_StartSound(explodemo, sfx_cybdth); S_StartSoundFromMobj(explodemo, sfx_cybdth);
} }
} }
...@@ -974,7 +957,7 @@ void P_ExplodeMissile(mobj_t *mo) ...@@ -974,7 +957,7 @@ void P_ExplodeMissile(mobj_t *mo)
mo->flags |= MF_NOCLIPTHING; // Dummy flag to indicate that this was already called. mo->flags |= MF_NOCLIPTHING; // Dummy flag to indicate that this was already called.
if (mo->info->deathsound && !(mo->flags2 & MF2_DEBRIS)) if (mo->info->deathsound && !(mo->flags2 & MF2_DEBRIS))
S_StartSound(mo, mo->info->deathsound); S_StartSoundFromMobj(mo, mo->info->deathsound);
P_SetMobjState(mo, mo->info->deathstate); P_SetMobjState(mo, mo->info->deathstate);
} }
...@@ -1108,9 +1091,8 @@ static fixed_t HighestOnLine(fixed_t radius, fixed_t x, fixed_t y, line_t *line, ...@@ -1108,9 +1091,8 @@ static fixed_t HighestOnLine(fixed_t radius, fixed_t x, fixed_t y, line_t *line,
); );
} }
fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect) fixed_t P_MobjFloorZ(sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, fixed_t radius, line_t *line, boolean lowest, boolean perfect)
{ {
I_Assert(mobj != NULL);
I_Assert(sector != NULL); I_Assert(sector != NULL);
if (sector->f_slope) { if (sector->f_slope) {
...@@ -1119,14 +1101,14 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t ...@@ -1119,14 +1101,14 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t
// Get the corner of the object that should be the highest on the slope // Get the corner of the object that should be the highest on the slope
if (slope->d.x < 0) if (slope->d.x < 0)
testx = mobj->radius; testx = radius;
else else
testx = -mobj->radius; testx = -radius;
if (slope->d.y < 0) if (slope->d.y < 0)
testy = mobj->radius; testy = radius;
else else
testy = -mobj->radius; testy = -radius;
if ((slope->zdelta > 0) ^ !!(lowest)) { if ((slope->zdelta > 0) ^ !!(lowest)) {
testx = -testx; testx = -testx;
...@@ -1141,7 +1123,7 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t ...@@ -1141,7 +1123,7 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t
return P_GetSlopeZAt(slope, testx, testy); return P_GetSlopeZAt(slope, testx, testy);
// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point // If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
if (perfect) { if (perfect && boundsec) {
size_t i; size_t i;
line_t *ld; line_t *ld;
fixed_t bbox[4]; fixed_t bbox[4];
...@@ -1152,10 +1134,10 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t ...@@ -1152,10 +1134,10 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t
else else
finalheight = INT32_MIN; finalheight = INT32_MIN;
bbox[BOXLEFT] = x-mobj->radius; bbox[BOXLEFT] = x-radius;
bbox[BOXRIGHT] = x+mobj->radius; bbox[BOXRIGHT] = x+radius;
bbox[BOXTOP] = y+mobj->radius; bbox[BOXTOP] = y+radius;
bbox[BOXBOTTOM] = y-mobj->radius; bbox[BOXBOTTOM] = y-radius;
for (i = 0; i < boundsec->linecount; i++) { for (i = 0; i < boundsec->linecount; i++) {
ld = boundsec->lines[i]; ld = boundsec->lines[i];
...@@ -1167,9 +1149,9 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t ...@@ -1167,9 +1149,9 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t
continue; continue;
if (lowest) if (lowest)
finalheight = min(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, true)); finalheight = min(finalheight, HighestOnLine(radius, x, y, ld, slope, true));
else else
finalheight = max(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, false)); finalheight = max(finalheight, HighestOnLine(radius, x, y, ld, slope, false));
} }
return finalheight; return finalheight;
...@@ -1180,14 +1162,13 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t ...@@ -1180,14 +1162,13 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t
if (line == NULL) if (line == NULL)
return P_GetSlopeZAt(slope, x, y); return P_GetSlopeZAt(slope, x, y);
return HighestOnLine(mobj->radius, x, y, line, slope, lowest); return HighestOnLine(radius, x, y, line, slope, lowest);
} else // Well, that makes it easy. Just get the floor height } else // Well, that makes it easy. Just get the floor height
return sector->floorheight; return sector->floorheight;
} }
fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect) fixed_t P_MobjCeilingZ(sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, fixed_t radius, line_t *line, boolean lowest, boolean perfect)
{ {
I_Assert(mobj != NULL);
I_Assert(sector != NULL); I_Assert(sector != NULL);
if (sector->c_slope) { if (sector->c_slope) {
...@@ -1196,14 +1177,14 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed ...@@ -1196,14 +1177,14 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed
// Get the corner of the object that should be the highest on the slope // Get the corner of the object that should be the highest on the slope
if (slope->d.x < 0) if (slope->d.x < 0)
testx = mobj->radius; testx = radius;
else else
testx = -mobj->radius; testx = -radius;
if (slope->d.y < 0) if (slope->d.y < 0)
testy = mobj->radius; testy = radius;
else else
testy = -mobj->radius; testy = -radius;
if ((slope->zdelta > 0) ^ !!(lowest)) { if ((slope->zdelta > 0) ^ !!(lowest)) {
testx = -testx; testx = -testx;
...@@ -1218,7 +1199,7 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed ...@@ -1218,7 +1199,7 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed
return P_GetSlopeZAt(slope, testx, testy); return P_GetSlopeZAt(slope, testx, testy);
// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point // If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
if (perfect) { if (perfect && boundsec) {
size_t i; size_t i;
line_t *ld; line_t *ld;
fixed_t bbox[4]; fixed_t bbox[4];
...@@ -1229,10 +1210,10 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed ...@@ -1229,10 +1210,10 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed
else else
finalheight = INT32_MIN; finalheight = INT32_MIN;
bbox[BOXLEFT] = x-mobj->radius; bbox[BOXLEFT] = x-radius;
bbox[BOXRIGHT] = x+mobj->radius; bbox[BOXRIGHT] = x+radius;
bbox[BOXTOP] = y+mobj->radius; bbox[BOXTOP] = y+radius;
bbox[BOXBOTTOM] = y-mobj->radius; bbox[BOXBOTTOM] = y-radius;
for (i = 0; i < boundsec->linecount; i++) { for (i = 0; i < boundsec->linecount; i++) {
ld = boundsec->lines[i]; ld = boundsec->lines[i];
...@@ -1244,9 +1225,9 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed ...@@ -1244,9 +1225,9 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed
continue; continue;
if (lowest) if (lowest)
finalheight = min(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, true)); finalheight = min(finalheight, HighestOnLine(radius, x, y, ld, slope, true));
else else
finalheight = max(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, false)); finalheight = max(finalheight, HighestOnLine(radius, x, y, ld, slope, false));
} }
return finalheight; return finalheight;
...@@ -1257,165 +1238,11 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed ...@@ -1257,165 +1238,11 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed
if (line == NULL) if (line == NULL)
return P_GetSlopeZAt(slope, x, y); return P_GetSlopeZAt(slope, x, y);
return HighestOnLine(mobj->radius, x, y, line, slope, lowest); return HighestOnLine(radius, x, y, line, slope, lowest);
} else // Well, that makes it easy. Just get the ceiling height } else // Well, that makes it easy. Just get the ceiling height
return sector->ceilingheight; return sector->ceilingheight;
} }
// Now do the same as all above, but for cameras because apparently cameras are special?
fixed_t P_CameraFloorZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect)
{
I_Assert(mobj != NULL);
I_Assert(sector != NULL);
if (sector->f_slope) {
fixed_t testx, testy;
pslope_t *slope = sector->f_slope;
// Get the corner of the object that should be the highest on the slope
if (slope->d.x < 0)
testx = mobj->radius;
else
testx = -mobj->radius;
if (slope->d.y < 0)
testy = mobj->radius;
else
testy = -mobj->radius;
if ((slope->zdelta > 0) ^ !!(lowest)) {
testx = -testx;
testy = -testy;
}
testx += x;
testy += y;
// If the highest point is in the sector, then we have it easy! Just get the Z at that point
if (R_IsPointInSector(boundsec ? boundsec : sector, testx, testy))
return P_GetSlopeZAt(slope, testx, testy);
// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
if (perfect) {
size_t i;
line_t *ld;
fixed_t bbox[4];
fixed_t finalheight;
if (lowest)
finalheight = INT32_MAX;
else
finalheight = INT32_MIN;
bbox[BOXLEFT] = x-mobj->radius;
bbox[BOXRIGHT] = x+mobj->radius;
bbox[BOXTOP] = y+mobj->radius;
bbox[BOXBOTTOM] = y-mobj->radius;
for (i = 0; i < boundsec->linecount; i++) {
ld = boundsec->lines[i];
if (bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || bbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
|| bbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || bbox[BOXBOTTOM] >= ld->bbox[BOXTOP])
continue;
if (P_BoxOnLineSide(bbox, ld) != -1)
continue;
if (lowest)
finalheight = min(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, true));
else
finalheight = max(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, false));
}
return finalheight;
}
// If we're just testing for base sector location (no collision line), just go for the center's spot...
// It'll get fixed when we test for collision anyway, and the final result can't be lower than this
if (line == NULL)
return P_GetSlopeZAt(slope, x, y);
return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
} else // Well, that makes it easy. Just get the floor height
return sector->floorheight;
}
fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect)
{
I_Assert(mobj != NULL);
I_Assert(sector != NULL);
if (sector->c_slope) {
fixed_t testx, testy;
pslope_t *slope = sector->c_slope;
// Get the corner of the object that should be the highest on the slope
if (slope->d.x < 0)
testx = mobj->radius;
else
testx = -mobj->radius;
if (slope->d.y < 0)
testy = mobj->radius;
else
testy = -mobj->radius;
if ((slope->zdelta > 0) ^ !!(lowest)) {
testx = -testx;
testy = -testy;
}
testx += x;
testy += y;
// If the highest point is in the sector, then we have it easy! Just get the Z at that point
if (R_IsPointInSector(boundsec ? boundsec : sector, testx, testy))
return P_GetSlopeZAt(slope, testx, testy);
// If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point
if (perfect) {
size_t i;
line_t *ld;
fixed_t bbox[4];
fixed_t finalheight;
if (lowest)
finalheight = INT32_MAX;
else
finalheight = INT32_MIN;
bbox[BOXLEFT] = x-mobj->radius;
bbox[BOXRIGHT] = x+mobj->radius;
bbox[BOXTOP] = y+mobj->radius;
bbox[BOXBOTTOM] = y-mobj->radius;
for (i = 0; i < boundsec->linecount; i++) {
ld = boundsec->lines[i];
if (bbox[BOXRIGHT] <= ld->bbox[BOXLEFT] || bbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
|| bbox[BOXTOP] <= ld->bbox[BOXBOTTOM] || bbox[BOXBOTTOM] >= ld->bbox[BOXTOP])
continue;
if (P_BoxOnLineSide(bbox, ld) != -1)
continue;
if (lowest)
finalheight = min(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, true));
else
finalheight = max(finalheight, HighestOnLine(mobj->radius, x, y, ld, slope, false));
}
return finalheight;
}
// If we're just testing for base sector location (no collision line), just go for the center's spot...
// It'll get fixed when we test for collision anyway, and the final result can't be lower than this
if (line == NULL)
return P_GetSlopeZAt(slope, x, y);
return HighestOnLine(mobj->radius, x, y, line, slope, lowest);
} else // Well, that makes it easy. Just get the ceiling height
return sector->ceilingheight;
}
static void P_PlayerFlip(mobj_t *mo) static void P_PlayerFlip(mobj_t *mo)
{ {
if (!mo->player) if (!mo->player)
...@@ -1541,6 +1368,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) ...@@ -1541,6 +1368,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo)
case MT_WATERDROP: case MT_WATERDROP:
case MT_CYBRAKDEMON: case MT_CYBRAKDEMON:
gravityadd >>= 1; gravityadd >>= 1;
break;
default: default:
break; break;
} }
...@@ -1908,7 +1736,7 @@ void P_XYMovement(mobj_t *mo) ...@@ -1908,7 +1736,7 @@ void P_XYMovement(mobj_t *mo)
{ {
P_BounceMove(mo); P_BounceMove(mo);
xmove = ymove = 0; xmove = ymove = 0;
S_StartSound(mo, mo->info->activesound); S_StartSoundFromMobj(mo, mo->info->activesound);
// Bounce ring algorithm // Bounce ring algorithm
if (mo->type == MT_THROWNBOUNCE) if (mo->type == MT_THROWNBOUNCE)
...@@ -1934,7 +1762,7 @@ void P_XYMovement(mobj_t *mo) ...@@ -1934,7 +1762,7 @@ void P_XYMovement(mobj_t *mo)
} }
else if (mo->flags & MF_STICKY) else if (mo->flags & MF_STICKY)
{ {
S_StartSound(mo, mo->info->activesound); S_StartSoundFromMobj(mo, mo->info->activesound);
mo->momx = mo->momy = mo->momz = 0; //Full stop! mo->momx = mo->momy = mo->momz = 0; //Full stop!
mo->flags |= MF_NOGRAVITY; //Stay there! mo->flags |= MF_NOGRAVITY; //Stay there!
mo->flags &= ~MF_STICKY; //Don't check again! mo->flags &= ~MF_STICKY; //Don't check again!
...@@ -2347,8 +2175,8 @@ boolean P_CheckDeathPitCollide(mobj_t *mo) ...@@ -2347,8 +2175,8 @@ boolean P_CheckDeathPitCollide(mobj_t *mo)
if (mo->player && mo->player->pflags & PF_GODMODE) if (mo->player && mo->player->pflags & PF_GODMODE)
return false; return false;
fixed_t sectorFloor = P_GetSectorFloorZAt(mo->subsector->sector, mo->x, mo->y); fixed_t sectorFloor = P_GetSpecialBottomZ(mo, mo->subsector->sector, mo->subsector->sector);
fixed_t sectorCeiling = P_GetSectorCeilingZAt(mo->subsector->sector, mo->x, mo->y); fixed_t sectorCeiling = P_GetSpecialTopZ(mo, mo->subsector->sector, mo->subsector->sector);
if (((mo->z <= sectorFloor if (((mo->z <= sectorFloor
&& ((mo->subsector->sector->flags & MSF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & MSF_FLIPSPECIAL_FLOOR)) && ((mo->subsector->sector->flags & MSF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & MSF_FLIPSPECIAL_FLOOR))
...@@ -2458,7 +2286,7 @@ boolean P_ZMovement(mobj_t *mo) ...@@ -2458,7 +2286,7 @@ boolean P_ZMovement(mobj_t *mo)
{ {
mo->momz = -mo->momz; mo->momz = -mo->momz;
mo->z += mo->momz; mo->z += mo->momz;
S_StartSound(mo, mo->info->activesound); S_StartSoundFromMobj(mo, mo->info->activesound);
mo->threshold++; mo->threshold++;
// Be sure to change the XY one too if you change this. // Be sure to change the XY one too if you change this.
...@@ -2484,7 +2312,7 @@ boolean P_ZMovement(mobj_t *mo) ...@@ -2484,7 +2312,7 @@ boolean P_ZMovement(mobj_t *mo)
mo->momx = mo->momy = mo->momz = 0; mo->momx = mo->momy = mo->momz = 0;
mo->z = mo->floorz; mo->z = mo->floorz;
if (mo->info->painsound) if (mo->info->painsound)
S_StartSound(mo, mo->info->painsound); S_StartSoundFromMobj(mo, mo->info->painsound);
} }
break; break;
case MT_RING: // Ignore still rings case MT_RING: // Ignore still rings
...@@ -2544,7 +2372,7 @@ boolean P_ZMovement(mobj_t *mo) ...@@ -2544,7 +2372,7 @@ boolean P_ZMovement(mobj_t *mo)
// float down towards target if too close // float down towards target if too close
if (!(mo->flags2 & MF2_SKULLFLY) && !(mo->flags2 & MF2_INFLOAT)) if (!(mo->flags2 & MF2_SKULLFLY) && !(mo->flags2 & MF2_INFLOAT))
{ {
dist = P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y); dist = P_GetMobjDistance2D(mo, mo->target);
delta = (mo->target->z + (mo->height>>1)) - mo->z; delta = (mo->target->z + (mo->height>>1)) - mo->z;
...@@ -2623,7 +2451,7 @@ boolean P_ZMovement(mobj_t *mo) ...@@ -2623,7 +2451,7 @@ boolean P_ZMovement(mobj_t *mo)
// Otherwise bounce up at half speed. // Otherwise bounce up at half speed.
else else
mom.z = -mom.z/2; mom.z = -mom.z/2;
S_StartSound(mo, mo->info->activesound); S_StartSoundFromMobj(mo, mo->info->activesound);
} }
} }
// Hack over. Back to your regularly scheduled detonation. -SH // Hack over. Back to your regularly scheduled detonation. -SH
...@@ -2708,7 +2536,7 @@ boolean P_ZMovement(mobj_t *mo) ...@@ -2708,7 +2536,7 @@ boolean P_ZMovement(mobj_t *mo)
else if (mo->type == MT_FALLINGROCK) else if (mo->type == MT_FALLINGROCK)
{ {
if (P_MobjFlip(mo)*mom.z > FixedMul(2*FRACUNIT, mo->scale)) if (P_MobjFlip(mo)*mom.z > FixedMul(2*FRACUNIT, mo->scale))
S_StartSound(mo, mo->info->activesound + P_RandomKey(mo->info->reactiontime)); S_StartSoundFromMobj(mo, mo->info->activesound + P_RandomKey(mo->info->reactiontime));
mom.z /= 2; // Rocks not so bouncy mom.z /= 2; // Rocks not so bouncy
...@@ -2772,7 +2600,7 @@ boolean P_ZMovement(mobj_t *mo) ...@@ -2772,7 +2600,7 @@ boolean P_ZMovement(mobj_t *mo)
if (P_MobjFlip(mo)*mo->momz >= 0) if (P_MobjFlip(mo)*mo->momz >= 0)
{ {
mo->momz = -mo->momz; mo->momz = -mo->momz;
S_StartSound(mo, mo->info->activesound); S_StartSoundFromMobj(mo, mo->info->activesound);
} }
} }
else else
...@@ -3070,7 +2898,7 @@ nightsdone: ...@@ -3070,7 +2898,7 @@ nightsdone:
// hit the ceiling // hit the ceiling
if (mariomode) if (mariomode)
S_StartSound(mo, sfx_mario1); S_StartSoundFromMobj(mo, sfx_mario1);
if (!mo->player->climbing) if (!mo->player->climbing)
mo->momz = 0; mo->momz = 0;
...@@ -3133,7 +2961,7 @@ boolean P_SceneryZMovement(mobj_t *mo) ...@@ -3133,7 +2961,7 @@ boolean P_SceneryZMovement(mobj_t *mo)
} }
if (mo->threshold != 42) // Don't make pop sound if threshold is 42. if (mo->threshold != 42) // Don't make pop sound if threshold is 42.
S_StartSound(explodemo, sfx_bubbl1 + P_RandomKey(5)); S_StartSoundFromMobj(explodemo, sfx_bubbl1 + P_RandomKey(5));
//note that we assign the bubble sound to one of the new bubbles. //note that we assign the bubble sound to one of the new bubbles.
// in other words, IT ACTUALLY GETS USED YAAAAAAAY // in other words, IT ACTUALLY GETS USED YAAAAAAAY
...@@ -3447,11 +3275,11 @@ void P_MobjCheckWater(mobj_t *mobj) ...@@ -3447,11 +3275,11 @@ void P_MobjCheckWater(mobj_t *mobj)
mobjtype_t bubbletype; mobjtype_t bubbletype;
if (mobj->eflags & MFE_GOOWATER || wasingoo) if (mobj->eflags & MFE_GOOWATER || wasingoo)
S_StartSound(mobj, sfx_ghit); S_StartSoundFromMobj(mobj, sfx_ghit);
else if (mobj->eflags & MFE_TOUCHLAVA) else if (mobj->eflags & MFE_TOUCHLAVA)
S_StartSound(mobj, sfx_splash); S_StartSoundFromMobj(mobj, sfx_splash);
else else
S_StartSound(mobj, sfx_splish); // And make a sound! S_StartSoundFromMobj(mobj, sfx_splish); // And make a sound!
bubblecount = FixedDiv(abs(mobj->momz), mobj->scale)>>(FRACBITS-1); bubblecount = FixedDiv(abs(mobj->momz), mobj->scale)>>(FRACBITS-1);
// Max bubble count // Max bubble count
...@@ -3610,7 +3438,7 @@ void P_DestroyRobots(void) ...@@ -3610,7 +3438,7 @@ void P_DestroyRobots(void)
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) 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; continue;
mo = (mobj_t *)think; mo = (mobj_t *)think;
...@@ -3683,7 +3511,7 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled ...@@ -3683,7 +3511,7 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
if (!P_TryCameraMove(thiscam->x + thiscam->momx, thiscam->y + thiscam->momy, thiscam)) // Thanks for the greatly improved camera, Lach -- Sev if (!P_TryCameraMove(thiscam->x + thiscam->momx, thiscam->y + thiscam->momy, thiscam)) // Thanks for the greatly improved camera, Lach -- Sev
{ // Never fails for 2D mode. { // Never fails for 2D mode.
mobj_t dummy; mobj_t dummy;
dummy.thinker.function.acp1 = (actionf_p1)P_MobjThinker; dummy.thinker.function = (actionf_p1)P_MobjThinker;
dummy.subsector = thiscam->subsector; dummy.subsector = thiscam->subsector;
dummy.x = thiscam->x; dummy.x = thiscam->x;
dummy.y = thiscam->y; dummy.y = thiscam->y;
...@@ -3693,11 +3521,11 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled ...@@ -3693,11 +3521,11 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled
P_ResetCamera(player, thiscam); P_ResetCamera(player, thiscam);
else else
{ {
fixed_t camspeed = P_AproxDistance(thiscam->momx, thiscam->momy); fixed_t camspeed = GetDistance2D(0, 0, thiscam->momx, thiscam->momy);
P_SlideCameraMove(thiscam); P_SlideCameraMove(thiscam);
if (!resetcalled && P_AproxDistance(thiscam->momx, thiscam->momy) == camspeed) if (!resetcalled && GetDistance2D(0, 0, thiscam->momx, thiscam->momy) == camspeed)
{ {
P_ResetCamera(player, thiscam); P_ResetCamera(player, thiscam);
resetcalled = true; resetcalled = true;
...@@ -3887,7 +3715,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj) ...@@ -3887,7 +3715,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
// momentum movement // momentum movement
mobj->eflags &= ~MFE_JUSTSTEPPEDDOWN; mobj->eflags &= ~MFE_JUSTSTEPPEDDOWN;
if (mobj->state-states == S_PLAY_BOUNCE_LANDING) if (P_IsPlayerInState(mobj->player, S_PLAY_BOUNCE_LANDING))
goto animonly; // no need for checkposition - doesn't move at ALL goto animonly; // no need for checkposition - doesn't move at ALL
// Zoom tube // Zoom tube
...@@ -3937,7 +3765,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj) ...@@ -3937,7 +3765,7 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
// always do the gravity bit now, that's simpler // always do the gravity bit now, that's simpler
// BUT CheckPosition only if wasn't done before. // BUT CheckPosition only if wasn't done before.
if (!(mobj->eflags & MFE_ONGROUND) || mobj->momz if (mobj->momz
|| ((mobj->eflags & MFE_VERTICALFLIP) && mobj->z + mobj->height != mobj->ceilingz) || ((mobj->eflags & MFE_VERTICALFLIP) && mobj->z + mobj->height != mobj->ceilingz)
|| (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z != mobj->floorz) || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z != mobj->floorz)
|| P_IsObjectInGoop(mobj)) || P_IsObjectInGoop(mobj))
...@@ -3950,22 +3778,11 @@ static void P_PlayerMobjThinker(mobj_t *mobj) ...@@ -3950,22 +3778,11 @@ static void P_PlayerMobjThinker(mobj_t *mobj)
} }
else else
{ {
#if 0 // i don't know why this is here, it's causing a few undesired state glitches, and disabling it doesn't appear to negatively affect the game, but i don't want it gone permanently just in case some obscure bug crops up
if (!(mobj->player->powers[pw_carry] == CR_NIGHTSMODE)) // used for drilling
mobj->player->pflags &= ~PF_STARTJUMP;
mobj->player->pflags &= ~(PF_JUMPED|PF_NOJUMPDAMAGE);
if (mobj->player->secondjump || mobj->player->powers[pw_tailsfly])
{
mobj->player->secondjump = 0;
mobj->player->powers[pw_tailsfly] = 0;
P_SetMobjState(mobj, S_PLAY_WALK);
}
#endif
mobj->eflags &= ~MFE_JUSTHITFLOOR; mobj->eflags &= ~MFE_JUSTHITFLOOR;
} }
animonly: animonly:
P_CyclePlayerMobjState(mobj); P_CycleMobjState(mobj);
} }
static void CalculatePrecipFloor(precipmobj_t *mobj) static void CalculatePrecipFloor(precipmobj_t *mobj)
...@@ -4167,7 +3984,7 @@ boolean P_BossTargetPlayer(mobj_t *actor, boolean closest) ...@@ -4167,7 +3984,7 @@ boolean P_BossTargetPlayer(mobj_t *actor, boolean closest)
else if (actor->lastlook == stop) else if (actor->lastlook == stop)
return (closest && lastdist > 0); return (closest && lastdist > 0);
if (!playeringame[actor->lastlook]) if (!players[actor->lastlook].ingame)
continue; continue;
if (!closest && c++ == 2) if (!closest && c++ == 2)
...@@ -4189,7 +4006,7 @@ boolean P_BossTargetPlayer(mobj_t *actor, boolean closest) ...@@ -4189,7 +4006,7 @@ boolean P_BossTargetPlayer(mobj_t *actor, boolean closest)
if (closest) if (closest)
{ {
dist = P_AproxDistance(actor->x - player->mo->x, actor->y - player->mo->y); dist = P_GetMobjDistance2D(actor, player->mo);
if (!lastdist || dist < lastdist) if (!lastdist || dist < lastdist)
{ {
lastdist = dist+1; lastdist = dist+1;
...@@ -4211,7 +4028,7 @@ boolean P_SupermanLook4Players(mobj_t *actor) ...@@ -4211,7 +4028,7 @@ boolean P_SupermanLook4Players(mobj_t *actor)
for (c = 0; c < MAXPLAYERS; c++) for (c = 0; c < MAXPLAYERS; c++)
{ {
if (playeringame[c] && !players[c].spectator) if (players[c].ingame && !players[c].spectator)
{ {
if (players[c].pflags & PF_INVIS) if (players[c].pflags & PF_INVIS)
continue; // ignore notarget continue; // ignore notarget
...@@ -4247,7 +4064,7 @@ static void P_GenericBossThinker(mobj_t *mobj) ...@@ -4247,7 +4064,7 @@ static void P_GenericBossThinker(mobj_t *mobj)
// look for a new target // look for a new target
if (P_BossTargetPlayer(mobj, false) && mobj->info->seesound) if (P_BossTargetPlayer(mobj, false) && mobj->info->seesound)
S_StartSound(mobj, mobj->info->seesound); S_StartSoundFromMobj(mobj, mobj->info->seesound);
return; return;
} }
...@@ -4287,7 +4104,7 @@ static void P_Boss1Thinker(mobj_t *mobj) ...@@ -4287,7 +4104,7 @@ static void P_Boss1Thinker(mobj_t *mobj)
// look for a new target // look for a new target
if (P_BossTargetPlayer(mobj, false) && mobj->info->seesound) if (P_BossTargetPlayer(mobj, false) && mobj->info->seesound)
S_StartSound(mobj, mobj->info->seesound); S_StartSoundFromMobj(mobj, mobj->info->seesound);
return; return;
} }
...@@ -4334,7 +4151,7 @@ static void P_Boss2Thinker(mobj_t *mobj) ...@@ -4334,7 +4151,7 @@ static void P_Boss2Thinker(mobj_t *mobj)
// look for a new target // look for a new target
if (P_BossTargetPlayer(mobj, false) && mobj->info->seesound) if (P_BossTargetPlayer(mobj, false) && mobj->info->seesound)
S_StartSound(mobj, mobj->info->seesound); S_StartSoundFromMobj(mobj, mobj->info->seesound);
return; return;
} }
...@@ -4420,7 +4237,7 @@ static void P_Boss3Thinker(mobj_t *mobj) ...@@ -4420,7 +4237,7 @@ static void P_Boss3Thinker(mobj_t *mobj)
// this can happen if the boss was hurt earlier than expected // this can happen if the boss was hurt earlier than expected
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) 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; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -4560,7 +4377,7 @@ static void P_Boss3Thinker(mobj_t *mobj) ...@@ -4560,7 +4377,7 @@ static void P_Boss3Thinker(mobj_t *mobj)
if (mobj->tracer->x == mobj->x && mobj->tracer->y == mobj->y) if (mobj->tracer->x == mobj->x && mobj->tracer->y == mobj->y)
{ {
// apply ambush for old routing, otherwise whack a mole only // apply ambush for old routing, otherwise whack a mole only
dist = P_AproxDistance(P_AproxDistance(mobj->tracer->x - mobj->x, mobj->tracer->y - mobj->y), mobj->tracer->z + mobj->movefactor - mobj->z); dist = GetDistance3D(mobj->tracer->x, mobj->tracer->y, mobj->tracer->z + mobj->movefactor, mobj->x, mobj->y, mobj->z);
if (dist < 1) if (dist < 1)
dist = 1; dist = 1;
...@@ -4618,7 +4435,7 @@ static void P_Boss3Thinker(mobj_t *mobj) ...@@ -4618,7 +4435,7 @@ static void P_Boss3Thinker(mobj_t *mobj)
sprev = shock; sprev = shock;
} }
if (!P_MobjWasRemoved(shock)) if (!P_MobjWasRemoved(shock))
S_StartSound(mobj, shock->info->seesound); S_StartSoundFromMobj(mobj, shock->info->seesound);
// look for a new target // look for a new target
P_BossTargetPlayer(mobj, true); P_BossTargetPlayer(mobj, true);
...@@ -4701,7 +4518,7 @@ static void P_Boss4PinchSpikeballs(mobj_t *mobj, angle_t angle, fixed_t dz) ...@@ -4701,7 +4518,7 @@ static void P_Boss4PinchSpikeballs(mobj_t *mobj, angle_t angle, fixed_t dz)
#else #else
if (mobj->spawnpoint) if (mobj->spawnpoint)
{ {
rad -= R_PointToDist2(mobj->x, mobj->y, rad -= GetDistance2D(mobj->x, mobj->y,
(mobj->spawnpoint->x<<FRACBITS), (mobj->spawnpoint->y<<FRACBITS)); (mobj->spawnpoint->x<<FRACBITS), (mobj->spawnpoint->y<<FRACBITS));
} }
#endif #endif
...@@ -4842,7 +4659,7 @@ static void P_Boss4Thinker(mobj_t *mobj) ...@@ -4842,7 +4659,7 @@ static void P_Boss4Thinker(mobj_t *mobj)
mobj->movecount %= 360*FRACUNIT; mobj->movecount %= 360*FRACUNIT;
if (((oldmovecount>>FRACBITS)%120 >= 60) && !((mobj->movecount>>FRACBITS)%120 >= 60)) if (((oldmovecount>>FRACBITS)%120 >= 60) && !((mobj->movecount>>FRACBITS)%120 >= 60))
S_StartSound(NULL, sfx_mswing); S_StartSoundFromEverywhere(sfx_mswing);
} }
// movedir == battle stage: // movedir == battle stage:
...@@ -4929,7 +4746,7 @@ static void P_Boss4Thinker(mobj_t *mobj) ...@@ -4929,7 +4746,7 @@ static void P_Boss4Thinker(mobj_t *mobj)
{ {
mobj->momz = mobj->movefactor = 0; mobj->momz = mobj->movefactor = 0;
mobj->threshold = 1110<<FRACBITS; mobj->threshold = 1110<<FRACBITS;
S_StartSound(NULL, sfx_s3k60); S_StartSoundFromEverywhere(sfx_s3k60);
mobj->movedir++; mobj->movedir++;
} }
...@@ -5101,7 +4918,7 @@ static void P_Boss5Thinker(mobj_t *mobj) ...@@ -5101,7 +4918,7 @@ static void P_Boss5Thinker(mobj_t *mobj)
} }
if (mobj->state == &states[mobj->info->xdeathstate]) if (mobj->state == &states[mobj->info->xdeathstate])
mobj->momz -= (2*FRACUNIT)/3; mobj->momz -= (2*FRACUNIT)/3;
else if (mobj->tracer && P_AproxDistance(mobj->tracer->x - mobj->x, mobj->tracer->y - mobj->y) < 2*mobj->radius) else if (mobj->tracer && P_AreMobjsClose2D(mobj->tracer, mobj, 2*mobj->radius))
mobj->flags &= ~MF_NOCLIP; mobj->flags &= ~MF_NOCLIP;
} }
else else
...@@ -5177,7 +4994,7 @@ static void P_Boss7Thinker(mobj_t *mobj) ...@@ -5177,7 +4994,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
if (mobj->health > 0) if (mobj->health > 0)
mobj->health--; mobj->health--;
S_StartSound(0, (mobj->health) ? sfx_behurt : sfx_bedie2); S_StartSoundFromEverywhere((mobj->health) ? sfx_behurt : sfx_bedie2);
mobj->reactiontime /= 3; mobj->reactiontime /= 3;
...@@ -5190,7 +5007,7 @@ static void P_Boss7Thinker(mobj_t *mobj) ...@@ -5190,7 +5007,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
// It was a team effort // It was a team effort
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i]) if (!players[i].ingame)
continue; continue;
P_AddPlayerScore(&players[i], 1000); P_AddPlayerScore(&players[i], 1000);
...@@ -5217,11 +5034,11 @@ static void P_Boss7Thinker(mobj_t *mobj) ...@@ -5217,11 +5034,11 @@ static void P_Boss7Thinker(mobj_t *mobj)
INT32 i; INT32 i;
mobj->state->nextstate = mobj->info->painstate; // Reset mobj->state->nextstate = mobj->info->painstate; // Reset
S_StartSound(0, sfx_bedeen); S_StartSoundFromEverywhere(sfx_bedeen);
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i] || players[i].spectator) if (!players[i].ingame || players[i].spectator)
continue; continue;
if (!players[i].mo) if (!players[i].mo)
...@@ -5230,7 +5047,7 @@ static void P_Boss7Thinker(mobj_t *mobj) ...@@ -5230,7 +5047,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
if (players[i].mo->health <= 0) if (players[i].mo->health <= 0)
continue; continue;
if (P_AproxDistance(players[i].mo->x - mobj->x, players[i].mo->y - mobj->y) > (mobj->radius + players[i].mo->radius)) if (P_AreMobjsFar2D(players[i].mo, mobj, mobj->radius + players[i].mo->radius))
continue; continue;
if (players[i].mo->z > mobj->z + mobj->height - FRACUNIT if (players[i].mo->z > mobj->z + mobj->height - FRACUNIT
...@@ -5241,7 +5058,7 @@ static void P_Boss7Thinker(mobj_t *mobj) ...@@ -5241,7 +5058,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
mobj->state->nextstate = mobj->info->spawnstate; mobj->state->nextstate = mobj->info->spawnstate;
// Laugh // Laugh
S_StartSound(0, sfx_bewar1 + P_RandomKey(4)); S_StartSoundFromEverywhere(sfx_bewar1 + P_RandomKey(4));
} }
} }
} }
...@@ -5261,7 +5078,7 @@ static void P_Boss7Thinker(mobj_t *mobj) ...@@ -5261,7 +5078,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
var2 = 2*TICRATE + (80<<16); var2 = 2*TICRATE + (80<<16);
A_LobShot(mobj); A_LobShot(mobj);
S_StartSound(0, sfx_begoop); S_StartSoundFromEverywhere(sfx_begoop);
} }
} }
else if (mobj->state == &states[S_BLACKEGG_SHOOT2]) else if (mobj->state == &states[S_BLACKEGG_SHOOT2])
...@@ -5285,7 +5102,7 @@ static void P_Boss7Thinker(mobj_t *mobj) ...@@ -5285,7 +5102,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
S_StopSound(missile); S_StopSound(missile);
if (leveltime & 1) if (leveltime & 1)
S_StartSound(0, sfx_beshot); S_StartSoundFromEverywhere(sfx_beshot);
} }
else if (mobj->state == &states[S_BLACKEGG_JUMP1] && mobj->tics == 1) else if (mobj->state == &states[S_BLACKEGG_JUMP1] && mobj->tics == 1)
{ {
...@@ -5303,7 +5120,7 @@ static void P_Boss7Thinker(mobj_t *mobj) ...@@ -5303,7 +5120,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
// Looks for players in goop. If you find one, try to jump on him. // Looks for players in goop. If you find one, try to jump on him.
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i] || players[i].spectator) if (!players[i].ingame || players[i].spectator)
continue; continue;
if (!players[i].mo) if (!players[i].mo)
...@@ -5329,7 +5146,7 @@ static void P_Boss7Thinker(mobj_t *mobj) ...@@ -5329,7 +5146,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
if (mobj->health <= mobj->info->damage && !mapthings[j].args[1]) if (mobj->health <= mobj->info->damage && !mapthings[j].args[1])
continue; // don't jump to center continue; // don't jump to center
dist = P_AproxDistance(players[i].mo->x - mo2->x, players[i].mo->y - mo2->y); dist = P_GetMobjDistance2D(players[i].mo, mo2);
if (!(closestNum == -1 || dist < closestdist)) if (!(closestNum == -1 || dist < closestdist))
continue; continue;
...@@ -5399,7 +5216,7 @@ static void P_Boss7Thinker(mobj_t *mobj) ...@@ -5399,7 +5216,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
an = mobj->angle; an = mobj->angle;
an >>= ANGLETOFINESHIFT; an >>= ANGLETOFINESHIFT;
dist = P_AproxDistance(hitspot->x - mobj->x, hitspot->y - mobj->y); dist = P_GetMobjDistance2D(hitspot, mobj);
horizontal = dist / airtime; horizontal = dist / airtime;
vertical = (gravity*airtime)/2; vertical = (gravity*airtime)/2;
...@@ -5418,7 +5235,7 @@ static void P_Boss7Thinker(mobj_t *mobj) ...@@ -5418,7 +5235,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
fixed_t x,y,z; fixed_t x,y,z;
mobj_t *mo2; mobj_t *mo2;
S_StartSound(0, sfx_befall); S_StartSoundFromEverywhere(sfx_befall);
z = mobj->floorz; z = mobj->floorz;
for (j = 0; j < 2; j++) for (j = 0; j < 2; j++)
...@@ -5443,7 +5260,7 @@ static void P_Boss7Thinker(mobj_t *mobj) ...@@ -5443,7 +5260,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
// Hurt player?? // Hurt player??
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i] || players[i].spectator) if (!players[i].ingame || players[i].spectator)
continue; continue;
if (!players[i].mo) if (!players[i].mo)
...@@ -5452,7 +5269,7 @@ static void P_Boss7Thinker(mobj_t *mobj) ...@@ -5452,7 +5269,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
if (players[i].mo->health <= 0) if (players[i].mo->health <= 0)
continue; continue;
if (P_AproxDistance(players[i].mo->x - mobj->x, players[i].mo->y - mobj->y) > mobj->radius*4) if (P_AreMobjsFar2D(players[i].mo, mobj, mobj->radius*4))
continue; continue;
if (players[i].mo->z > mobj->z + 128*FRACUNIT) if (players[i].mo->z > mobj->z + 128*FRACUNIT)
...@@ -5464,13 +5281,13 @@ static void P_Boss7Thinker(mobj_t *mobj) ...@@ -5464,13 +5281,13 @@ static void P_Boss7Thinker(mobj_t *mobj)
P_DamageMobj(players[i].mo, mobj, mobj, 1, 0); P_DamageMobj(players[i].mo, mobj, mobj, 1, 0);
// Laugh // Laugh
S_StartSound(0, sfx_bewar1 + P_RandomKey(4)); S_StartSoundFromEverywhere(sfx_bewar1 + P_RandomKey(4));
} }
P_SetMobjState(mobj, mobj->info->spawnstate); P_SetMobjState(mobj, mobj->info->spawnstate);
} }
else if (mobj->state == &states[mobj->info->deathstate] && mobj->tics == mobj->state->tics) else if (mobj->state == &states[mobj->info->deathstate] && mobj->tics == mobj->state->tics)
S_StartSound(0, sfx_bedie1 + (P_RandomFixed() & 1)); S_StartSoundFromEverywhere(sfx_bedie1 + (P_RandomFixed() & 1));
} }
...@@ -5479,7 +5296,7 @@ static void P_Boss7Thinker(mobj_t *mobj) ...@@ -5479,7 +5296,7 @@ static void P_Boss7Thinker(mobj_t *mobj)
mobj->movedir = InvAngle(mobj->movedir);\ mobj->movedir = InvAngle(mobj->movedir);\
mobj->threshold = 6 + (FixedMul(24<<FRACBITS, FixedDiv((mobj->info->spawnhealth - mobj->health)<<FRACBITS, (mobj->info->spawnhealth-1)<<FRACBITS))>>FRACBITS);\ mobj->threshold = 6 + (FixedMul(24<<FRACBITS, FixedDiv((mobj->info->spawnhealth - mobj->health)<<FRACBITS, (mobj->info->spawnhealth-1)<<FRACBITS))>>FRACBITS);\
if (mobj->info->activesound)\ if (mobj->info->activesound)\
S_StartSound(mobj, mobj->info->activesound);\ S_StartSoundFromMobj(mobj, mobj->info->activesound);\
if (mobj->info->painchance)\ if (mobj->info->painchance)\
P_SetMobjState(mobj, mobj->info->painchance);\ P_SetMobjState(mobj, mobj->info->painchance);\
mobj->flags2 &= ~MF2_INVERTAIMABLE;\ mobj->flags2 &= ~MF2_INVERTAIMABLE;\
...@@ -5509,7 +5326,7 @@ static void P_Boss9Thinker(mobj_t *mobj) ...@@ -5509,7 +5326,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
// Build a hoop linked list of 'em! // Build a hoop linked list of 'em!
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) 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; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -5704,7 +5521,7 @@ static void P_Boss9Thinker(mobj_t *mobj) ...@@ -5704,7 +5521,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
missile->z -= missile->fuse*missile->momz; missile->z -= missile->fuse*missile->momz;
P_SetThingPosition(missile); P_SetThingPosition(missile);
S_StartSound(mobj, sfx_s3kb3); S_StartSoundFromMobj(mobj, sfx_s3kb3);
} }
} }
} }
...@@ -5716,7 +5533,7 @@ static void P_Boss9Thinker(mobj_t *mobj) ...@@ -5716,7 +5533,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
// Spawn energy particles // Spawn energy particles
for (spawner = mobj->hnext; spawner; spawner = spawner->hnext) for (spawner = mobj->hnext; spawner; spawner = spawner->hnext)
{ {
dist = P_AproxDistance(spawner->x - mobj->x, spawner->y - mobj->y); dist = P_GetMobjDistance2D(spawner, mobj);
if (P_RandomRange(1,(dist>>FRACBITS)/16) == 1) if (P_RandomRange(1,(dist>>FRACBITS)/16) == 1)
break; break;
} }
...@@ -5725,7 +5542,7 @@ static void P_Boss9Thinker(mobj_t *mobj) ...@@ -5725,7 +5542,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
mobj_t *missile = P_SpawnMissile(spawner, mobj, MT_MSGATHER); mobj_t *missile = P_SpawnMissile(spawner, mobj, MT_MSGATHER);
if (!P_MobjWasRemoved(missile)) if (!P_MobjWasRemoved(missile))
{ {
missile->fuse = (dist/P_AproxDistance(missile->momx, missile->momy)); missile->fuse = (dist / P_GetMobjMomentum2D(missile));
if (missile->fuse <= 0) // Prevents a division by zero when calculating missile->scalespeed if (missile->fuse <= 0) // Prevents a division by zero when calculating missile->scalespeed
missile->fuse = 1; missile->fuse = 1;
...@@ -5772,7 +5589,7 @@ static void P_Boss9Thinker(mobj_t *mobj) ...@@ -5772,7 +5589,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
if (!(mobj->threshold%4)) { if (!(mobj->threshold%4)) {
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4); mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4);
if (!mobj->reactiontime) if (!mobj->reactiontime)
S_StartSound(mobj, sfx_zoom); // zoom! S_StartSoundFromMobj(mobj, sfx_zoom); // zoom!
} }
} }
// else -- Pausing between energy ball shots // else -- Pausing between energy ball shots
...@@ -5793,7 +5610,7 @@ static void P_Boss9Thinker(mobj_t *mobj) ...@@ -5793,7 +5610,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
{ {
mobj_t *missile; mobj_t *missile;
if (mobj->info->seesound) if (mobj->info->seesound)
S_StartSound(mobj, mobj->info->seesound); S_StartSoundFromMobj(mobj, mobj->info->seesound);
P_SetMobjState(mobj, mobj->info->missilestate); P_SetMobjState(mobj, mobj->info->missilestate);
if (mobj->extravalue1 == 3) if (mobj->extravalue1 == 3)
mobj->reactiontime = TICRATE/16; mobj->reactiontime = TICRATE/16;
...@@ -5881,7 +5698,7 @@ static void P_Boss9Thinker(mobj_t *mobj) ...@@ -5881,7 +5698,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
return; return;
mobj->threshold--; mobj->threshold--;
if (!mobj->threshold) { // failed bounce! if (!mobj->threshold) { // failed bounce!
S_StartSound(mobj, sfx_mspogo); S_StartSoundFromMobj(mobj, sfx_mspogo);
P_BounceMove(mobj); P_BounceMove(mobj);
mobj->angle = R_PointToAngle2(mobj->momx, mobj->momy,0,0); mobj->angle = R_PointToAngle2(mobj->momx, mobj->momy,0,0);
mobj->momz = 4*FRACUNIT; mobj->momz = 4*FRACUNIT;
...@@ -5894,13 +5711,13 @@ static void P_Boss9Thinker(mobj_t *mobj) ...@@ -5894,13 +5711,13 @@ static void P_Boss9Thinker(mobj_t *mobj)
else if (!(mobj->threshold%4)) else if (!(mobj->threshold%4))
{ // We've decided to lock onto the player this bounce. { // We've decided to lock onto the player this bounce.
P_SetMobjState(mobj, mobj->state->nextstate); P_SetMobjState(mobj, mobj->state->nextstate);
S_StartSound(mobj, sfx_s3k5a); S_StartSoundFromMobj(mobj, sfx_s3k5a);
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4); mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4);
mobj->reactiontime = TICRATE - 5*(mobj->info->damage - mobj->health); // targetting time mobj->reactiontime = TICRATE - 5*(mobj->info->damage - mobj->health); // targetting time
} }
else else
{ // No homing, just use P_BounceMove { // No homing, just use P_BounceMove
S_StartSound(mobj, sfx_s3kaa); // make the bounces distinct... S_StartSoundFromMobj(mobj, sfx_s3kaa); // make the bounces distinct...
P_BounceMove(mobj); P_BounceMove(mobj);
mobj->angle = R_PointToAngle2(0,0,mobj->momx,mobj->momy); mobj->angle = R_PointToAngle2(0,0,mobj->momx,mobj->momy);
mobj->reactiontime = 1; // TICRATE/4; // just a pause before you bounce away mobj->reactiontime = 1; // TICRATE/4; // just a pause before you bounce away
...@@ -5921,7 +5738,7 @@ static void P_Boss9Thinker(mobj_t *mobj) ...@@ -5921,7 +5738,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
{ {
if (P_MobjWasRemoved(mobj)) if (P_MobjWasRemoved(mobj))
return; return;
S_StartSound(mobj, sfx_mspogo); S_StartSoundFromMobj(mobj, sfx_mspogo);
P_BounceMove(mobj); P_BounceMove(mobj);
mobj->angle = R_PointToAngle2(mobj->momx, mobj->momy,0,0); mobj->angle = R_PointToAngle2(mobj->momx, mobj->momy,0,0);
} }
...@@ -5999,7 +5816,7 @@ static void P_Boss9Thinker(mobj_t *mobj) ...@@ -5999,7 +5816,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
default: default:
// Fly up and prepare for an attack! // Fly up and prepare for an attack!
// We have to charge up first, so let's go up into the air // We have to charge up first, so let's go up into the air
S_StartSound(mobj, sfx_beflap); S_StartSoundFromMobj(mobj, sfx_beflap);
P_SetMobjState(mobj, mobj->info->raisestate); P_SetMobjState(mobj, mobj->info->raisestate);
if (mobj->floorz >= mobj->target->floorz) if (mobj->floorz >= mobj->target->floorz)
mobj->watertop = mobj->floorz + 256*FRACUNIT; mobj->watertop = mobj->floorz + 256*FRACUNIT;
...@@ -6057,7 +5874,7 @@ static void P_Boss9Thinker(mobj_t *mobj) ...@@ -6057,7 +5874,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
mobj->fuse = 3*TICRATE; mobj->fuse = 3*TICRATE;
mobj->flags |= MF_PAIN; mobj->flags |= MF_PAIN;
if (mobj->info->attacksound) if (mobj->info->attacksound)
S_StartSound(mobj, mobj->info->attacksound); S_StartSoundFromMobj(mobj, mobj->info->attacksound);
A_FaceTarget(mobj); A_FaceTarget(mobj);
break; break;
...@@ -6079,7 +5896,7 @@ static void P_Boss9Thinker(mobj_t *mobj) ...@@ -6079,7 +5896,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
else else
mobj->movedir = 2; mobj->movedir = 2;
if (mobj->info->seesound) if (mobj->info->seesound)
S_StartSound(mobj, mobj->info->seesound); S_StartSoundFromMobj(mobj, mobj->info->seesound);
P_SetMobjState(mobj, mobj->info->seestate); P_SetMobjState(mobj, mobj->info->seestate);
if (mobj->movedir == 2) if (mobj->movedir == 2)
mobj->threshold = 12; // bounce 12 times mobj->threshold = 12; // bounce 12 times
...@@ -6183,7 +6000,7 @@ nodanger: ...@@ -6183,7 +6000,7 @@ nodanger:
mobj->flags2 |= MF2_INVERTAIMABLE; mobj->flags2 |= MF2_INVERTAIMABLE;
// Move normally: Approach the player using normal thrust and simulated friction. // Move normally: Approach the player using normal thrust and simulated friction.
dist = P_AproxDistance(mobj->x-mobj->target->x, mobj->y-mobj->target->y); dist = P_GetMobjDistance2D(mobj, mobj->target);
P_Thrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), -3*FRACUNIT/8); P_Thrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), -3*FRACUNIT/8);
if (dist < 64*FRACUNIT && !(mobj->target->player && mobj->target->player->homing)) if (dist < 64*FRACUNIT && !(mobj->target->player && mobj->target->player->homing))
P_Thrust(mobj, mobj->angle, -4*FRACUNIT); P_Thrust(mobj, mobj->angle, -4*FRACUNIT);
...@@ -6191,7 +6008,7 @@ nodanger: ...@@ -6191,7 +6008,7 @@ nodanger:
P_Thrust(mobj, mobj->angle, FRACUNIT); P_Thrust(mobj, mobj->angle, FRACUNIT);
else else
P_Thrust(mobj, mobj->angle + ANGLE_90, FINECOSINE((((angle_t)(leveltime*ANG1))>>ANGLETOFINESHIFT) & FINEMASK)>>1); P_Thrust(mobj, mobj->angle + ANGLE_90, FINECOSINE((((angle_t)(leveltime*ANG1))>>ANGLETOFINESHIFT) & FINEMASK)>>1);
mobj->momz += P_AproxDistance(mobj->momx, mobj->momy)/12; // Move up higher the faster you're going. mobj->momz += P_GetMobjMomentum2D(mobj)/12; // Move up higher the faster you're going.
} }
} }
} }
...@@ -6206,32 +6023,23 @@ mobj_t *P_GetClosestAxis(mobj_t *source) ...@@ -6206,32 +6023,23 @@ mobj_t *P_GetClosestAxis(mobj_t *source)
thinker_t *th; thinker_t *th;
mobj_t *mo2; mobj_t *mo2;
mobj_t *closestaxis = NULL; mobj_t *closestaxis = NULL;
fixed_t dist1, dist2 = 0; INT32 dist, closestdist = INT32_MAX;
// scan the thinkers to find the closest axis point // scan the thinkers to find the closest axis point
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) 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; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
if (mo2->type == MT_AXIS) if (mo2->type == MT_AXIS)
{ {
if (closestaxis == NULL) dist = P_GetMobjLargeDistance2D(source, mo2) - mo2->radius / FRACUNIT;
{ if (dist < closestdist)
closestaxis = mo2;
dist2 = R_PointToDist2(source->x, source->y, mo2->x, mo2->y)-mo2->radius;
}
else
{
dist1 = R_PointToDist2(source->x, source->y, mo2->x, mo2->y)-mo2->radius;
if (dist1 < dist2)
{ {
closestaxis = mo2; closestaxis = mo2;
dist2 = dist1; closestdist = dist;
}
} }
} }
} }
...@@ -6254,7 +6062,7 @@ static void P_MoveHoop(mobj_t *mobj) ...@@ -6254,7 +6062,7 @@ static void P_MoveHoop(mobj_t *mobj)
{ {
const fixed_t fuse = (mobj->fuse*mobj->extravalue2); const fixed_t fuse = (mobj->fuse*mobj->extravalue2);
const angle_t fa = mobj->movedir*(FINEANGLES/mobj->extravalue1); const angle_t fa = mobj->movedir*(FINEANGLES/mobj->extravalue1);
matrix_t m; oldmatrix_t m;
vector4_t v; vector4_t v;
vector4_t res; vector4_t res;
fixed_t finalx, finaly, finalz; fixed_t finalx, finaly, finalz;
...@@ -6295,7 +6103,7 @@ void P_SpawnHoopOfSomething(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT ...@@ -6295,7 +6103,7 @@ void P_SpawnHoopOfSomething(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT
{ {
mobj_t *mobj; mobj_t *mobj;
INT32 i; INT32 i;
matrix_t m; oldmatrix_t m;
vector4_t v; vector4_t v;
vector4_t res; vector4_t res;
fixed_t finalx, finaly, finalz; fixed_t finalx, finaly, finalz;
...@@ -6364,7 +6172,7 @@ void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 numb ...@@ -6364,7 +6172,7 @@ void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 numb
{ {
mobj_t *mobj; mobj_t *mobj;
INT32 i; INT32 i;
matrix_t m; oldmatrix_t m;
vector4_t v; vector4_t v;
vector4_t res; vector4_t res;
fixed_t finalx, finaly, finalz, dist; fixed_t finalx, finaly, finalz, dist;
...@@ -6406,7 +6214,7 @@ void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 numb ...@@ -6406,7 +6214,7 @@ void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 numb
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, x, y); mobj->angle = R_PointToAngle2(mobj->x, mobj->y, x, y);
// change slope // change slope
dist = P_AproxDistance(P_AproxDistance(x - mobj->x, y - mobj->y), z - mobj->z); dist = GetDistance3D(x, y, z, mobj->x, mobj->y, mobj->z);
if (dist < 1) if (dist < 1)
dist = 1; dist = 1;
...@@ -6472,7 +6280,7 @@ void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on y ...@@ -6472,7 +6280,7 @@ void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on y
fixed_t tx = dest->x; fixed_t tx = dest->x;
fixed_t ty = dest->y; fixed_t ty = dest->y;
fixed_t tz = dest->z + (dest->height/2); // Aim for center fixed_t tz = dest->z + (dest->height/2); // Aim for center
fixed_t xydist = P_AproxDistance(tx - source->x, ty - source->y); fixed_t xydist = GetDistance2D(source->x, source->y, tx, ty);
if (!dest || dest->health <= 0 || !dest->player || !source->tracer) if (!dest || dest->health <= 0 || !dest->player || !source->tracer)
return; return;
...@@ -6481,7 +6289,7 @@ void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on y ...@@ -6481,7 +6289,7 @@ void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on y
source->angle = R_PointToAngle2(source->x, source->y, tx, ty); source->angle = R_PointToAngle2(source->x, source->y, tx, ty);
// change slope // change slope
dist = P_AproxDistance(xydist, tz - source->z); dist = GetDistance3D(source->x, source->y, source->z, tx, ty, tz);
if (dist < 1) if (dist < 1)
dist = 1; dist = 1;
...@@ -6507,9 +6315,9 @@ void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on y ...@@ -6507,9 +6315,9 @@ void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on y
else else
{ {
if (nightsgrab) if (nightsgrab)
speedmul = P_AproxDistance(dest->momx, dest->momy) + FixedMul(8*FRACUNIT, source->scale); speedmul = P_GetMobjMomentum2D(dest) + FixedMul(8*FRACUNIT, source->scale);
else else
speedmul = P_AproxDistance(dest->momx, dest->momy) + FixedMul(source->info->speed, source->scale); speedmul = P_GetMobjMomentum2D(dest) + FixedMul(source->info->speed, source->scale);
source->momx = FixedMul(FixedDiv(tx - source->x, dist), speedmul); source->momx = FixedMul(FixedDiv(tx - source->x, dist), speedmul);
source->momy = FixedMul(FixedDiv(ty - source->y, dist), speedmul); source->momy = FixedMul(FixedDiv(ty - source->y, dist), speedmul);
...@@ -6517,9 +6325,7 @@ void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on y ...@@ -6517,9 +6325,7 @@ void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on y
} }
// Instead of just unsetting NOCLIP like an idiot, let's check the distance to our target. // Instead of just unsetting NOCLIP like an idiot, let's check the distance to our target.
ndist = P_AproxDistance(P_AproxDistance(tx - (source->x+source->momx), ndist = GetDistance3D(tx, ty, tz, source->x + source->momx, source->y + source->momy, source->z + source->momz);
ty - (source->y+source->momy)),
tz - (source->z+source->momz));
if (ndist > dist) // gone past our target if (ndist > dist) // gone past our target
{ {
...@@ -6555,7 +6361,7 @@ static void P_NightsItemChase(mobj_t *thing) ...@@ -6555,7 +6361,7 @@ static void P_NightsItemChase(mobj_t *thing)
// //
void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot) void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot)
{ {
matrix_t m; oldmatrix_t m;
vector4_t unit_lengthways, unit_sideways, pos_lengthways, pos_sideways; vector4_t unit_lengthways, unit_sideways, pos_lengthways, pos_sideways;
vector4_t res; vector4_t res;
fixed_t radius, dist = 0, zstore; fixed_t radius, dist = 0, zstore;
...@@ -6639,7 +6445,7 @@ void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot) ...@@ -6639,7 +6445,7 @@ void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot)
if (dosound && (mobj->flags2 & MF2_BOSSNOTRAP)) if (dosound && (mobj->flags2 & MF2_BOSSNOTRAP))
{ {
S_StartSound(mobj, mobj->info->activesound); S_StartSoundFromMobj(mobj, mobj->info->activesound);
dosound = false; dosound = false;
} }
...@@ -6817,9 +6623,22 @@ static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield) ...@@ -6817,9 +6623,22 @@ static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield)
thing->flags |= MF_NOCLIPHEIGHT; thing->flags |= MF_NOCLIPHEIGHT;
thing->eflags = (thing->eflags & ~MFE_VERTICALFLIP)|(thing->target->eflags & MFE_VERTICALFLIP); thing->eflags = (thing->eflags & ~MFE_VERTICALFLIP)|(thing->target->eflags & MFE_VERTICALFLIP);
P_SetScale(thing, FixedMul(thing->target->scale, thing->target->player->shieldscale), true); //Set the shield's scale based on shieldscale, hide it if we're too small!
fixed_t scale = FixedMul(thing->target->scale, thing->target->player->shieldscale);
if (scale < 1) {
P_SetScale(thing, thing->target->scale, true);
thing->old_scale = thing->target->old_scale;
thing->flags2 |= (MF2_DONTDRAW|MF2_JUSTATTACKED); //Hide and indicate we're hidden
} else {
P_SetScale(thing, scale, true);
thing->old_scale = FixedMul(thing->target->old_scale, thing->target->player->shieldscale); thing->old_scale = FixedMul(thing->target->old_scale, thing->target->player->shieldscale);
//Only unhide if we were hidden by the above code
if (thing->flags2 & MF2_JUSTATTACKED)
thing->flags2 &= ~(MF2_DONTDRAW|MF2_JUSTATTACKED);
}
#define NewMH(mobj) mobj->height // Ugly mobj-height and player-height defines, for the sake of prettier code #define NewMH(mobj) mobj->height // Ugly mobj-height and player-height defines, for the sake of prettier code
#define NewPH(player) P_GetPlayerHeight(player) #define NewPH(player) P_GetPlayerHeight(player)
#define OldMH(mobj) FixedMul(mobj->height, FixedDiv(mobj->old_scale, mobj->scale)) #define OldMH(mobj) FixedMul(mobj->height, FixedDiv(mobj->old_scale, mobj->scale))
...@@ -6943,6 +6762,12 @@ void P_RunOverlays(void) ...@@ -6943,6 +6762,12 @@ void P_RunOverlays(void)
else else
zoffs = 0; zoffs = 0;
// hide the overlay as well if we're part of a hidden shield
if ((mo->target->flags2 & (MF2_JUSTATTACKED|MF2_DONTDRAW)) == (MF2_JUSTATTACKED|MF2_DONTDRAW))
mo->flags2 |= (MF2_DONTDRAW|MF2_JUSTATTACKED);
else if (mo->flags2 & MF2_JUSTATTACKED)
mo->flags2 &= ~(MF2_DONTDRAW|MF2_JUSTATTACKED);
P_UnsetThingPosition(mo); P_UnsetThingPosition(mo);
mo->x = mo->target->x; mo->x = mo->target->x;
mo->y = mo->target->y; mo->y = mo->target->y;
...@@ -7063,7 +6888,7 @@ static void P_KoopaThinker(mobj_t *koopa) ...@@ -7063,7 +6888,7 @@ static void P_KoopaThinker(mobj_t *koopa)
if (P_MobjWasRemoved(flame)) if (P_MobjWasRemoved(flame))
return; return;
flame->momx = -FixedMul(flame->info->speed, flame->scale); flame->momx = -FixedMul(flame->info->speed, flame->scale);
S_StartSound(flame, sfx_koopfr); S_StartSoundFromMobj(flame, sfx_koopfr);
} }
else if (P_RandomChance(5*FRACUNIT/256)) else if (P_RandomChance(5*FRACUNIT/256))
{ {
...@@ -7175,14 +7000,6 @@ static void P_MobjScaleThink(mobj_t *mobj) ...@@ -7175,14 +7000,6 @@ static void P_MobjScaleThink(mobj_t *mobj)
mobj->z -= (mobj->height - oldheight)/2; mobj->z -= (mobj->height - oldheight)/2;
else if (correctionType == 2) else if (correctionType == 2)
mobj->z -= mobj->height - oldheight; mobj->z -= mobj->height - oldheight;
if (mobj->scale == mobj->destscale)
/// \todo Lua hook for "reached destscale"?
switch (mobj->type)
{
default:
break;
}
} }
static void P_MaceSceneryThink(mobj_t *mobj) static void P_MaceSceneryThink(mobj_t *mobj)
...@@ -7199,8 +7016,8 @@ static void P_MaceSceneryThink(mobj_t *mobj) ...@@ -7199,8 +7016,8 @@ static void P_MaceSceneryThink(mobj_t *mobj)
// Quick! Look through players! Don't move unless a player is relatively close by. // Quick! Look through players! Don't move unless a player is relatively close by.
// The below is selected based on CEZ2's first room. I promise you it is a coincidence that it looks like the weed number. // The below is selected based on CEZ2's first room. I promise you it is a coincidence that it looks like the weed number.
for (i = 0; i < MAXPLAYERS; ++i) for (i = 0; i < MAXPLAYERS; ++i)
if (playeringame[i] && players[i].mo if (players[i].ingame && players[i].mo
&& P_AproxDistance(P_AproxDistance(mobj->x - players[i].mo->x, mobj->y - players[i].mo->y), mobj->z - players[i].mo->z) < (4200 << FRACBITS)) && P_AreMobjsClose3D(mobj, players[i].mo, 4200 << FRACBITS))
break; // Stop looking. break; // Stop looking.
if (i == MAXPLAYERS) if (i == MAXPLAYERS)
{ {
...@@ -7322,7 +7139,7 @@ static void P_FlameJetSceneryThink(mobj_t *mobj) ...@@ -7322,7 +7139,7 @@ static void P_FlameJetSceneryThink(mobj_t *mobj)
strength = (mobj->movedir ? mobj->movedir : 80)<<(FRACBITS-2); strength = (mobj->movedir ? mobj->movedir : 80)<<(FRACBITS-2);
P_InstaThrust(flame, flame->angle, strength); P_InstaThrust(flame, flame->angle, strength);
S_StartSound(flame, sfx_fire); S_StartSoundFromMobj(flame, sfx_fire);
} }
static void P_VerticalFlameJetSceneryThink(mobj_t *mobj) static void P_VerticalFlameJetSceneryThink(mobj_t *mobj)
...@@ -7365,7 +7182,7 @@ static void P_VerticalFlameJetSceneryThink(mobj_t *mobj) ...@@ -7365,7 +7182,7 @@ static void P_VerticalFlameJetSceneryThink(mobj_t *mobj)
P_SetMobjState(flame, S_FLAMEJETFLAME7); P_SetMobjState(flame, S_FLAMEJETFLAME7);
} }
P_InstaThrust(flame, mobj->angle, FixedDiv(mobj->fuse*FRACUNIT, 3*FRACUNIT)); P_InstaThrust(flame, mobj->angle, FixedDiv(mobj->fuse*FRACUNIT, 3*FRACUNIT));
S_StartSound(flame, sfx_fire); S_StartSoundFromMobj(flame, sfx_fire);
} }
static boolean P_ParticleGenSceneryThink(mobj_t *mobj) static boolean P_ParticleGenSceneryThink(mobj_t *mobj)
...@@ -7451,7 +7268,7 @@ static void P_RosySceneryThink(mobj_t *mobj) ...@@ -7451,7 +7268,7 @@ static void P_RosySceneryThink(mobj_t *mobj)
statenum_t stat = (mobj->state - states); statenum_t stat = (mobj->state - states);
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i]) if (!players[i].ingame)
continue; continue;
if (!players[i].mo) if (!players[i].mo)
continue; continue;
...@@ -7459,7 +7276,9 @@ static void P_RosySceneryThink(mobj_t *mobj) ...@@ -7459,7 +7276,9 @@ static void P_RosySceneryThink(mobj_t *mobj)
continue; continue;
if (!players[i].mo->health) if (!players[i].mo->health)
continue; continue;
actualwork = work = FixedHypot(mobj->x - players[i].mo->x, mobj->y - players[i].mo->y); if (P_AreMobjsFar2D(mobj, players[i].mo, pdist)) // Integer overflow prevention
continue;
actualwork = work = P_GetMobjDistance2D(mobj, players[i].mo);
if (player) if (player)
{ {
if (players[i].skin == 0 || players[i].skin == 5) if (players[i].skin == 0 || players[i].skin == 5)
...@@ -7471,7 +7290,7 @@ static void P_RosySceneryThink(mobj_t *mobj) ...@@ -7471,7 +7290,7 @@ static void P_RosySceneryThink(mobj_t *mobj)
player = &players[i]; player = &players[i];
} }
if (stat == S_ROSY_JUMP || stat == S_ROSY_PAIN) if (stat == S_ROSY_JUMP || stat == S_ROSY_FALL || stat == S_ROSY_PAIN)
{ {
if (P_IsObjectOnGround(mobj)) if (P_IsObjectOnGround(mobj))
{ {
...@@ -7482,16 +7301,16 @@ static void P_RosySceneryThink(mobj_t *mobj) ...@@ -7482,16 +7301,16 @@ static void P_RosySceneryThink(mobj_t *mobj)
stat = S_ROSY_WALK; stat = S_ROSY_WALK;
P_SetMobjState(mobj, stat); P_SetMobjState(mobj, stat);
} }
else if (P_MobjFlip(mobj)*mobj->momz < 0) else if (P_MobjFlip(mobj)*mobj->momz < 0 && stat == S_ROSY_JUMP)
mobj->frame = mobj->state->frame + mobj->state->var1; P_SetMobjState(mobj, S_ROSY_FALL);
} }
if (!player) if (!player)
{ {
if ((stat < S_ROSY_IDLE1 || stat > S_ROSY_IDLE4) && stat != S_ROSY_JUMP) if (stat != S_ROSY_IDLE && stat != S_ROSY_JUMP && stat != S_ROSY_FALL)
{ {
mobj->momx = mobj->momy = 0; mobj->momx = mobj->momy = 0;
P_SetMobjState(mobj, S_ROSY_IDLE1); P_SetMobjState(mobj, S_ROSY_IDLE);
} }
} }
else else
...@@ -7505,13 +7324,11 @@ static void P_RosySceneryThink(mobj_t *mobj) ...@@ -7505,13 +7324,11 @@ static void P_RosySceneryThink(mobj_t *mobj)
switch (stat) switch (stat)
{ {
case S_ROSY_IDLE1: case S_ROSY_IDLE:
case S_ROSY_IDLE2:
case S_ROSY_IDLE3:
case S_ROSY_IDLE4:
dojump = true; dojump = true;
break; break;
case S_ROSY_JUMP: case S_ROSY_JUMP:
case S_ROSY_FALL:
case S_ROSY_PAIN: case S_ROSY_PAIN:
// handled above // handled above
break; break;
...@@ -7533,12 +7350,11 @@ static void P_RosySceneryThink(mobj_t *mobj) ...@@ -7533,12 +7350,11 @@ static void P_RosySceneryThink(mobj_t *mobj)
{ {
fixed_t mom, max; fixed_t mom, max;
P_Thrust(mobj, angletoplayer, (3*FRACUNIT) >> 1); P_Thrust(mobj, angletoplayer, (3*FRACUNIT) >> 1);
mom = FixedHypot(mobj->momx, mobj->momy); mom = P_GetMobjMomentum2D(mobj);
max = pdist; max = pdist;
if ((--mobj->extravalue1) <= 0) if ((--mobj->extravalue1) <= 0)
{ {
if (++mobj->frame > mobj->state->frame + mobj->state->var1) P_SetMobjState(mobj, S_ROSY_WALK);
mobj->frame = mobj->state->frame;
if (mom > 12*mobj->scale) if (mom > 12*mobj->scale)
mobj->extravalue1 = 2; mobj->extravalue1 = 2;
else if (mom > 6*mobj->scale) else if (mom > 6*mobj->scale)
...@@ -7557,7 +7373,7 @@ static void P_RosySceneryThink(mobj_t *mobj) ...@@ -7557,7 +7373,7 @@ static void P_RosySceneryThink(mobj_t *mobj)
mobj->target->momx = mobj->momx; mobj->target->momx = mobj->momx;
mobj->target->momy = mobj->momy; mobj->target->momy = mobj->momy;
P_SetMobjState(mobj, (stat = S_ROSY_HUG)); P_SetMobjState(mobj, (stat = S_ROSY_HUG));
S_StartSound(mobj, sfx_cdpcm6); S_StartSoundFromMobj(mobj, sfx_cdpcm6);
mobj->angle = angletoplayer; mobj->angle = angletoplayer;
} }
} }
...@@ -7594,7 +7410,7 @@ static void P_RosySceneryThink(mobj_t *mobj) ...@@ -7594,7 +7410,7 @@ static void P_RosySceneryThink(mobj_t *mobj)
if (mobj->cvmem < (love ? 5*TICRATE : 0)) if (mobj->cvmem < (love ? 5*TICRATE : 0))
{ {
P_SetMobjState(mobj, (stat = S_ROSY_PAIN)); P_SetMobjState(mobj, (stat = S_ROSY_PAIN));
S_StartSound(mobj, sfx_cdpcm7); S_StartSoundFromMobj(mobj, sfx_cdpcm7);
} }
else else
P_SetMobjState(mobj, (stat = S_ROSY_JUMP)); P_SetMobjState(mobj, (stat = S_ROSY_JUMP));
...@@ -7615,7 +7431,7 @@ static void P_RosySceneryThink(mobj_t *mobj) ...@@ -7615,7 +7431,7 @@ static void P_RosySceneryThink(mobj_t *mobj)
if (player->exiting || --mobj->cvmem < TICRATE) if (player->exiting || --mobj->cvmem < TICRATE)
{ {
P_SetMobjState(mobj, (stat = S_ROSY_HUG)); P_SetMobjState(mobj, (stat = S_ROSY_HUG));
S_StartSound(mobj, sfx_cdpcm6); S_StartSoundFromMobj(mobj, sfx_cdpcm6);
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y);
mobj->target->momx = mobj->momx; mobj->target->momx = mobj->momx;
mobj->target->momy = mobj->momy; mobj->target->momy = mobj->momy;
...@@ -7640,7 +7456,7 @@ static void P_RosySceneryThink(mobj_t *mobj) ...@@ -7640,7 +7456,7 @@ static void P_RosySceneryThink(mobj_t *mobj)
mobj->z += P_MobjFlip(mobj); mobj->z += P_MobjFlip(mobj);
mobj->momx = mobj->momy = 0; mobj->momx = mobj->momy = 0;
P_SetObjectMomZ(mobj, 6 << FRACBITS, false); P_SetObjectMomZ(mobj, 6 << FRACBITS, false);
S_StartSound(mobj, sfx_cdfm02); S_StartSoundFromMobj(mobj, sfx_cdfm02);
} }
if (makeheart) if (makeheart)
...@@ -7865,7 +7681,7 @@ static void P_MobjSceneryThink(mobj_t *mobj) ...@@ -7865,7 +7681,7 @@ static void P_MobjSceneryThink(mobj_t *mobj)
{ {
mobj->health = 0; mobj->health = 0;
P_SetMobjState(mobj, mobj->info->deathstate); P_SetMobjState(mobj, mobj->info->deathstate);
S_StartSound(mobj, mobj->info->deathsound + P_RandomKey(mobj->info->mass)); S_StartSoundFromMobj(mobj, mobj->info->deathsound + P_RandomKey(mobj->info->mass));
return; return;
} }
break; break;
...@@ -8214,6 +8030,10 @@ static boolean P_MobjBossThink(mobj_t *mobj) ...@@ -8214,6 +8030,10 @@ static boolean P_MobjBossThink(mobj_t *mobj)
case MT_METALSONIC_BATTLE: case MT_METALSONIC_BATTLE:
P_Boss9Thinker(mobj); P_Boss9Thinker(mobj);
break; break;
case MT_OLDK:
if (mobj->health <= 0)
mobj->momz -= (2*FRACUNIT)/3;
break;
default: // Generic SOC-made boss default: // Generic SOC-made boss
if (mobj->flags2 & MF2_SKULLFLY) if (mobj->flags2 & MF2_SKULLFLY)
P_SpawnGhostMobj(mobj); P_SpawnGhostMobj(mobj);
...@@ -8228,7 +8048,7 @@ static boolean P_MobjBossThink(mobj_t *mobj) ...@@ -8228,7 +8048,7 @@ static boolean P_MobjBossThink(mobj_t *mobj)
{ {
if (mobj->target) if (mobj->target)
{ {
mobj->momz = FixedMul(FixedDiv(mobj->target->z - mobj->z, P_AproxDistance(mobj->x - mobj->target->x, mobj->y - mobj->target->y)), mobj->scale << 1); mobj->momz = FixedMul(FixedDiv(mobj->target->z - mobj->z, P_GetMobjDistance2D(mobj, mobj->target)), mobj->scale << 1);
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y);
} }
else else
...@@ -8255,7 +8075,7 @@ static boolean P_MobjBossThink(mobj_t *mobj) ...@@ -8255,7 +8075,7 @@ static boolean P_MobjBossThink(mobj_t *mobj)
} }
if (mobj->momz && mobj->z + mobj->momz <= mobj->floorz) if (mobj->momz && mobj->z + mobj->momz <= mobj->floorz)
{ {
S_StartSound(mobj, sfx_befall); S_StartSoundFromMobj(mobj, sfx_befall);
if (mobj->state != states + S_CYBRAKDEMON_DIE8) if (mobj->state != states + S_CYBRAKDEMON_DIE8)
P_SetMobjState(mobj, S_CYBRAKDEMON_DIE8); P_SetMobjState(mobj, S_CYBRAKDEMON_DIE8);
} }
...@@ -8285,7 +8105,7 @@ static boolean P_MobjDeadThink(mobj_t *mobj) ...@@ -8285,7 +8105,7 @@ static boolean P_MobjDeadThink(mobj_t *mobj)
{ {
if (!mobj->fuse) if (!mobj->fuse)
{ {
S_StartSound(mobj, sfx_s3k77); S_StartSoundFromMobj(mobj, sfx_s3k77);
mobj->flags2 |= MF2_DONTDRAW; mobj->flags2 |= MF2_DONTDRAW;
mobj->fuse = TICRATE; mobj->fuse = TICRATE;
} }
...@@ -8339,7 +8159,7 @@ static boolean P_MobjDeadThink(mobj_t *mobj) ...@@ -8339,7 +8159,7 @@ static boolean P_MobjDeadThink(mobj_t *mobj)
mo2->angle = fa << ANGLETOFINESHIFT; mo2->angle = fa << ANGLETOFINESHIFT;
if (!i && !(mobj->fuse & 2)) if (!i && !(mobj->fuse & 2))
S_StartSound(mo2, mobj->info->deathsound); S_StartSoundFromMobj(mo2, mobj->info->deathsound);
flicky = P_InternalFlickySpawn(mo2, 0, 8*FRACUNIT, false, -1); flicky = P_InternalFlickySpawn(mo2, 0, 8*FRACUNIT, false, -1);
if (!flicky) if (!flicky)
...@@ -8378,7 +8198,7 @@ static boolean P_MobjDeadThink(mobj_t *mobj) ...@@ -8378,7 +8198,7 @@ static boolean P_MobjDeadThink(mobj_t *mobj)
mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS), mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS),
MT_SONIC3KBOSSEXPLODE); MT_SONIC3KBOSSEXPLODE);
if (!P_MobjWasRemoved(explosion)) if (!P_MobjWasRemoved(explosion))
S_StartSound(explosion, sfx_s3kb4); S_StartSoundFromMobj(explosion, sfx_s3kb4);
} }
if (mobj->movedir == DMG_DROWNED) if (mobj->movedir == DMG_DROWNED)
P_SetObjectMomZ(mobj, -FRACUNIT/2, true); // slower fall from drowning P_SetObjectMomZ(mobj, -FRACUNIT/2, true); // slower fall from drowning
...@@ -8397,7 +8217,7 @@ static boolean P_MobjDeadThink(mobj_t *mobj) ...@@ -8397,7 +8217,7 @@ static boolean P_MobjDeadThink(mobj_t *mobj)
mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS), mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS),
MT_SONIC3KBOSSEXPLODE); MT_SONIC3KBOSSEXPLODE);
if (!P_MobjWasRemoved(explosion)) if (!P_MobjWasRemoved(explosion))
S_StartSound(explosion, sfx_s3kb4); S_StartSoundFromMobj(explosion, sfx_s3kb4);
} }
P_SetObjectMomZ(mobj, -2*FRACUNIT/3, true); P_SetObjectMomZ(mobj, -2*FRACUNIT/3, true);
} }
...@@ -8477,7 +8297,7 @@ static void P_ArrowThink(mobj_t *mobj) ...@@ -8477,7 +8297,7 @@ static void P_ArrowThink(mobj_t *mobj)
0------dist(momx,momy) 0------dist(momx,momy)
*/ */
fixed_t dist = P_AproxDistance(mobj->momx, mobj->momy); fixed_t dist = P_GetMobjMomentum2D(mobj);
angle_t angle = R_PointToAngle2(0, 0, dist, mobj->momz); angle_t angle = R_PointToAngle2(0, 0, dist, mobj->momz);
if (angle > ANG20 && angle <= ANGLE_180) if (angle > ANG20 && angle <= ANGLE_180)
...@@ -8490,7 +8310,7 @@ static void P_ArrowThink(mobj_t *mobj) ...@@ -8490,7 +8310,7 @@ static void P_ArrowThink(mobj_t *mobj)
if (!(mobj->extravalue1) && (mobj->momz < 0)) if (!(mobj->extravalue1) && (mobj->momz < 0))
{ {
mobj->extravalue1 = 1; mobj->extravalue1 = 1;
S_StartSound(mobj, mobj->info->activesound); S_StartSoundFromMobj(mobj, mobj->info->activesound);
} }
if (leveltime & 1) if (leveltime & 1)
{ {
...@@ -8515,13 +8335,13 @@ static void P_BumbleboreThink(mobj_t *mobj) ...@@ -8515,13 +8335,13 @@ static void P_BumbleboreThink(mobj_t *mobj)
if (!mobj->target) if (!mobj->target)
P_SetMobjState(mobj, mobj->info->spawnstate); P_SetMobjState(mobj, mobj->info->spawnstate);
else if (P_MobjFlip(mobj)*((mobj->z + (mobj->height >> 1)) - (mobj->target->z + (mobj->target->height >> 1))) > 0 else if (P_MobjFlip(mobj)*((mobj->z + (mobj->height >> 1)) - (mobj->target->z + (mobj->target->height >> 1))) > 0
&& R_PointToDist2(mobj->x, mobj->y, mobj->target->x, mobj->target->y) <= 32*FRACUNIT) && P_AreMobjsClose2D(mobj, mobj->target, 32*FRACUNIT))
{ {
mobj->momx >>= 1; mobj->momx >>= 1;
mobj->momy >>= 1; mobj->momy >>= 1;
if (++mobj->movefactor == 4) if (++mobj->movefactor == 4)
{ {
S_StartSound(mobj, mobj->info->seesound); S_StartSoundFromMobj(mobj, mobj->info->seesound);
mobj->momx = mobj->momy = mobj->momz = 0; mobj->momx = mobj->momy = mobj->momz = 0;
mobj->flags = (mobj->flags|MF_PAIN) & ~MF_NOGRAVITY; mobj->flags = (mobj->flags|MF_PAIN) & ~MF_NOGRAVITY;
P_SetMobjState(mobj, mobj->info->meleestate); P_SetMobjState(mobj, mobj->info->meleestate);
...@@ -8535,7 +8355,7 @@ static void P_BumbleboreThink(mobj_t *mobj) ...@@ -8535,7 +8355,7 @@ static void P_BumbleboreThink(mobj_t *mobj)
if (P_IsObjectOnGround(mobj)) if (P_IsObjectOnGround(mobj))
{ {
S_StopSound(mobj); S_StopSound(mobj);
S_StartSound(mobj, mobj->info->attacksound); S_StartSoundFromMobj(mobj, mobj->info->attacksound);
mobj->flags = (mobj->flags | MF_NOGRAVITY) & ~MF_PAIN; mobj->flags = (mobj->flags | MF_NOGRAVITY) & ~MF_PAIN;
mobj->momx = mobj->momy = mobj->momz = 0; mobj->momx = mobj->momy = mobj->momz = 0;
P_SetMobjState(mobj, mobj->info->painstate); P_SetMobjState(mobj, mobj->info->painstate);
...@@ -8661,7 +8481,7 @@ static boolean P_JetFume1Think(mobj_t *mobj) ...@@ -8661,7 +8481,7 @@ static boolean P_JetFume1Think(mobj_t *mobj)
mobj->destscale = mobj->target->scale; mobj->destscale = mobj->target->scale;
if (!(dashmod && mobj->target->state == states + S_METALSONIC_BOUNCE)) if (!(dashmod && mobj->target->state == states + S_METALSONIC_BOUNCE))
{ {
mobj->destscale = (mobj->destscale + FixedDiv(R_PointToDist2(0, 0, mobj->target->momx, mobj->target->momy), 36*mobj->target->scale))/3; mobj->destscale = (mobj->destscale + FixedDiv(P_GetMobjMomentum2D(mobj->target), 36*mobj->target->scale))/3;
} }
if (mobj->target->eflags & MFE_VERTICALFLIP) if (mobj->target->eflags & MFE_VERTICALFLIP)
mobj->z = mobj->target->z + mobj->target->height/2 + mobj->height/2; mobj->z = mobj->target->z + mobj->target->height/2 + mobj->height/2;
...@@ -8706,7 +8526,7 @@ static boolean P_EggRobo1Think(mobj_t *mobj) ...@@ -8706,7 +8526,7 @@ static boolean P_EggRobo1Think(mobj_t *mobj)
if (mobj->movecount) if (mobj->movecount)
{ {
if (!(--mobj->movecount)) if (!(--mobj->movecount))
S_StartSound(mobj, mobj->info->deathsound); S_StartSoundFromMobj(mobj, mobj->info->deathsound);
} }
else else
{ {
...@@ -8746,12 +8566,13 @@ static boolean P_EggRobo1Think(mobj_t *mobj) ...@@ -8746,12 +8566,13 @@ static boolean P_EggRobo1Think(mobj_t *mobj)
if (mobj->state == &states[mobj->info->spawnstate]) if (mobj->state == &states[mobj->info->spawnstate])
{ {
UINT8 i; UINT8 i;
fixed_t dist = INT32_MAX; fixed_t dist;
INT32 largedist = INT32_MAX;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
fixed_t compdist; INT32 compdist;
if (!playeringame[i]) if (!players[i].ingame)
continue; continue;
if (players[i].spectator) if (players[i].spectator)
continue; continue;
...@@ -8765,26 +8586,23 @@ static boolean P_EggRobo1Think(mobj_t *mobj) ...@@ -8765,26 +8586,23 @@ static boolean P_EggRobo1Think(mobj_t *mobj)
continue; continue;
if (players[i].mo->z + players[i].mo->height < mobj->z - 8*mobj->scale) if (players[i].mo->z + players[i].mo->height < mobj->z - 8*mobj->scale)
continue; continue;
compdist = P_AproxDistance( compdist = GetLargeDistance2D(players[i].mo->x + players[i].mo->momx, players[i].mo->y + players[i].mo->momy, basex, basey);
players[i].mo->x + players[i].mo->momx - basex, if (compdist >= largedist)
players[i].mo->y + players[i].mo->momy - basey);
if (compdist >= dist)
continue; continue;
dist = compdist; largedist = compdist;
P_SetTarget(&mobj->target, players[i].mo); P_SetTarget(&mobj->target, players[i].mo);
} }
dist = mobj->target ? GetDistance2D(mobj->target->x + mobj->target->momx, mobj->target->y + mobj->target->momy, basex, basey) : INT32_MAX;
if (dist < (SPECTATORRADIUS << 1)) if (dist < (SPECTATORRADIUS << 1))
{ {
didmove = true; didmove = true;
mobj->frame = 3 + ((leveltime & 2) >> 1); mobj->frame = 3 + ((leveltime & 2) >> 1);
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y);
if (P_AproxDistance( if (GetDistance2D(mobj->x, mobj->y, basex, basey) < mobj->scale)
mobj->x - basex, S_StartSoundFromMobj(mobj, mobj->info->seesound);
mobj->y - basey)
< mobj->scale)
S_StartSound(mobj, mobj->info->seesound);
P_MoveOrigin(mobj, P_MoveOrigin(mobj,
(15*(mobj->x >> 4)) + (basex >> 4) + P_ReturnThrustX(mobj, mobj->angle, SPECTATORRADIUS >> 4), (15*(mobj->x >> 4)) + (basex >> 4) + P_ReturnThrustX(mobj, mobj->angle, SPECTATORRADIUS >> 4),
...@@ -8811,7 +8629,7 @@ static boolean P_EggRobo1Think(mobj_t *mobj) ...@@ -8811,7 +8629,7 @@ static boolean P_EggRobo1Think(mobj_t *mobj)
if (!didmove) if (!didmove)
{ {
if (P_AproxDistance(mobj->x - basex, mobj->y - basey) < mobj->scale) if (GetDistance2D(mobj->x, mobj->y, basex, basey) < mobj->scale)
P_MoveOrigin(mobj, basex, basey, mobj->z); P_MoveOrigin(mobj, basex, basey, mobj->z);
else else
P_MoveOrigin(mobj, P_MoveOrigin(mobj,
...@@ -8967,7 +8785,7 @@ static void P_NiGHTSDroneThink(mobj_t *mobj) ...@@ -8967,7 +8785,7 @@ static void P_NiGHTSDroneThink(mobj_t *mobj)
boolean bonustime = false; boolean bonustime = false;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].bonustime && players[i].powers[pw_carry] == CR_NIGHTSMODE) if (players[i].ingame && players[i].bonustime && players[i].powers[pw_carry] == CR_NIGHTSMODE)
{ {
bonustime = true; bonustime = true;
break; break;
...@@ -9021,7 +8839,7 @@ static void P_NiGHTSDroneThink(mobj_t *mobj) ...@@ -9021,7 +8839,7 @@ static void P_NiGHTSDroneThink(mobj_t *mobj)
// state switching logic // state switching logic
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].bonustime && players[i].powers[pw_carry] == CR_NIGHTSMODE) if (players[i].ingame && players[i].bonustime && players[i].powers[pw_carry] == CR_NIGHTSMODE)
{ {
bonustime = true; bonustime = true;
break; break;
...@@ -9040,7 +8858,7 @@ static void P_NiGHTSDroneThink(mobj_t *mobj) ...@@ -9040,7 +8858,7 @@ static void P_NiGHTSDroneThink(mobj_t *mobj)
else if (!G_IsSpecialStage(gamemap)) else if (!G_IsSpecialStage(gamemap))
{ {
for (i = 0; i < MAXPLAYERS; 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)
{ {
bonustime = true; // variable reuse bonustime = true; // variable reuse
break; break;
...@@ -9182,7 +9000,7 @@ static void P_PyreFlyThink(mobj_t *mobj) ...@@ -9182,7 +9000,7 @@ static void P_PyreFlyThink(mobj_t *mobj)
P_PyreFlyBurn(mobj, fireradius*FRACUNIT, 40, MT_PYREFLY_FIRE, 0); P_PyreFlyBurn(mobj, fireradius*FRACUNIT, 40, MT_PYREFLY_FIRE, 0);
} }
hdist = R_PointToDist2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); hdist = P_GetMobjDistance2D(mobj, mobj->target);
if (hdist > 1500*FRACUNIT) if (hdist > 1500*FRACUNIT)
{ {
...@@ -9201,7 +9019,7 @@ static void P_PyreFlyThink(mobj_t *mobj) ...@@ -9201,7 +9019,7 @@ static void P_PyreFlyThink(mobj_t *mobj)
{ {
//Aim for player z position. If too close to floor/ceiling, aim just above/below them. //Aim for player z position. If too close to floor/ceiling, aim just above/below them.
fixed_t destz = min(max(mobj->target->z, mobj->target->floorz + 70*FRACUNIT), mobj->target->ceilingz - 80*FRACUNIT - mobj->height); fixed_t destz = min(max(mobj->target->z, mobj->target->floorz + 70*FRACUNIT), mobj->target->ceilingz - 80*FRACUNIT - mobj->height);
fixed_t dist = P_AproxDistance(hdist, destz - mobj->z); fixed_t dist = GetDistance3D(mobj->x, mobj->y, mobj->z, destz, mobj->target->x, mobj->target->y);
P_InstaThrust(mobj, R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y), 2*FRACUNIT); P_InstaThrust(mobj, R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y), 2*FRACUNIT);
mobj->momz = FixedMul(FixedDiv(destz - mobj->z, dist), 2*FRACUNIT); mobj->momz = FixedMul(FixedDiv(destz - mobj->z, dist), 2*FRACUNIT);
} }
...@@ -9257,7 +9075,7 @@ static void P_PterabyteThink(mobj_t *mobj) ...@@ -9257,7 +9075,7 @@ static void P_PterabyteThink(mobj_t *mobj)
return; return;
} }
hdist = R_PointToDist2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); hdist = P_GetMobjDistance2D(mobj, mobj->target);
if (hdist > 450*FRACUNIT) if (hdist > 450*FRACUNIT)
{ {
P_SetTarget(&mobj->target, NULL); P_SetTarget(&mobj->target, NULL);
...@@ -9266,7 +9084,7 @@ static void P_PterabyteThink(mobj_t *mobj) ...@@ -9266,7 +9084,7 @@ static void P_PterabyteThink(mobj_t *mobj)
P_SetMobjState(mobj, S_PTERABYTE_SWOOPDOWN); P_SetMobjState(mobj, S_PTERABYTE_SWOOPDOWN);
mobj->extravalue1++; mobj->extravalue1++;
S_StartSound(mobj, mobj->info->attacksound); S_StartSoundFromMobj(mobj, mobj->info->attacksound);
time = FixedDiv(hdist, hspeed); time = FixedDiv(hdist, hspeed);
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y);
fa = (mobj->angle >> ANGLETOFINESHIFT) & FINEMASK; fa = (mobj->angle >> ANGLETOFINESHIFT) & FINEMASK;
...@@ -9303,7 +9121,7 @@ static void P_PterabyteThink(mobj_t *mobj) ...@@ -9303,7 +9121,7 @@ static void P_PterabyteThink(mobj_t *mobj)
var1 = 2*mobj->info->speed; var1 = 2*mobj->info->speed;
var2 = 1; var2 = 1;
A_HomingChase(mobj); A_HomingChase(mobj);
if (P_AproxDistance(mobj->x - mobj->tracer->x, mobj->y - mobj->tracer->y) <= mobj->info->speed) if (P_AreMobjsClose2D(mobj, mobj->tracer, mobj->info->speed))
{ {
mobj->extravalue1 -= 2; mobj->extravalue1 -= 2;
mobj->momx = mobj->momy = mobj->momz = 0; mobj->momx = mobj->momy = mobj->momz = 0;
...@@ -9330,9 +9148,9 @@ static void P_DragonbomberThink(mobj_t *mobj) ...@@ -9330,9 +9148,9 @@ static void P_DragonbomberThink(mobj_t *mobj)
if (!P_MobjWasRemoved(mine)) if (!P_MobjWasRemoved(mine))
{ {
mine->angle = segment->angle; mine->angle = segment->angle;
P_InstaThrust(mine, mobj->angle, P_AproxDistance(mobj->momx, mobj->momy) >> 1); P_InstaThrust(mine, mobj->angle, P_GetMobjMomentum2D(mobj) >> 1);
P_SetObjectMomZ(mine, -2*FRACUNIT, true); P_SetObjectMomZ(mine, -2*FRACUNIT, true);
S_StartSound(mine, mine->info->seesound); S_StartSoundFromMobj(mine, mine->info->seesound);
} }
P_SetMobjState(segment, segment->info->raisestate); P_SetMobjState(segment, segment->info->raisestate);
mobj->threshold = mobj->info->painchance; mobj->threshold = mobj->info->painchance;
...@@ -9341,7 +9159,7 @@ static void P_DragonbomberThink(mobj_t *mobj) ...@@ -9341,7 +9159,7 @@ static void P_DragonbomberThink(mobj_t *mobj)
} }
if (mobj->target) // Are we chasing a player? if (mobj->target) // Are we chasing a player?
{ {
fixed_t dist = P_AproxDistance(mobj->x - mobj->target->x, mobj->y - mobj->target->y); fixed_t dist = P_GetMobjDistance2D(mobj, mobj->target);
if (dist > 2000*mobj->scale) // Not anymore! if (dist > 2000*mobj->scale) // Not anymore!
P_SetTarget(&mobj->target, NULL); P_SetTarget(&mobj->target, NULL);
else else
...@@ -9416,14 +9234,14 @@ static inline boolean PIT_PushThing(mobj_t *thing) ...@@ -9416,14 +9234,14 @@ static inline boolean PIT_PushThing(mobj_t *thing)
fixed_t radius = pushmobj->spawnpoint->args[0] << FRACBITS; fixed_t radius = pushmobj->spawnpoint->args[0] << FRACBITS;
if (pushmobj->spawnpoint->args[2] & TMPP_NOZFADE) if (pushmobj->spawnpoint->args[2] & TMPP_NOZFADE)
dist = P_AproxDistance(thing->x - sx, thing->y - sy); dist = GetDistance2D(thing->x, thing->y, sx, sy);
else else
{ {
// Make sure the Z is in range // Make sure the Z is in range
if (thing->z < sz - radius || thing->z > sz + radius) if (thing->z < sz - radius || thing->z > sz + radius)
return false; return false;
dist = P_AproxDistance(P_AproxDistance(thing->x - sx, thing->y - sy), thing->z - sz); dist = GetDistance3D(sx, sy, sz, thing->x, thing->y, thing->z);
} }
speed = (abs(pushmobj->spawnpoint->args[1]) - ((dist>>FRACBITS)>>1))<<(FRACBITS - PUSH_FACTOR - 1); speed = (abs(pushmobj->spawnpoint->args[1]) - ((dist>>FRACBITS)>>1))<<(FRACBITS - PUSH_FACTOR - 1);
...@@ -9490,12 +9308,12 @@ static void P_PointPushThink(mobj_t *mobj) ...@@ -9490,12 +9308,12 @@ static void P_PointPushThink(mobj_t *mobj)
radius = mobj->spawnpoint->args[0] << FRACBITS; radius = mobj->spawnpoint->args[0] << FRACBITS;
pushmobj = mobj; pushmobj = mobj;
xl = (unsigned)(mobj->x - radius - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT; xl = (unsigned)(mobj->x - radius - bmaporgx)>>MAPBLOCKSHIFT;
xh = (unsigned)(mobj->x + radius - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT; xh = (unsigned)(mobj->x + radius - bmaporgx)>>MAPBLOCKSHIFT;
yl = (unsigned)(mobj->y - radius - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT; yl = (unsigned)(mobj->y - radius - bmaporgy)>>MAPBLOCKSHIFT;
yh = (unsigned)(mobj->y + radius - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT; yh = (unsigned)(mobj->y + radius - bmaporgy)>>MAPBLOCKSHIFT;
P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_PushThing); P_DoBlockThingsIterate(xl, yl, xh, yh, PIT_PushThing, pushmobj);
} }
static boolean P_MobjRegularThink(mobj_t *mobj) static boolean P_MobjRegularThink(mobj_t *mobj)
...@@ -9564,7 +9382,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) ...@@ -9564,7 +9382,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
mobj->eflags |= MFE_UNDERWATER; //P_MobjCheckWater(mobj); // solely for MFE_UNDERWATER for A_FlickySpawn mobj->eflags |= MFE_UNDERWATER; //P_MobjCheckWater(mobj); // solely for MFE_UNDERWATER for A_FlickySpawn
{ {
if (mobj->tracer && mobj->tracer->player && mobj->tracer->health > 0 if (mobj->tracer && mobj->tracer->player && mobj->tracer->health > 0
&& P_AproxDistance(P_AproxDistance(mobj->tracer->x - mobj->x, mobj->tracer->y - mobj->y), mobj->tracer->z - mobj->z) <= mobj->radius*16) && P_AreMobjsClose3D(mobj->tracer, mobj, mobj->radius*16))
{ {
var1 = mobj->info->speed; var1 = mobj->info->speed;
var2 = 1; var2 = 1;
...@@ -9576,7 +9394,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) ...@@ -9576,7 +9394,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
mobj->z = mobj->floorz; mobj->z = mobj->floorz;
if (leveltime % mobj->info->painchance == 0) if (leveltime % mobj->info->painchance == 0)
S_StartSound(mobj, mobj->info->activesound); S_StartSoundFromMobj(mobj, mobj->info->activesound);
if ((statenum_t)(mobj->state - states) != mobj->info->seestate) if ((statenum_t)(mobj->state - states) != mobj->info->seestate)
P_SetMobjState(mobj, mobj->info->seestate); P_SetMobjState(mobj, mobj->info->seestate);
...@@ -9670,7 +9488,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) ...@@ -9670,7 +9488,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
if (mobj->state - states == S_SMASHSPIKE_FALL && P_IsObjectOnGround(mobj)) if (mobj->state - states == S_SMASHSPIKE_FALL && P_IsObjectOnGround(mobj))
{ {
P_SetMobjState(mobj, S_SMASHSPIKE_STOMP1); P_SetMobjState(mobj, S_SMASHSPIKE_STOMP1);
S_StartSound(mobj, sfx_spsmsh); S_StartSoundFromMobj(mobj, sfx_spsmsh);
} }
else if (mobj->state - states == S_SMASHSPIKE_RISE2 && P_MobjFlip(mobj)*(mobj->z - mobj->movecount) >= 0) else if (mobj->state - states == S_SMASHSPIKE_RISE2 && P_MobjFlip(mobj)*(mobj->z - mobj->movecount) >= 0)
{ {
...@@ -9692,14 +9510,14 @@ static boolean P_MobjRegularThink(mobj_t *mobj) ...@@ -9692,14 +9510,14 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
// Target nearest player on your mare. // Target nearest player on your mare.
// (You can make it float up/down by adding MF_FLOAT, // (You can make it float up/down by adding MF_FLOAT,
// but beware level design pitfalls.) // but beware level design pitfalls.)
fixed_t shortest = 1024*FRACUNIT; INT32 shortest = 1024;
INT32 i; INT32 i;
P_SetTarget(&mobj->target, NULL); P_SetTarget(&mobj->target, NULL);
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
if (playeringame[i] && players[i].mo if (players[i].ingame && players[i].mo
&& players[i].mare == mobj->threshold && players[i].spheres > 0) && players[i].mare == mobj->threshold && players[i].spheres > 0)
{ {
fixed_t dist = P_AproxDistance(players[i].mo->x - mobj->x, players[i].mo->y - mobj->y); INT32 dist = P_GetMobjLargeDistance2D(players[i].mo, mobj);
if (dist < shortest) if (dist < shortest)
{ {
P_SetTarget(&mobj->target, players[i].mo); P_SetTarget(&mobj->target, players[i].mo);
...@@ -9730,7 +9548,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) ...@@ -9730,7 +9548,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
P_KoopaThinker(mobj); P_KoopaThinker(mobj);
break; break;
case MT_FIREBALL: case MT_FIREBALL:
if (P_AproxDistance(mobj->momx, mobj->momy) <= 16*FRACUNIT) // Once fireballs lose enough speed, kill them if (P_GetMobjMomentum2D(mobj) <= 16*FRACUNIT) // Once fireballs lose enough speed, kill them
{ {
P_KillMobj(mobj, NULL, NULL, 0); P_KillMobj(mobj, NULL, NULL, 0);
return false; return false;
...@@ -9954,7 +9772,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) ...@@ -9954,7 +9772,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
} }
momz = abs(mobj->momz); momz = abs(mobj->momz);
if (R_PointToDist2(0, 0, mobj->momx, mobj->momy) < momz) if (P_GetMobjMomentum2D(mobj) < momz)
P_InstaThrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), momz); P_InstaThrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), momz);
mobj->flags2 |= MF2_AMBUSH; mobj->flags2 |= MF2_AMBUSH;
break; break;
...@@ -10042,13 +9860,13 @@ static void P_FiringThink(mobj_t *mobj) ...@@ -10042,13 +9860,13 @@ static void P_FiringThink(mobj_t *mobj)
if (mobj->health <= 0) if (mobj->health <= 0)
return; return;
if (mobj->state->action.acp1 == (actionf_p1)A_Boss1Laser) if (mobj->state->action == (actionf_p1)A_Boss1Laser)
{ {
if (mobj->state->tics > 1) if (mobj->state->tics > 1)
{ {
var1 = mobj->state->var1; var1 = mobj->state->var1;
var2 = mobj->state->var2 & 65535; var2 = mobj->state->var2 & 65535;
mobj->state->action.acp1(mobj); mobj->state->action(mobj);
} }
} }
else if (leveltime & 1) // Fire mode else if (leveltime & 1) // Fire mode
...@@ -10076,7 +9894,7 @@ static void P_FiringThink(mobj_t *mobj) ...@@ -10076,7 +9894,7 @@ static void P_FiringThink(mobj_t *mobj)
missile->flags2 |= MF2_SUPERFIRE; missile->flags2 |= MF2_SUPERFIRE;
if (mobj->info->attacksound) if (mobj->info->attacksound)
S_StartSound(missile, mobj->info->attacksound); S_StartSoundFromMobj(missile, mobj->info->attacksound);
} }
} }
else else
...@@ -10161,9 +9979,9 @@ static void P_FlagFuseThink(mobj_t *mobj) ...@@ -10161,9 +9979,9 @@ static void P_FlagFuseThink(mobj_t *mobj)
// Assumedly in splitscreen players will be on opposing teams // Assumedly in splitscreen players will be on opposing teams
if (players[consoleplayer].ctfteam == 1 || splitscreen) if (players[consoleplayer].ctfteam == 1 || splitscreen)
S_StartSound(NULL, sfx_hoop1); S_StartSoundFromEverywhere(sfx_hoop1);
else if (players[consoleplayer].ctfteam == 2) else if (players[consoleplayer].ctfteam == 2)
S_StartSound(NULL, sfx_hoop3); S_StartSoundFromEverywhere(sfx_hoop3);
redflag = flagmo; redflag = flagmo;
} }
...@@ -10174,9 +9992,9 @@ static void P_FlagFuseThink(mobj_t *mobj) ...@@ -10174,9 +9992,9 @@ static void P_FlagFuseThink(mobj_t *mobj)
// Assumedly in splitscreen players will be on opposing teams // Assumedly in splitscreen players will be on opposing teams
if (players[consoleplayer].ctfteam == 2 || splitscreen) if (players[consoleplayer].ctfteam == 2 || splitscreen)
S_StartSound(NULL, sfx_hoop1); S_StartSoundFromEverywhere(sfx_hoop1);
else if (players[consoleplayer].ctfteam == 1) else if (players[consoleplayer].ctfteam == 1)
S_StartSound(NULL, sfx_hoop3); S_StartSoundFromEverywhere(sfx_hoop3);
blueflag = flagmo; blueflag = flagmo;
} }
...@@ -10243,14 +10061,14 @@ static boolean P_FuseThink(mobj_t *mobj) ...@@ -10243,14 +10061,14 @@ static boolean P_FuseThink(mobj_t *mobj)
{ {
mobj->fuse = 30; mobj->fuse = 30;
P_SetMobjState(mobj, S_LAVAFALL_TELL); P_SetMobjState(mobj, S_LAVAFALL_TELL);
S_StartSound(mobj, mobj->info->seesound); S_StartSoundFromMobj(mobj, mobj->info->seesound);
} }
else if (mobj->state - states == S_LAVAFALL_TELL) else if (mobj->state - states == S_LAVAFALL_TELL)
{ {
mobj->fuse = 40; mobj->fuse = 40;
P_SetMobjState(mobj, S_LAVAFALL_SHOOT); P_SetMobjState(mobj, S_LAVAFALL_SHOOT);
S_StopSound(mobj); S_StopSound(mobj);
S_StartSound(mobj, mobj->info->attacksound); S_StartSoundFromMobj(mobj, mobj->info->attacksound);
} }
else else
{ {
...@@ -10269,19 +10087,19 @@ static boolean P_FuseThink(mobj_t *mobj) ...@@ -10269,19 +10087,19 @@ static boolean P_FuseThink(mobj_t *mobj)
P_SetMobjState(mobj, mobj->info->spawnstate); P_SetMobjState(mobj, mobj->info->spawnstate);
mobj->fuse = 100; mobj->fuse = 100;
S_StopSound(mobj); S_StopSound(mobj);
S_StartSound(mobj, sfx_s3k8c); S_StartSoundFromMobj(mobj, sfx_s3k8c);
} }
else if (mobj->extravalue2 == 1) else if (mobj->extravalue2 == 1)
{ {
mobj->fuse = 50; mobj->fuse = 50;
S_StartSound(mobj, sfx_s3ka3); S_StartSoundFromMobj(mobj, sfx_s3ka3);
} }
else else
{ {
P_SetMobjState(mobj, mobj->info->meleestate); P_SetMobjState(mobj, mobj->info->meleestate);
mobj->fuse = 100; mobj->fuse = 100;
S_StopSound(mobj); S_StopSound(mobj);
S_StartSound(mobj, sfx_s3kc2l); S_StartSoundFromMobj(mobj, sfx_s3kc2l);
} }
return false; return false;
case MT_PLAYER: case MT_PLAYER:
...@@ -10300,6 +10118,7 @@ static boolean P_FuseThink(mobj_t *mobj) ...@@ -10300,6 +10118,7 @@ static boolean P_FuseThink(mobj_t *mobj)
// //
void P_MobjThinker(mobj_t *mobj) void P_MobjThinker(mobj_t *mobj)
{ {
boolean ispushable;
I_Assert(mobj != NULL); I_Assert(mobj != NULL);
I_Assert(!P_MobjWasRemoved(mobj)); I_Assert(!P_MobjWasRemoved(mobj));
...@@ -10325,8 +10144,10 @@ void P_MobjThinker(mobj_t *mobj) ...@@ -10325,8 +10144,10 @@ void P_MobjThinker(mobj_t *mobj)
tmfloorthing = tmhitthing = NULL; tmfloorthing = tmhitthing = NULL;
ispushable = mobj->flags & MF_PUSHABLE || (mobj->info->flags & MF_PUSHABLE && mobj->fuse);
// Sector flag MSF_TRIGGERLINE_MOBJ allows ANY mobj to trigger a linedef exec // Sector flag MSF_TRIGGERLINE_MOBJ allows ANY mobj to trigger a linedef exec
P_CheckMobjTrigger(mobj, false); P_CheckMobjTrigger(mobj, ispushable);
if (mobj->scale != mobj->destscale) if (mobj->scale != mobj->destscale)
P_MobjScaleThink(mobj); // Slowly scale up/down to reach your destscale. P_MobjScaleThink(mobj); // Slowly scale up/down to reach your destscale.
...@@ -10370,7 +10191,7 @@ void P_MobjThinker(mobj_t *mobj) ...@@ -10370,7 +10191,7 @@ void P_MobjThinker(mobj_t *mobj)
// if it's pushable, or if it would be pushable other than temporary disablement, use the // if it's pushable, or if it would be pushable other than temporary disablement, use the
// separate thinker // separate thinker
if (mobj->flags & MF_PUSHABLE || (mobj->info->flags & MF_PUSHABLE && mobj->fuse)) if (ispushable)
{ {
if (!P_MobjPushableThink(mobj)) if (!P_MobjPushableThink(mobj))
return; return;
...@@ -10401,7 +10222,7 @@ void P_MobjThinker(mobj_t *mobj) ...@@ -10401,7 +10222,7 @@ void P_MobjThinker(mobj_t *mobj)
if (leveltime % mobj->health) if (leveltime % mobj->health)
return; return;
if (mobj->threshold) if (mobj->threshold)
S_StartSound(mobj, mobj->threshold); S_StartSoundFromMobj(mobj, mobj->threshold);
return; return;
} }
...@@ -10479,9 +10300,6 @@ void P_MobjThinker(mobj_t *mobj) ...@@ -10479,9 +10300,6 @@ void P_MobjThinker(mobj_t *mobj)
} }
// Can end up here if a player dies. // Can end up here if a player dies.
if (mobj->player)
P_CyclePlayerMobjState(mobj);
else
P_CycleMobjState(mobj); P_CycleMobjState(mobj);
if (P_MobjWasRemoved(mobj)) if (P_MobjWasRemoved(mobj))
...@@ -10497,6 +10315,7 @@ void P_MobjThinker(mobj_t *mobj) ...@@ -10497,6 +10315,7 @@ void P_MobjThinker(mobj_t *mobj)
case MT_GRENADEPICKUP: case MT_GRENADEPICKUP:
if (mobj->health == 0) // Fading tile if (mobj->health == 0) // Fading tile
{ {
// TODO: Maybe use mobj->alpha instead of messing with frame flags
INT32 value = mobj->info->damage/10; INT32 value = mobj->info->damage/10;
value = mobj->fuse/value; value = mobj->fuse/value;
value = 10-value; value = 10-value;
...@@ -10548,8 +10367,6 @@ void P_PushableThinker(mobj_t *mobj) ...@@ -10548,8 +10367,6 @@ void P_PushableThinker(mobj_t *mobj)
I_Assert(mobj != NULL); I_Assert(mobj != NULL);
I_Assert(!P_MobjWasRemoved(mobj)); I_Assert(!P_MobjWasRemoved(mobj));
P_CheckMobjTrigger(mobj, true);
// it has to be pushable RIGHT NOW for this part to happen // it has to be pushable RIGHT NOW for this part to happen
if (mobj->flags & MF_PUSHABLE && !(mobj->momx || mobj->momy)) if (mobj->flags & MF_PUSHABLE && !(mobj->momx || mobj->momy))
P_TryMove(mobj, mobj->x, mobj->y, true); P_TryMove(mobj, mobj->x, mobj->y, true);
...@@ -10771,6 +10588,19 @@ static fixed_t P_DefaultMobjShadowScale (mobj_t *thing) ...@@ -10771,6 +10588,19 @@ static fixed_t P_DefaultMobjShadowScale (mobj_t *thing)
} }
} }
static INT32 P_SetupNPC(mobj_t *mobj, const char *name)
{
INT32 skinnum = R_SkinAvailable(name);
if (skinnum != -1)
{
mobj->skin = skins[skinnum];
mobj->color = skins[skinnum]->prefcolor;
}
return skinnum;
}
// //
// P_SpawnMobj // P_SpawnMobj
// //
...@@ -10798,7 +10628,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) ...@@ -10798,7 +10628,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...)
} }
// this is officially a mobj, declared as soon as possible. // this is officially a mobj, declared as soon as possible.
mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; mobj->thinker.function = (actionf_p1)P_MobjThinker;
mobj->type = type; mobj->type = type;
mobj->info = info; mobj->info = info;
...@@ -10842,6 +10672,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) ...@@ -10842,6 +10672,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...)
// Sprite rendering // Sprite rendering
mobj->blendmode = AST_TRANSLUCENT; mobj->blendmode = AST_TRANSLUCENT;
mobj->alpha = FRACUNIT;
mobj->spritexscale = mobj->spriteyscale = mobj->scale; mobj->spritexscale = mobj->spriteyscale = mobj->scale;
mobj->spritexoffset = mobj->spriteyoffset = 0; mobj->spritexoffset = mobj->spriteyoffset = 0;
mobj->floorspriteslope = NULL; mobj->floorspriteslope = NULL;
...@@ -10902,6 +10733,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) ...@@ -10902,6 +10733,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...)
// when spawning MT_PLAYER, set mobj->player before calling MobjSpawn hook to prevent P_RemoveMobj from succeeding on player mobj. // when spawning MT_PLAYER, set mobj->player before calling MobjSpawn hook to prevent P_RemoveMobj from succeeding on player mobj.
va_start(args, type); va_start(args, type);
mobj->player = va_arg(args, player_t *); mobj->player = va_arg(args, player_t *);
if (mobj->player)
mobj->player->mo = mobj; mobj->player->mo = mobj;
va_end(args); va_end(args);
} }
...@@ -10982,7 +10814,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) ...@@ -10982,7 +10814,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...)
ball->threshold = ball->radius + mobj->radius + FixedMul(ball->info->painchance, ball->scale); ball->threshold = ball->radius + mobj->radius + FixedMul(ball->info->painchance, ball->scale);
var1 = ball->state->var1, var2 = ball->state->var2; var1 = ball->state->var1, var2 = ball->state->var2;
ball->state->action.acp1(ball); ball->state->action(ball);
} }
} }
break; break;
...@@ -11029,7 +10861,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) ...@@ -11029,7 +10861,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...)
} }
break; break;
case MT_BIGMINE: case MT_BIGMINE:
mobj->extravalue1 = FixedHypot(mobj->x, mobj->y)>>FRACBITS; mobj->extravalue1 = GetDistance2D(0, 0, mobj->x, mobj->y) >> FRACBITS;
break; break;
case MT_WAVINGFLAG1: case MT_WAVINGFLAG1:
case MT_WAVINGFLAG2: case MT_WAVINGFLAG2:
...@@ -11122,17 +10954,14 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) ...@@ -11122,17 +10954,14 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...)
nummaprings++; nummaprings++;
break; break;
case MT_METALSONIC_RACE: case MT_METALSONIC_RACE:
mobj->skin = skins[5];
/* FALLTHRU */
case MT_METALSONIC_BATTLE: case MT_METALSONIC_BATTLE:
mobj->color = skins[5]->prefcolor; sc = P_SetupNPC(mobj, "metalsonic");
sc = 5;
break; break;
case MT_FANG: case MT_FANG:
sc = 4; sc = P_SetupNPC(mobj, "fang");
break; break;
case MT_ROSY: case MT_ROSY:
sc = 3; sc = P_SetupNPC(mobj, "amy");
break; break;
case MT_CORK: case MT_CORK:
mobj->flags2 |= MF2_SUPERFIRE; mobj->flags2 |= MF2_SUPERFIRE;
...@@ -11162,15 +10991,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) ...@@ -11162,15 +10991,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...)
mcsolid->angle = mobj->angle + ANGLE_90; mcsolid->angle = mobj->angle + ANGLE_90;
} }
break; break;
case MT_TORCHFLOWER:
{
mobj_t *fire = P_SpawnMobjFromMobj(mobj, 0, 0, 46*FRACUNIT, MT_FLAME);
if (!P_MobjWasRemoved(fire))
P_SetTarget(&mobj->target, fire);
break;
}
case MT_PYREFLY: case MT_PYREFLY:
mobj->extravalue1 = (FixedHypot(mobj->x, mobj->y)/FRACUNIT) % 360; mobj->extravalue1 = (GetDistance2D(0, 0, mobj->x, mobj->y) / FRACUNIT) % 360;
mobj->extravalue2 = 0; mobj->extravalue2 = 0;
mobj->fuse = 100; mobj->fuse = 100;
break; break;
...@@ -11194,7 +11016,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) ...@@ -11194,7 +11016,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...)
UINT8 i; UINT8 i;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
if (!playeringame[i] || players[i].spectator) if (!players[i].ingame || players[i].spectator)
continue; continue;
if (players[i].skin == sc) if (players[i].skin == sc)
...@@ -11214,7 +11036,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) ...@@ -11214,7 +11036,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...)
} }
// Call action functions when the state is set // Call action functions when the state is set
if (st->action.acp1 && (mobj->flags & MF_RUNSPAWNFUNC)) if (st->action && (mobj->flags & MF_RUNSPAWNFUNC))
{ {
if (levelloading) if (levelloading)
{ {
...@@ -11229,7 +11051,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...) ...@@ -11229,7 +11051,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type, ...)
var1 = st->var1; var1 = st->var1;
var2 = st->var2; var2 = st->var2;
astate = st; astate = st;
st->action.acp1(mobj); st->action(mobj);
// DANGER! This can cause P_SpawnMobj to return NULL! // DANGER! This can cause P_SpawnMobj to return NULL!
// Avoid using MF_RUNSPAWNFUNC on mobjs whose spawn state expects target or tracer to already be set! // Avoid using MF_RUNSPAWNFUNC on mobjs whose spawn state expects target or tracer to already be set!
if (P_MobjWasRemoved(mobj)) if (P_MobjWasRemoved(mobj))
...@@ -11277,7 +11099,7 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype ...@@ -11277,7 +11099,7 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
mobj->z = z; mobj->z = z;
mobj->momz = mobjinfo[type].speed; mobj->momz = mobjinfo[type].speed;
mobj->thinker.function.acp1 = (actionf_p1)P_NullPrecipThinker; mobj->thinker.function = (actionf_p1)P_NullPrecipThinker;
P_AddThinker(THINK_PRECIP, &mobj->thinker); P_AddThinker(THINK_PRECIP, &mobj->thinker);
CalculatePrecipFloor(mobj); CalculatePrecipFloor(mobj);
...@@ -11298,14 +11120,14 @@ static inline precipmobj_t *P_SpawnRainMobj(fixed_t x, fixed_t y, fixed_t z, mob ...@@ -11298,14 +11120,14 @@ static inline precipmobj_t *P_SpawnRainMobj(fixed_t x, fixed_t y, fixed_t z, mob
{ {
precipmobj_t *mo = P_SpawnPrecipMobj(x,y,z,type); precipmobj_t *mo = P_SpawnPrecipMobj(x,y,z,type);
mo->precipflags |= PCF_RAIN; mo->precipflags |= PCF_RAIN;
//mo->thinker.function.acp1 = (actionf_p1)P_RainThinker; //mo->thinker.function = (actionf_p1)P_RainThinker;
return mo; return mo;
} }
static inline precipmobj_t *P_SpawnSnowMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) static inline precipmobj_t *P_SpawnSnowMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
{ {
precipmobj_t *mo = P_SpawnPrecipMobj(x,y,z,type); precipmobj_t *mo = P_SpawnPrecipMobj(x,y,z,type);
//mo->thinker.function.acp1 = (actionf_p1)P_SnowThinker; //mo->thinker.function = (actionf_p1)P_SnowThinker;
return mo; return mo;
} }
...@@ -11333,17 +11155,16 @@ tic_t itemrespawntime[ITEMQUESIZE]; ...@@ -11333,17 +11155,16 @@ tic_t itemrespawntime[ITEMQUESIZE];
size_t iquehead, iquetail; size_t iquehead, iquetail;
#ifdef PARANOIA #ifdef PARANOIA
#define SCRAMBLE_REMOVED // Force debug build to crash when Removed mobj is accessed #define SCRAMBLE_REMOVED // Force debug build to crash when a removed mobj is accessed
#endif #endif
void P_RemoveMobj(mobj_t *mobj) void P_RemoveMobj(mobj_t *mobj)
{ {
I_Assert(mobj != NULL); I_Assert(mobj != NULL);
if (P_MobjWasRemoved(mobj)) if (P_MobjWasRemoved(mobj) || mobj->thinker.removing)
return; // something already removing this mobj. return; // Something already removed or is removing this mobj.
mobj->thinker.function.acp1 = (actionf_p1)P_RemoveThinkerDelayed; // shh. no recursing. mobj->thinker.removing = true; // Set earlier to avoid recursion.
LUA_HookMobj(mobj, MOBJ_HOOK(MobjRemoved)); LUA_HookMobj(mobj, MOBJ_HOOK(MobjRemoved));
mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; // needed for P_UnsetThingPosition, etc. to work.
// Rings only, please! // Rings only, please!
if (mobj->spawnpoint && if (mobj->spawnpoint &&
...@@ -11441,15 +11262,6 @@ void P_RemoveMobj(mobj_t *mobj) ...@@ -11441,15 +11262,6 @@ void P_RemoveMobj(mobj_t *mobj)
#endif #endif
} }
// This does not need to be added to Lua.
// To test it in Lua, check mobj.valid
boolean P_MobjWasRemoved(mobj_t *mobj)
{
if (mobj && mobj->thinker.function.acp1 == (actionf_p1)P_MobjThinker)
return false;
return true;
}
void P_RemovePrecipMobj(precipmobj_t *mobj) void P_RemovePrecipMobj(precipmobj_t *mobj)
{ {
// unlink from sector and block lists // unlink from sector and block lists
...@@ -11469,7 +11281,7 @@ void P_RemovePrecipMobj(precipmobj_t *mobj) ...@@ -11469,7 +11281,7 @@ void P_RemovePrecipMobj(precipmobj_t *mobj)
void P_RemoveSavegameMobj(mobj_t *mobj) void P_RemoveSavegameMobj(mobj_t *mobj)
{ {
// unlink from sector and block lists // unlink from sector and block lists
if (((thinker_t *)mobj)->function.acp1 == (actionf_p1)P_NullPrecipThinker) if (((thinker_t *)mobj)->function == (actionf_p1)P_NullPrecipThinker)
{ {
P_UnsetPrecipThingPosition((precipmobj_t *)mobj); P_UnsetPrecipThingPosition((precipmobj_t *)mobj);
...@@ -11638,7 +11450,7 @@ void P_PrecipitationEffects(void) ...@@ -11638,7 +11450,7 @@ void P_PrecipitationEffects(void)
// Local effects from here on out! // Local effects from here on out!
// If we're not in game fully yet, we don't worry about them. // If we're not in game fully yet, we don't worry about them.
if (!playeringame[displayplayer] || !players[displayplayer].mo) if (!players[displayplayer].ingame || !players[displayplayer].mo)
return; return;
if (sound_disabled) if (sound_disabled)
...@@ -11677,7 +11489,7 @@ void P_PrecipitationEffects(void) ...@@ -11677,7 +11489,7 @@ void P_PrecipitationEffects(void)
volume = 255; volume = 255;
if (sounds_rain && (!leveltime || leveltime % 80 == 1)) if (sounds_rain && (!leveltime || leveltime % 80 == 1))
S_StartSoundAtVolume(players[displayplayer].mo, sfx_rainin, volume); S_StartSoundFromMobjVol(players[displayplayer].mo, sfx_rainin, volume);
if (!sounds_thunder) if (!sounds_thunder)
return; return;
...@@ -11685,7 +11497,7 @@ void P_PrecipitationEffects(void) ...@@ -11685,7 +11497,7 @@ void P_PrecipitationEffects(void)
if (effects_lightning && lightningStrike && volume) if (effects_lightning && lightningStrike && volume)
{ {
// Large, close thunder sounds to go with our lightning. // Large, close thunder sounds to go with our lightning.
S_StartSoundAtVolume(players[displayplayer].mo, sfx_litng1 + M_RandomKey(4), volume); S_StartSoundFromMobjVol(players[displayplayer].mo, sfx_litng1 + M_RandomKey(4), volume);
} }
else if (thunderchance < 20) else if (thunderchance < 20)
{ {
...@@ -11693,7 +11505,7 @@ void P_PrecipitationEffects(void) ...@@ -11693,7 +11505,7 @@ void P_PrecipitationEffects(void)
if (volume < 80) if (volume < 80)
volume = 80; volume = 80;
S_StartSoundAtVolume(players[displayplayer].mo, sfx_athun1 + M_RandomKey(2), volume); S_StartSoundFromMobjVol(players[displayplayer].mo, sfx_athun1 + M_RandomKey(2), volume);
} }
} }
...@@ -13013,7 +12825,7 @@ static boolean P_MapAlreadyHasStarPost(mobj_t *mobj) ...@@ -13013,7 +12825,7 @@ static boolean P_MapAlreadyHasStarPost(mobj_t *mobj)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) 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; continue;
mo2 = (mobj_t *)th; mo2 = (mobj_t *)th;
...@@ -13162,6 +12974,13 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean ...@@ -13162,6 +12974,13 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
} }
} }
break; break;
case MT_TORCHFLOWER:
{
mobj_t *fire = P_SpawnMobjFromMobj(mobj, 0, 0, 46*FRACUNIT, MT_FLAME);
if (!P_MobjWasRemoved(fire))
P_SetTarget(&mobj->target, fire);
break;
}
case MT_CANDLE: case MT_CANDLE:
case MT_CANDLEPRICKET: case MT_CANDLEPRICKET:
if (mthing->args[0]) if (mthing->args[0])
...@@ -13300,6 +13119,32 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean ...@@ -13300,6 +13119,32 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
banner->angle = mobjangle + ANGLE_90; banner->angle = mobjangle + ANGLE_90;
} }
break; break;
case MT_SSZTREE:
{ // Spawn the branches
INT32 i;
mobj_t *branch;
for (i = 0; i < 5; i++)
{
branch = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_SSZTREE_BRANCH);
if (P_MobjWasRemoved(branch))
continue;
branch->angle = mobj->angle + FixedAngle(i*72*FRACUNIT);
}
}
break;
case MT_SSZTREE2:
{ // Spawn the branches
INT32 i;
mobj_t *branch;
for (i = 0; i < 5; i++)
{
branch = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_SSZTREE2_BRANCH);
if (P_MobjWasRemoved(branch))
continue;
branch->angle = mobj->angle + FixedAngle(i*72*FRACUNIT);
}
}
break;
case MT_HHZTREE_TOP: case MT_HHZTREE_TOP:
{ // Spawn the branches { // Spawn the branches
angle_t mobjangle = FixedAngle(mthing->angle << FRACBITS) & (ANGLE_90 - 1); angle_t mobjangle = FixedAngle(mthing->angle << FRACBITS) & (ANGLE_90 - 1);
...@@ -13334,7 +13179,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean ...@@ -13334,7 +13179,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
{ {
P_SetMobjState(mobj, mobj->info->meleestate); P_SetMobjState(mobj, mobj->info->meleestate);
mobj->extravalue2 = 2; mobj->extravalue2 = 2;
S_StartSound(mobj, sfx_s3kc2l); S_StartSoundFromMobj(mobj, sfx_s3kc2l);
} }
break; break;
case MT_BIGFERN: case MT_BIGFERN:
...@@ -13709,7 +13554,7 @@ void P_SpawnHoop(mapthing_t *mthing) ...@@ -13709,7 +13554,7 @@ void P_SpawnHoop(mapthing_t *mthing)
mobj_t *mobj = NULL; mobj_t *mobj = NULL;
mobj_t *nextmobj = NULL; mobj_t *nextmobj = NULL;
mobj_t *hoopcenter; mobj_t *hoopcenter;
matrix_t pitchmatrix, yawmatrix; oldmatrix_t pitchmatrix, yawmatrix;
fixed_t radius = mthing->args[0] << FRACBITS; fixed_t radius = mthing->args[0] << FRACBITS;
fixed_t sizefactor = 4*FRACUNIT; fixed_t sizefactor = 4*FRACUNIT;
fixed_t hoopsize = radius/sizefactor; fixed_t hoopsize = radius/sizefactor;
...@@ -13892,7 +13737,7 @@ static void P_SpawnItemCircle(mapthing_t *mthing, mobjtype_t *itemtypes, UINT8 n ...@@ -13892,7 +13737,7 @@ static void P_SpawnItemCircle(mapthing_t *mthing, mobjtype_t *itemtypes, UINT8 n
angle_t angle = FixedAngle(mthing->angle << FRACBITS); angle_t angle = FixedAngle(mthing->angle << FRACBITS);
angle_t fa; angle_t fa;
INT32 i; INT32 i;
matrix_t m; oldmatrix_t m;
vector4_t v, res; vector4_t v, res;
for (i = 0; i < numitemtypes; i++) for (i = 0; i < numitemtypes; i++)
...@@ -14067,6 +13912,7 @@ mobj_t *P_SpawnXYZMissile(mobj_t *source, mobj_t *dest, mobjtype_t type, ...@@ -14067,6 +13912,7 @@ mobj_t *P_SpawnXYZMissile(mobj_t *source, mobj_t *dest, mobjtype_t type,
angle_t an; angle_t an;
INT32 dist; INT32 dist;
fixed_t speed; fixed_t speed;
boolean spawned;
I_Assert(source != NULL); I_Assert(source != NULL);
I_Assert(dest != NULL); I_Assert(dest != NULL);
...@@ -14092,7 +13938,7 @@ mobj_t *P_SpawnXYZMissile(mobj_t *source, mobj_t *dest, mobjtype_t type, ...@@ -14092,7 +13938,7 @@ mobj_t *P_SpawnXYZMissile(mobj_t *source, mobj_t *dest, mobjtype_t type,
} }
if (th->info->seesound) if (th->info->seesound)
S_StartSound(th, th->info->seesound); S_StartSoundFromMobj(th, th->info->seesound);
P_SetTarget(&th->target, source); // where it came from P_SetTarget(&th->target, source); // where it came from
an = R_PointToAngle2(x, y, dest->x, dest->y); an = R_PointToAngle2(x, y, dest->x, dest->y);
...@@ -14102,7 +13948,7 @@ mobj_t *P_SpawnXYZMissile(mobj_t *source, mobj_t *dest, mobjtype_t type, ...@@ -14102,7 +13948,7 @@ mobj_t *P_SpawnXYZMissile(mobj_t *source, mobj_t *dest, mobjtype_t type,
th->momx = FixedMul(speed, FINECOSINE(an)); th->momx = FixedMul(speed, FINECOSINE(an));
th->momy = FixedMul(speed, FINESINE(an)); th->momy = FixedMul(speed, FINESINE(an));
dist = P_AproxDistance(dest->x - x, dest->y - y); dist = GetDistance2D(x, y, dest->x, dest->y);
dist = dist / speed; dist = dist / speed;
if (dist < 1) if (dist < 1)
...@@ -14111,11 +13957,11 @@ mobj_t *P_SpawnXYZMissile(mobj_t *source, mobj_t *dest, mobjtype_t type, ...@@ -14111,11 +13957,11 @@ mobj_t *P_SpawnXYZMissile(mobj_t *source, mobj_t *dest, mobjtype_t type,
th->momz = (dest->z - z) / dist; th->momz = (dest->z - z) / dist;
if (th->flags & MF_MISSILE) if (th->flags & MF_MISSILE)
dist = P_CheckMissileSpawn(th); spawned = P_CheckMissileSpawn(th);
else else
dist = 1; spawned = 1;
return dist ? th : NULL; return spawned ? th : NULL;
} }
// //
...@@ -14155,7 +14001,7 @@ mobj_t *P_SpawnAlteredDirectionMissile(mobj_t *source, mobjtype_t type, fixed_t ...@@ -14155,7 +14001,7 @@ mobj_t *P_SpawnAlteredDirectionMissile(mobj_t *source, mobjtype_t type, fixed_t
} }
if (th->info->seesound) if (th->info->seesound)
S_StartSound(th, th->info->seesound); S_StartSoundFromMobj(th, th->info->seesound);
P_SetTarget(&th->target, source->target); // where it came from P_SetTarget(&th->target, source->target); // where it came from
an = R_PointToAngle2(0, 0, source->momx, source->momy) + (ANG1*shiftingAngle); an = R_PointToAngle2(0, 0, source->momx, source->momy) + (ANG1*shiftingAngle);
...@@ -14165,7 +14011,7 @@ mobj_t *P_SpawnAlteredDirectionMissile(mobj_t *source, mobjtype_t type, fixed_t ...@@ -14165,7 +14011,7 @@ mobj_t *P_SpawnAlteredDirectionMissile(mobj_t *source, mobjtype_t type, fixed_t
th->momx = FixedMul(speed, FINECOSINE(an)); th->momx = FixedMul(speed, FINECOSINE(an));
th->momy = FixedMul(speed, FINESINE(an)); th->momy = FixedMul(speed, FINESINE(an));
dist = P_AproxDistance(source->momx*800, source->momy*800); dist = P_GetMobjMomentum2D(source)*800;
dist = dist / speed; dist = dist / speed;
if (dist < 1) if (dist < 1)
...@@ -14221,7 +14067,7 @@ mobj_t *P_SpawnPointMissile(mobj_t *source, fixed_t xa, fixed_t ya, fixed_t za, ...@@ -14221,7 +14067,7 @@ mobj_t *P_SpawnPointMissile(mobj_t *source, fixed_t xa, fixed_t ya, fixed_t za,
} }
if (th->info->seesound) if (th->info->seesound)
S_StartSound(th, th->info->seesound); S_StartSoundFromMobj(th, th->info->seesound);
P_SetTarget(&th->target, source); // where it came from P_SetTarget(&th->target, source); // where it came from
an = R_PointToAngle2(x, y, xa, ya); an = R_PointToAngle2(x, y, xa, ya);
...@@ -14231,7 +14077,7 @@ mobj_t *P_SpawnPointMissile(mobj_t *source, fixed_t xa, fixed_t ya, fixed_t za, ...@@ -14231,7 +14077,7 @@ mobj_t *P_SpawnPointMissile(mobj_t *source, fixed_t xa, fixed_t ya, fixed_t za,
th->momx = FixedMul(speed, FINECOSINE(an)); th->momx = FixedMul(speed, FINECOSINE(an));
th->momy = FixedMul(speed, FINESINE(an)); th->momy = FixedMul(speed, FINESINE(an));
dist = P_AproxDistance(xa - x, ya - y); dist = GetDistance2D(x, y, xa, ya);
dist = dist / speed; dist = dist / speed;
if (dist < 1) if (dist < 1)
...@@ -14295,7 +14141,7 @@ mobj_t *P_SpawnMissile(mobj_t *source, mobj_t *dest, mobjtype_t type) ...@@ -14295,7 +14141,7 @@ mobj_t *P_SpawnMissile(mobj_t *source, mobj_t *dest, mobjtype_t type)
} }
if (th->info->seesound) if (th->info->seesound)
S_StartSound(source, th->info->seesound); S_StartSoundFromMobj(source, th->info->seesound);
P_SetTarget(&th->target, source); // where it came from P_SetTarget(&th->target, source); // where it came from
...@@ -14312,9 +14158,9 @@ mobj_t *P_SpawnMissile(mobj_t *source, mobj_t *dest, mobjtype_t type) ...@@ -14312,9 +14158,9 @@ mobj_t *P_SpawnMissile(mobj_t *source, mobj_t *dest, mobjtype_t type)
th->momy = FixedMul(speed, FINESINE(an)); th->momy = FixedMul(speed, FINESINE(an));
if (type == MT_TURRETLASER || type == MT_ENERGYBALL) // More accurate! if (type == MT_TURRETLASER || type == MT_ENERGYBALL) // More accurate!
dist = P_AproxDistance(dest->x+(dest->momx*gsf) - source->x, dest->y+(dest->momy*gsf) - source->y); dist = GetDistance2D(source->x, source->y, dest->x+(dest->momx*gsf), dest->y+(dest->momy*gsf));
else else
dist = P_AproxDistance(dest->x - source->x, dest->y - source->y); dist = P_GetMobjDistance2D(dest, source);
dist = dist / speed; dist = dist / speed;
...@@ -14389,7 +14235,7 @@ mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle, UINT8 allowai ...@@ -14389,7 +14235,7 @@ mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle, UINT8 allowai
// The rail ring has no unique thrown object, so we must do this. // The rail ring has no unique thrown object, so we must do this.
if (th->info->seesound && !(th->flags2 & MF2_RAILRING)) if (th->info->seesound && !(th->flags2 & MF2_RAILRING))
S_StartSound(source, th->info->seesound); S_StartSoundFromMobj(source, th->info->seesound);
P_SetTarget(&th->target, source); P_SetTarget(&th->target, source);
...@@ -14444,7 +14290,8 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo ...@@ -14444,7 +14290,8 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo
yofs = FixedMul(yofs, mobj->scale); yofs = FixedMul(yofs, mobj->scale);
zofs = FixedMul(zofs, mobj->scale); zofs = FixedMul(zofs, mobj->scale);
newmobj = P_SpawnMobj(mobj->x + xofs, mobj->y + yofs, mobj->z + zofs, type); newmobj = P_SpawnMobj(mobj->x + xofs, mobj->y + yofs, mobj->z + zofs, type, NULL);
if (!newmobj) if (!newmobj)
return NULL; return NULL;
...@@ -14506,3 +14353,61 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo ...@@ -14506,3 +14353,61 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo
return newmobj; return newmobj;
} }
boolean P_IsMobjInPainState(mobj_t *mobj)
{
if (mobj->player)
return P_IsPlayerInState(mobj->player, S_PLAY_PAIN);
else
return (mobj->state == &states[mobj->info->painstate]);
}
fixed_t P_GetMobjDistance2D(mobj_t *mobj1, mobj_t *mobj2)
{
return GetDistance2D(mobj1->x, mobj1->y, mobj2->x, mobj2->y);
}
fixed_t P_GetMobjDistance3D(mobj_t *mobj1, mobj_t *mobj2)
{
return GetDistance3D(mobj1->x, mobj1->y, mobj1->z, mobj2->x, mobj2->y, mobj2->z);
}
INT32 P_GetMobjLargeDistance2D(mobj_t *mobj1, mobj_t *mobj2)
{
return GetLargeDistance2D(mobj1->x, mobj1->y, mobj2->x, mobj2->y);
}
INT32 P_GetMobjLargeDistance3D(mobj_t *mobj1, mobj_t *mobj2)
{
return GetLargeDistance3D(mobj1->x, mobj1->y, mobj1->z, mobj2->x, mobj2->y, mobj2->z);
}
boolean P_AreMobjsClose2D(mobj_t *mobj1, mobj_t *mobj2, fixed_t maxdist)
{
return ArePointsClose2D(mobj1->x, mobj1->y, mobj2->x, mobj2->y, maxdist);
}
boolean P_AreMobjsClose3D(mobj_t *mobj1, mobj_t *mobj2, fixed_t maxdist)
{
return ArePointsClose3D(mobj1->x, mobj1->y, mobj1->z, mobj2->x, mobj2->y, mobj2->z, maxdist);
}
boolean P_AreMobjsFar2D(mobj_t *mobj1, mobj_t *mobj2, fixed_t mindist)
{
return ArePointsFar2D(mobj1->x, mobj1->y, mobj2->x, mobj2->y, mindist);
}
boolean P_AreMobjsFar3D(mobj_t *mobj1, mobj_t *mobj2, fixed_t mindist)
{
return ArePointsFar3D(mobj1->x, mobj1->y, mobj1->z, mobj2->x, mobj2->y, mobj2->z, mindist);
}
fixed_t P_GetMobjMomentum2D(mobj_t *mobj)
{
return GetDistance2D(0, 0, mobj->momx, mobj->momy);
}
fixed_t P_GetMobjMomentum3D(mobj_t *mobj)
{
return GetDistance3D(0, 0, 0, mobj->momx, mobj->momy, mobj->momz);
}