From 7c0088b752b6ac6df2c824c48b6382e4d7becbae Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 7 Dec 2021 17:23:42 -0500 Subject: [PATCH 01/69] TERRAIN lump mockup --- src/k_terrain.c | 366 ++++++++++++++++++++++++++++++++++++++++++++++++ src/k_terrain.h | 70 +++++++++ 2 files changed, 436 insertions(+) create mode 100644 src/k_terrain.c create mode 100644 src/k_terrain.h diff --git a/src/k_terrain.c b/src/k_terrain.c new file mode 100644 index 000000000..ea78c9d2d --- /dev/null +++ b/src/k_terrain.c @@ -0,0 +1,366 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2021 by ZDoom + GZDoom teams, and contributors +// Copyright (C) 2021 by Sally "TehRealSalt" Cochenour +// Copyright (C) 2021 by Kart Krew +// +// 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 k_terrain.c +/// \brief Implementation of TERRAIN lump from GZDoom codebase for DRRR. + +#include "k_terrain.h" + +#include "z_zone.h" + +t_splash_t *splashDefs = NULL; +UINT16 numSplashDefs = 0; + +t_footstep_t *footstepDefs = NULL; +UINT16 numFootstepDefs = 0; + +terrain_t *terrainDefs = NULL; +UINT16 numTerrainDefs = 0; + +UINT16 defaultTerrain = UINT16_MAX; + +terrain_t *K_GetTerrainByIndex(UINT16 checkIndex) +{ + if (checkIndex >= numTerrainDefs) + { + return NULL; + } + + return terrainDefs[checkIndex]; +} + +terrain_t *K_GetTerrainByName(const char *checkName) +{ + INT32 i; + + if (numTerrainDefs == 0) + { + return NULL; + } + + // Search backwards through all terrain definitions. + // The latest one will have priority over the older one. + for (i = numTerrainDefs-1; i >= 0; i--) + { + terrain_t t = terrainDefs[i]; + + if (stricmp(checkName, t->name) == 0) + { + // Name matches. + return t; + } + } + + return NULL; +} + +terrain_t *K_GetDefaultTerrain(void) +{ + return K_GetTerrainByIndex(defaultTerrain); +} + +terrain_t *K_GetTerrainForTextureNum(INT32 textureNum) +{ + INT32 i, j; + + if (textureNum == -1) + { + return NULL; + } + + if (numTerrainDefs == 0) + { + return NULL; + } + + // Search backwards through all terrain definitions. + // The latest one will have priority over the older one. + + for (i = numTerrainDefs-1; i >= 0; i--) + { + terrain_t t = terrainDefs[i]; + + if (t->numTextureIDs == 0) + { + // No textures are applied to this terrain type. + continue; + } + + for (j = 0; j < numTextureIDs; j++) + { + if (textureNum == t->textureIDs[j]) + { + // Texture matches. + return t; + } + } + } + + // This texture doesn't have a terrain directly applied to it, + // so we fallback to the default terrain. + return K_GetDefaultTerrain(); +} + +terrain_t *K_GetTerrainForTextureName(const char *checkName) +{ + return K_GetTerrainForTextureNum( R_CheckTextureNumForName(checkName) ); +} + +static void K_GrowSplashDefs(void) +{ + numSplashDefs++; + splashDefs = (t_splash_t *)Z_Realloc(splashDefs, sizeof(t_splash_t) * (numSplashDefs + 1), PU_STATIC, NULL); +} + +static void K_GrowFootstepDefs(void) +{ + numFootstepDefs++; + footstepDefs = (t_footstep_t *)Z_Realloc(footstepDefs, sizeof(t_footstep_t) * (numFootstepDefs + 1), PU_STATIC, NULL); +} + +static void K_ParseNextLine(char *p, char *token) +{ + // parse next line + while (*p != '\0' && *p != '\n') + { + ++p; + } + + if (*p == '\n') + { + ++p; + } + + token = M_GetToken(p); +} + +static void K_GrowTerrainDefs(void) +{ + numTerrainDefs++; + terrainDefs = (terrain_t *)Z_Realloc(terrainDefs, sizeof(terrain_t) * (numTerrainDefs + 1), PU_STATIC, NULL); +} + +static void K_ParseTerrainDefintion(void) +{ + char *token; + size_t tokenLength; + char *endPos; + size_t i; + + // Startname + token = M_GetToken(NULL); + + if (token == NULL) + { + I_Error("Error parsing TERRAIN lump: Expected terrain definition, got end of file"); + } + + if (stricmp(token, "{") != 0) + { + I_Error("Error parsing TERRAIN lump: No starting bracket"); + } + + while (token != NULL) + { + + } + tokenLength = strlen(token); + + if (stricmp(animdefsToken, "OPTIONAL") == 0) + { + // This is meaningful to ZDoom - it tells the program NOT to bomb out + // if the textures can't be found - but it's useless in SRB2, so we'll + // just smile, nod, and carry on + Z_Free(animdefsToken); + animdefsToken = M_GetToken(NULL); + + if (animdefsToken == NULL) + { + I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where start texture/flat name should be"); + } + else if (stricmp(animdefsToken, "RANGE") == 0) + { + // Oh. Um. Apparently "OPTIONAL" is a texture name. Naughty. + // I should probably handle this more gracefully, but right now + // I can't be bothered; especially since ZDoom doesn't handle this + // condition at all. + I_Error("Error parsing ANIMDEFS lump: \"OPTIONAL\" is a keyword; you cannot use it as the startname of an animation"); + } + } + animdefsTokenLength = strlen(animdefsToken); + if (animdefsTokenLength>8) + { + I_Error("Error parsing ANIMDEFS lump: lump name \"%s\" exceeds 8 characters", animdefsToken); + } + + // Search for existing animdef + for (i = 0; i < maxanims; i++) + if (animdefs[i].istexture == istexture // Check if it's the same type! + && stricmp(animdefsToken, animdefs[i].startname) == 0) + { + //CONS_Alert(CONS_NOTICE, "Duplicate animation: %s\n", animdefsToken); + + // If we weren't parsing in reverse order, we would `break` here and parse the new data into the existing slot we found. + // Instead, we're just going to skip parsing the rest of this line entirely. + Z_Free(animdefsToken); + return; + } + + // Not found + if (i == maxanims) + { + // Increase the size to make room for the new animation definition + GrowAnimDefs(); + strncpy(animdefs[i].startname, animdefsToken, 9); + } + + // animdefs[i].startname is now set to animdefsToken either way. + Z_Free(animdefsToken); + + // set texture type + animdefs[i].istexture = istexture; + + // "RANGE" + animdefsToken = M_GetToken(NULL); + if (animdefsToken == NULL) + { + I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"RANGE\" after \"%s\"'s startname should be", animdefs[i].startname); + } + if (stricmp(animdefsToken, "ALLOWDECALS") == 0) + { + // Another ZDoom keyword, ho-hum. Skip it, move on to the next token. + Z_Free(animdefsToken); + animdefsToken = M_GetToken(NULL); + } + if (stricmp(animdefsToken, "PIC") == 0) + { + // This is technically legitimate ANIMDEFS syntax, but SRB2 doesn't support it. + I_Error("Error parsing ANIMDEFS lump: Animation definitions utilizing \"PIC\" (specific frames instead of a consecutive range) are not supported by SRB2"); + } + if (stricmp(animdefsToken, "RANGE") != 0) + { + I_Error("Error parsing ANIMDEFS lump: Expected \"RANGE\" after \"%s\"'s startname, got \"%s\"", animdefs[i].startname, animdefsToken); + } + Z_Free(animdefsToken); + + // Endname + animdefsToken = M_GetToken(NULL); + if (animdefsToken == NULL) + { + I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s end texture/flat name should be", animdefs[i].startname); + } + animdefsTokenLength = strlen(animdefsToken); + if (animdefsTokenLength>8) + { + I_Error("Error parsing ANIMDEFS lump: lump name \"%s\" exceeds 8 characters", animdefsToken); + } + strncpy(animdefs[i].endname, animdefsToken, 9); + Z_Free(animdefsToken); + + // "TICS" + animdefsToken = M_GetToken(NULL); + if (animdefsToken == NULL) + { + I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s \"TICS\" should be", animdefs[i].startname); + } + if (stricmp(animdefsToken, "RAND") == 0) + { + // This is technically legitimate ANIMDEFS syntax, but SRB2 doesn't support it. + I_Error("Error parsing ANIMDEFS lump: Animation definitions utilizing \"RAND\" (random duration per frame) are not supported by SRB2"); + } + if (stricmp(animdefsToken, "TICS") != 0) + { + I_Error("Error parsing ANIMDEFS lump: Expected \"TICS\" in animation definition for \"%s\", got \"%s\"", animdefs[i].startname, animdefsToken); + } + Z_Free(animdefsToken); + + // Speed + animdefsToken = M_GetToken(NULL); + if (animdefsToken == NULL) + { + I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s animation speed should be", animdefs[i].startname); + } + endPos = NULL; +#ifndef AVOID_ERRNO + errno = 0; +#endif + + animSpeed = strtol(animdefsToken,&endPos,10); + + if (endPos == animdefsToken // Empty string + || *endPos != '\0' // Not end of string +#ifndef AVOID_ERRNO + || errno == ERANGE // Number out-of-range +#endif + || animSpeed < 0) // Number is not positive + { + I_Error("Error parsing ANIMDEFS lump: Expected a positive integer for \"%s\"'s animation speed, got \"%s\"", animdefs[i].startname, animdefsToken); + } + + animdefs[i].speed = animSpeed; + + Z_Free(animdefsToken); +} + +void K_ParseTERRAINLump(INT32 wadNum, UINT16 lumpnum) +{ + char *lump; + size_t lumpLength; + char *fullText; + char *token; + char *p; + + // Since lumps AREN'T \0-terminated like I'd assumed they should be, I'll + // need to make a space of memory where I can ensure that it will terminate + // correctly. Start by loading the relevant data from the WAD. + lump = (char *)W_CacheLumpNumPwad(wadNum, lumpnum, PU_STATIC); + + // If that didn't exist, we have nothing to do here. + if (lump == NULL) + { + return; + } + + // If we're still here, then it DOES exist; figure out how long it is, and allot memory accordingly. + lumpLength = W_LumpLengthPwad(wadNum, lumpnum); + fullText = (char *)Z_Malloc((lumpLength + 1) * sizeof(char), PU_STATIC, NULL); + + // Now move the contents of the lump into this new location. + memmove(fullText, lump, lumpLength); + + // Make damn well sure the last character in our new memory location is \0. + fullText[lumpLength] = '\0'; + + // Finally, free up the memory from the first data load, because we really + // don't need it. + Z_Free(lump); + + // Now, let's start parsing this thing + p = fullText; + token = M_GetToken(p); + + while (token != NULL) + { + if (stricmp(token, "TERRAIN") == 0) + { + Z_Free(token); + K_ParseTerrainDefintion(&p, &token); + } + else + { + I_Error("Error parsing TERRAIN lump: Expected \"SPLASH\", \"FOOTSTEP\", \"TERRAIN\", \"FLOOR\"; got \"%s\"", token); + } + + K_ParseNextLine(&p, &token); + } + + Z_Free(token); + Z_Free((void *)fullText); +} diff --git a/src/k_terrain.h b/src/k_terrain.h new file mode 100644 index 000000000..ac504cd48 --- /dev/null +++ b/src/k_terrain.h @@ -0,0 +1,70 @@ +// DR. ROBOTNIK'S RING RACERS +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2021 by ZDoom + GZDoom teams, and contributors +// Copyright (C) 2021 by Sally "TehRealSalt" Cochenour +// Copyright (C) 2021 by Kart Krew +// +// 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 k_terrain.h +/// \brief Implementation of a TERRAIN-style lump for DRRR, ala GZDoom's codebase. + +#ifndef __K_TERRAIN_H__ +#define __K_TERRAIN_H__ + +typedef struct t_splash_s +{ + // Splash definition. + // These are particles spawned when hitting the floor. + + const char *name; // Lookup name. + + UINT16 objType; // Thing type. MT_NULL to not spawn anything. + UINT16 sound; // Sound to play. +} t_splash_t; + +typedef struct t_footstep_s +{ + // Footstep definition. + // These are particles spawned when moving fast enough on a floor. + + const char *name; // Lookup name. + + UINT16 objType; // Thing type. MT_NULL to not spawn anything. + UINT16 sound; // Sound to play. +} t_footstep_t; + +typedef struct terrain_s +{ + // Terrain definition. + // These are all of the properties that the floor gets. + + const char *name; // Lookup name. + + INT32 *textureIDs; // Texture nums this terrain applies to. (Doesn't support flats, stop using them already.) + UINT32 numTextureIDs; // Length of the above table. + + UINT16 splashID; // Splash defintion ID. + UINT16 footstepID; // Footstep defintion ID. + + fixed_t friction; // The default friction of this texture. + UINT8 offroad; // The default offroad level of this texture. + INT16 damageType; // The default damage type of this texture. (Negative means no damage). +} terrain_t; + +// Arrays for all terrain definitions. +extern t_splash_t *splashDefs; +extern UINT16 numSplashDefs; + +extern t_footstep_t *footstepDefs; +extern UINT16 numFootstepDefs; + +extern terrain_t *terrainDefs; +extern UINT16 numTerrainDefs; + +// Default terrain definition ID. +extern UINT16 defaultTerrain; + +#endif // __K_TERRAIN_H__ From a8615cac5b1d30e6047dfc77901aeec0a3255f90 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 8 Dec 2021 19:16:12 -0500 Subject: [PATCH 02/69] TERRAIN lump reading Does not impact gameplay but hey pretty cool --- src/Sourcefile | 1 + src/k_terrain.c | 409 ++++++++++++++++++++++-------------------------- src/k_terrain.h | 19 ++- src/w_wad.c | 4 + 4 files changed, 204 insertions(+), 229 deletions(-) diff --git a/src/Sourcefile b/src/Sourcefile index 9bc27d4da..a1d6e176a 100644 --- a/src/Sourcefile +++ b/src/Sourcefile @@ -111,3 +111,4 @@ k_botitem.c k_botsearch.c k_grandprix.c k_hud.c +k_terrain.c diff --git a/src/k_terrain.c b/src/k_terrain.c index ea78c9d2d..77537f0f3 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -13,6 +13,12 @@ #include "k_terrain.h" +#include "dehacked.h" // get_number +#include "doomtype.h" +#include "fastcmp.h" +#include "m_fixed.h" +#include "r_textures.h" +#include "w_wad.h" #include "z_zone.h" t_splash_t *splashDefs = NULL; @@ -33,7 +39,7 @@ terrain_t *K_GetTerrainByIndex(UINT16 checkIndex) return NULL; } - return terrainDefs[checkIndex]; + return &terrainDefs[checkIndex]; } terrain_t *K_GetTerrainByName(const char *checkName) @@ -49,7 +55,7 @@ terrain_t *K_GetTerrainByName(const char *checkName) // The latest one will have priority over the older one. for (i = numTerrainDefs-1; i >= 0; i--) { - terrain_t t = terrainDefs[i]; + terrain_t *t = &terrainDefs[i]; if (stricmp(checkName, t->name) == 0) { @@ -68,7 +74,7 @@ terrain_t *K_GetDefaultTerrain(void) terrain_t *K_GetTerrainForTextureNum(INT32 textureNum) { - INT32 i, j; + INT32 i; if (textureNum == -1) { @@ -85,7 +91,8 @@ terrain_t *K_GetTerrainForTextureNum(INT32 textureNum) for (i = numTerrainDefs-1; i >= 0; i--) { - terrain_t t = terrainDefs[i]; + terrain_t *t = &terrainDefs[i]; + size_t j; if (t->numTextureIDs == 0) { @@ -93,7 +100,7 @@ terrain_t *K_GetTerrainForTextureNum(INT32 textureNum) continue; } - for (j = 0; j < numTextureIDs; j++) + for (j = 0; j < t->numTextureIDs; j++) { if (textureNum == t->textureIDs[j]) { @@ -113,254 +120,204 @@ terrain_t *K_GetTerrainForTextureName(const char *checkName) return K_GetTerrainForTextureNum( R_CheckTextureNumForName(checkName) ); } -static void K_GrowSplashDefs(void) +// +// Parser code starts here. +// + +static void K_TerrainDefaults(terrain_t *terrain) { - numSplashDefs++; - splashDefs = (t_splash_t *)Z_Realloc(splashDefs, sizeof(t_splash_t) * (numSplashDefs + 1), PU_STATIC, NULL); + terrain->splashID = UINT16_MAX; + terrain->footstepID = UINT16_MAX; + + terrain->friction = FRACUNIT; + terrain->offroad = 0; + terrain->damageType = -1; } -static void K_GrowFootstepDefs(void) -{ - numFootstepDefs++; - footstepDefs = (t_footstep_t *)Z_Realloc(footstepDefs, sizeof(t_footstep_t) * (numFootstepDefs + 1), PU_STATIC, NULL); -} - -static void K_ParseNextLine(char *p, char *token) -{ - // parse next line - while (*p != '\0' && *p != '\n') - { - ++p; - } - - if (*p == '\n') - { - ++p; - } - - token = M_GetToken(p); -} - -static void K_GrowTerrainDefs(void) +static void K_NewTerrainDefs(void) { numTerrainDefs++; terrainDefs = (terrain_t *)Z_Realloc(terrainDefs, sizeof(terrain_t) * (numTerrainDefs + 1), PU_STATIC, NULL); + K_TerrainDefaults( &terrainDefs[numTerrainDefs - 1] ); } -static void K_ParseTerrainDefintion(void) +static void K_ParseTerrainParameter(UINT32 i, char *param, char *val) { - char *token; - size_t tokenLength; - char *endPos; + terrain_t *terrain = &terrainDefs[i]; + + if (stricmp(param, "splash") == 0) + { + //terrain->splashID = 0; + } + else if (stricmp(param, "footstep") == 0) + { + //terrain->footstepID = 0; + } + else if (stricmp(param, "friction") == 0) + { + terrain->friction = FLOAT_TO_FIXED(atof(val)); + } + else if (stricmp(param, "offroad") == 0) + { + terrain->offroad = (UINT8)get_number(val); + } + else if (stricmp(param, "damageType") == 0) + { + terrain->damageType = (INT16)get_number(val); + } +} + +static boolean K_DoTERRAINLumpParse(size_t num, void (*parser)(UINT32, char *, char *)) +{ + char *param, *val; + + param = M_GetToken(NULL); + + if (!fastcmp(param, "{")) + { + Z_Free(param); + CONS_Alert(CONS_WARNING, "Invalid TERRAIN data capsule!\n"); + return false; + } + + Z_Free(param); + + while (true) + { + param = M_GetToken(NULL); + + if (fastcmp(param, "}")) + { + Z_Free(param); + break; + } + + val = M_GetToken(NULL); + parser(num, param, val); + + Z_Free(param); + Z_Free(val); + } + + return true; +} + +static boolean K_TERRAINLumpParser(UINT8 *data, size_t size) +{ + char *tkn = M_GetToken((char *)data); + size_t pos = 0; size_t i; - // Startname - token = M_GetToken(NULL); - - if (token == NULL) + while (tkn && (pos = M_GetTokenPos()) < size) { - I_Error("Error parsing TERRAIN lump: Expected terrain definition, got end of file"); - } + boolean result = true; - if (stricmp(token, "{") != 0) - { - I_Error("Error parsing TERRAIN lump: No starting bracket"); - } - - while (token != NULL) - { - - } - tokenLength = strlen(token); - - if (stricmp(animdefsToken, "OPTIONAL") == 0) - { - // This is meaningful to ZDoom - it tells the program NOT to bomb out - // if the textures can't be found - but it's useless in SRB2, so we'll - // just smile, nod, and carry on - Z_Free(animdefsToken); - animdefsToken = M_GetToken(NULL); - - if (animdefsToken == NULL) + // Avoid anything inside bracketed stuff, only look for external keywords. + if (fastcmp(tkn, "{") || fastcmp(tkn, "}")) { - I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where start texture/flat name should be"); + CONS_Alert(CONS_ERROR, "Rogue bracket detected in TERRAIN lump.\n"); + Z_Free(tkn); + return false; } - else if (stricmp(animdefsToken, "RANGE") == 0) + // Check for valid fields. + else if (stricmp(tkn, "terrain") == 0) { - // Oh. Um. Apparently "OPTIONAL" is a texture name. Naughty. - // I should probably handle this more gracefully, but right now - // I can't be bothered; especially since ZDoom doesn't handle this - // condition at all. - I_Error("Error parsing ANIMDEFS lump: \"OPTIONAL\" is a keyword; you cannot use it as the startname of an animation"); - } - } - animdefsTokenLength = strlen(animdefsToken); - if (animdefsTokenLength>8) - { - I_Error("Error parsing ANIMDEFS lump: lump name \"%s\" exceeds 8 characters", animdefsToken); - } + Z_Free(tkn); + tkn = M_GetToken(NULL); + pos = M_GetTokenPos(); - // Search for existing animdef - for (i = 0; i < maxanims; i++) - if (animdefs[i].istexture == istexture // Check if it's the same type! - && stricmp(animdefsToken, animdefs[i].startname) == 0) - { - //CONS_Alert(CONS_NOTICE, "Duplicate animation: %s\n", animdefsToken); + if (tkn && pos < size) + { + terrain_t *t = NULL; - // If we weren't parsing in reverse order, we would `break` here and parse the new data into the existing slot we found. - // Instead, we're just going to skip parsing the rest of this line entirely. - Z_Free(animdefsToken); - return; - } + for (i = 0; i < numTerrainDefs; i++) + { + t = &terrainDefs[i]; - // Not found - if (i == maxanims) - { - // Increase the size to make room for the new animation definition - GrowAnimDefs(); - strncpy(animdefs[i].startname, animdefsToken, 9); - } + if (stricmp(tkn, t->name) == 0) + { + break; + } + } - // animdefs[i].startname is now set to animdefsToken either way. - Z_Free(animdefsToken); + if (i == numTerrainDefs) + { + K_NewTerrainDefs(); + t = &terrainDefs[i]; - // set texture type - animdefs[i].istexture = istexture; + strncpy(t->name, tkn, TERRAIN_NAME_LEN); + CONS_Printf("Created new Terrain type '%s'\n", t->name); + } - // "RANGE" - animdefsToken = M_GetToken(NULL); - if (animdefsToken == NULL) - { - I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"RANGE\" after \"%s\"'s startname should be", animdefs[i].startname); - } - if (stricmp(animdefsToken, "ALLOWDECALS") == 0) - { - // Another ZDoom keyword, ho-hum. Skip it, move on to the next token. - Z_Free(animdefsToken); - animdefsToken = M_GetToken(NULL); - } - if (stricmp(animdefsToken, "PIC") == 0) - { - // This is technically legitimate ANIMDEFS syntax, but SRB2 doesn't support it. - I_Error("Error parsing ANIMDEFS lump: Animation definitions utilizing \"PIC\" (specific frames instead of a consecutive range) are not supported by SRB2"); - } - if (stricmp(animdefsToken, "RANGE") != 0) - { - I_Error("Error parsing ANIMDEFS lump: Expected \"RANGE\" after \"%s\"'s startname, got \"%s\"", animdefs[i].startname, animdefsToken); - } - Z_Free(animdefsToken); - - // Endname - animdefsToken = M_GetToken(NULL); - if (animdefsToken == NULL) - { - I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s end texture/flat name should be", animdefs[i].startname); - } - animdefsTokenLength = strlen(animdefsToken); - if (animdefsTokenLength>8) - { - I_Error("Error parsing ANIMDEFS lump: lump name \"%s\" exceeds 8 characters", animdefsToken); - } - strncpy(animdefs[i].endname, animdefsToken, 9); - Z_Free(animdefsToken); - - // "TICS" - animdefsToken = M_GetToken(NULL); - if (animdefsToken == NULL) - { - I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s \"TICS\" should be", animdefs[i].startname); - } - if (stricmp(animdefsToken, "RAND") == 0) - { - // This is technically legitimate ANIMDEFS syntax, but SRB2 doesn't support it. - I_Error("Error parsing ANIMDEFS lump: Animation definitions utilizing \"RAND\" (random duration per frame) are not supported by SRB2"); - } - if (stricmp(animdefsToken, "TICS") != 0) - { - I_Error("Error parsing ANIMDEFS lump: Expected \"TICS\" in animation definition for \"%s\", got \"%s\"", animdefs[i].startname, animdefsToken); - } - Z_Free(animdefsToken); - - // Speed - animdefsToken = M_GetToken(NULL); - if (animdefsToken == NULL) - { - I_Error("Error parsing ANIMDEFS lump: Unexpected end of file where \"%s\"'s animation speed should be", animdefs[i].startname); - } - endPos = NULL; -#ifndef AVOID_ERRNO - errno = 0; -#endif - - animSpeed = strtol(animdefsToken,&endPos,10); - - if (endPos == animdefsToken // Empty string - || *endPos != '\0' // Not end of string -#ifndef AVOID_ERRNO - || errno == ERANGE // Number out-of-range -#endif - || animSpeed < 0) // Number is not positive - { - I_Error("Error parsing ANIMDEFS lump: Expected a positive integer for \"%s\"'s animation speed, got \"%s\"", animdefs[i].startname, animdefsToken); - } - - animdefs[i].speed = animSpeed; - - Z_Free(animdefsToken); -} - -void K_ParseTERRAINLump(INT32 wadNum, UINT16 lumpnum) -{ - char *lump; - size_t lumpLength; - char *fullText; - char *token; - char *p; - - // Since lumps AREN'T \0-terminated like I'd assumed they should be, I'll - // need to make a space of memory where I can ensure that it will terminate - // correctly. Start by loading the relevant data from the WAD. - lump = (char *)W_CacheLumpNumPwad(wadNum, lumpnum, PU_STATIC); - - // If that didn't exist, we have nothing to do here. - if (lump == NULL) - { - return; - } - - // If we're still here, then it DOES exist; figure out how long it is, and allot memory accordingly. - lumpLength = W_LumpLengthPwad(wadNum, lumpnum); - fullText = (char *)Z_Malloc((lumpLength + 1) * sizeof(char), PU_STATIC, NULL); - - // Now move the contents of the lump into this new location. - memmove(fullText, lump, lumpLength); - - // Make damn well sure the last character in our new memory location is \0. - fullText[lumpLength] = '\0'; - - // Finally, free up the memory from the first data load, because we really - // don't need it. - Z_Free(lump); - - // Now, let's start parsing this thing - p = fullText; - token = M_GetToken(p); - - while (token != NULL) - { - if (stricmp(token, "TERRAIN") == 0) - { - Z_Free(token); - K_ParseTerrainDefintion(&p, &token); + result = K_DoTERRAINLumpParse(i, K_ParseTerrainParameter); + } + // TODO: the other block types! + else + { + CONS_Alert(CONS_NOTICE, "No terrain type name.\n"); + } } else { - I_Error("Error parsing TERRAIN lump: Expected \"SPLASH\", \"FOOTSTEP\", \"TERRAIN\", \"FLOOR\"; got \"%s\"", token); + CONS_Alert(CONS_NOTICE, "Unknown field '%s' found in TERRAIN lump.\n", tkn); + Z_Free(tkn); + return false; } - K_ParseNextLine(&p, &token); + if (result == false) + { + Z_Free(tkn); + return false; + } + + Z_Free(tkn); + tkn = M_GetToken(NULL); } - Z_Free(token); - Z_Free((void *)fullText); + Z_Free(tkn); + return true; +} + +void K_InitTerrain(UINT16 wadNum) +{ + UINT16 lumpNum; + lumpinfo_t *lump_p = wadfiles[wadNum]->lumpinfo; + + // Iterate through all lumps and compare the name individually. + // In PK3 files, you can potentially have multiple TERRAIN differentiated by + // their file extension. + for (lumpNum = 0; lumpNum < wadfiles[wadNum]->numlumps; lumpNum++, lump_p++) + { + UINT8 *data; + + if (memcmp(lump_p->name, "TERRAIN", 8) != 0) + { + continue; + } + + data = (UINT8 *)W_CacheLumpNumPwad(wadNum, lumpNum, PU_STATIC); + + // If that didn't exist, we have nothing to do here. + if (data == NULL) + { + continue; + } + else + { + size_t size = W_LumpLengthPwad(wadNum, lumpNum); + + size_t nameLength = strlen(wadfiles[wadNum]->filename) + 1 + strlen(lump_p->fullname); // length of file name, '|', and lump name + char *name = malloc(nameLength + 1); + + sprintf(name, "%s|%s", wadfiles[wadNum]->filename, lump_p->fullname); + name[nameLength] = '\0'; + + size = W_LumpLengthPwad(wadNum, lumpNum); + + CONS_Printf(M_GetText("Loading TERRAIN from %s\n"), name); + K_TERRAINLumpParser(data, size); + + free(name); + } + } } diff --git a/src/k_terrain.h b/src/k_terrain.h index ac504cd48..d774fa130 100644 --- a/src/k_terrain.h +++ b/src/k_terrain.h @@ -14,12 +14,17 @@ #ifndef __K_TERRAIN_H__ #define __K_TERRAIN_H__ +#include "doomtype.h" +#include "m_fixed.h" + +#define TERRAIN_NAME_LEN 32 + typedef struct t_splash_s { // Splash definition. // These are particles spawned when hitting the floor. - const char *name; // Lookup name. + char name[TERRAIN_NAME_LEN]; // Lookup name. UINT16 objType; // Thing type. MT_NULL to not spawn anything. UINT16 sound; // Sound to play. @@ -30,7 +35,7 @@ typedef struct t_footstep_s // Footstep definition. // These are particles spawned when moving fast enough on a floor. - const char *name; // Lookup name. + char name[TERRAIN_NAME_LEN]; // Lookup name. UINT16 objType; // Thing type. MT_NULL to not spawn anything. UINT16 sound; // Sound to play. @@ -41,7 +46,7 @@ typedef struct terrain_s // Terrain definition. // These are all of the properties that the floor gets. - const char *name; // Lookup name. + char name[TERRAIN_NAME_LEN]; // Lookup name. INT32 *textureIDs; // Texture nums this terrain applies to. (Doesn't support flats, stop using them already.) UINT32 numTextureIDs; // Length of the above table. @@ -67,4 +72,12 @@ extern UINT16 numTerrainDefs; // Default terrain definition ID. extern UINT16 defaultTerrain; +terrain_t *K_GetTerrainByIndex(UINT16 checkIndex); +terrain_t *K_GetTerrainByName(const char *checkName); +terrain_t *K_GetDefaultTerrain(void); +terrain_t *K_GetTerrainForTextureNum(INT32 textureNum); +terrain_t *K_GetTerrainForTextureName(const char *checkName); + +void K_InitTerrain(UINT16 wadNum); + #endif // __K_TERRAIN_H__ diff --git a/src/w_wad.c b/src/w_wad.c index 4e7e97dbb..34f846664 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -69,6 +69,8 @@ #include "m_misc.h" // M_MapNumber #include "g_game.h" // G_SetGameModified +#include "k_terrain.h" + #ifdef HWRENDER #include "hardware/hw_main.h" #include "hardware/hw_glob.h" @@ -866,6 +868,8 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup) break; } + K_InitTerrain(numwadfiles - 1); + if (refreshdirmenu & REFRESHDIR_GAMEDATA) G_LoadGameData(); DEH_UpdateMaxFreeslots(); From 150faf9de67dfdb8a106233d6595e09a7ee471fb Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 9 Dec 2021 00:56:05 -0500 Subject: [PATCH 03/69] Add terrain pointer to mobj_t --- src/k_kart.c | 1 + src/k_terrain.c | 88 ++++++++++++++++++++++++++++++++++++++++--------- src/k_terrain.h | 14 ++++++++ src/p_inter.c | 1 + src/p_local.h | 1 + src/p_map.c | 51 +++++++++++++++++++++++++--- src/p_maputl.c | 8 +++++ src/p_maputl.h | 1 + src/p_mobj.c | 79 ++++++++++++++++++++++++++++++-------------- src/p_mobj.h | 1 + src/p_slopes.c | 1 + 11 files changed, 203 insertions(+), 43 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 73661c018..cf51e3646 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5176,6 +5176,7 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound) return; mo->standingslope = NULL; + mo->terrain = NULL; mo->eflags |= MFE_SPRUNG; diff --git a/src/k_terrain.c b/src/k_terrain.c index 77537f0f3..fabc89882 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -14,9 +14,13 @@ #include "k_terrain.h" #include "dehacked.h" // get_number +#include "doomdata.h" +#include "doomdef.h" #include "doomtype.h" #include "fastcmp.h" #include "m_fixed.h" +#include "p_local.h" +#include "p_mobj.h" #include "r_textures.h" #include "w_wad.h" #include "z_zone.h" @@ -120,10 +124,51 @@ terrain_t *K_GetTerrainForTextureName(const char *checkName) return K_GetTerrainForTextureNum( R_CheckTextureNumForName(checkName) ); } +void K_UpdateMobjTerrain(mobj_t *mo, INT32 flatID) +{ + levelflat_t *levelFlat = NULL; + + if (mo == NULL || P_MobjWasRemoved(mo) == true) + { + // Invalid object. + return; + } + + if (flatID < 0 || flatID >= (signed)numlevelflats) + { + // Clearly invalid floor... + mo->terrain = NULL; + return; + } + + if (mo->flags & MF_NOCLIPHEIGHT) + { + // You can't collide with floors anyway! + mo->terrain = NULL; + return; + } + + // Update the object's terrain pointer. + levelFlat = &levelflats[flatID]; + mo->terrain = K_GetTerrainForTextureName(levelFlat->name); +} + // // Parser code starts here. // +static void K_FlagBoolean(UINT32 *inputFlags, UINT32 newFlag, char *val) +{ + if (stricmp(val, "true") == 0) + { + *inputFlags |= newFlag; + } + else if (stricmp(val, "false") == 0) + { + *inputFlags &= ~newFlag; + } +} + static void K_TerrainDefaults(terrain_t *terrain) { terrain->splashID = UINT16_MAX; @@ -132,6 +177,8 @@ static void K_TerrainDefaults(terrain_t *terrain) terrain->friction = FRACUNIT; terrain->offroad = 0; terrain->damageType = -1; + terrain->trickPanel = 0; + terrain->flags = 0; } static void K_NewTerrainDefs(void) @@ -159,12 +206,24 @@ static void K_ParseTerrainParameter(UINT32 i, char *param, char *val) } else if (stricmp(param, "offroad") == 0) { - terrain->offroad = (UINT8)get_number(val); + terrain->offroad = (UINT8)get_number(val); // offroad strength enum? } else if (stricmp(param, "damageType") == 0) { terrain->damageType = (INT16)get_number(val); } + else if (stricmp(param, "trickPanel") == 0) + { + terrain->trickPanel = (UINT8)get_number(val); // trick panel strength enum? + } + else if (stricmp(param, "liquid") == 0) + { + K_FlagBoolean(&terrain->flags, TRF_LIQUID, val); + } + else if (stricmp(param, "sneakerPanel") == 0) + { + K_FlagBoolean(&terrain->flags, TRF_SNEAKERPANEL, val); + } } static boolean K_DoTERRAINLumpParse(size_t num, void (*parser)(UINT32, char *, char *)) @@ -210,14 +269,13 @@ static boolean K_TERRAINLumpParser(UINT8 *data, size_t size) while (tkn && (pos = M_GetTokenPos()) < size) { - boolean result = true; + boolean valid = true; // Avoid anything inside bracketed stuff, only look for external keywords. if (fastcmp(tkn, "{") || fastcmp(tkn, "}")) { CONS_Alert(CONS_ERROR, "Rogue bracket detected in TERRAIN lump.\n"); - Z_Free(tkn); - return false; + valid = false; } // Check for valid fields. else if (stricmp(tkn, "terrain") == 0) @@ -249,28 +307,28 @@ static boolean K_TERRAINLumpParser(UINT8 *data, size_t size) CONS_Printf("Created new Terrain type '%s'\n", t->name); } - result = K_DoTERRAINLumpParse(i, K_ParseTerrainParameter); + valid = K_DoTERRAINLumpParse(i, K_ParseTerrainParameter); } // TODO: the other block types! else { - CONS_Alert(CONS_NOTICE, "No terrain type name.\n"); + CONS_Alert(CONS_ERROR, "No terrain type name.\n"); + valid = false; } } else { - CONS_Alert(CONS_NOTICE, "Unknown field '%s' found in TERRAIN lump.\n", tkn); - Z_Free(tkn); - return false; - } - - if (result == false) - { - Z_Free(tkn); - return false; + CONS_Alert(CONS_ERROR, "Unknown field '%s' found in TERRAIN lump.\n", tkn); + valid = false; } Z_Free(tkn); + + if (valid == false) + { + return false; + } + tkn = M_GetToken(NULL); } diff --git a/src/k_terrain.h b/src/k_terrain.h index d774fa130..94db49dfb 100644 --- a/src/k_terrain.h +++ b/src/k_terrain.h @@ -14,8 +14,11 @@ #ifndef __K_TERRAIN_H__ #define __K_TERRAIN_H__ +#include "doomdata.h" +#include "doomdef.h" #include "doomtype.h" #include "m_fixed.h" +#include "p_mobj.h" #define TERRAIN_NAME_LEN 32 @@ -41,6 +44,13 @@ typedef struct t_footstep_s UINT16 sound; // Sound to play. } t_footstep_t; +typedef enum +{ + // Terrain flag values. + TRF_LIQUID = 1, // Texture water properties (wavy, slippery, etc) + TRF_SNEAKERPANEL = 1<<1 // Texture is a booster +} terrain_flags_t; + typedef struct terrain_s { // Terrain definition. @@ -57,6 +67,8 @@ typedef struct terrain_s fixed_t friction; // The default friction of this texture. UINT8 offroad; // The default offroad level of this texture. INT16 damageType; // The default damage type of this texture. (Negative means no damage). + UINT8 trickPanel; // Trick panel strength + UINT32 flags; // Flag values (see: terrain_flags_t) } terrain_t; // Arrays for all terrain definitions. @@ -78,6 +90,8 @@ terrain_t *K_GetDefaultTerrain(void); terrain_t *K_GetTerrainForTextureNum(INT32 textureNum); terrain_t *K_GetTerrainForTextureName(const char *checkName); +void K_UpdateMobjTerrain(mobj_t *mo, INT32 flatID); + void K_InitTerrain(UINT16 wadNum); #endif // __K_TERRAIN_H__ diff --git a/src/p_inter.c b/src/p_inter.c index 0a2bb4e13..e0171522e 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1061,6 +1061,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget target->flags |= MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; P_SetThingPosition(target); target->standingslope = NULL; + target->terrain = NULL; target->pmomz = 0; target->player->playerstate = PST_DEAD; diff --git a/src/p_local.h b/src/p_local.h index 61a8cf3a0..fa6e39670 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -384,6 +384,7 @@ extern camera_t *mapcampointer; extern fixed_t tmx; extern fixed_t tmy; extern pslope_t *tmfloorslope, *tmceilingslope; +extern INT32 tmfloorpic, tmceilingpic; /* cphipps 2004/08/30 */ extern void P_MapStart(void); diff --git a/src/p_map.c b/src/p_map.c index d0716790b..36ec3ef0a 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -24,12 +24,13 @@ #include "r_sky.h" #include "s_sound.h" #include "w_wad.h" + #include "k_kart.h" // SRB2kart 011617 #include "k_collide.h" #include "k_respawn.h" - #include "hu_stuff.h" // SRB2kart #include "i_system.h" // SRB2kart +#include "k_terrain.h" #include "r_splats.h" @@ -60,6 +61,7 @@ mobj_t *tmfloorthing; // the thing corresponding to tmfloorz or NULL if tmfloorz mobj_t *tmhitthing; // the solid thing you bumped into (for collisions) ffloor_t *tmfloorrover, *tmceilingrover; pslope_t *tmfloorslope, *tmceilingslope; +INT32 tmfloorpic, tmceilingpic; static fixed_t tmfloorstep; static fixed_t tmceilingstep; @@ -303,6 +305,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) } object->standingslope = NULL; // Okay, now we know it's not going to be relevant - no launching off at silly angles for you. + object->terrain = NULL; object->eflags |= MFE_SPRUNG; // apply this flag asap! spring->flags &= ~(MF_SOLID|MF_SPECIAL); // De-solidify @@ -441,6 +444,7 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object) } object->standingslope = NULL; // No launching off at silly angles for you. + object->terrain = NULL; switch (spring->type) { @@ -1427,6 +1431,7 @@ static boolean PIT_CheckThing(mobj_t *thing) tmfloorz = thing->z + thing->height; tmfloorrover = NULL; tmfloorslope = NULL; + tmfloorpic = -1; } return true; } @@ -1446,6 +1451,7 @@ static boolean PIT_CheckThing(mobj_t *thing) tmfloorz = tmceilingz = topz; // block while in air tmceilingrover = NULL; tmceilingslope = NULL; + tmceilingpic = -1; tmfloorthing = thing; // needed for side collision } else if (topz < tmceilingz && tmthing->z <= thing->z+thing->height) @@ -1453,6 +1459,7 @@ static boolean PIT_CheckThing(mobj_t *thing) tmceilingz = topz; tmceilingrover = NULL; tmceilingslope = NULL; + tmceilingpic = -1; tmfloorthing = thing; // thing we may stand on } } @@ -1468,6 +1475,7 @@ static boolean PIT_CheckThing(mobj_t *thing) tmceilingz = thing->z; tmceilingrover = NULL; tmceilingslope = NULL; + tmceilingpic = -1; } return true; } @@ -1487,6 +1495,7 @@ static boolean PIT_CheckThing(mobj_t *thing) tmfloorz = tmceilingz = topz; // block while in air tmfloorrover = NULL; tmfloorslope = NULL; + tmfloorpic = -1; tmfloorthing = thing; // needed for side collision } else if (topz > tmfloorz && tmthing->z+tmthing->height >= thing->z) @@ -1494,6 +1503,7 @@ static boolean PIT_CheckThing(mobj_t *thing) tmfloorz = topz; tmfloorrover = NULL; tmfloorslope = NULL; + tmfloorpic = -1; tmfloorthing = thing; // thing we may stand on } } @@ -1673,6 +1683,7 @@ static boolean PIT_CheckLine(line_t *ld) ceilingline = ld; tmceilingrover = openceilingrover; tmceilingslope = opentopslope; + tmceilingpic = opentoppic; tmceilingstep = openceilingstep; if (thingtop == tmthing->ceilingz) { @@ -1685,6 +1696,7 @@ static boolean PIT_CheckLine(line_t *ld) tmfloorz = openbottom; tmfloorrover = openfloorrover; tmfloorslope = openbottomslope; + tmfloorpic = openbottompic; tmfloorstep = openfloorstep; if (tmthing->z == tmthing->floorz) { @@ -1781,6 +1793,8 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) tmceilingrover = NULL; tmfloorslope = newsubsec->sector->f_slope; tmceilingslope = newsubsec->sector->c_slope; + tmfloorpic = newsubsec->sector->floorpic; + tmceilingpic = newsubsec->sector->ceilingpic; tmfloorstep = 0; tmceilingstep = 0; @@ -1834,6 +1848,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) tmfloorz = topheight - sinklevel; tmfloorrover = rover; tmfloorslope = *rover->t_slope; + tmfloorpic = *rover->toppic; } } else if (thing->eflags & MFE_VERTICALFLIP && thingtop <= bottomheight + sinklevel && thing->momz >= 0) @@ -1842,6 +1857,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) tmceilingz = bottomheight + sinklevel; tmceilingrover = rover; tmceilingslope = *rover->b_slope; + tmceilingpic = *rover->bottompic; } } } @@ -1865,6 +1881,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) tmfloorz = thing->z; tmfloorrover = rover; tmfloorslope = NULL; + tmfloorpic = *rover->toppic; } } // Quicksand blocks never change heights otherwise. @@ -1882,6 +1899,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) tmfloorz = tmdropoffz = topheight; tmfloorrover = rover; tmfloorslope = *rover->t_slope; + tmfloorpic = *rover->toppic; } if (bottomheight < tmceilingz && abs(delta1) >= abs(delta2) && !(rover->flags & FF_PLATFORM) @@ -1890,6 +1908,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) tmceilingz = tmdrpoffceilz = bottomheight; tmceilingrover = rover; tmceilingslope = *rover->b_slope; + tmceilingpic = *rover->bottompic; } } } @@ -1964,12 +1983,14 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) tmfloorz = tmdropoffz = polytop; tmfloorslope = NULL; tmfloorrover = NULL; + tmfloorpic = polysec->ceilingpic; } if (polybottom < tmceilingz && abs(delta1) >= abs(delta2)) { tmceilingz = tmdrpoffceilz = polybottom; tmceilingslope = NULL; tmceilingrover = NULL; + tmceilingpic = polysec->floorpic; } } plink = (polymaplink_t *)(plink->link.next); @@ -2387,6 +2408,8 @@ boolean PIT_PushableMoved(mobj_t *thing) ffloor_t *oldceilrover = tmceilingrover; pslope_t *oldfslope = tmfloorslope; pslope_t *oldcslope = tmceilingslope; + INT32 oldfpic = tmfloorpic; + INT32 oldcpic = tmceilingpic; // Move the player P_TryMove(thing, thing->x+stand->momx, thing->y+stand->momy, true); @@ -2403,6 +2426,8 @@ boolean PIT_PushableMoved(mobj_t *thing) tmceilingrover = oldceilrover; tmfloorslope = oldfslope; tmceilingslope = oldcslope; + tmfloorpic = oldfpic; + tmceilingpic = oldcpic; thing->momz = stand->momz; } else @@ -2616,9 +2641,14 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (!(thing->flags & MF_NOCLIPHEIGHT)) { // Assign thing's standingslope if needed - if (thing->z <= tmfloorz && !(thing->eflags & MFE_VERTICALFLIP)) { + if (thing->z <= tmfloorz && !(thing->eflags & MFE_VERTICALFLIP)) + { + K_UpdateMobjTerrain(thing, tmfloorpic); + if (!startingonground && tmfloorslope) + { P_HandleSlopeLanding(thing, tmfloorslope); + } if (thing->momz <= 0) { @@ -2626,12 +2656,19 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) P_SetPitchRollFromSlope(thing, thing->standingslope); if (thing->momz == 0 && thing->player && !startingonground) + { P_PlayerHitFloor(thing->player, true); + } } } - else if (thing->z+thing->height >= tmceilingz && (thing->eflags & MFE_VERTICALFLIP)) { + else if (thing->z+thing->height >= tmceilingz && (thing->eflags & MFE_VERTICALFLIP)) + { + K_UpdateMobjTerrain(thing, tmceilingpic); + if (!startingonground && tmceilingslope) + { P_HandleSlopeLanding(thing, tmceilingslope); + } if (thing->momz >= 0) { @@ -2639,12 +2676,18 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) P_SetPitchRollFromSlope(thing, thing->standingslope); if (thing->momz == 0 && thing->player && !startingonground) + { P_PlayerHitFloor(thing->player, true); + } } } } - else // don't set standingslope if you're not going to clip against it + else + { + // don't set standingslope if you're not going to clip against it thing->standingslope = NULL; + thing->terrain = NULL; + } /* FIXME: slope step down (even up) has some false positives, so just ignore them entirely. */ diff --git a/src/p_maputl.c b/src/p_maputl.c index 2e21f5ee3..e30c0e0da 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -342,6 +342,7 @@ fixed_t openceilingstep; fixed_t openceilingdrop; fixed_t openfloorstep; fixed_t openfloordrop; +INT32 opentoppic, openbottompic; // P_CameraLineOpening // P_LineOpening, but for camera @@ -537,6 +538,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) highceiling = INT32_MIN; lowfloor = INT32_MAX; opentopslope = openbottomslope = NULL; + opentoppic = openbottompic = -1; openceilingstep = 0; openceilingdrop = 0; openfloorstep = 0; @@ -556,6 +558,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) opentop = height[lo]; highceiling = height[hi]; opentopslope = sector[lo]->c_slope; + opentoppic = sector[lo]->ceilingpic; if (mobj) { @@ -575,6 +578,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) openbottom = height[hi]; lowfloor = height[lo]; openbottomslope = sector[hi]->f_slope; + openbottompic = sector[hi]->floorpic; if (mobj) { @@ -747,6 +751,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (bottomheight < open[FRONT].top) { open[FRONT].top = bottomheight; opentopslope = *rover->b_slope; + opentoppic = *rover->bottompic; open[FRONT].ceilingrover = rover; } else if (bottomheight < highceiling) @@ -758,6 +763,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (topheight > open[FRONT].bottom) { open[FRONT].bottom = topheight; openbottomslope = *rover->t_slope; + openbottompic = *rover->toppic; open[FRONT].floorrover = rover; } else if (topheight > lowfloor) @@ -789,6 +795,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (bottomheight < open[BACK].top) { open[BACK].top = bottomheight; opentopslope = *rover->b_slope; + opentoppic = *rover->bottompic; open[BACK].ceilingrover = rover; } else if (bottomheight < highceiling) @@ -800,6 +807,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (topheight > open[BACK].bottom) { open[BACK].bottom = topheight; openbottomslope = *rover->t_slope; + openbottompic = *rover->toppic; open[BACK].floorrover = rover; } else if (topheight > lowfloor) diff --git a/src/p_maputl.h b/src/p_maputl.h index 6f0c1f8ad..43a7fb507 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -63,6 +63,7 @@ extern fixed_t openceilingstep; extern fixed_t openceilingdrop; extern fixed_t openfloorstep; extern fixed_t openfloordrop; +extern INT32 opentoppic, openbottompic; void P_LineOpening(line_t *plinedef, mobj_t *mobj); diff --git a/src/p_mobj.c b/src/p_mobj.c index b066e2a1c..46394dd24 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -40,6 +40,7 @@ #include "k_color.h" #include "k_respawn.h" #include "k_bot.h" +#include "k_terrain.h" static CV_PossibleValue_t CV_BobSpeed[] = {{0, "MIN"}, {4*FRACUNIT, "MAX"}, {0, NULL}}; consvar_t cv_movebob = CVAR_INIT ("movebob", "1.0", CV_FLOAT|CV_SAVE, CV_BobSpeed, NULL); @@ -1505,7 +1506,10 @@ void P_XYMovement(mobj_t *mo) oldy = mo->y; if (mo->flags & MF_NOCLIPHEIGHT) + { mo->standingslope = NULL; + mo->terrain = NULL; + } // adjust various things based on slope if (mo->standingslope && abs(mo->standingslope->zdelta) > FRACUNIT>>8) { @@ -1671,6 +1675,7 @@ void P_XYMovement(mobj_t *mo) { mo->momz = transfermomz; mo->standingslope = NULL; + mo->terrain = NULL; P_SetPitchRoll(mo, ANGLE_90, transferslope->xydirection + (transferslope->zangle @@ -1782,6 +1787,7 @@ void P_XYMovement(mobj_t *mo) mo->momz = P_MobjFlip(mo)*FRACUNIT/2; mo->z = predictedz + P_MobjFlip(mo); mo->standingslope = NULL; + mo->terrain = NULL; //CONS_Printf("Launched off of flat surface running into downward slope\n"); } } @@ -2274,6 +2280,8 @@ boolean P_ZMovement(mobj_t *mo) } P_CheckPosition(mo, mo->x, mo->y); // Sets mo->standingslope correctly + K_UpdateMobjTerrain(mo, ((mo->eflags & MFE_VERTICALFLIP) ? tmceilingpic : tmfloorpic)); + if (((mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope) && (mo->type != MT_STEAM)) { mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope; @@ -2503,12 +2511,17 @@ boolean P_ZMovement(mobj_t *mo) if (mo->type == MT_STEAM) return true; } - else if (!(mo->flags & MF_NOGRAVITY)) // Gravity here! + else { - /// \todo may not be needed (done in P_MobjThinker normally) - mo->eflags &= ~MFE_JUSTHITFLOOR; + mo->terrain = NULL; - P_CheckGravity(mo, true); + if (!(mo->flags & MF_NOGRAVITY)) // Gravity here! + { + /// \todo may not be needed (done in P_MobjThinker normally) + mo->eflags &= ~MFE_JUSTHITFLOOR; + + P_CheckGravity(mo, true); + } } if (((mo->z + mo->height > mo->ceilingz && !(mo->eflags & MFE_VERTICALFLIP)) @@ -2712,20 +2725,29 @@ void P_PlayerZMovement(mobj_t *mo) if (onground && !(mo->flags & MF_NOCLIPHEIGHT)) { if (mo->eflags & MFE_VERTICALFLIP) + { mo->z = mo->ceilingz - mo->height; + } else + { mo->z = mo->floorz; + } + + K_UpdateMobjTerrain(mo, (mo->eflags & MFE_VERTICALFLIP ? tmceilingpic : tmfloorpic)); // Get up if you fell. if (mo->player->panim == PA_HURT && mo->player->spinouttimer == 0 && mo->player->tumbleBounces == 0) + { P_SetPlayerMobjState(mo, S_KART_STILL); + } - if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)) { + if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)) + { // Handle landing on slope during Z movement P_HandleSlopeLanding(mo, (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)); } - if (P_MobjFlip(mo)*mo->momz < 0) // falling + if (P_MobjFlip(mo) * mo->momz < 0) // falling { boolean clipmomz = !(P_CheckDeathPitCollide(mo)); @@ -2736,29 +2758,38 @@ void P_PlayerZMovement(mobj_t *mo) P_PlayerPolyObjectZMovement(mo); if (clipmomz) + { mo->momz = (tmfloorthing ? tmfloorthing->momz : 0); + } } else if (tmfloorthing) - mo->momz = tmfloorthing->momz; - } - else if (!(mo->flags & MF_NOGRAVITY)) // Gravity here! - { - if (P_IsObjectInGoop(mo) && !(mo->flags & MF_NOCLIPHEIGHT)) { - if (mo->z < mo->floorz) - { - mo->z = mo->floorz; - mo->momz = 0; - } - else if (mo->z + mo->height > mo->ceilingz) - { - mo->z = mo->ceilingz - mo->height; - mo->momz = 0; - } + mo->momz = tmfloorthing->momz; + } + } + else + { + mo->terrain = NULL; + + if (!(mo->flags & MF_NOGRAVITY)) // Gravity here! + { + if (P_IsObjectInGoop(mo) && !(mo->flags & MF_NOCLIPHEIGHT)) + { + if (mo->z < mo->floorz) + { + mo->z = mo->floorz; + mo->momz = 0; + } + else if (mo->z + mo->height > mo->ceilingz) + { + mo->z = mo->ceilingz - mo->height; + mo->momz = 0; + } + } + /// \todo may not be needed (done in P_MobjThinker normally) + mo->eflags &= ~MFE_JUSTHITFLOOR; + P_CheckGravity(mo, true); } - /// \todo may not be needed (done in P_MobjThinker normally) - mo->eflags &= ~MFE_JUSTHITFLOOR; - P_CheckGravity(mo, true); } if (((mo->eflags & MFE_VERTICALFLIP && mo->z < mo->floorz) || (!(mo->eflags & MFE_VERTICALFLIP) && mo->z + mo->height > mo->ceilingz)) diff --git a/src/p_mobj.h b/src/p_mobj.h index 2373bdca4..9d73c433b 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -395,6 +395,7 @@ typedef struct mobj_s fixed_t sprxoff, spryoff, sprzoff; // Sprite offsets in real space, does NOT affect position or collision + struct terrain_s *terrain; // Terrain definition of the floor this object last hit. NULL when in the air. INT32 hitlag; // Sal-style hit lag, straight from Captain Fetch's jowls // WARNING: New fields must be added separately to savegame and Lua. diff --git a/src/p_slopes.c b/src/p_slopes.c index 1bde8f4ee..6c660ad0f 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -850,6 +850,7 @@ void P_SlopeLaunch(mobj_t *mo) //CONS_Printf("Launched off of slope.\n"); mo->standingslope = NULL; + mo->terrain = NULL; if (mo->player) { From 53d777788a258aaffb3a174a3af565ca38d81c14 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 9 Dec 2021 01:21:34 -0500 Subject: [PATCH 04/69] Friction value is used, implemented DefaultTerrain --- src/k_terrain.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++ src/k_terrain.h | 1 + src/p_mobj.c | 2 +- 3 files changed, 91 insertions(+), 1 deletion(-) diff --git a/src/k_terrain.c b/src/k_terrain.c index fabc89882..4928281b1 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -153,6 +153,58 @@ void K_UpdateMobjTerrain(mobj_t *mo, INT32 flatID) mo->terrain = K_GetTerrainForTextureName(levelFlat->name); } +void K_SetDefaultFriction(mobj_t *mo) +{ + mo->friction = ORIG_FRICTION; + + if (mo->player != NULL) + { + mo->movefactor = FRACUNIT; + } + + if (mo->terrain != NULL) + { + fixed_t strength = mo->terrain->friction; + + fixed_t newFriction = INT32_MAX; + fixed_t newMovefactor = INT32_MAX; + + if (strength > 0) // sludge + { + strength = strength*2; // otherwise, the maximum sludginess value is +967... + } + + // The following might seem odd. At the time of movement, + // the move distance is multiplied by 'friction/0x10000', so a + // higher friction value actually means 'less friction'. + newFriction = ORIG_FRICTION - FixedMul(0x1EB8, strength) / 0x80; // ORIG_FRICTION is 0xE800 + + if (newFriction > FRACUNIT) + { + newFriction = FRACUNIT; + } + + if (newFriction < 0) + { + newFriction = 0; + } + + newMovefactor = FixedDiv(ORIG_FRICTION, newFriction); + + if (newMovefactor < FRACUNIT) + { + newMovefactor = 19*newMovefactor - 18*FRACUNIT; + } + else + { + newMovefactor = FRACUNIT; + } + + mo->friction = newFriction; + mo->movefactor = newMovefactor; + } +} + // // Parser code starts here. // @@ -316,6 +368,43 @@ static boolean K_TERRAINLumpParser(UINT8 *data, size_t size) valid = false; } } + else if (stricmp(tkn, "defaultTerrain") == 0) + { + Z_Free(tkn); + tkn = M_GetToken(NULL); + pos = M_GetTokenPos(); + + if (tkn && pos < size) + { + terrain_t *t = NULL; + + for (i = 0; i < numTerrainDefs; i++) + { + t = &terrainDefs[i]; + + if (stricmp(tkn, t->name) == 0) + { + break; + } + } + + if (i == numTerrainDefs) + { + CONS_Alert(CONS_ERROR, "Invalid DefaultTerrain type.\n"); + valid = false; + } + else + { + defaultTerrain = i; + } + } + // TODO: the other block types! + else + { + CONS_Alert(CONS_ERROR, "No DefaultTerrain type.\n"); + valid = false; + } + } else { CONS_Alert(CONS_ERROR, "Unknown field '%s' found in TERRAIN lump.\n", tkn); diff --git a/src/k_terrain.h b/src/k_terrain.h index 94db49dfb..5660c0d4b 100644 --- a/src/k_terrain.h +++ b/src/k_terrain.h @@ -91,6 +91,7 @@ terrain_t *K_GetTerrainForTextureNum(INT32 textureNum); terrain_t *K_GetTerrainForTextureName(const char *checkName); void K_UpdateMobjTerrain(mobj_t *mo, INT32 flatID); +void K_SetDefaultFriction(mobj_t *mo); void K_InitTerrain(UINT16 wadNum); diff --git a/src/p_mobj.c b/src/p_mobj.c index 46394dd24..87ea3d9b5 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1341,7 +1341,7 @@ static void P_XYFriction(mobj_t *mo, fixed_t oldx, fixed_t oldy) mo->momy = FixedMul(mo->momy, mo->friction); } - mo->friction = ORIG_FRICTION; + K_SetDefaultFriction(mo); } } else From f7834054a5c0da760093a24c265b5f327564b6df Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 9 Dec 2021 01:55:29 -0500 Subject: [PATCH 05/69] You can now link terrain to textures --- src/k_terrain.c | 128 ++++++++++++++++++++++++++++++++++++++---------- src/k_terrain.h | 21 ++++++-- 2 files changed, 119 insertions(+), 30 deletions(-) diff --git a/src/k_terrain.c b/src/k_terrain.c index 4928281b1..a2b09158d 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -34,6 +34,9 @@ UINT16 numFootstepDefs = 0; terrain_t *terrainDefs = NULL; UINT16 numTerrainDefs = 0; +t_floor_t *terrainFloorDefs = NULL; +UINT16 numTerrainFloorDefs = 0; + UINT16 defaultTerrain = UINT16_MAX; terrain_t *K_GetTerrainByIndex(UINT16 checkIndex) @@ -76,16 +79,11 @@ terrain_t *K_GetDefaultTerrain(void) return K_GetTerrainByIndex(defaultTerrain); } -terrain_t *K_GetTerrainForTextureNum(INT32 textureNum) +terrain_t *K_GetTerrainForTextureName(const char *checkName) { INT32 i; - if (textureNum == -1) - { - return NULL; - } - - if (numTerrainDefs == 0) + if (numTerrainFloorDefs == 0) { return NULL; } @@ -93,24 +91,13 @@ terrain_t *K_GetTerrainForTextureNum(INT32 textureNum) // Search backwards through all terrain definitions. // The latest one will have priority over the older one. - for (i = numTerrainDefs-1; i >= 0; i--) + for (i = 0; i < numTerrainFloorDefs; i++) { - terrain_t *t = &terrainDefs[i]; - size_t j; + t_floor_t *f = &terrainFloorDefs[i]; - if (t->numTextureIDs == 0) + if (stricmp(checkName, f->textureName) == 0) { - // No textures are applied to this terrain type. - continue; - } - - for (j = 0; j < t->numTextureIDs; j++) - { - if (textureNum == t->textureIDs[j]) - { - // Texture matches. - return t; - } + return K_GetTerrainByIndex(f->terrainID); } } @@ -119,9 +106,17 @@ terrain_t *K_GetTerrainForTextureNum(INT32 textureNum) return K_GetDefaultTerrain(); } -terrain_t *K_GetTerrainForTextureName(const char *checkName) +terrain_t *K_GetTerrainForTextureNum(INT32 textureNum) { - return K_GetTerrainForTextureNum( R_CheckTextureNumForName(checkName) ); + texture_t *tex = NULL; + + if (textureNum < 0 || textureNum >= numtextures) + { + return NULL; + } + + tex = textures[textureNum]; + return K_GetTerrainForTextureName(tex->name); } void K_UpdateMobjTerrain(mobj_t *mo, INT32 flatID) @@ -278,6 +273,12 @@ static void K_ParseTerrainParameter(UINT32 i, char *param, char *val) } } +static void K_NewTerrainFloorDefs(void) +{ + numTerrainFloorDefs++; + terrainFloorDefs = (t_floor_t *)Z_Realloc(terrainFloorDefs, sizeof(t_floor_t) * (numTerrainFloorDefs + 1), PU_STATIC, NULL); +} + static boolean K_DoTERRAINLumpParse(size_t num, void (*parser)(UINT32, char *, char *)) { char *param, *val; @@ -361,13 +362,88 @@ static boolean K_TERRAINLumpParser(UINT8 *data, size_t size) valid = K_DoTERRAINLumpParse(i, K_ParseTerrainParameter); } - // TODO: the other block types! else { CONS_Alert(CONS_ERROR, "No terrain type name.\n"); valid = false; } } + else if (stricmp(tkn, "floor") == 0) + { + Z_Free(tkn); + tkn = M_GetToken(NULL); + pos = M_GetTokenPos(); + + if (tkn && pos < size) + { + if (stricmp(tkn, "optional") == 0) + { + // "optional" is ZDoom syntax + // We don't use it, but we can ignore it. + Z_Free(tkn); + tkn = M_GetToken(NULL); + pos = M_GetTokenPos(); + } + + if (tkn && pos < size) + { + t_floor_t *f = NULL; + + for (i = 0; i < numTerrainFloorDefs; i++) + { + f = &terrainFloorDefs[i]; + + if (stricmp(tkn, f->textureName) == 0) + { + break; + } + } + + if (i == numTerrainFloorDefs) + { + K_NewTerrainFloorDefs(); + f = &terrainFloorDefs[i]; + + strncpy(f->textureName, tkn, 9); + } + + Z_Free(tkn); + tkn = M_GetToken(NULL); + pos = M_GetTokenPos(); + + if (tkn && pos < size) + { + terrain_t *t = K_GetTerrainByName(tkn); + + if (t == NULL) + { + CONS_Alert(CONS_ERROR, "Invalid Terrain type '%s'.\n", tkn); + valid = false; + } + else + { + f->terrainID = (t - terrainDefs); + CONS_Printf("Texture '%s' set to Terrain '%s'\n", f->textureName, tkn); + } + } + else + { + CONS_Alert(CONS_ERROR, "No terrain for floor definition.\n"); + valid = false; + } + } + else + { + CONS_Alert(CONS_ERROR, "No texture for floor definition.\n"); + valid = false; + } + } + else + { + CONS_Alert(CONS_ERROR, "No texture for floor definition.\n"); + valid = false; + } + } else if (stricmp(tkn, "defaultTerrain") == 0) { Z_Free(tkn); @@ -398,13 +474,13 @@ static boolean K_TERRAINLumpParser(UINT8 *data, size_t size) defaultTerrain = i; } } - // TODO: the other block types! else { CONS_Alert(CONS_ERROR, "No DefaultTerrain type.\n"); valid = false; } } + // TODO: splash & footstep blocks else { CONS_Alert(CONS_ERROR, "Unknown field '%s' found in TERRAIN lump.\n", tkn); diff --git a/src/k_terrain.h b/src/k_terrain.h index 5660c0d4b..e42a2ada2 100644 --- a/src/k_terrain.h +++ b/src/k_terrain.h @@ -58,9 +58,6 @@ typedef struct terrain_s char name[TERRAIN_NAME_LEN]; // Lookup name. - INT32 *textureIDs; // Texture nums this terrain applies to. (Doesn't support flats, stop using them already.) - UINT32 numTextureIDs; // Length of the above table. - UINT16 splashID; // Splash defintion ID. UINT16 footstepID; // Footstep defintion ID. @@ -71,6 +68,19 @@ typedef struct terrain_s UINT32 flags; // Flag values (see: terrain_flags_t) } terrain_t; +typedef struct t_floor_s +{ + // Terrain floor definition. + // Ties texture names to a . + + // (Could be optimized by using texture IDs instead of names, + // but was concerned because I recall sooomething about those not being netsafe? + // Someone confirm if I just hallucinated that. :V) + + char textureName[9]; // Floor texture name. + UINT16 terrainID; // Terrain definition ID. +} t_floor_t; + // Arrays for all terrain definitions. extern t_splash_t *splashDefs; extern UINT16 numSplashDefs; @@ -81,14 +91,17 @@ extern UINT16 numFootstepDefs; extern terrain_t *terrainDefs; extern UINT16 numTerrainDefs; +extern t_floor_t *terrainFloorDefs; +extern UINT16 numTerrainFloorDefs; + // Default terrain definition ID. extern UINT16 defaultTerrain; terrain_t *K_GetTerrainByIndex(UINT16 checkIndex); terrain_t *K_GetTerrainByName(const char *checkName); terrain_t *K_GetDefaultTerrain(void); -terrain_t *K_GetTerrainForTextureNum(INT32 textureNum); terrain_t *K_GetTerrainForTextureName(const char *checkName); +terrain_t *K_GetTerrainForTextureNum(INT32 textureNum); void K_UpdateMobjTerrain(mobj_t *mo, INT32 flatID); void K_SetDefaultFriction(mobj_t *mo); From d7a8ec9fbde39a86187032d25323de703f799b65 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 9 Dec 2021 02:37:44 -0500 Subject: [PATCH 06/69] Liquid terrain functions --- src/p_mobj.c | 119 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 92 insertions(+), 27 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 87ea3d9b5..8bbd90f51 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3042,27 +3042,78 @@ void P_MobjCheckWater(mobj_t *mobj) } } + if (mobj->terrain != NULL) + { + if (mobj->terrain->flags & TRF_LIQUID) + { + // This floor is water. + mobj->eflags |= MFE_TOUCHWATER; + + if (mobj->eflags & MFE_VERTICALFLIP) + { + mobj->watertop = thingtop + height; + mobj->waterbottom = thingtop; + } + else + { + mobj->watertop = mobj->z; + mobj->waterbottom = mobj->z - height; + } + } + } + // Spectators and dead players don't get to do any of the things after this. if (p && (p->spectator || p->playerstate != PST_LIVE)) + { return; + } // The rest of this code only executes on a water state change. if (waterwasnotset || !!(mobj->eflags & MFE_UNDERWATER) == wasinwater) + { return; + } if ((p) // Players || (mobj->flags & MF_PUSHABLE) // Pushables || ((mobj->info->flags & MF_PUSHABLE) && mobj->fuse) // Previously pushable, might be moving still ) { + fixed_t waterZ = INT32_MAX; + fixed_t solidZ = INT32_MAX; + fixed_t diff = INT32_MAX; + + fixed_t thingZ = INT32_MAX; + boolean splashValid = false; + + if (mobj->eflags & MFE_VERTICALFLIP) + { + waterZ = mobj->waterbottom; + solidZ = mobj->ceilingz; + } + else + { + waterZ = mobj->watertop; + solidZ = mobj->floorz; + } + + diff = waterZ - solidZ; + if (mobj->eflags & MFE_VERTICALFLIP) + { + diff = -diff; + } + // Check to make sure you didn't just cross into a sector to jump out of // that has shallower water than the block you were originally in. - if ((!(mobj->eflags & MFE_VERTICALFLIP) && mobj->watertop-mobj->floorz <= height>>1) - || ((mobj->eflags & MFE_VERTICALFLIP) && mobj->ceilingz-mobj->waterbottom <= height>>1)) + if (diff <= (height >> 1)) + { return; + } - if (mobj->eflags & MFE_GOOWATER || wasingoo) { // Decide what happens to your momentum when you enter/leave goopy water. - if (P_MobjFlip(mobj)*mobj->momz > 0) + if (mobj->eflags & MFE_GOOWATER || wasingoo) + { + // Decide what happens to your momentum when you enter/leave goopy water. + if (P_MobjFlip(mobj) * mobj->momz > 0) { mobj->momz -= (mobj->momz/8); // cut momentum a little bit to prevent multiple bobs //CONS_Printf("leaving\n"); @@ -3074,25 +3125,42 @@ void P_MobjCheckWater(mobj_t *mobj) //CONS_Printf("entering\n"); } } - else if (wasinwater && P_MobjFlip(mobj)*mobj->momz > 0) - mobj->momz = FixedMul(mobj->momz, FixedDiv(780*FRACUNIT, 457*FRACUNIT)); // Give the mobj a little out-of-water boost. - - if (P_MobjFlip(mobj)*mobj->momz < 0) + else if (wasinwater && P_MobjFlip(mobj) * mobj->momz > 0) { - if ((mobj->eflags & MFE_VERTICALFLIP && thingtop-(height>>1)-mobj->momz <= mobj->waterbottom) - || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z+(height>>1)-mobj->momz >= mobj->watertop)) + // Give the mobj a little out-of-water boost. + mobj->momz = FixedMul(mobj->momz, FixedDiv(780*FRACUNIT, 457*FRACUNIT)); + } + + if (mobj->eflags & MFE_VERTICALFLIP) + { + thingZ = thingtop - (height >> 1); + splashValid = (thingZ - mobj->momz <= waterZ); + } + else + { + thingZ = mobj->z + (height >> 1); + splashValid = (thingZ - mobj->momz >= waterZ); + } + + if (P_MobjFlip(mobj) * mobj->momz <= 0) + { + if (splashValid == true) { // Spawn a splash mobj_t *splish; mobjtype_t splishtype = (mobj->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH; + if (mobj->eflags & MFE_VERTICALFLIP) { - splish = P_SpawnMobj(mobj->x, mobj->y, mobj->waterbottom-FixedMul(mobjinfo[splishtype].height, mobj->scale), splishtype); + splish = P_SpawnMobj(mobj->x, mobj->y, waterZ - FixedMul(mobjinfo[splishtype].height, mobj->scale), splishtype); splish->flags2 |= MF2_OBJECTFLIP; splish->eflags |= MFE_VERTICALFLIP; } else - splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, splishtype); + { + splish = P_SpawnMobj(mobj->x, mobj->y, waterZ, splishtype); + } + splish->destscale = mobj->scale; P_SetScale(splish, mobj->scale); } @@ -3101,40 +3169,37 @@ void P_MobjCheckWater(mobj_t *mobj) if (p && p->waterskip < 2 && ((p->speed/3 > abs(mobj->momz)) // Going more forward than horizontal, so you can skip across the water. || (p->speed > 20*mapobjectscale && p->waterskip)) // Already skipped once, so you can skip once more! - && ((!(mobj->eflags & MFE_VERTICALFLIP) && thingtop - mobj->momz > mobj->watertop) - || ((mobj->eflags & MFE_VERTICALFLIP) && mobj->z - mobj->momz < mobj->waterbottom))) + && (splashValid == true)) { - const fixed_t hop = 5<scale; mobj->momx = (4*mobj->momx)/5; mobj->momy = (4*mobj->momy)/5; - - if (mobj->eflags & MFE_VERTICALFLIP) - mobj->momz = FixedMul(-hop, mobj->scale); - else - mobj->momz = FixedMul(hop, mobj->scale); + mobj->momz = hop * P_MobjFlip(mobj); p->waterskip++; } } - else if (P_MobjFlip(mobj)*mobj->momz > 0) + else if (P_MobjFlip(mobj) * mobj->momz > 0) { - if (((mobj->eflags & MFE_VERTICALFLIP && thingtop-(height>>1)-mobj->momz > mobj->waterbottom) - || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z+(height>>1)-mobj->momz < mobj->watertop)) - && !(mobj->eflags & MFE_UNDERWATER)) // underwater check to prevent splashes on opposite side + if (splashValid == true && !(mobj->eflags & MFE_UNDERWATER)) // underwater check to prevent splashes on opposite side { // Spawn a splash mobj_t *splish; mobjtype_t splishtype = (mobj->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH; + if (mobj->eflags & MFE_VERTICALFLIP) { - splish = P_SpawnMobj(mobj->x, mobj->y, mobj->waterbottom-FixedMul(mobjinfo[splishtype].height, mobj->scale), splishtype); + splish = P_SpawnMobj(mobj->x, mobj->y, waterZ - FixedMul(mobjinfo[splishtype].height, mobj->scale), splishtype); splish->flags2 |= MF2_OBJECTFLIP; splish->eflags |= MFE_VERTICALFLIP; } else - splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, splishtype); + { + splish = P_SpawnMobj(mobj->x, mobj->y, waterZ, splishtype); + } + splish->destscale = mobj->scale; P_SetScale(splish, mobj->scale); } @@ -3155,7 +3220,7 @@ void P_MobjCheckWater(mobj_t *mobj) else S_StartSound(mobj, sfx_splish); // And make a sound! - bubblecount = FixedDiv(abs(mobj->momz), mobj->scale)>>(FRACBITS-1); + bubblecount = FixedDiv(abs(mobj->momz), mobj->scale) >> (FRACBITS-1); // Max bubble count if (bubblecount > 128) bubblecount = 128; From e212f947adc729a1ee38708936436ec63ad78a8b Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 9 Dec 2021 03:20:45 -0500 Subject: [PATCH 07/69] Implement the sector special-like effects Offroad, sneaker panels, trick panels, and damaging floors can now be set via terrain. --- src/k_kart.c | 14 ++++++- src/k_terrain.c | 99 ++++++++++++++++++++++++++++++++++++++++++++----- src/k_terrain.h | 2 + src/p_spec.c | 4 ++ src/r_bsp.c | 32 ++++++++++++++-- 5 files changed, 137 insertions(+), 14 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index cf51e3646..e880181e5 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -33,6 +33,7 @@ #include "k_waypoint.h" #include "k_bot.h" #include "k_hud.h" +#include "k_terrain.h" // SOME IMPORTANT VARIABLES DEFINED IN DOOMDEF.H: // gamespeed is cc (0 for easy, 1 for normal, 2 for hard) @@ -1605,6 +1606,7 @@ static UINT8 K_CheckOffroadCollide(mobj_t *mo) } } + return 0; // couldn't find any offroad } @@ -1616,7 +1618,17 @@ static UINT8 K_CheckOffroadCollide(mobj_t *mo) */ static void K_UpdateOffroad(player_t *player) { - fixed_t offroadstrength = (K_CheckOffroadCollide(player->mo) << FRACBITS); + terrain_t *terrain = player->mo->terrain; + fixed_t offroadstrength = 0; + + if (terrain != NULL && terrain->offroad > 0) + { + offroadstrength = (terrain->offroad << FRACBITS); + } + else + { + offroadstrength = (K_CheckOffroadCollide(player->mo) << FRACBITS); + } // If you are in offroad, a timer starts. if (offroadstrength) diff --git a/src/k_terrain.c b/src/k_terrain.c index a2b09158d..b8edebf03 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -25,6 +25,8 @@ #include "w_wad.h" #include "z_zone.h" +#include "k_kart.h" // on the chopping block... + t_splash_t *splashDefs = NULL; UINT16 numSplashDefs = 0; @@ -119,20 +121,25 @@ terrain_t *K_GetTerrainForTextureNum(INT32 textureNum) return K_GetTerrainForTextureName(tex->name); } -void K_UpdateMobjTerrain(mobj_t *mo, INT32 flatID) +terrain_t *K_GetTerrainForFlatNum(INT32 flatID) { levelflat_t *levelFlat = NULL; - if (mo == NULL || P_MobjWasRemoved(mo) == true) - { - // Invalid object. - return; - } - if (flatID < 0 || flatID >= (signed)numlevelflats) { // Clearly invalid floor... - mo->terrain = NULL; + return NULL; + } + + levelFlat = &levelflats[flatID]; + return K_GetTerrainForTextureName(levelFlat->name); +} + +void K_UpdateMobjTerrain(mobj_t *mo, INT32 flatID) +{ + if (mo == NULL || P_MobjWasRemoved(mo) == true) + { + // Invalid object. return; } @@ -144,12 +151,84 @@ void K_UpdateMobjTerrain(mobj_t *mo, INT32 flatID) } // Update the object's terrain pointer. - levelFlat = &levelflats[flatID]; - mo->terrain = K_GetTerrainForTextureName(levelFlat->name); + mo->terrain = K_GetTerrainForFlatNum(flatID); +} + +void K_ProcessTerrainEffect(mobj_t *mo) +{ + player_t *player = NULL; + terrain_t *terrain = NULL; + + if (mo == NULL || P_MobjWasRemoved(mo) == true) + { + // Invalid object. + return; + } + + if (mo->terrain == NULL) + { + // No terrain type. + return; + } + + terrain = mo->terrain; + player = mo->player; + + if (player == NULL) + { + // maybe can support regualar mobjs later? :) + return; + } + + // Damage effects + if (terrain->damageType > 0) + { + UINT8 dmg = (terrain->damageType & 0xFF); + P_DamageMobj(mo, NULL, NULL, 1, dmg); + } + + // Sneaker panel + if (terrain->flags & TRF_SNEAKERPANEL) + { + if (!player->floorboost) + player->floorboost = 3; + else + player->floorboost = 2; + + K_DoSneaker(player, 0); + } + + // Trick panel + if (terrain->trickPanel > 0 && !(mo->eflags & MFE_SPRUNG)) + { + const fixed_t hscale = mapobjectscale + (mapobjectscale - mo->scale); + const fixed_t minspeed = 24*hscale; + fixed_t speed = FixedHypot(mo->momx, mo->momy); + fixed_t upwards = 16 * FRACUNIT * terrain->trickPanel; + + player->trickpanel = 1; + player->pflags |= PF_TRICKDELAY; + K_DoPogoSpring(mo, upwards, 1); + + if (speed < minspeed) + { + speed = minspeed; + } + + P_InstaThrust(mo, mo->angle, speed); + } + + // (Offroad is handled elsewhere!) } void K_SetDefaultFriction(mobj_t *mo) { + if (mo == NULL || P_MobjWasRemoved(mo) == true) + { + // Invalid object. + return; + } + mo->friction = ORIG_FRICTION; if (mo->player != NULL) diff --git a/src/k_terrain.h b/src/k_terrain.h index e42a2ada2..600656522 100644 --- a/src/k_terrain.h +++ b/src/k_terrain.h @@ -102,8 +102,10 @@ terrain_t *K_GetTerrainByName(const char *checkName); terrain_t *K_GetDefaultTerrain(void); terrain_t *K_GetTerrainForTextureName(const char *checkName); terrain_t *K_GetTerrainForTextureNum(INT32 textureNum); +terrain_t *K_GetTerrainForFlatNum(INT32 flatID); void K_UpdateMobjTerrain(mobj_t *mo, INT32 flatID); +void K_ProcessTerrainEffect(mobj_t *mo); void K_SetDefaultFriction(mobj_t *mo); void K_InitTerrain(UINT16 wadNum); diff --git a/src/p_spec.c b/src/p_spec.c index 07825759c..db615fb4f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -43,6 +43,7 @@ #include "k_kart.h" #include "console.h" // CON_LogMessage #include "k_respawn.h" +#include "k_terrain.h" #ifdef HW3SOUND #include "hardware/hw3sound.h" @@ -4333,7 +4334,9 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers // Conveyor stuff if (section3 == 2 || section3 == 4) + { player->onconveyor = section3; + } special = section1; @@ -5050,6 +5053,7 @@ void P_PlayerInSpecialSector(player_t *player) if (!player->mo) return; + K_ProcessTerrainEffect(player->mo); originalsector = player->mo->subsector->sector; P_PlayerOnSpecial3DFloor(player, originalsector); // Handle FOFs first. diff --git a/src/r_bsp.c b/src/r_bsp.c index e9d51c03a..6095f3739 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -23,6 +23,8 @@ #include "z_zone.h" // Check R_Prep3DFloors #include "taglist.h" +#include "k_terrain.h" + seg_t *curline; side_t *sidedef; line_t *linedef; @@ -67,11 +69,35 @@ boolean R_IsRipplePlane(sector_t *sector, ffloor_t *rover, int ceiling) static void R_PlaneLightOverride(sector_t *sector, boolean ceiling, INT32 *lightlevel) { - if (GETSECSPECIAL(sector->special, 4) == 6) // Fullbright sneaker panels + terrain_t *t = NULL; + + if (ceiling == true) { - if ((ceiling && (sector->flags & SF_FLIPSPECIAL_CEILING)) - || (!ceiling && (sector->flags & SF_FLIPSPECIAL_FLOOR))) + t = K_GetTerrainForFlatNum(sector->ceilingpic); + } + else + { + t = K_GetTerrainForFlatNum(sector->floorpic); + } + + if (t != NULL) + { + if (t->flags & TRF_SNEAKERPANEL) + { *lightlevel = 255; + } + } + else + { + // Sector effect sneaker panels (DEPRECATED) + if (GETSECSPECIAL(sector->special, 4) == 6) + { + if ((ceiling && (sector->flags & SF_FLIPSPECIAL_CEILING)) + || (!ceiling && (sector->flags & SF_FLIPSPECIAL_FLOOR))) + { + *lightlevel = 255; + } + } } } From b1ffaa99f84fdf0a4cdd23d43b72220a39ad2093 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 9 Dec 2021 13:20:35 -0500 Subject: [PATCH 08/69] Sync mobj->terrain This should be enough I think to sync terrain up. The data structures can't change after the files have been loaded, so it should be good. Needs proper online testing though --- src/k_terrain.c | 21 +++++++++++++++++++++ src/k_terrain.h | 1 + src/p_saveg.c | 16 ++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/src/k_terrain.c b/src/k_terrain.c index b8edebf03..8c55ac4f2 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -41,6 +41,27 @@ UINT16 numTerrainFloorDefs = 0; UINT16 defaultTerrain = UINT16_MAX; +/*-------------------------------------------------- + size_t K_GetTerrainHeapIndex(terrain_t *terrain) + + See header file for description. +--------------------------------------------------*/ +size_t K_GetTerrainHeapIndex(terrain_t *terrain) +{ + size_t i = SIZE_MAX; + + if (terrain == NULL) + { + CONS_Debug(DBG_GAMELOGIC, "NULL terrain in K_GetTerrainHeapIndex.\n"); + } + else + { + i = (terrain - terrainDefs); + } + + return i; +} + terrain_t *K_GetTerrainByIndex(UINT16 checkIndex) { if (checkIndex >= numTerrainDefs) diff --git a/src/k_terrain.h b/src/k_terrain.h index 600656522..c5bf51168 100644 --- a/src/k_terrain.h +++ b/src/k_terrain.h @@ -97,6 +97,7 @@ extern UINT16 numTerrainFloorDefs; // Default terrain definition ID. extern UINT16 defaultTerrain; +size_t K_GetTerrainHeapIndex(terrain_t *terrain); terrain_t *K_GetTerrainByIndex(UINT16 checkIndex); terrain_t *K_GetTerrainByName(const char *checkName); terrain_t *K_GetDefaultTerrain(void); diff --git a/src/p_saveg.c b/src/p_saveg.c index 39a4fec28..bfa6d6e15 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -38,6 +38,7 @@ // SRB2Kart #include "k_battle.h" #include "k_pwrlv.h" +#include "k_terrain.h" savedata_t savedata; UINT8 *save_p; @@ -1540,6 +1541,7 @@ typedef enum MD2_KITEMCAP = 1<<26, MD2_ITNEXT = 1<<27, MD2_LASTMOMZ = 1<<28, + MD2_TERRAIN = 1<<29, } mobj_diff2_t; typedef enum @@ -1782,6 +1784,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff2 |= MD2_ITNEXT; if (mobj->lastmomz) diff2 |= MD2_LASTMOMZ; + if (mobj->terrain != NULL) + diff2 |= MD2_TERRAIN; if (diff2 != 0) diff |= MD_MORE; @@ -1979,6 +1983,10 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) { WRITEINT32(save_p, mobj->lastmomz); } + if (diff2 & MD2_TERRAIN) + { + WRITEUINT32(save_p, K_GetTerrainHeapIndex(mobj->terrain)); + } WRITEUINT32(save_p, mobj->mobjnum); } @@ -3077,6 +3085,14 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) { mobj->lastmomz = READINT32(save_p); } + if (diff2 & MD2_TERRAIN) + { + mobj->terrain = (terrain_t *)(size_t)READUINT32(save_p); + } + else + { + mobj->terrain = NULL; + } if (diff & MD_REDFLAG) { From 35a72e56dc691dbac149bf07b4e0a8a44c047e7c Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 9 Dec 2021 14:45:59 -0500 Subject: [PATCH 09/69] Implement splash & footstep blocks, commentate more of the code They do nothing atm, but they can be set properly now :) --- src/k_terrain.c | 578 +++++++++++++++++++++++++++++++++++++++++++----- src/k_terrain.h | 330 +++++++++++++++++++++++++-- src/p_user.c | 4 - 3 files changed, 839 insertions(+), 73 deletions(-) diff --git a/src/k_terrain.c b/src/k_terrain.c index 8c55ac4f2..9ba13757d 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -14,6 +14,7 @@ #include "k_terrain.h" #include "dehacked.h" // get_number +#include "deh_soc.h" // get_mobjtype #include "doomdata.h" #include "doomdef.h" #include "doomtype.h" @@ -27,19 +28,155 @@ #include "k_kart.h" // on the chopping block... -t_splash_t *splashDefs = NULL; -UINT16 numSplashDefs = 0; +static t_splash_t *splashDefs = NULL; +static size_t numSplashDefs = 0; -t_footstep_t *footstepDefs = NULL; -UINT16 numFootstepDefs = 0; +static t_footstep_t *footstepDefs = NULL; +static size_t numFootstepDefs = 0; -terrain_t *terrainDefs = NULL; -UINT16 numTerrainDefs = 0; +static terrain_t *terrainDefs = NULL; +static size_t numTerrainDefs = 0; -t_floor_t *terrainFloorDefs = NULL; -UINT16 numTerrainFloorDefs = 0; +static t_floor_t *terrainFloorDefs = NULL; +static size_t numTerrainFloorDefs = 0; -UINT16 defaultTerrain = UINT16_MAX; +static size_t defaultTerrain = SIZE_MAX; + +/*-------------------------------------------------- + size_t K_GetSplashHeapIndex(t_splash_t *splash) + + See header file for description. +--------------------------------------------------*/ +size_t K_GetSplashHeapIndex(t_splash_t *splash) +{ + if (splash == NULL) + { + return SIZE_MAX; + } + + return (splash - splashDefs); +} + +/*-------------------------------------------------- + size_t K_GetNumSplashDefs(void) + + See header file for description. +--------------------------------------------------*/ +size_t K_GetNumSplashDefs(void) +{ + return numSplashDefs; +} + +/*-------------------------------------------------- + t_splash_t *K_GetSplashByIndex(size_t checkIndex) + + See header file for description. +--------------------------------------------------*/ +t_splash_t *K_GetSplashByIndex(size_t checkIndex) +{ + if (checkIndex >= numSplashDefs) + { + return NULL; + } + + return &splashDefs[checkIndex]; +} + +/*-------------------------------------------------- + t_splash_t *K_GetSplashByName(const char *checkName) + + See header file for description. +--------------------------------------------------*/ +t_splash_t *K_GetSplashByName(const char *checkName) +{ + size_t i; + + if (numSplashDefs == 0) + { + return NULL; + } + + for (i = 0; i < numSplashDefs; i++) + { + t_splash_t *s = &splashDefs[i]; + + if (stricmp(checkName, s->name) == 0) + { + // Name matches. + return s; + } + } + + return NULL; +} + +/*-------------------------------------------------- + size_t K_GetFootstepHeapIndex(t_footstep_t *footstep) + + See header file for description. +--------------------------------------------------*/ +size_t K_GetFootstepHeapIndex(t_footstep_t *footstep) +{ + if (footstep == NULL) + { + return SIZE_MAX; + } + + return (footstep - footstepDefs); +} + +/*-------------------------------------------------- + size_t K_GetNumFootstepDefs(void) + + See header file for description. +--------------------------------------------------*/ +size_t K_GetNumFootstepDefs(void) +{ + return numFootstepDefs; +} + +/*-------------------------------------------------- + t_footstep_t *K_GetFootstepByIndex(size_t checkIndex) + + See header file for description. +--------------------------------------------------*/ +t_footstep_t *K_GetFootstepByIndex(size_t checkIndex) +{ + if (checkIndex >= numFootstepDefs) + { + return NULL; + } + + return &footstepDefs[checkIndex]; +} + +/*-------------------------------------------------- + t_footstep_t *K_GetFootstepByName(const char *checkName) + + See header file for description. +--------------------------------------------------*/ +t_footstep_t *K_GetFootstepByName(const char *checkName) +{ + size_t i; + + if (numFootstepDefs == 0) + { + return NULL; + } + + for (i = 0; i < numFootstepDefs; i++) + { + t_footstep_t *fs = &footstepDefs[i]; + + if (stricmp(checkName, fs->name) == 0) + { + // Name matches. + return fs; + } + } + + return NULL; +} /*-------------------------------------------------- size_t K_GetTerrainHeapIndex(terrain_t *terrain) @@ -48,21 +185,30 @@ UINT16 defaultTerrain = UINT16_MAX; --------------------------------------------------*/ size_t K_GetTerrainHeapIndex(terrain_t *terrain) { - size_t i = SIZE_MAX; - if (terrain == NULL) { - CONS_Debug(DBG_GAMELOGIC, "NULL terrain in K_GetTerrainHeapIndex.\n"); - } - else - { - i = (terrain - terrainDefs); + return SIZE_MAX; } - return i; + return (terrain - terrainDefs); } -terrain_t *K_GetTerrainByIndex(UINT16 checkIndex) +/*-------------------------------------------------- + size_t K_GetNumTerrainDefs(void) + + See header file for description. +--------------------------------------------------*/ +size_t K_GetNumTerrainDefs(void) +{ + return numTerrainDefs; +} + +/*-------------------------------------------------- + terrain_t *K_GetTerrainByIndex(size_t checkIndex) + + See header file for description. +--------------------------------------------------*/ +terrain_t *K_GetTerrainByIndex(size_t checkIndex) { if (checkIndex >= numTerrainDefs) { @@ -72,18 +218,21 @@ terrain_t *K_GetTerrainByIndex(UINT16 checkIndex) return &terrainDefs[checkIndex]; } +/*-------------------------------------------------- + terrain_t *K_GetTerrainByName(const char *checkName) + + See header file for description. +--------------------------------------------------*/ terrain_t *K_GetTerrainByName(const char *checkName) { - INT32 i; + size_t i; if (numTerrainDefs == 0) { return NULL; } - // Search backwards through all terrain definitions. - // The latest one will have priority over the older one. - for (i = numTerrainDefs-1; i >= 0; i--) + for (i = 0; i < numTerrainDefs; i++) { terrain_t *t = &terrainDefs[i]; @@ -97,23 +246,30 @@ terrain_t *K_GetTerrainByName(const char *checkName) return NULL; } +/*-------------------------------------------------- + terrain_t *K_GetDefaultTerrain(void) + + See header file for description. +--------------------------------------------------*/ terrain_t *K_GetDefaultTerrain(void) { return K_GetTerrainByIndex(defaultTerrain); } +/*-------------------------------------------------- + terrain_t *K_GetTerrainForTextureName(const char *checkName) + + See header file for description. +--------------------------------------------------*/ terrain_t *K_GetTerrainForTextureName(const char *checkName) { - INT32 i; + size_t i; if (numTerrainFloorDefs == 0) { return NULL; } - // Search backwards through all terrain definitions. - // The latest one will have priority over the older one. - for (i = 0; i < numTerrainFloorDefs; i++) { t_floor_t *f = &terrainFloorDefs[i]; @@ -129,6 +285,11 @@ terrain_t *K_GetTerrainForTextureName(const char *checkName) return K_GetDefaultTerrain(); } +/*-------------------------------------------------- + terrain_t *K_GetTerrainForTextureNum(INT32 textureNum) + + See header file for description. +--------------------------------------------------*/ terrain_t *K_GetTerrainForTextureNum(INT32 textureNum) { texture_t *tex = NULL; @@ -142,6 +303,11 @@ terrain_t *K_GetTerrainForTextureNum(INT32 textureNum) return K_GetTerrainForTextureName(tex->name); } +/*-------------------------------------------------- + terrain_t *K_GetTerrainForFlatNum(INT32 flatID) + + See header file for description. +--------------------------------------------------*/ terrain_t *K_GetTerrainForFlatNum(INT32 flatID) { levelflat_t *levelFlat = NULL; @@ -156,6 +322,11 @@ terrain_t *K_GetTerrainForFlatNum(INT32 flatID) return K_GetTerrainForTextureName(levelFlat->name); } +/*-------------------------------------------------- + void K_UpdateMobjTerrain(mobj_t *mo, INT32 flatID) + + See header file for description. +--------------------------------------------------*/ void K_UpdateMobjTerrain(mobj_t *mo, INT32 flatID) { if (mo == NULL || P_MobjWasRemoved(mo) == true) @@ -175,6 +346,11 @@ void K_UpdateMobjTerrain(mobj_t *mo, INT32 flatID) mo->terrain = K_GetTerrainForFlatNum(flatID); } +/*-------------------------------------------------- + void K_ProcessTerrainEffect(mobj_t *mo) + + See header file for description. +--------------------------------------------------*/ void K_ProcessTerrainEffect(mobj_t *mo) { player_t *player = NULL; @@ -242,17 +418,26 @@ void K_ProcessTerrainEffect(mobj_t *mo) // (Offroad is handled elsewhere!) } +/*-------------------------------------------------- + void K_SetDefaultFriction(mobj_t *mo) + + See header file for description. +--------------------------------------------------*/ void K_SetDefaultFriction(mobj_t *mo) { + boolean isPlayer = false; + if (mo == NULL || P_MobjWasRemoved(mo) == true) { // Invalid object. return; } + isPlayer = (mo->player != NULL); + mo->friction = ORIG_FRICTION; - if (mo->player != NULL) + if (isPlayer == true) { mo->movefactor = FRACUNIT; } @@ -266,7 +451,7 @@ void K_SetDefaultFriction(mobj_t *mo) if (strength > 0) // sludge { - strength = strength*2; // otherwise, the maximum sludginess value is +967... + strength = strength * 2; // otherwise, the maximum sludginess value is +967... } // The following might seem odd. At the time of movement, @@ -284,26 +469,40 @@ void K_SetDefaultFriction(mobj_t *mo) newFriction = 0; } - newMovefactor = FixedDiv(ORIG_FRICTION, newFriction); - - if (newMovefactor < FRACUNIT) - { - newMovefactor = 19*newMovefactor - 18*FRACUNIT; - } - else - { - newMovefactor = FRACUNIT; - } - mo->friction = newFriction; - mo->movefactor = newMovefactor; + + if (isPlayer == true) + { + newMovefactor = FixedDiv(ORIG_FRICTION, newFriction); + + if (newMovefactor < FRACUNIT) + { + newMovefactor = 19*newMovefactor - 18*FRACUNIT; + } + else + { + newMovefactor = FRACUNIT; + } + + mo->movefactor = newMovefactor; + } } } -// -// Parser code starts here. -// +/*-------------------------------------------------- + static void K_FlagBoolean(UINT32 *inputFlags, UINT32 newFlag, char *val) + Sets a flag to true or false depending on + the string input. + + Input Arguments:- + inputFlags - Pointer to flags value to modify. + newFlag - The flag(s) to set / unset. + val - The string input from the file. + + Return:- + None +--------------------------------------------------*/ static void K_FlagBoolean(UINT32 *inputFlags, UINT32 newFlag, char *val) { if (stricmp(val, "true") == 0) @@ -316,10 +515,147 @@ static void K_FlagBoolean(UINT32 *inputFlags, UINT32 newFlag, char *val) } } +/*-------------------------------------------------- + static void K_SplashDefaults(t_splash_t *splash) + + Sets the defaults for a new Splash block. + + Input Arguments:- + splash - Terrain Splash structure to default. + + Return:- + None +--------------------------------------------------*/ +static void K_SplashDefaults(t_splash_t *splash) +{ + splash->mobjType = MT_NULL; + splash->sfx = sfx_None; +} + +/*-------------------------------------------------- + static void K_NewSplashDefs(void) + + Increases the size of splashDefs by 1, and + sets the new struct's values to their defaults. + + Input Arguments:- + None + + Return:- + None +--------------------------------------------------*/ +static void K_NewSplashDefs(void) +{ + numSplashDefs++; + splashDefs = (t_splash_t *)Z_Realloc(splashDefs, sizeof(t_splash_t) * (numSplashDefs + 1), PU_STATIC, NULL); + K_SplashDefaults( &splashDefs[numSplashDefs - 1] ); +} + +/*-------------------------------------------------- + static void K_ParseSplashParameter(size_t i, char *param, char *val) + + Parser function for Splash blocks. + + Input Arguments:- + i - Struct ID + param - Parameter string + val - Value string + + Return:- + None +--------------------------------------------------*/ +static void K_ParseSplashParameter(size_t i, char *param, char *val) +{ + t_splash_t *splash = &splashDefs[i]; + + if (stricmp(param, "mobjType") == 0) + { + splash->mobjType = get_mobjtype(val); + } + else if (stricmp(param, "sfx") == 0) + { + splash->sfx = get_sfx(val); + } +} + +/*-------------------------------------------------- + static void K_FootstepDefaults(t_footstep_t *footstep) + + Sets the defaults for a new Footstep block. + + Input Arguments:- + footstep - Terrain Footstep structure to default. + + Return:- + None +--------------------------------------------------*/ +static void K_FootstepDefaults(t_footstep_t *footstep) +{ + footstep->mobjType = MT_NULL; + footstep->sfx = sfx_None; +} + +/*-------------------------------------------------- + static void K_NewFootstepDefs(void) + + Increases the size of footstepDefs by 1, and + sets the new struct's values to their defaults. + + Input Arguments:- + None + + Return:- + None +--------------------------------------------------*/ +static void K_NewFootstepDefs(void) +{ + numFootstepDefs++; + footstepDefs = (t_footstep_t *)Z_Realloc(footstepDefs, sizeof(t_footstep_t) * (numFootstepDefs + 1), PU_STATIC, NULL); + K_FootstepDefaults( &footstepDefs[numFootstepDefs - 1] ); +} + +/*-------------------------------------------------- + static void K_ParseFootstepParameter(size_t i, char *param, char *val) + + Parser function for Footstep blocks. + + Input Arguments:- + i - Struct ID + param - Parameter string + val - Value string + + Return:- + None +--------------------------------------------------*/ +static void K_ParseFootstepParameter(size_t i, char *param, char *val) +{ + t_footstep_t *footstep = &footstepDefs[i]; + + if (stricmp(param, "mobjType") == 0) + { + footstep->mobjType = get_mobjtype(val); + } + else if (stricmp(param, "sfx") == 0) + { + footstep->sfx = get_sfx(val); + } +} + +/*-------------------------------------------------- + static void K_TerrainDefaults(terrain_t *terrain) + + Sets the defaults for a new Terrain block. + + Input Arguments:- + terrain - Terrain structure to default. + + Return:- + None +--------------------------------------------------*/ static void K_TerrainDefaults(terrain_t *terrain) { - terrain->splashID = UINT16_MAX; - terrain->footstepID = UINT16_MAX; + terrain->splashID = SIZE_MAX; + terrain->footstepID = SIZE_MAX; terrain->friction = FRACUNIT; terrain->offroad = 0; @@ -328,6 +664,18 @@ static void K_TerrainDefaults(terrain_t *terrain) terrain->flags = 0; } +/*-------------------------------------------------- + static void K_NewTerrainDefs(void) + + Increases the size of terrainDefs by 1, and + sets the new struct's values to their defaults. + + Input Arguments:- + None + + Return:- + None +--------------------------------------------------*/ static void K_NewTerrainDefs(void) { numTerrainDefs++; @@ -335,17 +683,32 @@ static void K_NewTerrainDefs(void) K_TerrainDefaults( &terrainDefs[numTerrainDefs - 1] ); } +/*-------------------------------------------------- + static void K_ParseTerrainParameter(UINT32 i, char *param, char *val) + + Parser function for Terrain blocks. + + Input Arguments:- + i - Struct ID + param - Parameter string + val - Value string + + Return:- + None +--------------------------------------------------*/ static void K_ParseTerrainParameter(UINT32 i, char *param, char *val) { terrain_t *terrain = &terrainDefs[i]; if (stricmp(param, "splash") == 0) { - //terrain->splashID = 0; + t_splash_t *splash = K_GetSplashByName(val); + terrain->splashID = K_GetSplashHeapIndex(splash); } else if (stricmp(param, "footstep") == 0) { - //terrain->footstepID = 0; + t_footstep_t *footstep = K_GetFootstepByName(val); + terrain->footstepID = K_GetFootstepHeapIndex(footstep); } else if (stricmp(param, "friction") == 0) { @@ -373,12 +736,37 @@ static void K_ParseTerrainParameter(UINT32 i, char *param, char *val) } } +/*-------------------------------------------------- + static void K_NewTerrainFloorDefs(void) + + Increases the size of numTerrainFloorDefs by 1. + + Input Arguments:- + None + + Return:- + None +--------------------------------------------------*/ static void K_NewTerrainFloorDefs(void) { numTerrainFloorDefs++; terrainFloorDefs = (t_floor_t *)Z_Realloc(terrainFloorDefs, sizeof(t_floor_t) * (numTerrainFloorDefs + 1), PU_STATIC, NULL); } +/*-------------------------------------------------- + static boolean K_DoTERRAINLumpParse(size_t num, void (*parser)(UINT32, char *, char *)) + + Runs another parser function for the TERRAIN + lump, handling the nitty-gritty parts of the + token handling. + + Input Arguments:- + num - Struct ID to modify. Which one it will modify depends on the parser function. + parser - The parser function. Takes three inputs: Struct ID, Parameter String, and Value String. + + Return:- + false if any errors occured, otherwise true. +--------------------------------------------------*/ static boolean K_DoTERRAINLumpParse(size_t num, void (*parser)(UINT32, char *, char *)) { char *param, *val; @@ -414,6 +802,18 @@ static boolean K_DoTERRAINLumpParse(size_t num, void (*parser)(UINT32, char *, c return true; } +/*-------------------------------------------------- + static boolean K_TERRAINLumpParser(UINT8 *data, size_t size) + + Parses inputted lump data as a TERRAIN lump. + + Input Arguments:- + data - Pointer to lump data. + size - The length of the lump data. + + Return:- + false if any errors occured, otherwise true. +--------------------------------------------------*/ static boolean K_TERRAINLumpParser(UINT8 *data, size_t size) { char *tkn = M_GetToken((char *)data); @@ -431,6 +831,80 @@ static boolean K_TERRAINLumpParser(UINT8 *data, size_t size) valid = false; } // Check for valid fields. + else if (stricmp(tkn, "splash") == 0) + { + Z_Free(tkn); + tkn = M_GetToken(NULL); + pos = M_GetTokenPos(); + + if (tkn && pos < size) + { + t_splash_t *s = NULL; + + for (i = 0; i < numSplashDefs; i++) + { + s = &splashDefs[i]; + + if (stricmp(tkn, s->name) == 0) + { + break; + } + } + + if (i == numSplashDefs) + { + K_NewSplashDefs(); + s = &splashDefs[i]; + + strncpy(s->name, tkn, TERRAIN_NAME_LEN); + CONS_Printf("Created new Splash type '%s'\n", s->name); + } + + valid = K_DoTERRAINLumpParse(i, K_ParseSplashParameter); + } + else + { + CONS_Alert(CONS_ERROR, "No Splash type name.\n"); + valid = false; + } + } + else if (stricmp(tkn, "footstep") == 0) + { + Z_Free(tkn); + tkn = M_GetToken(NULL); + pos = M_GetTokenPos(); + + if (tkn && pos < size) + { + t_footstep_t *fs = NULL; + + for (i = 0; i < numFootstepDefs; i++) + { + fs = &footstepDefs[i]; + + if (stricmp(tkn, fs->name) == 0) + { + break; + } + } + + if (i == numFootstepDefs) + { + K_NewFootstepDefs(); + fs = &footstepDefs[i]; + + strncpy(fs->name, tkn, TERRAIN_NAME_LEN); + CONS_Printf("Created new Footstep type '%s'\n", fs->name); + } + + valid = K_DoTERRAINLumpParse(i, K_ParseFootstepParameter); + } + else + { + CONS_Alert(CONS_ERROR, "No Footstep type name.\n"); + valid = false; + } + } else if (stricmp(tkn, "terrain") == 0) { Z_Free(tkn); @@ -464,7 +938,7 @@ static boolean K_TERRAINLumpParser(UINT8 *data, size_t size) } else { - CONS_Alert(CONS_ERROR, "No terrain type name.\n"); + CONS_Alert(CONS_ERROR, "No Terrain type name.\n"); valid = false; } } @@ -522,7 +996,7 @@ static boolean K_TERRAINLumpParser(UINT8 *data, size_t size) } else { - f->terrainID = (t - terrainDefs); + f->terrainID = K_GetTerrainHeapIndex(t); CONS_Printf("Texture '%s' set to Terrain '%s'\n", f->textureName, tkn); } } @@ -580,7 +1054,6 @@ static boolean K_TERRAINLumpParser(UINT8 *data, size_t size) valid = false; } } - // TODO: splash & footstep blocks else { CONS_Alert(CONS_ERROR, "Unknown field '%s' found in TERRAIN lump.\n", tkn); @@ -601,6 +1074,11 @@ static boolean K_TERRAINLumpParser(UINT8 *data, size_t size) return true; } +/*-------------------------------------------------- + void K_InitTerrain(UINT16 wadNum) + + See header file for description. +--------------------------------------------------*/ void K_InitTerrain(UINT16 wadNum) { UINT16 lumpNum; diff --git a/src/k_terrain.h b/src/k_terrain.h index c5bf51168..0e36388ea 100644 --- a/src/k_terrain.h +++ b/src/k_terrain.h @@ -29,8 +29,8 @@ typedef struct t_splash_s char name[TERRAIN_NAME_LEN]; // Lookup name. - UINT16 objType; // Thing type. MT_NULL to not spawn anything. - UINT16 sound; // Sound to play. + UINT16 mobjType; // Thing type. MT_NULL to not spawn anything. + UINT16 sfx; // Sound to play. } t_splash_t; typedef struct t_footstep_s @@ -40,8 +40,8 @@ typedef struct t_footstep_s char name[TERRAIN_NAME_LEN]; // Lookup name. - UINT16 objType; // Thing type. MT_NULL to not spawn anything. - UINT16 sound; // Sound to play. + UINT16 mobjType; // Thing type. MT_NULL to not spawn anything. + UINT16 sfx; // Sound to play. } t_footstep_t; typedef enum @@ -58,8 +58,8 @@ typedef struct terrain_s char name[TERRAIN_NAME_LEN]; // Lookup name. - UINT16 splashID; // Splash defintion ID. - UINT16 footstepID; // Footstep defintion ID. + size_t splashID; // Splash defintion ID. + size_t footstepID; // Footstep defintion ID. fixed_t friction; // The default friction of this texture. UINT8 offroad; // The default offroad level of this texture. @@ -78,37 +78,329 @@ typedef struct t_floor_s // Someone confirm if I just hallucinated that. :V) char textureName[9]; // Floor texture name. - UINT16 terrainID; // Terrain definition ID. + size_t terrainID; // Terrain definition ID. } t_floor_t; -// Arrays for all terrain definitions. -extern t_splash_t *splashDefs; -extern UINT16 numSplashDefs; +/*-------------------------------------------------- + size_t K_GetSplashHeapIndex(t_splash_t *splash); -extern t_footstep_t *footstepDefs; -extern UINT16 numFootstepDefs; + Returns a splash defintion's index in the + splash definition heap. -extern terrain_t *terrainDefs; -extern UINT16 numTerrainDefs; + Input Arguments:- + splash - The splash definition to return the index of. -extern t_floor_t *terrainFloorDefs; -extern UINT16 numTerrainFloorDefs; + Return:- + The splash heap index, SIZE_MAX if the splash was invalid. +--------------------------------------------------*/ -// Default terrain definition ID. -extern UINT16 defaultTerrain; +size_t K_GetSplashHeapIndex(t_splash_t *splash); + + +/*-------------------------------------------------- + size_t K_GetNumSplashDefs(void); + + Returns the number of splash definitions. + + Input Arguments:- + None + + Return:- + Length of splashDefs. +--------------------------------------------------*/ + +size_t K_GetNumSplashDefs(void); + + +/*-------------------------------------------------- + t_splash_t *K_GetSplashByIndex(size_t checkIndex); + + Retrieves a splash definition by its heap index. + + Input Arguments:- + checkIndex - The heap index to retrieve. + + Return:- + The splash definition, NULL if it didn't exist. +--------------------------------------------------*/ + +t_splash_t *K_GetSplashByIndex(size_t checkIndex); + + +/*-------------------------------------------------- + t_splash_t *K_GetSplashByName(const char *checkName); + + Retrieves a splash definition by its lookup name. + + Input Arguments:- + checkName - The lookup name to retrieve. + + Return:- + The splash definition, NULL if it didn't exist. +--------------------------------------------------*/ + +t_splash_t *K_GetSplashByName(const char *checkName); + + +/*-------------------------------------------------- + size_t K_GetFootstepHeapIndex(t_footstep_t *footstep); + + Returns a footstep defintion's index in the + footstep definition heap. + + Input Arguments:- + footstep - The footstep definition to return the index of. + + Return:- + The footstep heap index, SIZE_MAX if the footstep was invalid. +--------------------------------------------------*/ + +size_t K_GetFootstepHeapIndex(t_footstep_t *footstep); + + +/*-------------------------------------------------- + size_t K_GetNumFootstepDefs(void); + + Returns the number of footstep definitions. + + Input Arguments:- + None + + Return:- + Length of footstepDefs. +--------------------------------------------------*/ + +size_t K_GetNumFootstepDefs(void); + + +/*-------------------------------------------------- + t_footstep_t *K_GetFootstepByIndex(size_t checkIndex); + + Retrieves a footstep definition by its heap index. + + Input Arguments:- + checkIndex - The heap index to retrieve. + + Return:- + The footstep definition, NULL if it didn't exist. +--------------------------------------------------*/ + +t_footstep_t *K_GetFootstepByIndex(size_t checkIndex); + + +/*-------------------------------------------------- + t_footstep_t *K_GetFootstepByName(const char *checkName); + + Retrieves a footstep definition by its lookup name. + + Input Arguments:- + checkName - The lookup name to retrieve. + + Return:- + The footstep definition, NULL if it didn't exist. +--------------------------------------------------*/ + +t_footstep_t *K_GetFootstepByName(const char *checkName); + + +/*-------------------------------------------------- + size_t K_GetTerrainHeapIndex(terrain_t *terrain); + + Returns a terrain defintion's index in the + terrain definition heap. + + Input Arguments:- + terrain - The terrain definition to return the index of. + + Return:- + The terrain heap index, SIZE_MAX if the terrain was invalid. +--------------------------------------------------*/ size_t K_GetTerrainHeapIndex(terrain_t *terrain); -terrain_t *K_GetTerrainByIndex(UINT16 checkIndex); + + +/*-------------------------------------------------- + size_t K_GetNumTerrainDefs(void); + + Returns the number of terrain definitions. + + Input Arguments:- + None + + Return:- + Length of terrainDefs. +--------------------------------------------------*/ + +size_t K_GetNumTerrainDefs(void); + + +/*-------------------------------------------------- + terrain_t *K_GetTerrainByIndex(size_t checkIndex); + + Retrieves a terrain definition by its heap index. + + Input Arguments:- + checkIndex - The heap index to retrieve. + + Return:- + The terrain definition, NULL if it didn't exist. +--------------------------------------------------*/ + +terrain_t *K_GetTerrainByIndex(size_t checkIndex); + + +/*-------------------------------------------------- + terrain_t *K_GetTerrainByName(const char *checkName); + + Retrieves a terrain definition by its lookup name. + + Input Arguments:- + checkName - The lookup name to retrieve. + + Return:- + The terrain definition, NULL if it didn't exist. +--------------------------------------------------*/ + terrain_t *K_GetTerrainByName(const char *checkName); + +/*-------------------------------------------------- + terrain_t *K_GetDefaultTerrain(void); + + Returns the default terrain definition, used + in cases where terrain is not set for a texture. + + Input Arguments:- + None + + Return:- + The default terrain definition, NULL if it didn't exist. +--------------------------------------------------*/ + terrain_t *K_GetDefaultTerrain(void); + + +/*-------------------------------------------------- + terrain_t *K_GetTerrainForTextureName(const char *checkName); + + Returns the terrain definition applied to + the texture name inputted. + + Input Arguments:- + checkName - The texture's name. + + Return:- + The texture's terrain definition if it exists, + otherwise the default terrain if it exists, + otherwise NULL. +--------------------------------------------------*/ + terrain_t *K_GetTerrainForTextureName(const char *checkName); + + +/*-------------------------------------------------- + terrain_t *K_GetTerrainForTextureNum(INT32 textureNum); + + Returns the terrain definition applied to + the texture ID inputted. + + Input Arguments:- + textureNum - The texture's ID. + + Return:- + The texture's terrain definition if it exists, + otherwise the default terrain if it exists, + otherwise NULL. +--------------------------------------------------*/ + terrain_t *K_GetTerrainForTextureNum(INT32 textureNum); + + +/*-------------------------------------------------- + terrain_t *K_GetTerrainForFlatNum(INT32 flatID); + + Returns the terrain definition applied to + the level flat ID. + + Input Arguments:- + flatID - The level flat's ID. + + Return:- + The level flat's terrain definition if it exists, + otherwise the default terrain if it exists, + otherwise NULL. +--------------------------------------------------*/ + terrain_t *K_GetTerrainForFlatNum(INT32 flatID); + +/*-------------------------------------------------- + void K_UpdateMobjTerrain(mobj_t *mo, INT32 flatID); + + Updates an object's terrain pointer, based on + the level flat ID supplied. Intended to be called + when the object moves to new floors. + + Input Arguments:- + mo - The object to update. + flatID - The level flat ID the object is standing on. + + Return:- + None +--------------------------------------------------*/ + void K_UpdateMobjTerrain(mobj_t *mo, INT32 flatID); + + +/*-------------------------------------------------- + void K_ProcessTerrainEffect(mobj_t *mo); + + Handles applying terrain effects to the object, + intended to be called in a thinker. + + Currently only intended for players, but + could be modified to be inclusive of all + object types. + + Input Arguments:- + mo - The object to apply effects to. + + Return:- + None +--------------------------------------------------*/ + void K_ProcessTerrainEffect(mobj_t *mo); + + +/*-------------------------------------------------- + void K_SetDefaultFriction(mobj_t *mo); + + Resets an object to their default friction values. + If they are on terrain with different friction, + they will update to that value. + + Input Arguments:- + mo - The object to reset the friction values of. + + Return:- + None +--------------------------------------------------*/ + void K_SetDefaultFriction(mobj_t *mo); + +/*-------------------------------------------------- + void K_InitTerrain(UINT16 wadNum); + + Finds the TERRAIN lumps in a WAD/PK3, and + processes all of them. + + Input Arguments:- + wadNum - WAD file ID to process. + + Return:- + None +--------------------------------------------------*/ + void K_InitTerrain(UINT16 wadNum); #endif // __K_TERRAIN_H__ diff --git a/src/p_user.c b/src/p_user.c index 5f5242e66..2550e3ba6 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2118,8 +2118,6 @@ void P_MovePlayer(player_t *player) player->mo->rollangle = 0; } - player->mo->movefactor = FRACUNIT; // We're not going to do any more with this, so let's change it back for the next frame. - //{ SRB2kart // Drifting sound @@ -4468,8 +4466,6 @@ void P_PlayerThink(player_t *player) P_MovePlayer(player); } - player->mo->movefactor = FRACUNIT; // We're not going to do any more with this, so let's change it back for the next frame. - // Unset statis flag after moving. // In other words, if you manually set stasis via code, // it lasts for one tic. From b3d3135c5871e27742fbdc97c0095c88f5a7a75d Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 9 Dec 2021 15:54:22 -0500 Subject: [PATCH 10/69] Instead of embedding specific textures to be tripwire in hardcode ... make it a TERRAIN flag! --- src/k_kart.c | 11 +++++------ src/k_terrain.c | 12 ++++++++++-- src/k_terrain.h | 4 +++- src/lua_playerlib.c | 4 ++-- src/p_setup.c | 8 +++----- src/p_spec.c | 2 +- 6 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index de660b812..812b856ce 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5063,7 +5063,7 @@ void K_DoSneaker(player_t *player, INT32 type) { const fixed_t intendedboost = FRACUNIT/2; - if (!player->floorboost || player->floorboost == 3) + if (player->floorboost == 0 || player->floorboost == 3) { const sfxenum_t normalsfx = sfx_cdfm01; const sfxenum_t smallsfx = sfx_cdfm40; @@ -5086,7 +5086,7 @@ void K_DoSneaker(player_t *player, INT32 type) player->numsneakers++; } - if (!player->sneakertimer) + if (player->sneakertimer == 0) { if (type == 2) { @@ -5120,13 +5120,12 @@ void K_DoSneaker(player_t *player, INT32 type) { player->pflags |= PF_ATTACKDOWN; K_PlayBoostTaunt(player->mo); - } player->sneakertimer = sneakertime; // set angle for spun out players: - player->boostangle = (INT32)player->mo->angle; + player->boostangle = player->mo->angle; } static void K_DoShrink(player_t *user) @@ -6646,7 +6645,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) // update boost angle if not spun out if (!player->spinouttimer && !player->wipeoutslow) - player->boostangle = (INT32)player->mo->angle; + player->boostangle = player->mo->angle; K_GetKartBoostPower(player); @@ -6919,7 +6918,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->sneakertimer && player->wipeoutslow > 0 && player->wipeoutslow < wipeoutslowtime+1) player->wipeoutslow = wipeoutslowtime+1; - if (player->floorboost) + if (player->floorboost > 0) player->floorboost--; if (player->driftboost) diff --git a/src/k_terrain.c b/src/k_terrain.c index 9ba13757d..dfd059893 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -274,7 +274,7 @@ terrain_t *K_GetTerrainForTextureName(const char *checkName) { t_floor_t *f = &terrainFloorDefs[i]; - if (stricmp(checkName, f->textureName) == 0) + if (strncasecmp(checkName, f->textureName, 8) == 0) { return K_GetTerrainByIndex(f->terrainID); } @@ -387,7 +387,7 @@ void K_ProcessTerrainEffect(mobj_t *mo) // Sneaker panel if (terrain->flags & TRF_SNEAKERPANEL) { - if (!player->floorboost) + if (player->floorboost == 0) player->floorboost = 3; else player->floorboost = 2; @@ -734,6 +734,14 @@ static void K_ParseTerrainParameter(UINT32 i, char *param, char *val) { K_FlagBoolean(&terrain->flags, TRF_SNEAKERPANEL, val); } + else if (stricmp(param, "bumpy") == 0 || stricmp(param, "stairJank") == 0) + { + K_FlagBoolean(&terrain->flags, TRF_STAIRJANK, val); + } + else if (stricmp(param, "tripwire") == 0) + { + K_FlagBoolean(&terrain->flags, TRF_TRIPWIRE, val); + } } /*-------------------------------------------------- diff --git a/src/k_terrain.h b/src/k_terrain.h index 0e36388ea..e53a72358 100644 --- a/src/k_terrain.h +++ b/src/k_terrain.h @@ -48,7 +48,9 @@ typedef enum { // Terrain flag values. TRF_LIQUID = 1, // Texture water properties (wavy, slippery, etc) - TRF_SNEAKERPANEL = 1<<1 // Texture is a booster + TRF_SNEAKERPANEL = 1<<1, // Texture is a booster + TRF_STAIRJANK = 1<<2, // Texture is bumpy road + TRF_TRIPWIRE = 1<<3 // Texture is a tripwire when used as a midtexture } terrain_flags_t; typedef struct terrain_s diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index f7c20ab64..23e2e2b67 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -281,7 +281,7 @@ static int player_get(lua_State *L) else if (fastcmp(field,"handleboost")) lua_pushinteger(L, plr->handleboost); else if (fastcmp(field,"boostangle")) - lua_pushinteger(L, plr->boostangle); + lua_pushangle(L, plr->boostangle); else if (fastcmp(field,"draftpower")) lua_pushinteger(L, plr->draftpower); else if (fastcmp(field,"draftleeway")) @@ -626,7 +626,7 @@ static int player_set(lua_State *L) else if (fastcmp(field,"handleboost")) plr->handleboost = luaL_checkinteger(L, 3); else if (fastcmp(field,"boostangle")) - plr->boostangle = luaL_checkinteger(L, 3); + plr->boostangle = luaL_checkangle(L, 3); else if (fastcmp(field,"draftpower")) plr->draftpower = luaL_checkinteger(L, 3); else if (fastcmp(field,"draftleeway")) diff --git a/src/p_setup.c b/src/p_setup.c index fab5429b8..30323c70e 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -91,6 +91,7 @@ #include "k_waypoint.h" #include "k_bot.h" #include "k_grandprix.h" +#include "k_terrain.h" // TRF_TRIPWIRE // Replay names have time #if !defined (UNDER_CE) @@ -1939,18 +1940,15 @@ static void P_ProcessLinedefsAfterSidedefs(void) size_t i = numlines; register line_t *ld = lines; - const INT32 TEX_TRIPWIRE = R_TextureNumForName("TRIPWIRE"); - const INT32 TEX_4RIPWIRE = R_TextureNumForName("4RIPWIRE"); - for (; i--; ld++) { INT32 midtexture = sides[ld->sidenum[0]].midtexture; + terrain_t *terrain = K_GetTerrainForTextureNum(midtexture); ld->frontsector = sides[ld->sidenum[0]].sector; //e6y: Can't be -1 here ld->backsector = ld->sidenum[1] != 0xffff ? sides[ld->sidenum[1]].sector : 0; - if (midtexture == TEX_TRIPWIRE || - midtexture == TEX_4RIPWIRE) + if (terrain != NULL && (terrain->flags & TRF_TRIPWIRE)) { ld->tripwire = true; } diff --git a/src/p_spec.c b/src/p_spec.c index cd6f0f6ae..a52cfe932 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4660,7 +4660,7 @@ DoneSection2: case 6: // SRB2kart 190117 - Sneaker Panel if (roversector || P_MobjReadyToTrigger(player->mo, sector)) { - if (!player->floorboost) + if (player->floorboost == 0) player->floorboost = 3; else player->floorboost = 2; From 047b725a309c8d5b2f8da48e0fdbd2ab3f721f00 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 9 Dec 2021 16:12:09 -0500 Subject: [PATCH 11/69] Implement bumpy floor --- src/k_terrain.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/k_terrain.c b/src/k_terrain.c index dfd059893..1ad7e45a3 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -415,6 +415,26 @@ void K_ProcessTerrainEffect(mobj_t *mo) P_InstaThrust(mo, mo->angle, speed); } + // Bumpy floor + if (terrain->flags & TRF_STAIRJANK) + { + /* use a shorter sound if not two tics have passed + * since the last step */ + S_StartSound(mo, player->stairjank + >= 16 ? sfx_s23b : sfx_s268); + + if (player->stairjank == 0) + { + mobj_t *spark = P_SpawnMobjFromMobj(mo, + 0, 0, 0, MT_JANKSPARK); + spark->fuse = 9; + spark->cusval = K_StairJankFlip(ANGLE_90); + P_SetTarget(&spark->target, mo); + } + + player->stairjank = 17; + } + // (Offroad is handled elsewhere!) } From 35a3f65e83f8e6058cf3d6731de7c8086f5cd4b1 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 9 Dec 2021 16:32:31 -0500 Subject: [PATCH 12/69] Allow "texture" as an alias to "floor" Since we I'm using it for Tripwire too --- src/k_terrain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_terrain.c b/src/k_terrain.c index 1ad7e45a3..9cfd399d0 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -970,7 +970,7 @@ static boolean K_TERRAINLumpParser(UINT8 *data, size_t size) valid = false; } } - else if (stricmp(tkn, "floor") == 0) + else if (stricmp(tkn, "floor") == 0 || stricmp(tkn, "texture") == 0) { Z_Free(tkn); tkn = M_GetToken(NULL); From a6d1043d1736b09dfd40ac4cd1a628c71fc04d98 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 17 Dec 2021 18:29:35 -0500 Subject: [PATCH 13/69] Reduce turning for bots when they stair jank --- src/k_bot.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/k_bot.c b/src/k_bot.c index 24f3517a2..44f9c27c2 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -662,7 +662,10 @@ fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t --------------------------------------------------*/ static botprediction_t *K_CreateBotPrediction(player_t *player) { - const INT16 handling = K_GetKartTurnValue(player, KART_FULLTURN); // Reduce prediction based on how fast you can turn + // Stair janking makes it harder to steer, so attempt to steer harder. + const UINT8 jankDiv = (player->stairjank > 0 ? 2 : 1); + + const INT16 handling = K_GetKartTurnValue(player, KART_FULLTURN) / jankDiv; // Reduce prediction based on how fast you can turn const INT16 normal = KART_FULLTURN; // "Standard" handling to compare to const tic_t futuresight = (TICRATE * normal) / max(1, handling); // How far ahead into the future to try and predict From 436b6d50ea03300719d4d8b28d65aa55c9a6cbbc Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 18 Dec 2021 16:31:08 -0500 Subject: [PATCH 14/69] Bot predict nudging scale is based on the prediction's radius --- src/k_botsearch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_botsearch.c b/src/k_botsearch.c index 846521e6f..a06eb55f1 100644 --- a/src/k_botsearch.c +++ b/src/k_botsearch.c @@ -619,7 +619,7 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) fixed_t avgX = 0, avgY = 0; fixed_t avgDist = 0; - const fixed_t baseNudge = 128 * mapobjectscale; + const fixed_t baseNudge = predict->radius; fixed_t maxNudge = distToPredict; fixed_t nudgeDist = 0; angle_t nudgeDir = 0; From edef941a081c2dd7287bb06af0246abd9e47911e Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 18 Dec 2021 18:30:19 -0500 Subject: [PATCH 15/69] Add scale & color parameters to terrain particles --- src/k_terrain.c | 16 ++++++++++++++++ src/k_terrain.h | 4 ++++ 2 files changed, 20 insertions(+) diff --git a/src/k_terrain.c b/src/k_terrain.c index 9cfd399d0..c2022d1b9 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -596,6 +596,14 @@ static void K_ParseSplashParameter(size_t i, char *param, char *val) { splash->sfx = get_sfx(val); } + else if (stricmp(param, "scale") == 0) + { + splash->scale = FLOAT_TO_FIXED(atof(val)); + } + else if (stricmp(param, "color") == 0) + { + splash->color = get_skincolor(val); + } } /*-------------------------------------------------- @@ -659,6 +667,14 @@ static void K_ParseFootstepParameter(size_t i, char *param, char *val) { footstep->sfx = get_sfx(val); } + else if (stricmp(param, "scale") == 0) + { + footstep->scale = FLOAT_TO_FIXED(atof(val)); + } + else if (stricmp(param, "color") == 0) + { + footstep->color = get_skincolor(val); + } } /*-------------------------------------------------- diff --git a/src/k_terrain.h b/src/k_terrain.h index e53a72358..d494f5edf 100644 --- a/src/k_terrain.h +++ b/src/k_terrain.h @@ -31,6 +31,8 @@ typedef struct t_splash_s UINT16 mobjType; // Thing type. MT_NULL to not spawn anything. UINT16 sfx; // Sound to play. + fixed_t scale; // Thing scale multiplier. + UINT16 color; // Colorize effect. SKINCOLOR_NONE has no colorize. } t_splash_t; typedef struct t_footstep_s @@ -42,6 +44,8 @@ typedef struct t_footstep_s UINT16 mobjType; // Thing type. MT_NULL to not spawn anything. UINT16 sfx; // Sound to play. + fixed_t scale; // Thing scale multiplier. + UINT16 color; // Colorize effect. SKINCOLOR_NONE has no colorize. } t_footstep_t; typedef enum From 8667aeb620ccf16cc4a1ed5dba6e5f480f4da6d2 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 18 Dec 2021 21:23:41 -0500 Subject: [PATCH 16/69] Add footstep particles --- src/k_kart.c | 20 ++---- src/k_kart.h | 2 +- src/k_terrain.c | 164 ++++++++++++++++++++++++++++++++++++++++++++-- src/k_terrain.h | 16 +++++ src/lua_baselib.c | 3 +- src/p_user.c | 2 +- 6 files changed, 181 insertions(+), 26 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index c0f5909ec..fefc5387b 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -4346,7 +4346,7 @@ void K_SpawnSparkleTrail(mobj_t *mo) sparkle->color = mo->color; } -void K_SpawnWipeoutTrail(mobj_t *mo, boolean offroad) +void K_SpawnWipeoutTrail(mobj_t *mo) { mobj_t *dust; angle_t aoff; @@ -4373,13 +4373,6 @@ void K_SpawnWipeoutTrail(mobj_t *mo, boolean offroad) dust->destscale = mo->scale; P_SetScale(dust, mo->scale); K_FlipFromObject(dust, mo); - - if (offroad) // offroad effect - { - dust->momx = mo->momx/2; - dust->momy = mo->momy/2; - dust->momz = mo->momz/2; - } } void K_SpawnDraftDust(mobj_t *mo) @@ -6698,16 +6691,11 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) ghost->renderflags |= RF_DONTDRAW; } + // Could probably be moved somewhere else. + K_HandleFootstepParticles(player->mo); + if (P_IsObjectOnGround(player->mo)) { - // Offroad dust - if (player->boostpower < FRACUNIT) - { - K_SpawnWipeoutTrail(player->mo, true); - if (leveltime % 6 == 0) - S_StartSound(player->mo, sfx_cdfm70); - } - // Draft dust if (player->draftpower >= FRACUNIT) { diff --git a/src/k_kart.h b/src/k_kart.h index dffc1cedf..04d80fd05 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -76,7 +76,7 @@ void K_RunFinishLineBeam(void); UINT16 K_DriftSparkColor(player_t *player, INT32 charge); void K_SpawnBoostTrail(player_t *player); void K_SpawnSparkleTrail(mobj_t *mo); -void K_SpawnWipeoutTrail(mobj_t *mo, boolean offroad); +void K_SpawnWipeoutTrail(mobj_t *mo); void K_SpawnDraftDust(mobj_t *mo); void K_DriftDustHandling(mobj_t *spawner); void K_Squish(mobj_t *mo); diff --git a/src/k_terrain.c b/src/k_terrain.c index c2022d1b9..4f9f63cbf 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -20,6 +20,7 @@ #include "doomtype.h" #include "fastcmp.h" #include "m_fixed.h" +#include "m_random.h" #include "p_local.h" #include "p_mobj.h" #include "r_textures.h" @@ -41,6 +42,7 @@ static t_floor_t *terrainFloorDefs = NULL; static size_t numTerrainFloorDefs = 0; static size_t defaultTerrain = SIZE_MAX; +static size_t defaultOffroadFootstep = SIZE_MAX; /*-------------------------------------------------- size_t K_GetSplashHeapIndex(t_splash_t *splash) @@ -509,6 +511,114 @@ void K_SetDefaultFriction(mobj_t *mo) } } +/*-------------------------------------------------- + static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs) + + See header file for description. +--------------------------------------------------*/ +static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs) +{ + mobj_t *dust = NULL; + angle_t pushAngle = ANGLE_MAX; + angle_t tireAngle = ANGLE_MAX; + fixed_t momentum = INT32_MAX; + + if (mo->player != NULL) + { + tireAngle = (mo->player->drawangle + ANGLE_180); + } + else + { + tireAngle = (mo->angle + ANGLE_180); + } + + if ((leveltime / 2) & 1) + { + tireAngle -= ANGLE_45; + tireAngle -= P_RandomRange(0, ANGLE_11hh); + } + else + { + tireAngle += ANGLE_45; + tireAngle += P_RandomRange(0, ANGLE_11hh); + } + + pushAngle = K_MomentumAngle(mo) + ANGLE_180; + + dust = P_SpawnMobjFromMobj( + mo, + (P_RandomRange(-2, 2) * FRACUNIT) + (24 * FINECOSINE(tireAngle >> ANGLETOFINESHIFT)), + (P_RandomRange(-2, 2) * FRACUNIT) + (24 * FINESINE(tireAngle >> ANGLETOFINESHIFT)), + 0, fs->mobjType + ); + + P_SetTarget(&dust->target, mo); + dust->angle = K_MomentumAngle(mo); + + dust->destscale = FixedMul(mo->scale, fs->scale); + P_SetScale(dust, dust->destscale); + + dust->momx = mo->momx; + dust->momy = mo->momy; + dust->momz = mo->momz; + + momentum = P_AproxDistance(mo->momx, mo->momy) / 2; + dust->momx += FixedMul(momentum, FINECOSINE(pushAngle >> ANGLETOFINESHIFT)); + dust->momy += FixedMul(momentum, FINESINE(pushAngle >> ANGLETOFINESHIFT)); + dust->momz += (momentum / 16) * P_MobjFlip(mo); + + if (fs->color != SKINCOLOR_NONE) + { + dust->color = fs->color; + } + + if (fs->sfx != sfx_None && (leveltime % 6 == 0)) + { + S_StartSound(mo, fs->sfx); + } +} + +/*-------------------------------------------------- + void K_HandleFootstepParticles(mobj_t *mo) + + See header file for description. +--------------------------------------------------*/ +void K_HandleFootstepParticles(mobj_t *mo) +{ + t_footstep_t *fs = NULL; + + if (mo == NULL || P_MobjWasRemoved(mo) == true) + { + // Invalid object. + return; + } + + if (mo->terrain == NULL || mo->terrain->footstepID == SIZE_MAX) + { + // If no terrain, check for offroad. + // If we're in offroad, use the default particle. + + if (mo->player != NULL && mo->player->boostpower < FRACUNIT) + { + fs = K_GetFootstepByIndex(defaultOffroadFootstep); + } + } + else + { + fs = K_GetFootstepByIndex(mo->terrain->footstepID); + } + + if (fs == NULL || fs->mobjType == MT_NULL) + { + // No particles to spawn. + return; + } + + // Idea for later: if different spawning styles are desired, + // we can put a switch case here! + K_SpawnFootstepParticle(mo, fs); +} + /*-------------------------------------------------- static void K_FlagBoolean(UINT32 *inputFlags, UINT32 newFlag, char *val) @@ -550,6 +660,8 @@ static void K_SplashDefaults(t_splash_t *splash) { splash->mobjType = MT_NULL; splash->sfx = sfx_None; + splash->scale = FRACUNIT; + splash->color = SKINCOLOR_NONE; } /*-------------------------------------------------- @@ -590,11 +702,11 @@ static void K_ParseSplashParameter(size_t i, char *param, char *val) if (stricmp(param, "mobjType") == 0) { - splash->mobjType = get_mobjtype(val); + splash->mobjType = get_number(val) + 1; } else if (stricmp(param, "sfx") == 0) { - splash->sfx = get_sfx(val); + splash->sfx = get_number(val); } else if (stricmp(param, "scale") == 0) { @@ -602,7 +714,7 @@ static void K_ParseSplashParameter(size_t i, char *param, char *val) } else if (stricmp(param, "color") == 0) { - splash->color = get_skincolor(val); + splash->color = get_number(val); } } @@ -621,6 +733,8 @@ static void K_FootstepDefaults(t_footstep_t *footstep) { footstep->mobjType = MT_NULL; footstep->sfx = sfx_None; + footstep->scale = FRACUNIT; + footstep->color = SKINCOLOR_NONE; } /*-------------------------------------------------- @@ -661,11 +775,11 @@ static void K_ParseFootstepParameter(size_t i, char *param, char *val) if (stricmp(param, "mobjType") == 0) { - footstep->mobjType = get_mobjtype(val); + footstep->mobjType = get_number(val) + 1; } else if (stricmp(param, "sfx") == 0) { - footstep->sfx = get_sfx(val); + footstep->sfx = get_number(val); } else if (stricmp(param, "scale") == 0) { @@ -673,7 +787,7 @@ static void K_ParseFootstepParameter(size_t i, char *param, char *val) } else if (stricmp(param, "color") == 0) { - footstep->color = get_skincolor(val); + footstep->color = get_number(val); } } @@ -1090,6 +1204,7 @@ static boolean K_TERRAINLumpParser(UINT8 *data, size_t size) else { defaultTerrain = i; + CONS_Printf("DefaultTerrain set to '%s'\n", tkn); } } else @@ -1098,6 +1213,43 @@ static boolean K_TERRAINLumpParser(UINT8 *data, size_t size) valid = false; } } + else if (stricmp(tkn, "defaultOffroadFootstep") == 0) + { + Z_Free(tkn); + tkn = M_GetToken(NULL); + pos = M_GetTokenPos(); + + if (tkn && pos < size) + { + t_footstep_t *fs = NULL; + + for (i = 0; i < numFootstepDefs; i++) + { + fs = &footstepDefs[i]; + + if (stricmp(tkn, fs->name) == 0) + { + break; + } + } + + if (i == numFootstepDefs) + { + CONS_Alert(CONS_ERROR, "Invalid DefaultOffroadFootstep type.\n"); + valid = false; + } + else + { + defaultOffroadFootstep = i; + CONS_Printf("DefaultOffroadFootstep set to '%s'\n", tkn); + } + } + else + { + CONS_Alert(CONS_ERROR, "No DefaultOffroadFootstep type.\n"); + valid = false; + } + } else { CONS_Alert(CONS_ERROR, "Unknown field '%s' found in TERRAIN lump.\n", tkn); diff --git a/src/k_terrain.h b/src/k_terrain.h index d494f5edf..32921d393 100644 --- a/src/k_terrain.h +++ b/src/k_terrain.h @@ -394,6 +394,22 @@ void K_ProcessTerrainEffect(mobj_t *mo); void K_SetDefaultFriction(mobj_t *mo); +/*-------------------------------------------------- + void K_HandleFootstepParticles(mobj_t *mo); + + Spawns the footstep particles for an object's + terrain type. Intended to be called every tic. + + Input Arguments:- + mo - The object to spawn footsteps for. + + Return:- + None +--------------------------------------------------*/ + +void K_HandleFootstepParticles(mobj_t *mo); + + /*-------------------------------------------------- void K_InitTerrain(UINT16 wadNum); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index e07c41bd4..7f410310c 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -3588,11 +3588,10 @@ static int lib_kSpawnSparkleTrail(lua_State *L) static int lib_kSpawnWipeoutTrail(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - boolean offroad = lua_optboolean(L, 2); NOHUD if (!mo) return LUA_ErrInvalid(L, "mobj_t"); - K_SpawnWipeoutTrail(mo, offroad); + K_SpawnWipeoutTrail(mo); return 0; } diff --git a/src/p_user.c b/src/p_user.c index 0cd83dfc7..5a065e8d5 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2265,7 +2265,7 @@ void P_MovePlayer(player_t *player) K_SpawnSparkleTrail(player->mo); if (player->wipeoutslow > 1 && (leveltime & 1)) - K_SpawnWipeoutTrail(player->mo, false); + K_SpawnWipeoutTrail(player->mo); K_DriftDustHandling(player->mo); From 528ee29f2fa5f8a87489729cd8d45e922d5d8496 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 18 Dec 2021 23:30:57 -0500 Subject: [PATCH 17/69] Use mobjzmovement for footsteps --- src/k_terrain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_terrain.c b/src/k_terrain.c index 4f9f63cbf..d94acb886 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -560,7 +560,7 @@ static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs) dust->momx = mo->momx; dust->momy = mo->momy; - dust->momz = mo->momz; + dust->momz = P_GetMobjZMovement(mo) / 2; momentum = P_AproxDistance(mo->momx, mo->momy) / 2; dust->momx += FixedMul(momentum, FINECOSINE(pushAngle >> ANGLETOFINESHIFT)); From da459a9c73606c64de1f27ae943ee79ebcdc31d4 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 19 Dec 2021 00:57:45 -0500 Subject: [PATCH 18/69] Add terrain splashes --- src/k_terrain.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++-- src/k_terrain.h | 29 +++++++++++ src/p_local.h | 2 +- src/p_user.c | 10 ++-- 4 files changed, 156 insertions(+), 10 deletions(-) diff --git a/src/k_terrain.c b/src/k_terrain.c index d94acb886..1bbef1bcb 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -511,6 +511,102 @@ void K_SetDefaultFriction(mobj_t *mo) } } +/*-------------------------------------------------- + static void K_SpawnSplashParticles(mobj_t *mo, t_splash_t *s, fixed_t impact) + + See header file for description. +--------------------------------------------------*/ +static void K_SpawnSplashParticles(mobj_t *mo, t_splash_t *s, fixed_t impact) +{ + const UINT8 numParticles = s->numParticles; + const angle_t particleSpread = ANGLE_MAX / numParticles; + size_t i; + + for (i = 0; i < numParticles; i++) + { + mobj_t *dust = NULL; + angle_t pushAngle = (particleSpread * i); + fixed_t momH = INT32_MAX; + fixed_t momV = INT32_MAX; + + if (numParticles == 1) + { + // Random angle. + pushAngle = P_RandomRange(0, ANGLE_MAX); + } + + dust = P_SpawnMobjFromMobj( + mo, + (12 * FINECOSINE(pushAngle >> ANGLETOFINESHIFT)), + (12 * FINESINE(pushAngle >> ANGLETOFINESHIFT)), + 0, s->mobjType + ); + + P_SetTarget(&dust->target, mo); + dust->angle = pushAngle; + + dust->destscale = FixedMul(mo->scale, s->scale); + P_SetScale(dust, dust->destscale); + + dust->momx = mo->momx / 2; + dust->momy = mo->momy / 2; + dust->momz = 0; + + momH = FixedMul(impact, s->pushH); + momV = FixedMul(impact, s->pushV); + + dust->momx += FixedMul(momH, FINECOSINE(pushAngle >> ANGLETOFINESHIFT)); + dust->momy += FixedMul(momH, FINESINE(pushAngle >> ANGLETOFINESHIFT)); + dust->momz += momV * P_MobjFlip(mo); + + if (s->color != SKINCOLOR_NONE) + { + dust->color = s->color; + } + + if (s->sfx != sfx_None) + { + S_StartSound(mo, s->sfx); + } + } +} + +/*-------------------------------------------------- + void K_SpawnSplashForMobj(mobj_t *mo, fixed_t impact) + + See header file for description. +--------------------------------------------------*/ +void K_SpawnSplashForMobj(mobj_t *mo, fixed_t impact) +{ + t_splash_t *s = NULL; + + if (mo == NULL || P_MobjWasRemoved(mo) == true) + { + // Invalid object. + return; + } + + if (mo->terrain == NULL || mo->terrain->splashID == SIZE_MAX) + { + // No impact for this terrain type. + return; + } + else + { + s = K_GetSplashByIndex(mo->terrain->splashID); + } + + if (s == NULL || s->mobjType == MT_NULL || s->numParticles == 0) + { + // No particles to spawn. + return; + } + + // Idea for later: if different spawning styles are desired, + // we can put a switch case here! + K_SpawnSplashParticles(mo, s, impact); +} + /*-------------------------------------------------- static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs) @@ -522,6 +618,8 @@ static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs) angle_t pushAngle = ANGLE_MAX; angle_t tireAngle = ANGLE_MAX; fixed_t momentum = INT32_MAX; + fixed_t momH = INT32_MAX; + fixed_t momV = INT32_MAX; if (mo->player != NULL) { @@ -562,17 +660,20 @@ static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs) dust->momy = mo->momy; dust->momz = P_GetMobjZMovement(mo) / 2; - momentum = P_AproxDistance(mo->momx, mo->momy) / 2; - dust->momx += FixedMul(momentum, FINECOSINE(pushAngle >> ANGLETOFINESHIFT)); - dust->momy += FixedMul(momentum, FINESINE(pushAngle >> ANGLETOFINESHIFT)); - dust->momz += (momentum / 16) * P_MobjFlip(mo); + momentum = P_AproxDistance(mo->momx, mo->momy); + momH = FixedMul(momentum, fs->pushH); + momV = FixedMul(momentum, fs->pushV); + + dust->momx += FixedMul(momH, FINECOSINE(pushAngle >> ANGLETOFINESHIFT)); + dust->momy += FixedMul(momH, FINESINE(pushAngle >> ANGLETOFINESHIFT)); + dust->momz += (momV / 16) * P_MobjFlip(mo); if (fs->color != SKINCOLOR_NONE) { dust->color = fs->color; } - if (fs->sfx != sfx_None && (leveltime % 6 == 0)) + if ((fs->sfx != sfx_None) && (fs->sfxFreq > 0) && (leveltime % fs->sfxFreq == 0)) { S_StartSound(mo, fs->sfx); } @@ -662,6 +763,13 @@ static void K_SplashDefaults(t_splash_t *splash) splash->sfx = sfx_None; splash->scale = FRACUNIT; splash->color = SKINCOLOR_NONE; + + splash->pushH = FRACUNIT/4; + splash->pushV = FRACUNIT/64; + splash->spread = 2; + splash->cone = ANGLE_11hh; + + splash->numParticles = 8; } /*-------------------------------------------------- @@ -735,6 +843,13 @@ static void K_FootstepDefaults(t_footstep_t *footstep) footstep->sfx = sfx_None; footstep->scale = FRACUNIT; footstep->color = SKINCOLOR_NONE; + + footstep->pushH = FRACUNIT/2; + footstep->pushV = FRACUNIT/32; + footstep->spread = 2; + footstep->cone = ANGLE_11hh; + + footstep->sfxFreq = 6; } /*-------------------------------------------------- diff --git a/src/k_terrain.h b/src/k_terrain.h index 32921d393..e4055be23 100644 --- a/src/k_terrain.h +++ b/src/k_terrain.h @@ -33,6 +33,13 @@ typedef struct t_splash_s UINT16 sfx; // Sound to play. fixed_t scale; // Thing scale multiplier. UINT16 color; // Colorize effect. SKINCOLOR_NONE has no colorize. + + fixed_t pushH; // Push-out horizontal multiplier. + fixed_t pushV; // Push-out vertical multiplier. + fixed_t spread; // Randomized spread distance. + angle_t cone; // Randomized angle of the push-out. + + UINT8 numParticles; // Number of particles to spawn. } t_splash_t; typedef struct t_footstep_s @@ -46,6 +53,13 @@ typedef struct t_footstep_s UINT16 sfx; // Sound to play. fixed_t scale; // Thing scale multiplier. UINT16 color; // Colorize effect. SKINCOLOR_NONE has no colorize. + + fixed_t pushH; // Push-out horizontal multiplier. + fixed_t pushV; // Push-out vertical multiplier. + fixed_t spread; // Randomized spread distance. + angle_t cone; // Randomized angle of the push-out. + + tic_t sfxFreq; // How frequently to play the sound. } t_footstep_t; typedef enum @@ -394,6 +408,21 @@ void K_ProcessTerrainEffect(mobj_t *mo); void K_SetDefaultFriction(mobj_t *mo); +/*-------------------------------------------------- + void K_SpawnSplashForMobj(mobj_t *mo, fixed_t impact); + + Spawns the splash particles for an object's + terrain type. Intended to be called when hitting a floor. + + Input Arguments:- + mo - The object to spawn a splash for. + + Return:- + None +--------------------------------------------------*/ +void K_SpawnSplashForMobj(mobj_t *mo, fixed_t impact); + + /*-------------------------------------------------- void K_HandleFootstepParticles(mobj_t *mo); diff --git a/src/p_local.h b/src/p_local.h index 7ddf59875..b9802b106 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -168,7 +168,7 @@ boolean P_IsObjectOnGroundIn(mobj_t *mo, sector_t *sec); boolean P_IsObjectOnRealGround(mobj_t *mo, sector_t *sec); // SRB2Kart #define P_IsObjectFlipped(o) ((o)->eflags & MFE_VERTICALFLIP) boolean P_InQuicksand(mobj_t *mo); -boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff); +boolean P_PlayerHitFloor(player_t *player, boolean fromAir); void P_SetObjectMomZ(mobj_t *mo, fixed_t value, boolean relative); void P_RestoreMusic(player_t *player); diff --git a/src/p_user.c b/src/p_user.c index 5a065e8d5..9ba08e7d4 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -52,6 +52,7 @@ #include "k_respawn.h" #include "k_bot.h" #include "k_grandprix.h" +#include "k_terrain.h" // K_SpawnSplashForMobj #ifdef HW3SOUND #include "hardware/hw3sound.h" @@ -1274,17 +1275,18 @@ void P_DoPlayerExit(player_t *player) // // Handles player hitting floor surface. // Returns whether to clip momz. -boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) +boolean P_PlayerHitFloor(player_t *player, boolean fromAir) { boolean clipmomz; - (void)dorollstuff; - I_Assert(player->mo != NULL); clipmomz = !(P_CheckDeathPitCollide(player->mo)); - // SRB2Kart: removed lots of really vanilla-specific code here + if (fromAir == true && clipmomz == true) + { + K_SpawnSplashForMobj(player->mo, abs(player->mo->momz)); + } return clipmomz; } From 9bae31fd038de51e73b1d6401ce1b302581b6cc0 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 19 Dec 2021 01:09:37 -0500 Subject: [PATCH 19/69] Properly put in the parameters --- src/k_terrain.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/k_terrain.c b/src/k_terrain.c index 1bbef1bcb..8b8fa64df 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -824,6 +824,26 @@ static void K_ParseSplashParameter(size_t i, char *param, char *val) { splash->color = get_number(val); } + else if (stricmp(param, "pushH") == 0) + { + splash->pushH = FLOAT_TO_FIXED(atof(val)); + } + else if (stricmp(param, "pushV") == 0) + { + splash->pushV = FLOAT_TO_FIXED(atof(val)); + } + else if (stricmp(param, "spread") == 0) + { + splash->spread = FLOAT_TO_FIXED(atof(val)); + } + else if (stricmp(param, "cone") == 0) + { + splash->cone = AngleFixed(FLOAT_TO_FIXED(atof(val))); // lol + } + else if (stricmp(param, "numParticles") == 0) + { + splash->numParticles = (UINT8)atoi(val); + } } /*-------------------------------------------------- @@ -904,6 +924,26 @@ static void K_ParseFootstepParameter(size_t i, char *param, char *val) { footstep->color = get_number(val); } + else if (stricmp(param, "pushH") == 0) + { + footstep->pushH = FLOAT_TO_FIXED(atof(val)); + } + else if (stricmp(param, "pushV") == 0) + { + footstep->pushV = FLOAT_TO_FIXED(atof(val)); + } + else if (stricmp(param, "spread") == 0) + { + footstep->spread = FLOAT_TO_FIXED(atof(val)); + } + else if (stricmp(param, "cone") == 0) + { + footstep->cone = AngleFixed(FLOAT_TO_FIXED(atof(val))); // lol + } + else if (stricmp(param, "sfxFreq") == 0) + { + footstep->sfxFreq = (tic_t)atoi(val); + } } /*-------------------------------------------------- From 72b2997440d3ffc471b4cf327d3c8264b4de4dc4 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 23 Dec 2021 03:23:42 -0500 Subject: [PATCH 20/69] Remove off by one """"fix"""" --- src/k_terrain.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_terrain.c b/src/k_terrain.c index 8b8fa64df..d178b212c 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -810,7 +810,7 @@ static void K_ParseSplashParameter(size_t i, char *param, char *val) if (stricmp(param, "mobjType") == 0) { - splash->mobjType = get_number(val) + 1; + splash->mobjType = get_number(val); } else if (stricmp(param, "sfx") == 0) { @@ -910,7 +910,7 @@ static void K_ParseFootstepParameter(size_t i, char *param, char *val) if (stricmp(param, "mobjType") == 0) { - footstep->mobjType = get_number(val) + 1; + footstep->mobjType = get_number(val); } else if (stricmp(param, "sfx") == 0) { From d1827b1c161fc2f583c3f8c43d5b85bd4b2dbe92 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 23 Dec 2021 22:48:23 -0500 Subject: [PATCH 21/69] Fix it not using footstep->cone --- src/k_terrain.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_terrain.c b/src/k_terrain.c index d178b212c..0328d29b3 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -633,12 +633,12 @@ static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs) if ((leveltime / 2) & 1) { tireAngle -= ANGLE_45; - tireAngle -= P_RandomRange(0, ANGLE_11hh); + tireAngle -= P_RandomRange(0, footstep->cone); } else { tireAngle += ANGLE_45; - tireAngle += P_RandomRange(0, ANGLE_11hh); + tireAngle += P_RandomRange(0, footstep->cone); } pushAngle = K_MomentumAngle(mo) + ANGLE_180; From a0c36c6126cc566dba5825e45edcdfe772820a81 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 23 Dec 2021 22:50:57 -0500 Subject: [PATCH 22/69] Wrong var name oops I autopiloted --- src/k_terrain.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_terrain.c b/src/k_terrain.c index 0328d29b3..33c7d4cf9 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -633,12 +633,12 @@ static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs) if ((leveltime / 2) & 1) { tireAngle -= ANGLE_45; - tireAngle -= P_RandomRange(0, footstep->cone); + tireAngle -= P_RandomRange(0, fs->cone); } else { tireAngle += ANGLE_45; - tireAngle += P_RandomRange(0, footstep->cone); + tireAngle += P_RandomRange(0, fs->cone); } pushAngle = K_MomentumAngle(mo) + ANGLE_180; From 2d5d78b76e50565b7bb7c9126c135d503f77c09c Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 23 Dec 2021 22:58:25 -0500 Subject: [PATCH 23/69] Oops ... can't use raw angles for P_RandomRange anyway. --- src/k_terrain.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_terrain.c b/src/k_terrain.c index 33c7d4cf9..b50fead33 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -633,12 +633,12 @@ static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs) if ((leveltime / 2) & 1) { tireAngle -= ANGLE_45; - tireAngle -= P_RandomRange(0, fs->cone); + tireAngle -= P_RandomRange(0, fs->cone / ANG1) * ANG1; } else { tireAngle += ANGLE_45; - tireAngle += P_RandomRange(0, fs->cone); + tireAngle += P_RandomRange(0, fs->cone / ANG1) * ANG1; } pushAngle = K_MomentumAngle(mo) + ANGLE_180; From 8cdfe87dca006b2f741b9ef39ef7f8a5b36db41d Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 23 Dec 2021 23:15:36 -0500 Subject: [PATCH 24/69] Let's just convert this in a more sane fashion... --- src/k_terrain.c | 4 ++-- src/tables.c | 10 ++++++++++ src/tables.h | 2 ++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/k_terrain.c b/src/k_terrain.c index b50fead33..da5a93f90 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -838,7 +838,7 @@ static void K_ParseSplashParameter(size_t i, char *param, char *val) } else if (stricmp(param, "cone") == 0) { - splash->cone = AngleFixed(FLOAT_TO_FIXED(atof(val))); // lol + splash->cone = FloatToAngle(atof(val)); } else if (stricmp(param, "numParticles") == 0) { @@ -938,7 +938,7 @@ static void K_ParseFootstepParameter(size_t i, char *param, char *val) } else if (stricmp(param, "cone") == 0) { - footstep->cone = AngleFixed(FLOAT_TO_FIXED(atof(val))); // lol + footstep->cone = FloatToAngle(atof(val)); } else if (stricmp(param, "sfxFreq") == 0) { diff --git a/src/tables.c b/src/tables.c index 42ad6a73c..8c4dc50e1 100644 --- a/src/tables.c +++ b/src/tables.c @@ -185,6 +185,16 @@ INT32 AngleDeltaSigned(angle_t a1, angle_t a2) return (INT32)(a1) - (INT32)(a2); } +float AngleToFloat(angle_t x) +{ + return x / (float)ANG1; +} + +angle_t FloatToAngle(float f) +{ + return (angle_t)(f * ANG1); +} + #include "t_ftan.c" #include "t_fsin.c" diff --git a/src/tables.h b/src/tables.h index 5e5b6e57b..e122975e1 100644 --- a/src/tables.h +++ b/src/tables.h @@ -108,6 +108,8 @@ FUNCMATH angle_t FixedAngleC(fixed_t fa, fixed_t factor); // difference between two angle_t FUNCMATH INT32 AngleDelta(angle_t a1, angle_t a2); FUNCMATH INT32 AngleDeltaSigned(angle_t a1, angle_t a2); +FUNCMATH float AngleToFloat(angle_t x); +FUNCMATH angle_t FloatToAngle(float f); /// The FixedAcos function FUNCMATH angle_t FixedAcos(fixed_t x); From cdf75cfbe025df2d90144bd59b570aabd35a7d4b Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 23 Dec 2021 21:08:19 -0800 Subject: [PATCH 25/69] Fix incompatible prototype --- src/k_terrain.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/k_terrain.c b/src/k_terrain.c index da5a93f90..e365b2907 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -989,7 +989,7 @@ static void K_NewTerrainDefs(void) } /*-------------------------------------------------- - static void K_ParseTerrainParameter(UINT32 i, char *param, char *val) + static void K_ParseTerrainParameter(size_t i, char *param, char *val) Parser function for Terrain blocks. @@ -1001,7 +1001,7 @@ static void K_NewTerrainDefs(void) Return:- None --------------------------------------------------*/ -static void K_ParseTerrainParameter(UINT32 i, char *param, char *val) +static void K_ParseTerrainParameter(size_t i, char *param, char *val) { terrain_t *terrain = &terrainDefs[i]; @@ -1080,7 +1080,7 @@ static void K_NewTerrainFloorDefs(void) Return:- false if any errors occured, otherwise true. --------------------------------------------------*/ -static boolean K_DoTERRAINLumpParse(size_t num, void (*parser)(UINT32, char *, char *)) +static boolean K_DoTERRAINLumpParse(size_t num, void (*parser)(size_t, char *, char *)) { char *param, *val; From ff3cb90cda57da10c0f70ee7130529ede46661e8 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 24 Dec 2021 09:50:00 -0500 Subject: [PATCH 26/69] Super random push Looks better to me, and makes cone have a more pronounced effect --- src/k_terrain.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/k_terrain.c b/src/k_terrain.c index da5a93f90..907c610fa 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -630,19 +630,21 @@ static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs) tireAngle = (mo->angle + ANGLE_180); } + pushAngle = K_MomentumAngle(mo) + ANGLE_180; + if ((leveltime / 2) & 1) { tireAngle -= ANGLE_45; tireAngle -= P_RandomRange(0, fs->cone / ANG1) * ANG1; + pushAngle -= P_RandomRange(0, fs->cone / ANG1) * ANG1; } else { tireAngle += ANGLE_45; tireAngle += P_RandomRange(0, fs->cone / ANG1) * ANG1; + pushAngle += P_RandomRange(0, fs->cone / ANG1) * ANG1; } - pushAngle = K_MomentumAngle(mo) + ANGLE_180; - dust = P_SpawnMobjFromMobj( mo, (P_RandomRange(-2, 2) * FRACUNIT) + (24 * FINECOSINE(tireAngle >> ANGLETOFINESHIFT)), From ce01b494f4c56ff934aab508cd77e52ad996bae5 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 24 Dec 2021 11:30:19 -0500 Subject: [PATCH 27/69] Add functions to handle interpolation Much less code duplication --- src/hardware/hw_main.c | 60 +++++--------- src/hardware/hw_md2.c | 29 ++++--- src/k_hud.c | 180 +++++++++++------------------------------ src/r_fps.c | 21 ++++- src/r_fps.h | 3 + src/r_things.c | 52 +++++------- 6 files changed, 123 insertions(+), 222 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 0da791279..83f92c15f 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -40,9 +40,12 @@ #include "../r_things.h" // R_GetShadowZ #include "../d_main.h" #include "../p_slopes.h" -#include "../k_kart.h" // HITLAGJITTERS #include "hw_md2.h" +// SRB2Kart +#include "../k_kart.h" // HITLAGJITTERS +#include "../r_fps.h" + #ifdef NEWCLIP #include "hw_clip.h" #endif @@ -3641,17 +3644,9 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) fixed_t slopez; pslope_t *groundslope; - fixed_t interpx = thing->x; - fixed_t interpy = thing->y; - fixed_t interpz = thing->z; - - // do interpolation - if (cv_frameinterpolation.value == 1) - { - interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x); - interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y); - interpz = thing->old_z + FixedMul(rendertimefrac, thing->z - thing->old_z); - } + fixed_t interpx = R_InterpolateFixed(thing->old_x, thing->x); + fixed_t interpy = R_InterpolateFixed(thing->old_y, thing->y); + fixed_t interpz = R_InterpolateFixed(thing->old_z, thing->z); // hitlag vibrating (todo: interp somehow?) if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG)) @@ -5084,25 +5079,18 @@ static void HWR_ProjectSprite(mobj_t *thing) dispoffset = thing->info->dispoffset; - interpx = thing->x; - interpy = thing->y; - interpz = thing->z; - interpangle = (thing->player ? thing->player->drawangle : thing->angle); + interpx = R_InterpolateFixed(thing->old_x, thing->x); + interpy = R_InterpolateFixed(thing->old_y, thing->y); + interpz = R_InterpolateFixed(thing->old_z, thing->z); + interpangle = ANGLE_MAX; - if (cv_frameinterpolation.value == 1) + if (thing->player) { - interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x); - interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y); - interpz = thing->old_z + FixedMul(rendertimefrac, thing->z - thing->old_z); - - if (thing->player) - { - interpangle = thing->player->old_drawangle + FixedMul(rendertimefrac, thing->player->drawangle - thing->player->old_drawangle); - } - else - { - interpangle = thing->old_angle + FixedMul(rendertimefrac, thing->angle - thing->old_angle); - } + interpangle = R_InterpolateAngle(thing->player->old_drawangle, thing->player->drawangle); + } + else + { + interpangle = R_InterpolateAngle(thing->old_angle, thing->angle); } // hitlag vibrating (todo: interp somehow?) @@ -5526,17 +5514,9 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) if (!thing) return; - interpx = thing->x; - interpy = thing->y; - interpz = thing->z; - - // do interpolation - if (cv_frameinterpolation.value == 1) - { - interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x); - interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y); - interpz = thing->old_z + FixedMul(rendertimefrac, thing->z - thing->old_z); - } + interpx = R_InterpolateFixed(thing->old_x, thing->x); + interpy = R_InterpolateFixed(thing->old_y, thing->y); + interpz = R_InterpolateFixed(thing->old_z, thing->z); // transform the origin point tr_x = FIXED_TO_FLOAT(interpx) - gl_viewx; diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 95077a54a..cf9d0b5c8 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -46,6 +46,7 @@ // SRB2Kart #include "../k_color.h" #include "../k_kart.h" // HITLAGJITTERS +#include "../r_fps.h" #ifdef HAVE_PNG @@ -1368,17 +1369,9 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) INT32 mod; float finalscale; - fixed_t interpx = spr->mobj->x; - fixed_t interpy = spr->mobj->y; - fixed_t interpz = spr->mobj->z; - - // do interpolation - if (cv_frameinterpolation.value == 1) - { - interpx = spr->mobj->old_x + FixedMul(rendertimefrac, spr->mobj->x - spr->mobj->old_x); - interpy = spr->mobj->old_y + FixedMul(rendertimefrac, spr->mobj->y - spr->mobj->old_y); - interpz = spr->mobj->old_z + FixedMul(rendertimefrac, spr->mobj->z - spr->mobj->old_z); - } + fixed_t interpx = R_InterpolateFixed(spr->mobj->old_x, spr->mobj->x); + fixed_t interpy = R_InterpolateFixed(spr->mobj->old_y, spr->mobj->y); + fixed_t interpz = R_InterpolateFixed(spr->mobj->old_z, spr->mobj->z); // hitlag vibrating if (spr->mobj->hitlag > 0 && (spr->mobj->eflags & MFE_DAMAGEHITLAG)) @@ -1636,10 +1629,16 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) if (sprframe->rotate || papersprite) { - fixed_t anglef = AngleFixed(spr->mobj->angle); + fixed_t anglef = INT32_MAX; if (spr->mobj->player) - anglef = AngleFixed(spr->mobj->player->drawangle); + { + anglef = AngleFixed(R_InterpolateAngle(spr->mobj->player->old_drawangle, spr->mobj->player->drawangle)); + } + else + { + anglef = AngleFixed(R_InterpolateAngle(spr->mobj->old_angle, spr->mobj->angle)); + } p.angley = FIXED_TO_FLOAT(anglef); } @@ -1671,8 +1670,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr) } } - p.anglez = FIXED_TO_FLOAT(AngleFixed(spr->mobj->pitch)); - p.anglex = FIXED_TO_FLOAT(AngleFixed(spr->mobj->roll)); + p.anglez = FIXED_TO_FLOAT(AngleFixed(R_InterpolateAngle(spr->mobj->old_pitch, spr->mobj->pitch))); + p.anglex = FIXED_TO_FLOAT(AngleFixed(R_InterpolateAngle(spr->mobj->old_roll, spr->mobj->roll))); // SRB2CBTODO: MD2 scaling support finalscale *= FIXED_TO_FLOAT(spr->mobj->scale); diff --git a/src/k_hud.c b/src/k_hud.c index 7f54abd49..2490139c2 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -31,6 +31,7 @@ #include "r_main.h" #include "s_sound.h" #include "r_things.h" +#include "r_fps.h" #define NUMPOSNUMS 10 #define NUMPOSFRAMES 7 // White, three blues, three reds @@ -835,48 +836,26 @@ void K_ObjectTracking(trackingResult_t *result, vector3_t *point, UINT8 cameraNu return; } - // TODO: needs da interp + // TODO: parts need interp if (cam->chase == true && !player->spectator) { // Use the camera's properties. - viewpointX = cam->x; - viewpointY = cam->y; - viewpointZ = cam->z - point->z; - viewpointAngle = (INT32)cam->angle; - viewpointAiming = (INT32)cam->aiming; - viewpointRoll = (INT32)player->viewrollangle; - - if (cv_frameinterpolation.value == 1) - { - viewpointX = cam->old_x + FixedMul(rendertimefrac, cam->x - cam->old_x); - viewpointY = cam->old_y + FixedMul(rendertimefrac, cam->y - cam->old_y); - viewpointZ = (cam->old_z + FixedMul(rendertimefrac, cam->z - cam->old_z)) - point->z; - - viewpointAngle = (INT32)(cam->old_angle + FixedMul(rendertimefrac, cam->angle - cam->old_angle)); - viewpointAiming = (INT32)(cam->old_aiming + FixedMul(rendertimefrac, cam->aiming - cam->old_aiming)); - viewpointRoll = (INT32)(player->old_viewrollangle + FixedMul(rendertimefrac, player->viewrollangle - player->old_viewrollangle)); - } + viewpointX = R_InterpolateFixed(cam->old_x, cam->x); + viewpointY = R_InterpolateFixed(cam->old_y, cam->y); + viewpointZ = R_InterpolateFixed(cam->old_z, cam->z) - point->z; + viewpointAngle = (INT32)R_InterpolateAngle(cam->old_angle, cam->angle); + viewpointAiming = (INT32)R_InterpolateAngle(cam->old_aiming, cam->aiming); + viewpointRoll = (INT32)R_InterpolateAngle(player->old_viewrollangle, player->viewrollangle); } else { // Use player properties. - viewpointX = player->mo->x; - viewpointY = player->mo->y; - viewpointZ = player->viewz - point->z; - viewpointAngle = (INT32)player->mo->angle; + viewpointX = R_InterpolateFixed(player->mo->old_x, player->mo->x); + viewpointY = R_InterpolateFixed(player->mo->old_y, player->mo->y); + viewpointZ = R_InterpolateFixed(player->mo->old_z, player->mo->z) - point->z; //player->old_viewz + viewpointAngle = (INT32)R_InterpolateAngle(player->mo->old_angle, player->mo->angle); viewpointAiming = (INT32)player->aiming; - viewpointRoll = (INT32)player->viewrollangle; - - if (cv_frameinterpolation.value == 1) - { - viewpointX = player->mo->old_x + FixedMul(rendertimefrac, player->mo->x - player->mo->old_x); - viewpointY = player->mo->old_y + FixedMul(rendertimefrac, player->mo->y - player->mo->old_y); - viewpointZ = (player->mo->old_z + FixedMul(rendertimefrac, player->viewz - player->mo->old_z)) - point->z; //player->old_viewz - - viewpointAngle = (INT32)(player->mo->old_angle + FixedMul(rendertimefrac, player->mo->angle - player->mo->old_angle)); - //viewpointAiming = (INT32)(player->mo->old_aiming + FixedMul(rendertimefrac, player->mo->aiming - player->mo->old_aiming)); - viewpointRoll = (INT32)(player->old_viewrollangle + FixedMul(rendertimefrac, player->viewrollangle - player->old_viewrollangle)); - } + viewpointRoll = (INT32)R_InterpolateAngle(player->old_viewrollangle, player->viewrollangle); } viewpointAngle += (INT32)angleOffset; @@ -2631,24 +2610,13 @@ static void K_drawKartPlayerCheck(void) continue; } - v.x = checkplayer->mo->x; - v.y = checkplayer->mo->y; - v.z = checkplayer->mo->z; + v.x = R_InterpolateFixed(checkplayer->mo->old_x, checkplayer->mo->x); + v.y = R_InterpolateFixed(checkplayer->mo->old_y, checkplayer->mo->y); + v.z = R_InterpolateFixed(checkplayer->mo->old_z, checkplayer->mo->z); - pPos.x = stplyr->mo->x; - pPos.y = stplyr->mo->y; - pPos.z = stplyr->mo->z; - - if (cv_frameinterpolation.value == 1) - { - v.x = checkplayer->mo->old_x + FixedMul(rendertimefrac, checkplayer->mo->x - checkplayer->mo->old_x); - v.y = checkplayer->mo->old_y + FixedMul(rendertimefrac, checkplayer->mo->y - checkplayer->mo->old_y); - v.z = checkplayer->mo->old_z + FixedMul(rendertimefrac, checkplayer->mo->z - checkplayer->mo->old_z); - - pPos.x = stplyr->mo->old_x + FixedMul(rendertimefrac, stplyr->mo->x - stplyr->mo->old_x); - pPos.y = stplyr->mo->old_y + FixedMul(rendertimefrac, stplyr->mo->y - stplyr->mo->old_y); - pPos.z = stplyr->mo->old_z + FixedMul(rendertimefrac, stplyr->mo->z - stplyr->mo->old_z); - } + pPos.x = R_InterpolateFixed(stplyr->mo->old_x, stplyr->mo->x); + pPos.y = R_InterpolateFixed(stplyr->mo->old_y, stplyr->mo->y); + pPos.z = R_InterpolateFixed(stplyr->mo->old_z, stplyr->mo->z); distance = R_PointToDist2(pPos.x, pPos.y, v.x, v.y); @@ -2834,29 +2802,15 @@ static void K_drawKartNameTags(void) if (thiscam->chase == true) { - c.x = thiscam->x; - c.y = thiscam->y; - c.z = thiscam->z; - - if (cv_frameinterpolation.value == 1) - { - c.x = thiscam->old_x + FixedMul(rendertimefrac, thiscam->x - thiscam->old_x); - c.y = thiscam->old_y + FixedMul(rendertimefrac, thiscam->y - thiscam->old_y); - c.z = thiscam->old_z + FixedMul(rendertimefrac, thiscam->z - thiscam->old_z); - } + c.x = R_InterpolateFixed(thiscam->old_x, thiscam->x); + c.y = R_InterpolateFixed(thiscam->old_y, thiscam->y); + c.z = R_InterpolateFixed(thiscam->old_z, thiscam->z); } else { - c.x = stplyr->mo->x; - c.y = stplyr->mo->y; - c.z = stplyr->mo->z; - - if (cv_frameinterpolation.value == 1) - { - c.x = stplyr->mo->old_x + FixedMul(rendertimefrac, stplyr->mo->x - stplyr->mo->old_x); - c.y = stplyr->mo->old_y + FixedMul(rendertimefrac, stplyr->mo->y - stplyr->mo->old_y); - c.z = stplyr->mo->old_z + FixedMul(rendertimefrac, stplyr->mo->z - stplyr->mo->old_z); - } + c.x = R_InterpolateFixed(stplyr->mo->old_x, stplyr->mo->x); + c.y = R_InterpolateFixed(stplyr->mo->old_y, stplyr->mo->y); + c.z = R_InterpolateFixed(stplyr->mo->old_z, stplyr->mo->z); } for (i = 0; i < MAXPLAYERS; i++) @@ -2895,16 +2849,9 @@ static void K_drawKartNameTags(void) continue; } - v.x = ntplayer->mo->x; - v.y = ntplayer->mo->y; - v.z = ntplayer->mo->z; - - if (cv_frameinterpolation.value == 1) - { - v.x = ntplayer->mo->old_x + FixedMul(rendertimefrac, ntplayer->mo->x - ntplayer->mo->old_x); - v.y = ntplayer->mo->old_y + FixedMul(rendertimefrac, ntplayer->mo->y - ntplayer->mo->old_y); - v.z = ntplayer->mo->old_z + FixedMul(rendertimefrac, ntplayer->mo->z - ntplayer->mo->old_z); - } + v.x = R_InterpolateFixed(ntplayer->mo->old_x, ntplayer->mo->x); + v.y = R_InterpolateFixed(ntplayer->mo->old_x, ntplayer->mo->x); + v.z = R_InterpolateFixed(ntplayer->mo->old_x, ntplayer->mo->x); if (!(ntplayer->mo->eflags & MFE_VERTICALFLIP)) { @@ -2959,16 +2906,9 @@ static void K_drawKartNameTags(void) SINT8 localindicator = -1; vector3_t v; - v.x = ntplayer->mo->x; - v.y = ntplayer->mo->y; - v.z = ntplayer->mo->z; - - if (cv_frameinterpolation.value == 1) - { - v.x = ntplayer->mo->old_x + FixedMul(rendertimefrac, ntplayer->mo->x - ntplayer->mo->old_x); - v.y = ntplayer->mo->old_y + FixedMul(rendertimefrac, ntplayer->mo->y - ntplayer->mo->old_y); - v.z = ntplayer->mo->old_z + FixedMul(rendertimefrac, ntplayer->mo->z - ntplayer->mo->old_z); - } + v.x = R_InterpolateFixed(ntplayer->mo->old_x, ntplayer->mo->x); + v.y = R_InterpolateFixed(ntplayer->mo->old_y, ntplayer->mo->y); + v.z = R_InterpolateFixed(ntplayer->mo->old_z, ntplayer->mo->z); v.z += (ntplayer->mo->height / 2); @@ -3208,14 +3148,8 @@ static void K_drawKartMinimap(void) else colormap = NULL; - interpx = g->mo->x; - interpy = g->mo->y; - - if (cv_frameinterpolation.value == 1) - { - interpx = g->mo->old_x + FixedMul(rendertimefrac, g->mo->x - g->mo->old_x); - interpy = g->mo->old_y + FixedMul(rendertimefrac, g->mo->y - g->mo->old_y); - } + interpx = R_InterpolateFixed(g->mo->old_x, g->mo->x); + interpy = R_InterpolateFixed(g->mo->old_y, g->mo->y); K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap, AutomapPic); g = g->next; @@ -3273,14 +3207,8 @@ static void K_drawKartMinimap(void) else colormap = NULL; - interpx = players[i].mo->x; - interpy = players[i].mo->y; - - if (cv_frameinterpolation.value == 1) - { - interpx = players[i].mo->old_x + FixedMul(rendertimefrac, players[i].mo->x - players[i].mo->old_x); - interpy = players[i].mo->old_y + FixedMul(rendertimefrac, players[i].mo->y - players[i].mo->old_y); - } + interpx = R_InterpolateFixed(players[i].mo->old_x, players[i].mo->x); + interpy = R_InterpolateFixed(players[i].mo->old_y, players[i].mo->y); K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap, AutomapPic); // Target reticule @@ -3308,14 +3236,8 @@ static void K_drawKartMinimap(void) colormap = R_GetTranslationColormap(TC_RAINBOW, mobj->color, GTC_CACHE); } - interpx = mobj->x; - interpy = mobj->y; - - if (cv_frameinterpolation.value == 1) - { - interpx = mobj->old_x + FixedMul(rendertimefrac, mobj->x - mobj->old_x); - interpy = mobj->old_y + FixedMul(rendertimefrac, mobj->y - mobj->old_y); - } + interpx = R_InterpolateFixed(mobj->old_x, mobj->x); + interpy = R_InterpolateFixed(mobj->old_y, mobj->y); K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_spbminimap, colormap, AutomapPic); } @@ -3345,14 +3267,8 @@ static void K_drawKartMinimap(void) else colormap = NULL; - interpx = players[localplayers[i]].mo->x; - interpy = players[localplayers[i]].mo->y; - - if (cv_frameinterpolation.value == 1) - { - interpx = players[localplayers[i]].mo->old_x + FixedMul(rendertimefrac, players[localplayers[i]].mo->x - players[localplayers[i]].mo->old_x); - interpy = players[localplayers[i]].mo->old_y + FixedMul(rendertimefrac, players[localplayers[i]].mo->y - players[localplayers[i]].mo->old_y); - } + interpx = R_InterpolateFixed(players[localplayers[i]].mo->old_x, players[localplayers[i]].mo->x); + interpy = R_InterpolateFixed(players[localplayers[i]].mo->old_y, players[localplayers[i]].mo->y); K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap, AutomapPic); @@ -3631,7 +3547,7 @@ static void K_drawKartFinish(void) x = ((TICRATE - stplyr->karthud[khud_cardanimation])*(xval > x ? xval : x))/TICRATE; ox = ((TICRATE - (stplyr->karthud[khud_cardanimation] - 1))*(xval > x ? xval : x))/TICRATE; - interpx = ox + FixedMul(rendertimefrac, x - ox); + interpx = R_InterpolateFixed(ox, x); if (r_splitscreen && stplyr == &players[displayplayers[1]]) interpx = -interpx; @@ -4039,11 +3955,11 @@ static void K_drawLapStartAnim(void) newval = (BASEVIDWIDTH/2 + (32 * max(0, t - 76))) * FRACUNIT; oldval = (BASEVIDWIDTH/2 + (32 * max(0, tOld - 76))) * FRACUNIT; - interpx = oldval + FixedMul(rendertimefrac, newval - oldval); + interpx = R_InterpolateFixed(oldval, newval); newval = (48 - (32 * max(0, progress - 76))) * FRACUNIT; oldval = (48 - (32 * max(0, progressOld - 76))) * FRACUNIT; - interpy = oldval + FixedMul(rendertimefrac, newval - oldval); + interpy = R_InterpolateFixed(oldval, newval); V_DrawFixedPatch( interpx, interpy, @@ -4054,7 +3970,7 @@ static void K_drawLapStartAnim(void) { newval = (4 - abs((signed)((leveltime % 8) - 4))) * FRACUNIT; oldval = (4 - abs((signed)((leveltimeOld % 8) - 4))) * FRACUNIT; - interpy += oldval + FixedMul(rendertimefrac, newval - oldval); + interpy += R_InterpolateFixed(oldval, newval); V_DrawFixedPatch( interpx, interpy, @@ -4066,7 +3982,7 @@ static void K_drawLapStartAnim(void) { newval = (62 - (32 * max(0, progress - 76))) * FRACUNIT; oldval = (62 - (32 * max(0, progressOld - 76))) * FRACUNIT; - interpx = oldval + FixedMul(rendertimefrac, newval - oldval); + interpx = R_InterpolateFixed(oldval, newval); V_DrawFixedPatch( interpx, // 27 @@ -4078,7 +3994,7 @@ static void K_drawLapStartAnim(void) { newval = (188 + (32 * max(0, progress - 76))) * FRACUNIT; oldval = (188 + (32 * max(0, progressOld - 76))) * FRACUNIT; - interpx = oldval + FixedMul(rendertimefrac, newval - oldval); + interpx = R_InterpolateFixed(oldval, newval); V_DrawFixedPatch( interpx, // 194 @@ -4091,7 +4007,7 @@ static void K_drawLapStartAnim(void) { newval = (82 - (32 * max(0, progress - 76))) * FRACUNIT; oldval = (82 - (32 * max(0, progressOld - 76))) * FRACUNIT; - interpx = oldval + FixedMul(rendertimefrac, newval - oldval); + interpx = R_InterpolateFixed(oldval, newval); V_DrawFixedPatch( interpx, // 61 @@ -4103,7 +4019,7 @@ static void K_drawLapStartAnim(void) { newval = (188 + (32 * max(0, progress - 76))) * FRACUNIT; oldval = (188 + (32 * max(0, progressOld - 76))) * FRACUNIT; - interpx = oldval + FixedMul(rendertimefrac, newval - oldval); + interpx = R_InterpolateFixed(oldval, newval); V_DrawFixedPatch( interpx, // 194 @@ -4115,7 +4031,7 @@ static void K_drawLapStartAnim(void) { newval = (208 + (32 * max(0, progress - 76))) * FRACUNIT; oldval = (208 + (32 * max(0, progressOld - 76))) * FRACUNIT; - interpx = oldval + FixedMul(rendertimefrac, newval - oldval); + interpx = R_InterpolateFixed(oldval, newval); V_DrawFixedPatch( interpx, // 221 diff --git a/src/r_fps.c b/src/r_fps.c index 7258d3b75..59f10bae8 100644 --- a/src/r_fps.c +++ b/src/r_fps.c @@ -32,7 +32,6 @@ static viewvars_t skyview_new[MAXSPLITSCREENPLAYERS]; static viewvars_t *oldview = &pview_old[0]; viewvars_t *newview = &pview_new[0]; - enum viewcontext_e viewcontext = VIEWCONTEXT_PLAYER1; static fixed_t R_LerpFixed(fixed_t from, fixed_t to, fixed_t frac) @@ -147,3 +146,23 @@ void R_SetViewContext(enum viewcontext_e _viewcontext) break; } } + +fixed_t R_InterpolateFixed(fixed_t from, fixed_t to) +{ + if (cv_frameinterpolation.value == 0) + { + return to; + } + + return (from + R_LerpFixed(from, to, rendertimefrac)); +} + +angle_t R_InterpolateAngle(angle_t from, angle_t to) +{ + if (cv_frameinterpolation.value == 0) + { + return to; + } + + return (from + R_LerpAngle(from, to, rendertimefrac)); +} diff --git a/src/r_fps.h b/src/r_fps.h index eb674b142..246c16e64 100644 --- a/src/r_fps.h +++ b/src/r_fps.h @@ -56,4 +56,7 @@ void R_UpdateViewInterpolation(void); // Set the current view context (the viewvars pointed to by newview) void R_SetViewContext(enum viewcontext_e _viewcontext); +fixed_t R_InterpolateFixed(fixed_t from, fixed_t to); +angle_t R_InterpolateAngle(angle_t from, angle_t to); + #endif diff --git a/src/r_things.c b/src/r_things.c index 8636eeef0..ccd6740d8 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -46,6 +46,7 @@ // SRB2kart #include "k_color.h" #include "k_kart.h" // HITLAGJITTERS +#include "r_fps.h" #define MINZ (FRACUNIT*4) #define BASEYCENTER (BASEVIDHEIGHT/2) @@ -1468,26 +1469,18 @@ static void R_ProjectSprite(mobj_t *thing) #endif // uncapped/interpolation - fixed_t interpx = thing->x; - fixed_t interpy = thing->y; - fixed_t interpz = thing->z; - angle_t interpangle = (thing->player ? thing->player->drawangle : thing->angle); + fixed_t interpx = R_InterpolateFixed(thing->old_x, thing->x); + fixed_t interpy = R_InterpolateFixed(thing->old_y, thing->y); + fixed_t interpz = R_InterpolateFixed(thing->old_z, thing->z); + angle_t interpangle = ANGLE_MAX; - // do interpolation - if (cv_frameinterpolation.value == 1) + if (thing->player) { - interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x); - interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y); - interpz = thing->old_z + FixedMul(rendertimefrac, thing->z - thing->old_z); - - if (thing->player) - { - interpangle = thing->player->old_drawangle + FixedMul(rendertimefrac, thing->player->drawangle - thing->player->old_drawangle); - } - else - { - interpangle = thing->old_angle + FixedMul(rendertimefrac, thing->angle - thing->old_angle); - } + interpangle = R_InterpolateAngle(thing->player->old_drawangle, thing->player->drawangle); + } + else + { + interpangle = R_InterpolateAngle(thing->old_angle, thing->angle); } // hitlag vibrating (todo: interp somehow?) @@ -1815,11 +1808,10 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t linkscale; thing = thing->tracer; - if (cv_frameinterpolation.value == 1) - { - interpx = thing->old_x + FixedMul(thing->x - thing->old_x, rendertimefrac); - interpy = thing->old_y + FixedMul(thing->y - thing->old_y, rendertimefrac); - } + + interpx = R_InterpolateFixed(thing->old_x, thing->x); + interpy = R_InterpolateFixed(thing->old_y, thing->y); + interpz = R_InterpolateFixed(thing->old_z, thing->z); // hitlag vibrating (todo: interp somehow?) if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG)) @@ -2158,17 +2150,9 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) fixed_t gz, gzt; // uncapped/interpolation - fixed_t interpx = thing->x; - fixed_t interpy = thing->y; - fixed_t interpz = thing->z; - - // do interpolation - if (cv_frameinterpolation.value == 1) - { - interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x); - interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y); - interpz = thing->old_z + FixedMul(rendertimefrac, thing->z - thing->old_z); - } + fixed_t interpx = R_InterpolateFixed(thing->old_x, thing->x); + fixed_t interpy = R_InterpolateFixed(thing->old_y, thing->y); + fixed_t interpz = R_InterpolateFixed(thing->old_z, thing->z); // transform the origin point tr_x = interpx - viewx; From cc250afd4503ac9d65d50cbf0c05277c820b37dd Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 24 Dec 2021 12:45:51 -0500 Subject: [PATCH 28/69] P_InitAngle, to fix angle interpolation on spawning objects --- src/k_battle.c | 4 +- src/k_kart.c | 70 ++++++++++++++++++------------ src/k_race.c | 4 +- src/k_respawn.c | 4 +- src/lua_baselib.c | 41 +++++++++++++++++- src/p_enemy.c | 81 +++++++++++++++++----------------- src/p_inter.c | 20 ++++++--- src/p_local.h | 7 ++- src/p_map.c | 30 +++++++++++-- src/p_mobj.c | 108 +++++++++++++++++++++++++--------------------- src/p_saveg.c | 20 ++++----- src/p_slopes.c | 4 +- src/p_spec.c | 4 +- src/p_telept.c | 4 +- src/p_user.c | 20 ++++----- 15 files changed, 258 insertions(+), 163 deletions(-) diff --git a/src/k_battle.c b/src/k_battle.c index 8a5257206..c4902fb05 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -235,7 +235,7 @@ mobj_t *K_SpawnSphereBox(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 f (void)amount; - drop->angle = angle; + P_InitAngle(drop, angle); P_Thrust(drop, FixedAngle(P_RandomFixed() * 180) + angle, P_RandomRange(4, 12) * mapobjectscale); @@ -529,7 +529,7 @@ static void K_SpawnOvertimeLaser(fixed_t x, fixed_t y, fixed_t scale) mo->eflags |= MFE_VERTICALFLIP; } - mo->angle = R_PointToAngle2(mo->x, mo->y, battleovertime.x, battleovertime.y) + ANGLE_90; + P_InitAngle(mo, R_PointToAngle2(mo->x, mo->y, battleovertime.x, battleovertime.y) + ANGLE_90); mo->renderflags |= (RF_DONTDRAW & ~(K_GetPlayerDontDrawFlag(player))); P_SetScale(mo, scale); diff --git a/src/k_kart.c b/src/k_kart.c index 08b54f30b..4bc39f590 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1963,7 +1963,7 @@ void K_SpawnDashDustRelease(player_t *player) dust = P_SpawnMobj(newx, newy, player->mo->z, MT_FASTDUST); P_SetTarget(&dust->target, player->mo); - dust->angle = travelangle - ((i&1) ? -1 : 1)*ANGLE_45; + P_InitAngle(dust, travelangle - ((i&1) ? -1 : 1) * ANGLE_45); dust->destscale = player->mo->scale; P_SetScale(dust, player->mo->scale); @@ -2043,7 +2043,7 @@ void K_SpawnNormalSpeedLines(player_t *player) MT_FASTLINE); P_SetTarget(&fast->target, player->mo); - fast->angle = K_MomentumAngle(player->mo); + P_InitAngle(fast, K_MomentumAngle(player->mo)); fast->momx = 3*player->mo->momx/4; fast->momy = 3*player->mo->momy/4; fast->momz = 3*P_GetMobjZMovement(player->mo)/4; @@ -2071,7 +2071,7 @@ void K_SpawnInvincibilitySpeedLines(mobj_t *mo) fast->momz = 3*P_GetMobjZMovement(mo)/4; P_SetTarget(&fast->target, mo); - fast->angle = K_MomentumAngle(mo); + P_InitAngle(fast, K_MomentumAngle(mo)); fast->color = mo->color; fast->colorized = true; K_MatchGenericExtraFlags(fast, mo); @@ -3519,7 +3519,7 @@ void K_TakeBumpersFromPlayer(player_t *player, player_t *victim, UINT8 amount) P_SetTarget(&newmo->tracer, victim->mo); P_SetTarget(&newmo->target, player->mo); - newmo->angle = (diff * (newbumper-1)); + P_InitAngle(newmo, (diff * (newbumper-1))); newmo->color = victim->skincolor; if (newbumper+1 < 2) @@ -3600,7 +3600,7 @@ void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 mobj->z -= mobj->height>>1; // change angle - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, x, y); + P_InitAngle(mobj, R_PointToAngle2(mobj->x, mobj->y, x, y)); // change slope dist = P_AproxDistance(P_AproxDistance(x - mobj->x, y - mobj->y), z - mobj->z); @@ -3687,7 +3687,7 @@ void K_SpawnMineExplosion(mobj_t *source, UINT8 color) { dust = P_SpawnMobj(source->x, source->y, source->z, MT_SMOKE); P_SetMobjState(dust, S_OPAQUESMOKE1); - dust->angle = (ANGLE_180/16) * i; + P_InitAngle(dust, (ANGLE_180/16) * i); P_SetScale(dust, source->scale); dust->destscale = source->scale*10; dust->scalespeed = source->scale/12; @@ -3800,7 +3800,7 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I th->z = th->floorz; } - th->angle = an; + P_InitAngle(th, an); th->momx = FixedMul(finalspeed, FINECOSINE(an>>ANGLETOFINESHIFT)); th->momy = FixedMul(finalspeed, FINESINE(an>>ANGLETOFINESHIFT)); @@ -3968,7 +3968,7 @@ static void K_SpawnDriftElectricity(player_t *player) y = P_ReturnThrustY(mo, verticalangle, verticalradius) + P_ReturnThrustY(mo, horizonatalangle, horizontalradius); spark = P_SpawnMobjFromMobj(mo, x, y, 0, MT_DRIFTELECTRICITY); - spark->angle = sparkangle; + P_InitAngle(spark, sparkangle); spark->color = color; K_GenericExtraFlagsNoZAdjust(spark, mo); @@ -4010,7 +4010,7 @@ void K_SpawnDriftElectricSparks(player_t *player) fixed_t yoff = P_ReturnThrustY(mo, sparkangle, sparkradius); mobj_t *spark = P_SpawnMobjFromMobj(mo, x + xoff, y + yoff, z, MT_DRIFTELECTRICSPARK); - spark->angle = sparkangle; + P_InitAngle(spark, sparkangle); spark->color = color; P_InstaThrust(spark, mo->angle + ANGLE_90, hspeed); P_SetObjectMomZ(spark, vspeed, false); @@ -4061,7 +4061,7 @@ static void K_SpawnDriftSparks(player_t *player) spark = P_SpawnMobj(newx, newy, player->mo->z, MT_DRIFTSPARK); P_SetTarget(&spark->target, player->mo); - spark->angle = travelangle-(ANGLE_45/5)*player->drift; + P_InitAngle(spark, travelangle-(ANGLE_45/5)*player->drift); spark->destscale = player->mo->scale; P_SetScale(spark, player->mo->scale); @@ -4205,7 +4205,7 @@ static void K_SpawnAIZDust(player_t *player) newy = player->mo->y + P_ReturnThrustY(player->mo, travelangle - (player->aizdriftstrat*ANGLE_45), FixedMul(24*FRACUNIT, player->mo->scale)); spark = P_SpawnMobj(newx, newy, player->mo->z, MT_AIZDRIFTSTRAT); - spark->angle = travelangle+(player->aizdriftstrat*ANGLE_90); + P_InitAngle(spark, travelangle+(player->aizdriftstrat*ANGLE_90)); P_SetScale(spark, (spark->destscale = (3*player->mo->scale)>>2)); spark->momx = (6*player->mo->momx)/5; @@ -4257,7 +4257,7 @@ void K_SpawnBoostTrail(player_t *player) flame = P_SpawnMobj(newx, newy, ground, MT_SNEAKERTRAIL); P_SetTarget(&flame->target, player->mo); - flame->angle = travelangle; + P_InitAngle(flame, travelangle); flame->fuse = TICRATE*2; flame->destscale = player->mo->scale; P_SetScale(flame, player->mo->scale); @@ -4313,7 +4313,7 @@ void K_SpawnSparkleTrail(mobj_t *mo) newz = mo->z + (P_RandomRange(0, mo->height>>FRACBITS)*FRACUNIT); sparkle = P_SpawnMobj(newx, newy, newz, MT_SPARKLETRAIL); - sparkle->angle = R_PointToAngle2(mo->x, mo->y, sparkle->x, sparkle->y); + P_InitAngle(sparkle, R_PointToAngle2(mo->x, mo->y, sparkle->x, sparkle->y)); sparkle->movefactor = R_PointToDist2(mo->x, mo->y, sparkle->x, sparkle->y); // Save the distance we spawned away from the player. //CONS_Printf("movefactor: %d\n", sparkle->movefactor/FRACUNIT); sparkle->extravalue1 = (sparkle->z - mo->z); // Keep track of our Z position relative to the player's, I suppose. @@ -4359,7 +4359,7 @@ void K_SpawnWipeoutTrail(mobj_t *mo, boolean offroad) mo->z, MT_WIPEOUTTRAIL); P_SetTarget(&dust->target, mo); - dust->angle = K_MomentumAngle(mo); + P_InitAngle(dust, K_MomentumAngle(mo)); dust->destscale = mo->scale; P_SetScale(dust, mo->scale); K_FlipFromObject(dust, mo); @@ -4429,7 +4429,7 @@ void K_SpawnDraftDust(mobj_t *mo) P_SetMobjState(dust, S_DRAFTDUST1 + foff); P_SetTarget(&dust->target, mo); - dust->angle = ang - (ANGLE_90 * sign); // point completely perpendicular from the player + P_InitAngle(dust, ang - (ANGLE_90 * sign)); // point completely perpendicular from the player dust->destscale = mo->scale; P_SetScale(dust, mo->scale); K_FlipFromObject(dust, mo); @@ -4852,11 +4852,18 @@ void K_PuntMine(mobj_t *origMine, mobj_t *punter) mine = P_SpawnMobj(origMine->x, origMine->y, origMine->z, MT_SSMINE); P_SetTarget(&mine->target, mineOwner); + mine->angle = origMine->angle; mine->flags2 = origMine->flags2; mine->floorz = origMine->floorz; mine->ceilingz = origMine->ceilingz; + // Copy interp data + mine->old_angle = origMine->old_angle; + mine->old_x = origMine->old_x; + mine->old_y = origMine->old_y; + mine->old_z = origMine->old_z; + // Since we aren't using P_KillMobj, we need to clean up the hnext reference P_SetTarget(&mineOwner->hnext, NULL); mineOwner->player->bananadrag = 0; @@ -4932,7 +4939,7 @@ static void K_DoThunderShield(player_t *player) for (i=0; i<7; i++) { mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_THOK); - mo->angle = P_RandomRange(0, 359)*ANG1; + P_InitAngle(mo, P_RandomRange(0, 359)*ANG1); mo->fuse = P_RandomRange(20, 50); P_SetTarget(&mo->target, player->mo); P_SetMobjState(mo, S_KLIT1); @@ -4945,7 +4952,7 @@ static void K_DoThunderShield(player_t *player) sx = player->mo->x + FixedMul((player->mo->scale*THUNDERRADIUS), FINECOSINE((an*i)>>ANGLETOFINESHIFT)); sy = player->mo->y + FixedMul((player->mo->scale*THUNDERRADIUS), FINESINE((an*i)>>ANGLETOFINESHIFT)); mo = P_SpawnMobj(sx, sy, player->mo->z, MT_THOK); - mo-> angle = an*i; + P_InitAngle(mo, an*i); mo->extravalue1 = THUNDERRADIUS; // Used to know whether we should teleport by radius or something. mo->scale = player->mo->scale*3; P_SetTarget(&mo->target, player->mo); @@ -5263,7 +5270,7 @@ static void K_ThrowLandMine(player_t *player) P_SetScale(landMine, player->mo->scale); landMine->destscale = player->mo->destscale; - landMine->angle = player->mo->angle; + P_InitAngle(landMine, player->mo->angle); landMine->momz = (30 * mapobjectscale * P_MobjFlip(player->mo)) + player->mo->momz; landMine->color = player->skincolor; @@ -5419,6 +5426,12 @@ void K_DropHnextList(player_t *player, boolean keepshields) dropwork->floorz = work->floorz; dropwork->ceilingz = work->ceilingz; + // Copy interp data + dropwork->old_angle = work->old_angle; + dropwork->old_x = work->old_x; + dropwork->old_y = work->old_y; + dropwork->old_z = work->old_z; + if (ponground) { // floorz and ceilingz aren't properly set to account for FOFs and Polyobjects on spawn @@ -5506,7 +5519,7 @@ mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 P_SetScale(drop, drop->scale>>4); drop->destscale = (3*drop->destscale)/2; - drop->angle = angle; + P_InitAngle(drop, angle); P_Thrust(drop, FixedAngle(P_RandomFixed() * 180) + angle, 16*mapobjectscale); @@ -5864,7 +5877,7 @@ static void K_CalculateBananaSlope(mobj_t *mobj, fixed_t x, fixed_t y, fixed_t z } //mobj->standingslope = slope; - P_SetPitchRollFromSlope(mobj, slope); + P_InitPitchRollFromSlope(mobj, slope); } // Move the hnext chain! @@ -6956,7 +6969,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) { mobj_t *ring = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RING); ring->extravalue1 = 1; // Ring collect animation timer - ring->angle = player->mo->angle; // animation angle + P_InitAngle(ring, player->mo->angle); // animation angle P_SetTarget(&ring->target, player->mo); // toucher for thinker player->pickuprings++; if (player->superring <= 3) @@ -7768,6 +7781,7 @@ void K_SpawnDriftBoostExplosion(player_t *player, int stage) { mobj_t *overlay = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_DRIFTEXPLODE); + P_InitAngle(overlay, K_MomentumAngle(player->mo)); P_SetTarget(&overlay->target, player->mo); P_SetScale(overlay, (overlay->destscale = player->mo->scale)); K_FlipFromObject(overlay, player->mo); @@ -8313,9 +8327,9 @@ static void K_KartSpindashWind(mobj_t *parent) P_SetTarget(&wind->target, parent); if (parent->momx || parent->momy) - wind->angle = R_PointToAngle2(0, 0, parent->momx, parent->momy); + P_InitAngle(wind, R_PointToAngle2(0, 0, parent->momx, parent->momy)); else - wind->angle = parent->player->drawangle; + P_InitAngle(wind, parent->player->drawangle); wind->momx = 3 * parent->momx / 4; wind->momy = 3 * parent->momy / 4; @@ -8348,7 +8362,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 = K_MomentumAngle(player->mo); + P_InitAngle(grease, K_MomentumAngle(player->mo)); grease->extravalue1 = i; } } @@ -8762,7 +8776,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_ROCKETSNEAKER); K_MatchGenericExtraFlags(mo, player->mo); mo->flags |= MF_NOCLIPTHING; - mo->angle = player->mo->angle; + P_InitAngle(mo, player->mo->angle); mo->threshold = 10; mo->movecount = moloop%2; mo->movedir = mo->lastlook = moloop+1; @@ -8872,7 +8886,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) break; } mo->flags |= MF_NOCLIPTHING; - mo->angle = newangle; + P_InitAngle(mo, newangle); mo->threshold = 10; mo->movecount = player->itemamount; mo->movedir = mo->lastlook = moloop+1; @@ -8913,7 +8927,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) break; } mo->flags |= MF_NOCLIPTHING; - mo->angle = newangle; + P_InitAngle(mo, newangle); mo->threshold = 10; mo->movecount = player->itemamount; mo->movedir = mo->lastlook = moloop+1; @@ -9309,7 +9323,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) spdl = P_SpawnMobj(sx, sy, sz, MT_FASTLINE); P_SetTarget(&spdl->target, player->mo); - spdl->angle = R_PointToAngle2(spdl->x, spdl->y, player->mo->x, player->mo->y); + P_InitAngle(spdl, R_PointToAngle2(spdl->x, spdl->y, player->mo->x, player->mo->y)); spdl->rollangle = -ANG1*90*P_MobjFlip(player->mo); // angle them downwards relative to the player's gravity... spdl->spriteyscale = player->trickboostpower+FRACUNIT; spdl->momx = player->mo->momx; diff --git a/src/k_race.c b/src/k_race.c index ec3bd9b4f..f459e7a80 100644 --- a/src/k_race.c +++ b/src/k_race.c @@ -370,7 +370,7 @@ static void K_DrawFinishLineBeamForLine(fixed_t offset, angle_t aiming, line_t * P_SetMobjState(end1, S_FINISHBEAMEND1); end1->renderflags = RF_DONTDRAW & ~K_GetPlayerDontDrawFlag(&players[displayplayers[i]]); - end1->angle = lineangle; + P_InitAngle(end1, lineangle); end2 = P_SpawnMobj( v->x + (8*sx), @@ -381,7 +381,7 @@ static void K_DrawFinishLineBeamForLine(fixed_t offset, angle_t aiming, line_t * P_SetMobjState(end2, S_FINISHBEAMEND2); end2->renderflags = RF_DONTDRAW & ~K_GetPlayerDontDrawFlag(&players[displayplayers[i]]); - end2->angle = lineangle; + P_InitAngle(end2, lineangle); P_SetTarget(&end2->tracer, end1); end2->flags2 |= MF2_LINKDRAW; diff --git a/src/k_respawn.c b/src/k_respawn.c index 2e93a57d8..b79a5ca69 100644 --- a/src/k_respawn.c +++ b/src/k_respawn.c @@ -582,7 +582,7 @@ static void K_MovePlayerToRespawnPoint(player_t *player) P_SetTarget(&lasermo->target, player->mo); - lasermo->angle = stepha + ANGLE_90; + P_InitAngle(lasermo, stepha + ANGLE_90); P_SetScale(lasermo, (lasermo->destscale = player->mo->scale)); } } @@ -645,7 +645,7 @@ static void K_DropDashWait(player_t *player) P_SetTarget(&laser->target, player->mo); - laser->angle = newangle + ANGLE_90; + P_InitAngle(laser, newangle + ANGLE_90); laser->momz = (8 * player->mo->scale) * P_MobjFlip(player->mo); P_SetScale(laser, (laser->destscale = player->mo->scale)); } diff --git a/src/lua_baselib.c b/src/lua_baselib.c index e07c41bd4..eec97d2d0 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1415,7 +1415,7 @@ static int lib_pTeleportMove(lua_State *L) INLEVEL if (!thing) return LUA_ErrInvalid(L, "mobj_t"); - LUA_Deprecated(L, "P_TeleportMove", "P_SetOrigin or P_MoveOrigin"); + LUA_Deprecated(L, "P_TeleportMove", "P_SetOrigin\" or \"P_MoveOrigin"); lua_pushboolean(L, P_SetOrigin(thing, x, y, z)); LUA_PushUserdata(L, tmthing, META_MOBJ); P_SetTarget(&tmthing, ptmthing); @@ -1456,6 +1456,42 @@ static int lib_pMoveOrigin(lua_State *L) return 2; } +static int lib_pInitAngle(lua_State *L) +{ + mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + angle_t newValue = luaL_checkangle(L, 2); + NOHUD + INLEVEL + if (!thing) + return LUA_ErrInvalid(L, "mobj_t"); + P_InitAngle(thing, newValue); + return 0; +} + +static int lib_pInitPitch(lua_State *L) +{ + mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + angle_t newValue = luaL_checkangle(L, 2); + NOHUD + INLEVEL + if (!thing) + return LUA_ErrInvalid(L, "mobj_t"); + P_InitPitch(thing, newValue); + return 0; +} + +static int lib_pInitRoll(lua_State *L) +{ + mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + angle_t newValue = luaL_checkangle(L, 2); + NOHUD + INLEVEL + if (!thing) + return LUA_ErrInvalid(L, "mobj_t"); + P_InitRoll(thing, newValue); + return 0; +} + static int lib_pSlideMove(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); @@ -3872,6 +3908,9 @@ static luaL_Reg lib[] = { {"P_TeleportMove",lib_pTeleportMove}, {"P_SetOrigin",lib_pSetOrigin}, {"P_MoveOrigin",lib_pMoveOrigin}, + {"P_InitAngle",lib_pInitAngle}, + {"P_InitPitch",lib_pInitPitch}, + {"P_InitRoll",lib_pInitRoll}, {"P_SlideMove",lib_pSlideMove}, {"P_BounceMove",lib_pBounceMove}, {"P_CheckSight", lib_pCheckSight}, diff --git a/src/p_enemy.c b/src/p_enemy.c index 749d0dc09..0eccc5f55 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -1220,7 +1220,7 @@ void A_StatueBurst(mobj_t *actor) if (!locvar1 || !(new = P_SpawnMobjFromMobj(actor, 0, 0, 0, locvar1))) return; - new->angle = actor->angle; + P_InitAngle(new, actor->angle); P_SetTarget(&new->target, actor->target); if (locvar2) P_SetMobjState(new, (statenum_t)locvar2); @@ -2519,8 +2519,8 @@ void A_LobShot(mobj_t *actor) P_SetTarget(&shot->target, actor); // where it came from - shot->angle = an = actor->angle; - an >>= ANGLETOFINESHIFT; + P_InitAngle(shot, actor->angle); + an = actor->angle >> ANGLETOFINESHIFT; dist = P_AproxDistance(actor->target->x - shot->x, actor->target->y - shot->y); @@ -2886,7 +2886,7 @@ void A_Boss1Laser(mobj_t *actor) S_StartSound(actor, mobjinfo[locvar1].seesound); point = P_SpawnMobj(x + P_ReturnThrustX(actor, actor->angle, actor->radius), y + P_ReturnThrustY(actor, actor->angle, actor->radius), actor->z - actor->height / 2, MT_EGGMOBILE_TARGET); - point->angle = actor->angle; + P_InitAngle(point, actor->angle); point->fuse = dur+1; P_SetTarget(&point->target, actor->target); P_SetTarget(&actor->target, point); @@ -2896,7 +2896,7 @@ void A_Boss1Laser(mobj_t *actor) point = P_SpawnMobj(x, y, z, locvar1); P_SetTarget(&point->target, actor); - point->angle = actor->angle; + P_InitAngle(point, actor->angle); speed = point->radius; point->momz = FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT), speed); point->momx = FixedMul(FINESINE(angle>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(point->angle>>ANGLETOFINESHIFT), speed)); @@ -2905,7 +2905,7 @@ void A_Boss1Laser(mobj_t *actor) for (i = 0; i < 256; i++) { mobj_t *mo = P_SpawnMobj(point->x, point->y, point->z, point->type); - mo->angle = point->angle; + P_InitAngle(mo, point->angle); mo->color = LASERCOLORS[((UINT8)(i + 3*dur) >> 2) % sizeof(LASERCOLORS)]; // codeing P_UnsetThingPosition(mo); mo->flags = MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY; @@ -2937,7 +2937,7 @@ void A_Boss1Laser(mobj_t *actor) if (z - floorz < mobjinfo[MT_EGGMOBILE_FIRE].height>>1 && dur & 1) { point = P_SpawnMobj(x, y, floorz, MT_EGGMOBILE_FIRE); - point->angle = actor->angle; + P_InitAngle(point, actor->angle); point->destscale = actor->scale; P_SetScale(point, point->destscale); P_SetTarget(&point->target, actor); @@ -3521,7 +3521,7 @@ bossjustdie: P_ReturnThrustX(mo, mo->angle - ANGLE_90, 32<angle - ANGLE_90, 32<angle = mo->angle; + P_InitAngle(mo2, mo->angle); P_InstaThrust(mo2, mo2->angle - ANGLE_90, 4*mo2->scale); P_SetObjectMomZ(mo2, 4*FRACUNIT, false); P_SetMobjState(mo2, S_BOSSEGLZ1); @@ -3530,7 +3530,7 @@ bossjustdie: P_ReturnThrustX(mo, mo->angle + ANGLE_90, 32<angle + ANGLE_90, 32<angle = mo->angle; + P_InitAngle(mo2, mo->angle); P_InstaThrust(mo2, mo2->angle + ANGLE_90, 4*mo2->scale); P_SetObjectMomZ(mo2, 4*FRACUNIT, false); P_SetMobjState(mo2, S_BOSSEGLZ2); @@ -3542,7 +3542,7 @@ bossjustdie: P_ReturnThrustX(mo, mo->angle - ANGLE_90, 32<angle - ANGLE_90, 32<angle = mo->angle; + P_InitAngle(mo2, mo->angle); P_InstaThrust(mo2, mo2->angle - ANGLE_90, 4*mo2->scale); P_SetObjectMomZ(mo2, 4*FRACUNIT, false); P_SetMobjState(mo2, S_BOSSTANK1); @@ -3551,7 +3551,7 @@ bossjustdie: P_ReturnThrustX(mo, mo->angle + ANGLE_90, 32<angle + ANGLE_90, 32<angle = mo->angle; + P_InitAngle(mo2, mo->angle); P_InstaThrust(mo2, mo2->angle + ANGLE_90, 4*mo2->scale); P_SetObjectMomZ(mo2, 4*FRACUNIT, false); P_SetMobjState(mo2, S_BOSSTANK2); @@ -3559,7 +3559,7 @@ bossjustdie: mo2 = P_SpawnMobjFromMobj(mo, 0, 0, mobjinfo[MT_EGGMOBILE2].height + (32<angle = mo->angle; + P_InitAngle(mo2, mo->angle); P_SetObjectMomZ(mo2, 4*FRACUNIT, false); mo2->momz += mo->momz; P_SetMobjState(mo2, S_BOSSSPIGOT); @@ -3568,7 +3568,7 @@ bossjustdie: case MT_EGGMOBILE3: { mo2 = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_BOSSJUNK); - mo2->angle = mo->angle; + P_InitAngle(mo2, mo->angle); P_SetMobjState(mo2, S_BOSSSEBH1); } break; @@ -3642,7 +3642,8 @@ bossjustdie: pole->tracer->flags |= MF_NOCLIPTHING; P_SetScale(pole, (pole->destscale = 2*FRACUNIT)); P_SetScale(pole->tracer, (pole->tracer->destscale = 2*FRACUNIT)); - pole->angle = pole->tracer->angle = mo->tracer->angle; + P_InitAngle(pole, mo->tracer->angle); + P_InitAngle(pole->tracer, mo->tracer->angle); pole->tracer->tracer->angle = pole->angle - ANGLE_90; pole->momx = P_ReturnThrustX(pole, pole->angle, speed); pole->momy = P_ReturnThrustY(pole, pole->angle, speed); @@ -4011,7 +4012,7 @@ void A_AttractChase(mobj_t *actor) sparkle = P_SpawnMobj(actor->target->x, actor->target->y, actor->target->z, MT_RINGSPARKS); P_SetTarget(&sparkle->target, actor->target); - sparkle->angle = (actor->target->angle + (offset>>1)) + (offset * actor->target->player->sparkleanim); + P_InitAngle(sparkle, (actor->target->angle + (offset>>1)) + (offset * actor->target->player->sparkleanim)); actor->target->player->sparkleanim = (actor->target->player->sparkleanim+1) % 20; P_KillMobj(actor, actor->target, actor->target, DMG_NORMAL); @@ -5265,7 +5266,7 @@ void A_RockSpawn(mobj_t *actor) mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_FALLINGROCK); P_SetMobjState(mo, mobjinfo[type].spawnstate); - mo->angle = R_PointToAngle2(line->v2->x, line->v2->y, line->v1->x, line->v1->y); + P_InitAngle(mo, R_PointToAngle2(line->v2->x, line->v2->y, line->v1->x, line->v1->y)); P_InstaThrust(mo, mo->angle, dist + randomoomph); mo->momz = dist + randomoomph; @@ -7131,7 +7132,7 @@ void A_Boss3ShockThink(mobj_t *actor) snew->momx = (actor->momx + snext->momx) >> 1; snew->momy = (actor->momy + snext->momy) >> 1; snew->momz = (actor->momz + snext->momz) >> 1; // is this really needed? - snew->angle = (actor->angle + snext->angle) >> 1; + P_InitAngle(snew, (actor->angle + snext->angle) >> 1); P_SetTarget(&snew->target, actor->target); snew->fuse = actor->fuse; @@ -7283,7 +7284,7 @@ void A_SpawnObjectAbsolute(mobj_t *actor) mo = P_SpawnMobj(x<angle = actor->angle; + P_InitAngle(mo, actor->angle); if (actor->eflags & MFE_VERTICALFLIP) mo->flags2 |= MF2_OBJECTFLIP; @@ -7325,7 +7326,7 @@ void A_SpawnObjectRelative(mobj_t *actor) (actor->eflags & MFE_VERTICALFLIP) ? ((actor->z + actor->height - mobjinfo[type].height) - FixedMul(z<scale)) : (actor->z + FixedMul(z<scale)), type); // Spawn objects with an angle matching the spawner's, rather than spawning Eastwards - Monster Iestyn - mo->angle = actor->angle; + P_InitAngle(mo, actor->angle); if (actor->eflags & MFE_VERTICALFLIP) mo->flags2 |= MF2_OBJECTFLIP; @@ -8035,7 +8036,7 @@ void A_BossJetFume(mobj_t *actor) P_SetScale(filler, filler->destscale); if (actor->eflags & MFE_VERTICALFLIP) filler->flags2 |= MF2_OBJECTFLIP; - filler->angle = actor->angle - ANGLE_180; + P_InitAngle(filler, actor->angle - ANGLE_180); P_SetTarget(&actor->tracer, filler); }*/ @@ -9745,7 +9746,7 @@ void A_TrapShot(mobj_t *actor) S_StartSound(missile, missile->info->seesound); P_SetTarget(&missile->target, actor); - missile->angle = actor->angle; + P_InitAngle(missile, actor->angle); speed = FixedMul(missile->info->speed, missile->scale); @@ -10324,7 +10325,7 @@ void A_BrakLobShot(mobj_t *actor) S_StartSound(shot, shot->info->seesound); P_SetTarget(&shot->target, actor); // where it came from - shot->angle = actor->angle; + P_InitAngle(shot, actor->angle); // Horizontal axes first. First parameter is initial horizontal impulse, second is to correct its angle. shot->momx = FixedMul(FixedMul(v, FINECOSINE(theta >> ANGLETOFINESHIFT)), FINECOSINE(shot->angle >> ANGLETOFINESHIFT)); @@ -10391,7 +10392,7 @@ void A_NapalmScatter(mobj_t *actor) mo = P_SpawnMobj(actor->x, actor->y, actor->z, typeOfShot); P_SetTarget(&mo->target, actor->target); // Transfer target so Brak doesn't hit himself like an idiot - mo->angle = fa << ANGLETOFINESHIFT; + P_InitAngle(mo, fa << ANGLETOFINESHIFT); mo->momx = FixedMul(FINECOSINE(fa),vx); mo->momy = FixedMul(FINESINE(fa),vx); mo->momz = vy; @@ -10415,7 +10416,7 @@ void A_SpawnFreshCopy(mobj_t *actor) newObject = P_SpawnMobjFromMobj(actor, 0, 0, 0, actor->type); newObject->flags2 = actor->flags2 & MF2_AMBUSH; - newObject->angle = actor->angle; + P_InitAngle(newObject, actor->angle); newObject->color = actor->color; P_SetTarget(&newObject->target, actor->target); P_SetTarget(&newObject->tracer, actor->tracer); @@ -10451,7 +10452,7 @@ mobj_t *P_InternalFlickySpawn(mobj_t *actor, mobjtype_t flickytype, fixed_t momz } flicky = P_SpawnMobjFromMobj(actor, offsx, offsy, 0, flickytype); - flicky->angle = actor->angle; + P_InitAngle(flicky, actor->angle); if (flickytype == MT_SEED) flicky->z += P_MobjFlip(actor)*(actor->height - flicky->height)/2; @@ -10601,7 +10602,7 @@ void A_FlickyCenter(mobj_t *actor) else if (actor->flags & MF_SLIDEME) // aimless { actor->tracer->fuse = 0; // less than 2*TICRATE means move aimlessly. - actor->tracer->angle = P_RandomKey(180)*ANG2; + P_InitAngle(actor->tracer, P_RandomKey(180)*ANG2); } else //orbit actor->tracer->fuse = FRACUNIT; @@ -11302,7 +11303,7 @@ void A_ConnectToGround(mobj_t *actor) { work = P_SpawnMobjFromMobj(actor, 0, 0, workz, locvar1); if (work) - work->angle = ang; + P_InitAngle(work, ang); ang += ANGLE_90; workz += workh; } @@ -11348,7 +11349,7 @@ void A_SpawnParticleRelative(mobj_t *actor) (actor->eflags & MFE_VERTICALFLIP) ? ((actor->z + actor->height - mobjinfo[MT_PARTICLE].height) - FixedMul(z<scale)) : (actor->z + FixedMul(z<scale)), MT_PARTICLE); // Spawn objects with an angle matching the spawner's, rather than spawning Eastwards - Monster Iestyn - mo->angle = actor->angle; + P_InitAngle(mo, actor->angle); if (actor->eflags & MFE_VERTICALFLIP) mo->flags2 |= MF2_OBJECTFLIP; @@ -12095,7 +12096,7 @@ void A_Boss5MakeJunk(mobj_t *actor) broked->fuse = TICRATE; else broked->fuse = (((locvar2 & 1) ? 4 : 2)*TICRATE)/3; - broked->angle = ang; + P_InitAngle(broked, ang); P_InstaThrust(broked, ang, ((locvar2 & 2) ? 8 : 5)*actor->scale); P_SetObjectMomZ(broked, (((locvar2) ? 4 : 0) + P_RandomRange(2, 5))< 0) @@ -12174,7 +12175,7 @@ static void P_DustRing(mobjtype_t mobjtype, UINT32 div, fixed_t x, fixed_t y, fi mobjtype ); - dust->angle = ang*i + ANGLE_90; + P_InitAngle(dust, ang*i + ANGLE_90); P_SetScale(dust, FixedMul(initscale, scale)); dust->destscale = FixedMul(4*FRACUNIT + P_RandomFixed(), scale); dust->scalespeed = scale/24; @@ -12379,7 +12380,7 @@ static mobj_t *P_TrainSeg(mobj_t *src, fixed_t x, fixed_t y, fixed_t z, angle_t s->fuse = 16*TICRATE; s->sprite = spr; s->frame = frame|FF_PAPERSPRITE; - s->angle = ang; + P_InitAngle(s, ang); P_Thrust(s, src->angle, 7*FRACUNIT); return s; } @@ -12751,7 +12752,7 @@ void A_SaloonDoorSpawn(mobj_t *actor) // One door... if (!(door = P_SpawnMobjFromMobj(actor, c, s, 0, locvar1))) return; - door->angle = ang + ANGLE_180; + P_InitAngle(door, ang + ANGLE_180); door->extravalue1 = AngleFixed(door->angle); // Origin angle door->extravalue2 = 0; // Angular speed P_SetTarget(&door->tracer, actor); // Origin door @@ -12759,7 +12760,7 @@ void A_SaloonDoorSpawn(mobj_t *actor) // ...two door! if (!(door = P_SpawnMobjFromMobj(actor, -c, -s, 0, locvar1))) return; - door->angle = ang; + P_InitAngle(door, ang); door->extravalue1 = AngleFixed(door->angle); // Origin angle door->extravalue2 = 0; // Angular speed P_SetTarget(&door->tracer, actor); // Origin door @@ -12955,7 +12956,7 @@ void A_SpawnPterabytes(mobj_t *actor) c = FINECOSINE(fa); s = FINESINE(fa); waypoint = P_SpawnMobjFromMobj(actor, FixedMul(c, rad), FixedMul(s, rad), 0, MT_PTERABYTEWAYPOINT); - waypoint->angle = ang + ANGLE_90; + P_InitAngle(waypoint, ang + ANGLE_90); P_SetTarget(&waypoint->tracer, actor); ptera = P_SpawnMobjFromMobj(waypoint, 0, 0, 0, MT_PTERABYTE); ptera->angle = waypoint->angle; @@ -13129,7 +13130,7 @@ void A_DragonbomberSpawn(mobj_t *actor) segment = P_SpawnMobjFromMobj(mo, x, y, 0, MT_DRAGONTAIL); P_SetTarget(&segment->target, mo); P_SetTarget(&mo->tracer, segment); - segment->angle = mo->angle; + P_InitAngle(segment, mo->angle); mo = segment; } for (i = 0; i < 2; i++) // spawn wings @@ -13531,7 +13532,7 @@ static void SpawnSPBDust(mobj_t *mo) P_SetScale(dust, mo->scale*2); dust->colorized = true; dust->color = SKINCOLOR_RED; - dust->angle = mo->angle - FixedAngle(FRACUNIT*90 - FRACUNIT*180*i); // The first one will spawn to the right of the spb, the second one to the left. + P_InitAngle(dust, mo->angle - FixedAngle(FRACUNIT*90 - FRACUNIT*180*i)); // The first one will spawn to the right of the spb, the second one to the left. P_Thrust(dust, dust->angle, 6*dust->scale); K_MatchGenericExtraFlags(dust, mo); @@ -13568,7 +13569,7 @@ static void SpawnSPBAIZDust(mobj_t *mo, INT32 dir) spark->flags = MF_NOGRAVITY|MF_PAIN; P_SetTarget(&spark->target, mo); - spark->angle = travelangle+(dir*ANGLE_90); + P_InitAngle(spark, travelangle+(dir*ANGLE_90)); P_SetScale(spark, (spark->destscale = mo->scale*3/2)); spark->momx = (6*mo->momx)/5; @@ -13587,7 +13588,7 @@ static void SpawnSPBSpeedLines(mobj_t *actor) MT_FASTLINE); P_SetTarget(&fast->target, actor); - fast->angle = K_MomentumAngle(actor); + P_InitAngle(fast, K_MomentumAngle(actor)); fast->color = SKINCOLOR_RED; fast->colorized = true; K_MatchGenericExtraFlags(fast, actor); @@ -14289,7 +14290,7 @@ void A_RandomShadowFrame(mobj_t *actor) P_SetScale(fake, FRACUNIT*3/2); fake->scale = FRACUNIT*3/2; fake->destscale = FRACUNIT*3/2; - fake->angle = actor->angle; + P_InitAngle(fake, actor->angle); fake->tics = -1; actor->renderflags |= RF_DONTDRAW; actor->extravalue1 = 1; @@ -14677,6 +14678,8 @@ void A_FlameShieldPaper(mobj_t *actor) paper->frame |= framea; } + P_InitAngle(paper, paper->angle); + paper->extravalue1 = i; } } diff --git a/src/p_inter.c b/src/p_inter.c index 4dafa91c2..596bef294 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1184,7 +1184,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget mo->angle = FixedAngle((P_RandomKey(36)*10)<angle = mo->angle; + P_InitAngle(mo2, mo->angle); P_SetMobjState(mo2, S_BOSSSEBH2); if (++i == 2) // we've already removed 2 of these, let's stop now @@ -1251,6 +1251,12 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget kart->eflags |= MFE_DAMAGEHITLAG; P_SetObjectMomZ(kart, 6*FRACUNIT, false); kart->extravalue1 = target->player->kartweight; + + // Copy interp data + kart->old_angle = target->old_angle; + kart->old_x = target->old_x; + kart->old_y = target->old_y; + kart->old_z = target->old_z; } if (source && !P_MobjWasRemoved(source)) @@ -1322,7 +1328,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget for (i = 0; i < 2; i++) { mobj_t *blast = P_SpawnMobjFromMobj(target, 0, 0, target->info->height >> 1, MT_BATTLEBUMPER_BLAST); - blast->angle = angle + i*ANGLE_90; + P_InitAngle(blast, angle + i*ANGLE_90); P_SetScale(blast, 2*blast->scale/3); blast->destscale = 2*blast->scale; } @@ -1547,7 +1553,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget chunk = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_SPIKE);\ P_SetMobjState(chunk, target->info->xdeathstate);\ chunk->health = 0;\ - chunk->angle = angtweak;\ + P_InitAngle(chunk, angtweak);\ P_UnsetThingPosition(chunk);\ chunk->flags = MF_NOCLIP;\ chunk->x += xmov;\ @@ -1569,7 +1575,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget chunk = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_SPIKE); P_SetMobjState(chunk, target->info->deathstate); chunk->health = 0; - chunk->angle = ang + ANGLE_180; + P_InitAngle(chunk, ang + ANGLE_180); P_UnsetThingPosition(chunk); chunk->flags = MF_NOCLIP; chunk->x -= xoffs; @@ -1615,7 +1621,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget chunk = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_WALLSPIKE);\ P_SetMobjState(chunk, target->info->xdeathstate);\ chunk->health = 0;\ - chunk->angle = target->angle;\ + P_InitAngle(chunk, target->angle);\ P_UnsetThingPosition(chunk);\ chunk->flags = MF_NOCLIP;\ chunk->x += xmov - forwardxoffs;\ @@ -1641,7 +1647,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget P_SetMobjState(chunk, target->info->deathstate); chunk->health = 0; - chunk->angle = target->angle; + P_InitAngle(chunk, target->angle); P_UnsetThingPosition(chunk); chunk->flags = MF_NOCLIP; chunk->x += forwardxoffs - xoffs; @@ -1766,7 +1772,7 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, boom = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_FZEROBOOM); boom->scale = player->mo->scale; - boom->angle = player->mo->angle; + P_InitAngle(boom, player->mo->angle); P_SetTarget(&boom->target, player->mo); } diff --git a/src/p_local.h b/src/p_local.h index bfe8d9e08..0b71554da 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -410,6 +410,9 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff); boolean P_Move(mobj_t *actor, fixed_t speed); boolean P_SetOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z); boolean P_MoveOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z); +void P_InitAngle(mobj_t *thing, angle_t newValue); +void P_InitPitch(mobj_t *thing, angle_t newValue); +void P_InitRoll(mobj_t *thing, angle_t newValue); void P_SlideMove(mobj_t *mo); void P_BouncePlayerMove(mobj_t *mo); void P_BounceMove(mobj_t *mo); @@ -524,8 +527,8 @@ boolean P_CheckMissileSpawn(mobj_t *th); void P_Thrust(mobj_t *mo, angle_t angle, fixed_t move); void P_ExplodeMissile(mobj_t *mo); void P_CheckGravity(mobj_t *mo, boolean affect); -void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope); -void P_SetPitchRoll(mobj_t *mo, angle_t pitch, angle_t yaw); +void P_InitPitchRollFromSlope(mobj_t *mo, pslope_t *slope); +void P_InitPitchRoll(mobj_t *mo, angle_t pitch, angle_t yaw); fixed_t P_ScaleFromMap(fixed_t n, fixed_t scale); fixed_t P_GetMobjHead(const mobj_t *); fixed_t P_GetMobjFeet(const mobj_t *); diff --git a/src/p_map.c b/src/p_map.c index 28487e2e3..883eac52a 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -155,6 +155,30 @@ boolean P_MoveOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z) return P_TeleportMove(thing, x, y, z); } +// +// P_InitAngle - Change an object's angle, including interp values. +// +void P_InitAngle(mobj_t *thing, angle_t newValue) +{ + thing->angle = thing->old_angle = newValue; +} + +// +// P_InitPitch - Change an object's pitch, including interp values. +// +void P_InitPitch(mobj_t *thing, angle_t newValue) +{ + thing->pitch = thing->old_pitch = newValue; +} + +// +// P_InitRoll - Change an object's roll, including interp values. +// +void P_InitRoll(mobj_t *thing, angle_t newValue) +{ + thing->roll = thing->old_roll = newValue; +} + // ========================================================================= // MOVEMENT ITERATOR FUNCTIONS // ========================================================================= @@ -408,7 +432,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 = K_MomentumAngle(object); + P_InitAngle(grease, K_MomentumAngle(object)); grease->extravalue1 = i; } @@ -2662,7 +2686,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (thing->momz <= 0) { thing->standingslope = tmfloorslope; - P_SetPitchRollFromSlope(thing, thing->standingslope); + P_InitPitchRollFromSlope(thing, thing->standingslope); if (thing->momz == 0 && thing->player && !startingonground) P_PlayerHitFloor(thing->player, true); @@ -2675,7 +2699,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (thing->momz >= 0) { thing->standingslope = tmceilingslope; - P_SetPitchRollFromSlope(thing, thing->standingslope); + P_InitPitchRollFromSlope(thing, thing->standingslope); if (thing->momz == 0 && thing->player && !startingonground) P_PlayerHitFloor(thing->player, true); diff --git a/src/p_mobj.c b/src/p_mobj.c index 2981f6110..7bba60fa3 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1231,9 +1231,9 @@ void P_CheckGravity(mobj_t *mo, boolean affect) } // -// P_SetPitchRollFromSlope +// P_InitPitchRollFromSlope // -void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope) +void P_InitPitchRollFromSlope(mobj_t *mo, pslope_t *slope) { if (slope) { @@ -1251,9 +1251,9 @@ void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope) } // -// P_SetPitchRoll +// P_InitPitchRoll // -void P_SetPitchRoll(mobj_t *mo, angle_t pitch, angle_t yaw) +void P_InitPitchRoll(mobj_t *mo, angle_t pitch, angle_t yaw) { pitch = InvAngle(pitch); yaw >>= ANGLETOFINESHIFT; @@ -1671,7 +1671,7 @@ void P_XYMovement(mobj_t *mo) { mo->momz = transfermomz; mo->standingslope = NULL; - P_SetPitchRoll(mo, ANGLE_90, + P_InitPitchRoll(mo, ANGLE_90, transferslope->xydirection + (transferslope->zangle & ANGLE_180)); @@ -1753,7 +1753,7 @@ void P_XYMovement(mobj_t *mo) // Now compare the Zs of the different quantizations if (oldangle-newangle > ANG30 && oldangle-newangle < ANGLE_180) { // Allow for a bit of sticking - this value can be adjusted later mo->standingslope = oldslope; - P_SetPitchRollFromSlope(mo, mo->standingslope); + P_InitPitchRollFromSlope(mo, mo->standingslope); P_SlopeLaunch(mo); //CONS_Printf("launched off of slope - "); @@ -2277,7 +2277,7 @@ boolean P_ZMovement(mobj_t *mo) if (((mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope) && (mo->type != MT_STEAM)) { mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope; - P_SetPitchRollFromSlope(mo, mo->standingslope); + P_InitPitchRollFromSlope(mo, mo->standingslope); P_ReverseQuantizeMomentumToSlope(&mom, mo->standingslope); } @@ -2383,7 +2383,7 @@ boolean P_ZMovement(mobj_t *mo) MT_KART_TIRE ); - tire->angle = mo->angle; + P_InitAngle(tire, mo->angle); tire->fuse = 3*TICRATE; P_InstaThrust(tire, tireAngle, 4 * mo->scale); P_SetObjectMomZ(tire, 4*FRACUNIT, false); @@ -2403,7 +2403,7 @@ boolean P_ZMovement(mobj_t *mo) MT_KART_TIRE ); - tire->angle = mo->angle; + P_InitAngle(tire, mo->angle); tire->fuse = 3*TICRATE; P_InstaThrust(tire, tireAngle, 4 * mo->scale); P_SetObjectMomZ(tire, 4*FRACUNIT, false); @@ -4050,7 +4050,7 @@ static void P_SpawnItemCapsuleParts(mobj_t *mobj) part = part->hnext; P_SetTarget(&part->target, mobj); P_SetMobjState(part, buttState); - part->angle = i * ANG_CAPSULE; + P_InitAngle(part, i * ANG_CAPSULE); part->movedir = spin; // rotation speed part->movefactor = 0; // z offset part->extravalue1 = buttScale; // relative scale @@ -4061,7 +4061,7 @@ static void P_SpawnItemCapsuleParts(mobj_t *mobj) part = part->hnext; P_SetTarget(&part->target, mobj); P_SetMobjState(part, S_ITEMCAPSULE_TOP_SIDE); - part->angle = i * ANG_CAPSULE; + P_InitAngle(part, i * ANG_CAPSULE); part->movedir = spin; // rotation speed part->movefactor = mobj->info->height - part->info->height; // z offset } @@ -4386,7 +4386,7 @@ void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 numb mobj->z -= mobj->height>>1; // change angle - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, x, y); + P_InitAngle(mobj, R_PointToAngle2(mobj->x, mobj->y, x, y)); // change slope dist = P_AproxDistance(P_AproxDistance(x - mobj->x, y - mobj->y), z - mobj->z); @@ -5069,7 +5069,7 @@ static void P_FlameJetSceneryThink(mobj_t *mobj) flame = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_FLAMEJETFLAME); P_SetMobjState(flame, S_FLAMEJETFLAME4); - flame->angle = mobj->angle; + P_InitAngle(flame, mobj->angle); if (mobj->flags2 & MF2_AMBUSH) // Wave up and down instead of side-to-side flame->momz = mobj->fuse << (FRACBITS - 2); @@ -5530,7 +5530,7 @@ static void P_MobjSceneryThink(mobj_t *mobj) { mobj_t *blast = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_BATTLEBUMPER_BLAST); - blast->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy) + ANGLE_45; + P_InitAngle(blast, R_PointToAngle2(0, 0, mobj->momx, mobj->momy) + ANGLE_45); blast->destscale *= 4; if (i & 1) @@ -7399,7 +7399,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) mobj->z + (mobj->height/2) + (P_RandomRange(-20,20) * mobj->scale), MT_FASTLINE); - fast->angle = mobj->angle; + P_InitAngle(fast, mobj->angle); fast->momx = 3*mobj->target->momx/4; fast->momy = 3*mobj->target->momy/4; fast->momz = 3*P_GetMobjZMovement(mobj->target)/4; @@ -7461,7 +7461,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) if (underlayst != S_NULL) { mobj_t *underlay = P_SpawnMobj(mobj->target->x, mobj->target->y, mobj->target->z, MT_FLAMESHIELDUNDERLAY); - underlay->angle = mobj->angle; + P_InitAngle(underlay, mobj->angle); P_SetMobjState(underlay, underlayst); } break; @@ -8839,7 +8839,7 @@ static boolean P_FuseThink(mobj_t *mobj) for (i = 0; i < 5; i++) { mobj_t *debris = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_SMK_ICEBLOCK_DEBRIS); - debris->angle = FixedAngle(P_RandomRange(0,360)<angle, P_RandomRange(3,18)*(FRACUNIT/4)); debris->momz = P_RandomRange(4,8)<angle = mobj->angle + ((mobj->flags2 & MF2_AMBUSH) ? ANGLE_90 : ANGLE_270);; + P_InitAngle(bigmeatyclaw, mobj->angle + ((mobj->flags2 & MF2_AMBUSH) ? ANGLE_90 : ANGLE_270)); P_SetTarget(&mobj->tracer, bigmeatyclaw); P_SetTarget(&bigmeatyclaw->tracer, mobj); mobj->reactiontime >>= 1; @@ -9624,7 +9624,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) case MT_BANPYURA: { mobj_t *bigmeatyclaw = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_BANPSPRING); - bigmeatyclaw->angle = mobj->angle + ((mobj->flags2 & MF2_AMBUSH) ? ANGLE_90 : ANGLE_270);; + P_InitAngle(bigmeatyclaw, mobj->angle + ((mobj->flags2 & MF2_AMBUSH) ? ANGLE_90 : ANGLE_270)); P_SetTarget(&mobj->tracer, bigmeatyclaw); P_SetTarget(&bigmeatyclaw->tracer, mobj); mobj->reactiontime >>= 1; @@ -9757,7 +9757,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) break; case MT_MINECARTEND: P_SetTarget(&mobj->tracer, P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_MINECARTENDSOLID)); - mobj->tracer->angle = mobj->angle + ANGLE_90; + P_InitAngle(mobj->tracer, mobj->angle + ANGLE_90); break; case MT_TORCHFLOWER: { @@ -9879,7 +9879,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) angle_t ang = i * diff; mobj_t *side = P_SpawnMobj(mobj->x + FINECOSINE((ang>>ANGLETOFINESHIFT) & FINEMASK), mobj->y + FINESINE((ang>>ANGLETOFINESHIFT) & FINEMASK), mobj->z, MT_DAYTONAPINETREE_SIDE); - side->angle = ang; + P_InitAngle(side, ang); side->target = mobj; side->threshold = i; } @@ -9896,7 +9896,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) cur = P_SpawnMobj(mobj->x + FINECOSINE(((mobj->angle*8)>>ANGLETOFINESHIFT) & FINEMASK), mobj->y + FINESINE(((mobj->angle*8)>>ANGLETOFINESHIFT) & FINEMASK), mobj->z, MT_EZZPROPELLER_BLADE); - cur->angle = mobj->angle; + P_InitAngle(cur, mobj->angle); P_SetTarget(&cur->hprev, prev); P_SetTarget(&prev->hnext, cur); @@ -9956,7 +9956,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) cur->threshold = i; P_MoveOrigin(cur, cur->x + ((cur->radius>>FRACBITS) * FINECOSINE((FixedAngle((90*cur->threshold)<>ANGLETOFINESHIFT) & FINEMASK)), cur->y + ((cur->radius>>FRACBITS) * FINESINE((FixedAngle((90*cur->threshold)<>ANGLETOFINESHIFT) & FINEMASK)), cur->z); - cur->angle = ANGLE_90*(cur->threshold+1); + P_InitAngle(cur, ANGLE_90*(cur->threshold+1)); P_SetTarget(&cur->hprev, prev); P_SetTarget(&prev->hnext, cur); @@ -10717,7 +10717,7 @@ void P_SpawnPlayer(INT32 playernum) mobj = P_SpawnMobj(0, 0, 0, MT_PLAYER); (mobj->player = p)->mo = mobj; - mobj->angle = 0; + mobj->angle = mobj->old_angle = 0; // set color translations for player sprites mobj->color = p->skincolor; @@ -10804,6 +10804,12 @@ void P_AfterPlayerSpawn(INT32 playernum) mobj_t *mobj = p->mo; UINT8 i; + // Update interpolation + mobj->old_x = mobj->x; + mobj->old_y = mobj->y; + mobj->old_z = mobj->z; + mobj->old_angle = mobj->angle; + P_SetPlayerAngle(p, mobj->angle); p->viewheight = P_GetPlayerViewHeight(p); @@ -11398,7 +11404,7 @@ static boolean P_SetupMace(mapthing_t *mthing, mobj_t *mobj, boolean *doangle) spawnee->friction = mroll;\ spawnee->movefactor = mwidthset;\ spawnee->movecount = dist;\ - spawnee->angle = myaw;\ + P_InitAngle(spawnee, myaw);\ spawnee->flags |= (MF_NOGRAVITY|mflagsapply);\ spawnee->flags2 |= (mflags2apply|moreflags2);\ spawnee->eflags |= meflagsapply;\ @@ -11597,29 +11603,29 @@ static boolean P_SetupBooster(mapthing_t* mthing, mobj_t* mobj, boolean strong) statenum_t rollerstate = strong ? S_REDBOOSTERROLLER : S_YELLOWBOOSTERROLLER; mobj_t *seg = P_SpawnMobjFromMobj(mobj, 26*x1, 26*y1, 0, MT_BOOSTERSEG); - seg->angle = angle - ANGLE_90; + P_InitAngle(seg, angle - ANGLE_90); P_SetMobjState(seg, facestate); seg = P_SpawnMobjFromMobj(mobj, -26*x1, -26*y1, 0, MT_BOOSTERSEG); - seg->angle = angle + ANGLE_90; + P_InitAngle(seg, angle + ANGLE_90); P_SetMobjState(seg, facestate); seg = P_SpawnMobjFromMobj(mobj, 21*x2, 21*y2, 0, MT_BOOSTERSEG); - seg->angle = angle; + P_InitAngle(seg, angle); P_SetMobjState(seg, leftstate); seg = P_SpawnMobjFromMobj(mobj, -21*x2, -21*y2, 0, MT_BOOSTERSEG); - seg->angle = angle; + P_InitAngle(seg, angle); P_SetMobjState(seg, rightstate); seg = P_SpawnMobjFromMobj(mobj, 13*(x1 + x2), 13*(y1 + y2), 0, MT_BOOSTERROLLER); - seg->angle = angle; + P_InitAngle(seg, angle); P_SetMobjState(seg, rollerstate); seg = P_SpawnMobjFromMobj(mobj, 13*(x1 - x2), 13*(y1 - y2), 0, MT_BOOSTERROLLER); - seg->angle = angle; + P_InitAngle(seg, angle); P_SetMobjState(seg, rollerstate); seg = P_SpawnMobjFromMobj(mobj, -13*(x1 + x2), -13*(y1 + y2), 0, MT_BOOSTERROLLER); - seg->angle = angle; + P_InitAngle(seg, angle); P_SetMobjState(seg, rollerstate); seg = P_SpawnMobjFromMobj(mobj, -13*(x1 - x2), -13*(y1 - y2), 0, MT_BOOSTERROLLER); - seg->angle = angle; + P_InitAngle(seg, angle); P_SetMobjState(seg, rollerstate); return true; @@ -11796,19 +11802,19 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean case MT_THZTREE: { // Spawn the branches angle_t mobjangle = FixedAngle((mthing->angle % 113) << FRACBITS); - P_SpawnMobjFromMobj(mobj, FRACUNIT, 0, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_22h; - P_SpawnMobjFromMobj(mobj, 0, FRACUNIT, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_157h; - P_SpawnMobjFromMobj(mobj, -FRACUNIT, 0, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_270; + P_InitAngle(P_SpawnMobjFromMobj(mobj, FRACUNIT, 0, 0, MT_THZTREEBRANCH), mobjangle + ANGLE_22h); + P_InitAngle(P_SpawnMobjFromMobj(mobj, 0, FRACUNIT, 0, MT_THZTREEBRANCH), mobjangle + ANGLE_157h); + P_InitAngle(P_SpawnMobjFromMobj(mobj, -FRACUNIT, 0, 0, MT_THZTREEBRANCH), mobjangle + ANGLE_270); } break; case MT_CEZPOLE1: case MT_CEZPOLE2: { // Spawn the banner angle_t mobjangle = FixedAngle(mthing->angle << FRACBITS); - P_SpawnMobjFromMobj(mobj, + P_InitAngle(P_SpawnMobjFromMobj(mobj, P_ReturnThrustX(mobj, mobjangle, 4 << FRACBITS), P_ReturnThrustY(mobj, mobjangle, 4 << FRACBITS), - 0, ((mobj->type == MT_CEZPOLE1) ? MT_CEZBANNER1 : MT_CEZBANNER2))->angle = mobjangle + ANGLE_90; + 0, ((mobj->type == MT_CEZPOLE1) ? MT_CEZBANNER1 : MT_CEZBANNER2)), mobjangle + ANGLE_90); } break; case MT_HHZTREE_TOP: @@ -11817,7 +11823,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean mobj_t* leaf; #define doleaf(x, y) \ leaf = P_SpawnMobjFromMobj(mobj, x, y, 0, MT_HHZTREE_PART);\ - leaf->angle = mobjangle;\ + P_InitAngle(leaf, mobjangle);\ P_SetMobjState(leaf, leaf->info->seestate);\ mobjangle += ANGLE_90 doleaf(FRACUNIT, 0); @@ -11841,7 +11847,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean fixed_t xoffs = FINECOSINE(fa); fixed_t yoffs = FINESINE(fa); mobj_t* leaf = P_SpawnMobjFromMobj(mobj, xoffs, yoffs, 0, MT_BIGFERNLEAF); - leaf->angle = angle; + P_InitAngle(leaf, angle); angle += ANGLE_45; } break; @@ -11951,7 +11957,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean mobj->x - P_ReturnThrustX(mobj, mobjangle, baseradius), mobj->y - P_ReturnThrustY(mobj, mobjangle, baseradius), mobj->z, MT_WALLSPIKEBASE); - base->angle = mobjangle + ANGLE_90; + P_InitAngle(base, mobjangle + ANGLE_90); base->destscale = mobj->destscale; P_SetScale(base, mobj->scale); P_SetTarget(&base->target, mobj); @@ -12137,7 +12143,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean leaf = P_SpawnMobj(mobj->x + FINECOSINE((mobj->angle>>ANGLETOFINESHIFT) & FINEMASK), mobj->y + FINESINE((mobj->angle>>ANGLETOFINESHIFT) & FINEMASK), top, MT_AAZTREE_LEAF); - leaf->angle = mobj->angle; + P_InitAngle(leaf, mobj->angle); // Small coconut for each leaf P_SpawnMobj(mobj->x + (32 * FINECOSINE((mobj->angle>>ANGLETOFINESHIFT) & FINEMASK)), @@ -12354,7 +12360,9 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y, return mobj; if (doangle) - mobj->angle = FixedAngle(mthing->angle << FRACBITS); + { + P_InitAngle(mobj, FixedAngle(mthing->angle << FRACBITS)); + } if ((mobj->flags & MF_SPRING) && mobj->info->damage != 0 @@ -12366,8 +12374,8 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y, mobj->spryoff = FixedMul(mobj->radius, FINESINE(a >> ANGLETOFINESHIFT)); } - mobj->pitch = FixedAngle(mthing->pitch << FRACBITS); - mobj->roll = FixedAngle(mthing->roll << FRACBITS); + P_InitPitch(mobj, FixedAngle(mthing->pitch << FRACBITS)); + P_InitRoll(mobj, FixedAngle(mthing->roll << FRACBITS)); mthing->mobj = mobj; @@ -12774,7 +12782,7 @@ mobj_t *P_SpawnXYZMissile(mobj_t *source, mobj_t *dest, mobjtype_t type, P_SetTarget(&th->target, source); // where it came from an = R_PointToAngle2(x, y, dest->x, dest->y); - th->angle = an; + P_InitAngle(th, an); an >>= ANGLETOFINESHIFT; th->momx = FixedMul(speed, FINECOSINE(an)); th->momy = FixedMul(speed, FINESINE(an)); @@ -12836,7 +12844,7 @@ mobj_t *P_SpawnAlteredDirectionMissile(mobj_t *source, mobjtype_t type, fixed_t P_SetTarget(&th->target, source->target); // where it came from an = R_PointToAngle2(0, 0, source->momx, source->momy) + (ANG1*shiftingAngle); - th->angle = an; + P_InitAngle(th, an); an >>= ANGLETOFINESHIFT; th->momx = FixedMul(speed, FINECOSINE(an)); th->momy = FixedMul(speed, FINESINE(an)); @@ -12901,7 +12909,7 @@ mobj_t *P_SpawnPointMissile(mobj_t *source, fixed_t xa, fixed_t ya, fixed_t za, P_SetTarget(&th->target, source); // where it came from an = R_PointToAngle2(x, y, xa, ya); - th->angle = an; + P_InitAngle(th, an); an >>= ANGLETOFINESHIFT; th->momx = FixedMul(speed, FINECOSINE(an)); th->momy = FixedMul(speed, FINESINE(an)); @@ -12980,7 +12988,7 @@ mobj_t *P_SpawnMissile(mobj_t *source, mobj_t *dest, mobjtype_t type) else an = R_PointToAngle2(source->x, source->y, dest->x, dest->y); - th->angle = an; + P_InitAngle(th, an); an >>= ANGLETOFINESHIFT; th->momx = FixedMul(speed, FINECOSINE(an)); th->momy = FixedMul(speed, FINESINE(an)); @@ -13068,7 +13076,7 @@ mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle, UINT8 allowai speed = th->info->speed; - th->angle = an; + P_InitAngle(th, an); th->momx = FixedMul(speed, FINECOSINE(an>>ANGLETOFINESHIFT)); th->momy = FixedMul(speed, FINESINE(an>>ANGLETOFINESHIFT)); diff --git a/src/p_saveg.c b/src/p_saveg.c index 39a4fec28..357dbb0aa 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2885,19 +2885,19 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker) mobj->info = &mobjinfo[mobj->type]; if (diff & MD_POS) { - mobj->x = READFIXED(save_p); - mobj->y = READFIXED(save_p); - mobj->angle = READANGLE(save_p); - mobj->pitch = READANGLE(save_p); - mobj->roll = READANGLE(save_p); + mobj->x = mobj->old_x = READFIXED(save_p); + mobj->y = mobj->old_y = READFIXED(save_p); + mobj->angle = mobj->old_angle = READANGLE(save_p); + mobj->pitch = mobj->old_pitch = READANGLE(save_p); + mobj->roll = mobj->old_roll = READANGLE(save_p); } else { - mobj->x = mobj->spawnpoint->x << FRACBITS; - mobj->y = mobj->spawnpoint->y << FRACBITS; - mobj->angle = FixedAngle(mobj->spawnpoint->angle*FRACUNIT); - mobj->pitch = FixedAngle(mobj->spawnpoint->pitch*FRACUNIT); - mobj->roll = FixedAngle(mobj->spawnpoint->roll*FRACUNIT); + mobj->x = mobj->old_x = mobj->spawnpoint->x << FRACBITS; + mobj->y = mobj->old_y = mobj->spawnpoint->y << FRACBITS; + mobj->angle = mobj->old_angle = FixedAngle(mobj->spawnpoint->angle*FRACUNIT); + mobj->pitch = mobj->old_pitch = FixedAngle(mobj->spawnpoint->pitch*FRACUNIT); + mobj->roll = mobj->old_roll = FixedAngle(mobj->spawnpoint->roll*FRACUNIT); } if (diff & MD_MOM) { diff --git a/src/p_slopes.c b/src/p_slopes.c index 1bde8f4ee..b60e5e348 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -898,7 +898,7 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) if (P_MobjFlip(thing)*(thing->momz) < 0) // falling, land on slope { thing->standingslope = slope; - P_SetPitchRollFromSlope(thing, slope); + P_InitPitchRollFromSlope(thing, slope); thing->momz = -P_MobjFlip(thing); } return; @@ -914,7 +914,7 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) thing->momx = mom.x; thing->momy = mom.y; thing->standingslope = slope; - P_SetPitchRollFromSlope(thing, slope); + P_InitPitchRollFromSlope(thing, slope); thing->momz = -P_MobjFlip(thing); } } diff --git a/src/p_spec.c b/src/p_spec.c index caf4704d2..bf7784cd3 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3633,7 +3633,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (mobj) { if (line->flags & ML_EFFECT1) - mobj->angle = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y); + P_InitAngle(mobj, R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y)); CONS_Debug(DBG_GAMELOGIC, "Linedef Type %d - Spawn Object: %d spawned at (%d, %d, %d)\n", line->special, mobj->type, mobj->x>>FRACBITS, mobj->y>>FRACBITS, mobj->z>>FRACBITS); //TODO: Convert mobj->type to a string somehow. } else @@ -3928,7 +3928,7 @@ void P_SetupSignExit(player_t *player) if (player->mo && !P_MobjWasRemoved(player->mo)) { thing = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->floorz, MT_SIGN); - thing->angle = player->mo->angle; + P_InitAngle(thing, player->mo->angle); P_SetupSignObject(thing, player->mo, true); // Use :youfuckedup: sign face } } diff --git a/src/p_telept.c b/src/p_telept.c index 3e2917092..434994ce6 100644 --- a/src/p_telept.c +++ b/src/p_telept.c @@ -97,7 +97,7 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, P_FlashPal(thing->player, PAL_MIXUP, 10); } - thing->angle = angle; + P_InitAngle(thing, angle); thing->momx = thing->momy = thing->momz = 0; @@ -171,7 +171,7 @@ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle P_FlashPal(thing->player, PAL_MIXUP, 10); } - thing->angle = angle; + P_InitAngle(thing, angle); return true; } diff --git a/src/p_user.c b/src/p_user.c index 4837022e2..5813d1ac4 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -379,7 +379,7 @@ void P_GiveFinishFlags(player_t *player) fixed_t xoffs = FINECOSINE(fa); fixed_t yoffs = FINESINE(fa); mobj_t* flag = P_SpawnMobjFromMobj(player->mo, xoffs, yoffs, 0, MT_FINISHFLAG); - flag->angle = angle; + P_InitAngle(flag, angle); angle += FixedAngle(120*FRACUNIT); P_SetTarget(&flag->target, player->mo); @@ -2176,7 +2176,7 @@ void P_MovePlayer(player_t *player) if (trailScale > 0) { const angle_t forwardangle = K_MomentumAngle(player->mo); - const fixed_t playerVisualRadius = player->mo->radius + 8*FRACUNIT; + const fixed_t playerVisualRadius = player->mo->radius + (8 * player->mo->scale); const size_t numFrames = S_WATERTRAIL8 - S_WATERTRAIL1; const statenum_t curOverlayFrame = S_WATERTRAIL1 + (leveltime % numFrames); const statenum_t curUnderlayFrame = S_WATERTRAILUNDERLAY1 + (leveltime % numFrames); @@ -2197,7 +2197,7 @@ void P_MovePlayer(player_t *player) // underlay water = P_SpawnMobj(x1, y1, ((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_WATERTRAILUNDERLAY].height, player->mo->scale) : player->mo->watertop), MT_WATERTRAILUNDERLAY); - water->angle = forwardangle - ANGLE_180 - ANGLE_22h; + P_InitAngle(water, forwardangle - ANGLE_180 - ANGLE_22h); water->destscale = trailScale; water->momx = player->mo->momx; water->momy = player->mo->momy; @@ -2208,7 +2208,7 @@ void P_MovePlayer(player_t *player) // overlay water = P_SpawnMobj(x1, y1, ((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_WATERTRAIL].height, player->mo->scale) : player->mo->watertop), MT_WATERTRAIL); - water->angle = forwardangle - ANGLE_180 - ANGLE_22h; + P_InitAngle(water, forwardangle - ANGLE_180 - ANGLE_22h); water->destscale = trailScale; water->momx = player->mo->momx; water->momy = player->mo->momy; @@ -2220,7 +2220,7 @@ void P_MovePlayer(player_t *player) // Underlay water = P_SpawnMobj(x2, y2, ((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_WATERTRAILUNDERLAY].height, player->mo->scale) : player->mo->watertop), MT_WATERTRAILUNDERLAY); - water->angle = forwardangle - ANGLE_180 + ANGLE_22h; + P_InitAngle(water, forwardangle - ANGLE_180 + ANGLE_22h); water->destscale = trailScale; water->momx = player->mo->momx; water->momy = player->mo->momy; @@ -2231,7 +2231,7 @@ void P_MovePlayer(player_t *player) // Overlay water = P_SpawnMobj(x2, y2, ((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_WATERTRAIL].height, player->mo->scale) : player->mo->watertop), MT_WATERTRAIL); - water->angle = forwardangle - ANGLE_180 + ANGLE_22h; + P_InitAngle(water, forwardangle - ANGLE_180 + ANGLE_22h); water->destscale = trailScale; water->momx = player->mo->momx; water->momy = player->mo->momy; @@ -3989,7 +3989,7 @@ static void P_HandleFollower(player_t *player) P_SetTarget(&player->follower, P_SpawnMobj(sx, sy, sz, MT_FOLLOWER)); P_SetFollowerState(player->follower, fl.idlestate); P_SetTarget(&player->follower->target, player->mo); // we need that to know when we need to disappear - player->follower->angle = player->mo->angle; + P_InitAngle(player->follower, player->mo->angle); // This is safe to only spawn it here, the follower is removed then respawned when switched. if (bubble) @@ -4052,10 +4052,8 @@ static void P_HandleFollower(player_t *player) if (player->pflags & PF_NOCONTEST) player->follower->renderflags |= RF_DONTDRAW; - if (player->speed && (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 + // if we're moving let's make the angle the direction we're moving towards. This is to avoid drifting / reverse looking awkward. + player->follower->angle = K_MomentumAngle(player->follower); // Finally, if the follower has bubbles, move them, set their scale, etc.... // This is what I meant earlier by it being easier, now we can just use this weird lil loop to get the job done! From 6c13ddca01d32489367b5182995400a35c47d8f0 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 24 Dec 2021 13:00:12 -0500 Subject: [PATCH 29/69] Rename PitchRoll stuff back I did a find+replace because I realized the functions I added were named too similar to other ones & to make the purpose more obvious ... but it ended up changing them too anyway! Gah! --- src/k_kart.c | 2 +- src/p_local.h | 4 ++-- src/p_map.c | 4 ++-- src/p_mobj.c | 14 +++++++------- src/p_slopes.c | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 4bc39f590..2dacce0ef 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -5877,7 +5877,7 @@ static void K_CalculateBananaSlope(mobj_t *mobj, fixed_t x, fixed_t y, fixed_t z } //mobj->standingslope = slope; - P_InitPitchRollFromSlope(mobj, slope); + P_SetPitchRollFromSlope(mobj, slope); } // Move the hnext chain! diff --git a/src/p_local.h b/src/p_local.h index 0b71554da..51a43b639 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -527,8 +527,8 @@ boolean P_CheckMissileSpawn(mobj_t *th); void P_Thrust(mobj_t *mo, angle_t angle, fixed_t move); void P_ExplodeMissile(mobj_t *mo); void P_CheckGravity(mobj_t *mo, boolean affect); -void P_InitPitchRollFromSlope(mobj_t *mo, pslope_t *slope); -void P_InitPitchRoll(mobj_t *mo, angle_t pitch, angle_t yaw); +void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope); +void P_SetPitchRoll(mobj_t *mo, angle_t pitch, angle_t yaw); fixed_t P_ScaleFromMap(fixed_t n, fixed_t scale); fixed_t P_GetMobjHead(const mobj_t *); fixed_t P_GetMobjFeet(const mobj_t *); diff --git a/src/p_map.c b/src/p_map.c index 883eac52a..7899a0964 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2686,7 +2686,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (thing->momz <= 0) { thing->standingslope = tmfloorslope; - P_InitPitchRollFromSlope(thing, thing->standingslope); + P_SetPitchRollFromSlope(thing, thing->standingslope); if (thing->momz == 0 && thing->player && !startingonground) P_PlayerHitFloor(thing->player, true); @@ -2699,7 +2699,7 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) if (thing->momz >= 0) { thing->standingslope = tmceilingslope; - P_InitPitchRollFromSlope(thing, thing->standingslope); + P_SetPitchRollFromSlope(thing, thing->standingslope); if (thing->momz == 0 && thing->player && !startingonground) P_PlayerHitFloor(thing->player, true); diff --git a/src/p_mobj.c b/src/p_mobj.c index 7bba60fa3..c8b1ca4d0 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1231,9 +1231,9 @@ void P_CheckGravity(mobj_t *mo, boolean affect) } // -// P_InitPitchRollFromSlope +// P_SetPitchRollFromSlope // -void P_InitPitchRollFromSlope(mobj_t *mo, pslope_t *slope) +void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope) { if (slope) { @@ -1251,9 +1251,9 @@ void P_InitPitchRollFromSlope(mobj_t *mo, pslope_t *slope) } // -// P_InitPitchRoll +// P_SetPitchRoll // -void P_InitPitchRoll(mobj_t *mo, angle_t pitch, angle_t yaw) +void P_SetPitchRoll(mobj_t *mo, angle_t pitch, angle_t yaw) { pitch = InvAngle(pitch); yaw >>= ANGLETOFINESHIFT; @@ -1671,7 +1671,7 @@ void P_XYMovement(mobj_t *mo) { mo->momz = transfermomz; mo->standingslope = NULL; - P_InitPitchRoll(mo, ANGLE_90, + P_SetPitchRoll(mo, ANGLE_90, transferslope->xydirection + (transferslope->zangle & ANGLE_180)); @@ -1753,7 +1753,7 @@ void P_XYMovement(mobj_t *mo) // Now compare the Zs of the different quantizations if (oldangle-newangle > ANG30 && oldangle-newangle < ANGLE_180) { // Allow for a bit of sticking - this value can be adjusted later mo->standingslope = oldslope; - P_InitPitchRollFromSlope(mo, mo->standingslope); + P_SetPitchRollFromSlope(mo, mo->standingslope); P_SlopeLaunch(mo); //CONS_Printf("launched off of slope - "); @@ -2277,7 +2277,7 @@ boolean P_ZMovement(mobj_t *mo) if (((mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope) && (mo->type != MT_STEAM)) { mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope; - P_InitPitchRollFromSlope(mo, mo->standingslope); + P_SetPitchRollFromSlope(mo, mo->standingslope); P_ReverseQuantizeMomentumToSlope(&mom, mo->standingslope); } diff --git a/src/p_slopes.c b/src/p_slopes.c index b60e5e348..1bde8f4ee 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -898,7 +898,7 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) if (P_MobjFlip(thing)*(thing->momz) < 0) // falling, land on slope { thing->standingslope = slope; - P_InitPitchRollFromSlope(thing, slope); + P_SetPitchRollFromSlope(thing, slope); thing->momz = -P_MobjFlip(thing); } return; @@ -914,7 +914,7 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) thing->momx = mom.x; thing->momy = mom.y; thing->standingslope = slope; - P_InitPitchRollFromSlope(thing, slope); + P_SetPitchRollFromSlope(thing, slope); thing->momz = -P_MobjFlip(thing); } } From 0a915a719b17d2b3204304e57ada9a4b07a69b6b Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 24 Dec 2021 13:17:57 -0500 Subject: [PATCH 30/69] Hack to fix drift spark explosion while keeping its interpolation --- src/p_mobj.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index c8b1ca4d0..269d99652 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -6815,12 +6815,15 @@ static boolean P_MobjRegularThink(mobj_t *mobj) if (( mobj->fuse & 1 )) { nudge = 4*mobj->target->radius; + /* unrotate interp angle */ + mobj->old_angle -= ANGLE_90; } else { nudge = 2*mobj->target->radius; /* rotate the papersprite frames to see the flat angle */ mobj->angle += ANGLE_90; + mobj->old_angle += ANGLE_90; } P_MoveOrigin(mobj, From d63ce0c803982df2608f568e0a8c2c6b68edb0e1 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 24 Dec 2021 22:52:38 -0500 Subject: [PATCH 31/69] Fix jawz reticule in uncapped --- src/k_kart.c | 3 +++ src/p_enemy.c | 3 +++ src/p_mobj.c | 3 +++ 3 files changed, 9 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index 2dacce0ef..28d351ba6 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -7161,6 +7161,9 @@ void K_KartPlayerAfterThink(player_t *player) } ret = P_SpawnMobj(targ->mo->x, targ->mo->y, targ->mo->z, MT_PLAYERRETICULE); + ret->old_x = targ->mo->old_x; + ret->old_y = targ->mo->old_y; + ret->old_z = targ->mo->old_z; P_SetTarget(&ret->target, targ->mo); ret->frame |= ((leveltime % 10) / 2); ret->tics = 1; diff --git a/src/p_enemy.c b/src/p_enemy.c index 0eccc5f55..d9b1fd840 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -13400,6 +13400,9 @@ void A_JawzChase(mobj_t *actor) } ret = P_SpawnMobj(actor->tracer->x, actor->tracer->y, actor->tracer->z, MT_PLAYERRETICULE); + ret->old_x = actor->tracer->old_x; + ret->old_y = actor->tracer->old_y; + ret->old_z = actor->tracer->old_z; P_SetTarget(&ret->target, actor->tracer); ret->frame |= ((leveltime % 10) / 2) + 5; ret->color = actor->cvmem; diff --git a/src/p_mobj.c b/src/p_mobj.c index 269d99652..f09fb5b60 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7018,6 +7018,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj) return false; } P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z); + mobj->old_x = mobj->target->old_x; + mobj->old_y = mobj->target->old_y; + mobj->old_z = mobj->target->old_z; break; case MT_INSTASHIELDB: mobj->renderflags ^= RF_DONTDRAW; From b87b00fcdabd91a2f2b3da94f7e092083690a906 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 24 Dec 2021 23:07:12 -0500 Subject: [PATCH 32/69] Apply the same fix for instashield overlay --- src/k_kart.c | 6 ++++++ src/p_mobj.c | 3 +++ 2 files changed, 9 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index 28d351ba6..d13ee39c7 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3136,9 +3136,15 @@ void K_DoInstashield(player_t *player) S_StartSound(player->mo, sfx_cdpcm9); layera = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_INSTASHIELDA); + layera->old_x = player->mo->old_x; + layera->old_y = player->mo->old_y; + layera->old_z = player->mo->old_z; P_SetTarget(&layera->target, player->mo); layerb = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_INSTASHIELDB); + layerb->old_x = player->mo->old_x; + layerb->old_y = player->mo->old_y; + layerb->old_z = player->mo->old_z; P_SetTarget(&layerb->target, player->mo); } diff --git a/src/p_mobj.c b/src/p_mobj.c index f09fb5b60..886c0eaa1 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7033,6 +7033,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj) return false; } P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z); + mobj->old_x = mobj->target->old_x; + mobj->old_y = mobj->target->old_y; + mobj->old_z = mobj->target->old_z; K_MatchGenericExtraFlags(mobj, mobj->target); break; case MT_BATTLEPOINT: From 09eefc7e9b8757f267838a8c6fb43ea03894f9e9 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 24 Dec 2021 23:17:28 -0500 Subject: [PATCH 33/69] Make drop shadows slightly better in uncapped They still jitter uphill --- src/hardware/hw_main.c | 4 ++-- src/r_things.c | 45 +++++++++++++++++++++++++++++------------- src/r_things.h | 2 +- 3 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 83f92c15f..13d31dc14 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -3668,7 +3668,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) interpy += thing->spryoff; interpz += thing->sprzoff; - groundz = R_GetShadowZ(thing, &groundslope); + groundz = R_GetShadowZ(thing, &groundslope, interpx, interpy, interpz); gpatch = (patch_t *)W_CachePatchName("DSHADOW", PU_SPRITE); if (!(gpatch && ((GLPatch_t *)gpatch->hardware)->mipmap->format)) return; @@ -5295,7 +5295,7 @@ static void HWR_ProjectSprite(mobj_t *thing) if (caster && !P_MobjWasRemoved(caster)) { - fixed_t groundz = R_GetShadowZ(thing, NULL); + fixed_t groundz = R_GetShadowZ(thing, NULL, interpx, interpy, interpz); fixed_t floordiff = abs(((thing->eflags & MFE_VERTICALFLIP) ? caster->height : 0) + caster->z - groundz); shadowheight = FIXED_TO_FLOAT(floordiff); diff --git a/src/r_things.c b/src/r_things.c index ccd6740d8..e585a0928 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1148,7 +1148,9 @@ static void R_SplitSprite(vissprite_t *sprite) // Get the first visible floor below the object for shadows // shadowslope is filled with the floor's slope, if provided // -fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope) +fixed_t R_GetShadowZ( + mobj_t *thing, pslope_t **shadowslope, + fixed_t interpx, fixed_t interpy, fixed_t interpz) { boolean isflipped = thing->eflags & MFE_VERTICALFLIP; fixed_t z, groundz = isflipped ? INT32_MAX : INT32_MIN; @@ -1156,7 +1158,8 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope) msecnode_t *node; sector_t *sector; ffloor_t *rover; -#define CHECKZ (isflipped ? z > thing->z+thing->height/2 && z < groundz : z < thing->z+thing->height/2 && z > groundz) + +#define CHECKZ (isflipped ? z > interpz+thing->height/2 && z < groundz : z < interpz+thing->height/2 && z > groundz) for (node = thing->touching_sectorlist; node; node = node->m_sectorlist_next) { @@ -1167,7 +1170,7 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope) if (sector->heightsec != -1) z = isflipped ? sectors[sector->heightsec].ceilingheight : sectors[sector->heightsec].floorheight; else - z = isflipped ? P_GetSectorCeilingZAt(sector, thing->x, thing->y) : P_GetSectorFloorZAt(sector, thing->x, thing->y); + z = isflipped ? P_GetSectorCeilingZAt(sector, interpx, interpy) : P_GetSectorFloorZAt(sector, interpx, interpy); if CHECKZ { @@ -1181,7 +1184,7 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope) if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES) || (rover->alpha < 90 && !(rover->flags & FF_SWIMMABLE))) continue; - z = isflipped ? P_GetFFloorBottomZAt(rover, thing->x, thing->y) : P_GetFFloorTopZAt(rover, thing->x, thing->y); + z = isflipped ? P_GetFFloorBottomZAt(rover, interpx, interpy) : P_GetFFloorTopZAt(rover, interpx, interpy); if CHECKZ { @@ -1268,11 +1271,12 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope) static void R_SkewShadowSprite( mobj_t *thing, pslope_t *groundslope, fixed_t groundz, INT32 spriteheight, fixed_t scalemul, - fixed_t *shadowyscale, fixed_t *shadowskew) + fixed_t *shadowyscale, fixed_t *shadowskew, + fixed_t interpx, fixed_t interpy) { // haha let's try some dumb stuff fixed_t xslope, zslope; - angle_t sloperelang = (R_PointToAngle(thing->x, thing->y) - groundslope->xydirection) >> ANGLETOFINESHIFT; + angle_t sloperelang = (R_PointToAngle(interpx, interpy) - groundslope->xydirection) >> ANGLETOFINESHIFT; xslope = FixedMul(FINESINE(sloperelang), groundslope->zdelta); zslope = FixedMul(FINECOSINE(sloperelang), groundslope->zdelta); @@ -1288,7 +1292,10 @@ static void R_SkewShadowSprite( *shadowskew = xslope; } -static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, fixed_t tx, fixed_t tz) +static void R_ProjectDropShadow( + mobj_t *thing, vissprite_t *vis, + fixed_t scale, fixed_t tx, fixed_t tz, + fixed_t interpx, fixed_t interpy, fixed_t interpz) { vissprite_t *shadow; patch_t *patch; @@ -1297,7 +1304,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, fixed_t groundz; pslope_t *groundslope; - groundz = R_GetShadowZ(thing, &groundslope); + groundz = R_GetShadowZ(thing, &groundslope, interpx, interpy, interpz); if (abs(groundz-viewz)/tz > 4) return; // Prevent stretchy shadows and possible crashes @@ -1311,7 +1318,14 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, shadowskew = 0; if (groundslope) - R_SkewShadowSprite(thing, groundslope, groundz, patch->height, FRACUNIT, &shadowyscale, &shadowskew); + { + R_SkewShadowSprite( + thing, + groundslope, groundz, + patch->height, FRACUNIT, + &shadowyscale, &shadowskew, + interpx, interpy); + } tx -= patch->width * shadowxscale/2; x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS; @@ -1330,8 +1344,8 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, shadow->mobjflags = 0; shadow->sortscale = vis->sortscale; shadow->dispoffset = vis->dispoffset - 5; - shadow->gx = thing->x; - shadow->gy = thing->y; + shadow->gx = interpx; + shadow->gy = interpy; shadow->gzt = groundz + patch->height * shadowyscale / 2; shadow->gz = shadow->gzt - patch->height * shadowyscale; shadow->texturemid = FixedMul(thing->scale, FixedDiv(shadow->gzt - viewz, shadowyscale)); @@ -1901,7 +1915,7 @@ static void R_ProjectSprite(mobj_t *thing) if (shadowdraw || shadoweffects) { - fixed_t groundz = R_GetShadowZ(thing, NULL); + fixed_t groundz = R_GetShadowZ(thing, NULL, interpx, interpy, interpz); boolean isflipped = (thing->eflags & MFE_VERTICALFLIP); if (shadoweffects) @@ -1925,7 +1939,7 @@ static void R_ProjectSprite(mobj_t *thing) if (shadowskew) { - R_SkewShadowSprite(thing, thing->standingslope, groundz, patch->height, shadowscale, &spriteyscale, &sheartan); + R_SkewShadowSprite(thing, thing->standingslope, groundz, patch->height, shadowscale, &spriteyscale, &sheartan, interpx, interpy); gzt = (isflipped ? (thing->z + thing->height) : thing->z) + patch->height * spriteyscale / 2; gz = gzt - patch->height * spriteyscale; @@ -2124,7 +2138,10 @@ static void R_ProjectSprite(mobj_t *thing) R_SplitSprite(vis); if (oldthing->shadowscale && cv_shadow.value) - R_ProjectDropShadow(oldthing, vis, oldthing->shadowscale, basetx, basetz); + { + R_ProjectDropShadow(oldthing, vis, oldthing->shadowscale, basetx, basetz, + interpx, interpy, interpz); + } // Debug ++objectsdrawn; diff --git a/src/r_things.h b/src/r_things.h index 7ff1bd4c7..4e0c8194a 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -59,7 +59,7 @@ void R_DrawFlippedMaskedColumn(column_t *column, column_t *brightmap); extern INT16 negonearray[MAXVIDWIDTH]; extern INT16 screenheightarray[MAXVIDWIDTH]; -fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope); +fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope, fixed_t interpx, fixed_t interpy, fixed_t interpz); //SoM: 6/5/2000: Light sprites correctly! void R_AddSprites(sector_t *sec, INT32 lightlevel); From 1c908f533dca6aa4e4aeb8696c62078477656fcf Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 25 Dec 2021 02:07:56 -0500 Subject: [PATCH 34/69] Fully fix drop shadows It used the thing's floorz / ceilingz directly -- that wouldn't account for interpolated coordinates. --- src/r_things.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index e585a0928..97d45d62d 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1152,14 +1152,17 @@ fixed_t R_GetShadowZ( mobj_t *thing, pslope_t **shadowslope, fixed_t interpx, fixed_t interpy, fixed_t interpz) { + fixed_t halfHeight = interpz + (thing->height >> 1); boolean isflipped = thing->eflags & MFE_VERTICALFLIP; + fixed_t floorz = P_GetFloorZ(thing, thing->subsector->sector, interpx, interpy, NULL); + fixed_t ceilingz = P_GetCeilingZ(thing, thing->subsector->sector, interpx, interpy, NULL); fixed_t z, groundz = isflipped ? INT32_MAX : INT32_MIN; pslope_t *slope, *groundslope = NULL; msecnode_t *node; sector_t *sector; ffloor_t *rover; -#define CHECKZ (isflipped ? z > interpz+thing->height/2 && z < groundz : z < interpz+thing->height/2 && z > groundz) +#define CHECKZ (isflipped ? z > halfHeight && z < groundz : z < halfHeight && z > groundz) for (node = thing->touching_sectorlist; node; node = node->m_sectorlist_next) { @@ -1194,10 +1197,10 @@ fixed_t R_GetShadowZ( } } - if (isflipped ? (thing->ceilingz < groundz - (!groundslope ? 0 : FixedMul(abs(groundslope->zdelta), thing->radius*3/2))) - : (thing->floorz > groundz + (!groundslope ? 0 : FixedMul(abs(groundslope->zdelta), thing->radius*3/2)))) + if (isflipped ? (ceilingz < groundz - (!groundslope ? 0 : FixedMul(abs(groundslope->zdelta), thing->radius*3/2))) + : (floorz > groundz + (!groundslope ? 0 : FixedMul(abs(groundslope->zdelta), thing->radius*3/2)))) { - groundz = isflipped ? thing->ceilingz : thing->floorz; + groundz = isflipped ? ceilingz : floorz; groundslope = NULL; } @@ -1208,10 +1211,10 @@ fixed_t R_GetShadowZ( { INT32 xl, xh, yl, yh, bx, by; - xl = (unsigned)(thing->x - thing->radius - bmaporgx)>>MAPBLOCKSHIFT; - xh = (unsigned)(thing->x + thing->radius - bmaporgx)>>MAPBLOCKSHIFT; - yl = (unsigned)(thing->y - thing->radius - bmaporgy)>>MAPBLOCKSHIFT; - yh = (unsigned)(thing->y + thing->radius - bmaporgy)>>MAPBLOCKSHIFT; + xl = (unsigned)(interpx - thing->radius - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)(interpx + thing->radius - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)(interpy - thing->radius - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)(interpy + thing->radius - bmaporgy)>>MAPBLOCKSHIFT; BMBOUNDFIX(xl, xh, yl, yh); @@ -1248,7 +1251,7 @@ fixed_t R_GetShadowZ( // We're inside it! Yess... z = po->lines[0]->backsector->ceilingheight; - if (z < thing->z+thing->height/2 && z > groundz) + if (z < halfHeight && z > groundz) { groundz = z; groundslope = NULL; From 762ee92c06cf801343aa3f9f817fbe5ef6a70fda Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 25 Dec 2021 03:53:55 -0500 Subject: [PATCH 35/69] Purple spark electricity UNCAPPED --- src/k_kart.c | 3 +++ src/p_mobj.c | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/k_kart.c b/src/k_kart.c index d13ee39c7..ca32c6f6d 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3975,6 +3975,9 @@ static void K_SpawnDriftElectricity(player_t *player) + P_ReturnThrustY(mo, horizonatalangle, horizontalradius); spark = P_SpawnMobjFromMobj(mo, x, y, 0, MT_DRIFTELECTRICITY); P_InitAngle(spark, sparkangle); + spark->momx = mo->momx; + spark->momy = mo->momy; + spark->momz = mo->momz; spark->color = color; K_GenericExtraFlagsNoZAdjust(spark, mo); diff --git a/src/p_mobj.c b/src/p_mobj.c index 886c0eaa1..57034ebe0 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -13155,6 +13155,17 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo newmobj->z = mobj->z + mobj->height - zofs - newmobj->height; } + // EXPERIMENT: Let all objects set their interp values relative to their owner's old values. + // This will hopefully create a lot less mobj-specific spawn cases, + // but if there's any weird scenarios feel free to remove again. + newmobj->old_x = mobj->old_x + xofs; + newmobj->old_y = mobj->old_y + yofs; + newmobj->old_z = mobj->old_z + zofs; + /* + newmobj->angle = mobj->angle; + newmobj->old_angle = mobj->old_angle; + */ + return newmobj; } @@ -13171,6 +13182,14 @@ fixed_t P_GetMobjHead(const mobj_t *mobj) fixed_t P_GetMobjFeet(const mobj_t *mobj) { + /* + | | + | | + /--\------/ | + | | + ----------------- + */ + return P_IsObjectFlipped(mobj) ? mobj->z + mobj->height : mobj->z; } From fcc5c8e0c4a3cd379cf42f56c293c99d1d9d2fd5 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 25 Dec 2021 04:57:35 -0500 Subject: [PATCH 36/69] Interpolate music credits --- src/hu_stuff.c | 173 +++++++++++++++++++++++++++++++++---------------- src/s_sound.c | 2 +- src/s_sound.h | 3 +- src/v_video.c | 12 ++++ src/v_video.h | 2 + 5 files changed, 134 insertions(+), 58 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 7afc7d531..059bc00f8 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -56,6 +56,7 @@ #include "k_kart.h" #include "k_color.h" #include "k_hud.h" +#include "r_fps.h" // coords are scaled #define HU_INPUTX 0 @@ -165,6 +166,8 @@ static tic_t cechotimer = 0; static tic_t cechoduration = 5*TICRATE; static INT32 cechoflags = 0; +static tic_t resynch_ticker = 0; + //====================================================================== // HEADS UP INIT //====================================================================== @@ -892,6 +895,64 @@ static inline boolean HU_keyInChatString(char *s, char ch) // // +static void HU_TickSongCredits(void) +{ + char *str; + INT32 len; + fixed_t destx; + + cursongcredit.old_x = cursongcredit.x; + + if (!cursongcredit.def) // No def + { + cursongcredit.x = cursongcredit.old_x = 0; + cursongcredit.anim = 0; + cursongcredit.trans = NUMTRANSMAPS; + return; + } + + str = va("\x1F"" %s", cursongcredit.def->source); + len = V_ThinStringWidth(str, V_ALLOWLOWERCASE|V_6WIDTHSPACE); + destx = (len+7) * FRACUNIT; + + if (cursongcredit.anim > 0) + { + if (cursongcredit.trans > 0) + { + cursongcredit.trans--; + } + + if (cursongcredit.x < destx) + { + cursongcredit.x += (destx - cursongcredit.x) / 2; + } + + if (cursongcredit.x > destx) + { + cursongcredit.x = destx; + } + + cursongcredit.anim--; + } + else + { + if (cursongcredit.trans < NUMTRANSMAPS) + { + cursongcredit.trans++; + } + + if (cursongcredit.x > 0) + { + cursongcredit.x /= 2; + } + + if (cursongcredit.x < 0) + { + cursongcredit.x = 0; + } + } +} + void HU_Ticker(void) { if (dedicated) @@ -906,6 +967,49 @@ void HU_Ticker(void) hu_showscores = false; hu_keystrokes = false; + + if (chat_on) + { + // count down the scroll timer. + if (chat_scrolltime > 0) + chat_scrolltime--; + } + else + { + chat_scrolltime = 0; + } + + if (netgame) // would handle that in hu_drawminichat, but it's actually kinda awkward when you're typing a lot of messages. (only handle that in netgames duh) + { + size_t i = 0; + + // handle spam while we're at it: + for(; (i 0) + stop_spamming[i]--; + } + + // handle chat timers + for (i=0; (i 0) + chat_timers[i]--; + else + HU_removeChatText_Mini(); + } + } + + cechotimer--; + + if (gamestate != GS_LEVEL) + { + return; + } + + resynch_ticker++; + + HU_TickSongCredits(); } #ifndef NONET @@ -1887,8 +1991,6 @@ static void HU_DrawCEcho(void) echoptr = line; echoptr++; } - - --cechotimer; } // @@ -1938,42 +2040,28 @@ static void HU_DrawDemoInfo(void) void HU_DrawSongCredits(void) { char *str; - INT32 len, destx; - INT32 y = (r_splitscreen ? (BASEVIDHEIGHT/2)-4 : 32); + fixed_t x; + fixed_t y = (r_splitscreen ? (BASEVIDHEIGHT/2)-4 : 32) * FRACUNIT; INT32 bgt; if (!cursongcredit.def) // No def + { return; + } str = va("\x1F"" %s", cursongcredit.def->source); - len = V_ThinStringWidth(str, V_ALLOWLOWERCASE|V_6WIDTHSPACE); - destx = (len+7); + bgt = (NUMTRANSMAPS/2) + (cursongcredit.trans / 2); + x = R_InterpolateFixed(cursongcredit.old_x, cursongcredit.x); - if (cursongcredit.anim) - { - if (cursongcredit.trans > 0) - cursongcredit.trans--; - if (cursongcredit.x < destx) - cursongcredit.x += (destx - cursongcredit.x) / 2; - if (cursongcredit.x > destx) - cursongcredit.x = destx; - cursongcredit.anim--; - } - else - { - if (cursongcredit.trans < NUMTRANSMAPS) - cursongcredit.trans++; - if (cursongcredit.x > 0) - cursongcredit.x /= 2; - if (cursongcredit.x < 0) - cursongcredit.x = 0; - } - - bgt = (NUMTRANSMAPS/2)+(cursongcredit.trans/2); if (bgt < NUMTRANSMAPS) - V_DrawScaledPatch(cursongcredit.x, y-2, V_SNAPTOLEFT|(bgt< 0) - chat_scrolltime--; if (!OLDCHAT) HU_DrawChat(); else @@ -1999,31 +2084,9 @@ void HU_Drawer(void) else { typelines = 1; - chat_scrolltime = 0; if (!OLDCHAT && cv_consolechat.value < 2 && netgame) // Don't display minimized chat if you set the mode to Window (Hidden) HU_drawMiniChat(); // draw messages in a cool fashion. } - - if (netgame) // would handle that in hu_drawminichat, but it's actually kinda awkward when you're typing a lot of messages. (only handle that in netgames duh) - { - size_t i = 0; - - // handle spam while we're at it: - for(; (i 0) - stop_spamming[i]--; - } - - // handle chat timers - for (i=0; (i 0) - chat_timers[i]--; - else - HU_removeChatText_Mini(); - } - } #endif if (cechotimer) @@ -2062,12 +2125,10 @@ void HU_Drawer(void) // draw desynch text if (hu_redownloadinggamestate) { - static UINT32 resynch_ticker = 0; char resynch_text[14]; UINT32 i; // Animate the dots - resynch_ticker++; strcpy(resynch_text, "Resynching"); for (i = 0; i < (resynch_ticker / 16) % 4; i++) strcat(resynch_text, "."); diff --git a/src/s_sound.c b/src/s_sound.c index 7e44bb207..ac66a5777 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1580,7 +1580,7 @@ void S_ShowMusicCredit(void) { cursongcredit.def = def; cursongcredit.anim = 5*TICRATE; - cursongcredit.x = 0; + cursongcredit.x = cursongcredit.old_x =0; cursongcredit.trans = NUMTRANSMAPS; return; } diff --git a/src/s_sound.h b/src/s_sound.h index 816a90fb5..3e6decf74 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -179,8 +179,9 @@ extern struct cursongcredit { musicdef_t *def; UINT16 anim; - INT32 x; UINT8 trans; + fixed_t x; + fixed_t old_x; } cursongcredit; extern musicdef_t *musicdefstart; diff --git a/src/v_video.c b/src/v_video.c index 5bd7ba733..abaee0886 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -2216,6 +2216,18 @@ void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *st V_DrawThinString(x, y, option, string); } +void V_DrawCenteredThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) +{ + x -= (V_ThinStringWidth(string, option) / 2) * FRACUNIT; + V_DrawThinStringAtFixed(x, y, option, string); +} + +void V_DrawRightAlignedThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string) +{ + x -= V_ThinStringWidth(string, option) * FRACUNIT; + V_DrawThinStringAtFixed(x, y, option, string); +} + // Draws a number using the PING font thingy. // TODO: Merge number drawing functions into one with "font name" selection. diff --git a/src/v_video.h b/src/v_video.h index da4506c9a..402f485a4 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -261,6 +261,8 @@ void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *st #define V_DrawThinStringAtFixed( x,y,option,string ) \ V__DrawOneScaleString (x,y,FRACUNIT,option,TINY_FONT,string) +void V_DrawCenteredThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); +void V_DrawRightAlignedThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string); // Draws a titlecard font string. // timer: when the letters start appearing (leave to 0 to disable) From ac2ab1bdcc967298cabb494ee6fa5bc6bbc953a4 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 25 Dec 2021 05:18:33 -0500 Subject: [PATCH 37/69] Only calculate string when we need it --- src/hu_stuff.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 059bc00f8..498daad9a 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -897,13 +897,7 @@ static inline boolean HU_keyInChatString(char *s, char ch) // static void HU_TickSongCredits(void) { - char *str; - INT32 len; - fixed_t destx; - - cursongcredit.old_x = cursongcredit.x; - - if (!cursongcredit.def) // No def + if (cursongcredit.def == NULL) // No def { cursongcredit.x = cursongcredit.old_x = 0; cursongcredit.anim = 0; @@ -911,12 +905,14 @@ static void HU_TickSongCredits(void) return; } - str = va("\x1F"" %s", cursongcredit.def->source); - len = V_ThinStringWidth(str, V_ALLOWLOWERCASE|V_6WIDTHSPACE); - destx = (len+7) * FRACUNIT; + cursongcredit.old_x = cursongcredit.x; if (cursongcredit.anim > 0) { + char *str = va("\x1F"" %s", cursongcredit.def->source); + INT32 len = V_ThinStringWidth(str, V_ALLOWLOWERCASE|V_6WIDTHSPACE); + fixed_t destx = (len+7) * FRACUNIT; + if (cursongcredit.trans > 0) { cursongcredit.trans--; From 1558a7e8ecfed834611846ab9005c54b1e76c5e5 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sat, 25 Dec 2021 05:51:09 -0500 Subject: [PATCH 38/69] Fix lap animation interp being reversed --- src/k_hud.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_hud.c b/src/k_hud.c index 2490139c2..ae6124a75 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -3944,7 +3944,7 @@ static void K_drawLapStartAnim(void) const UINT8 t = stplyr->karthud[khud_lapanimation]; const UINT8 progress = 80 - t; - const UINT8 tOld = t - 1; + const UINT8 tOld = t + 1; const UINT8 progressOld = 80 - tOld; const tic_t leveltimeOld = leveltime - 1; From 07f965d4eb367e171388574e3e4e45f6851d5b40 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 29 Dec 2021 22:25:04 -0800 Subject: [PATCH 39/69] Check to sting player before removing one ring --- src/k_collide.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/k_collide.c b/src/k_collide.c index 96fe30182..9c722e548 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -537,24 +537,24 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2) if (t1Condition == true) { - P_PlayerRingBurst(t2->player, 1); - if (t2->player->rings <= 0) { P_DamageMobj(t2, t1, t1, 1, DMG_STING); stung = true; } + + P_PlayerRingBurst(t2->player, 1); } if (t2Condition == true) { - P_PlayerRingBurst(t1->player, 1); - if (t1->player->rings <= 0) { P_DamageMobj(t1, t2, t2, 1, DMG_STING); stung = true; } + + P_PlayerRingBurst(t1->player, 1); } return stung; From 5498f9d02d5e99661f5b50707491715a0c7c5e1f Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 29 Dec 2021 22:58:21 -0800 Subject: [PATCH 40/69] Let objects receive damage while in hitlag --- src/p_inter.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index 4dafa91c2..4f2b76221 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1838,8 +1838,10 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (!(target->flags & MF_SHOOTABLE)) return false; // shouldn't happen... +#if 0 if (!(damagetype & DMG_DEATHMASK) && target->hitlag > 0) return false; +#endif } if (target->flags2 & MF2_SKULLFLY) @@ -1922,7 +1924,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (combo == false) { - if (player->flashing > 0) + if (player->mo->hitlag == 0 && player->flashing > 0) { // Post-hit invincibility K_DoInstashield(player); From c6f69e8f5955fb1c698394c8f6d4122cb4d6d68f Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 2 Jan 2022 21:42:20 -0500 Subject: [PATCH 41/69] Add required speed percent --- src/k_terrain.c | 24 +++++++++++++++++++++++- src/k_terrain.h | 2 ++ src/lua_mobjlib.c | 3 --- src/lua_playerlib.c | 5 +---- 4 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/k_terrain.c b/src/k_terrain.c index 8c7a0643d..323e55734 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -618,16 +618,29 @@ static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs) angle_t pushAngle = ANGLE_MAX; angle_t tireAngle = ANGLE_MAX; fixed_t momentum = INT32_MAX; + fixed_t speedValue = INT32_MAX; fixed_t momH = INT32_MAX; fixed_t momV = INT32_MAX; + momentum = P_AproxDistance(mo->momx, mo->momy); + if (mo->player != NULL) { tireAngle = (mo->player->drawangle + ANGLE_180); + speedValue = K_GetKartSpeedFromStat(mo->player->kartspeed); } else { tireAngle = (mo->angle + ANGLE_180); + speedValue = K_GetKartSpeedFromStat(5); + } + + speedValue = FixedMul(speedValue, mo->scale); + speedValue = FixedMul(speedValue, fs->requiredSpeed); + + if (momentum < speedValue) + { + return; } pushAngle = K_MomentumAngle(mo) + ANGLE_180; @@ -662,7 +675,6 @@ static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs) dust->momy = mo->momy; dust->momz = P_GetMobjZMovement(mo) / 2; - momentum = P_AproxDistance(mo->momx, mo->momy); momH = FixedMul(momentum, fs->pushH); momV = FixedMul(momentum, fs->pushV); @@ -872,6 +884,8 @@ static void K_FootstepDefaults(t_footstep_t *footstep) footstep->cone = ANGLE_11hh; footstep->sfxFreq = 6; + footstep->frequency = 1; + footstep->requiredSpeed = 0; } /*-------------------------------------------------- @@ -946,6 +960,14 @@ static void K_ParseFootstepParameter(size_t i, char *param, char *val) { footstep->sfxFreq = (tic_t)atoi(val); } + else if (stricmp(param, "frequency") == 0) + { + footstep->frequency = (tic_t)atoi(val); + } + else if (stricmp(param, "requiredSpeed") == 0) + { + footstep->requiredSpeed = FLOAT_TO_FIXED(atof(val)); + } } /*-------------------------------------------------- diff --git a/src/k_terrain.h b/src/k_terrain.h index e4055be23..924f7a1b1 100644 --- a/src/k_terrain.h +++ b/src/k_terrain.h @@ -60,6 +60,8 @@ typedef struct t_footstep_s angle_t cone; // Randomized angle of the push-out. tic_t sfxFreq; // How frequently to play the sound. + tic_t frequency; // How frequently to spawn the particles. + fixed_t requiredSpeed; // Speed percentage you need to be at to trigger the particles. } t_footstep_t; typedef enum diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 8a4a1e7a5..4c2a4f24d 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -494,9 +494,6 @@ static int mobj_set(lua_State *L) if (hook_cmd_running) return luaL_error(L, "Do not alter mobj_t in CMD building code!"); - if (hook_cmd_running) - return luaL_error(L, "Do not alter mobj_t in BuildCMD code!"); - switch(field) { case mobj_valid: diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 23e2e2b67..17e1a39b1 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -499,9 +499,6 @@ static int player_set(lua_State *L) if (hook_cmd_running) return luaL_error(L, "Do not alter player_t in CMD building code!"); - if (hook_cmd_running) - return luaL_error(L, "Do not alter player_t in BuildCMD code!"); - 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 @@ -861,7 +858,7 @@ static int karthud_set(lua_State *L) if (hud_running) return luaL_error(L, "Do not alter player_t in HUD rendering code!"); if (hook_cmd_running) - return luaL_error(L, "Do not alter player_t in BuildCMD code!"); + return luaL_error(L, "Do not alter player_t in CMD building code!"); karthud[ks] = i; return 0; } From 9e56e54e31aa8647b29c2f7718c0b32ea877e99a Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 3 Jan 2022 00:07:46 -0500 Subject: [PATCH 42/69] Implement particle spawn frequency, offset spawning by player num --- src/k_terrain.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/k_terrain.c b/src/k_terrain.c index 323e55734..68a78af69 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -612,7 +612,7 @@ void K_SpawnSplashForMobj(mobj_t *mo, fixed_t impact) See header file for description. --------------------------------------------------*/ -static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs) +static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs, tic_t timer) { mobj_t *dust = NULL; angle_t pushAngle = ANGLE_MAX; @@ -621,6 +621,13 @@ static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs) fixed_t speedValue = INT32_MAX; fixed_t momH = INT32_MAX; fixed_t momV = INT32_MAX; + fixed_t xOff = INT32_MAX; + fixed_t yOff = INT32_MAX; + + if (timer % fs->frequency != 0) + { + return; + } momentum = P_AproxDistance(mo->momx, mo->momy); @@ -645,7 +652,7 @@ static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs) pushAngle = K_MomentumAngle(mo) + ANGLE_180; - if ((leveltime / 2) & 1) + if (((timer / fs->frequency) / 2) & 1) { tireAngle -= ANGLE_45; tireAngle -= P_RandomRange(0, fs->cone / ANG1) * ANG1; @@ -658,10 +665,13 @@ static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs) pushAngle += P_RandomRange(0, fs->cone / ANG1) * ANG1; } + xOff = P_RandomRange(-fs->spread / FRACUNIT, fs->spread / FRACUNIT) * FRACUNIT; + yOff = P_RandomRange(-fs->spread / FRACUNIT, fs->spread / FRACUNIT) * FRACUNIT; + dust = P_SpawnMobjFromMobj( mo, - (P_RandomRange(-2, 2) * FRACUNIT) + (24 * FINECOSINE(tireAngle >> ANGLETOFINESHIFT)), - (P_RandomRange(-2, 2) * FRACUNIT) + (24 * FINESINE(tireAngle >> ANGLETOFINESHIFT)), + xOff + (24 * FINECOSINE(tireAngle >> ANGLETOFINESHIFT)), + yOff + (24 * FINESINE(tireAngle >> ANGLETOFINESHIFT)), 0, fs->mobjType ); @@ -687,7 +697,7 @@ static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs) dust->color = fs->color; } - if ((fs->sfx != sfx_None) && (fs->sfxFreq > 0) && (leveltime % fs->sfxFreq == 0)) + if ((fs->sfx != sfx_None) && (fs->sfxFreq > 0) && (timer % fs->sfxFreq == 0)) { S_StartSound(mo, fs->sfx); } @@ -700,6 +710,7 @@ static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs) --------------------------------------------------*/ void K_HandleFootstepParticles(mobj_t *mo) { + tic_t timer = leveltime; t_footstep_t *fs = NULL; if (mo == NULL || P_MobjWasRemoved(mo) == true) @@ -723,15 +734,21 @@ void K_HandleFootstepParticles(mobj_t *mo) fs = K_GetFootstepByIndex(mo->terrain->footstepID); } - if (fs == NULL || fs->mobjType == MT_NULL) + if (fs == NULL || fs->mobjType == MT_NULL || fs->frequency <= 0) { // No particles to spawn. return; } + if (mo->player != NULL) + { + // Offset timer by player ID. + timer += mo->player - players; + } + // Idea for later: if different spawning styles are desired, // we can put a switch case here! - K_SpawnFootstepParticle(mo, fs); + K_SpawnFootstepParticle(mo, fs, timer); } /*-------------------------------------------------- @@ -780,7 +797,7 @@ static void K_SplashDefaults(t_splash_t *splash) splash->pushH = FRACUNIT/4; splash->pushV = FRACUNIT/64; - splash->spread = 2; + splash->spread = 2*FRACUNIT; splash->cone = ANGLE_11hh; splash->numParticles = 8; @@ -880,7 +897,7 @@ static void K_FootstepDefaults(t_footstep_t *footstep) footstep->pushH = FRACUNIT/2; footstep->pushV = FRACUNIT/32; - footstep->spread = 2; + footstep->spread = 2*FRACUNIT; footstep->cone = ANGLE_11hh; footstep->sfxFreq = 6; From 2033e84bce292a671d442df28e9dad308d6d5c62 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 3 Jan 2022 00:17:59 -0500 Subject: [PATCH 43/69] Minimum impact amount for splashes --- src/k_terrain.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/k_terrain.c b/src/k_terrain.c index 68a78af69..bae39d216 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -578,6 +578,7 @@ static void K_SpawnSplashParticles(mobj_t *mo, t_splash_t *s, fixed_t impact) --------------------------------------------------*/ void K_SpawnSplashForMobj(mobj_t *mo, fixed_t impact) { + const fixed_t minImpact = 4 * mo->scale; t_splash_t *s = NULL; if (mo == NULL || P_MobjWasRemoved(mo) == true) @@ -602,6 +603,11 @@ void K_SpawnSplashForMobj(mobj_t *mo, fixed_t impact) return; } + if (impact < minImpact) + { + impact = minImpact; + } + // Idea for later: if different spawning styles are desired, // we can put a switch case here! K_SpawnSplashParticles(mo, s, impact); From df3a0ad5079cc630625b44d8b7c798a6af1fe943 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 3 Jan 2022 01:40:38 -0500 Subject: [PATCH 44/69] Only do spread if above 0 --- src/k_terrain.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/k_terrain.c b/src/k_terrain.c index bae39d216..f5323e94b 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -627,8 +627,8 @@ static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs, tic_t timer) fixed_t speedValue = INT32_MAX; fixed_t momH = INT32_MAX; fixed_t momV = INT32_MAX; - fixed_t xOff = INT32_MAX; - fixed_t yOff = INT32_MAX; + fixed_t xOff = 0; + fixed_t yOff = 0; if (timer % fs->frequency != 0) { @@ -671,8 +671,11 @@ static void K_SpawnFootstepParticle(mobj_t *mo, t_footstep_t *fs, tic_t timer) pushAngle += P_RandomRange(0, fs->cone / ANG1) * ANG1; } - xOff = P_RandomRange(-fs->spread / FRACUNIT, fs->spread / FRACUNIT) * FRACUNIT; - yOff = P_RandomRange(-fs->spread / FRACUNIT, fs->spread / FRACUNIT) * FRACUNIT; + if (fs->spread > 0) + { + xOff = P_RandomRange(-fs->spread / FRACUNIT, fs->spread / FRACUNIT) * FRACUNIT; + yOff = P_RandomRange(-fs->spread / FRACUNIT, fs->spread / FRACUNIT) * FRACUNIT; + } dust = P_SpawnMobjFromMobj( mo, From c4385166e521b1c81790ad49478a1f7f89e7ac3b Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 3 Jan 2022 20:02:22 -0500 Subject: [PATCH 45/69] Scale gravity with map scale instead of object scale --- src/p_map.c | 8 +++----- src/p_mobj.c | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index 28487e2e3..ec3f73e47 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -267,9 +267,7 @@ static boolean P_SpecialIsLinedefCrossType(line_t *ld) // boolean P_DoSpring(mobj_t *spring, mobj_t *object) { - //INT32 pflags; - const fixed_t hscale = mapobjectscale + (mapobjectscale - object->scale); - const fixed_t vscale = mapobjectscale + (object->scale - mapobjectscale); + const fixed_t scaleVal = FixedSqrt(FixedMul(mapobjectscale, spring->scale)); fixed_t vertispeed = spring->info->mass; fixed_t horizspeed = spring->info->damage; UINT16 starcolor = (spring->info->painchance % numskincolors); @@ -346,13 +344,13 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) if (vertispeed) { - object->momz = FixedMul(vertispeed, FixedSqrt(FixedMul(vscale, spring->scale))); + object->momz = FixedMul(vertispeed, scaleVal); } if (horizspeed) { angle_t finalAngle = spring->angle; - fixed_t finalSpeed = FixedMul(horizspeed, FixedSqrt(FixedMul(hscale, spring->scale))); + fixed_t finalSpeed = FixedMul(horizspeed, scaleVal); fixed_t objectSpeed; if (object->player) diff --git a/src/p_mobj.c b/src/p_mobj.c index 2981f6110..bcb6c442e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1201,7 +1201,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) gravityadd = -((gravityadd/5) + (gravityadd/8)); } - gravityadd = FixedMul(gravityadd, mo->scale); + gravityadd = FixedMul(gravityadd, mapobjectscale); return gravityadd; } From cab1af54980493323e94a54bfea3dbcbcd8d1623 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 4 Jan 2022 00:23:12 -0500 Subject: [PATCH 46/69] Don't do hitlag combo with items with threshold Prevents instakill ballhog --- src/k_collide.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/k_collide.c b/src/k_collide.c index 9c722e548..5d072c0eb 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -17,6 +17,9 @@ boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2) boolean damageitem = false; boolean sprung = false; + if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0)) + return true; + if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0))) return true; @@ -108,6 +111,9 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2) { boolean damageitem = false; + if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0)) + return true; + if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0))) return true; @@ -186,6 +192,9 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2) boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2) { + if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0)) + return true; + // Push fakes out of other item boxes if (t2->type == MT_RANDOMITEM || t2->type == MT_EGGMANITEM) { @@ -258,6 +267,9 @@ boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2) boolean K_MineCollide(mobj_t *t1, mobj_t *t2) { + if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0)) + return true; + if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0))) return true; @@ -331,6 +343,9 @@ boolean K_MineExplosionCollide(mobj_t *t1, mobj_t *t2) boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2) { + if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0)) + return true; + if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0))) return true; @@ -398,6 +413,9 @@ boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2) boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2) { + if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0)) + return true; + if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0))) return true; From 50eb3eeda2d70a05732bff8ba0e81ebfb5491167 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 4 Jan 2022 00:39:01 -0500 Subject: [PATCH 47/69] Don't use damage hitlag effects on a person when they "win" a ring sting exchange Only applies to ring sting collision (no other types of damage touching), only applies to the person not getting stung. The person who is getting stung & sting trades are unaffected. --- src/k_collide.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/k_collide.c b/src/k_collide.c index 5d072c0eb..9b0463bfc 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -483,7 +483,8 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2) { boolean t1Condition = false; boolean t2Condition = false; - boolean stung = false; + boolean stungT1 = false; + boolean stungT2 = false; // Grow damage t1Condition = (t1->scale > t2->scale + (mapobjectscale/8)); @@ -558,7 +559,7 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2) if (t2->player->rings <= 0) { P_DamageMobj(t2, t1, t1, 1, DMG_STING); - stung = true; + stungT2 = true; } P_PlayerRingBurst(t2->player, 1); @@ -569,11 +570,21 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2) if (t1->player->rings <= 0) { P_DamageMobj(t1, t2, t2, 1, DMG_STING); - stung = true; + stungT1 = true; } P_PlayerRingBurst(t1->player, 1); } - return stung; + // No damage hitlag for stinging. + if (stungT1 == true && stungT2 == false) + { + t2->eflags &= ~MFE_DAMAGEHITLAG; + } + else if (stungT2 == true && stungT1 == false) + { + t1->eflags &= ~MFE_DAMAGEHITLAG; + } + + return (stungT1 || stungT2); } From 211fc17974187eacf396e64529ff291be1b85a03 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 4 Jan 2022 12:45:20 -0500 Subject: [PATCH 48/69] NULL terrain for spectators --- src/k_terrain.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/k_terrain.c b/src/k_terrain.c index f5323e94b..e03ee2059 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -344,6 +344,13 @@ void K_UpdateMobjTerrain(mobj_t *mo, INT32 flatID) return; } + if (mo->player != NULL && mo->player->spectator == true) + { + // We don't want a terrain pointer for spectators. + mo->terrain = NULL; + return; + } + // Update the object's terrain pointer. mo->terrain = K_GetTerrainForFlatNum(flatID); } From 7237b6bea961afff0d3289e1c226bac2c0defa1b Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 4 Jan 2022 23:35:59 +0000 Subject: [PATCH 49/69] Fix infinite pain floors If inflictor is null and you're in hitlag do not damage again --- src/p_inter.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index 6a352ecec..59ea152ab 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1844,10 +1844,8 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (!(target->flags & MF_SHOOTABLE)) return false; // shouldn't happen... -#if 0 - if (!(damagetype & DMG_DEATHMASK) && target->hitlag > 0) + if (!(damagetype & DMG_DEATHMASK) && target->hitlag > 0 && inflictor == NULL) return false; -#endif } if (target->flags2 & MF2_SKULLFLY) From 9e3e06547911d11ea9dfde39d684065a89ecbf2c Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 5 Jan 2022 02:09:31 -0500 Subject: [PATCH 50/69] Bot lookback - Bots use lookback when they have a attack item that hits back & they see you. - Bot item throwing was made slower for easier difficulties. (Lv. 9 should still be pretty fast.) - Bot cone detection was made much much farther & wider Lookback sparkle is a signal for "they are contemplating throwing backwards" --- src/k_botitem.c | 81 +++++++++++++++++++++++++++++++++++++------------ src/k_kart.c | 20 ++++++------ 2 files changed, 72 insertions(+), 29 deletions(-) diff --git a/src/k_botitem.c b/src/k_botitem.c index 4bb83931c..90e3d8172 100644 --- a/src/k_botitem.c +++ b/src/k_botitem.c @@ -382,6 +382,8 @@ static void K_BotItemGenericTap(player_t *player, ticcmd_t *cmd) --------------------------------------------------*/ static boolean K_BotRevealsGenericTrap(player_t *player, INT16 turnamt, boolean mine) { + const fixed_t coneDist = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)); + if (abs(turnamt) >= KART_FULLTURN/2) { // DON'T reveal on turns, we can place bananas on turns whenever we have multiple to spare, @@ -404,7 +406,7 @@ static boolean K_BotRevealsGenericTrap(player_t *player, INT16 turnamt, boolean } // Check your behind. - if (K_PlayerInCone(player, player->mo->radius * 16, 10, true) != NULL) + if (K_PlayerInCone(player, coneDist, 15, true) != NULL) { return true; } @@ -536,16 +538,19 @@ static void K_BotItemRocketSneaker(player_t *player, ticcmd_t *cmd) --------------------------------------------------*/ static void K_BotItemBanana(player_t *player, ticcmd_t *cmd, INT16 turnamt) { + const fixed_t coneDist = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)); SINT8 throwdir = -1; + boolean tryLookback = false; player_t *target = NULL; player->botvars.itemconfirm++; - target = K_PlayerInCone(player, player->mo->radius * 16, 10, true); + target = K_PlayerInCone(player, coneDist, 15, true); if (target != NULL) { K_ItemConfirmForTarget(player, target, player->botvars.difficulty); throwdir = -1; + tryLookback = true; } if (abs(turnamt) >= KART_FULLTURN/2) @@ -564,7 +569,12 @@ static void K_BotItemBanana(player_t *player, ticcmd_t *cmd, INT16 turnamt) } } - if (player->botvars.itemconfirm > 2*TICRATE || player->bananadrag >= TICRATE) + if (tryLookback == true && throwdir == -1) + { + cmd->buttons |= BT_LOOKBACK; + } + + if (player->botvars.itemconfirm > 10*TICRATE || player->bananadrag >= TICRATE) { K_BotGenericPressItem(player, cmd, throwdir); } @@ -585,12 +595,14 @@ static void K_BotItemBanana(player_t *player, ticcmd_t *cmd, INT16 turnamt) --------------------------------------------------*/ static void K_BotItemMine(player_t *player, ticcmd_t *cmd, INT16 turnamt) { + const fixed_t coneDist = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)); SINT8 throwdir = 0; + boolean tryLookback = false; player_t *target = NULL; player->botvars.itemconfirm++; - target = K_PlayerInCone(player, player->mo->radius * 16, 10, true); + target = K_PlayerInCone(player, coneDist, 15, true); if (target != NULL) { K_ItemConfirmForTarget(player, target, player->botvars.difficulty); @@ -601,6 +613,7 @@ static void K_BotItemMine(player_t *player, ticcmd_t *cmd, INT16 turnamt) { player->botvars.itemconfirm += player->botvars.difficulty / 2; throwdir = -1; + tryLookback = true; } else { @@ -619,7 +632,12 @@ static void K_BotItemMine(player_t *player, ticcmd_t *cmd, INT16 turnamt) } } - if (player->botvars.itemconfirm > 2*TICRATE || player->bananadrag >= TICRATE) + if (tryLookback == true && throwdir == -1) + { + cmd->buttons |= BT_LOOKBACK; + } + + if (player->botvars.itemconfirm > 10*TICRATE || player->bananadrag >= TICRATE) { K_BotGenericPressItem(player, cmd, throwdir); } @@ -640,6 +658,7 @@ static void K_BotItemMine(player_t *player, ticcmd_t *cmd, INT16 turnamt) --------------------------------------------------*/ static void K_BotItemLandmine(player_t *player, ticcmd_t *cmd, INT16 turnamt) { + const fixed_t coneDist = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)); player_t *target = NULL; player->botvars.itemconfirm++; @@ -649,13 +668,14 @@ static void K_BotItemLandmine(player_t *player, ticcmd_t *cmd, INT16 turnamt) player->botvars.itemconfirm += player->botvars.difficulty / 2; } - target = K_PlayerInCone(player, player->mo->radius * 16, 10, true); + target = K_PlayerInCone(player, coneDist, 15, true); if (target != NULL) { K_ItemConfirmForTarget(player, target, player->botvars.difficulty); + cmd->buttons |= BT_LOOKBACK; } - if (player->botvars.itemconfirm > 2*TICRATE) + if (player->botvars.itemconfirm > 10*TICRATE) { K_BotGenericPressItem(player, cmd, -1); } @@ -675,8 +695,10 @@ static void K_BotItemLandmine(player_t *player, ticcmd_t *cmd, INT16 turnamt) --------------------------------------------------*/ static void K_BotItemEggman(player_t *player, ticcmd_t *cmd) { + const fixed_t coneDist = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)); const UINT8 stealth = K_EggboxStealth(player->mo->x, player->mo->y); SINT8 throwdir = -1; + boolean tryLookback = false; player_t *target = NULL; player->botvars.itemconfirm++; @@ -688,11 +710,12 @@ static void K_BotItemEggman(player_t *player, ticcmd_t *cmd) throwdir = 1; } - target = K_PlayerInCone(player, player->mo->radius * 16, 10, true); + target = K_PlayerInCone(player, coneDist, 15, true); if (target != NULL) { K_ItemConfirmForTarget(player, target, player->botvars.difficulty); throwdir = -1; + tryLookback = true; } if (stealth > 1 || player->itemroulette > 0) @@ -701,7 +724,12 @@ static void K_BotItemEggman(player_t *player, ticcmd_t *cmd) throwdir = -1; } - if (player->botvars.itemconfirm > 2*TICRATE || player->bananadrag >= TICRATE) + if (tryLookback == true && throwdir == -1) + { + cmd->buttons |= BT_LOOKBACK; + } + + if (player->botvars.itemconfirm > 10*TICRATE || player->bananadrag >= TICRATE) { K_BotGenericPressItem(player, cmd, throwdir); } @@ -720,6 +748,7 @@ static void K_BotItemEggman(player_t *player, ticcmd_t *cmd) --------------------------------------------------*/ static boolean K_BotRevealsEggbox(player_t *player) { + const fixed_t coneDist = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)); const UINT8 stealth = K_EggboxStealth(player->mo->x, player->mo->y); player_t *target = NULL; @@ -737,7 +766,7 @@ static boolean K_BotRevealsEggbox(player_t *player) } // Check your behind. - target = K_PlayerInCone(player, player->mo->radius * 16, 10, true); + target = K_PlayerInCone(player, coneDist, 15, true); if (target != NULL) { return true; @@ -810,8 +839,9 @@ static void K_BotItemEggmanExplosion(player_t *player, ticcmd_t *cmd) static void K_BotItemOrbinaut(player_t *player, ticcmd_t *cmd) { const fixed_t topspeed = K_GetKartSpeed(player, false); - fixed_t radius = (player->mo->radius * 32); + fixed_t radius = FixedMul(2560 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)); SINT8 throwdir = -1; + boolean tryLookback = false; UINT8 snipeMul = 2; player_t *target = NULL; @@ -823,24 +853,30 @@ static void K_BotItemOrbinaut(player_t *player, ticcmd_t *cmd) player->botvars.itemconfirm++; - target = K_PlayerInCone(player, radius, 10, false); + target = K_PlayerInCone(player, radius, 15, false); if (target != NULL) { K_ItemConfirmForTarget(player, target, player->botvars.difficulty * snipeMul); throwdir = 1; } - else if (K_PlayerInCone(player, radius, 10, true)) + else { - target = K_PlayerInCone(player, radius, 10, true); + target = K_PlayerInCone(player, radius, 15, true); if (target != NULL) { K_ItemConfirmForTarget(player, target, player->botvars.difficulty); throwdir = -1; + tryLookback = true; } } - if (player->botvars.itemconfirm > 5*TICRATE) + if (tryLookback == true && throwdir == -1) + { + cmd->buttons |= BT_LOOKBACK; + } + + if (player->botvars.itemconfirm > 25*TICRATE) { K_BotGenericPressItem(player, cmd, throwdir); } @@ -861,8 +897,9 @@ static void K_BotItemOrbinaut(player_t *player, ticcmd_t *cmd) static void K_BotItemJawz(player_t *player, ticcmd_t *cmd) { const fixed_t topspeed = K_GetKartSpeed(player, false); - fixed_t radius = (player->mo->radius * 32); + fixed_t radius = FixedMul(2560 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)); SINT8 throwdir = 1; + boolean tryLookback = false; UINT8 snipeMul = 2; INT32 lastTarg = player->lastjawztarget; player_t *target = NULL; @@ -875,11 +912,12 @@ static void K_BotItemJawz(player_t *player, ticcmd_t *cmd) player->botvars.itemconfirm++; - target = K_PlayerInCone(player, radius, 10, true); + target = K_PlayerInCone(player, radius, 15, true); if (target != NULL) { K_ItemConfirmForTarget(player, target, player->botvars.difficulty); throwdir = -1; + tryLookback = true; } if (lastTarg != -1 @@ -913,7 +951,12 @@ static void K_BotItemJawz(player_t *player, ticcmd_t *cmd) } } - if (player->botvars.itemconfirm > 5*TICRATE) + if (tryLookback == true && throwdir == -1) + { + cmd->buttons |= BT_LOOKBACK; + } + + if (player->botvars.itemconfirm > 25*TICRATE) { K_BotGenericPressItem(player, cmd, throwdir); } @@ -1007,7 +1050,7 @@ static void K_BotItemBubble(player_t *player, ticcmd_t *cmd) } else if (player->bubbleblowup >= bubbletime) { - if (player->botvars.itemconfirm >= 10*TICRATE) + if (player->botvars.itemconfirm > 10*TICRATE) { hold = true; } diff --git a/src/k_kart.c b/src/k_kart.c index ca32c6f6d..baf93a01e 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2211,19 +2211,19 @@ void K_KartMoveAnimation(player_t *player) SINT8 destGlanceDir = 0; SINT8 drift = player->drift; - // Uses turning over steering -- it's important to show player feedback immediately. - if (player->cmd.turning < -minturn) - { - turndir = -1; - } - else if (player->cmd.turning > minturn) - { - turndir = 1; - } - if (!lookback) { player->pflags &= ~PF_LOOKDOWN; + + // Uses turning over steering -- it's important to show player feedback immediately. + if (player->cmd.turning < -minturn) + { + turndir = -1; + } + else if (player->cmd.turning > minturn) + { + turndir = 1; + } } else if (drift == 0) { From 7613cabfae1aca9a3a709b18779f463997e1d3b8 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 5 Jan 2022 03:17:38 -0500 Subject: [PATCH 51/69] No flashing tics in Battle --- src/k_kart.c | 11 +++++++++-- src/p_user.c | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/k_kart.c b/src/k_kart.c index 53426531a..255dff396 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -2962,11 +2962,18 @@ UINT16 K_GetKartFlashing(player_t *player) { UINT16 tics = flashingtics; - if (!player) + if (gametype == GT_BATTLE) + { + // TODO: gametyperules + return 1; + } + + if (player == NULL) + { return tics; + } tics += (tics/8) * (player->kartspeed); - return tics; } diff --git a/src/p_user.c b/src/p_user.c index a5b07fbc6..f96eb80ee 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4553,7 +4553,7 @@ void P_PlayerThink(player_t *player) || (player->pflags & PF_NOCONTEST) // NO CONTEST explosion || ((gametyperules & GTR_BUMPERS) && player->bumpers <= 0 && player->karmadelay))) { - if (player->flashing > 0 && player->flashing < K_GetKartFlashing(player) + if (player->flashing > 1 && player->flashing < K_GetKartFlashing(player) && (leveltime & 1)) player->mo->renderflags |= RF_DONTDRAW; else From bb53ee22be8d6f69162bd1866e68ed1bff0c1afe Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 5 Jan 2022 03:24:19 -0500 Subject: [PATCH 52/69] Buff tether in Battle - /4 minimum distance - x2 speed --- src/k_kart.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/k_kart.c b/src/k_kart.c index 255dff396..8a1f02451 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1721,6 +1721,7 @@ static void K_UpdateDraft(player_t *player) { fixed_t topspd = K_GetKartSpeed(player, false); fixed_t draftdistance; + fixed_t minDist; UINT8 leniency; UINT8 i; @@ -1740,6 +1741,13 @@ static void K_UpdateDraft(player_t *player) draftdistance = FixedMul(draftdistance, K_GetKartGameSpeedScalar(gamespeed)); } + minDist = 640 * player->mo->scale; + if (gametype == GT_BATTLE) + { + // TODO: gametyperules + minDist /= 4; + } + // On the contrary, the leniency period biases toward high weight. // (See also: the leniency variable in K_SpawnDraftDust) leniency = (3*TICRATE)/4 + ((player->kartweight-1) * (TICRATE/4)); @@ -1798,7 +1806,7 @@ static void K_UpdateDraft(player_t *player) #ifndef EASYDRAFTTEST // TOO close to draft. - if (dist < FixedMul(RING_DIST>>1, player->mo->scale)) + if (dist < minDist) continue; // Not close enough to draft. @@ -2866,6 +2874,13 @@ static void K_GetKartBoostPower(player_t *player) { // 30% - 44%, each point of speed adds 1.75% fixed_t draftspeed = ((3*FRACUNIT)/10) + ((player->kartspeed-1) * ((7*FRACUNIT)/400)); + + if (gametype == GT_BATTLE) + { + // TODO: gametyperules + draftspeed *= 2; + } + speedboost += FixedMul(draftspeed, player->draftpower); // (Drafting suffers no boost stack penalty.) numboosts++; } From 7533472799562f8aa6d8916359ae00a085d5de6c Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 5 Jan 2022 03:46:19 -0500 Subject: [PATCH 53/69] Less Karma Bomb CBT - Karma delay is 3sec instead of 10sec - Karma delay is only used for initially changing into a bomb --- src/g_game.c | 2 +- src/k_kart.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index e4fd7d209..2d927d158 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -261,7 +261,7 @@ INT32 stealtime = TICRATE/2; INT32 sneakertime = TICRATE + (TICRATE/3); INT32 itemtime = 8*TICRATE; INT32 bubbletime = TICRATE/2; -INT32 comebacktime = 10*TICRATE; +INT32 comebacktime = 3*TICRATE; INT32 bumptime = 6; INT32 greasetics = 3*TICRATE; INT32 wipeoutslowtime = 20; diff --git a/src/k_kart.c b/src/k_kart.c index 8a1f02451..bd6924e12 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -3481,13 +3481,14 @@ void K_HandleBumperChanges(player_t *player, UINT8 prevBumpers) karmahitbox->destscale = player->mo->destscale; P_SetScale(karmahitbox, player->mo->scale); + player->karmadelay = comebacktime; + if (netgame) { CONS_Printf(M_GetText("%s lost all of their bumpers!\n"), player_names[player-players]); } } - player->karmadelay = comebacktime; K_CalculateBattleWanted(); K_CheckBumpers(); } From b31d66e7f8fb3bd0e357831461924a32e46459ac Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 5 Jan 2022 05:10:09 -0500 Subject: [PATCH 54/69] PLEASE NO RNG --- src/k_battle.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/k_battle.c b/src/k_battle.c index c4902fb05..4b8bf219a 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -469,16 +469,15 @@ void K_RunPaperItemSpawners(void) firstUnspawnedEmerald ); } - else if (P_RandomChance(FRACUNIT/3)) + else { drop = K_SpawnSphereBox( spotList[r]->x, spotList[r]->y, spotList[r]->z + (128 * mapobjectscale * flip), FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip, 10 ); - } - else - { + K_FlipFromObject(drop, spotList[r]); + drop = K_CreatePaperItem( spotList[r]->x, spotList[r]->y, spotList[r]->z + (128 * mapobjectscale * flip), FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip, From 8326f324564ba85319a4759fc18ee9ea2b4ab4d8 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 5 Jan 2022 17:44:11 -0500 Subject: [PATCH 55/69] Fix default terrain friction --- src/k_terrain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_terrain.c b/src/k_terrain.c index e03ee2059..945ba8450 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -1019,7 +1019,7 @@ static void K_TerrainDefaults(terrain_t *terrain) terrain->splashID = SIZE_MAX; terrain->footstepID = SIZE_MAX; - terrain->friction = FRACUNIT; + terrain->friction = 0; terrain->offroad = 0; terrain->damageType = -1; terrain->trickPanel = 0; From c5279e57953681f1138c49ca01a20ff639f4f869 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 5 Jan 2022 17:58:48 -0500 Subject: [PATCH 56/69] Fix missing line for trick panels --- src/k_terrain.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/k_terrain.c b/src/k_terrain.c index 945ba8450..f0a5347ea 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -416,6 +416,9 @@ void K_ProcessTerrainEffect(mobj_t *mo) player->pflags |= PF_TRICKDELAY; K_DoPogoSpring(mo, upwards, 1); + // Reduce speed + speed /= 2; + if (speed < minspeed) { speed = minspeed; From 5da3dd94c016da90100c559032f5e88c1bbf807f Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 5 Jan 2022 21:23:09 -0800 Subject: [PATCH 57/69] Disable titlecard fade on join --- src/p_setup.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/p_setup.c b/src/p_setup.c index bf64566b7..6c5903483 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -4225,7 +4225,9 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) return true; // If so... - G_PreLevelTitleCard(); + // but not if joining because the fade may time us out + if (!fromnetsave) + G_PreLevelTitleCard(); return true; } From 3ba8f38829ef5515f1472d9d5e4bed53e4cccec5 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 6 Jan 2022 01:20:31 -0500 Subject: [PATCH 58/69] Save showfps --- src/v_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/v_video.c b/src/v_video.c index abaee0886..147e3892f 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -45,7 +45,7 @@ UINT8 *screens[5]; // screens[3] = fade screen start // screens[4] = fade screen end, postimage tempoarary buffer -consvar_t cv_ticrate = CVAR_INIT ("showfps", "No", 0, CV_YesNo, NULL); +consvar_t cv_ticrate = CVAR_INIT ("showfps", "No", CV_SAVE, CV_YesNo, NULL); static void CV_palette_OnChange(void); From 11ced1c3d61c944eaf462b2c32a4092cd9d0dc9f Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 5 Jan 2022 22:32:07 -0800 Subject: [PATCH 59/69] Fix nametag distance check --- src/k_hud.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_hud.c b/src/k_hud.c index ae6124a75..0404046be 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -2850,8 +2850,8 @@ static void K_drawKartNameTags(void) } v.x = R_InterpolateFixed(ntplayer->mo->old_x, ntplayer->mo->x); - v.y = R_InterpolateFixed(ntplayer->mo->old_x, ntplayer->mo->x); - v.z = R_InterpolateFixed(ntplayer->mo->old_x, ntplayer->mo->x); + v.y = R_InterpolateFixed(ntplayer->mo->old_x, ntplayer->mo->y); + v.z = R_InterpolateFixed(ntplayer->mo->old_x, ntplayer->mo->z); if (!(ntplayer->mo->eflags & MFE_VERTICALFLIP)) { From 93c36af2c083d71bfd89a528b3fc99fba26289d2 Mon Sep 17 00:00:00 2001 From: James R Date: Thu, 6 Jan 2022 00:46:14 -0800 Subject: [PATCH 60/69] Oops almost fucked it again 11ced1c3d --- src/k_hud.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_hud.c b/src/k_hud.c index 0404046be..fd83afd56 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -2850,8 +2850,8 @@ static void K_drawKartNameTags(void) } v.x = R_InterpolateFixed(ntplayer->mo->old_x, ntplayer->mo->x); - v.y = R_InterpolateFixed(ntplayer->mo->old_x, ntplayer->mo->y); - v.z = R_InterpolateFixed(ntplayer->mo->old_x, ntplayer->mo->z); + v.y = R_InterpolateFixed(ntplayer->mo->old_y, ntplayer->mo->y); + v.z = R_InterpolateFixed(ntplayer->mo->old_z, ntplayer->mo->z); if (!(ntplayer->mo->eflags & MFE_VERTICALFLIP)) { From fc103834afe1141365243c71c926150c67dff637 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 11 Jan 2022 22:49:01 -0800 Subject: [PATCH 61/69] Cache terrain on levelflats --- src/k_terrain.c | 5 +---- src/p_setup.c | 3 +++ src/p_setup.h | 3 +++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/k_terrain.c b/src/k_terrain.c index f0a5347ea..44b8b3163 100644 --- a/src/k_terrain.c +++ b/src/k_terrain.c @@ -312,16 +312,13 @@ terrain_t *K_GetTerrainForTextureNum(INT32 textureNum) --------------------------------------------------*/ terrain_t *K_GetTerrainForFlatNum(INT32 flatID) { - levelflat_t *levelFlat = NULL; - if (flatID < 0 || flatID >= (signed)numlevelflats) { // Clearly invalid floor... return NULL; } - levelFlat = &levelflats[flatID]; - return K_GetTerrainForTextureName(levelFlat->name); + return levelflats[flatID].terrain; } /*-------------------------------------------------- diff --git a/src/p_setup.c b/src/p_setup.c index 6c5903483..853fdd30c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -661,6 +661,9 @@ flatfound: levelflat->u.flat.baselumpnum = LUMPERROR; } + levelflat->terrain = + K_GetTerrainForTextureName(levelflat->name); + CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name); return ( numlevelflats++ ); diff --git a/src/p_setup.h b/src/p_setup.h index 0a7587ec0..dfa79da14 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -17,6 +17,7 @@ #include "doomdata.h" #include "doomstat.h" #include "r_defs.h" +#include "k_terrain.h" // map md5, sent to players via PT_SERVERINFO extern unsigned char mapmd5[16]; @@ -71,6 +72,8 @@ typedef struct UINT16 width, height; + terrain_t *terrain; + // for flat animation INT32 animseq; // start pos. in the anim sequence INT32 numpics; From 8a7a20e6f2652c598b6dbdb0d9d6acf973ace6e7 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 12 Jan 2022 00:33:35 -0800 Subject: [PATCH 62/69] Fix NOMIXER --- src/sdl/sdl_sound.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c index d7a5cb384..ac7a35167 100644 --- a/src/sdl/sdl_sound.c +++ b/src/sdl/sdl_sound.c @@ -517,7 +517,7 @@ static inline void I_SetChannels(void) } } -void I_SetSfxVolume(UINT8 volume) +void I_SetSfxVolume(int volume) { INT32 i; @@ -1466,7 +1466,7 @@ void I_ResumeSong(void) #endif } -void I_SetMusicVolume(UINT8 volume) +void I_SetMusicVolume(int volume) { (void)volume; } @@ -1477,6 +1477,9 @@ boolean I_SetSongTrack(int track) return false; } +void I_UpdateSongLagThreshold(void){} +void I_UpdateSongLagConditions(void){} + /// ------------------------ /// MUSIC FADING /// ------------------------ From 2c6dfd5498d2a23b2d0254c64af80741c6345374 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 12 Jan 2022 04:30:03 -0800 Subject: [PATCH 63/69] Do not speed up underwater/heatwave effect in OpenGL --- src/hardware/hw_main.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 13d31dc14..962c8f986 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -6751,7 +6751,6 @@ void HWR_DoPostProcessor(player_t *player) // 10 by 10 grid. 2 coordinates (xy) float v[SCREENVERTS][SCREENVERTS][2]; static double disStart = 0; - static fixed_t last_fractime = 0; UINT8 x, y; INT32 WAVELENGTH; @@ -6783,16 +6782,7 @@ void HWR_DoPostProcessor(player_t *player) } HWD.pfnPostImgRedraw(v); if (!(paused || P_AutoPause())) - disStart += 1; - if (renderdeltatics > FRACUNIT) - { - disStart = disStart - FIXED_TO_FLOAT(last_fractime) + 1 + FIXED_TO_FLOAT(rendertimefrac); - } - else - { - disStart = disStart - FIXED_TO_FLOAT(last_fractime) + FIXED_TO_FLOAT(rendertimefrac); - } - last_fractime = rendertimefrac; + disStart += FIXED_TO_FLOAT(renderdeltatics); // Capture the screen again for screen waving on the intermission if(gamestate != GS_INTERMISSION) From 0d41c36f0979652fa3c38d46ea8c46a730607585 Mon Sep 17 00:00:00 2001 From: James R Date: Wed, 12 Jan 2022 04:30:43 -0800 Subject: [PATCH 64/69] Closer OpenGL underwater/heatwave effect to Software --- src/hardware/hw_main.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 962c8f986..74f13ff0e 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -6760,15 +6760,15 @@ void HWR_DoPostProcessor(player_t *player) // Modifies the wave. if (*type == postimg_water) { - WAVELENGTH = 20; // Lower is longer - AMPLITUDE = 20; // Lower is bigger - FREQUENCY = 16; // Lower is faster + WAVELENGTH = 5; + AMPLITUDE = 20; + FREQUENCY = 8; } else { - WAVELENGTH = 10; // Lower is longer - AMPLITUDE = 30; // Lower is bigger - FREQUENCY = 4; // Lower is faster + WAVELENGTH = 10; + AMPLITUDE = 60; + FREQUENCY = 4; } for (x = 0; x < SCREENVERTS; x++) From 2af1c6fc3011d09e6d37e71a09d882793b835720 Mon Sep 17 00:00:00 2001 From: SteelT Date: Wed, 12 Jan 2022 20:57:25 -0500 Subject: [PATCH 65/69] Fix sounds playing multiple times during intro if interpolation is on --- src/f_finale.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index eff9ed3f7..0fc575e8e 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -345,16 +345,6 @@ static void F_IntroDrawScene(void) // DRAW A FULL PIC INSTEAD OF FLAT! if (intro_scenenum == 0) { - if (finalecount == 8) - S_StartSound(NULL, sfx_vroom); - else if (finalecount == 47) - { - // Need to use M_Random otherwise it always uses the same sound - INT32 rskin = M_RandomKey(numskins); - UINT8 rtaunt = M_RandomKey(2); - sfxenum_t rsound = skins[rskin].soundsid[SKSKBST1+rtaunt]; - S_StartSound(NULL, rsound); - } background = W_CachePatchName("KARTKREW", PU_CACHE); highres = true; } @@ -453,6 +443,20 @@ void F_IntroTicker(void) timetonext--; + if (intro_scenenum == 0) + { + if (finalecount == 8) + S_StartSound(NULL, sfx_vroom); + else if (finalecount == 47) + { + // Need to use M_Random otherwise it always uses the same sound + INT32 rskin = M_RandomKey(numskins); + UINT8 rtaunt = M_RandomKey(2); + sfxenum_t rsound = skins[rskin].soundsid[SKSKBST1+rtaunt]; + S_StartSound(NULL, rsound); + } + } + F_WriteText(); // check for skipping From 521f8eac3e687349cbd3a9b95a62fbdbcc32b0d5 Mon Sep 17 00:00:00 2001 From: James R Date: Fri, 14 Jan 2022 22:36:49 -0800 Subject: [PATCH 66/69] Fix overflow in precipitation sector search --- src/p_mobj.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index f3d326862..fcf0a8e9e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10536,7 +10536,8 @@ void P_PrecipitationEffects(void) volume = 255; // Sky above? We get it full blast. else { - fixed_t x, y, yl, yh, xl, xh; + /* GCC is optimizing away y >= yl, FUCK YOU */ + volatile fixed_t x, y, yl, yh, xl, xh; fixed_t closedist, newdist; // Essentially check in a 1024 unit radius of the player for an outdoor area. @@ -10545,8 +10546,8 @@ void P_PrecipitationEffects(void) xl = players[g_localplayers[0]].mo->x - 1024*FRACUNIT; xh = players[g_localplayers[0]].mo->x + 1024*FRACUNIT; closedist = 2048*FRACUNIT; - for (y = yl; y <= yh; y += FRACUNIT*64) - for (x = xl; x <= xh; x += FRACUNIT*64) + for (y = yl; y >= yl && y <= yh; y += FRACUNIT*64) + for (x = xl; x >= xl && x <= xh; x += FRACUNIT*64) { if (R_PointInSubsector(x, y)->sector->ceilingpic == skyflatnum) // Found the outdoors! { @@ -13316,4 +13317,4 @@ fixed_t P_GetMobjZMovement(mobj_t *mo) speed = FixedHypot(mo->momx, mo->momy); return P_ReturnThrustY(mo, slope->zangle, P_ReturnThrustX(mo, angDiff, speed)); -} \ No newline at end of file +} From 3eac1fed0f44a8285a9f6b82a12e86997bbb0d34 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 16 Jan 2022 20:57:56 +0000 Subject: [PATCH 67/69] Rewrote the fix to: - be comprehensive (still allow rain to be heard against the topleft corner, not just the bottomright corner) - not use volatile (now uses INT64) - not perform this pointinsubsector search if the map has no rain/thunder (yes I tested EHZ with this check dummied out so this bug won't crop up again later) --- src/p_mobj.c | 44 ++++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index fcf0a8e9e..1d8b2f3ee 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10488,6 +10488,8 @@ void P_PrecipitationEffects(void) boolean effects_lightning = (precipprops[curWeather].effects & PRECIPFX_LIGHTNING); boolean lightningStrike = false; + boolean sounds_rain = (rainsfx != sfx_None && (!leveltime || leveltime % rainfreq == 1)); + // No thunder except every other tic. if (!(leveltime & 1)) { @@ -10532,30 +10534,48 @@ void P_PrecipitationEffects(void) if (sound_disabled) return; // Sound off? D'aw, no fun. + if (!sounds_rain && !sounds_thunder) + return; // no need to calculate volume at ALL + if (players[g_localplayers[0]].mo->subsector->sector->ceilingpic == skyflatnum) volume = 255; // Sky above? We get it full blast. else { - /* GCC is optimizing away y >= yl, FUCK YOU */ - volatile fixed_t x, y, yl, yh, xl, xh; + INT64 x, y, yl, yh, xl, xh; fixed_t closedist, newdist; // Essentially check in a 1024 unit radius of the player for an outdoor area. - yl = players[g_localplayers[0]].mo->y - 1024*FRACUNIT; - yh = players[g_localplayers[0]].mo->y + 1024*FRACUNIT; - xl = players[g_localplayers[0]].mo->x - 1024*FRACUNIT; - xh = players[g_localplayers[0]].mo->x + 1024*FRACUNIT; - closedist = 2048*FRACUNIT; - for (y = yl; y >= yl && y <= yh; y += FRACUNIT*64) - for (x = xl; x >= xl && x <= xh; x += FRACUNIT*64) +#define RADIUSSTEP (64*FRACUNIT) +#define SEARCHRADIUS (16*RADIUSSTEP) + yl = yh = players[g_localplayers[0]].mo->y; + yl -= SEARCHRADIUS; + while (yl < INT32_MIN) + yl += RADIUSSTEP; + yh += SEARCHRADIUS; + while (yh > INT32_MAX) + yh -= RADIUSSTEP; + + xl = xh = players[g_localplayers[0]].mo->x; + xl -= SEARCHRADIUS; + while (xl < INT32_MIN) + xl += RADIUSSTEP; + xh += SEARCHRADIUS; + while (xh > INT32_MAX) + xh -= RADIUSSTEP; + + closedist = SEARCHRADIUS*2; +#undef SEARCHRADIUS + for (y = yl; y <= yh; y += RADIUSSTEP) + for (x = xl; x <= xh; x += RADIUSSTEP) { - if (R_PointInSubsector(x, y)->sector->ceilingpic == skyflatnum) // Found the outdoors! + if (R_PointInSubsector((fixed_t)x, (fixed_t)y)->sector->ceilingpic == skyflatnum) // Found the outdoors! { - newdist = S_CalculateSoundDistance(players[g_localplayers[0]].mo->x, players[g_localplayers[0]].mo->y, 0, x, y, 0); + newdist = S_CalculateSoundDistance(players[g_localplayers[0]].mo->x, players[g_localplayers[0]].mo->y, 0, (fixed_t)x, (fixed_t)y, 0); if (newdist < closedist) closedist = newdist; } } +#undef RADIUSSTEP volume = 255 - (closedist>>(FRACBITS+2)); } @@ -10565,7 +10585,7 @@ void P_PrecipitationEffects(void) else if (volume > 255) volume = 255; - if (rainsfx != sfx_None && (!leveltime || leveltime % rainfreq == 1)) + if (sounds_rain) S_StartSoundAtVolume(players[g_localplayers[0]].mo, rainsfx, volume); if (!sounds_thunder) From ef6ee928acbc762b8dbf863c0cf377e8952c7d8e Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 16 Jan 2022 22:02:11 +0000 Subject: [PATCH 68/69] After I experienced a few consistent crashes for invalid subsector references in P_BounceMove/P_SlideMove, add a few extra checks for whether the mobj is removed. --- src/p_map.c | 9 ++++++++- src/p_mobj.c | 5 +++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/p_map.c b/src/p_map.c index 8fb58cd0a..fb79b6677 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -3732,7 +3732,7 @@ stairstep: tmymove = 0; } if (!P_TryMove(mo, newx, newy, true)) { - if (success) + if (success || P_MobjWasRemoved(mo)) return; // Good enough!! else goto retry; @@ -3856,6 +3856,9 @@ void P_BounceMove(mobj_t *mo) INT32 hitcount; fixed_t mmomx = 0, mmomy = 0; + if (P_MobjWasRemoved(mo)) + return; + if (mo->player) { P_BouncePlayerMove(mo); @@ -3979,7 +3982,11 @@ bounceback: mo->momy = tmymove; if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true)) + { + if (P_MobjWasRemoved(mo)) + return; goto retry; + } } // diff --git a/src/p_mobj.c b/src/p_mobj.c index f3d326862..b93c8d8d3 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1694,6 +1694,8 @@ void P_XYMovement(mobj_t *mo) else { P_BounceMove(mo); + if (P_MobjWasRemoved(mo)) + return; xmove = ymove = 0; S_StartSound(mo, mo->info->activesound); @@ -1843,6 +1845,9 @@ void P_SceneryXYMovement(mobj_t *mo) if (!P_SceneryTryMove(mo, mo->x + mo->momx, mo->y + mo->momy)) P_BounceMove(mo); + if (P_MobjWasRemoved(mo)) + return; + if ((!(mo->eflags & MFE_VERTICALFLIP) && mo->z > mo->floorz) || (mo->eflags & MFE_VERTICALFLIP && mo->z+mo->height < mo->ceilingz)) return; // no friction when airborne From 867b0516e6ddc48d71f760d29d95cb1dc0d14a94 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 16 Jan 2022 23:53:14 +0000 Subject: [PATCH 69/69] Terrain pointers were not getting properly relinked on netsave load, now they are. Thanks Sal for taking a moment out of your day to rubber duck with me --- src/p_saveg.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/p_saveg.c b/src/p_saveg.c index 7710ee0de..6aff9a33f 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -4119,6 +4119,15 @@ static void P_RelinkPointers(void) if (!(mobj->itnext = P_FindNewPosition(temp))) CONS_Debug(DBG_GAMELOGIC, "itnext not found on %d\n", mobj->type); } + if (mobj->terrain) + { + temp = (UINT32)(size_t)mobj->terrain; + mobj->terrain = K_GetTerrainByIndex(temp); + if (mobj->terrain == NULL) + { + CONS_Debug(DBG_GAMELOGIC, "terrain not found on %d\n", mobj->type); + } + } if (mobj->player) { if ( mobj->player->awayviewmobj)