mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'master' into battle-rethink
This commit is contained in:
commit
56a20d05df
46 changed files with 1053 additions and 371 deletions
|
|
@ -453,8 +453,9 @@ if(${SRB2_CONFIG_HAVE_DISCORDRPC})
|
|||
if(${DISCORDRPC_FOUND})
|
||||
set(SRB2_HAVE_DISCORDRPC ON)
|
||||
add_definitions(-DHAVE_DISCORDRPC)
|
||||
set(SRB2_DISCORDRPC_SOURCES discord.c)
|
||||
set(SRB2_DISCORDRPC_HEADERS discord.h)
|
||||
add_definitions(-DUSE_STUN)
|
||||
set(SRB2_DISCORDRPC_SOURCES discord.c stun.c)
|
||||
set(SRB2_DISCORDRPC_HEADERS discord.h stun.h)
|
||||
prepend_sources(SRB2_DISCORDRPC_SOURCES)
|
||||
prepend_sources(SRB2_DISCORDRPC_HEADERS)
|
||||
source_group("Discord Rich Presence" FILES ${SRB2_DISCORDRPC_SOURCES} ${SRB2_DISCORDRPC_HEADERS})
|
||||
|
|
|
|||
|
|
@ -393,8 +393,8 @@ endif
|
|||
|
||||
ifdef HAVE_DISCORDRPC
|
||||
LIBS+=-ldiscord-rpc
|
||||
CFLAGS+=-DHAVE_DISCORDRPC
|
||||
OBJS+=$(OBJDIR)/discord.o
|
||||
CFLAGS+=-DHAVE_DISCORDRPC -DUSE_STUN
|
||||
OBJS+=$(OBJDIR)/discord.o $(OBJDIR)/stun.o
|
||||
endif
|
||||
|
||||
include blua/Makefile.cfg
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ enum
|
|||
/* Command buffer flags. */
|
||||
enum
|
||||
{
|
||||
COM_SAFE = 1,
|
||||
COM_SAFE = 0x01,
|
||||
};
|
||||
|
||||
typedef void (*com_func_t)(void);
|
||||
|
|
|
|||
|
|
@ -2356,7 +2356,10 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent)
|
|||
cl_mode = CL_CHECKFILES;
|
||||
}
|
||||
else
|
||||
{
|
||||
cl_mode = CL_ASKJOIN; // files need not be checked for the server.
|
||||
*asksent = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -3583,6 +3586,76 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_CURL
|
||||
/** Add a login for HTTP downloads. If the
|
||||
* user/password is missing, remove it.
|
||||
*
|
||||
* \sa Command_list_http_logins
|
||||
*/
|
||||
static void Command_set_http_login (void)
|
||||
{
|
||||
HTTP_login *login;
|
||||
HTTP_login **prev_next;
|
||||
|
||||
if (COM_Argc() < 2)
|
||||
{
|
||||
CONS_Printf(
|
||||
"set_http_login <URL> [user:password]: Set or remove a login to "
|
||||
"authenticate HTTP downloads.\n"
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
login = CURLGetLogin(COM_Argv(1), &prev_next);
|
||||
|
||||
if (COM_Argc() == 2)
|
||||
{
|
||||
if (login)
|
||||
{
|
||||
(*prev_next) = login->next;
|
||||
CONS_Printf("Login for '%s' removed.\n", login->url);
|
||||
Z_Free(login);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (login)
|
||||
Z_Free(login->auth);
|
||||
else
|
||||
{
|
||||
login = ZZ_Alloc(sizeof *login);
|
||||
login->url = Z_StrDup(COM_Argv(1));
|
||||
}
|
||||
|
||||
login->auth = Z_StrDup(COM_Argv(2));
|
||||
|
||||
login->next = curl_logins;
|
||||
curl_logins = login;
|
||||
}
|
||||
}
|
||||
|
||||
/** List logins for HTTP downloads.
|
||||
*
|
||||
* \sa Command_set_http_login
|
||||
*/
|
||||
static void Command_list_http_logins (void)
|
||||
{
|
||||
HTTP_login *login;
|
||||
|
||||
for (
|
||||
login = curl_logins;
|
||||
login;
|
||||
login = login->next
|
||||
){
|
||||
CONS_Printf(
|
||||
"'%s' -> '%s'\n",
|
||||
login->url,
|
||||
login->auth
|
||||
);
|
||||
}
|
||||
}
|
||||
#endif/*HAVE_CURL*/
|
||||
|
||||
static CV_PossibleValue_t netticbuffer_cons_t[] = {{0, "MIN"}, {3, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_netticbuffer = CVAR_INIT ("netticbuffer", "1", CV_SAVE, netticbuffer_cons_t, NULL);
|
||||
|
||||
|
|
@ -3658,6 +3731,10 @@ void D_ClientServerInit(void)
|
|||
COM_AddCommand("reloadbans", Command_ReloadBan);
|
||||
COM_AddCommand("connect", Command_connect);
|
||||
COM_AddCommand("nodes", Command_Nodes);
|
||||
#ifdef HAVE_CURL
|
||||
COM_AddCommand("set_http_login", Command_set_http_login);
|
||||
COM_AddCommand("list_http_logins", Command_list_http_logins);
|
||||
#endif
|
||||
#ifdef PACKETDROP
|
||||
COM_AddCommand("drop", Command_Drop);
|
||||
COM_AddCommand("droprate", Command_Droprate);
|
||||
|
|
@ -5495,7 +5572,10 @@ static void CL_SendClientCmd(void)
|
|||
boolean mis = false;
|
||||
|
||||
if (lowest_lag && ( gametic % lowest_lag ))
|
||||
{
|
||||
cl_packetmissed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
netbuffer->packettype = PT_CLIENTCMD;
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ applications may follow different packet versions.
|
|||
// be transmitted.
|
||||
|
||||
// Networking and tick handling related.
|
||||
#define BACKUPTICS 32
|
||||
#define BACKUPTICS 1024
|
||||
#define TICQUEUE 512 // more than enough for most timeouts....
|
||||
#define MAXTEXTCMD 256
|
||||
//
|
||||
|
|
@ -571,6 +571,7 @@ extern INT32 mapchangepending;
|
|||
|
||||
// Points inside doomcom
|
||||
extern doomdata_t *netbuffer;
|
||||
extern consvar_t cv_stunserver;
|
||||
extern consvar_t cv_httpsource;
|
||||
|
||||
extern consvar_t cv_showjoinaddress;
|
||||
|
|
|
|||
|
|
@ -748,6 +748,10 @@ void D_RegisterServerCommands(void)
|
|||
|
||||
CV_RegisterVar(&cv_dummyconsvar);
|
||||
|
||||
#ifdef USE_STUN
|
||||
CV_RegisterVar(&cv_stunserver);
|
||||
#endif
|
||||
|
||||
CV_RegisterVar(&cv_discordinvites);
|
||||
RegisterNetXCmd(XD_DISCORD, Got_DiscordInfo);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@ static UINT32 curl_origfilesize;
|
|||
static UINT32 curl_origtotalfilesize;
|
||||
static char *curl_realname = NULL;
|
||||
fileneeded_t *curl_curfile = NULL;
|
||||
HTTP_login *curl_logins;
|
||||
#endif
|
||||
|
||||
luafiletransfer_t *luafiletransfers = NULL;
|
||||
|
|
@ -476,10 +477,10 @@ INT32 CL_CheckFiles(void)
|
|||
|
||||
for (i = 0; i < fileneedednum; i++)
|
||||
{
|
||||
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_FALLBACK)
|
||||
if (fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD || fileneeded[i].status == FS_FALLBACK)
|
||||
downloadrequired = true;
|
||||
|
||||
if (fileneeded[i].status == FS_FOUND || fileneeded[i].status == FS_NOTFOUND)
|
||||
if (fileneeded[i].status != FS_OPEN)
|
||||
filestoload++;
|
||||
|
||||
if (fileneeded[i].status != FS_NOTCHECKED) //since we're running this over multiple tics now, its possible for us to come across files checked in previous tics
|
||||
|
|
@ -1646,6 +1647,8 @@ int curlprogress_callback(void *clientp, double dltotal, double dlnow, double ul
|
|||
|
||||
void CURLPrepareFile(const char* url, int dfilenum)
|
||||
{
|
||||
HTTP_login *login;
|
||||
|
||||
#ifdef PARANOIA
|
||||
if (M_CheckParm("-nodownload"))
|
||||
I_Error("Attempted to download files in -nodownload mode");
|
||||
|
|
@ -1674,6 +1677,14 @@ void CURLPrepareFile(const char* url, int dfilenum)
|
|||
|
||||
curl_easy_setopt(http_handle, CURLOPT_USERAGENT, va("SRB2Kart/v%d.%d", VERSION, SUBVERSION)); // Set user agent as some servers won't accept invalid user agents.
|
||||
|
||||
// Authenticate if the user so wishes
|
||||
login = CURLGetLogin(url, NULL);
|
||||
|
||||
if (login)
|
||||
{
|
||||
curl_easy_setopt(http_handle, CURLOPT_USERPWD, login->auth);
|
||||
}
|
||||
|
||||
// Follow a redirect request, if sent by the server.
|
||||
curl_easy_setopt(http_handle, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
|
||||
|
|
@ -1775,4 +1786,27 @@ void CURLGetFile(void)
|
|||
curl_global_cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
HTTP_login *
|
||||
CURLGetLogin (const char *url, HTTP_login ***return_prev_next)
|
||||
{
|
||||
HTTP_login * login;
|
||||
HTTP_login ** prev_next;
|
||||
|
||||
for (
|
||||
prev_next = &curl_logins;
|
||||
( login = (*prev_next));
|
||||
prev_next = &login->next
|
||||
){
|
||||
if (strcmp(login->url, url) == 0)
|
||||
{
|
||||
if (return_prev_next)
|
||||
(*return_prev_next) = prev_next;
|
||||
|
||||
return login;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -72,6 +72,16 @@ extern UINT32 totalfilesrequestedsize;
|
|||
extern boolean curl_failedwebdownload;
|
||||
extern boolean curl_running;
|
||||
extern INT32 curl_transfers;
|
||||
|
||||
typedef struct HTTP_login HTTP_login;
|
||||
|
||||
extern struct HTTP_login
|
||||
{
|
||||
char * url;
|
||||
char * auth;
|
||||
HTTP_login * next;
|
||||
}
|
||||
*curl_logins;
|
||||
#endif
|
||||
|
||||
UINT8 *PutFileNeeded(UINT16 firstfile);
|
||||
|
|
@ -151,6 +161,7 @@ size_t nameonlylength(const char *s);
|
|||
#ifdef HAVE_CURL
|
||||
void CURLPrepareFile(const char* url, int dfilenum);
|
||||
void CURLGetFile(void);
|
||||
HTTP_login * CURLGetLogin (const char *url, HTTP_login ***return_prev_next);
|
||||
#endif
|
||||
|
||||
#endif // __D_NETFIL__
|
||||
|
|
|
|||
|
|
@ -9351,6 +9351,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
|
|||
"S_WATERTRAILUNDERLAY7",
|
||||
"S_WATERTRAILUNDERLAY8",
|
||||
|
||||
"S_SPINDASHDUST",
|
||||
"S_SPINDASHWIND",
|
||||
|
||||
#ifdef SEENAMES
|
||||
"S_NAMECHECK",
|
||||
#endif
|
||||
|
|
@ -10423,6 +10426,9 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s
|
|||
"MT_WATERTRAIL",
|
||||
"MT_WATERTRAILUNDERLAY",
|
||||
|
||||
"MT_SPINDASHDUST",
|
||||
"MT_SPINDASHWIND",
|
||||
|
||||
"MT_PAPERITEMSPOT",
|
||||
|
||||
#ifdef SEENAMES
|
||||
|
|
|
|||
138
src/discord.c
138
src/discord.c
|
|
@ -12,9 +12,7 @@
|
|||
|
||||
#ifdef HAVE_DISCORDRPC
|
||||
|
||||
#ifdef HAVE_CURL
|
||||
#include <curl/curl.h>
|
||||
#endif // HAVE_CURL
|
||||
#include <time.h>
|
||||
|
||||
#include "i_system.h"
|
||||
#include "d_clisrv.h"
|
||||
|
|
@ -27,6 +25,8 @@
|
|||
#include "mserv.h" // cv_advertise
|
||||
#include "z_zone.h"
|
||||
#include "byteptr.h"
|
||||
#include "stun.h"
|
||||
#include "i_tcp.h" // current_port
|
||||
|
||||
#include "discord.h"
|
||||
#include "doomdef.h"
|
||||
|
|
@ -45,16 +45,7 @@ struct discordInfo_s discordInfo;
|
|||
|
||||
discordRequest_t *discordRequestList = NULL;
|
||||
|
||||
#ifdef HAVE_CURL
|
||||
struct SelfIPbuffer
|
||||
{
|
||||
CURL *curl;
|
||||
char *pointer;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
static char self_ip[IP_SIZE];
|
||||
#endif // HAVE_CURL
|
||||
|
||||
/*--------------------------------------------------
|
||||
static char *DRPC_XORIPString(const char *input)
|
||||
|
|
@ -335,39 +326,23 @@ void DRPC_Init(void)
|
|||
DRPC_UpdatePresence();
|
||||
}
|
||||
|
||||
#ifdef HAVE_CURL
|
||||
/*--------------------------------------------------
|
||||
static size_t DRPC_WriteServerIP(char *s, size_t size, size_t n, void *userdata)
|
||||
static void DRPC_GotServerIP(UINT32 address)
|
||||
|
||||
Writing function for use with curl. Only intended to be used with simple text.
|
||||
Callback triggered by successful STUN response.
|
||||
|
||||
Input Arguments:-
|
||||
s - Data to write
|
||||
size - Always 1.
|
||||
n - Length of data
|
||||
userdata - Passed in from CURLOPT_WRITEDATA, intended to be SelfIPbuffer
|
||||
address - IPv4 address of this machine, in network byte order.
|
||||
|
||||
Return:-
|
||||
Number of bytes wrote in this pass.
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
static size_t DRPC_WriteServerIP(char *s, size_t size, size_t n, void *userdata)
|
||||
static void DRPC_GotServerIP(UINT32 address)
|
||||
{
|
||||
struct SelfIPbuffer *buffer;
|
||||
size_t newlength;
|
||||
|
||||
buffer = userdata;
|
||||
|
||||
newlength = buffer->length + size*n;
|
||||
buffer->pointer = realloc(buffer->pointer, newlength+1);
|
||||
|
||||
memcpy(buffer->pointer + buffer->length, s, size*n);
|
||||
|
||||
buffer->pointer[newlength] = '\0';
|
||||
buffer->length = newlength;
|
||||
|
||||
return size*n;
|
||||
const unsigned char * p = (const unsigned char *)&address;
|
||||
sprintf(self_ip, "%u.%u.%u.%u:%u", p[0], p[1], p[2], p[3], current_port);
|
||||
DRPC_UpdatePresence();
|
||||
}
|
||||
#endif // HAVE_CURL
|
||||
|
||||
/*--------------------------------------------------
|
||||
static const char *DRPC_GetServerIP(void)
|
||||
|
|
@ -387,64 +362,21 @@ static const char *DRPC_GetServerIP(void)
|
|||
{
|
||||
// We're not the server, so we could successfully get the IP!
|
||||
// No need to do anything else :)
|
||||
return address;
|
||||
sprintf(self_ip, "%s:%u", address, current_port);
|
||||
return self_ip;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_CURL
|
||||
// This is a little bit goofy, but
|
||||
// there's practically no good way to get your own public IP address,
|
||||
// so we've gotta break out curl for this :V
|
||||
if (!self_ip[0])
|
||||
{
|
||||
CURL *curl;
|
||||
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
curl = curl_easy_init();
|
||||
|
||||
if (curl)
|
||||
{
|
||||
// The API to get your public IP address from.
|
||||
// Picked because it's stupid simple and it's been up for a long time.
|
||||
const char *api = "http://ip4only.me/api/";
|
||||
|
||||
struct SelfIPbuffer buffer;
|
||||
CURLcode success;
|
||||
|
||||
buffer.length = 0;
|
||||
buffer.pointer = malloc(buffer.length+1);
|
||||
buffer.pointer[0] = '\0';
|
||||
|
||||
curl_easy_setopt(curl, CURLOPT_URL, api);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, DRPC_WriteServerIP);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
|
||||
|
||||
success = curl_easy_perform(curl);
|
||||
|
||||
if (success == CURLE_OK)
|
||||
{
|
||||
char *tmp;
|
||||
tmp = strtok(buffer.pointer, ",");
|
||||
|
||||
if (!strcmp(tmp, "IPv4")) // ensure correct type of IP
|
||||
{
|
||||
tmp = strtok(NULL, ",");
|
||||
strncpy(self_ip, tmp, IP_SIZE); // Yay, we have the IP :)
|
||||
}
|
||||
}
|
||||
|
||||
free(buffer.pointer);
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
|
||||
curl_global_cleanup();
|
||||
}
|
||||
|
||||
if (self_ip[0])
|
||||
{
|
||||
return self_ip;
|
||||
}
|
||||
else
|
||||
#endif // HAVE_CURL
|
||||
return NULL; // Could not get your IP for whatever reason, so we cannot do Discord invites
|
||||
{
|
||||
// There happens to be a good way to get it after all! :D
|
||||
STUN_bind(DRPC_GotServerIP);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
@ -510,19 +442,6 @@ void DRPC_UpdatePresence(void)
|
|||
// Server info
|
||||
if (netgame)
|
||||
{
|
||||
if (cv_advertise.value)
|
||||
{
|
||||
discordPresence.state = "Public";
|
||||
}
|
||||
else
|
||||
{
|
||||
discordPresence.state = "Private";
|
||||
}
|
||||
|
||||
discordPresence.partyId = server_context; // Thanks, whoever gave us Mumble support, for implementing the EXACT thing Discord wanted for this field!
|
||||
discordPresence.partySize = D_NumPlayers(); // Players in server
|
||||
discordPresence.partyMax = discordInfo.maxPlayers; // Max players
|
||||
|
||||
if (DRPC_InvitesAreAllowed() == true)
|
||||
{
|
||||
const char *join;
|
||||
|
|
@ -536,7 +455,24 @@ void DRPC_UpdatePresence(void)
|
|||
|
||||
joinSecretSet = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (cv_advertise.value)
|
||||
{
|
||||
discordPresence.state = "Public";
|
||||
}
|
||||
else
|
||||
{
|
||||
discordPresence.state = "Private";
|
||||
}
|
||||
|
||||
discordPresence.partyId = server_context; // Thanks, whoever gave us Mumble support, for implementing the EXACT thing Discord wanted for this field!
|
||||
discordPresence.partySize = D_NumPlayers(); // Players in server
|
||||
discordPresence.partyMax = discordInfo.maxPlayers; // Max players
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -318,10 +318,6 @@ void G_ReadDemoExtraData(void)
|
|||
playeringame[p] = true;
|
||||
G_AddPlayer(p);
|
||||
players[p].spectator = true;
|
||||
|
||||
// There's likely an off-by-one error in timing recording or playback of joins. This hacks around it so I don't have to find out where that is. \o/
|
||||
if (oldcmd[p].forwardmove)
|
||||
P_RandomByte();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3617,9 +3617,9 @@ static boolean HWR_DoCulling(line_t *cullheight, line_t *viewcullheight, float v
|
|||
|
||||
static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
|
||||
{
|
||||
const fixed_t thingxpos = thing->x + thing->sprxoff;
|
||||
const fixed_t thingypos = thing->y + thing->spryoff;
|
||||
const fixed_t thingzpos = thing->z + thing->sprzoff;
|
||||
fixed_t thingxpos = thing->x + thing->sprxoff;
|
||||
fixed_t thingypos = thing->y + thing->spryoff;
|
||||
fixed_t thingzpos = thing->z + thing->sprzoff;
|
||||
|
||||
GLPatch_t *gpatch;
|
||||
FOutVector shadowVerts[4];
|
||||
|
|
@ -3637,6 +3637,21 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
|
|||
fixed_t slopez;
|
||||
pslope_t *groundslope;
|
||||
|
||||
// hitlag vibrating
|
||||
if (thing->hitlag > 0)
|
||||
{
|
||||
fixed_t mul = thing->hitlag * (FRACUNIT / 10);
|
||||
|
||||
if (leveltime & 1)
|
||||
{
|
||||
mul = -mul;
|
||||
}
|
||||
|
||||
thingxpos += FixedMul(thing->momx, mul);
|
||||
thingypos += FixedMul(thing->momy, mul);
|
||||
thingzpos += FixedMul(thing->momz, mul);
|
||||
}
|
||||
|
||||
groundz = R_GetShadowZ(thing, &groundslope);
|
||||
|
||||
floordiff = abs((flip < 0 ? thing->height : 0) + thingzpos - groundz);
|
||||
|
|
@ -4867,9 +4882,9 @@ static void HWR_AddSprites(sector_t *sec)
|
|||
// BP why not use xtoviexangle/viewangletox like in bsp ?....
|
||||
static void HWR_ProjectSprite(mobj_t *thing)
|
||||
{
|
||||
const fixed_t thingxpos = thing->x + thing->sprxoff;
|
||||
const fixed_t thingypos = thing->y + thing->spryoff;
|
||||
const fixed_t thingzpos = thing->z + thing->sprzoff;
|
||||
fixed_t thingxpos = thing->x + thing->sprxoff;
|
||||
fixed_t thingypos = thing->y + thing->spryoff;
|
||||
fixed_t thingzpos = thing->z + thing->sprzoff;
|
||||
|
||||
gl_vissprite_t *vis;
|
||||
float tr_x, tr_y;
|
||||
|
|
@ -4907,6 +4922,21 @@ static void HWR_ProjectSprite(mobj_t *thing)
|
|||
if (!thing)
|
||||
return;
|
||||
|
||||
// hitlag vibrating
|
||||
if (thing->hitlag > 0)
|
||||
{
|
||||
fixed_t mul = thing->hitlag * (FRACUNIT / 10);
|
||||
|
||||
if (leveltime & 1)
|
||||
{
|
||||
mul = -mul;
|
||||
}
|
||||
|
||||
thingxpos += FixedMul(thing->momx, mul);
|
||||
thingypos += FixedMul(thing->momy, mul);
|
||||
thingzpos += FixedMul(thing->momz, mul);
|
||||
}
|
||||
|
||||
dispoffset = thing->info->dispoffset;
|
||||
|
||||
this_scale = FIXED_TO_FLOAT(thing->scale);
|
||||
|
|
|
|||
|
|
@ -1340,9 +1340,9 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
|
||||
// Look at HWR_ProjectSprite for more
|
||||
{
|
||||
const fixed_t thingxpos = spr->mobj->x + spr->mobj->sprxoff;
|
||||
const fixed_t thingypos = spr->mobj->y + spr->mobj->spryoff;
|
||||
const fixed_t thingzpos = spr->mobj->z + spr->mobj->sprzoff;
|
||||
fixed_t thingxpos = spr->mobj->x + spr->mobj->sprxoff;
|
||||
fixed_t thingypos = spr->mobj->y + spr->mobj->spryoff;
|
||||
fixed_t thingzpos = spr->mobj->z + spr->mobj->sprzoff;
|
||||
|
||||
GLPatch_t *gpatch;
|
||||
INT32 durs = spr->mobj->state->tics;
|
||||
|
|
@ -1358,6 +1358,21 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
INT32 mod;
|
||||
float finalscale;
|
||||
|
||||
// hitlag vibrating
|
||||
if (spr->mobj->hitlag > 0)
|
||||
{
|
||||
fixed_t mul = spr->mobj->hitlag * (FRACUNIT / 10);
|
||||
|
||||
if (leveltime & 1)
|
||||
{
|
||||
mul = -mul;
|
||||
}
|
||||
|
||||
thingxpos += FixedMul(spr->mobj->momx, mul);
|
||||
thingypos += FixedMul(spr->mobj->momy, mul);
|
||||
thingzpos += FixedMul(spr->mobj->momz, mul);
|
||||
}
|
||||
|
||||
// Apparently people don't like jump frames like that, so back it goes
|
||||
//if (tics > durs)
|
||||
//durs = tics;
|
||||
|
|
|
|||
|
|
@ -152,6 +152,7 @@ static UINT8 UPNP_support = TRUE;
|
|||
#include "d_netfil.h"
|
||||
#include "i_tcp.h"
|
||||
#include "m_argv.h"
|
||||
#include "stun.h"
|
||||
|
||||
#include "doomstat.h"
|
||||
|
||||
|
|
@ -575,6 +576,13 @@ static boolean SOCK_Get(void)
|
|||
(void *)&fromaddress, &fromlen);
|
||||
if (c != ERRSOCKET)
|
||||
{
|
||||
#ifdef USE_STUN
|
||||
if (STUN_got_response(doomcom->data, c))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// find remote node number
|
||||
for (j = 1; j <= MAXNETNODES; j++) //include LAN
|
||||
{
|
||||
|
|
|
|||
76
src/info.c
76
src/info.c
|
|
@ -738,6 +738,9 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
"DBCL", // Drift boost clip
|
||||
"DBNC", // Drift boost clip's sparks
|
||||
"DBST", // Drift boost plume
|
||||
|
||||
"SDDS", // Spindash dust
|
||||
"SDWN", // Spindash wind
|
||||
};
|
||||
|
||||
char spr2names[NUMPLAYERSPRITES][5] =
|
||||
|
|
@ -5064,6 +5067,9 @@ state_t states[NUMSTATES] =
|
|||
{SPR_WTRL, FF_TRANS50|FF_PAPERSPRITE|14, 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAILUNDERLAY7
|
||||
{SPR_WTRL, FF_TRANS50|FF_PAPERSPRITE|15, 2, {NULL}, 0, 0, S_NULL}, // S_WATERTRAILUNDERLAY8
|
||||
|
||||
{SPR_SDDS, FF_ANIMATE, 9, {NULL}, 9, 1, S_NULL}, // S_SPINDASHDUST
|
||||
{SPR_SDWN, FF_ANIMATE|FF_PAPERSPRITE, 18, {NULL}, 9, 2, S_NULL}, // S_SPINDASHWIND
|
||||
|
||||
#ifdef SEENAMES
|
||||
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK
|
||||
#endif
|
||||
|
|
@ -8415,7 +8421,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
25*FRACUNIT, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags
|
||||
MF_SOLID|MF_SPRING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
|
||||
S_YELLOWSPRING2 // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -8442,7 +8448,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
40*FRACUNIT, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags
|
||||
MF_SOLID|MF_SPRING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
|
||||
S_REDSPRING2 // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -8469,7 +8475,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
64*FRACUNIT, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags
|
||||
MF_SOLID|MF_SPRING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
|
||||
S_BLUESPRING2 // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -8496,7 +8502,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
15*FRACUNIT, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags
|
||||
MF_SOLID|MF_SPRING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
|
||||
S_GREYSPRING2 // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -8523,7 +8529,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
25*FRACUNIT, // mass
|
||||
25*FRACUNIT, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags
|
||||
MF_SOLID|MF_SPRING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
|
||||
S_YDIAG2 // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -8550,7 +8556,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
40*FRACUNIT, // mass
|
||||
40*FRACUNIT, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags
|
||||
MF_SOLID|MF_SPRING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
|
||||
S_RDIAG2 // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -8577,7 +8583,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
64*FRACUNIT, // mass
|
||||
64*FRACUNIT, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags
|
||||
MF_SOLID|MF_SPRING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
|
||||
S_BDIAG2 // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -8604,7 +8610,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
15*FRACUNIT, // mass
|
||||
15*FRACUNIT, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SOLID|MF_SPRING|MF_DONTENCOREMAP, // flags
|
||||
MF_SOLID|MF_SPRING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
|
||||
S_GDIAG2 // raisestate
|
||||
},
|
||||
|
||||
|
|
@ -28503,6 +28509,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_SPINDASHDUST
|
||||
-1, // doomednum
|
||||
S_SPINDASHDUST, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
12*FRACUNIT, // radius
|
||||
24*FRACUNIT, // height
|
||||
0, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_SPINDASHWIND
|
||||
-1, // doomednum
|
||||
S_SPINDASHWIND, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
12*FRACUNIT, // radius
|
||||
24*FRACUNIT, // height
|
||||
0, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_PAPERITEMSPOT
|
||||
-1, // doomednum
|
||||
S_INVISIBLE, // spawnstate
|
||||
|
|
|
|||
|
|
@ -1010,6 +1010,9 @@ typedef enum sprite
|
|||
SPR_DBNC, // Drift boost clip's sparks
|
||||
SPR_DBST, // Drift boost plume
|
||||
|
||||
SPR_SDDS, // Spindash dust
|
||||
SPR_SDWN, // Spindash wind
|
||||
|
||||
SPR_FIRSTFREESLOT,
|
||||
SPR_LASTFREESLOT = SPR_FIRSTFREESLOT + NUMSPRITEFREESLOTS - 1,
|
||||
NUMSPRITES
|
||||
|
|
@ -5219,6 +5222,9 @@ typedef enum state
|
|||
S_WATERTRAILUNDERLAY7,
|
||||
S_WATERTRAILUNDERLAY8,
|
||||
|
||||
S_SPINDASHDUST,
|
||||
S_SPINDASHWIND,
|
||||
|
||||
#ifdef SEENAMES
|
||||
S_NAMECHECK,
|
||||
#endif
|
||||
|
|
@ -6311,6 +6317,9 @@ typedef enum mobj_type
|
|||
MT_WATERTRAIL,
|
||||
MT_WATERTRAILUNDERLAY,
|
||||
|
||||
MT_SPINDASHDUST,
|
||||
MT_SPINDASHWIND,
|
||||
|
||||
MT_PAPERITEMSPOT,
|
||||
|
||||
#ifdef SEENAMES
|
||||
|
|
|
|||
|
|
@ -30,7 +30,8 @@ boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2)
|
|||
|
||||
if (t2->player)
|
||||
{
|
||||
if (t2->player->powers[pw_flashing] && (t1->type == MT_ORBINAUT_SHIELD || t1->type == MT_JAWZ_SHIELD))
|
||||
if ((t2->player->powers[pw_flashing] > 0 && t2->hitlag == 0)
|
||||
&& !(t1->type == MT_ORBINAUT || t1->type == MT_JAWZ || t1->type == MT_JAWZ_DUD))
|
||||
return true;
|
||||
|
||||
if (t2->player->kartstuff[k_hyudorotimer])
|
||||
|
|
@ -57,11 +58,6 @@ boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2)
|
|||
|| t2->type == MT_BALLHOG)
|
||||
{
|
||||
// Other Item Damage
|
||||
if (t2->eflags & MFE_VERTICALFLIP)
|
||||
t2->z -= t2->height;
|
||||
else
|
||||
t2->z += t2->height;
|
||||
|
||||
S_StartSound(t2, t2->info->deathsound);
|
||||
P_KillMobj(t2, t1, t1, DMG_NORMAL);
|
||||
|
||||
|
|
@ -93,11 +89,6 @@ boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2)
|
|||
if (damageitem)
|
||||
{
|
||||
// This Item Damage
|
||||
if (t1->eflags & MFE_VERTICALFLIP)
|
||||
t1->z -= t1->height;
|
||||
else
|
||||
t1->z += t1->height;
|
||||
|
||||
S_StartSound(t1, t1->info->deathsound);
|
||||
P_KillMobj(t1, t2, t2, DMG_NORMAL);
|
||||
|
||||
|
|
@ -132,7 +123,7 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2)
|
|||
|
||||
if (t2->player)
|
||||
{
|
||||
if (t2->player->powers[pw_flashing])
|
||||
if (t2->player->powers[pw_flashing] > 0 && t2->hitlag == 0)
|
||||
return true;
|
||||
|
||||
// Banana snipe!
|
||||
|
|
@ -146,7 +137,6 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2)
|
|||
}
|
||||
else
|
||||
{
|
||||
// Player Damage
|
||||
P_DamageMobj(t2, t1, t1->target, 1, DMG_NORMAL);
|
||||
}
|
||||
|
||||
|
|
@ -158,11 +148,6 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2)
|
|||
|| t2->type == MT_BALLHOG)
|
||||
{
|
||||
// Other Item Damage
|
||||
if (t2->eflags & MFE_VERTICALFLIP)
|
||||
t2->z -= t2->height;
|
||||
else
|
||||
t2->z += t2->height;
|
||||
|
||||
S_StartSound(t2, t2->info->deathsound);
|
||||
P_KillMobj(t2, t1, t1, DMG_NORMAL);
|
||||
|
||||
|
|
@ -183,11 +168,6 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2)
|
|||
if (damageitem)
|
||||
{
|
||||
// This Item Damage
|
||||
if (t1->eflags & MFE_VERTICALFLIP)
|
||||
t1->z -= t1->height;
|
||||
else
|
||||
t1->z += t1->height;
|
||||
|
||||
S_StartSound(t1, t1->info->deathsound);
|
||||
P_KillMobj(t1, t2, t2, DMG_NORMAL);
|
||||
|
||||
|
|
@ -286,15 +266,19 @@ boolean K_MineCollide(mobj_t *t1, mobj_t *t2)
|
|||
|
||||
if (t2->player)
|
||||
{
|
||||
if (t2->player->powers[pw_flashing])
|
||||
if (t2->player->powers[pw_flashing] > 0 && t2->hitlag == 0)
|
||||
return true;
|
||||
|
||||
// Bomb punting
|
||||
if ((t1->state >= &states[S_SSMINE1] && t1->state <= &states[S_SSMINE4])
|
||||
|| (t1->state >= &states[S_SSMINE_DEPLOY8] && t1->state <= &states[S_SSMINE_DEPLOY13]))
|
||||
{
|
||||
P_KillMobj(t1, t2, t2, DMG_NORMAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
K_PuntMine(t1, t2);
|
||||
}
|
||||
}
|
||||
else if (t2->type == MT_ORBINAUT || t2->type == MT_JAWZ || t2->type == MT_JAWZ_DUD
|
||||
|| t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD)
|
||||
|
|
@ -303,11 +287,6 @@ boolean K_MineCollide(mobj_t *t1, mobj_t *t2)
|
|||
P_KillMobj(t1, t2, t2, DMG_NORMAL);
|
||||
|
||||
// Other Item Damage
|
||||
if (t2->eflags & MFE_VERTICALFLIP)
|
||||
t2->z -= t2->height;
|
||||
else
|
||||
t2->z += t2->height;
|
||||
|
||||
S_StartSound(t2, t2->info->deathsound);
|
||||
P_KillMobj(t2, t1, t1, DMG_NORMAL);
|
||||
|
||||
|
|
@ -329,10 +308,17 @@ boolean K_MineExplosionCollide(mobj_t *t1, mobj_t *t2)
|
|||
{
|
||||
if (t2->player)
|
||||
{
|
||||
if (t2->player->powers[pw_flashing])
|
||||
if (t2->player->powers[pw_flashing] > 0 && t2->hitlag == 0)
|
||||
return true;
|
||||
|
||||
P_DamageMobj(t2, t1, t1->target, 1, (t1->state == &states[S_MINEEXPLOSION1]) ? DMG_EXPLODE : DMG_NORMAL);
|
||||
if (t1->state == &states[S_MINEEXPLOSION1])
|
||||
{
|
||||
P_DamageMobj(t2, t1, t1->target, 1, DMG_EXPLODE);
|
||||
}
|
||||
else
|
||||
{
|
||||
P_DamageMobj(t2, t1, t1->target, 1, DMG_NORMAL);
|
||||
}
|
||||
}
|
||||
else if (t2->flags & MF_SHOOTABLE)
|
||||
{
|
||||
|
|
@ -350,14 +336,16 @@ boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2)
|
|||
|
||||
if (t2->player)
|
||||
{
|
||||
if (t2->player->powers[pw_flashing])
|
||||
if (t2->player->powers[pw_flashing] > 0 && t2->hitlag == 0)
|
||||
return true;
|
||||
|
||||
S_StartSound(NULL, sfx_bsnipe); // let all players hear it.
|
||||
|
||||
HU_SetCEchoFlags(0);
|
||||
HU_SetCEchoDuration(5);
|
||||
HU_DoCEcho(va("%s\\was hit by a kitchen sink.\\\\\\\\", player_names[t2->player-players]));
|
||||
I_OutputMsg("%s was hit by a kitchen sink.\n", player_names[t2->player-players]);
|
||||
|
||||
P_DamageMobj(t2, t1, t1->target, 1, DMG_INSTAKILL);
|
||||
P_KillMobj(t1, t2, t2, DMG_NORMAL);
|
||||
}
|
||||
|
|
|
|||
214
src/k_kart.c
214
src/k_kart.c
|
|
@ -1461,8 +1461,8 @@ static void K_UpdateDraft(player_t *player)
|
|||
continue;
|
||||
|
||||
#ifndef EASYDRAFTTEST
|
||||
yourangle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy);
|
||||
theirangle = R_PointToAngle2(0, 0, players[i].mo->momx, players[i].mo->momy);
|
||||
yourangle = K_MomentumAngle(player->mo);
|
||||
theirangle = K_MomentumAngle(players[i].mo);
|
||||
|
||||
diff = R_PointToAngle2(player->mo->x, player->mo->y, players[i].mo->x, players[i].mo->y) - yourangle;
|
||||
if (diff > ANGLE_180)
|
||||
|
|
@ -2019,7 +2019,7 @@ void K_PlayPowerGloatSound(mobj_t *source)
|
|||
|
||||
void K_MomentumToFacing(player_t *player)
|
||||
{
|
||||
angle_t dangle = player->mo->angle - R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy);
|
||||
angle_t dangle = player->mo->angle - K_MomentumAngle(player->mo);
|
||||
|
||||
if (dangle > ANGLE_180)
|
||||
dangle = InvAngle(dangle);
|
||||
|
|
@ -2048,7 +2048,7 @@ static fixed_t K_FlameShieldDashVar(INT32 val)
|
|||
return (3*FRACUNIT/4) + (((val * FRACUNIT) / TICRATE) / 2);
|
||||
}
|
||||
|
||||
tic_t K_GetSpindashChargeTime(player_t *player)
|
||||
INT16 K_GetSpindashChargeTime(player_t *player)
|
||||
{
|
||||
// more charge time for higher speed
|
||||
// Tails = 2s, Mighty = 3s, Fang = 4s, Metal = 4s
|
||||
|
|
@ -2366,6 +2366,83 @@ fixed_t K_3dKartMovement(player_t *player)
|
|||
return finalspeed;
|
||||
}
|
||||
|
||||
angle_t K_MomentumAngle(mobj_t *mo)
|
||||
{
|
||||
if (mo->momx || mo->momy)
|
||||
{
|
||||
return R_PointToAngle2(0, 0, mo->momx, mo->momy);
|
||||
}
|
||||
else
|
||||
{
|
||||
return mo->angle; // default to facing angle, rather than 0
|
||||
}
|
||||
}
|
||||
|
||||
void K_SetHitLagForObjects(mobj_t *mo1, mobj_t *mo2, INT32 tics)
|
||||
{
|
||||
boolean mo1valid = (mo1 && !P_MobjWasRemoved(mo1));
|
||||
boolean mo2valid = (mo2 && !P_MobjWasRemoved(mo2));
|
||||
|
||||
INT32 tics1 = tics;
|
||||
INT32 tics2 = tics;
|
||||
|
||||
if (mo1valid == true && mo2valid == true)
|
||||
{
|
||||
const fixed_t ticaddfactor = mapobjectscale * 8;
|
||||
const INT32 mintics = tics;
|
||||
|
||||
const fixed_t mo1speed = FixedHypot(FixedHypot(mo1->momx, mo1->momy), mo1->momz);
|
||||
const fixed_t mo2speed = FixedHypot(FixedHypot(mo2->momx, mo2->momy), mo2->momz);
|
||||
const fixed_t speeddiff = mo2speed - mo1speed;
|
||||
|
||||
const fixed_t scalediff = mo2->scale - mo1->scale;
|
||||
|
||||
const angle_t mo1angle = K_MomentumAngle(mo1);
|
||||
const angle_t mo2angle = K_MomentumAngle(mo2);
|
||||
|
||||
angle_t anglediff = mo1angle - mo2angle;
|
||||
fixed_t anglemul = FRACUNIT;
|
||||
|
||||
if (anglediff > ANGLE_180)
|
||||
{
|
||||
anglediff = InvAngle(anglediff);
|
||||
}
|
||||
|
||||
anglemul = FRACUNIT + (AngleFixed(anglediff) / 180); // x1.0 at 0, x1.5 at 90, x2.0 at 180
|
||||
|
||||
/*
|
||||
CONS_Printf("anglemul: %f\n", FIXED_TO_FLOAT(anglemul));
|
||||
CONS_Printf("speeddiff: %f\n", FIXED_TO_FLOAT(speeddiff));
|
||||
CONS_Printf("scalediff: %f\n", FIXED_TO_FLOAT(scalediff));
|
||||
*/
|
||||
|
||||
tics1 += FixedMul(speeddiff, FixedMul(anglemul, FRACUNIT + scalediff)) / ticaddfactor;
|
||||
tics2 += FixedMul(-speeddiff, FixedMul(anglemul, FRACUNIT - scalediff)) / ticaddfactor;
|
||||
|
||||
if (tics1 < mintics)
|
||||
{
|
||||
tics1 = mintics;
|
||||
}
|
||||
|
||||
if (tics2 < mintics)
|
||||
{
|
||||
tics2 = mintics;
|
||||
}
|
||||
}
|
||||
|
||||
//CONS_Printf("tics1: %d, tics2: %d\n", tics1, tics2);
|
||||
|
||||
if (mo1valid == true)
|
||||
{
|
||||
mo1->hitlag += tics1;
|
||||
}
|
||||
|
||||
if (mo2valid == true)
|
||||
{
|
||||
mo2->hitlag += tics2;
|
||||
}
|
||||
}
|
||||
|
||||
void K_DoInstashield(player_t *player)
|
||||
{
|
||||
mobj_t *layera;
|
||||
|
|
@ -2755,7 +2832,7 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color)
|
|||
if (!bombflashtimer && P_CheckSight(p->mo, source))
|
||||
{
|
||||
bombflashtimer = TICRATE*2;
|
||||
P_FlashPal(p, 1, 1);
|
||||
P_FlashPal(p, PAL_WHITE, 1);
|
||||
}
|
||||
break; // we can break right now because quakes are global to all split players somehow.
|
||||
}
|
||||
|
|
@ -3150,7 +3227,7 @@ static void K_SpawnAIZDust(player_t *player)
|
|||
if (player->speed <= K_GetKartSpeed(player, false))
|
||||
return;
|
||||
|
||||
travelangle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy);
|
||||
travelangle = K_MomentumAngle(player->mo);
|
||||
//S_StartSound(player->mo, sfx_s3k47);
|
||||
|
||||
{
|
||||
|
|
@ -3194,7 +3271,7 @@ void K_SpawnBoostTrail(player_t *player)
|
|||
if (player->kartstuff[k_drift] != 0)
|
||||
travelangle = player->mo->angle;
|
||||
else
|
||||
travelangle = R_PointToAngle2(0, 0, player->rmomx, player->rmomy);
|
||||
travelangle = K_MomentumAngle(player->mo);
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
|
|
@ -3286,7 +3363,7 @@ void K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent)
|
|||
mo->z, MT_WIPEOUTTRAIL);
|
||||
|
||||
P_SetTarget(&dust->target, mo);
|
||||
dust->angle = R_PointToAngle2(0,0,mo->momx,mo->momy);
|
||||
dust->angle = K_MomentumAngle(mo);
|
||||
dust->destscale = mo->scale;
|
||||
P_SetScale(dust, mo->scale);
|
||||
K_FlipFromObject(dust, mo);
|
||||
|
|
@ -3419,7 +3496,7 @@ void K_DriftDustHandling(mobj_t *spawner)
|
|||
if (P_AproxDistance(spawner->momx, spawner->momy) < 5*spawner->scale)
|
||||
return;
|
||||
|
||||
anglediff = abs((signed)(spawner->angle - R_PointToAngle2(0, 0, spawner->momx, spawner->momy)));
|
||||
anglediff = abs((signed)(spawner->angle - K_MomentumAngle(spawner)));
|
||||
}
|
||||
|
||||
if (anglediff > ANGLE_180)
|
||||
|
|
@ -3721,7 +3798,7 @@ static mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t map
|
|||
|
||||
void K_PuntMine(mobj_t *thismine, mobj_t *punter)
|
||||
{
|
||||
angle_t fa = R_PointToAngle2(0, 0, punter->momx, punter->momy) >> ANGLETOFINESHIFT;
|
||||
angle_t fa = K_MomentumAngle(punter) >> ANGLETOFINESHIFT;
|
||||
fixed_t z = 30*mapobjectscale + punter->momz;
|
||||
fixed_t spd;
|
||||
mobj_t *mine;
|
||||
|
|
@ -3758,6 +3835,9 @@ void K_PuntMine(mobj_t *thismine, mobj_t *punter)
|
|||
if (!mine || P_MobjWasRemoved(mine))
|
||||
return;
|
||||
|
||||
if (mine->threshold > 0 || mine->hitlag > 0)
|
||||
return;
|
||||
|
||||
spd = (82 + ((gamespeed-1) * 14))*mapobjectscale; // Avg Speed is 41 in Normal
|
||||
|
||||
mine->flags |= MF_NOCLIPTHING;
|
||||
|
|
@ -3767,6 +3847,8 @@ void K_PuntMine(mobj_t *thismine, mobj_t *punter)
|
|||
mine->extravalue1 = 0;
|
||||
mine->reactiontime = mine->info->reactiontime;
|
||||
|
||||
K_SetHitLagForObjects(punter, mine, 5);
|
||||
|
||||
mine->momx = punter->momx + FixedMul(FINECOSINE(fa), spd);
|
||||
mine->momy = punter->momy + FixedMul(FINESINE(fa), spd);
|
||||
mine->momz = P_MobjFlip(mine) * z;
|
||||
|
|
@ -5492,7 +5574,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
MT_FASTLINE);
|
||||
|
||||
P_SetTarget(&fast->target, player->mo);
|
||||
fast->angle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy);
|
||||
fast->angle = K_MomentumAngle(player->mo);
|
||||
fast->momx = 3*player->mo->momx/4;
|
||||
fast->momy = 3*player->mo->momy/4;
|
||||
fast->momz = 3*player->mo->momz/4;
|
||||
|
|
@ -6052,18 +6134,12 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
|
|||
{
|
||||
boolean finishlinehack = false;
|
||||
angle_t playerangle = player->mo->angle;
|
||||
angle_t momangle = player->mo->angle;
|
||||
angle_t momangle = K_MomentumAngle(player->mo);
|
||||
angle_t angletowaypoint =
|
||||
R_PointToAngle2(player->mo->x, player->mo->y, waypoint->mobj->x, waypoint->mobj->y);
|
||||
angle_t angledelta = ANGLE_MAX;
|
||||
angle_t momdelta = ANGLE_MAX;
|
||||
|
||||
if (player->mo->momx != 0 || player->mo->momy != 0)
|
||||
{
|
||||
// Defaults to facing angle if you're not moving.
|
||||
momangle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy);
|
||||
}
|
||||
|
||||
angledelta = playerangle - angletowaypoint;
|
||||
if (angledelta > ANGLE_180)
|
||||
{
|
||||
|
|
@ -6561,7 +6637,7 @@ static void K_KartDrift(player_t *player, boolean onground)
|
|||
{
|
||||
if (player->kartstuff[k_driftcharge] < 0 || player->kartstuff[k_driftcharge] >= dsone)
|
||||
{
|
||||
angle_t pushdir = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy);
|
||||
angle_t pushdir = K_MomentumAngle(player->mo);
|
||||
|
||||
S_StartSound(player->mo, sfx_s23c);
|
||||
//K_SpawnDashDustRelease(player);
|
||||
|
|
@ -6943,10 +7019,67 @@ boolean K_PlayerEBrake(player_t *player)
|
|||
&& player->powers[pw_nocontrol] == 0;
|
||||
}
|
||||
|
||||
static void K_KartSpindashDust(mobj_t *parent)
|
||||
{
|
||||
fixed_t rad = FixedDiv(FixedHypot(parent->radius, parent->radius), parent->scale);
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
fixed_t hmomentum = P_RandomRange(6, 12) * parent->scale;
|
||||
fixed_t vmomentum = P_RandomRange(2, 6) * parent->scale;
|
||||
|
||||
angle_t ang = parent->player->drawangle + ANGLE_180;
|
||||
SINT8 flip = 1;
|
||||
|
||||
mobj_t *dust;
|
||||
|
||||
if (i & 1)
|
||||
ang -= ANGLE_45;
|
||||
else
|
||||
ang += ANGLE_45;
|
||||
|
||||
dust = P_SpawnMobjFromMobj(parent,
|
||||
FixedMul(rad, FINECOSINE(ang >> ANGLETOFINESHIFT)),
|
||||
FixedMul(rad, FINESINE(ang >> ANGLETOFINESHIFT)),
|
||||
0, MT_SPINDASHDUST
|
||||
);
|
||||
flip = P_MobjFlip(dust);
|
||||
|
||||
dust->momx = FixedMul(hmomentum, FINECOSINE(ang >> ANGLETOFINESHIFT));
|
||||
dust->momy = FixedMul(hmomentum, FINESINE(ang >> ANGLETOFINESHIFT));
|
||||
dust->momz = vmomentum * flip;
|
||||
}
|
||||
}
|
||||
|
||||
static void K_KartSpindashWind(mobj_t *parent)
|
||||
{
|
||||
mobj_t *wind = P_SpawnMobjFromMobj(parent,
|
||||
P_RandomRange(-36,36) * FRACUNIT,
|
||||
P_RandomRange(-36,36) * FRACUNIT,
|
||||
FixedDiv(parent->height / 2, parent->scale) + (P_RandomRange(-20,20) * FRACUNIT),
|
||||
MT_SPINDASHWIND
|
||||
);
|
||||
|
||||
P_SetTarget(&wind->target, parent);
|
||||
|
||||
if (parent->momx || parent->momy)
|
||||
wind->angle = R_PointToAngle2(0, 0, parent->momx, parent->momy);
|
||||
else
|
||||
wind->angle = parent->player->drawangle;
|
||||
|
||||
wind->momx = 3 * parent->momx / 4;
|
||||
wind->momy = 3 * parent->momy / 4;
|
||||
wind->momz = 3 * parent->momz / 4;
|
||||
|
||||
K_MatchGenericExtraFlags(wind, parent);
|
||||
}
|
||||
|
||||
static void K_KartSpindash(player_t *player)
|
||||
{
|
||||
const tic_t MAXCHARGETIME = K_GetSpindashChargeTime(player);
|
||||
const INT16 MAXCHARGETIME = K_GetSpindashChargeTime(player);
|
||||
ticcmd_t *cmd = &player->cmd;
|
||||
boolean spawnWind = (leveltime % 2 == 0);
|
||||
|
||||
if (player->kartstuff[k_spindash] > 0 && (cmd->buttons & (BT_DRIFT|BT_BRAKE)) != (BT_DRIFT|BT_BRAKE))
|
||||
{
|
||||
|
|
@ -6961,7 +7094,7 @@ static void K_KartSpindash(player_t *player)
|
|||
mobj_t *grease;
|
||||
grease = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_TIREGREASE);
|
||||
P_SetTarget(&grease->target, player->mo);
|
||||
grease->angle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy);
|
||||
grease->angle = K_MomentumAngle(player->mo);
|
||||
grease->extravalue1 = i;
|
||||
}
|
||||
}
|
||||
|
|
@ -6972,6 +7105,17 @@ static void K_KartSpindash(player_t *player)
|
|||
S_StartSound(player->mo, sfx_s23c);
|
||||
}
|
||||
|
||||
|
||||
if ((player->kartstuff[k_spindashboost] > 0) && (spawnWind == true))
|
||||
{
|
||||
K_KartSpindashWind(player->mo);
|
||||
}
|
||||
|
||||
if (player->kartstuff[k_spindashboost] > (TICRATE/2))
|
||||
{
|
||||
K_KartSpindashDust(player->mo);
|
||||
}
|
||||
|
||||
if (K_PlayerEBrake(player) == false)
|
||||
{
|
||||
player->kartstuff[k_spindash] = 0;
|
||||
|
|
@ -6986,26 +7130,36 @@ static void K_KartSpindash(player_t *player)
|
|||
if ((cmd->buttons & (BT_DRIFT|BT_BRAKE)) == (BT_DRIFT|BT_BRAKE))
|
||||
{
|
||||
INT16 chargetime = MAXCHARGETIME - ++player->kartstuff[k_spindash];
|
||||
boolean spawnOldEffect = true;
|
||||
|
||||
if (chargetime <= (MAXCHARGETIME / 2))
|
||||
{
|
||||
K_KartSpindashDust(player->mo);
|
||||
spawnOldEffect = false;
|
||||
}
|
||||
|
||||
if (chargetime <= (MAXCHARGETIME / 4) && spawnWind == true)
|
||||
{
|
||||
K_KartSpindashWind(player->mo);
|
||||
}
|
||||
|
||||
if (chargetime > 0)
|
||||
{
|
||||
UINT16 soundcharge = 0;
|
||||
UINT8 add = 0;
|
||||
|
||||
while ((soundcharge += ++add) < chargetime);
|
||||
|
||||
if (soundcharge == chargetime)
|
||||
{
|
||||
K_SpawnDashDustRelease(player);
|
||||
if (spawnOldEffect == true)
|
||||
K_SpawnDashDustRelease(player);
|
||||
S_StartSound(player->mo, sfx_s3kab);
|
||||
}
|
||||
}
|
||||
else if (chargetime < -TICRATE)
|
||||
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_NORMAL);
|
||||
else
|
||||
{
|
||||
if (player->kartstuff[k_spindash] % 4 == 0)
|
||||
{
|
||||
K_SpawnDashDustRelease(player);
|
||||
K_FlameDashLeftoverSmoke(player->mo);
|
||||
}
|
||||
P_DamageMobj(player->mo, NULL, NULL, 1, DMG_NORMAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7599,7 +7753,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
if (!onground)
|
||||
{
|
||||
P_Thrust(
|
||||
player->mo, R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy),
|
||||
player->mo, K_MomentumAngle(player->mo),
|
||||
FixedMul(player->mo->scale, K_GetKartGameSpeedScalar(gamespeed))
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ void K_KartMoveAnimation(player_t *player);
|
|||
void K_KartPlayerHUDUpdate(player_t *player);
|
||||
void K_KartPlayerThink(player_t *player, ticcmd_t *cmd);
|
||||
void K_KartPlayerAfterThink(player_t *player);
|
||||
angle_t K_MomentumAngle(mobj_t *mo);
|
||||
void K_SetHitLagForObjects(mobj_t *mo1, mobj_t *mo2, INT32 tics);
|
||||
void K_DoInstashield(player_t *player);
|
||||
void K_BattleHitPlayer(player_t *player, player_t *victim, UINT8 points, boolean reducewanted);
|
||||
void K_RemoveBumper(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 amount, boolean force);
|
||||
|
|
@ -78,7 +80,7 @@ void K_StripItems(player_t *player);
|
|||
void K_StripOther(player_t *player);
|
||||
void K_MomentumToFacing(player_t *player);
|
||||
boolean K_ApplyOffroad(player_t *player);
|
||||
tic_t K_GetSpindashChargeTime(player_t *player);
|
||||
INT16 K_GetSpindashChargeTime(player_t *player);
|
||||
fixed_t K_GetSpindashChargeSpeed(player_t *player);
|
||||
fixed_t K_GetKartSpeedFromStat(UINT8 kartspeed);
|
||||
fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower);
|
||||
|
|
|
|||
|
|
@ -387,7 +387,8 @@ static int lib_pAproxDistance(lua_State *L)
|
|||
fixed_t dx = luaL_checkfixed(L, 1);
|
||||
fixed_t dy = luaL_checkfixed(L, 2);
|
||||
//HUDSAFE
|
||||
lua_pushfixed(L, P_AproxDistance(dx, dy));
|
||||
LUA_Deprecated(L, "P_AproxDistance", "FixedHypot");
|
||||
lua_pushfixed(L, FixedHypot(dx, dy));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -536,7 +536,6 @@ static luaL_Reg lib[] = {
|
|||
{"CV_StealthSet", lib_cvStealthSet},
|
||||
{"CV_AddValue", lib_cvAddValue},
|
||||
{"CONS_Printf", lib_consPrintf},
|
||||
{"CV_FindVar", lib_cvFindVar},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -109,10 +109,10 @@ void LUAh_PlayerQuit(player_t *plr, kickreason_t reason); // Hook for player qui
|
|||
boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping,
|
||||
UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms); // Hook for music changes
|
||||
|
||||
boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Allows to write to player cmd before the game does anything with them.
|
||||
boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Allows to write to player cmd before the game does anything with them.
|
||||
|
||||
void LUAh_IntermissionThinker(void); // Hook for Y_Ticker
|
||||
void LUAh_VoteThinker(void); // Hook for Y_VoteTicker
|
||||
void LUAh_VoteThinker(void); // Hook for Y_VoteTicker
|
||||
|
||||
#define LUAh_ShieldSpawn(player) LUAh_PlayerHook(player, hook_ShieldSpawn) // Hook for P_SpawnShieldOrb
|
||||
#define LUAh_ShieldSpecial(player) LUAh_PlayerHook(player, hook_ShieldSpecial) // Hook for shield abilities
|
||||
|
|
@ -128,4 +128,3 @@ boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_
|
|||
#define LUAh_PlayerThink(player) LUAh_PlayerHook(player, hook_PlayerThink) // Hook for P_PlayerThink
|
||||
boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname); // Hook for whether a jingle of the given music should continue playing
|
||||
void LUAh_GameQuit(void); // Hook for game quitting
|
||||
boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Hook for building player's ticcmd struct (Ported from SRB2Kart)
|
||||
|
|
|
|||
|
|
@ -95,7 +95,8 @@ enum mobj_e {
|
|||
mobj_whiteshadow,
|
||||
mobj_sprxoff,
|
||||
mobj_spryoff,
|
||||
mobj_sprzoff
|
||||
mobj_sprzoff,
|
||||
mobj_hitlag
|
||||
};
|
||||
|
||||
static const char *const mobj_opt[] = {
|
||||
|
|
@ -170,6 +171,7 @@ static const char *const mobj_opt[] = {
|
|||
"sprxoff",
|
||||
"spryoff",
|
||||
"sprzoff",
|
||||
"hitlag",
|
||||
NULL};
|
||||
|
||||
#define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field])
|
||||
|
|
@ -430,6 +432,9 @@ static int mobj_get(lua_State *L)
|
|||
case mobj_sprzoff:
|
||||
lua_pushfixed(L, mo->sprzoff);
|
||||
break;
|
||||
case mobj_hitlag:
|
||||
lua_pushinteger(L, mo->hitlag);
|
||||
break;
|
||||
default: // extra custom variables in Lua memory
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
|
||||
I_Assert(lua_istable(L, -1));
|
||||
|
|
@ -787,6 +792,9 @@ static int mobj_set(lua_State *L)
|
|||
case mobj_sprzoff:
|
||||
mo->sprzoff = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case mobj_hitlag:
|
||||
mo->hitlag = luaL_checkinteger(L, 3);
|
||||
break;
|
||||
default:
|
||||
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
|
||||
I_Assert(lua_istable(L, -1));
|
||||
|
|
|
|||
|
|
@ -26,25 +26,35 @@
|
|||
static int lib_iteratePlayers(lua_State *L)
|
||||
{
|
||||
INT32 i = -1;
|
||||
|
||||
if (lua_gettop(L) < 2)
|
||||
{
|
||||
//return luaL_error(L, "Don't call players.iterate() directly, use it as 'for player in players.iterate do <block> end'.");
|
||||
lua_pushcfunction(L, lib_iteratePlayers);
|
||||
return 1;
|
||||
}
|
||||
|
||||
lua_settop(L, 2);
|
||||
lua_remove(L, 1); // state is unused.
|
||||
|
||||
if (!lua_isnil(L, 1))
|
||||
i = (INT32)(*((player_t **)luaL_checkudata(L, 1, META_PLAYER)) - players);
|
||||
for (i++; i < MAXPLAYERS; i++)
|
||||
|
||||
i++;
|
||||
|
||||
if (i == serverplayer)
|
||||
{
|
||||
return LUA_PushServerPlayer(L);
|
||||
}
|
||||
|
||||
for (; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
if (!players[i].mo)
|
||||
continue;
|
||||
LUA_PushUserdata(L, &players[i], META_PLAYER);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -57,10 +67,10 @@ static int lib_getPlayer(lua_State *L)
|
|||
lua_Integer i = luaL_checkinteger(L, 2);
|
||||
if (i < 0 || i >= MAXPLAYERS)
|
||||
return luaL_error(L, "players[] index %d out of range (0 - %d)", i, MAXPLAYERS-1);
|
||||
if (i == serverplayer)
|
||||
return LUA_PushServerPlayer(L);
|
||||
if (!playeringame[i])
|
||||
return 0;
|
||||
if (!players[i].mo)
|
||||
return 0;
|
||||
LUA_PushUserdata(L, &players[i], META_PLAYER);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -121,8 +131,6 @@ static int lib_iterateDisplayplayers(lua_State *L)
|
|||
if (i > splitscreen || !playeringame[displayplayers[i]])
|
||||
return 0; // Stop! There are no more players for us to go through. There will never be a player gap in displayplayers.
|
||||
|
||||
if (!players[displayplayers[i]].mo)
|
||||
continue;
|
||||
LUA_PushUserdata(L, &players[displayplayers[i]], META_PLAYER);
|
||||
lua_pushinteger(L, i); // push this to recall what number we were on for the next function call. I suppose this also means you can retrieve the splitscreen player number with 'for p, n in displayplayers.iterate'!
|
||||
return 2;
|
||||
|
|
@ -143,8 +151,6 @@ static int lib_getDisplayplayers(lua_State *L)
|
|||
return 0;
|
||||
if (!playeringame[displayplayers[i]])
|
||||
return 0;
|
||||
if (!players[displayplayers[i]].mo)
|
||||
return 0;
|
||||
LUA_PushUserdata(L, &players[displayplayers[i]], META_PLAYER);
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -182,17 +188,8 @@ static int player_get(lua_State *L)
|
|||
lua_pushboolean(L, true);
|
||||
else if (fastcmp(field,"name"))
|
||||
lua_pushstring(L, player_names[plr-players]);
|
||||
else if (fastcmp(field,"realmo"))
|
||||
LUA_PushUserdata(L, plr->mo, META_MOBJ);
|
||||
// Kept for backward-compatibility
|
||||
// Should be fixed to work like "realmo" later
|
||||
else if (fastcmp(field,"mo"))
|
||||
{
|
||||
if (plr->spectator)
|
||||
lua_pushnil(L);
|
||||
else
|
||||
LUA_PushUserdata(L, plr->mo, META_MOBJ);
|
||||
}
|
||||
LUA_PushUserdata(L, plr->mo, META_MOBJ);
|
||||
else if (fastcmp(field,"cmd"))
|
||||
LUA_PushUserdata(L, &plr->cmd, META_TICCMD);
|
||||
else if (fastcmp(field,"playerstate"))
|
||||
|
|
@ -449,7 +446,7 @@ static int player_set(lua_State *L)
|
|||
if (hook_cmd_running)
|
||||
return luaL_error(L, "Do not alter player_t in BuildCMD code!");
|
||||
|
||||
if (fastcmp(field,"mo") || fastcmp(field,"realmo")) {
|
||||
if (fastcmp(field,"mo")) {
|
||||
mobj_t *newmo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
|
||||
plr->mo->player = NULL; // remove player pointer from old mobj
|
||||
(newmo->player = plr)->mo = newmo; // set player pointer for new mobj, and set new mobj as the player's mobj
|
||||
|
|
|
|||
|
|
@ -731,6 +731,14 @@ void LUA_PushUserdata(lua_State *L, void *data, const char *meta)
|
|||
lua_remove(L, -2); // remove LREG_VALID
|
||||
}
|
||||
|
||||
int LUA_PushServerPlayer(lua_State *L)
|
||||
{
|
||||
if ((!multiplayer || !(netgame || demo.playback)) && !playeringame[serverplayer])
|
||||
return 0;
|
||||
LUA_PushUserdata(L, &players[serverplayer], META_PLAYER);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// When userdata is freed, use this function to remove it from Lua.
|
||||
void LUA_InvalidateUserdata(void *data)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ void LUA_DumpFile(const char *filename);
|
|||
fixed_t LUA_EvalMath(const char *word);
|
||||
void LUA_PushLightUserdata(lua_State *L, void *data, const char *meta);
|
||||
void LUA_PushUserdata(lua_State *L, void *data, const char *meta);
|
||||
int LUA_PushServerPlayer(lua_State *L);
|
||||
void LUA_InvalidateUserdata(void *data);
|
||||
void LUA_InvalidateLevel(void);
|
||||
void LUA_InvalidateMapthings(void);
|
||||
|
|
|
|||
|
|
@ -18,8 +18,10 @@
|
|||
#define HAVE_SQRTF
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "m_fixed.h"
|
||||
#include "tables.h" // ANGLETOFINESHIFT
|
||||
|
||||
#ifdef __USE_C_FIXEDMUL__
|
||||
|
||||
|
|
@ -105,20 +107,34 @@ fixed_t FixedSqrt(fixed_t x)
|
|||
|
||||
fixed_t FixedHypot(fixed_t x, fixed_t y)
|
||||
{
|
||||
fixed_t ax, yx, yx2, yx1;
|
||||
if (abs(y) > abs(x)) // |y|>|x|
|
||||
// Moved the code from R_PointToDist2 to here,
|
||||
// since R_PointToDist2 did the same thing,
|
||||
// except less prone to overflowing.
|
||||
|
||||
angle_t angle;
|
||||
fixed_t dist;
|
||||
|
||||
x = abs(x);
|
||||
y = abs(y);
|
||||
|
||||
if (y > x)
|
||||
{
|
||||
ax = abs(y); // |y| => ax
|
||||
yx = FixedDiv(x, y); // (x/y)
|
||||
fixed_t temp;
|
||||
|
||||
temp = x;
|
||||
x = y;
|
||||
y = temp;
|
||||
}
|
||||
else // |x|>|y|
|
||||
{
|
||||
ax = abs(x); // |x| => ax
|
||||
yx = FixedDiv(y, x); // (x/y)
|
||||
}
|
||||
yx2 = FixedMul(yx, yx); // (x/y)^2
|
||||
yx1 = FixedSqrt(1 * FRACUNIT + yx2); // (1 + (x/y)^2)^1/2
|
||||
return FixedMul(ax, yx1); // |x|*((1 + (x/y)^2)^1/2)
|
||||
|
||||
if (!y)
|
||||
return x;
|
||||
|
||||
angle = (tantoangle[FixedDiv(y, x)>>DBITS] + ANGLE_90) >> ANGLETOFINESHIFT;
|
||||
|
||||
// use as cosine
|
||||
dist = FixedDiv(x, FINESINE(angle));
|
||||
|
||||
return dist;
|
||||
}
|
||||
|
||||
vector2_t *FV2_Load(vector2_t *vec, fixed_t x, fixed_t y)
|
||||
|
|
|
|||
46
src/m_swap.h
46
src/m_swap.h
|
|
@ -2,7 +2,7 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1993-1996 by id Software, Inc.
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2020 by Sonic Team Junior.
|
||||
// Copyright (C) 1999-2018 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
|
|
@ -14,30 +14,34 @@
|
|||
#ifndef __M_SWAP__
|
||||
#define __M_SWAP__
|
||||
|
||||
// Endianess handling.
|
||||
// WAD files are stored little endian.
|
||||
#include "endian.h"
|
||||
|
||||
// Little to big endian
|
||||
#define SWAP_SHORT(x) ((INT16)(\
|
||||
(((UINT16)(x) & (UINT16)0x00ffU) << 8) \
|
||||
| \
|
||||
(((UINT16)(x) & (UINT16)0xff00U) >> 8))) \
|
||||
|
||||
#define SWAP_LONG(x) ((INT32)(\
|
||||
(((UINT32)(x) & (UINT32)0x000000ffUL) << 24) \
|
||||
| \
|
||||
(((UINT32)(x) & (UINT32)0x0000ff00UL) << 8) \
|
||||
| \
|
||||
(((UINT32)(x) & (UINT32)0x00ff0000UL) >> 8) \
|
||||
| \
|
||||
(((UINT32)(x) & (UINT32)0xff000000UL) >> 24)))
|
||||
|
||||
// Endianess handling.
|
||||
// WAD files are stored little endian.
|
||||
#ifdef SRB2_BIG_ENDIAN
|
||||
|
||||
#define SHORT(x) ((INT16)(\
|
||||
(((UINT16)(x) & (UINT16)0x00ffU) << 8) \
|
||||
| \
|
||||
(((UINT16)(x) & (UINT16)0xff00U) >> 8))) \
|
||||
|
||||
#define LONG(x) ((INT32)(\
|
||||
(((UINT32)(x) & (UINT32)0x000000ffUL) << 24) \
|
||||
| \
|
||||
(((UINT32)(x) & (UINT32)0x0000ff00UL) << 8) \
|
||||
| \
|
||||
(((UINT32)(x) & (UINT32)0x00ff0000UL) >> 8) \
|
||||
| \
|
||||
(((UINT32)(x) & (UINT32)0xff000000UL) >> 24)))
|
||||
|
||||
#define SHORT SWAP_SHORT
|
||||
#define LONG SWAP_LONG
|
||||
#define MSBF_SHORT(x) ((INT16)(x))
|
||||
#define MSBF_LONG(x) ((INT32)(x))
|
||||
#else
|
||||
#define SHORT(x) ((INT16)(x))
|
||||
#define LONG(x) ((INT32)(x))
|
||||
#define SHORT(x) ((INT16)(x))
|
||||
#define LONG(x) ((INT32)(x))
|
||||
#define MSBF_SHORT SWAP_SHORT
|
||||
#define MSBF_LONG SWAP_LONG
|
||||
#endif
|
||||
|
||||
// Big to little endian
|
||||
|
|
|
|||
|
|
@ -4457,6 +4457,9 @@ void A_GrenadeRing(mobj_t *actor)
|
|||
if (actor->flags2 & MF2_DEBRIS)
|
||||
return;
|
||||
|
||||
if (actor->hitlag > 0)
|
||||
return;
|
||||
|
||||
if (actor->state == &states[S_SSMINE_DEPLOY8])
|
||||
explodedist = (3*explodedist)/2;
|
||||
|
||||
|
|
@ -4524,6 +4527,9 @@ void A_SSMineExplode(mobj_t *actor)
|
|||
if (actor->flags2 & MF2_DEBRIS)
|
||||
return;
|
||||
|
||||
if (actor->hitlag > 0)
|
||||
return;
|
||||
|
||||
type = (mobjtype_t)locvar1;
|
||||
|
||||
// Use blockmap to check for nearby shootables
|
||||
|
|
@ -8757,7 +8763,7 @@ void A_JawzChase(mobj_t *actor)
|
|||
|
||||
if (!actor->tracer)
|
||||
{
|
||||
actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy);
|
||||
actor->angle = K_MomentumAngle(actor);
|
||||
}
|
||||
|
||||
P_Thrust(actor, actor->angle, thrustamount);
|
||||
|
|
@ -8887,7 +8893,7 @@ static void SpawnSPBAIZDust(mobj_t *mo, INT32 dir)
|
|||
if (mo->eflags & MFE_VERTICALFLIP)
|
||||
sz = mo->ceilingz;
|
||||
|
||||
travelangle = R_PointToAngle2(0, 0, mo->momx, mo->momy);
|
||||
travelangle = K_MomentumAngle(mo);
|
||||
if (leveltime & 1 && abs(mo->z - sz) < FRACUNIT*64)
|
||||
{
|
||||
newx = mo->x + P_ReturnThrustX(mo, travelangle - (dir*ANGLE_45), FixedMul(24*FRACUNIT, mo->scale));
|
||||
|
|
@ -8917,7 +8923,7 @@ static void SpawnSPBSpeedLines(mobj_t *actor)
|
|||
MT_FASTLINE);
|
||||
|
||||
P_SetTarget(&fast->target, actor);
|
||||
fast->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy);
|
||||
fast->angle = K_MomentumAngle(actor);
|
||||
fast->color = SKINCOLOR_RED;
|
||||
fast->colorized = true;
|
||||
K_MatchGenericExtraFlags(fast, actor);
|
||||
|
|
|
|||
|
|
@ -452,6 +452,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
if (special->threshold > 0)
|
||||
return;
|
||||
|
||||
if (toucher->hitlag > 0)
|
||||
return;
|
||||
|
||||
player->powers[pw_emeralds] |= special->extravalue1;
|
||||
K_CheckEmeralds(player);
|
||||
break;
|
||||
|
|
@ -1101,6 +1104,8 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
if (LUAh_MobjDeath(target, inflictor, source, damagetype) || P_MobjWasRemoved(target))
|
||||
return;
|
||||
|
||||
//K_SetHitLagForObjects(target, inflictor, 15);
|
||||
|
||||
// SRB2kart
|
||||
// I wish I knew a better way to do this
|
||||
if (target->target && target->target->player && target->target->player->mo)
|
||||
|
|
@ -1672,8 +1677,10 @@ static boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *sou
|
|||
return true;
|
||||
}
|
||||
|
||||
static boolean P_KillPlayer(player_t *player, UINT8 type)
|
||||
static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 type)
|
||||
{
|
||||
(void)source;
|
||||
|
||||
if (player->exiting)
|
||||
{
|
||||
player->mo->destscale = 1;
|
||||
|
|
@ -1694,6 +1701,7 @@ static boolean P_KillPlayer(player_t *player, UINT8 type)
|
|||
}
|
||||
|
||||
K_DropEmeraldsFromPlayer(player, player->powers[pw_emeralds]);
|
||||
K_SetHitLagForObjects(player->mo, inflictor, 15);
|
||||
|
||||
player->pflags &= ~PF_SLIDING;
|
||||
player->powers[pw_carry] = CR_NONE;
|
||||
|
|
@ -1783,6 +1791,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
player_t *player;
|
||||
boolean force = false;
|
||||
|
||||
INT32 laglength = 10;
|
||||
|
||||
if (objectplacing)
|
||||
return false;
|
||||
|
||||
|
|
@ -1790,13 +1800,16 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
return false;
|
||||
|
||||
// Spectator handling
|
||||
if (multiplayer)
|
||||
{
|
||||
if (damagetype != DMG_SPECTATOR && target->player && target->player->spectator)
|
||||
return false;
|
||||
if (damagetype != DMG_SPECTATOR && target->player && target->player->spectator)
|
||||
return false;
|
||||
|
||||
if (source && source->player && source->player->spectator)
|
||||
return false;
|
||||
if (source && source->player && source->player->spectator)
|
||||
return false;
|
||||
|
||||
if (((damagetype & DMG_TYPEMASK) == DMG_STING)
|
||||
|| ((inflictor && !P_MobjWasRemoved(inflictor)) && inflictor->type == MT_BANANA && inflictor->health <= 1))
|
||||
{
|
||||
laglength = 5;
|
||||
}
|
||||
|
||||
// Everything above here can't be forced.
|
||||
|
|
@ -1860,7 +1873,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
// Instant-Death
|
||||
if ((damagetype & DMG_DEATHMASK))
|
||||
{
|
||||
if (!P_KillPlayer(player, damagetype))
|
||||
if (!P_KillPlayer(player, inflictor, source, damagetype))
|
||||
return false;
|
||||
}
|
||||
else if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype))
|
||||
|
|
@ -1994,6 +2007,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
}
|
||||
|
||||
player->kartstuff[k_instashield] = 15;
|
||||
K_SetHitLagForObjects(target, inflictor, laglength);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -2015,12 +2029,16 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
if (source && source->player && target)
|
||||
G_GhostAddHit((INT32) (source->player - players), target);
|
||||
|
||||
K_SetHitLagForObjects(target, inflictor, laglength);
|
||||
|
||||
if (target->health <= 0)
|
||||
{
|
||||
P_KillMobj(target, inflictor, source, damagetype);
|
||||
return true;
|
||||
}
|
||||
|
||||
//K_SetHitLagForObjects(target, inflictor, laglength);
|
||||
|
||||
if (player)
|
||||
P_ResetPlayer(target->player);
|
||||
else
|
||||
|
|
|
|||
20
src/p_map.c
20
src/p_map.c
|
|
@ -357,7 +357,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|
|||
mobj_t *grease;
|
||||
grease = P_SpawnMobj(object->x, object->y, object->z, MT_TIREGREASE);
|
||||
P_SetTarget(&grease->target, object);
|
||||
grease->angle = R_PointToAngle2(0, 0, object->momx, object->momy);
|
||||
grease->angle = K_MomentumAngle(object);
|
||||
grease->extravalue1 = i;
|
||||
}
|
||||
}
|
||||
|
|
@ -1217,19 +1217,31 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
if (!G_GametypeHasTeams() || tmthing->player->ctfteam != thing->player->ctfteam)
|
||||
{
|
||||
if (tmthing->scale > thing->scale + (mapobjectscale/8)) // SRB2kart - Handle squishes first!
|
||||
{
|
||||
P_DamageMobj(thing, tmthing, tmthing, 1, DMG_SQUISH);
|
||||
}
|
||||
else if (thing->scale > tmthing->scale + (mapobjectscale/8))
|
||||
{
|
||||
P_DamageMobj(tmthing, thing, thing, 1, DMG_SQUISH);
|
||||
}
|
||||
else if (tmthing->player->kartstuff[k_invincibilitytimer] && !thing->player->kartstuff[k_invincibilitytimer]) // SRB2kart - Then invincibility!
|
||||
{
|
||||
P_DamageMobj(thing, tmthing, tmthing, 1, DMG_WIPEOUT);
|
||||
}
|
||||
else if (thing->player->kartstuff[k_invincibilitytimer] && !tmthing->player->kartstuff[k_invincibilitytimer])
|
||||
{
|
||||
P_DamageMobj(tmthing, thing, thing, 1, DMG_WIPEOUT);
|
||||
}
|
||||
else if ((tmthing->player->kartstuff[k_flamedash] && tmthing->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD)
|
||||
&& !(thing->player->kartstuff[k_flamedash] && thing->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD)) // SRB2kart - Then flame shield!
|
||||
{
|
||||
P_DamageMobj(thing, tmthing, tmthing, 1, DMG_WIPEOUT);
|
||||
}
|
||||
else if ((thing->player->kartstuff[k_flamedash] && thing->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD)
|
||||
&& !(tmthing->player->kartstuff[k_flamedash] && tmthing->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD))
|
||||
{
|
||||
P_DamageMobj(tmthing, thing, thing, 1, DMG_WIPEOUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2468,6 +2480,12 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
|
|||
if (radius < mapobjectscale)
|
||||
radius = mapobjectscale;
|
||||
|
||||
if (thing->hitlag > 0)
|
||||
{
|
||||
// Do not move during hitlag
|
||||
return false;
|
||||
}
|
||||
|
||||
do {
|
||||
if (thing->flags & MF_NOCLIP) {
|
||||
tryx = x;
|
||||
|
|
|
|||
|
|
@ -24,19 +24,6 @@
|
|||
#include "p_slopes.h"
|
||||
#include "z_zone.h"
|
||||
|
||||
//
|
||||
// P_AproxDistance
|
||||
// Gives an estimation of distance (not exact)
|
||||
//
|
||||
fixed_t P_AproxDistance(fixed_t dx, fixed_t dy)
|
||||
{
|
||||
dx = abs(dx);
|
||||
dy = abs(dy);
|
||||
if (dx < dy)
|
||||
return dx + dy - (dx>>1);
|
||||
return dx + dy - (dy>>1);
|
||||
}
|
||||
|
||||
//
|
||||
// P_ClosestPointOnLine
|
||||
// Finds the closest point on a given line to the supplied point
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ typedef boolean (*traverser_t)(intercept_t *in);
|
|||
boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2,
|
||||
INT32 pflags, traverser_t ptrav);
|
||||
|
||||
FUNCMATH fixed_t P_AproxDistance(fixed_t dx, fixed_t dy);
|
||||
#define P_AproxDistance(dx, dy) FixedHypot(dx, dy)
|
||||
void P_ClosestPointOnLine(fixed_t x, fixed_t y, line_t *line, vertex_t *result);
|
||||
void P_ClosestPointOnLine3D(const vector3_t *p, const vector3_t *line, vector3_t *result);
|
||||
INT32 P_PointOnLineSide(fixed_t x, fixed_t y, line_t *line);
|
||||
|
|
|
|||
48
src/p_mobj.c
48
src/p_mobj.c
|
|
@ -1616,8 +1616,10 @@ void P_XYMovement(mobj_t *mo)
|
|||
relation = transferslope->xydirection - R_PointToAngle2(0, 0, mo->momx, mo->momy);
|
||||
else // Give it for free, I guess.
|
||||
relation = ANGLE_90;
|
||||
|
||||
transfermomz = FixedMul(transfermomz,
|
||||
abs(FINESINE((relation >> ANGLETOFINESHIFT) & FINEMASK)));
|
||||
|
||||
if (P_MobjFlip(mo)*(transfermomz - mo->momz) > 2*FRACUNIT) // Do the actual launch!
|
||||
{
|
||||
mo->momz = transfermomz;
|
||||
|
|
@ -1692,7 +1694,7 @@ void P_XYMovement(mobj_t *mo)
|
|||
|
||||
if (oldslope != mo->standingslope) { // First, compare different slopes
|
||||
angle_t oldangle, newangle;
|
||||
angle_t moveangle = R_PointToAngle2(0, 0, mo->momx, mo->momy);
|
||||
angle_t moveangle = K_MomentumAngle(mo);
|
||||
|
||||
oldangle = FixedMul((signed)oldslope->zangle, FINECOSINE((moveangle - oldslope->xydirection) >> ANGLETOFINESHIFT));
|
||||
|
||||
|
|
@ -1724,7 +1726,7 @@ void P_XYMovement(mobj_t *mo)
|
|||
P_SlopeLaunch(mo);
|
||||
}
|
||||
} else if (moved && mo->standingslope && predictedz) {
|
||||
angle_t moveangle = R_PointToAngle2(0, 0, mo->momx, mo->momy);
|
||||
angle_t moveangle = K_MomentumAngle(mo);
|
||||
angle_t newangle = FixedMul((signed)mo->standingslope->zangle, FINECOSINE((moveangle - mo->standingslope->xydirection) >> ANGLETOFINESHIFT));
|
||||
|
||||
/*CONS_Printf("flat to angle %f - predicted z of %f\n",
|
||||
|
|
@ -4882,8 +4884,6 @@ static boolean P_ParticleGenSceneryThink(mobj_t *mobj)
|
|||
|
||||
mobj->angle += mobj->movedir;
|
||||
}
|
||||
|
||||
mobj->angle += (angle_t)mobj->movecount;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -5624,6 +5624,9 @@ static void P_MobjSceneryThink(mobj_t *mobj)
|
|||
if (mobj->tics > 0)
|
||||
mobj->drawflags ^= MFD_DONTDRAW;
|
||||
break;
|
||||
case MT_SPINDASHWIND:
|
||||
mobj->drawflags ^= MFD_DONTDRAW;
|
||||
break;
|
||||
case MT_VWREF:
|
||||
case MT_VWREB:
|
||||
{
|
||||
|
|
@ -6140,7 +6143,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
frictionsafety = FRACUNIT;
|
||||
}
|
||||
|
||||
mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy);
|
||||
mobj->angle = K_MomentumAngle(mobj);
|
||||
if (mobj->health <= 5)
|
||||
{
|
||||
INT32 i;
|
||||
|
|
@ -6245,7 +6248,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
thrustamount = beatfriction + FixedDiv(mobj->movefactor - currentspeed, frictionsafety);
|
||||
}
|
||||
|
||||
mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy);
|
||||
mobj->angle = K_MomentumAngle(mobj);
|
||||
P_Thrust(mobj, mobj->angle, thrustamount);
|
||||
|
||||
if (P_MobjTouchingSectorSpecial(mobj, 3, 1, true))
|
||||
|
|
@ -6412,7 +6415,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
|
||||
//mobj->angle = mobj->target->angle;
|
||||
{
|
||||
angle_t angle = R_PointToAngle2(0, 0, mobj->target->momx, mobj->target->momy);
|
||||
angle_t angle = K_MomentumAngle(mobj->target);
|
||||
fixed_t nudge;
|
||||
|
||||
mobj->angle = angle;
|
||||
|
|
@ -6680,7 +6683,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
|
||||
{
|
||||
const angle_t off = FixedAngle(40*FRACUNIT);
|
||||
angle_t ang = mobj->target->angle;
|
||||
angle_t ang = K_MomentumAngle(mobj->target);
|
||||
fixed_t z;
|
||||
UINT8 trans = (mobj->target->player->kartstuff[k_tiregrease] * (NUMTRANSMAPS+1)) / greasetics;
|
||||
|
||||
|
|
@ -6693,9 +6696,6 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
if (mobj->eflags & MFE_VERTICALFLIP)
|
||||
z += mobj->target->height;
|
||||
|
||||
if (mobj->target->momx || mobj->target->momy)
|
||||
ang = R_PointToAngle2(0, 0, mobj->target->momx, mobj->target->momy);
|
||||
|
||||
if (mobj->extravalue1)
|
||||
ang = (signed)(ang - off);
|
||||
else
|
||||
|
|
@ -6990,10 +6990,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
}
|
||||
|
||||
P_TeleportMove(mobj, destx, desty, mobj->target->z);
|
||||
if (mobj->target->momx || mobj->target->momy)
|
||||
mobj->angle = R_PointToAngle2(0, 0, mobj->target->momx, mobj->target->momy);
|
||||
else
|
||||
mobj->angle = mobj->target->angle;
|
||||
mobj->angle = K_MomentumAngle(mobj->target);
|
||||
|
||||
if (underlayst != S_NULL)
|
||||
{
|
||||
|
|
@ -7870,7 +7867,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
mobj->momx = (23*mobj->momx)/24;
|
||||
mobj->momy = (23*mobj->momy)/24;
|
||||
|
||||
mobj->angle = R_PointToAngle2(0,0,mobj->momx,mobj->momy);
|
||||
mobj->angle = K_MomentumAngle(mobj);
|
||||
|
||||
if ((mobj->z - mobj->floorz) < (24*mobj->scale) && (leveltime % 3 != 0))
|
||||
{
|
||||
|
|
@ -8424,6 +8421,13 @@ void P_MobjThinker(mobj_t *mobj)
|
|||
if (mobj->hprev && P_MobjWasRemoved(mobj->hprev))
|
||||
P_SetTarget(&mobj->hprev, NULL);
|
||||
|
||||
// Don't run any thinker code while in hitlag
|
||||
if (mobj->hitlag > 0)
|
||||
{
|
||||
mobj->hitlag--;
|
||||
return;
|
||||
}
|
||||
|
||||
mobj->eflags &= ~(MFE_PUSHED|MFE_SPRUNG|MFE_JUSTBOUNCEDWALL);
|
||||
|
||||
tmfloorthing = tmhitthing = NULL;
|
||||
|
|
@ -9027,6 +9031,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
|||
|
||||
mobj->colorized = false;
|
||||
|
||||
mobj->hitlag = 0;
|
||||
|
||||
// Set shadowscale here, before spawn hook so that Lua can change it
|
||||
P_DefaultMobjShadowScale(mobj);
|
||||
|
||||
|
|
@ -11617,8 +11623,11 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
|
|||
|
||||
static void P_SetAmbush(mobj_t *mobj)
|
||||
{
|
||||
if (mobj->type == MT_YELLOWDIAG || mobj->type == MT_REDDIAG || mobj->type == MT_BLUEDIAG)
|
||||
mobj->angle += ANGLE_22h;
|
||||
if (mobj->flags & MF_SPRING)
|
||||
{
|
||||
// gravity toggle
|
||||
mobj->flags ^= MF_NOGRAVITY;
|
||||
}
|
||||
|
||||
if (mobj->flags & MF_NIGHTSITEM)
|
||||
{
|
||||
|
|
@ -11647,9 +11656,6 @@ static void P_SetAmbush(mobj_t *mobj)
|
|||
|
||||
static void P_SetObjectSpecial(mobj_t *mobj)
|
||||
{
|
||||
if (mobj->type == MT_YELLOWDIAG || mobj->type == MT_REDDIAG || mobj->type == MT_BLUEDIAG)
|
||||
mobj->flags |= MF_NOGRAVITY;
|
||||
|
||||
if ((mobj->flags & MF_MONITOR) && mobj->info->speed != 0)
|
||||
{
|
||||
// flag for strong/weak random boxes
|
||||
|
|
|
|||
|
|
@ -422,6 +422,8 @@ typedef struct mobj_s
|
|||
|
||||
fixed_t sprxoff, spryoff, sprzoff; // Sprite offsets in real space, does NOT affect position or collision
|
||||
|
||||
INT32 hitlag; // Sal-style hit lag, straight from Captain Fetch's jowls
|
||||
|
||||
// WARNING: New fields must be added separately to savegame and Lua.
|
||||
} mobj_t;
|
||||
|
||||
|
|
|
|||
|
|
@ -876,6 +876,10 @@ static void Polyobj_carryThings(polyobj_t *po, fixed_t dx, fixed_t dy)
|
|||
|
||||
for (; mo; mo = mo->bnext)
|
||||
{
|
||||
// lastlook is used by the SPB to determine targets, do not let it affect it
|
||||
if (mo->type == MT_SPB)
|
||||
continue;
|
||||
|
||||
if (mo->lastlook == pomovecount)
|
||||
continue;
|
||||
|
||||
|
|
@ -1106,6 +1110,10 @@ static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta,
|
|||
|
||||
for (; mo; mo = mo->bnext)
|
||||
{
|
||||
// lastlook is used by the SPB to determine targets, do not let it affect it
|
||||
if (mo->type == MT_SPB)
|
||||
continue;
|
||||
|
||||
if (mo->lastlook == pomovecount)
|
||||
continue;
|
||||
|
||||
|
|
|
|||
|
|
@ -1379,9 +1379,10 @@ typedef enum
|
|||
MD2_ROLLANGLE = 1<<14,
|
||||
MD2_SHADOWSCALE = 1<<15,
|
||||
MD2_DRAWFLAGS = 1<<16,
|
||||
MD2_WAYPOINTCAP = 1<<17,
|
||||
MD2_KITEMCAP = 1<<18,
|
||||
MD2_ITNEXT = 1<<19,
|
||||
MD2_HITLAG = 1<<17,
|
||||
MD2_WAYPOINTCAP = 1<<18,
|
||||
MD2_KITEMCAP = 1<<19,
|
||||
MD2_ITNEXT = 1<<20,
|
||||
} mobj_diff2_t;
|
||||
|
||||
typedef enum
|
||||
|
|
@ -1596,6 +1597,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
|
|||
diff2 |= MD2_SHADOWSCALE;
|
||||
if (mobj->drawflags)
|
||||
diff2 |= MD2_DRAWFLAGS;
|
||||
if (mobj->hitlag)
|
||||
diff2 |= MD2_HITLAG;
|
||||
if (mobj == waypointcap)
|
||||
diff2 |= MD2_WAYPOINTCAP;
|
||||
if (mobj == kitemcap)
|
||||
|
|
@ -1760,6 +1763,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
|
|||
|
||||
WRITEUINT16(save_p, df);
|
||||
}
|
||||
if (diff2 & MD2_HITLAG)
|
||||
WRITEINT32(save_p, mobj->hitlag);
|
||||
|
||||
WRITEUINT32(save_p, mobj->mobjnum);
|
||||
}
|
||||
|
|
@ -2824,6 +2829,8 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
|
|||
}
|
||||
if (diff2 & MD2_DRAWFLAGS)
|
||||
mobj->drawflags = READUINT16(save_p);
|
||||
if (diff2 & MD2_HITLAG)
|
||||
mobj->hitlag = READINT32(save_p);
|
||||
|
||||
if (diff & MD_REDFLAG)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -4602,8 +4602,7 @@ DoneSection2:
|
|||
{
|
||||
const fixed_t hscale = mapobjectscale + (mapobjectscale - player->mo->scale);
|
||||
const fixed_t minspeed = 24*hscale;
|
||||
angle_t pushangle = FixedHypot(player->mo->momx, player->mo->momy) ? R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy) : player->mo->angle;
|
||||
// if we have no speed for SOME REASON, use the player's angle, otherwise we'd be forcefully thrusted to what I can only assume is angle 0
|
||||
angle_t pushangle = K_MomentumAngle(player->mo);
|
||||
|
||||
if (player->mo->eflags & MFE_SPRUNG)
|
||||
break;
|
||||
|
|
@ -4625,8 +4624,7 @@ DoneSection2:
|
|||
const fixed_t hscale = mapobjectscale + (mapobjectscale - player->mo->scale);
|
||||
const fixed_t minspeed = 24*hscale;
|
||||
const fixed_t maxspeed = 28*hscale;
|
||||
angle_t pushangle = FixedHypot(player->mo->momx, player->mo->momy) ? R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy) : player->mo->angle;
|
||||
// if we have no speed for SOME REASON, use the player's angle, otherwise we'd be forcefully thrusted to what I can only assume is angle 0
|
||||
angle_t pushangle = K_MomentumAngle(player->mo);
|
||||
|
||||
if (player->mo->eflags & MFE_SPRUNG)
|
||||
break;
|
||||
|
|
@ -4673,7 +4671,7 @@ DoneSection2:
|
|||
}
|
||||
|
||||
lineangle = K_ReflectAngle(
|
||||
R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy), lineangle,
|
||||
K_MomentumAngle(player->mo), lineangle,
|
||||
playerspeed, linespeed
|
||||
);
|
||||
|
||||
|
|
|
|||
10
src/p_user.c
10
src/p_user.c
|
|
@ -2265,7 +2265,7 @@ void P_MovePlayer(player_t *player)
|
|||
|
||||
if (trailScale > 0)
|
||||
{
|
||||
const angle_t forwardangle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy);
|
||||
const angle_t forwardangle = K_MomentumAngle(player->mo);
|
||||
const fixed_t playerVisualRadius = player->mo->radius + 8*FRACUNIT;
|
||||
const size_t numFrames = S_WATERTRAIL8 - S_WATERTRAIL1;
|
||||
const statenum_t curOverlayFrame = S_WATERTRAIL1 + (leveltime % numFrames);
|
||||
|
|
@ -4065,7 +4065,7 @@ static void P_HandleFollower(player_t *player)
|
|||
player->follower->drawflags |= MFD_DONTDRAW;
|
||||
|
||||
if (player->speed && (player->follower->momx || player->follower->momy))
|
||||
player->follower->angle = R_PointToAngle2(0, 0, player->follower->momx, player->follower->momy);
|
||||
player->follower->angle = K_MomentumAngle(player->follower);
|
||||
// if we're moving let's make the angle the direction we're moving towards. This is to avoid drifting / reverse looking awkward.
|
||||
// Make sure the follower itself is also moving however, otherwise we'll be facing angle 0
|
||||
|
||||
|
|
@ -4211,6 +4211,11 @@ void P_PlayerThink(player_t *player)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (player->mo->hitlag > 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (player->awayviewmobj && P_MobjWasRemoved(player->awayviewmobj))
|
||||
{
|
||||
P_SetTarget(&player->awayviewmobj, NULL); // remove awayviewmobj asap if invalid
|
||||
|
|
@ -4297,6 +4302,7 @@ void P_PlayerThink(player_t *player)
|
|||
|
||||
if (player->playerstate == PST_DEAD)
|
||||
{
|
||||
LUAh_PlayerThink(player);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
24
src/r_main.c
24
src/r_main.c
|
|
@ -368,29 +368,7 @@ angle_t R_PointToAngle2(fixed_t pviewx, fixed_t pviewy, fixed_t x, fixed_t y)
|
|||
|
||||
fixed_t R_PointToDist2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1)
|
||||
{
|
||||
angle_t angle;
|
||||
fixed_t dx, dy, dist;
|
||||
|
||||
dx = abs(px1 - px2);
|
||||
dy = abs(py1 - py2);
|
||||
|
||||
if (dy > dx)
|
||||
{
|
||||
fixed_t temp;
|
||||
|
||||
temp = dx;
|
||||
dx = dy;
|
||||
dy = temp;
|
||||
}
|
||||
if (!dy)
|
||||
return dx;
|
||||
|
||||
angle = (tantoangle[FixedDiv(dy, dx)>>DBITS] + ANGLE_90) >> ANGLETOFINESHIFT;
|
||||
|
||||
// use as cosine
|
||||
dist = FixedDiv(dx, FINESINE(angle));
|
||||
|
||||
return dist;
|
||||
return FixedHypot(px1 - px2, py1 - py2);
|
||||
}
|
||||
|
||||
// Little extra utility. Works in the same way as R_PointToAngle2
|
||||
|
|
|
|||
|
|
@ -1074,14 +1074,6 @@ static void R_SplitSprite(vissprite_t *sprite)
|
|||
sprite->sz = cutfrac;
|
||||
newsprite->szt = (INT16)(sprite->sz - 1);
|
||||
|
||||
if (testheight < sprite->pzt && testheight > sprite->pz)
|
||||
sprite->pz = newsprite->pzt = testheight;
|
||||
else
|
||||
{
|
||||
newsprite->pz = newsprite->gz;
|
||||
newsprite->pzt = newsprite->gzt;
|
||||
}
|
||||
|
||||
newsprite->szt -= 8;
|
||||
|
||||
newsprite->cut |= SC_TOP;
|
||||
|
|
@ -1238,6 +1230,32 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope)
|
|||
return groundz;
|
||||
}
|
||||
|
||||
static void R_SetSpritePlaneHeights(vissprite_t *vis)
|
||||
{
|
||||
ffloor_t *rover;
|
||||
|
||||
fixed_t top;
|
||||
fixed_t bot;
|
||||
|
||||
vis->pt = vis->sector->floorheight;
|
||||
vis->pb = vis->sector->ceilingheight;
|
||||
|
||||
for (rover = vis->sector->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
if (rover->flags & FF_EXISTS)
|
||||
{
|
||||
top = P_GetFFloorTopZAt (rover, vis->gx, vis->gy);
|
||||
bot = P_GetFFloorBottomZAt (rover, vis->gx, vis->gy);
|
||||
|
||||
if (top <= vis->gzt && top > vis->pt)
|
||||
vis->pt = top;
|
||||
|
||||
if (bot >= vis->gz && bot < vis->pb)
|
||||
vis->pb = bot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, fixed_t tx, fixed_t tz)
|
||||
{
|
||||
vissprite_t *shadow;
|
||||
|
|
@ -1305,16 +1323,12 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
|
|||
shadow->patch = patch;
|
||||
shadow->heightsec = vis->heightsec;
|
||||
|
||||
shadow->thingheight = FRACUNIT;
|
||||
shadow->pz = groundz + (isflipped ? -shadow->thingheight : 0);
|
||||
shadow->pzt = shadow->pz + shadow->thingheight;
|
||||
|
||||
shadow->mobjflags = 0;
|
||||
shadow->sortscale = vis->sortscale;
|
||||
shadow->dispoffset = vis->dispoffset - 5;
|
||||
shadow->gx = thing->x;
|
||||
shadow->gy = thing->y;
|
||||
shadow->gzt = (isflipped ? shadow->pzt : shadow->pz) + SHORT(patch->height) * shadowyscale / 2;
|
||||
shadow->gzt = groundz + SHORT(patch->height) * shadowyscale / 2;
|
||||
shadow->gz = shadow->gzt - SHORT(patch->height) * shadowyscale;
|
||||
shadow->texturemid = FixedMul(thing->scale, FixedDiv(shadow->gzt - viewz, shadowyscale));
|
||||
if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES)
|
||||
|
|
@ -1330,6 +1344,8 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
|
|||
shadow->xscale = FixedMul(xscale, shadowxscale); //SoM: 4/17/2000
|
||||
shadow->scale = FixedMul(yscale, shadowyscale);
|
||||
shadow->sector = vis->sector;
|
||||
shadow->pt = vis->pt;
|
||||
shadow->pb = vis->pb;
|
||||
shadow->szt = (INT16)((centeryfrac - FixedMul(shadow->gzt - viewz, yscale))>>FRACBITS);
|
||||
shadow->sz = (INT16)((centeryfrac - FixedMul(shadow->gz - viewz, yscale))>>FRACBITS);
|
||||
shadow->cut = SC_ISSCALED|SC_SHADOW; //check this
|
||||
|
|
@ -1387,9 +1403,9 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
|
|||
//
|
||||
static void R_ProjectSprite(mobj_t *thing)
|
||||
{
|
||||
const fixed_t thingxpos = thing->x + thing->sprxoff;
|
||||
const fixed_t thingypos = thing->y + thing->spryoff;
|
||||
const fixed_t thingzpos = thing->z + thing->sprzoff;
|
||||
fixed_t thingxpos = thing->x + thing->sprxoff;
|
||||
fixed_t thingypos = thing->y + thing->spryoff;
|
||||
fixed_t thingzpos = thing->z + thing->sprzoff;
|
||||
|
||||
mobj_t *oldthing = thing;
|
||||
|
||||
|
|
@ -1448,6 +1464,21 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
INT32 rollangle = 0;
|
||||
#endif
|
||||
|
||||
// hitlag vibrating
|
||||
if (thing->hitlag > 0)
|
||||
{
|
||||
fixed_t mul = thing->hitlag * (FRACUNIT / 10);
|
||||
|
||||
if (leveltime & 1)
|
||||
{
|
||||
mul = -mul;
|
||||
}
|
||||
|
||||
thingxpos += FixedMul(thing->momx, mul);
|
||||
thingypos += FixedMul(thing->momy, mul);
|
||||
thingzpos += FixedMul(thing->momz, mul);
|
||||
}
|
||||
|
||||
// transform the origin point
|
||||
tr_x = thingxpos - viewx;
|
||||
tr_y = thingypos - viewy;
|
||||
|
|
@ -1812,9 +1843,6 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
vis->gy = thingypos;
|
||||
vis->gz = gz;
|
||||
vis->gzt = gzt;
|
||||
vis->thingheight = thing->height;
|
||||
vis->pz = thingzpos;
|
||||
vis->pzt = vis->pz + vis->thingheight;
|
||||
vis->texturemid = vis->gzt - viewz;
|
||||
vis->scalestep = scalestep;
|
||||
vis->paperoffset = paperoffset;
|
||||
|
|
@ -1832,6 +1860,9 @@ static void R_ProjectSprite(mobj_t *thing)
|
|||
vis->sector = thing->subsector->sector;
|
||||
vis->szt = (INT16)((centeryfrac - FixedMul(vis->gzt - viewz, sortscale))>>FRACBITS);
|
||||
vis->sz = (INT16)((centeryfrac - FixedMul(vis->gz - viewz, sortscale))>>FRACBITS);
|
||||
|
||||
R_SetSpritePlaneHeights(vis);
|
||||
|
||||
vis->cut = cut;
|
||||
if (thing->subsector->sector->numlights)
|
||||
vis->extra_colormap = *thing->subsector->sector->lightlist[light].extra_colormap;
|
||||
|
|
@ -2032,9 +2063,6 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
vis->gy = thing->y;
|
||||
vis->gz = gz;
|
||||
vis->gzt = gzt;
|
||||
vis->thingheight = 4*FRACUNIT;
|
||||
vis->pz = thing->z;
|
||||
vis->pzt = vis->pz + vis->thingheight;
|
||||
vis->texturemid = vis->gzt - viewz;
|
||||
vis->scalestep = 0;
|
||||
vis->paperdistance = 0;
|
||||
|
|
@ -2049,6 +2077,8 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
vis->szt = (INT16)((centeryfrac - FixedMul(vis->gzt - viewz, yscale))>>FRACBITS);
|
||||
vis->sz = (INT16)((centeryfrac - FixedMul(vis->gz - viewz, yscale))>>FRACBITS);
|
||||
|
||||
R_SetSpritePlaneHeights(vis);
|
||||
|
||||
iscale = FixedDiv(FRACUNIT, xscale);
|
||||
|
||||
vis->startfrac = 0;
|
||||
|
|
@ -2425,19 +2455,15 @@ static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean temps
|
|||
planeobjectz = P_GetZAt(r2->plane->slope, rover->gx, rover->gy, r2->plane->height);
|
||||
planecameraz = P_GetZAt(r2->plane->slope, viewx, viewy, r2->plane->height);
|
||||
|
||||
if (rover->mobjflags & MF_NOCLIPHEIGHT)
|
||||
// bird: if any part of the sprite peeks in front the plane
|
||||
if (planecameraz < viewz)
|
||||
{
|
||||
//Objects with NOCLIPHEIGHT can appear halfway in.
|
||||
if (planecameraz < viewz && rover->pz+(rover->thingheight/2) >= planeobjectz)
|
||||
continue;
|
||||
if (planecameraz > viewz && rover->pzt-(rover->thingheight/2) <= planeobjectz)
|
||||
if (rover->pt >= planeobjectz && rover->gzt >= planeobjectz)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
else if (planecameraz > viewz)
|
||||
{
|
||||
if (planecameraz < viewz && rover->pz >= planeobjectz)
|
||||
continue;
|
||||
if (planecameraz > viewz && rover->pzt <= planeobjectz)
|
||||
if (rover->pb <= planeobjectz && rover->gz <= planeobjectz)
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -138,8 +138,7 @@ typedef struct vissprite_s
|
|||
INT32 x1, x2;
|
||||
|
||||
fixed_t gx, gy; // for line side calculation
|
||||
fixed_t gz, gzt; // global bottom/top for silhouette clipping
|
||||
fixed_t pz, pzt; // physical bottom/top for sorting with 3D floors
|
||||
fixed_t gz, gzt; // global bottom/top for silhouette clipping and sorting with 3D floors
|
||||
|
||||
fixed_t startfrac; // horizontal position of x1
|
||||
fixed_t scale, sortscale; // sortscale only differs from scale for paper sprites and MF2_LINKDRAW
|
||||
|
|
@ -171,8 +170,8 @@ typedef struct vissprite_s
|
|||
fixed_t xscale;
|
||||
|
||||
// Precalculated top and bottom screen coords for the sprite.
|
||||
fixed_t thingheight; // The actual height of the thing (for 3D floors)
|
||||
sector_t *sector; // The sector containing the thing.
|
||||
fixed_t pt, pb; // plane heights, also for sorting against 3D floors
|
||||
INT16 sz, szt;
|
||||
|
||||
spritecut_e cut;
|
||||
|
|
|
|||
|
|
@ -2336,7 +2336,7 @@ static boolean S_PlayMusic(boolean looping, UINT32 fadeinms)
|
|||
S_InitMusicVolume(); // switch between digi and sequence volume
|
||||
|
||||
if (S_MusicNotInFocus())
|
||||
S_PauseAudio();
|
||||
I_SetMusicVolume(0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2780,9 +2780,9 @@ static void PlayMusicIfUnfocused_OnChange(void)
|
|||
if (window_notinfocus)
|
||||
{
|
||||
if (cv_playmusicifunfocused.value)
|
||||
I_PauseSong();
|
||||
I_SetMusicVolume(0);
|
||||
else
|
||||
I_ResumeSong();
|
||||
S_InitMusicVolume();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -651,7 +651,7 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt)
|
|||
window_notinfocus = false;
|
||||
|
||||
if (!paused)
|
||||
S_ResumeAudio(); //resume it
|
||||
S_InitMusicVolume();
|
||||
|
||||
if (cv_gamesounds.value)
|
||||
S_EnableSound();
|
||||
|
|
@ -670,7 +670,7 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt)
|
|||
// Tell game we lost focus, pause music
|
||||
window_notinfocus = true;
|
||||
if (!cv_playmusicifunfocused.value)
|
||||
I_PauseSong();
|
||||
I_SetMusicVolume(0);
|
||||
if (!cv_playsoundifunfocused.value)
|
||||
S_DisableSound();
|
||||
|
||||
|
|
|
|||
235
src/stun.c
Normal file
235
src/stun.c
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2020 by James R.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file stun.c
|
||||
/// \brief RFC 5389 client implementation to fetch external IP address.
|
||||
|
||||
/* https://tools.ietf.org/html/rfc5389 */
|
||||
|
||||
#if defined (__linux__)
|
||||
#include <sys/random.h>
|
||||
#elif defined (_WIN32)
|
||||
#define _CRT_RAND_S
|
||||
#elif defined (__APPLE__)
|
||||
#include <CommonCrypto/CommonRandom.h>
|
||||
#else
|
||||
#error "Need CSPRNG."
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "d_clisrv.h"
|
||||
#include "command.h"
|
||||
#include "i_net.h"
|
||||
#include "stun.h"
|
||||
|
||||
/* https://gist.github.com/zziuni/3741933 */
|
||||
/* I can only trust google to keep their shit up :y */
|
||||
consvar_t cv_stunserver = CVAR_INIT (
|
||||
"stunserver", "stun.l.google.com:19302", CV_SAVE, NULL, NULL
|
||||
);
|
||||
|
||||
static stun_callback_t stun_callback;
|
||||
|
||||
/* 18.4 STUN UDP and TCP Port Numbers */
|
||||
|
||||
#define STUN_PORT "3478"
|
||||
|
||||
/* 6. STUN Message Structure */
|
||||
|
||||
#define BIND_REQUEST 0x0001
|
||||
#define BIND_RESPONSE 0x0101
|
||||
|
||||
static const UINT32 MAGIC_COOKIE = MSBF_LONG (0x2112A442);
|
||||
|
||||
static char transaction_id[12];
|
||||
|
||||
/* 18.2 STUN Attribute Registry */
|
||||
|
||||
#define XOR_MAPPED_ADDRESS 0x0020
|
||||
|
||||
/* 15.1 MAPPED-ADDRESS */
|
||||
|
||||
#define STUN_IPV4 0x01
|
||||
|
||||
static SINT8
|
||||
STUN_node (void)
|
||||
{
|
||||
SINT8 node;
|
||||
|
||||
char * const colon = strchr(cv_stunserver.zstring, ':');
|
||||
|
||||
const char * const host = cv_stunserver.zstring;
|
||||
const char * const port = &colon[1];
|
||||
|
||||
I_Assert(I_NetMakeNodewPort != NULL);
|
||||
|
||||
if (colon != NULL)
|
||||
{
|
||||
*colon = '\0';
|
||||
|
||||
node = I_NetMakeNodewPort(host, port);
|
||||
|
||||
*colon = ':';
|
||||
}
|
||||
else
|
||||
{
|
||||
node = I_NetMakeNodewPort(host, STUN_PORT);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
static void
|
||||
csprng
|
||||
(
|
||||
void * const buffer,
|
||||
const size_t size
|
||||
){
|
||||
#if defined (_WIN32)
|
||||
size_t o;
|
||||
|
||||
for (o = 0; o < size; o += sizeof (unsigned int))
|
||||
{
|
||||
rand_s((unsigned int *)&((char *)buffer)[o]);
|
||||
}
|
||||
#elif defined (__linux__)
|
||||
getrandom(buffer, size, 0U);
|
||||
#elif defined (__APPLE__)
|
||||
CCRandomGenerateBytes(buffer, size);
|
||||
#elif defined (__FreeBSD__) || defined (__NetBSD__) || defined (__OpenBSD__)
|
||||
arc4random_buf(buffer, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
STUN_bind (stun_callback_t callback)
|
||||
{
|
||||
/* 6. STUN Message Structure */
|
||||
|
||||
const UINT16 type = MSBF_SHORT (BIND_REQUEST);
|
||||
|
||||
const SINT8 node = STUN_node();
|
||||
|
||||
doomcom->remotenode = node;
|
||||
doomcom->datalength = 20;
|
||||
|
||||
csprng(transaction_id, 12U);
|
||||
|
||||
memcpy(&doomcom->data[0], &type, 2U);
|
||||
memset(&doomcom->data[2], 0, 2U);
|
||||
memcpy(&doomcom->data[4], &MAGIC_COOKIE, 4U);
|
||||
memcpy(&doomcom->data[8], transaction_id, 12U);
|
||||
|
||||
stun_callback = callback;
|
||||
|
||||
I_NetSend();
|
||||
Net_CloseConnection(node);/* will handle response at I_NetGet */
|
||||
}
|
||||
|
||||
static size_t
|
||||
STUN_xor_mapped_address (const char * const value)
|
||||
{
|
||||
const UINT32 xaddr = *(const UINT32 *)&value[4];
|
||||
const UINT32 addr = xaddr ^ MAGIC_COOKIE;
|
||||
|
||||
(*stun_callback)(addr);
|
||||
|
||||
return 0U;
|
||||
}
|
||||
|
||||
static size_t
|
||||
align4 (size_t n)
|
||||
{
|
||||
return n + n % 4U;
|
||||
}
|
||||
|
||||
static size_t
|
||||
STUN_parse_attribute (const char * const attribute)
|
||||
{
|
||||
/* 15. STUN Attributes */
|
||||
const UINT16 type = MSBF_SHORT (*(const UINT16 *)&attribute[0]);
|
||||
const UINT16 length = MSBF_SHORT (*(const UINT16 *)&attribute[2]);
|
||||
|
||||
/* 15.2 XOR-MAPPED-ADDRESS */
|
||||
if (
|
||||
type == XOR_MAPPED_ADDRESS &&
|
||||
length == 8U &&
|
||||
(unsigned char)attribute[5] == STUN_IPV4
|
||||
){
|
||||
return STUN_xor_mapped_address(&attribute[4]);
|
||||
}
|
||||
|
||||
return align4(4U + length);
|
||||
}
|
||||
|
||||
boolean
|
||||
STUN_got_response
|
||||
(
|
||||
const char * const buffer,
|
||||
const size_t size
|
||||
){
|
||||
const char * const end = &buffer[size];
|
||||
|
||||
const char * p = &buffer[20];
|
||||
|
||||
UINT16 type;
|
||||
UINT16 length;
|
||||
|
||||
/*
|
||||
Check for STUN response.
|
||||
|
||||
Header is 20 bytes.
|
||||
XOR-MAPPED-ADDRESS attribute is required.
|
||||
Each attribute has a 2 byte header.
|
||||
The XOR-MAPPED-ADDRESS attribute also has a 8 byte value.
|
||||
This totals 10 bytes for the attribute.
|
||||
*/
|
||||
|
||||
if (size < 30U || stun_callback == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* 6. STUN Message Structure */
|
||||
|
||||
if (
|
||||
*(const UINT32 *)&buffer[4] == MAGIC_COOKIE &&
|
||||
memcmp(&buffer[8], transaction_id, 12U) == 0
|
||||
){
|
||||
type = MSBF_SHORT (*(const UINT16 *)&buffer[0]);
|
||||
length = MSBF_SHORT (*(const UINT16 *)&buffer[2]);
|
||||
|
||||
if (
|
||||
(type >> 14) == 0U &&
|
||||
(length & 0x02) == 0U &&
|
||||
(20U + length) <= size
|
||||
){
|
||||
if (type == BIND_RESPONSE)
|
||||
{
|
||||
do
|
||||
{
|
||||
length = STUN_parse_attribute(p);
|
||||
|
||||
if (length == 0U)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
p += length;
|
||||
}
|
||||
while (p < end) ;
|
||||
}
|
||||
|
||||
stun_callback = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
20
src/stun.h
Normal file
20
src/stun.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// SONIC ROBO BLAST 2 KART
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2020 by James R.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file stun.h
|
||||
/// \brief RFC 5389 client implementation to fetch external IP address.
|
||||
|
||||
#ifndef KART_STUN_H
|
||||
#define KART_STUN_H
|
||||
|
||||
typedef void (*stun_callback_t)(UINT32 address);
|
||||
|
||||
void STUN_bind (stun_callback_t);
|
||||
boolean STUN_got_response (const char * const buffer, const size_t size);
|
||||
|
||||
#endif/*KART_STUN_H*/
|
||||
Loading…
Add table
Reference in a new issue