From f7d1515888ace7e637635714e6cfa0ccae7a3ca5 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Thu, 18 Apr 2019 14:43:34 +0200 Subject: [PATCH 001/128] Perform dynamic slope thinking before other thinkers. Signed-off-by: Nev3r --- src/p_slopes.h | 12 +++++++----- src/p_spec.c | 5 ----- src/p_tick.c | 15 +++++++++++++++ 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/p_slopes.h b/src/p_slopes.h index b802ec25f..56f5d6187 100644 --- a/src/p_slopes.h +++ b/src/p_slopes.h @@ -10,9 +10,6 @@ /// \file p_slopes.c /// \brief ZDoom + Eternity Engine Slopes, ported and enhanced by Kalaron -#ifndef P_SLOPES_H__ -#define P_SLOPES_H__ - #ifdef ESLOPE void P_CalculateSlopeNormal(pslope_t *slope); void P_ResetDynamicSlopes(void); @@ -42,7 +39,12 @@ fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope); void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope); void P_ButteredSlope(mobj_t *mo); -#endif +/// Permit slopes to be dynamically altered. +typedef struct +{ + thinker_t thinker; + pslope_t* slope; +} dynplanethink_t; -// EOF +void T_DynamicSlope (dynplanethink_t* th); #endif // #ifdef ESLOPE diff --git a/src/p_spec.c b/src/p_spec.c index 44edec870..731a80074 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5558,11 +5558,6 @@ void P_UpdateSpecials(void) // POINT LIMIT P_CheckPointLimit(); -#ifdef ESLOPE - // Dynamic slopeness - P_RunDynamicSlopes(); -#endif - // ANIMATE TEXTURES for (anim = anims; anim < lastanim; anim++) { diff --git a/src/p_tick.c b/src/p_tick.c index 6f7c96ead..a32fa0029 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -25,6 +25,11 @@ // Object place #include "m_cheat.h" +#ifdef ESLOPE +// Dynamic slopes +#include "p_slopes.h" +#endif + tic_t leveltime; // @@ -609,6 +614,11 @@ void P_Ticker(boolean run) if (run) { + #ifdef ESLOPE + // Dynamic slopeness + P_RunDynamicSlopes(); + #endif + P_RunThinkers(); // Run any "after all the other thinkers" stuff @@ -724,6 +734,11 @@ void P_PreTicker(INT32 frames) memcpy(&players[i].cmd, &temptic, sizeof(ticcmd_t)); } +#ifdef ESLOPE + // Dynamic slopeness + P_RunDynamicSlopes(); +#endif + P_RunThinkers(); // Run any "after all the other thinkers" stuff From 5401e9560fb6c65986dc539e6de451bbdd2ab73f Mon Sep 17 00:00:00 2001 From: Nev3r Date: Fri, 19 Apr 2019 14:14:43 +0200 Subject: [PATCH 002/128] Dynamic slopes now use thinkers. * Moved dynamic slope-related data into its own thinker. * Vertex slopes no longer use the mapthings directly. Signed-off-by: Nev3r --- src/lua_maplib.c | 12 -- src/p_saveg.c | 84 ++++++++ src/p_setup.c | 2 +- src/p_slopes.c | 504 +++++++++++++++++++++-------------------------- src/p_slopes.h | 38 +++- src/p_tick.c | 15 -- src/r_defs.h | 34 +--- 7 files changed, 354 insertions(+), 335 deletions(-) diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 27b97204f..e137b301d 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -292,8 +292,6 @@ enum slope_e { slope_normal, slope_zangle, slope_xydirection, - slope_sourceline, - slope_refpos, slope_flags }; @@ -305,8 +303,6 @@ static const char *const slope_opt[] = { "normal", "zangle", "xydirection", - "sourceline", - "refpos", "flags", NULL}; @@ -1831,12 +1827,6 @@ static int slope_get(lua_State *L) case slope_xydirection: // xydirection lua_pushangle(L, slope->xydirection); return 1; - case slope_sourceline: // source linedef - LUA_PushUserdata(L, slope->sourceline, META_LINE); - return 1; - case slope_refpos: // refpos - lua_pushinteger(L, slope->refpos); - return 1; case slope_flags: // flags lua_pushinteger(L, slope->flags); return 1; @@ -1858,11 +1848,9 @@ static int slope_set(lua_State *L) switch(field) // todo: reorganize this shit { case slope_valid: // valid - case slope_sourceline: // sourceline case slope_d: // d case slope_flags: // flags case slope_normal: // normal - case slope_refpos: // refpos default: return luaL_error(L, "pslope_t field " LUA_QS " cannot be set.", slope_opt[field]); case slope_o: { // o diff --git a/src/p_saveg.c b/src/p_saveg.c index 0d58387b9..10c761753 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1304,6 +1304,10 @@ typedef enum tc_fade, tc_fadecolormap, tc_planedisplace, +#ifdef ESLOPE + tc_dynslopeline, + tc_dynslopevert, +#endif // ESLOPE #ifdef POLYOBJECTS tc_polyrotate, // haleyjd 03/26/06: polyobjects tc_polymove, @@ -1342,6 +1346,14 @@ static inline UINT32 SavePlayer(const player_t *player) return 0xFFFFFFFF; } +#ifdef ESLOPE +static UINT32 SaveSlope(const pslope_t *slope) +{ + if (slope) return (UINT32)(slope->id); + return 0xFFFFFFFF; +} +#endif // ESLOPE + // // SaveMobjThinker // @@ -1979,6 +1991,25 @@ static void SavePlaneDisplaceThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, ht->speed); WRITEUINT8(save_p, ht->type); } +#ifdef ESLOPE +/// Save a dynamic slope thinker. +static inline void SaveDynamicSlopeThinker(const thinker_t *th, const UINT8 type) +{ + const dynplanethink_t* ht = (const void*)th; + + CONS_Printf("Number of slopes: %d\n", slopecount); + + WRITEUINT8(save_p, type); + WRITEUINT8(save_p, ht->type); + WRITEUINT32(save_p, SaveSlope(ht->slope)); + WRITEUINT32(save_p, SaveLine(ht->sourceline)); + WRITEFIXED(save_p, ht->extent); + + WRITEMEM(save_p, ht->tags, sizeof(ht->tags)); + WRITEMEM(save_p, ht->vex, sizeof(ht->vex)); +} +#endif // ESLOPE + #ifdef POLYOBJECTS // @@ -2309,6 +2340,18 @@ static void P_NetArchiveThinkers(void) SavePlaneDisplaceThinker(th, tc_planedisplace); continue; } +#ifdef ESLOPE + else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeLine) + { + SaveDynamicSlopeThinker(th, tc_dynslopeline); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeVert) + { + SaveDynamicSlopeThinker(th, tc_dynslopevert); + continue; + } +#endif // ESLOPE #ifdef POLYOBJECTS else if (th->function.acp1 == (actionf_p1)T_PolyObjRotate) { @@ -2413,6 +2456,20 @@ static inline player_t *LoadPlayer(UINT32 player) return &players[player]; } +#ifdef ESLOPE +static inline pslope_t *LoadSlope(UINT32 slopeid) +{ + pslope_t *p = slopelist; + if (slopeid > slopecount) return NULL; + do + { + if (p->id == slopeid) + return p; + } while ((p = p->next)); + return NULL; +} +#endif // ESLOPE + // // LoadMobjThinker // @@ -3105,6 +3162,7 @@ static inline void LoadPlaneDisplaceThinker(actionf_p1 thinker) { planedisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; + ht->affectee = READINT32(save_p); ht->control = READINT32(save_p); ht->last_height = READFIXED(save_p); @@ -3113,6 +3171,24 @@ static inline void LoadPlaneDisplaceThinker(actionf_p1 thinker) P_AddThinker(&ht->thinker); } +#ifdef ESLOPE +/// Save a dynamic slope thinker. +static inline void LoadDynamicSlopeThinker(actionf_p1 thinker) +{ + dynplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + + ht->type = READUINT8(save_p); + ht->slope = LoadSlope(READUINT32(save_p)); + ht->sourceline = LoadLine(READUINT32(save_p)); + ht->extent = READFIXED(save_p); + READMEM(save_p, ht->tags, sizeof(ht->tags)); + READMEM(save_p, ht->vex, sizeof(ht->vex)); + + P_AddThinker(&ht->thinker); +} +#endif // ESLOPE + #ifdef POLYOBJECTS // @@ -3446,6 +3522,14 @@ static void P_NetUnArchiveThinkers(void) case tc_planedisplace: LoadPlaneDisplaceThinker((actionf_p1)T_PlaneDisplace); break; +#ifdef ESLOPE + case tc_dynslopeline: + LoadDynamicSlopeThinker((actionf_p1)T_DynamicSlopeLine); + break; + case tc_dynslopevert: + LoadDynamicSlopeThinker((actionf_p1)T_DynamicSlopeVert); + break; +#endif // ESLOPE #ifdef POLYOBJECTS case tc_polyrotate: LoadPolyrotatetThinker((actionf_p1)T_PolyObjRotate); diff --git a/src/p_setup.c b/src/p_setup.c index 3dd673906..229ae734d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2911,7 +2911,7 @@ boolean P_SetupLevel(boolean skipprecip) P_InitSpecials(); #ifdef ESLOPE - P_ResetDynamicSlopes(); + P_ResetDynamicSlopes(fromnetsave); #endif P_LoadThings(loademblems); diff --git a/src/p_slopes.c b/src/p_slopes.c index 5a6874196..237502400 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -25,8 +25,8 @@ #ifdef ESLOPE -static pslope_t *slopelist = NULL; -static UINT16 slopecount = 0; +pslope_t *slopelist = NULL; +UINT16 slopecount = 0; // Calculate line normal void P_CalculateSlopeNormal(pslope_t *slope) { @@ -35,58 +35,57 @@ void P_CalculateSlopeNormal(pslope_t *slope) { slope->normal.y = -FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.y); } -// With a vertex slope that has its vertices set, configure relevant slope info -static void P_ReconfigureVertexSlope(pslope_t *slope) +/// Setup slope via 3 vertexes. +static void ReconfigureViaVertexes (pslope_t *slope, const vector3_t v1, const vector3_t v2, const vector3_t v3) { vector3_t vec1, vec2; - // Set slope normal - vec1.x = (slope->vertices[1]->x - slope->vertices[0]->x) << FRACBITS; - vec1.y = (slope->vertices[1]->y - slope->vertices[0]->y) << FRACBITS; - vec1.z = (slope->vertices[1]->z - slope->vertices[0]->z) << FRACBITS; + // Set origin. + FV3_Copy(&slope->o, &v1); - vec2.x = (slope->vertices[2]->x - slope->vertices[0]->x) << FRACBITS; - vec2.y = (slope->vertices[2]->y - slope->vertices[0]->y) << FRACBITS; - vec2.z = (slope->vertices[2]->z - slope->vertices[0]->z) << FRACBITS; + // Get slope's normal. + FV3_SubEx(&v2, &v1, &vec1); + FV3_SubEx(&v3, &v1, &vec2); - // ugggggggh fixed-point maaaaaaath - slope->extent = max( - max(max(abs(vec1.x), abs(vec1.y)), abs(vec1.z)), - max(max(abs(vec2.x), abs(vec2.y)), abs(vec2.z)) - ) >> (FRACBITS+5); - vec1.x /= slope->extent; - vec1.y /= slope->extent; - vec1.z /= slope->extent; - vec2.x /= slope->extent; - vec2.y /= slope->extent; - vec2.z /= slope->extent; + // Set some defaults for a non-sloped "slope" + if (vec1.z == 0 && vec2.z == 0) + { + /// \todo Fix fully flat cases. + CONS_Printf("Please fix me\n"); - FV3_Cross(&vec1, &vec2, &slope->normal); - - slope->extent = R_PointToDist2(0, 0, R_PointToDist2(0, 0, slope->normal.x, slope->normal.y), slope->normal.z); - if (slope->normal.z < 0) - slope->extent = -slope->extent; - - slope->normal.x = FixedDiv(slope->normal.x, slope->extent); - slope->normal.y = FixedDiv(slope->normal.y, slope->extent); - slope->normal.z = FixedDiv(slope->normal.z, slope->extent); - - // Set origin - slope->o.x = slope->vertices[0]->x << FRACBITS; - slope->o.y = slope->vertices[0]->y << FRACBITS; - slope->o.z = slope->vertices[0]->z << FRACBITS; - - if (slope->normal.x == 0 && slope->normal.y == 0) { // Set some defaults for a non-sloped "slope" slope->zangle = slope->xydirection = 0; slope->zdelta = slope->d.x = slope->d.y = 0; - } else { + } + else + { + /// \note Using fixed point for vectorial products easily leads to overflows so we work around by downscaling them. + fixed_t m = max( + max(max(abs(vec1.x), abs(vec1.y)), abs(vec1.z)), + max(max(abs(vec2.x), abs(vec2.y)), abs(vec2.z)) + ) >> 5; // shifting right by 5 is good enough. + + FV3_Cross( + FV3_Divide(&vec1, m), + FV3_Divide(&vec2, m), + &slope->normal + ); + + // NOTE: FV3_Magnitude() doesn't work properly in some cases, and chaining FixedHypot() seems to give worse results. + m = R_PointToDist2(0, 0, R_PointToDist2(0, 0, slope->normal.x, slope->normal.y), slope->normal.z); + + // Invert normal if it's facing down. + if (slope->normal.z < 0) + m = -m; + + FV3_Divide(&slope->normal, m); + // Get direction vector - slope->extent = R_PointToDist2(0, 0, slope->normal.x, slope->normal.y); - slope->d.x = -FixedDiv(slope->normal.x, slope->extent); - slope->d.y = -FixedDiv(slope->normal.y, slope->extent); + m = FixedHypot(slope->normal.x, slope->normal.y); + slope->d.x = -FixedDiv(slope->normal.x, m); + slope->d.y = -FixedDiv(slope->normal.y, m); // Z delta - slope->zdelta = FixedDiv(slope->extent, slope->normal.z); + slope->zdelta = FixedDiv(m, slope->normal.z); // Get angles slope->xydirection = R_PointToAngle2(0, 0, slope->d.x, slope->d.y)+ANGLE_180; @@ -94,88 +93,95 @@ static void P_ReconfigureVertexSlope(pslope_t *slope) } } -// Recalculate dynamic slopes -void P_RunDynamicSlopes(void) { - pslope_t *slope; +/// Recalculate dynamic slopes. +void T_DynamicSlopeLine (dynplanethink_t* th) +{ + pslope_t* slope = th->slope; + line_t* srcline = th->sourceline; - for (slope = slopelist; slope; slope = slope->next) { - fixed_t zdelta; + fixed_t zdelta; - if (slope->flags & SL_NODYNAMIC) - continue; + switch(th->type) { + case DP_FRONTFLOOR: + zdelta = srcline->backsector->floorheight - srcline->frontsector->floorheight; + slope->o.z = srcline->frontsector->floorheight; + break; - switch(slope->refpos) { - case 1: // front floor - zdelta = slope->sourceline->backsector->floorheight - slope->sourceline->frontsector->floorheight; - slope->o.z = slope->sourceline->frontsector->floorheight; - break; - case 2: // front ceiling - zdelta = slope->sourceline->backsector->ceilingheight - slope->sourceline->frontsector->ceilingheight; - slope->o.z = slope->sourceline->frontsector->ceilingheight; - break; - case 3: // back floor - zdelta = slope->sourceline->frontsector->floorheight - slope->sourceline->backsector->floorheight; - slope->o.z = slope->sourceline->backsector->floorheight; - break; - case 4: // back ceiling - zdelta = slope->sourceline->frontsector->ceilingheight - slope->sourceline->backsector->ceilingheight; - slope->o.z = slope->sourceline->backsector->ceilingheight; - break; - case 5: // vertices - { - mapthing_t *mt; - size_t i; - INT32 l; - line_t *line; + case DP_FRONTCEIL: + zdelta = srcline->backsector->ceilingheight - srcline->frontsector->ceilingheight; + slope->o.z = srcline->frontsector->ceilingheight; + break; - for (i = 0; i < 3; i++) { - mt = slope->vertices[i]; - l = P_FindSpecialLineFromTag(799, mt->angle, -1); - if (l != -1) { - line = &lines[l]; - mt->z = line->frontsector->floorheight >> FRACBITS; - } - } + case DP_BACKFLOOR: + zdelta = srcline->frontsector->floorheight - srcline->backsector->floorheight; + slope->o.z = srcline->backsector->floorheight; + break; - P_ReconfigureVertexSlope(slope); - } - continue; // TODO + case DP_BACKCEIL: + zdelta = srcline->frontsector->ceilingheight - srcline->backsector->ceilingheight; + slope->o.z = srcline->backsector->ceilingheight; + break; - default: - I_Error("P_RunDynamicSlopes: slope has invalid type!"); - } + default: + return; + } - if (slope->zdelta != FixedDiv(zdelta, slope->extent)) { - slope->zdelta = FixedDiv(zdelta, slope->extent); - slope->zangle = R_PointToAngle2(0, 0, slope->extent, -zdelta); - P_CalculateSlopeNormal(slope); - } + if (slope->zdelta != FixedDiv(zdelta, th->extent)) { + slope->zdelta = FixedDiv(zdelta, th->extent); + slope->zangle = R_PointToAngle2(0, 0, th->extent, -zdelta); + P_CalculateSlopeNormal(slope); } } -// -// P_MakeSlope -// -// Alocates and fill the contents of a slope structure. -// -static pslope_t *P_MakeSlope(const vector3_t *o, const vector2_t *d, - const fixed_t zdelta, UINT8 flags) +/// Mapthing-defined +void T_DynamicSlopeVert (dynplanethink_t* th) { - pslope_t *ret = Z_Malloc(sizeof(pslope_t), PU_LEVEL, NULL); - memset(ret, 0, sizeof(*ret)); + pslope_t* slope = th->slope; - ret->o.x = o->x; - ret->o.y = o->y; - ret->o.z = o->z; + size_t i; + INT32 l; - ret->d.x = d->x; - ret->d.y = d->y; + for (i = 0; i < 3; i++) { + l = P_FindSpecialLineFromTag(799, th->tags[i], -1); + if (l != -1) { + th->vex[i].z = lines[l].frontsector->floorheight; + } + else + th->vex[i].z = 0; + } - ret->zdelta = zdelta; + ReconfigureViaVertexes(slope, th->vex[0], th->vex[1], th->vex[2]); +} +static inline void P_AddDynSlopeThinker (pslope_t* slope, dynplanetype_t type, line_t* sourceline, fixed_t extent, const INT16 tags[3], const vector3_t vx[3]) +{ + dynplanethink_t* th = Z_Calloc(sizeof (*th), PU_LEVSPEC, NULL); + switch (type) + { + case DP_VERTEX: + th->thinker.function.acp1 = (actionf_p1)T_DynamicSlopeVert; + memcpy(th->tags, tags, sizeof(th->tags)); + memcpy(th->vex, vx, sizeof(th->vex)); + break; + default: + th->thinker.function.acp1 = (actionf_p1)T_DynamicSlopeLine; + th->sourceline = sourceline; + th->extent = extent; + } + + th->slope = slope; + th->type = type; + + P_AddThinker(&th->thinker); +} + + +/// Create a new slope and add it to the slope list. +static inline pslope_t* Slope_Add (const UINT8 flags) +{ + pslope_t *ret = Z_Calloc(sizeof(pslope_t), PU_LEVEL, NULL); ret->flags = flags; - // Add to the slope list ret->next = slopelist; slopelist = ret; @@ -185,13 +191,24 @@ static pslope_t *P_MakeSlope(const vector3_t *o, const vector2_t *d, return ret; } -// -// P_GetExtent -// -// Returns the distance to the first line within the sector that -// is intersected by a line parallel to the plane normal with the point (ox, oy) -// -static fixed_t P_GetExtent(sector_t *sector, line_t *line) +/// Alocates and fill the contents of a slope structure. +static pslope_t *MakeViaVectors(const vector3_t *o, const vector2_t *d, + const fixed_t zdelta, UINT8 flags) +{ + pslope_t *ret = Slope_Add(flags); + + FV3_Copy(&ret->o, o); + FV2_Copy(&ret->d, d); + + ret->zdelta = zdelta; + + ret->flags = flags; + + return ret; +} + +/// Get furthest perpendicular distance from all vertexes in a sector for a given line. +static fixed_t GetExtent(sector_t *sector, line_t *line) { // ZDoom code reference: v3float_t = vertex_t fixed_t fardist = -FRACUNIT; @@ -224,14 +241,8 @@ static fixed_t P_GetExtent(sector_t *sector, line_t *line) return fardist; } - -// -// P_SpawnSlope_Line -// -// Creates one or more slopes based on the given line type and front/back -// sectors. -// -void P_SpawnSlope_Line(int linenum) +/// Creates one or more slopes based on the given line type and front/back sectors. +static void line_SpawnViaLine(const int linenum, const boolean spawnthinker) { // With dynamic slopes, it's fine to just leave this function as normal, // because checking to see if a slope had changed will waste more memory than @@ -274,6 +285,7 @@ void P_SpawnSlope_Line(int linenum) ny = -FixedDiv(line->dx, len); } + // Set origin to line's center. origin.x = line->v1->x + (line->v2->x - line->v1->x)/2; origin.y = line->v1->y + (line->v2->y - line->v1->y)/2; @@ -286,7 +298,7 @@ void P_SpawnSlope_Line(int linenum) direction.x = nx; direction.y = ny; - extent = P_GetExtent(line->frontsector, line); + extent = GetExtent(line->frontsector, line); if(extent < 0) { @@ -312,26 +324,17 @@ void P_SpawnSlope_Line(int linenum) // In P_SpawnSlopeLine the origin is the centerpoint of the sourcelinedef fslope = line->frontsector->f_slope = - P_MakeSlope(&point, &direction, dz, flags); - - // Set up some shit - fslope->extent = extent; - fslope->refpos = 1; + MakeViaVectors(&point, &direction, dz, flags); // Now remember that f_slope IS a vector // fslope->o = origin 3D point 1 of the vector // fslope->d = destination 3D point 2 of the vector // fslope->normal is a 3D line perpendicular to the 3D vector - // Sync the linedata of the line that started this slope - // TODO: Anything special for control sector based slopes later? - fslope->sourceline = line; - // To find the real highz/lowz of a slope, you need to check all the vertexes // in the slope's sector with P_GetZAt to get the REAL lowz & highz // Although these slopes are set by floorheights the ANGLE is what a slope is, // so technically any slope can extend on forever (they are just bound by sectors) - // *You can use sourceline as a reference to see if two slopes really are the same // Default points for high and low highest = point.z > origin.z ? point.z : origin.z; @@ -359,6 +362,9 @@ void P_SpawnSlope_Line(int linenum) fslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y); P_CalculateSlopeNormal(fslope); + + if (spawnthinker && !(flags & SL_NODYNAMIC)) + P_AddDynSlopeThinker(fslope, DP_FRONTFLOOR, line, extent, NULL, NULL); } if(frontceil) { @@ -369,15 +375,7 @@ void P_SpawnSlope_Line(int linenum) dz = FixedDiv(origin.z - point.z, extent); cslope = line->frontsector->c_slope = - P_MakeSlope(&point, &direction, dz, flags); - - // Set up some shit - cslope->extent = extent; - cslope->refpos = 2; - - // Sync the linedata of the line that started this slope - // TODO: Anything special for control sector based slopes later? - cslope->sourceline = line; + MakeViaVectors(&point, &direction, dz, flags); // Remember the way the slope is formed highest = point.z > origin.z ? point.z : origin.z; @@ -402,6 +400,9 @@ void P_SpawnSlope_Line(int linenum) cslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y); P_CalculateSlopeNormal(cslope); + + if (spawnthinker && !(flags & SL_NODYNAMIC)) + P_AddDynSlopeThinker(cslope, DP_FRONTCEIL, line, extent, NULL, NULL); } } if(backfloor || backceil) @@ -413,7 +414,7 @@ void P_SpawnSlope_Line(int linenum) direction.x = -nx; direction.y = -ny; - extent = P_GetExtent(line->backsector, line); + extent = GetExtent(line->backsector, line); if(extent < 0) { @@ -435,15 +436,7 @@ void P_SpawnSlope_Line(int linenum) dz = FixedDiv(origin.z - point.z, extent); fslope = line->backsector->f_slope = - P_MakeSlope(&point, &direction, dz, flags); - - // Set up some shit - fslope->extent = extent; - fslope->refpos = 3; - - // Sync the linedata of the line that started this slope - // TODO: Anything special for control sector based slopes later? - fslope->sourceline = line; + MakeViaVectors(&point, &direction, dz, flags); // Remember the way the slope is formed highest = point.z > origin.z ? point.z : origin.z; @@ -468,6 +461,9 @@ void P_SpawnSlope_Line(int linenum) fslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y); P_CalculateSlopeNormal(fslope); + + if (spawnthinker && !(flags & SL_NODYNAMIC)) + P_AddDynSlopeThinker(fslope, DP_BACKFLOOR, line, extent, NULL, NULL); } if(backceil) { @@ -478,15 +474,7 @@ void P_SpawnSlope_Line(int linenum) dz = FixedDiv(origin.z - point.z, extent); cslope = line->backsector->c_slope = - P_MakeSlope(&point, &direction, dz, flags); - - // Set up some shit - cslope->extent = extent; - cslope->refpos = 4; - - // Sync the linedata of the line that started this slope - // TODO: Anything special for control sector based slopes later? - cslope->sourceline = line; + MakeViaVectors(&point, &direction, dz, flags); // Remember the way the slope is formed highest = point.z > origin.z ? point.z : origin.z; @@ -511,6 +499,9 @@ void P_SpawnSlope_Line(int linenum) cslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y); P_CalculateSlopeNormal(cslope); + + if (spawnthinker && !(flags & SL_NODYNAMIC)) + P_AddDynSlopeThinker(cslope, DP_BACKCEIL, line, extent, NULL, NULL); } } @@ -518,63 +509,99 @@ void P_SpawnSlope_Line(int linenum) return; } -// -// P_NewVertexSlope -// -// Creates a new slope from three vertices with the specified IDs -// -static pslope_t *P_NewVertexSlope(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flags) +/// Creates a new slope from three mapthings with the specified IDs +static pslope_t *MakeViaMapthings(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flags, const boolean spawnthinker) { size_t i; - mapthing_t *mt = mapthings; + mapthing_t* mt = mapthings; + mapthing_t* vertices[3] = {0}; + INT16 tags[3] = {tag1, tag2, tag3}; - pslope_t *ret = Z_Malloc(sizeof(pslope_t), PU_LEVEL, NULL); - memset(ret, 0, sizeof(*ret)); - - // Start by setting flags - ret->flags = flags; - - // Now set up the vertex list - ret->vertices = Z_Malloc(3*sizeof(mapthing_t), PU_LEVEL, NULL); - memset(ret->vertices, 0, 3*sizeof(mapthing_t)); + vector3_t vx[3]; + pslope_t* ret = Slope_Add(flags); // And... look for the vertices in question. for (i = 0; i < nummapthings; i++, mt++) { if (mt->type != 750) // Haha, I'm hijacking the old Chaos Spawn thingtype for something! continue; - if (!ret->vertices[0] && mt->angle == tag1) - ret->vertices[0] = mt; - else if (!ret->vertices[1] && mt->angle == tag2) - ret->vertices[1] = mt; - else if (!ret->vertices[2] && mt->angle == tag3) - ret->vertices[2] = mt; + if (!vertices[0] && mt->angle == tag1) + vertices[0] = mt; + else if (!vertices[1] && mt->angle == tag2) + vertices[1] = mt; + else if (!vertices[2] && mt->angle == tag3) + vertices[2] = mt; } // Now set heights for each vertex, because they haven't been set yet for (i = 0; i < 3; i++) { - mt = ret->vertices[i]; + mt = vertices[i]; if (!mt) // If a vertex wasn't found, it's game over. There's nothing you can do to recover (except maybe try and kill the slope instead - TODO?) - I_Error("P_NewVertexSlope: Slope vertex %s (for linedef tag %d) not found!", sizeu1(i), tag1); + I_Error("MakeViaMapthings: Slope vertex %s (for linedef tag %d) not found!", sizeu1(i), tag1); + vx[i].x = mt->x << FRACBITS; + vx[i].y = mt->y << FRACBITS; if (mt->extrainfo) - mt->z = mt->options; + vx[i].z = mt->options << FRACBITS; else - mt->z = (R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)->sector->floorheight >> FRACBITS) + (mt->options >> ZSHIFT); + vx[i].z = (R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)->sector->floorheight) + ((mt->options >> ZSHIFT) << FRACBITS); } - P_ReconfigureVertexSlope(ret); - ret->refpos = 5; + ReconfigureViaVertexes(ret, vx[0], vx[1], vx[2]); - // Add to the slope list - ret->next = slopelist; - slopelist = ret; - - slopecount++; - ret->id = slopecount; + if (spawnthinker && !(flags & SL_NODYNAMIC)) + P_AddDynSlopeThinker(ret, DP_VERTEX, NULL, 0, tags, vx); return ret; } +/// Create vertex based slopes. +static void line_SpawnViaVertexes(const int linenum, const boolean spawnthinker) +{ + line_t *line = lines + linenum; + side_t *side; + pslope_t **slopetoset; + UINT16 tag1, tag2, tag3; + + UINT8 flags = SL_VERTEXSLOPE; + if (line->flags & ML_NOSONIC) + flags |= SL_NOPHYSICS; + if (!(line->flags & ML_NOTAILS)) + flags |= SL_NODYNAMIC; + + switch(line->special) + { + case 704: + slopetoset = &line->frontsector->f_slope; + side = &sides[line->sidenum[0]]; + break; + case 705: + slopetoset = &line->frontsector->c_slope; + side = &sides[line->sidenum[0]]; + break; + case 714: + slopetoset = &line->backsector->f_slope; + side = &sides[line->sidenum[1]]; + break; + case 715: + slopetoset = &line->backsector->c_slope; + side = &sides[line->sidenum[1]]; + default: + return; + } + + if (line->flags & ML_NOKNUX) + { + tag1 = line->tag; + tag2 = side->textureoffset >> FRACBITS; + tag3 = side->rowoffset >> FRACBITS; + } + else + tag1 = tag2 = tag3 = line->tag; + + *slopetoset = MakeViaMapthings(tag1, tag2, tag3, flags, spawnthinker); + + side->sector->hasslope = true; +} // @@ -615,12 +642,11 @@ pslope_t *P_SlopeById(UINT16 id) return ret; } -// Reset the dynamic slopes pointer, and read all of the fancy schmancy slopes -void P_ResetDynamicSlopes(void) { +/// Reset slopes and read them from special lines. +void P_ResetDynamicSlopes(const UINT32 fromsave) { size_t i; -#ifdef ESLOPE_TYPESHIM // Rewrite old specials to new ones, and give a console warning - boolean warned = false; -#endif + + boolean spawnthinkers = !(boolean)fromsave; slopelist = NULL; slopecount = 0; @@ -631,40 +657,6 @@ void P_ResetDynamicSlopes(void) { { switch (lines[i].special) { -#ifdef ESLOPE_TYPESHIM // Rewrite old specials to new ones, and give a console warning -#define WARNME if (!warned) {warned = true; CONS_Alert(CONS_WARNING, "This level uses old slope specials.\nA conversion will be needed before 2.2's release.\n");} - case 386: - case 387: - case 388: - lines[i].special += 700-386; - WARNME - P_SpawnSlope_Line(i); - break; - - case 389: - case 390: - case 391: - case 392: - lines[i].special += 710-389; - WARNME - P_SpawnSlope_Line(i); - break; - - case 393: - lines[i].special = 703; - WARNME - P_SpawnSlope_Line(i); - break; - - case 394: - case 395: - case 396: - lines[i].special += 720-394; - WARNME - break; - -#endif - case 700: case 701: case 702: @@ -673,52 +665,14 @@ void P_ResetDynamicSlopes(void) { case 711: case 712: case 713: - P_SpawnSlope_Line(i); + line_SpawnViaLine(i, spawnthinkers); break; case 704: case 705: case 714: case 715: - { - pslope_t **slopetoset; - size_t which = lines[i].special; - - UINT8 flags = SL_VERTEXSLOPE; - if (lines[i].flags & ML_NOSONIC) - flags |= SL_NOPHYSICS; - if (!(lines[i].flags & ML_NOTAILS)) - flags |= SL_NODYNAMIC; - - if (which == 704) - { - slopetoset = &lines[i].frontsector->f_slope; - which = 0; - } - else if (which == 705) - { - slopetoset = &lines[i].frontsector->c_slope; - which = 0; - } - else if (which == 714) - { - slopetoset = &lines[i].backsector->f_slope; - which = 1; - } - else // 715 - { - slopetoset = &lines[i].backsector->c_slope; - which = 1; - } - - if (lines[i].flags & ML_NOKNUX) - *slopetoset = P_NewVertexSlope(lines[i].tag, sides[lines[i].sidenum[which]].textureoffset >> FRACBITS, - sides[lines[i].sidenum[which]].rowoffset >> FRACBITS, flags); - else - *slopetoset = P_NewVertexSlope(lines[i].tag, lines[i].tag, lines[i].tag, flags); - - sides[lines[i].sidenum[which]].sector->hasslope = true; - } + line_SpawnViaVertexes(i, spawnthinkers); break; default: diff --git a/src/p_slopes.h b/src/p_slopes.h index 56f5d6187..65b5eeb4c 100644 --- a/src/p_slopes.h +++ b/src/p_slopes.h @@ -10,14 +10,15 @@ /// \file p_slopes.c /// \brief ZDoom + Eternity Engine Slopes, ported and enhanced by Kalaron +#include "m_fixed.h" // Vectors + #ifdef ESLOPE + +extern pslope_t *slopelist; +extern UINT16 slopecount; + void P_CalculateSlopeNormal(pslope_t *slope); -void P_ResetDynamicSlopes(void); -void P_RunDynamicSlopes(void); -// P_SpawnSlope_Line -// Creates one or more slopes based on the given line type and front/back -// sectors. -void P_SpawnSlope_Line(int linenum); +void P_ResetDynamicSlopes(const UINT32 fromsave); // // P_CopySectorSlope @@ -39,12 +40,33 @@ fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope); void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope); void P_ButteredSlope(mobj_t *mo); -/// Permit slopes to be dynamically altered. + +/// Dynamic plane type enum for the thinker. Will have a different functionality depending on this. +typedef enum { + DP_FRONTFLOOR, + DP_FRONTCEIL, + DP_BACKFLOOR, + DP_BACKCEIL, + DP_VERTEX +} dynplanetype_t; + +/// Permit slopes to be dynamically altered through a thinker. typedef struct { thinker_t thinker; + pslope_t* slope; + dynplanetype_t type; + + // Used by line slopes. + line_t* sourceline; + fixed_t extent; + + // Used by mapthing vertex slopes. + INT16 tags[3]; + vector3_t vex[3]; } dynplanethink_t; -void T_DynamicSlope (dynplanethink_t* th); +void T_DynamicSlopeLine (dynplanethink_t* th); +void T_DynamicSlopeVert (dynplanethink_t* th); #endif // #ifdef ESLOPE diff --git a/src/p_tick.c b/src/p_tick.c index a32fa0029..6f7c96ead 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -25,11 +25,6 @@ // Object place #include "m_cheat.h" -#ifdef ESLOPE -// Dynamic slopes -#include "p_slopes.h" -#endif - tic_t leveltime; // @@ -614,11 +609,6 @@ void P_Ticker(boolean run) if (run) { - #ifdef ESLOPE - // Dynamic slopeness - P_RunDynamicSlopes(); - #endif - P_RunThinkers(); // Run any "after all the other thinkers" stuff @@ -734,11 +724,6 @@ void P_PreTicker(INT32 frames) memcpy(&players[i].cmd, &temptic, sizeof(ticcmd_t)); } -#ifdef ESLOPE - // Dynamic slopeness - P_RunDynamicSlopes(); -#endif - P_RunThinkers(); // Run any "after all the other thinkers" stuff diff --git a/src/r_defs.h b/src/r_defs.h index e7315b35c..ba569d3a8 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -246,37 +246,23 @@ typedef enum { typedef struct pslope_s { UINT16 id; // The number of the slope, mostly used for netgame syncing purposes + struct pslope_s *next; // Make a linked list of dynamic slopes, for easy reference later - // --- Information used in clipping/projection --- - // Origin vector for the plane - vector3_t o; - - // 2-Dimentional vector (x, y) normalized. Used to determine distance from - // the origin in 2d mapspace. (Basically a thrust of FRACUNIT in xydirection angle) - vector2_t d; - - // The rate at which z changes based on distance from the origin plane. - fixed_t zdelta; - - // The normal of the slope; will always point upward, and thus be inverted on ceilings. I think it's only needed for physics? -Red - vector3_t normal; + // The plane's definition. + vector3_t o; /// Plane origin. + vector3_t normal; /// Plane normal. // For comparing when a slope should be rendered - fixed_t lowz; - fixed_t highz; + fixed_t lowz, highz; + + vector2_t d; /// Precomputed normalized projection of the normal over XY. + fixed_t zdelta; /// Precomputed Z unit increase per XY unit. // This values only check and must be updated if the slope itself is modified - angle_t zangle; // Angle of the plane going up from the ground (not mesured in degrees) - angle_t xydirection; // The direction the slope is facing (north, west, south, etc.) - - struct line_s *sourceline; // The line that generated the slope - fixed_t extent; // Distance value used for recalculating zdelta - UINT8 refpos; // 1=front floor 2=front ceiling 3=back floor 4=back ceiling (used for dynamic sloping) + angle_t zangle; /// Precomputed angle of the plane going up from the ground (not measured in degrees). + angle_t xydirection;/// Precomputed angle of the normal's projection on the XY plane. UINT8 flags; // Slope options - mapthing_t **vertices; // List should be three long for slopes made by vertex things, or one long for slopes using one vertex thing to anchor - - struct pslope_s *next; // Make a linked list of dynamic slopes, for easy reference later } pslope_t; #endif From 8a2e11ffa9a92ab674a73db1476d44e6dab1beb9 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Fri, 19 Apr 2019 20:21:29 +0200 Subject: [PATCH 003/128] Small code cleanup - Removed unused vars from the slope struct. I'm pretty sure they were meant for something at some point, but right now there's nothing using them and frankly I find it hard to understand what they were meant for. - Removed unused slope flags. - Flipped dynamic slope flag naming convention. Signed-off-by: Nev3r --- src/dehacked.c | 6 +-- src/p_slopes.c | 114 +++++-------------------------------------------- src/r_defs.h | 9 +--- 3 files changed, 14 insertions(+), 115 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 54dfc441e..f61ea5753 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8191,10 +8191,8 @@ struct { #endif #ifdef ESLOPE // Slope flags - {"SL_NOPHYSICS",SL_NOPHYSICS}, // Don't do momentum adjustment with this slope - {"SL_NODYNAMIC",SL_NODYNAMIC}, // Slope will never need to move during the level, so don't fuss with recalculating it - {"SL_ANCHORVERTEX",SL_ANCHORVERTEX},// Slope is using a Slope Vertex Thing to anchor its position - {"SL_VERTEXSLOPE",SL_VERTEXSLOPE}, // Slope is built from three Slope Vertex Things + {"SL_NOPHYSICS",SL_NOPHYSICS}, + {"SL_DYNAMIC",SL_DYNAMIC}, #endif // Angles diff --git a/src/p_slopes.c b/src/p_slopes.c index 237502400..8355e99c7 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -262,10 +262,8 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker) UINT8 flags = 0; // Slope flags if (line->flags & ML_NOSONIC) flags |= SL_NOPHYSICS; - if (!(line->flags & ML_NOTAILS)) - flags |= SL_NODYNAMIC; - if (line->flags & ML_NOKNUX) - flags |= SL_ANCHORVERTEX; + if (line->flags & ML_NOTAILS) + flags |= SL_DYNAMIC; if(!frontfloor && !backfloor && !frontceil && !backceil) { @@ -316,8 +314,6 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker) if(frontfloor) { - fixed_t highest, lowest; - size_t l; point.z = line->frontsector->floorheight; // Startz dz = FixedDiv(origin.z - point.z, extent); // Destinationz @@ -331,45 +327,16 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker) // fslope->d = destination 3D point 2 of the vector // fslope->normal is a 3D line perpendicular to the 3D vector - // To find the real highz/lowz of a slope, you need to check all the vertexes - // in the slope's sector with P_GetZAt to get the REAL lowz & highz - // Although these slopes are set by floorheights the ANGLE is what a slope is, - // so technically any slope can extend on forever (they are just bound by sectors) - - // Default points for high and low - highest = point.z > origin.z ? point.z : origin.z; - lowest = point.z < origin.z ? point.z : origin.z; - - // Now check to see what the REAL high and low points of the slope inside the sector - // TODO: Is this really needed outside of FOFs? -Red - - for (l = 0; l < line->frontsector->linecount; l++) - { - fixed_t height = P_GetZAt(line->frontsector->f_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y); - - if (height > highest) - highest = height; - - if (height < lowest) - lowest = height; - } - - // Sets extra clipping data for the frontsector's slope - fslope->highz = highest; - fslope->lowz = lowest; - fslope->zangle = R_PointToAngle2(0, origin.z, extent, point.z); fslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y); P_CalculateSlopeNormal(fslope); - if (spawnthinker && !(flags & SL_NODYNAMIC)) + if (spawnthinker && (flags & SL_DYNAMIC)) P_AddDynSlopeThinker(fslope, DP_FRONTFLOOR, line, extent, NULL, NULL); } if(frontceil) { - fixed_t highest, lowest; - size_t l; origin.z = line->backsector->ceilingheight; point.z = line->frontsector->ceilingheight; dz = FixedDiv(origin.z - point.z, extent); @@ -377,31 +344,12 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker) cslope = line->frontsector->c_slope = MakeViaVectors(&point, &direction, dz, flags); - // Remember the way the slope is formed - highest = point.z > origin.z ? point.z : origin.z; - lowest = point.z < origin.z ? point.z : origin.z; - - for (l = 0; l < line->frontsector->linecount; l++) - { - fixed_t height = P_GetZAt(line->frontsector->c_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y); - - if (height > highest) - highest = height; - - if (height < lowest) - lowest = height; - } - - // This line special sets extra clipping data for the frontsector's slope - cslope->highz = highest; - cslope->lowz = lowest; - cslope->zangle = R_PointToAngle2(0, origin.z, extent, point.z); cslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y); P_CalculateSlopeNormal(cslope); - if (spawnthinker && !(flags & SL_NODYNAMIC)) + if (spawnthinker && (flags & SL_DYNAMIC)) P_AddDynSlopeThinker(cslope, DP_FRONTCEIL, line, extent, NULL, NULL); } } @@ -430,45 +378,22 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker) if(backfloor) { - fixed_t highest, lowest; - size_t l; point.z = line->backsector->floorheight; dz = FixedDiv(origin.z - point.z, extent); fslope = line->backsector->f_slope = MakeViaVectors(&point, &direction, dz, flags); - // Remember the way the slope is formed - highest = point.z > origin.z ? point.z : origin.z; - lowest = point.z < origin.z ? point.z : origin.z; - - for (l = 0; l < line->backsector->linecount; l++) - { - fixed_t height = P_GetZAt(line->backsector->f_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y); - - if (height > highest) - highest = height; - - if (height < lowest) - lowest = height; - } - - // This line special sets extra clipping data for the frontsector's slope - fslope->highz = highest; - fslope->lowz = lowest; - fslope->zangle = R_PointToAngle2(0, origin.z, extent, point.z); fslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y); P_CalculateSlopeNormal(fslope); - if (spawnthinker && !(flags & SL_NODYNAMIC)) + if (spawnthinker && (flags & SL_DYNAMIC)) P_AddDynSlopeThinker(fslope, DP_BACKFLOOR, line, extent, NULL, NULL); } if(backceil) { - fixed_t highest, lowest; - size_t l; origin.z = line->frontsector->ceilingheight; point.z = line->backsector->ceilingheight; dz = FixedDiv(origin.z - point.z, extent); @@ -476,31 +401,12 @@ static void line_SpawnViaLine(const int linenum, const boolean spawnthinker) cslope = line->backsector->c_slope = MakeViaVectors(&point, &direction, dz, flags); - // Remember the way the slope is formed - highest = point.z > origin.z ? point.z : origin.z; - lowest = point.z < origin.z ? point.z : origin.z; - - for (l = 0; l < line->backsector->linecount; l++) - { - fixed_t height = P_GetZAt(line->backsector->c_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y); - - if (height > highest) - highest = height; - - if (height < lowest) - lowest = height; - } - - // This line special sets extra clipping data for the backsector's slope - cslope->highz = highest; - cslope->lowz = lowest; - cslope->zangle = R_PointToAngle2(0, origin.z, extent, point.z); cslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y); P_CalculateSlopeNormal(cslope); - if (spawnthinker && !(flags & SL_NODYNAMIC)) + if (spawnthinker && (flags & SL_DYNAMIC)) P_AddDynSlopeThinker(cslope, DP_BACKCEIL, line, extent, NULL, NULL); } } @@ -548,7 +454,7 @@ static pslope_t *MakeViaMapthings(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flag ReconfigureViaVertexes(ret, vx[0], vx[1], vx[2]); - if (spawnthinker && !(flags & SL_NODYNAMIC)) + if (spawnthinker && (flags & SL_DYNAMIC)) P_AddDynSlopeThinker(ret, DP_VERTEX, NULL, 0, tags, vx); return ret; @@ -562,11 +468,11 @@ static void line_SpawnViaVertexes(const int linenum, const boolean spawnthinker) pslope_t **slopetoset; UINT16 tag1, tag2, tag3; - UINT8 flags = SL_VERTEXSLOPE; + UINT8 flags = 0; if (line->flags & ML_NOSONIC) flags |= SL_NOPHYSICS; - if (!(line->flags & ML_NOTAILS)) - flags |= SL_NODYNAMIC; + if (line->flags & ML_NOTAILS) + flags |= SL_DYNAMIC; switch(line->special) { diff --git a/src/r_defs.h b/src/r_defs.h index ba569d3a8..def7b46f3 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -237,10 +237,8 @@ typedef struct linechain_s // Slopes #ifdef ESLOPE typedef enum { - SL_NOPHYSICS = 1, // Don't do momentum adjustment with this slope - SL_NODYNAMIC = 1<<1, // Slope will never need to move during the level, so don't fuss with recalculating it - SL_ANCHORVERTEX = 1<<2, // Slope is using a Slope Vertex Thing to anchor its position - SL_VERTEXSLOPE = 1<<3, // Slope is built from three Slope Vertex Things + SL_NOPHYSICS = 1, /// This plane will have no physics applied besides the positioning. + SL_DYNAMIC = 1<<1, /// This plane slope will be assigned a thinker to make it dynamic. } slopeflags_t; typedef struct pslope_s @@ -252,9 +250,6 @@ typedef struct pslope_s vector3_t o; /// Plane origin. vector3_t normal; /// Plane normal. - // For comparing when a slope should be rendered - fixed_t lowz, highz; - vector2_t d; /// Precomputed normalized projection of the normal over XY. fixed_t zdelta; /// Precomputed Z unit increase per XY unit. From 83001a5bc946a892cb85f8d1ba8fe7d9c11bafe3 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Fri, 19 Apr 2019 20:34:22 +0200 Subject: [PATCH 004/128] Fix line-based slopes' normals. The game never uses the normals directly yet so it's been left unnoticed ever since. Signed-off-by: Nev3r --- src/p_slopes.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/p_slopes.c b/src/p_slopes.c index 8355e99c7..7f389c16d 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -31,8 +31,8 @@ UINT16 slopecount = 0; // Calculate line normal void P_CalculateSlopeNormal(pslope_t *slope) { slope->normal.z = FINECOSINE(slope->zangle>>ANGLETOFINESHIFT); - slope->normal.x = -FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.x); - slope->normal.y = -FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.y); + slope->normal.x = FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.x); + slope->normal.y = FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.y); } /// Setup slope via 3 vertexes. @@ -51,7 +51,6 @@ static void ReconfigureViaVertexes (pslope_t *slope, const vector3_t v1, const v if (vec1.z == 0 && vec2.z == 0) { /// \todo Fix fully flat cases. - CONS_Printf("Please fix me\n"); slope->zangle = slope->xydirection = 0; slope->zdelta = slope->d.x = slope->d.y = 0; From b3ac590e5eed98ec5f2c6ba9f5bb8f5bd7a35df4 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sat, 20 Apr 2019 13:06:06 +0200 Subject: [PATCH 005/128] Add a slope thinker queue. Signed-off-by: Nev3r --- src/p_saveg.c | 2 -- src/p_setup.c | 1 + src/p_slopes.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- src/p_slopes.h | 2 ++ 4 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 10c761753..2aa7da726 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1997,8 +1997,6 @@ static inline void SaveDynamicSlopeThinker(const thinker_t *th, const UINT8 type { const dynplanethink_t* ht = (const void*)th; - CONS_Printf("Number of slopes: %d\n", slopecount); - WRITEUINT8(save_p, type); WRITEUINT8(save_p, ht->type); WRITEUINT32(save_p, SaveSlope(ht->slope)); diff --git a/src/p_setup.c b/src/p_setup.c index 229ae734d..7da992dc8 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2912,6 +2912,7 @@ boolean P_SetupLevel(boolean skipprecip) #ifdef ESLOPE P_ResetDynamicSlopes(fromnetsave); + P_LinkSlopeThinkers(); // Spawn slope thinkers just after plane move thinkers to avoid movement/update delays. #endif P_LoadThings(loademblems); diff --git a/src/p_slopes.c b/src/p_slopes.c index 7f389c16d..9ccd96df2 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -28,6 +28,46 @@ pslope_t *slopelist = NULL; UINT16 slopecount = 0; +thinker_t *dynthinklist; +size_t dynthinknum; + +/// Links previously queued thinker list to the main thinker list. +void P_LinkSlopeThinkers (void) +{ + size_t i; + thinker_t *th = dynthinklist; + + CONS_Printf("Number of dynamic thinkers: %d\n", dynthinknum); + + for (i = 0; i < dynthinknum; i++) + { + thinker_t *next = th->next; + P_AddThinker(th); + th = next; + } +} + +/// Queues a thinker to a partial linked list to be immediately incorporated later via P_LinkSlopeThinkers(). +static void P_QueueSlopeThinker (thinker_t* th) +{ + thinker_t* last = dynthinklist; + + // First entry. + if (!last) + { + dynthinklist = th; + dynthinknum++; + return; + } + + while (last->next) + last = last->next; + + last->next = th; + + dynthinknum++; +} + // Calculate line normal void P_CalculateSlopeNormal(pslope_t *slope) { slope->normal.z = FINECOSINE(slope->zangle>>ANGLETOFINESHIFT); @@ -171,7 +211,7 @@ static inline void P_AddDynSlopeThinker (pslope_t* slope, dynplanetype_t type, l th->slope = slope; th->type = type; - P_AddThinker(&th->thinker); + P_QueueSlopeThinker(&th->thinker); } @@ -556,6 +596,9 @@ void P_ResetDynamicSlopes(const UINT32 fromsave) { slopelist = NULL; slopecount = 0; + dynthinklist = NULL; + dynthinknum = 0; + // We'll handle copy slopes later, after all the tag lists have been made. // Yes, this means copied slopes won't affect things' spawning heights. Too bad for you. for (i = 0; i < numlines; i++) diff --git a/src/p_slopes.h b/src/p_slopes.h index 65b5eeb4c..c5acd4e42 100644 --- a/src/p_slopes.h +++ b/src/p_slopes.h @@ -17,6 +17,8 @@ extern pslope_t *slopelist; extern UINT16 slopecount; +void P_LinkSlopeThinkers (void); + void P_CalculateSlopeNormal(pslope_t *slope); void P_ResetDynamicSlopes(const UINT32 fromsave); From 7c17ed0aa6d24943eed2387958dce817bd2e254a Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sat, 20 Apr 2019 19:03:50 +0200 Subject: [PATCH 006/128] Things spawning over copied slopes now properly align on the new plane While I believe the opposite behavior was intentional at first, it has proven to be problematic and makes alignment a tedious task for copied planes. Signed-off-by: Nev3r --- src/p_slopes.c | 19 ++++++++++++++----- src/p_spec.c | 8 -------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/p_slopes.c b/src/p_slopes.c index 9ccd96df2..6c494c7b4 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -599,8 +599,7 @@ void P_ResetDynamicSlopes(const UINT32 fromsave) { dynthinklist = NULL; dynthinknum = 0; - // We'll handle copy slopes later, after all the tag lists have been made. - // Yes, this means copied slopes won't affect things' spawning heights. Too bad for you. + /// Generates line special-defined slopes. for (i = 0; i < numlines; i++) { switch (lines[i].special) @@ -627,11 +626,21 @@ void P_ResetDynamicSlopes(const UINT32 fromsave) { break; } } + + /// Copies slopes from tagged sectors via line specials. + /// \note Doesn't actually copy, but instead they share the same pointers. + for (i = 0; i < numlines; i++) + switch (lines[i].special) + { + case 720: + case 721: + case 722: + P_CopySectorSlope(&lines[i]); + default: + break; + } } - - - // ============================================================================ // // Various utilities related to slopes diff --git a/src/p_spec.c b/src/p_spec.c index 731a80074..284932739 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -7351,14 +7351,6 @@ void P_SpawnSpecials(INT32 fromnetsave) sectors[s].extra_colormap = sectors[s].spawn_extra_colormap = sides[lines[i].sidenum[0]].colormap_data; break; -#ifdef ESLOPE // Slope copy specials. Handled here for sanity. - case 720: - case 721: - case 722: - P_CopySectorSlope(&lines[i]); - break; -#endif - default: break; } From 39ba20be6b1b6ed939e28056940b5caf6fd6eec3 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sat, 20 Apr 2019 22:37:19 +0200 Subject: [PATCH 007/128] Basic multiple thinker list implementation Set up a main thinker list and a polyobject mover list to test things up. Works so far, networking as well. Signed-off-by: Nev3r --- src/d_clisrv.c | 4 +- src/d_netcmd.c | 2 +- src/f_finale.c | 2 +- src/g_game.c | 6 +- src/hardware/hw_light.c | 2 +- src/lua_script.c | 6 +- src/lua_thinkerlib.c | 6 +- src/m_cheat.c | 6 +- src/p_ceilng.c | 4 +- src/p_enemy.c | 18 +- src/p_floor.c | 14 +- src/p_inter.c | 16 +- src/p_lights.c | 10 +- src/p_local.h | 13 +- src/p_map.c | 2 +- src/p_mobj.c | 24 +- src/p_polyobj.c | 42 +- src/p_saveg.c | 970 ++++++++++++++++++++-------------------- src/p_setup.c | 6 +- src/p_spec.c | 68 +-- src/p_tick.c | 39 +- src/p_user.c | 44 +- src/r_data.c | 2 +- src/st_stuff.c | 2 +- 24 files changed, 659 insertions(+), 649 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 7f8c55af0..6796389e1 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4228,12 +4228,12 @@ static INT16 Consistancy(void) ret += P_GetRandSeed(); #ifdef MOBJCONSISTANCY - if (!thinkercap.next) + if (!thlist[THINK_MAIN].next) { DEBFILE(va("Consistancy = %u\n", ret)); return ret; } - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 392f0e5af..4a31070b9 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -4260,7 +4260,7 @@ static void Command_Archivetest_f(void) // assign mobjnum i = 1; - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) if (th->function.acp1 == (actionf_p1)P_MobjThinker) ((mobj_t *)th)->mobjnum = i++; diff --git a/src/f_finale.c b/src/f_finale.c index a89e0d577..0d9fffabd 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1661,7 +1661,7 @@ void F_TitleScreenTicker(boolean run) mobj_t *mo2; mobj_t *cameraref = NULL; - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; diff --git a/src/g_game.c b/src/g_game.c index 4a9dedf50..e02d545cb 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2557,7 +2557,7 @@ void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo) I_Assert((oldmo != NULL) && (newmo != NULL)); // scan all thinkers - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -4455,7 +4455,7 @@ void G_ConsGhostTic(void) demo_p += sizeof(angle_t); // angle, unnecessary for cons. mobj = NULL; - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -5851,7 +5851,7 @@ void G_DoPlayMetal(void) metalbuffer = metal_p = W_CacheLumpNum(l, PU_STATIC); // find metal sonic - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index dfb2c4351..6e05d6feb 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -1335,7 +1335,7 @@ static void HWR_SearchLightsInMobjs(void) //mobj_t * mobj; // search in the list of thinkers - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { // a mobj ? if (th->function.acp1 == (actionf_p1)P_MobjThinker) diff --git a/src/lua_script.c b/src/lua_script.c index 04aa55cf0..5ec923159 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -421,7 +421,7 @@ void LUA_InvalidateLevel(void) if (!gL) return; - for (th = thinkercap.next; th && th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th && th != &thlist[THINK_MAIN]; th = th->next) LUA_InvalidateUserdata(th); LUA_InvalidateMapthings(); @@ -1127,7 +1127,7 @@ void LUA_Archive(void) ArchiveExtVars(&players[i], "player"); } - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) if (th->function.acp1 == (actionf_p1)P_MobjThinker) { // archive function will determine when to skip mobjs, @@ -1161,7 +1161,7 @@ void LUA_UnArchive(void) do { mobjnum = READUINT32(save_p); // read a mobjnum - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) if (th->function.acp1 == (actionf_p1)P_MobjThinker && ((mobj_t *)th)->mobjnum == mobjnum) // find matching mobj UnArchiveExtVars(th); // apply variables diff --git a/src/lua_thinkerlib.c b/src/lua_thinkerlib.c index ae648613a..29bf7bb56 100644 --- a/src/lua_thinkerlib.c +++ b/src/lua_thinkerlib.c @@ -64,7 +64,7 @@ static int lib_iterateThinkers(lua_State *L) lua_settop(L, 2); if (lua_isnil(L, 2)) - th = &thinkercap; + th = &thlist[THINK_MAIN]; else if (lua_isuserdata(L, 2)) { if (lua_islightuserdata(L, 2)) @@ -94,11 +94,11 @@ static int lib_iterateThinkers(lua_State *L) if (!next) return luaL_error(L, "next thinker invalidated during iteration"); - for (; next != &thinkercap; next = next->next) + for (; next != &thlist[THINK_MAIN]; next = next->next) if (!it->filter || next->function.acp1 == it->filter) { push_thinker(next); - if (next->next != &thinkercap) + if (next->next != &thlist[THINK_MAIN]) { push_thinker(next->next); it->next = luaL_ref(L, LUA_REGISTRYINDEX); diff --git a/src/m_cheat.c b/src/m_cheat.c index bee60087f..92b953f7a 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -577,7 +577,7 @@ void Command_Teleport_f(void) INT32 starpostmax = 0; intz = starpostpath; // variable reuse - counting down for selection purposes - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -600,7 +600,7 @@ void Command_Teleport_f(void) break; } - if (th == &thinkercap) + if (th == &thlist[THINK_MAIN]) { if (intz == starpostpath) CONS_Alert(CONS_NOTICE, M_GetText("No starpost of position %d found (%d max).\n"), starpostnum, starpostmax); @@ -1069,7 +1069,7 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c thinker_t *th; mobj_t *mo; - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; diff --git a/src/p_ceilng.c b/src/p_ceilng.c index 757edebae..5395f618c 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -409,7 +409,7 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type) // new door thinker rtn = 1; ceiling = Z_Calloc(sizeof (*ceiling), PU_LEVSPEC, NULL); - P_AddThinker(&ceiling->thinker); + P_AddThinker(THINK_MAIN, &ceiling->thinker); sec->ceilingdata = ceiling; ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling; ceiling->sector = sec; @@ -629,7 +629,7 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type) // new door thinker rtn = 1; ceiling = Z_Calloc(sizeof (*ceiling), PU_LEVSPEC, NULL); - P_AddThinker(&ceiling->thinker); + P_AddThinker(THINK_MAIN, &ceiling->thinker); sec->ceilingdata = ceiling; ceiling->thinker.function.acp1 = (actionf_p1)T_CrushCeiling; ceiling->sector = sec; diff --git a/src/p_enemy.c b/src/p_enemy.c index 9d2425e53..5364c4207 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3514,7 +3514,7 @@ void A_BossDeath(mobj_t *mo) // scan the remaining thinkers to see // if all bosses are dead - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -3573,7 +3573,7 @@ bossjustdie: // Flee! Flee! Find a point to escape to! If none, just shoot upward! // scan the thinkers to find the runaway point - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -5759,7 +5759,7 @@ void A_RingExplode(mobj_t *actor) S_StartSound(actor, sfx_prloop); - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -7435,7 +7435,7 @@ void A_Boss3Path(mobj_t *actor) // scan the thinkers // to find a point that matches // the number - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -7826,7 +7826,7 @@ void A_FindTarget(mobj_t *actor) CONS_Debug(DBG_GAMELOGIC, "A_FindTarget called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2); // scan the thinkers - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -7891,7 +7891,7 @@ void A_FindTracer(mobj_t *actor) CONS_Debug(DBG_GAMELOGIC, "A_FindTracer called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2); // scan the thinkers - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -8454,7 +8454,7 @@ void A_RemoteAction(mobj_t *actor) fixed_t dist1 = 0, dist2 = 0; // scan the thinkers - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -8720,7 +8720,7 @@ void A_SetObjectTypeState(mobj_t *actor) return; #endif - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -9358,7 +9358,7 @@ void A_CheckThingCount(mobj_t *actor) return; #endif - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; diff --git a/src/p_floor.c b/src/p_floor.c index a1b1c45fc..131cc29d1 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1981,7 +1981,7 @@ void T_ThwompSector(levelspecthink_t *thwomp) if (!rover || (rover->flags & FF_EXISTS)) { // scan the thinkers to find players! - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -2701,7 +2701,7 @@ INT32 EV_DoFloor(line_t *line, floor_e floortype) // new floor thinker rtn = 1; dofloor = Z_Calloc(sizeof (*dofloor), PU_LEVSPEC, NULL); - P_AddThinker(&dofloor->thinker); + P_AddThinker(THINK_MAIN, &dofloor->thinker); // make sure another floor thinker won't get started over this one sec->floordata = dofloor; @@ -2922,7 +2922,7 @@ INT32 EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed) // create and initialize new elevator thinker rtn = 1; elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL); - P_AddThinker(&elevator->thinker); + P_AddThinker(THINK_MAIN, &elevator->thinker); sec->floordata = elevator; sec->ceilingdata = elevator; elevator->thinker.function.acp1 = (actionf_p1)T_MoveElevator; @@ -3149,7 +3149,7 @@ INT32 EV_BounceSector(sector_t *sec, fixed_t momz, line_t *sourceline) return 0; bouncer = Z_Calloc(sizeof (*bouncer), PU_LEVSPEC, NULL); - P_AddThinker(&bouncer->thinker); + P_AddThinker(THINK_MAIN, &bouncer->thinker); sec->ceilingdata = bouncer; bouncer->thinker.function.acp1 = (actionf_p1)T_BounceCheese; @@ -3183,7 +3183,7 @@ INT32 EV_DoContinuousFall(sector_t *sec, sector_t *backsector, fixed_t spd, bool // create and initialize new thinker faller = Z_Calloc(sizeof (*faller), PU_LEVSPEC, NULL); - P_AddThinker(&faller->thinker); + P_AddThinker(THINK_MAIN, &faller->thinker); faller->thinker.function.acp1 = (actionf_p1)T_ContinuousFalling; // set up the fields @@ -3232,7 +3232,7 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating, // create and initialize new elevator thinker elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL); - P_AddThinker(&elevator->thinker); + P_AddThinker(THINK_MAIN, &elevator->thinker); elevator->thinker.function.acp1 = (actionf_p1)T_StartCrumble; // Does this crumbler return? @@ -3311,7 +3311,7 @@ INT32 EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher) // create and initialize new elevator thinker block = Z_Calloc(sizeof (*block), PU_LEVSPEC, NULL); - P_AddThinker(&block->thinker); + P_AddThinker(THINK_MAIN, &block->thinker); roversec->floordata = block; roversec->ceilingdata = block; block->thinker.function.acp1 = (actionf_p1)T_MarioBlock; diff --git a/src/p_inter.c b/src/p_inter.c index 177b8d16e..0d8dfcbeb 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -97,7 +97,7 @@ void P_ClearStarPost(INT32 postnum) mobj_t *mo2; // scan the thinkers - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -126,7 +126,7 @@ void P_ResetStarposts(void) thinker_t *th; mobj_t *post; - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -807,7 +807,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // The player might have two Ideyas: toucher->tracer and toucher->tracer->hnext // so handle their anchorpoints accordingly. // scan the thinkers to find the corresponding anchorpoint - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -901,7 +901,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) count = 1; // scan the remaining thinkers - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -951,7 +951,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // Now we RE-scan all the thinkers to find close objects to pull // in from the paraloop. Isn't this just so efficient? - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -1325,7 +1325,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) EV_DoElevator(&junk, bridgeFall, false); // scan the remaining thinkers to find koopa - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -1424,7 +1424,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) thinker_t *th; mobj_t *mo2; - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -2461,7 +2461,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget // scan the thinkers to make sure all the old pinch dummies are gone on death // this can happen if the boss was hurt earlier than expected - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; diff --git a/src/p_lights.c b/src/p_lights.c index 67ec55e80..8459d9ea0 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -76,7 +76,7 @@ fireflicker_t *P_SpawnAdjustableFireFlicker(sector_t *minsector, sector_t *maxse P_RemoveLighting(maxsector); // out with the old, in with the new flick = Z_Calloc(sizeof (*flick), PU_LEVSPEC, NULL); - P_AddThinker(&flick->thinker); + P_AddThinker(THINK_MAIN, &flick->thinker); flick->thinker.function.acp1 = (actionf_p1)T_FireFlicker; flick->sector = maxsector; @@ -155,7 +155,7 @@ void P_SpawnLightningFlash(sector_t *sector) flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL); - P_AddThinker(&flash->thinker); + P_AddThinker(THINK_MAIN, &flash->thinker); flash->thinker.function.acp1 = (actionf_p1)T_LightningFlash; flash->sector = sector; @@ -214,7 +214,7 @@ strobe_t *P_SpawnAdjustableStrobeFlash(sector_t *minsector, sector_t *maxsector, P_RemoveLighting(maxsector); // out with the old, in with the new flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL); - P_AddThinker(&flash->thinker); + P_AddThinker(THINK_MAIN, &flash->thinker); flash->sector = maxsector; flash->darktime = darktime; @@ -289,7 +289,7 @@ glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector, P_RemoveLighting(maxsector); // out with the old, in with the new g = Z_Calloc(sizeof (*g), PU_LEVSPEC, NULL); - P_AddThinker(&g->thinker); + P_AddThinker(THINK_MAIN, &g->thinker); g->sector = maxsector; g->minlight = minsector->lightlevel; @@ -349,7 +349,7 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean ll->thinker.function.acp1 = (actionf_p1)T_LightFade; sector->lightingdata = ll; // set it to the lightlevel_t - P_AddThinker(&ll->thinker); // add thinker + P_AddThinker(THINK_MAIN, &ll->thinker); // add thinker ll->sector = sector; ll->sourcelevel = sector->lightlevel; diff --git a/src/p_local.h b/src/p_local.h index b686b9f09..254705ad6 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -61,15 +61,16 @@ #define P_GetPlayerHeight(player) FixedMul(player->height, player->mo->scale) #define P_GetPlayerSpinHeight(player) FixedMul(player->spinheight, player->mo->scale) -// -// P_TICK -// - // both the head and tail of the thinker list -extern thinker_t thinkercap; +typedef enum{ + THINK_POLYOBJ, + THINK_MAIN, + NUM_THINKERLISTS +} thinklistnum_t; /**< Thinker lists. */ +extern thinker_t thlist[]; void P_InitThinkers(void); -void P_AddThinker(thinker_t *thinker); +void P_AddThinker(const thinklistnum_t n, thinker_t *thinker); void P_RemoveThinker(thinker_t *thinker); // diff --git a/src/p_map.c b/src/p_map.c index ceaa6ca24..e63fe02dc 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -3872,7 +3872,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush) thinker_t *think; elevator_t *crumbler; - for (think = thinkercap.next; think != &thinkercap; think = think->next) + for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) { if (think->function.acp1 != (actionf_p1)T_StartCrumble) continue; diff --git a/src/p_mobj.c b/src/p_mobj.c index bfed9a2c0..ff07e2f2a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -713,7 +713,7 @@ void P_EmeraldManager(void) spawnpoints[i] = NULL; } - for (think = thinkercap.next; think != &thinkercap; think = think->next) + for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_MobjThinker) continue; // not a mobj thinker @@ -3699,7 +3699,7 @@ void P_DestroyRobots(void) mobj_t *mo; thinker_t *think; - for (think = thinkercap.next; think != &thinkercap; think = think->next) + for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_MobjThinker) continue; // not a mobj thinker @@ -4483,7 +4483,7 @@ static void P_Boss3Thinker(mobj_t *mobj) // scan the thinkers to make sure all the old pinch dummies are gone before making new ones // this can happen if the boss was hurt earlier than expected - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -4574,7 +4574,7 @@ static void P_Boss3Thinker(mobj_t *mobj) // scan the thinkers // to find a point that matches // the number - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -5195,7 +5195,7 @@ static void P_Boss7Thinker(mobj_t *mobj) closestdist = INT32_MAX; // Just in case... // Find waypoint he is closest to - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -5250,7 +5250,7 @@ static void P_Boss7Thinker(mobj_t *mobj) // scan the thinkers to find // the waypoint to use - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -5382,7 +5382,7 @@ static void P_Boss9Thinker(mobj_t *mobj) // Run through the thinkers ONCE and find all of the MT_BOSS9GATHERPOINT in the map. // Build a hoop linked list of 'em! - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -5848,7 +5848,7 @@ mobj_t *P_GetClosestAxis(mobj_t *source) fixed_t dist1, dist2 = 0; // scan the thinkers to find the closest axis point - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -9047,7 +9047,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) } if (!(mobj->flags & MF_NOTHINK)) - P_AddThinker(&mobj->thinker); + P_AddThinker(THINK_MAIN, &mobj->thinker); // Call action functions when the state is set if (st->action.acp1 && (mobj->flags & MF_RUNSPAWNFUNC)) @@ -9122,7 +9122,7 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype mobj->momz = mobjinfo[type].speed; mobj->thinker.function.acp1 = (actionf_p1)P_NullPrecipThinker; - P_AddThinker(&mobj->thinker); + P_AddThinker(THINK_MAIN, &mobj->thinker); CalculatePrecipFloor(mobj); @@ -9246,7 +9246,7 @@ void P_RemoveMobj(mobj_t *mobj) else { // Add thinker just to delay removing it until refrences are gone. mobj->flags &= ~MF_NOTHINK; - P_AddThinker((thinker_t *)mobj); + P_AddThinker(THINK_MAIN, (thinker_t *)mobj); #ifdef SCRAMBLE_REMOVED // Invalidate mobj_t data to cause crashes if accessed! memset((UINT8 *)mobj + sizeof(thinker_t), 0xff, sizeof(mobj_t) - sizeof(thinker_t)); @@ -11085,7 +11085,7 @@ ML_EFFECT4 : Don't clip inside the ground mobj->health = (mthing->angle / 360) + 1; // See if other starposts exist in this level that have the same value. - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; diff --git a/src/p_polyobj.c b/src/p_polyobj.c index dfa9906ba..05c2c9a65 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -146,16 +146,6 @@ FUNCINLINE static ATTRINLINE void Polyobj_vecSub2(vertex_t *dst, vertex_t *v1, v dst->y = v1->y - v2->y; } -// Add the polyobject's thinker to the thinker list -// Unlike P_AddThinker, this adds it to the front of the list instead of the back, so that carrying physics can work right. -Red -FUNCINLINE static ATTRINLINE void PolyObj_AddThinker(thinker_t *th) -{ - thinkercap.next->prev = th; - th->next = thinkercap.next; - th->prev = &thinkercap; - thinkercap.next = th; -} - // // P_PointInsidePolyobj // @@ -1518,7 +1508,7 @@ void Polyobj_InitLevel(void) // run down the thinker list, count the number of spawn points, and save // the mobj_t pointers on a queue for use below. - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 == (actionf_p1)P_MobjThinker) { @@ -1826,7 +1816,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) // Find out target first. // We redo this each tic to make savegame compatibility easier. - for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next) + for (wp = thlist[THINK_MAIN].next; wp != &thlist[THINK_MAIN]; wp = wp->next) { if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; @@ -1907,7 +1897,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) CONS_Debug(DBG_POLYOBJ, "Looking for next waypoint...\n"); // Find next waypoint - for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next) + for (wp = thlist[THINK_MAIN].next; wp != &thlist[THINK_MAIN]; wp = wp->next) { if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; @@ -1946,7 +1936,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) th->stophere = true; } - for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next) + for (wp = thlist[THINK_MAIN].next; wp != &thlist[THINK_MAIN]; wp = wp->next) { if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; @@ -1983,7 +1973,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) if (!th->continuous) th->comeback = false; - for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next) + for (wp = thlist[THINK_MAIN].next; wp != &thlist[THINK_MAIN]; wp = wp->next) { if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; @@ -2390,7 +2380,7 @@ INT32 EV_DoPolyObjRotate(polyrotdata_t *prdata) // create a new thinker th = Z_Malloc(sizeof(polyrotate_t), PU_LEVSPEC, NULL); th->thinker.function.acp1 = (actionf_p1)T_PolyObjRotate; - PolyObj_AddThinker(&th->thinker); + P_AddThinker(THINK_POLYOBJ, &th->thinker); po->thinker = &th->thinker; // set fields @@ -2455,7 +2445,7 @@ INT32 EV_DoPolyObjMove(polymovedata_t *pmdata) // create a new thinker th = Z_Malloc(sizeof(polymove_t), PU_LEVSPEC, NULL); th->thinker.function.acp1 = (actionf_p1)T_PolyObjMove; - PolyObj_AddThinker(&th->thinker); + P_AddThinker(THINK_POLYOBJ, &th->thinker); po->thinker = &th->thinker; // set fields @@ -2516,7 +2506,7 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) // create a new thinker th = Z_Malloc(sizeof(polywaypoint_t), PU_LEVSPEC, NULL); th->thinker.function.acp1 = (actionf_p1)T_PolyObjWaypoint; - PolyObj_AddThinker(&th->thinker); + P_AddThinker(THINK_POLYOBJ, &th->thinker); po->thinker = &th->thinker; // set fields @@ -2534,7 +2524,7 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) th->stophere = false; // Find the first waypoint we need to use - for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next) + for (wp = thlist[THINK_MAIN].next; wp != &thlist[THINK_MAIN]; wp = wp->next) { if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; @@ -2605,7 +2595,7 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) // Find the actual target movement waypoint target = first; - /*for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next) + /*for (wp = thlist[THINK_MAIN].next; wp != &thlist[THINK_MAIN]; wp = wp->next) { if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; @@ -2662,7 +2652,7 @@ static void Polyobj_doSlideDoor(polyobj_t *po, polydoordata_t *doordata) // allocate and add a new slide door thinker th = Z_Malloc(sizeof(polyslidedoor_t), PU_LEVSPEC, NULL); th->thinker.function.acp1 = (actionf_p1)T_PolyDoorSlide; - PolyObj_AddThinker(&th->thinker); + P_AddThinker(THINK_POLYOBJ, &th->thinker); // point the polyobject to this thinker po->thinker = &th->thinker; @@ -2710,7 +2700,7 @@ static void Polyobj_doSwingDoor(polyobj_t *po, polydoordata_t *doordata) // allocate and add a new swing door thinker th = Z_Malloc(sizeof(polyswingdoor_t), PU_LEVSPEC, NULL); th->thinker.function.acp1 = (actionf_p1)T_PolyDoorSwing; - PolyObj_AddThinker(&th->thinker); + P_AddThinker(THINK_POLYOBJ, &th->thinker); // point the polyobject to this thinker po->thinker = &th->thinker; @@ -2792,7 +2782,7 @@ INT32 EV_DoPolyObjDisplace(polydisplacedata_t *prdata) // create a new thinker th = Z_Malloc(sizeof(polydisplace_t), PU_LEVSPEC, NULL); th->thinker.function.acp1 = (actionf_p1)T_PolyObjDisplace; - PolyObj_AddThinker(&th->thinker); + P_AddThinker(THINK_POLYOBJ, &th->thinker); po->thinker = &th->thinker; // set fields @@ -2838,7 +2828,7 @@ INT32 EV_DoPolyObjRotDisplace(polyrotdisplacedata_t *prdata) // create a new thinker th = Z_Malloc(sizeof(polyrotdisplace_t), PU_LEVSPEC, NULL); th->thinker.function.acp1 = (actionf_p1)T_PolyObjRotDisplace; - PolyObj_AddThinker(&th->thinker); + P_AddThinker(THINK_POLYOBJ, &th->thinker); po->thinker = &th->thinker; // set fields @@ -2939,7 +2929,7 @@ INT32 EV_DoPolyObjFlag(line_t *pfdata) // create a new thinker th = Z_Malloc(sizeof(polymove_t), PU_LEVSPEC, NULL); th->thinker.function.acp1 = (actionf_p1)T_PolyObjFlag; - PolyObj_AddThinker(&th->thinker); + P_AddThinker(THINK_POLYOBJ, &th->thinker); po->thinker = &th->thinker; // set fields @@ -3089,7 +3079,7 @@ INT32 EV_DoPolyObjFade(polyfadedata_t *pfdata) // create a new thinker th = Z_Malloc(sizeof(polyfade_t), PU_LEVSPEC, NULL); th->thinker.function.acp1 = (actionf_p1)T_PolyObjFade; - PolyObj_AddThinker(&th->thinker); + P_AddThinker(THINK_POLYOBJ, &th->thinker); po->thinker = &th->thinker; // set fields diff --git a/src/p_saveg.c b/src/p_saveg.c index 0d58387b9..b72b055ae 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2135,236 +2135,241 @@ static inline void SaveWhatThinker(const thinker_t *th, const UINT8 type) static void P_NetArchiveThinkers(void) { const thinker_t *th; - UINT32 numsaved = 0; + UINT32 i; WRITEUINT32(save_p, ARCHIVEBLOCK_THINKERS); - // save off the current thinkers - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (i = 0; i < NUM_THINKERLISTS; i++) { - if (!(th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed - || th->function.acp1 == (actionf_p1)P_NullPrecipThinker)) - numsaved++; + UINT32 numsaved = 0; - if (th->function.acp1 == (actionf_p1)P_MobjThinker) + // save off the current thinkers + for (th = thlist[i].next; th != &thlist[i]; th = th->next) { - SaveMobjThinker(th, tc_mobj); - continue; - } -#ifdef PARANOIA - else if (th->function.acp1 == (actionf_p1)P_NullPrecipThinker); -#endif - else if (th->function.acp1 == (actionf_p1)T_MoveCeiling) - { - SaveCeilingThinker(th, tc_ceiling); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_CrushCeiling) - { - SaveCeilingThinker(th, tc_crushceiling); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_MoveFloor) - { - SaveFloormoveThinker(th, tc_floor); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_LightningFlash) - { - SaveLightflashThinker(th, tc_flash); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_StrobeFlash) - { - SaveStrobeThinker(th, tc_strobe); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_Glow) - { - SaveGlowThinker(th, tc_glow); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_FireFlicker) - { - SaveFireflickerThinker(th, tc_fireflicker); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_MoveElevator) - { - SaveElevatorThinker(th, tc_elevator); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_ContinuousFalling) - { - SaveSpecialLevelThinker(th, tc_continuousfalling); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_ThwompSector) - { - SaveSpecialLevelThinker(th, tc_thwomp); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_NoEnemiesSector) - { - SaveSpecialLevelThinker(th, tc_noenemies); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_EachTimeThinker) - { - SaveSpecialLevelThinker(th, tc_eachtime); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_RaiseSector) - { - SaveSpecialLevelThinker(th, tc_raisesector); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_CameraScanner) - { - SaveElevatorThinker(th, tc_camerascanner); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_Scroll) - { - SaveScrollThinker(th, tc_scroll); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_Friction) - { - SaveFrictionThinker(th, tc_friction); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_Pusher) - { - SavePusherThinker(th, tc_pusher); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_BounceCheese) - { - SaveSpecialLevelThinker(th, tc_bouncecheese); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_StartCrumble) - { - SaveElevatorThinker(th, tc_startcrumble); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_MarioBlock) - { - SaveSpecialLevelThinker(th, tc_marioblock); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_MarioBlockChecker) - { - SaveSpecialLevelThinker(th, tc_marioblockchecker); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_SpikeSector) - { - SaveSpecialLevelThinker(th, tc_spikesector); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_FloatSector) - { - SaveSpecialLevelThinker(th, tc_floatsector); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_BridgeThinker) - { - SaveSpecialLevelThinker(th, tc_bridgethinker); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_LaserFlash) - { - SaveLaserThinker(th, tc_laserflash); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_LightFade) - { - SaveLightlevelThinker(th, tc_lightfade); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_ExecutorDelay) - { - SaveExecutorThinker(th, tc_executor); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_Disappear) - { - SaveDisappearThinker(th, tc_disappear); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_Fade) - { - SaveFadeThinker(th, tc_fade); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_FadeColormap) - { - SaveFadeColormapThinker(th, tc_fadecolormap); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_PlaneDisplace) - { - SavePlaneDisplaceThinker(th, tc_planedisplace); - continue; - } -#ifdef POLYOBJECTS - else if (th->function.acp1 == (actionf_p1)T_PolyObjRotate) - { - SavePolyrotatetThinker(th, tc_polyrotate); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_PolyObjMove) - { - SavePolymoveThinker(th, tc_polymove); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_PolyObjWaypoint) - { - SavePolywaypointThinker(th, tc_polywaypoint); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_PolyDoorSlide) - { - SavePolyslidedoorThinker(th, tc_polyslidedoor); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_PolyDoorSwing) - { - SavePolyswingdoorThinker(th, tc_polyswingdoor); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_PolyObjFlag) - { - SavePolymoveThinker(th, tc_polyflag); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_PolyObjDisplace) - { - SavePolydisplaceThinker(th, tc_polydisplace); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_PolyObjRotDisplace) - { - SavePolyrotdisplaceThinker(th, tc_polyrotdisplace); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_PolyObjFade) - { - SavePolyfadeThinker(th, tc_polyfade); - continue; - } + if (!(th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed + || th->function.acp1 == (actionf_p1)P_NullPrecipThinker)) + numsaved++; + + if (th->function.acp1 == (actionf_p1)P_MobjThinker) + { + SaveMobjThinker(th, tc_mobj); + continue; + } + #ifdef PARANOIA + else if (th->function.acp1 == (actionf_p1)P_NullPrecipThinker); + #endif + else if (th->function.acp1 == (actionf_p1)T_MoveCeiling) + { + SaveCeilingThinker(th, tc_ceiling); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_CrushCeiling) + { + SaveCeilingThinker(th, tc_crushceiling); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_MoveFloor) + { + SaveFloormoveThinker(th, tc_floor); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_LightningFlash) + { + SaveLightflashThinker(th, tc_flash); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_StrobeFlash) + { + SaveStrobeThinker(th, tc_strobe); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_Glow) + { + SaveGlowThinker(th, tc_glow); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_FireFlicker) + { + SaveFireflickerThinker(th, tc_fireflicker); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_MoveElevator) + { + SaveElevatorThinker(th, tc_elevator); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_ContinuousFalling) + { + SaveSpecialLevelThinker(th, tc_continuousfalling); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_ThwompSector) + { + SaveSpecialLevelThinker(th, tc_thwomp); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_NoEnemiesSector) + { + SaveSpecialLevelThinker(th, tc_noenemies); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_EachTimeThinker) + { + SaveSpecialLevelThinker(th, tc_eachtime); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_RaiseSector) + { + SaveSpecialLevelThinker(th, tc_raisesector); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_CameraScanner) + { + SaveElevatorThinker(th, tc_camerascanner); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_Scroll) + { + SaveScrollThinker(th, tc_scroll); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_Friction) + { + SaveFrictionThinker(th, tc_friction); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_Pusher) + { + SavePusherThinker(th, tc_pusher); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_BounceCheese) + { + SaveSpecialLevelThinker(th, tc_bouncecheese); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_StartCrumble) + { + SaveElevatorThinker(th, tc_startcrumble); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_MarioBlock) + { + SaveSpecialLevelThinker(th, tc_marioblock); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_MarioBlockChecker) + { + SaveSpecialLevelThinker(th, tc_marioblockchecker); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_SpikeSector) + { + SaveSpecialLevelThinker(th, tc_spikesector); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_FloatSector) + { + SaveSpecialLevelThinker(th, tc_floatsector); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_BridgeThinker) + { + SaveSpecialLevelThinker(th, tc_bridgethinker); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_LaserFlash) + { + SaveLaserThinker(th, tc_laserflash); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_LightFade) + { + SaveLightlevelThinker(th, tc_lightfade); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_ExecutorDelay) + { + SaveExecutorThinker(th, tc_executor); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_Disappear) + { + SaveDisappearThinker(th, tc_disappear); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_Fade) + { + SaveFadeThinker(th, tc_fade); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_FadeColormap) + { + SaveFadeColormapThinker(th, tc_fadecolormap); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_PlaneDisplace) + { + SavePlaneDisplaceThinker(th, tc_planedisplace); + continue; + } + #ifdef POLYOBJECTS + else if (th->function.acp1 == (actionf_p1)T_PolyObjRotate) + { + SavePolyrotatetThinker(th, tc_polyrotate); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_PolyObjMove) + { + SavePolymoveThinker(th, tc_polymove); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_PolyObjWaypoint) + { + SavePolywaypointThinker(th, tc_polywaypoint); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_PolyDoorSlide) + { + SavePolyslidedoorThinker(th, tc_polyslidedoor); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_PolyDoorSwing) + { + SavePolyswingdoorThinker(th, tc_polyswingdoor); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_PolyObjFlag) + { + SavePolymoveThinker(th, tc_polyflag); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_PolyObjDisplace) + { + SavePolydisplaceThinker(th, tc_polydisplace); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_PolyObjRotDisplace) + { + SavePolyrotdisplaceThinker(th, tc_polyrotdisplace); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_PolyObjFade) + { + SavePolyfadeThinker(th, tc_polyfade); + continue; + } #endif #ifdef PARANOIA - else if (th->function.acv != P_RemoveThinkerDelayed) // wait garbage collection - I_Error("unknown thinker type %p", th->function.acp1); + else if (th->function.acv != P_RemoveThinkerDelayed) // wait garbage collection + I_Error("unknown thinker type %p", th->function.acp1); #endif + } + + CONS_Debug(DBG_NETPLAY, "%u thinkers saved\n", numsaved); + + WRITEUINT8(save_p, tc_end); } - - CONS_Debug(DBG_NETPLAY, "%u thinkers saved\n", numsaved); - - WRITEUINT8(save_p, tc_end); } // Now save the pointers, tracer and target, but at load time we must @@ -2376,7 +2381,7 @@ mobj_t *P_FindNewPosition(UINT32 oldposition) thinker_t *th; mobj_t *mobj; - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -2418,7 +2423,7 @@ static inline player_t *LoadPlayer(UINT32 player) // // Loads a mobj_t from a save game // -static void LoadMobjThinker(actionf_p1 thinker) +static thinker_t* LoadMobjThinker(actionf_p1 thinker) { thinker_t *next; mobj_t *mobj; @@ -2479,7 +2484,7 @@ static void LoadMobjThinker(actionf_p1 thinker) if (mapthings[spawnpointnum].type == 1705 || mapthings[spawnpointnum].type == 1713) // NiGHTS Hoop special case { P_SpawnHoopsAndRings(&mapthings[spawnpointnum], false); - return; + return NULL; } mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); @@ -2686,9 +2691,9 @@ static void LoadMobjThinker(actionf_p1 thinker) mobj->player->viewz = mobj->player->mo->z + mobj->player->viewheight; } - P_AddThinker(&mobj->thinker); - mobj->info = (mobjinfo_t *)next; // temporarily, set when leave this function + + return &mobj->thinker; } // @@ -2702,7 +2707,7 @@ static void LoadMobjThinker(actionf_p1 thinker) // 2 - Ceiling Only // 3 - Both // -static void LoadSpecialLevelThinker(actionf_p1 thinker, UINT8 floorOrCeiling) +static thinker_t* LoadSpecialLevelThinker(actionf_p1 thinker, UINT8 floorOrCeiling) { levelspecthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); size_t i; @@ -2723,7 +2728,7 @@ static void LoadSpecialLevelThinker(actionf_p1 thinker, UINT8 floorOrCeiling) ht->sector->floordata = ht; } - P_AddThinker(&ht->thinker); + return &ht->thinker; } // @@ -2731,7 +2736,7 @@ static void LoadSpecialLevelThinker(actionf_p1 thinker, UINT8 floorOrCeiling) // // Loads a ceiling_t from a save game // -static void LoadCeilingThinker(actionf_p1 thinker) +static thinker_t* LoadCeilingThinker(actionf_p1 thinker) { ceiling_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2752,7 +2757,7 @@ static void LoadCeilingThinker(actionf_p1 thinker) ht->sourceline = READFIXED(save_p); if (ht->sector) ht->sector->ceilingdata = ht; - P_AddThinker(&ht->thinker); + return &ht->thinker; } // @@ -2760,7 +2765,7 @@ static void LoadCeilingThinker(actionf_p1 thinker) // // Loads a floormove_t from a save game // -static void LoadFloormoveThinker(actionf_p1 thinker) +static thinker_t* LoadFloormoveThinker(actionf_p1 thinker) { floormove_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2776,7 +2781,7 @@ static void LoadFloormoveThinker(actionf_p1 thinker) ht->delaytimer = READFIXED(save_p); if (ht->sector) ht->sector->floordata = ht; - P_AddThinker(&ht->thinker); + return &ht->thinker; } // @@ -2784,7 +2789,7 @@ static void LoadFloormoveThinker(actionf_p1 thinker) // // Loads a lightflash_t from a save game // -static void LoadLightflashThinker(actionf_p1 thinker) +static thinker_t* LoadLightflashThinker(actionf_p1 thinker) { lightflash_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2793,7 +2798,7 @@ static void LoadLightflashThinker(actionf_p1 thinker) ht->minlight = READINT32(save_p); if (ht->sector) ht->sector->lightingdata = ht; - P_AddThinker(&ht->thinker); + return &ht->thinker; } // @@ -2801,7 +2806,7 @@ static void LoadLightflashThinker(actionf_p1 thinker) // // Loads a strobe_t from a save game // -static void LoadStrobeThinker(actionf_p1 thinker) +static thinker_t* LoadStrobeThinker(actionf_p1 thinker) { strobe_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2813,7 +2818,7 @@ static void LoadStrobeThinker(actionf_p1 thinker) ht->brighttime = READINT32(save_p); if (ht->sector) ht->sector->lightingdata = ht; - P_AddThinker(&ht->thinker); + return &ht->thinker; } // @@ -2821,7 +2826,7 @@ static void LoadStrobeThinker(actionf_p1 thinker) // // Loads a glow_t from a save game // -static void LoadGlowThinker(actionf_p1 thinker) +static thinker_t* LoadGlowThinker(actionf_p1 thinker) { glow_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2832,14 +2837,14 @@ static void LoadGlowThinker(actionf_p1 thinker) ht->speed = READINT32(save_p); if (ht->sector) ht->sector->lightingdata = ht; - P_AddThinker(&ht->thinker); + return &ht->thinker; } // // LoadFireflickerThinker // // Loads a fireflicker_t from a save game // -static void LoadFireflickerThinker(actionf_p1 thinker) +static thinker_t* LoadFireflickerThinker(actionf_p1 thinker) { fireflicker_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2850,14 +2855,14 @@ static void LoadFireflickerThinker(actionf_p1 thinker) ht->minlight = READINT32(save_p); if (ht->sector) ht->sector->lightingdata = ht; - P_AddThinker(&ht->thinker); + return &ht->thinker; } // // LoadElevatorThinker // // Loads a elevator_t from a save game // -static void LoadElevatorThinker(actionf_p1 thinker, UINT8 floorOrCeiling) +static thinker_t* LoadElevatorThinker(actionf_p1 thinker, UINT8 floorOrCeiling) { elevator_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2887,7 +2892,7 @@ static void LoadElevatorThinker(actionf_p1 thinker, UINT8 floorOrCeiling) ht->sector->floordata = ht; } - P_AddThinker(&ht->thinker); + return &ht->thinker; } // @@ -2895,7 +2900,7 @@ static void LoadElevatorThinker(actionf_p1 thinker, UINT8 floorOrCeiling) // // Loads a scroll_t from a save game // -static void LoadScrollThinker(actionf_p1 thinker) +static thinker_t* LoadScrollThinker(actionf_p1 thinker) { scroll_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2909,7 +2914,7 @@ static void LoadScrollThinker(actionf_p1 thinker) ht->accel = READINT32(save_p); ht->exclusive = READINT32(save_p); ht->type = READUINT8(save_p); - P_AddThinker(&ht->thinker); + return &ht->thinker; } // @@ -2917,7 +2922,7 @@ static void LoadScrollThinker(actionf_p1 thinker) // // Loads a friction_t from a save game // -static inline void LoadFrictionThinker(actionf_p1 thinker) +static inline thinker_t* LoadFrictionThinker(actionf_p1 thinker) { friction_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2926,7 +2931,7 @@ static inline void LoadFrictionThinker(actionf_p1 thinker) ht->affectee = READINT32(save_p); ht->referrer = READINT32(save_p); ht->roverfriction = READUINT8(save_p); - P_AddThinker(&ht->thinker); + return &ht->thinker; } // @@ -2934,7 +2939,7 @@ static inline void LoadFrictionThinker(actionf_p1 thinker) // // Loads a pusher_t from a save game // -static void LoadPusherThinker(actionf_p1 thinker) +static thinker_t* LoadPusherThinker(actionf_p1 thinker) { pusher_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2952,7 +2957,7 @@ static void LoadPusherThinker(actionf_p1 thinker) ht->exclusive = READINT32(save_p); ht->slider = READINT32(save_p); ht->source = P_GetPushThing(ht->affectee); - P_AddThinker(&ht->thinker); + return &ht->thinker; } // @@ -2960,7 +2965,7 @@ static void LoadPusherThinker(actionf_p1 thinker) // // Loads a laserthink_t from a save game // -static inline void LoadLaserThinker(actionf_p1 thinker) +static inline thinker_t* LoadLaserThinker(actionf_p1 thinker) { laserthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ffloor_t *rover = NULL; @@ -2972,7 +2977,7 @@ static inline void LoadLaserThinker(actionf_p1 thinker) if (rover->secnum == (size_t)(ht->sec - sectors) && rover->master == ht->sourceline) ht->ffloor = rover; - P_AddThinker(&ht->thinker); + return &ht->thinker; } // @@ -2980,7 +2985,7 @@ static inline void LoadLaserThinker(actionf_p1 thinker) // // Loads a lightlevel_t from a save game // -static inline void LoadLightlevelThinker(actionf_p1 thinker) +static inline thinker_t* LoadLightlevelThinker(actionf_p1 thinker) { lightlevel_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2992,7 +2997,7 @@ static inline void LoadLightlevelThinker(actionf_p1 thinker) ht->timer = READINT32(save_p); if (ht->sector) ht->sector->lightingdata = ht; - P_AddThinker(&ht->thinker); + return &ht->thinker; } // @@ -3000,7 +3005,7 @@ static inline void LoadLightlevelThinker(actionf_p1 thinker) // // Loads a executor_t from a save game // -static inline void LoadExecutorThinker(actionf_p1 thinker) +static inline thinker_t* LoadExecutorThinker(actionf_p1 thinker) { executor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -3008,7 +3013,7 @@ static inline void LoadExecutorThinker(actionf_p1 thinker) ht->caller = LoadMobj(READUINT32(save_p)); ht->sector = LoadSector(READUINT32(save_p)); ht->timer = READINT32(save_p); - P_AddThinker(&ht->thinker); + return &ht->thinker; } // @@ -3016,7 +3021,7 @@ static inline void LoadExecutorThinker(actionf_p1 thinker) // // Loads a disappear_t thinker // -static inline void LoadDisappearThinker(actionf_p1 thinker) +static inline thinker_t* LoadDisappearThinker(actionf_p1 thinker) { disappear_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -3027,7 +3032,7 @@ static inline void LoadDisappearThinker(actionf_p1 thinker) ht->affectee = READINT32(save_p); ht->sourceline = READINT32(save_p); ht->exists = READINT32(save_p); - P_AddThinker(&ht->thinker); + return &ht->thinker; } // @@ -3035,7 +3040,7 @@ static inline void LoadDisappearThinker(actionf_p1 thinker) // // Loads a fade_t thinker // -static inline void LoadFadeThinker(actionf_p1 thinker) +static inline thinker_t* LoadFadeThinker(actionf_p1 thinker) { sector_t *ss; fade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); @@ -3074,14 +3079,14 @@ static inline void LoadFadeThinker(actionf_p1 thinker) j++; } } - P_AddThinker(&ht->thinker); + return &ht->thinker; } // LoadFadeColormapThinker // // Loads a fadecolormap_t from a save game // -static inline void LoadFadeColormapThinker(actionf_p1 thinker) +static inline thinker_t* LoadFadeColormapThinker(actionf_p1 thinker) { fadecolormap_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -3093,7 +3098,7 @@ static inline void LoadFadeColormapThinker(actionf_p1 thinker) ht->timer = READINT32(save_p); if (ht->sector) ht->sector->fadecolormapdata = ht; - P_AddThinker(&ht->thinker); + return &ht->thinker; } // @@ -3101,7 +3106,7 @@ static inline void LoadFadeColormapThinker(actionf_p1 thinker) // // Loads a planedisplace_t thinker // -static inline void LoadPlaneDisplaceThinker(actionf_p1 thinker) +static inline thinker_t* LoadPlaneDisplaceThinker(actionf_p1 thinker) { planedisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -3110,7 +3115,7 @@ static inline void LoadPlaneDisplaceThinker(actionf_p1 thinker) ht->last_height = READFIXED(save_p); ht->speed = READFIXED(save_p); ht->type = READUINT8(save_p); - P_AddThinker(&ht->thinker); + return &ht->thinker; } #ifdef POLYOBJECTS @@ -3120,14 +3125,14 @@ static inline void LoadPlaneDisplaceThinker(actionf_p1 thinker) // // Loads a polyrotate_t thinker // -static inline void LoadPolyrotatetThinker(actionf_p1 thinker) +static inline thinker_t* LoadPolyrotatetThinker(actionf_p1 thinker) { polyrotate_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; ht->polyObjNum = READINT32(save_p); ht->speed = READINT32(save_p); ht->distance = READINT32(save_p); - P_AddThinker(&ht->thinker); + return &ht->thinker; } // @@ -3135,7 +3140,7 @@ static inline void LoadPolyrotatetThinker(actionf_p1 thinker) // // Loads a polymovet_t thinker // -static void LoadPolymoveThinker(actionf_p1 thinker) +static thinker_t* LoadPolymoveThinker(actionf_p1 thinker) { polymove_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -3145,7 +3150,7 @@ static void LoadPolymoveThinker(actionf_p1 thinker) ht->momy = READFIXED(save_p); ht->distance = READINT32(save_p); ht->angle = READANGLE(save_p); - P_AddThinker(&ht->thinker); + return &ht->thinker; } // @@ -3153,7 +3158,7 @@ static void LoadPolymoveThinker(actionf_p1 thinker) // // Loads a polywaypoint_t thinker // -static inline void LoadPolywaypointThinker(actionf_p1 thinker) +static inline thinker_t* LoadPolywaypointThinker(actionf_p1 thinker) { polywaypoint_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -3169,7 +3174,7 @@ static inline void LoadPolywaypointThinker(actionf_p1 thinker) ht->diffx = READFIXED(save_p); ht->diffy = READFIXED(save_p); ht->diffz = READFIXED(save_p); - P_AddThinker(&ht->thinker); + return &ht->thinker; } // @@ -3177,7 +3182,7 @@ static inline void LoadPolywaypointThinker(actionf_p1 thinker) // // loads a polyslidedoor_t thinker // -static inline void LoadPolyslidedoorThinker(actionf_p1 thinker) +static inline thinker_t* LoadPolyslidedoorThinker(actionf_p1 thinker) { polyslidedoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -3194,7 +3199,7 @@ static inline void LoadPolyslidedoorThinker(actionf_p1 thinker) ht->momx = READFIXED(save_p); ht->momy = READFIXED(save_p); ht->closing = READUINT8(save_p); - P_AddThinker(&ht->thinker); + return &ht->thinker; } // @@ -3202,7 +3207,7 @@ static inline void LoadPolyslidedoorThinker(actionf_p1 thinker) // // Loads a polyswingdoor_t thinker // -static inline void LoadPolyswingdoorThinker(actionf_p1 thinker) +static inline thinker_t* LoadPolyswingdoorThinker(actionf_p1 thinker) { polyswingdoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -3214,7 +3219,7 @@ static inline void LoadPolyswingdoorThinker(actionf_p1 thinker) ht->initDistance = READINT32(save_p); ht->distance = READINT32(save_p); ht->closing = READUINT8(save_p); - P_AddThinker(&ht->thinker); + return &ht->thinker; } // @@ -3222,7 +3227,7 @@ static inline void LoadPolyswingdoorThinker(actionf_p1 thinker) // // Loads a polydisplace_t thinker // -static inline void LoadPolydisplaceThinker(actionf_p1 thinker) +static inline thinker_t* LoadPolydisplaceThinker(actionf_p1 thinker) { polydisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -3231,10 +3236,10 @@ static inline void LoadPolydisplaceThinker(actionf_p1 thinker) ht->dx = READFIXED(save_p); ht->dy = READFIXED(save_p); ht->oldHeights = READFIXED(save_p); - P_AddThinker(&ht->thinker); + return &ht->thinker; } -static inline void LoadPolyrotdisplaceThinker(actionf_p1 thinker) +static inline thinker_t* LoadPolyrotdisplaceThinker(actionf_p1 thinker) { polyrotdisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -3243,7 +3248,7 @@ static inline void LoadPolyrotdisplaceThinker(actionf_p1 thinker) ht->rotscale = READFIXED(save_p); ht->turnobjs = READUINT8(save_p); ht->oldHeights = READFIXED(save_p); - P_AddThinker(&ht->thinker); + return &ht->thinker; } // @@ -3251,7 +3256,7 @@ static inline void LoadPolyrotdisplaceThinker(actionf_p1 thinker) // // Loads a polyfadet_t thinker // -static void LoadPolyfadeThinker(actionf_p1 thinker) +static thinker_t* LoadPolyfadeThinker(actionf_p1 thinker) { polyfade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -3263,7 +3268,7 @@ static void LoadPolyfadeThinker(actionf_p1 thinker) ht->ticbased = (boolean)READUINT8(save_p); ht->duration = READINT32(save_p); ht->timer = READINT32(save_p); - P_AddThinker(&ht->thinker); + return &ht->thinker; } #endif @@ -3296,15 +3301,18 @@ static void P_NetUnArchiveThinkers(void) I_Error("Bad $$$.sav at archive block Thinkers"); // remove all the current thinkers - currentthinker = thinkercap.next; - for (currentthinker = thinkercap.next; currentthinker != &thinkercap; currentthinker = next) + for (i = 0; i < NUM_THINKERLISTS; i++) { - next = currentthinker->next; + currentthinker = thlist[i].next; + for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = next) + { + next = currentthinker->next; - if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) - P_RemoveSavegameMobj((mobj_t *)currentthinker); // item isn't saved, don't remove it - else - Z_Free(currentthinker); + if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) + P_RemoveSavegameMobj((mobj_t *)currentthinker); // item isn't saved, don't remove it + else + Z_Free(currentthinker); + } } // we don't want the removed mobjs to come back @@ -3318,202 +3326,208 @@ static void P_NetUnArchiveThinkers(void) } // read in saved thinkers - for (;;) + for (i = 0; i < NUM_THINKERLISTS; i++) { - tclass = READUINT8(save_p); - - if (tclass == tc_end) - break; // leave the saved thinker reading loop - numloaded++; - - switch (tclass) + for (;;) { - case tc_mobj: - LoadMobjThinker((actionf_p1)P_MobjThinker); - break; + thinker_t* th; + tclass = READUINT8(save_p); - case tc_ceiling: - LoadCeilingThinker((actionf_p1)T_MoveCeiling); - break; + if (tclass == tc_end) + break; // leave the saved thinker reading loop + numloaded++; - case tc_crushceiling: - LoadCeilingThinker((actionf_p1)T_CrushCeiling); - break; - - case tc_floor: - LoadFloormoveThinker((actionf_p1)T_MoveFloor); - break; - - case tc_flash: - LoadLightflashThinker((actionf_p1)T_LightningFlash); - break; - - case tc_strobe: - LoadStrobeThinker((actionf_p1)T_StrobeFlash); - break; - - case tc_glow: - LoadGlowThinker((actionf_p1)T_Glow); - break; - - case tc_fireflicker: - LoadFireflickerThinker((actionf_p1)T_FireFlicker); - break; - - case tc_elevator: - LoadElevatorThinker((actionf_p1)T_MoveElevator, 3); - break; - - case tc_continuousfalling: - LoadSpecialLevelThinker((actionf_p1)T_ContinuousFalling, 3); - break; - - case tc_thwomp: - LoadSpecialLevelThinker((actionf_p1)T_ThwompSector, 3); - break; - - case tc_noenemies: - LoadSpecialLevelThinker((actionf_p1)T_NoEnemiesSector, 0); - break; - - case tc_eachtime: - LoadSpecialLevelThinker((actionf_p1)T_EachTimeThinker, 0); - break; - - case tc_raisesector: - LoadSpecialLevelThinker((actionf_p1)T_RaiseSector, 0); - break; - - /// \todo rewrite all the code that uses an elevator_t but isn't an elevator - /// \note working on it! - case tc_camerascanner: - LoadElevatorThinker((actionf_p1)T_CameraScanner, 0); - break; - - case tc_bouncecheese: - LoadSpecialLevelThinker((actionf_p1)T_BounceCheese, 2); - break; - - case tc_startcrumble: - LoadElevatorThinker((actionf_p1)T_StartCrumble, 1); - break; - - case tc_marioblock: - LoadSpecialLevelThinker((actionf_p1)T_MarioBlock, 3); - break; - - case tc_marioblockchecker: - LoadSpecialLevelThinker((actionf_p1)T_MarioBlockChecker, 0); - break; - - case tc_spikesector: - LoadSpecialLevelThinker((actionf_p1)T_SpikeSector, 0); - break; - - case tc_floatsector: - LoadSpecialLevelThinker((actionf_p1)T_FloatSector, 0); - break; - - case tc_bridgethinker: - LoadSpecialLevelThinker((actionf_p1)T_BridgeThinker, 3); - break; - - case tc_laserflash: - LoadLaserThinker((actionf_p1)T_LaserFlash); - break; - - case tc_lightfade: - LoadLightlevelThinker((actionf_p1)T_LightFade); - break; - - case tc_executor: - LoadExecutorThinker((actionf_p1)T_ExecutorDelay); - restoreNum = true; - break; - - case tc_disappear: - LoadDisappearThinker((actionf_p1)T_Disappear); - break; - - case tc_fade: - LoadFadeThinker((actionf_p1)T_Fade); - break; - - case tc_fadecolormap: - LoadFadeColormapThinker((actionf_p1)T_FadeColormap); - break; - - case tc_planedisplace: - LoadPlaneDisplaceThinker((actionf_p1)T_PlaneDisplace); - break; -#ifdef POLYOBJECTS - case tc_polyrotate: - LoadPolyrotatetThinker((actionf_p1)T_PolyObjRotate); - break; - - case tc_polymove: - LoadPolymoveThinker((actionf_p1)T_PolyObjMove); - break; - - case tc_polywaypoint: - LoadPolywaypointThinker((actionf_p1)T_PolyObjWaypoint); - break; - - case tc_polyslidedoor: - LoadPolyslidedoorThinker((actionf_p1)T_PolyDoorSlide); - break; - - case tc_polyswingdoor: - LoadPolyswingdoorThinker((actionf_p1)T_PolyDoorSwing); - break; - - case tc_polyflag: - LoadPolymoveThinker((actionf_p1)T_PolyObjFlag); - break; - - case tc_polydisplace: - LoadPolydisplaceThinker((actionf_p1)T_PolyObjDisplace); - break; - - case tc_polyrotdisplace: - LoadPolyrotdisplaceThinker((actionf_p1)T_PolyObjRotDisplace); - break; - - case tc_polyfade: - LoadPolyfadeThinker((actionf_p1)T_PolyObjFade); - break; -#endif - case tc_scroll: - LoadScrollThinker((actionf_p1)T_Scroll); - break; - - case tc_friction: - LoadFrictionThinker((actionf_p1)T_Friction); - break; - - case tc_pusher: - LoadPusherThinker((actionf_p1)T_Pusher); - break; - - default: - I_Error("P_UnarchiveSpecials: Unknown tclass %d in savegame", tclass); - } - } - - CONS_Debug(DBG_NETPLAY, "%u thinkers loaded\n", numloaded); - - if (restoreNum) - { - executor_t *delay = NULL; - UINT32 mobjnum; - for (currentthinker = thinkercap.next; currentthinker != &thinkercap; - currentthinker = currentthinker->next) - { - if (currentthinker->function.acp1 == (actionf_p1)T_ExecutorDelay) + switch (tclass) { - delay = (void *)currentthinker; - if ((mobjnum = (UINT32)(size_t)delay->caller)) - delay->caller = P_FindNewPosition(mobjnum); + case tc_mobj: + th = LoadMobjThinker((actionf_p1)P_MobjThinker); + break; + + case tc_ceiling: + th = LoadCeilingThinker((actionf_p1)T_MoveCeiling); + break; + + case tc_crushceiling: + th = LoadCeilingThinker((actionf_p1)T_CrushCeiling); + break; + + case tc_floor: + th = LoadFloormoveThinker((actionf_p1)T_MoveFloor); + break; + + case tc_flash: + th = LoadLightflashThinker((actionf_p1)T_LightningFlash); + break; + + case tc_strobe: + th = LoadStrobeThinker((actionf_p1)T_StrobeFlash); + break; + + case tc_glow: + th = LoadGlowThinker((actionf_p1)T_Glow); + break; + + case tc_fireflicker: + th = LoadFireflickerThinker((actionf_p1)T_FireFlicker); + break; + + case tc_elevator: + th = LoadElevatorThinker((actionf_p1)T_MoveElevator, 3); + break; + + case tc_continuousfalling: + th = LoadSpecialLevelThinker((actionf_p1)T_ContinuousFalling, 3); + break; + + case tc_thwomp: + th = LoadSpecialLevelThinker((actionf_p1)T_ThwompSector, 3); + break; + + case tc_noenemies: + th = LoadSpecialLevelThinker((actionf_p1)T_NoEnemiesSector, 0); + break; + + case tc_eachtime: + th = LoadSpecialLevelThinker((actionf_p1)T_EachTimeThinker, 0); + break; + + case tc_raisesector: + th = LoadSpecialLevelThinker((actionf_p1)T_RaiseSector, 0); + break; + + /// \todo rewrite all the code that uses an elevator_t but isn't an elevator + /// \note working on it! + case tc_camerascanner: + th = LoadElevatorThinker((actionf_p1)T_CameraScanner, 0); + break; + + case tc_bouncecheese: + th = LoadSpecialLevelThinker((actionf_p1)T_BounceCheese, 2); + break; + + case tc_startcrumble: + th = LoadElevatorThinker((actionf_p1)T_StartCrumble, 1); + break; + + case tc_marioblock: + th = LoadSpecialLevelThinker((actionf_p1)T_MarioBlock, 3); + break; + + case tc_marioblockchecker: + th = LoadSpecialLevelThinker((actionf_p1)T_MarioBlockChecker, 0); + break; + + case tc_spikesector: + th = LoadSpecialLevelThinker((actionf_p1)T_SpikeSector, 0); + break; + + case tc_floatsector: + th = LoadSpecialLevelThinker((actionf_p1)T_FloatSector, 0); + break; + + case tc_bridgethinker: + th = LoadSpecialLevelThinker((actionf_p1)T_BridgeThinker, 3); + break; + + case tc_laserflash: + th = LoadLaserThinker((actionf_p1)T_LaserFlash); + break; + + case tc_lightfade: + th = LoadLightlevelThinker((actionf_p1)T_LightFade); + break; + + case tc_executor: + th = LoadExecutorThinker((actionf_p1)T_ExecutorDelay); + restoreNum = true; + break; + + case tc_disappear: + th = LoadDisappearThinker((actionf_p1)T_Disappear); + break; + + case tc_fade: + th = LoadFadeThinker((actionf_p1)T_Fade); + break; + + case tc_fadecolormap: + th = LoadFadeColormapThinker((actionf_p1)T_FadeColormap); + break; + + case tc_planedisplace: + th = LoadPlaneDisplaceThinker((actionf_p1)T_PlaneDisplace); + break; + #ifdef POLYOBJECTS + case tc_polyrotate: + th = LoadPolyrotatetThinker((actionf_p1)T_PolyObjRotate); + break; + + case tc_polymove: + th = LoadPolymoveThinker((actionf_p1)T_PolyObjMove); + break; + + case tc_polywaypoint: + th = LoadPolywaypointThinker((actionf_p1)T_PolyObjWaypoint); + break; + + case tc_polyslidedoor: + th = LoadPolyslidedoorThinker((actionf_p1)T_PolyDoorSlide); + break; + + case tc_polyswingdoor: + th = LoadPolyswingdoorThinker((actionf_p1)T_PolyDoorSwing); + break; + + case tc_polyflag: + th = LoadPolymoveThinker((actionf_p1)T_PolyObjFlag); + break; + + case tc_polydisplace: + th = LoadPolydisplaceThinker((actionf_p1)T_PolyObjDisplace); + break; + + case tc_polyrotdisplace: + th = LoadPolyrotdisplaceThinker((actionf_p1)T_PolyObjRotDisplace); + break; + + case tc_polyfade: + th = LoadPolyfadeThinker((actionf_p1)T_PolyObjFade); + break; + #endif + case tc_scroll: + th = LoadScrollThinker((actionf_p1)T_Scroll); + break; + + case tc_friction: + th = LoadFrictionThinker((actionf_p1)T_Friction); + break; + + case tc_pusher: + th = LoadPusherThinker((actionf_p1)T_Pusher); + break; + + default: + I_Error("P_UnarchiveSpecials: Unknown tclass %d in savegame", tclass); + } + if (th) + P_AddThinker(i, th); + } + + CONS_Debug(DBG_NETPLAY, "%u thinkers loaded\n", numloaded); + + if (restoreNum) + { + executor_t *delay = NULL; + UINT32 mobjnum; + for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; + currentthinker = currentthinker->next) + { + if (currentthinker->function.acp1 == (actionf_p1)T_ExecutorDelay) + { + delay = (void *)currentthinker; + if ((mobjnum = (UINT32)(size_t)delay->caller)) + delay->caller = P_FindNewPosition(mobjnum); + } } } } @@ -3622,7 +3636,7 @@ static inline void P_FinishMobjs(void) mobj_t *mobj; // put info field there real value - for (currentthinker = thinkercap.next; currentthinker != &thinkercap; + for (currentthinker = thlist[THINK_MAIN].next; currentthinker != &thlist[THINK_MAIN]; currentthinker = currentthinker->next) { if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) @@ -3640,7 +3654,7 @@ static void P_RelinkPointers(void) UINT32 temp; // use info field (value = oldposition) to relink mobjs - for (currentthinker = thinkercap.next; currentthinker != &thinkercap; + for (currentthinker = thlist[THINK_MAIN].next; currentthinker != &thlist[THINK_MAIN]; currentthinker = currentthinker->next) { if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) @@ -4021,7 +4035,7 @@ void P_SaveNetGame(void) P_NetArchiveMisc(); // Assign the mobjnumber for pointer tracking - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 == (actionf_p1)P_MobjThinker) { diff --git a/src/p_setup.c b/src/p_setup.c index 3dd673906..61389a131 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -814,7 +814,7 @@ void P_ReloadRings(void) mapthing_t *mt = mapthings; // scan the thinkers to find rings/spheres/hoops to unset - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -883,7 +883,7 @@ void P_SwitchSpheresBonusMode(boolean bonustime) #endif // scan the thinkers to find spheres to switch - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -2298,7 +2298,7 @@ void P_LoadThingsOnly(void) } - for (think = thinkercap.next; think != &thinkercap; think = think->next) + for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_MobjThinker) continue; // not a mobj thinker diff --git a/src/p_spec.c b/src/p_spec.c index 44edec870..2c54eb2ab 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1644,7 +1644,7 @@ static void P_AddExecutorDelay(line_t *line, mobj_t *mobj, sector_t *sector) e->sector = sector; e->timer = (line->backsector->ceilingheight>>FRACBITS)+(line->backsector->floorheight>>FRACBITS); P_SetTarget(&e->caller, mobj); // Use P_SetTarget to make sure the mobj doesn't get freed while we're delaying. - P_AddThinker(&e->thinker); + P_AddThinker(THINK_MAIN, &e->thinker); } /** Used by P_RunTriggerLinedef to check a NiGHTS trigger linedef's conditions @@ -2253,7 +2253,7 @@ void P_SwitchWeather(INT32 weathernum) thinker_t *think; precipmobj_t *precipmobj; - for (think = thinkercap.next; think != &thinkercap; think = think->next) + for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker) continue; // not a precipmobj thinker @@ -2269,7 +2269,7 @@ void P_SwitchWeather(INT32 weathernum) precipmobj_t *precipmobj; state_t *st; - for (think = thinkercap.next; think != &thinkercap; think = think->next) + for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker) continue; // not a precipmobj thinker @@ -3136,7 +3136,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) scroll_t *scroller; thinker_t *th; - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)T_Scroll) continue; @@ -3972,7 +3972,7 @@ void P_SetupSignExit(player_t *player) // didn't find any signposts in the exit sector. // spin all signposts in the level then. - for (think = thinkercap.next; think != &thinkercap; think = think->next) + for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_MobjThinker) continue; // not a mobj thinker @@ -4004,7 +4004,7 @@ boolean P_IsFlagAtBase(mobjtype_t flag) mobj_t *mo; INT32 specialnum = 0; - for (think = thinkercap.next; think != &thinkercap; think = think->next) + for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_MobjThinker) continue; // not a mobj thinker @@ -4437,7 +4437,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers // Find the center of the Eggtrap and release all the pretty animals! // The chimps are my friends.. heeheeheheehehee..... - LouisJM - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -4743,7 +4743,7 @@ DoneSection2: // scan the thinkers // to find the first waypoint - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -4822,7 +4822,7 @@ DoneSection2: // scan the thinkers // to find the last waypoint - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -4974,7 +4974,7 @@ DoneSection2: // scan the thinkers // to find the first waypoint - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -5012,7 +5012,7 @@ DoneSection2: } // Find waypoint before this one (waypointlow) - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -5039,7 +5039,7 @@ DoneSection2: } // Find waypoint after this one (waypointhigh) - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -5758,7 +5758,7 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f // Just initialise both of these to placate the compiler. i = 0; - th = thinkercap.next; + th = thlist[THINK_MAIN].next; for(;;) { @@ -5768,7 +5768,7 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f th = secthinkers[sec2num].thinkers[i]; else break; } - else if (th == &thinkercap) + else if (th == &thlist[THINK_MAIN]) break; // Should this FOF have spikeness? @@ -5858,7 +5858,7 @@ static void P_AddSpikeThinker(sector_t *sec, INT32 referrer) // create and initialize new thinker spikes = Z_Calloc(sizeof (*spikes), PU_LEVSPEC, NULL); - P_AddThinker(&spikes->thinker); + P_AddThinker(THINK_MAIN, &spikes->thinker); spikes->thinker.function.acp1 = (actionf_p1)T_SpikeSector; @@ -5880,7 +5880,7 @@ static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline) // create and initialize new thinker floater = Z_Calloc(sizeof (*floater), PU_LEVSPEC, NULL); - P_AddThinker(&floater->thinker); + P_AddThinker(THINK_MAIN, &floater->thinker); floater->thinker.function.acp1 = (actionf_p1)T_FloatSector; @@ -5904,7 +5904,7 @@ static inline void P_AddBridgeThinker(line_t *sourceline, sector_t *sec) // create an initialize new thinker bridge = Z_Calloc(sizeof (*bridge), PU_LEVSPEC, NULL); - P_AddThinker(&bridge->thinker); + P_AddThinker(THINK_MAIN, &bridge->thinker); bridge->thinker.function.acp1 = (actionf_p1)T_BridgeThinker; @@ -5940,7 +5940,7 @@ static void P_AddPlaneDisplaceThinker(INT32 type, fixed_t speed, INT32 control, // create and initialize new displacement thinker displace = Z_Calloc(sizeof (*displace), PU_LEVSPEC, NULL); - P_AddThinker(&displace->thinker); + P_AddThinker(THINK_MAIN, &displace->thinker); displace->thinker.function.acp1 = (actionf_p1)T_PlaneDisplace; displace->affectee = affectee; @@ -5967,7 +5967,7 @@ static void P_AddBlockThinker(sector_t *sec, line_t *sourceline) // create and initialize new elevator thinker block = Z_Calloc(sizeof (*block), PU_LEVSPEC, NULL); - P_AddThinker(&block->thinker); + P_AddThinker(THINK_MAIN, &block->thinker); block->thinker.function.acp1 = (actionf_p1)T_MarioBlockChecker; block->sourceline = sourceline; @@ -5996,7 +5996,7 @@ static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline) levelspecthink_t *raise; raise = Z_Calloc(sizeof (*raise), PU_LEVSPEC, NULL); - P_AddThinker(&raise->thinker); + P_AddThinker(THINK_MAIN, &raise->thinker); raise->thinker.function.acp1 = (actionf_p1)T_RaiseSector; @@ -6035,7 +6035,7 @@ static void P_AddOldAirbob(sector_t *sec, line_t *sourceline, boolean noadjust) levelspecthink_t *airbob; airbob = Z_Calloc(sizeof (*airbob), PU_LEVSPEC, NULL); - P_AddThinker(&airbob->thinker); + P_AddThinker(THINK_MAIN, &airbob->thinker); airbob->thinker.function.acp1 = (actionf_p1)T_RaiseSector; @@ -6096,7 +6096,7 @@ static inline void P_AddThwompThinker(sector_t *sec, sector_t *actionsector, lin // create and initialize new elevator thinker thwomp = Z_Calloc(sizeof (*thwomp), PU_LEVSPEC, NULL); - P_AddThinker(&thwomp->thinker); + P_AddThinker(THINK_MAIN, &thwomp->thinker); thwomp->thinker.function.acp1 = (actionf_p1)T_ThwompSector; @@ -6132,7 +6132,7 @@ static inline void P_AddNoEnemiesThinker(sector_t *sec, line_t *sourceline) // create and initialize new thinker nobaddies = Z_Calloc(sizeof (*nobaddies), PU_LEVSPEC, NULL); - P_AddThinker(&nobaddies->thinker); + P_AddThinker(THINK_MAIN, &nobaddies->thinker); nobaddies->thinker.function.acp1 = (actionf_p1)T_NoEnemiesSector; @@ -6154,7 +6154,7 @@ static inline void P_AddEachTimeThinker(sector_t *sec, line_t *sourceline) // create and initialize new thinker eachtime = Z_Calloc(sizeof (*eachtime), PU_LEVSPEC, NULL); - P_AddThinker(&eachtime->thinker); + P_AddThinker(THINK_MAIN, &eachtime->thinker); eachtime->thinker.function.acp1 = (actionf_p1)T_EachTimeThinker; @@ -6176,7 +6176,7 @@ static inline void P_AddCameraScanner(sector_t *sourcesec, sector_t *actionsecto // create and initialize new elevator thinker elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL); - P_AddThinker(&elevator->thinker); + P_AddThinker(THINK_MAIN, &elevator->thinker); elevator->thinker.function.acp1 = (actionf_p1)T_CameraScanner; elevator->type = elevateBounce; @@ -6272,7 +6272,7 @@ static inline void EV_AddLaserThinker(sector_t *sec, sector_t *sec2, line_t *lin flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL); - P_AddThinker(&flash->thinker); + P_AddThinker(THINK_MAIN, &flash->thinker); flash->thinker.function.acp1 = (actionf_p1)T_LaserFlash; flash->ffloor = ffloor; @@ -6441,7 +6441,7 @@ void P_SpawnSpecials(INT32 fromnetsave) secthinkers = Z_Calloc(numsectors * sizeof(thinkerlist_t), PU_STATIC, NULL); // Firstly, find out how many there are in each sector - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 == (actionf_p1)T_SpikeSector) secthinkers[((levelspecthink_t *)th)->sector - sectors].count++; @@ -6461,7 +6461,7 @@ void P_SpawnSpecials(INT32 fromnetsave) } // Finally, populate the lists. - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { size_t secnum = (size_t)-1; @@ -7723,7 +7723,7 @@ static void Add_Scroller(INT32 type, fixed_t dx, fixed_t dy, INT32 control, INT3 if ((s->control = control) != -1) s->last_height = sectors[control].floorheight + sectors[control].ceilingheight; s->affectee = affectee; - P_AddThinker(&s->thinker); + P_AddThinker(THINK_MAIN, &s->thinker); } /** Initializes the scrollers. @@ -7892,7 +7892,7 @@ static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t o d->exists = true; d->timer = 1; - P_AddThinker(&d->thinker); + P_AddThinker(THINK_MAIN, &d->thinker); } /** Makes a FOF appear/disappear @@ -8381,7 +8381,7 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor FixedFloor(FixedDiv(abs(d->destvalue - d->alpha), d->speed))/FRACUNIT); } - P_AddThinker(&d->thinker); + P_AddThinker(THINK_MAIN, &d->thinker); } /** Makes a FOF fade @@ -8451,7 +8451,7 @@ static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, ext } sector->fadecolormapdata = d; - P_AddThinker(&d->thinker); // add thinker + P_AddThinker(THINK_MAIN, &d->thinker); // add thinker } void T_FadeColormap(fadecolormap_t *d) @@ -8570,7 +8570,7 @@ static void Add_Friction(INT32 friction, INT32 movefactor, INT32 affectee, INT32 else f->roverfriction = false; - P_AddThinker(&f->thinker); + P_AddThinker(THINK_MAIN, &f->thinker); } /** Applies friction to all things in a sector. @@ -8736,7 +8736,7 @@ static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t * p->z = p->source->z; } p->affectee = affectee; - P_AddThinker(&p->thinker); + P_AddThinker(THINK_MAIN, &p->thinker); } diff --git a/src/p_tick.c b/src/p_tick.c index 6f7c96ead..f4f73aa3d 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -35,8 +35,8 @@ tic_t leveltime; // but the first element must be thinker_t. // -// Both the head and tail of the thinker list. -thinker_t thinkercap; +// The entries will behave like both the head and tail of the lists. +thinker_t thlist[NUM_THINKERLISTS]; void Command_Numthinkers_f(void) { @@ -102,7 +102,7 @@ void Command_Numthinkers_f(void) return; } - for (think = thinkercap.next; think != &thinkercap; think = think->next) + for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) { if (think->function.acp1 != action) continue; @@ -139,7 +139,7 @@ void Command_CountMobjs_f(void) count = 0; - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -159,7 +159,7 @@ void Command_CountMobjs_f(void) { count = 0; - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -178,19 +178,18 @@ void Command_CountMobjs_f(void) // void P_InitThinkers(void) { - thinkercap.prev = thinkercap.next = &thinkercap; + UINT8 i; + for (i = 0; i < NUM_THINKERLISTS; i++) + thlist[i].prev = thlist[i].next = &thlist[i]; } -// -// P_AddThinker // Adds a new thinker at the end of the list. -// -void P_AddThinker(thinker_t *thinker) +void P_AddThinker(const thinklistnum_t n, thinker_t *thinker) { - thinkercap.prev->next = thinker; - thinker->next = &thinkercap; - thinker->prev = thinkercap.prev; - thinkercap.prev = thinker; + thlist[n].prev->next = thinker; + thinker->next = &thlist[n]; + thinker->prev = thlist[n].prev; + thlist[n].prev = thinker; thinker->references = 0; // killough 11/98: init reference counter to 0 } @@ -296,11 +295,17 @@ if ((*mop = targ) != NULL) // Set new target and if non-NULL, increase its count // static inline void P_RunThinkers(void) { - for (currentthinker = thinkercap.next; currentthinker != &thinkercap; currentthinker = currentthinker->next) + size_t i; + for (i = 0; i < NUM_THINKERLISTS; i++) { - if (currentthinker->function.acp1) - currentthinker->function.acp1(currentthinker); + //CONS_Printf("Running thinker list %d.\n", i); + for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = currentthinker->next) + { + if (currentthinker->function.acp1) + currentthinker->function.acp1(currentthinker); + } } + } // diff --git a/src/p_user.c b/src/p_user.c index ca14c64d4..fa5b0f502 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -343,7 +343,7 @@ UINT8 P_FindLowestMare(void) // scan the thinkers // to find the egg capsule with the lowest mare - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -392,7 +392,7 @@ boolean P_TransferToNextMare(player_t *player) // scan the thinkers // to find the closest axis point - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -443,7 +443,7 @@ static mobj_t *P_FindAxis(INT32 mare, INT32 axisnum) // scan the thinkers // to find the closest axis point - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -476,7 +476,7 @@ static mobj_t *P_FindAxisTransfer(INT32 mare, INT32 axisnum, mobjtype_t type) // scan the thinkers // to find the closest axis point - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -515,7 +515,7 @@ void P_TransferToAxis(player_t *player, INT32 axisnum) // scan the thinkers // to find the closest axis point - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -615,7 +615,7 @@ static void P_DeNightserizePlayer(player_t *player) } // Check to see if the player should be killed. - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -1567,7 +1567,7 @@ void P_SpawnShieldOrb(player_t *player) } // blaze through the thinkers to see if an orb already exists! - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -3057,7 +3057,7 @@ static void P_DoClimbing(player_t *player) angle_t sideangle; fixed_t dx, dy; - for (think = thinkercap.next; think != &thinkercap; think = think->next) + for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) { if (think->function.acp1 != (actionf_p1)T_Scroll) continue; @@ -4438,7 +4438,7 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range) if (player->powers[pw_super]) // increase range when super range *= 2; - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -5635,7 +5635,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad fixed_t truexspeed = xspeed*(!(player->pflags & PF_TRANSFERTOCLOSEST) && player->mo->target->flags2 & MF2_AMBUSH ? -1 : 1); // Find next waypoint - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; @@ -5671,7 +5671,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad // Look for a wrapper point. if (!transfer1) { - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; @@ -5699,7 +5699,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad } if (!transfer2) { - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; @@ -6406,7 +6406,7 @@ static void P_NiGHTSMovement(player_t *player) // scan the thinkers // to find the closest axis point - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -7216,7 +7216,7 @@ static void P_MovePlayer(player_t *player) thinker_t *th; mobj_t *mo2; - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -8124,7 +8124,7 @@ static void P_DoZoomTube(player_t *player) CONS_Debug(DBG_GAMELOGIC, "Looking for next waypoint...\n"); // Find next waypoint - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; @@ -8258,7 +8258,7 @@ static void P_DoRopeHang(player_t *player) CONS_Debug(DBG_GAMELOGIC, "Looking for next waypoint...\n"); // Find next waypoint - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; @@ -8283,7 +8283,7 @@ static void P_DoRopeHang(player_t *player) CONS_Debug(DBG_GAMELOGIC, "Next waypoint not found, wrapping to start...\n"); // Wrap around back to first waypoint - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; @@ -8349,7 +8349,7 @@ static void P_NukeAllPlayers(player_t *player) mobj_t *mo; thinker_t *think; - for (think = thinkercap.next; think != &thinkercap; think = think->next) + for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_MobjThinker) continue; // not a mobj thinker @@ -8397,7 +8397,7 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) } } - for (think = thinkercap.next; think != &thinkercap; think = think->next) + for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_MobjThinker) continue; // not a mobj thinker @@ -8448,7 +8448,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) const angle_t span = (bullet ? ANG30 : ANGLE_90); fixed_t dist, closestdist = 0; - for (think = thinkercap.next; think != &thinkercap; think = think->next) + for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_MobjThinker) continue; // not a mobj thinker @@ -8587,7 +8587,7 @@ void P_FindEmerald(void) // scan the remaining thinkers // to find all emeralds - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -10013,7 +10013,7 @@ void P_PlayerThink(player_t *player) fixed_t y = player->mo->y; fixed_t z = player->mo->z; - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; diff --git a/src/r_data.c b/src/r_data.c index 838bc160c..dbbc615fc 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -2242,7 +2242,7 @@ void R_PrecacheLevel(void) spritepresent = calloc(numsprites, sizeof (*spritepresent)); if (spritepresent == NULL) I_Error("%s: Out of memory looking up sprites", "R_PrecacheLevel"); - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) if (th->function.acp1 == (actionf_p1)P_MobjThinker) spritepresent[((mobj_t *)th)->sprite] = 1; diff --git a/src/st_stuff.c b/src/st_stuff.c index 9ad04b5ce..a946bf516 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2289,7 +2289,7 @@ static void ST_doItemFinderIconsAndSound(void) return; // Scan thinkers to find emblem mobj with these ids - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; From b60c66325c1cee2e64a6b063f1912a887a0d58d6 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sat, 20 Apr 2019 23:29:20 +0200 Subject: [PATCH 008/128] Added a mobj-only list entry for mobj thinkers Signed-off-by: Nev3r --- src/p_local.h | 1 + src/p_mobj.c | 6 +++--- src/p_polyobj.c | 14 +++++++------- src/p_saveg.c | 8 ++++---- src/p_setup.c | 6 +++--- src/p_spec.c | 18 +++++++++--------- src/p_tick.c | 6 +++--- src/p_user.c | 42 +++++++++++++++++++++--------------------- src/r_data.c | 2 +- src/st_stuff.c | 2 +- 10 files changed, 53 insertions(+), 52 deletions(-) diff --git a/src/p_local.h b/src/p_local.h index 254705ad6..1d5e7e36c 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -65,6 +65,7 @@ typedef enum{ THINK_POLYOBJ, THINK_MAIN, + THINK_MOBJ, NUM_THINKERLISTS } thinklistnum_t; /**< Thinker lists. */ extern thinker_t thlist[]; diff --git a/src/p_mobj.c b/src/p_mobj.c index ff07e2f2a..737b99e67 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9047,7 +9047,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) } if (!(mobj->flags & MF_NOTHINK)) - P_AddThinker(THINK_MAIN, &mobj->thinker); + P_AddThinker(THINK_MOBJ, &mobj->thinker); // Call action functions when the state is set if (st->action.acp1 && (mobj->flags & MF_RUNSPAWNFUNC)) @@ -9122,7 +9122,7 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype mobj->momz = mobjinfo[type].speed; mobj->thinker.function.acp1 = (actionf_p1)P_NullPrecipThinker; - P_AddThinker(THINK_MAIN, &mobj->thinker); + P_AddThinker(THINK_MOBJ, &mobj->thinker); CalculatePrecipFloor(mobj); @@ -9246,7 +9246,7 @@ void P_RemoveMobj(mobj_t *mobj) else { // Add thinker just to delay removing it until refrences are gone. mobj->flags &= ~MF_NOTHINK; - P_AddThinker(THINK_MAIN, (thinker_t *)mobj); + P_AddThinker(THINK_MOBJ, (thinker_t *)mobj); #ifdef SCRAMBLE_REMOVED // Invalidate mobj_t data to cause crashes if accessed! memset((UINT8 *)mobj + sizeof(thinker_t), 0xff, sizeof(mobj_t) - sizeof(thinker_t)); diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 05c2c9a65..c04f57723 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1508,7 +1508,7 @@ void Polyobj_InitLevel(void) // run down the thinker list, count the number of spawn points, and save // the mobj_t pointers on a queue for use below. - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 == (actionf_p1)P_MobjThinker) { @@ -1816,7 +1816,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) // Find out target first. // We redo this each tic to make savegame compatibility easier. - for (wp = thlist[THINK_MAIN].next; wp != &thlist[THINK_MAIN]; wp = wp->next) + for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; @@ -1897,7 +1897,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) CONS_Debug(DBG_POLYOBJ, "Looking for next waypoint...\n"); // Find next waypoint - for (wp = thlist[THINK_MAIN].next; wp != &thlist[THINK_MAIN]; wp = wp->next) + for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; @@ -1936,7 +1936,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) th->stophere = true; } - for (wp = thlist[THINK_MAIN].next; wp != &thlist[THINK_MAIN]; wp = wp->next) + for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; @@ -1973,7 +1973,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) if (!th->continuous) th->comeback = false; - for (wp = thlist[THINK_MAIN].next; wp != &thlist[THINK_MAIN]; wp = wp->next) + for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; @@ -2524,7 +2524,7 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) th->stophere = false; // Find the first waypoint we need to use - for (wp = thlist[THINK_MAIN].next; wp != &thlist[THINK_MAIN]; wp = wp->next) + for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; @@ -2595,7 +2595,7 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) // Find the actual target movement waypoint target = first; - /*for (wp = thlist[THINK_MAIN].next; wp != &thlist[THINK_MAIN]; wp = wp->next) + /*for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; diff --git a/src/p_saveg.c b/src/p_saveg.c index b72b055ae..bccf9dbe4 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2381,7 +2381,7 @@ mobj_t *P_FindNewPosition(UINT32 oldposition) thinker_t *th; mobj_t *mobj; - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -3636,7 +3636,7 @@ static inline void P_FinishMobjs(void) mobj_t *mobj; // put info field there real value - for (currentthinker = thlist[THINK_MAIN].next; currentthinker != &thlist[THINK_MAIN]; + for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ]; currentthinker = currentthinker->next) { if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) @@ -3654,7 +3654,7 @@ static void P_RelinkPointers(void) UINT32 temp; // use info field (value = oldposition) to relink mobjs - for (currentthinker = thlist[THINK_MAIN].next; currentthinker != &thlist[THINK_MAIN]; + for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ]; currentthinker = currentthinker->next) { if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) @@ -4035,7 +4035,7 @@ void P_SaveNetGame(void) P_NetArchiveMisc(); // Assign the mobjnumber for pointer tracking - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 == (actionf_p1)P_MobjThinker) { diff --git a/src/p_setup.c b/src/p_setup.c index 61389a131..876ca85a5 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -814,7 +814,7 @@ void P_ReloadRings(void) mapthing_t *mt = mapthings; // scan the thinkers to find rings/spheres/hoops to unset - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -883,7 +883,7 @@ void P_SwitchSpheresBonusMode(boolean bonustime) #endif // scan the thinkers to find spheres to switch - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -2298,7 +2298,7 @@ void P_LoadThingsOnly(void) } - for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) + for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_MobjThinker) continue; // not a mobj thinker diff --git a/src/p_spec.c b/src/p_spec.c index 2c54eb2ab..45027822c 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3972,7 +3972,7 @@ void P_SetupSignExit(player_t *player) // didn't find any signposts in the exit sector. // spin all signposts in the level then. - for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) + for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_MobjThinker) continue; // not a mobj thinker @@ -4004,7 +4004,7 @@ boolean P_IsFlagAtBase(mobjtype_t flag) mobj_t *mo; INT32 specialnum = 0; - for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) + for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_MobjThinker) continue; // not a mobj thinker @@ -4437,7 +4437,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers // Find the center of the Eggtrap and release all the pretty animals! // The chimps are my friends.. heeheeheheehehee..... - LouisJM - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -4743,7 +4743,7 @@ DoneSection2: // scan the thinkers // to find the first waypoint - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -4822,7 +4822,7 @@ DoneSection2: // scan the thinkers // to find the last waypoint - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -4974,7 +4974,7 @@ DoneSection2: // scan the thinkers // to find the first waypoint - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -5012,7 +5012,7 @@ DoneSection2: } // Find waypoint before this one (waypointlow) - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -5039,7 +5039,7 @@ DoneSection2: } // Find waypoint after this one (waypointhigh) - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -8451,7 +8451,7 @@ static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, ext } sector->fadecolormapdata = d; - P_AddThinker(THINK_MAIN, &d->thinker); // add thinker + P_AddThinker(THINK_MAIN, &d->thinker); } void T_FadeColormap(fadecolormap_t *d) diff --git a/src/p_tick.c b/src/p_tick.c index f4f73aa3d..4a71e3cd5 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -139,7 +139,7 @@ void Command_CountMobjs_f(void) count = 0; - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -159,7 +159,7 @@ void Command_CountMobjs_f(void) { count = 0; - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -298,7 +298,7 @@ static inline void P_RunThinkers(void) size_t i; for (i = 0; i < NUM_THINKERLISTS; i++) { - //CONS_Printf("Running thinker list %d.\n", i); + CONS_Printf("Running thinker list %d.\n", i); for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = currentthinker->next) { if (currentthinker->function.acp1) diff --git a/src/p_user.c b/src/p_user.c index fa5b0f502..26d62f62a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -343,7 +343,7 @@ UINT8 P_FindLowestMare(void) // scan the thinkers // to find the egg capsule with the lowest mare - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -392,7 +392,7 @@ boolean P_TransferToNextMare(player_t *player) // scan the thinkers // to find the closest axis point - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -443,7 +443,7 @@ static mobj_t *P_FindAxis(INT32 mare, INT32 axisnum) // scan the thinkers // to find the closest axis point - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -476,7 +476,7 @@ static mobj_t *P_FindAxisTransfer(INT32 mare, INT32 axisnum, mobjtype_t type) // scan the thinkers // to find the closest axis point - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -515,7 +515,7 @@ void P_TransferToAxis(player_t *player, INT32 axisnum) // scan the thinkers // to find the closest axis point - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -615,7 +615,7 @@ static void P_DeNightserizePlayer(player_t *player) } // Check to see if the player should be killed. - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -1567,7 +1567,7 @@ void P_SpawnShieldOrb(player_t *player) } // blaze through the thinkers to see if an orb already exists! - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -4438,7 +4438,7 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range) if (player->powers[pw_super]) // increase range when super range *= 2; - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -5635,7 +5635,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad fixed_t truexspeed = xspeed*(!(player->pflags & PF_TRANSFERTOCLOSEST) && player->mo->target->flags2 & MF2_AMBUSH ? -1 : 1); // Find next waypoint - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; @@ -5671,7 +5671,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad // Look for a wrapper point. if (!transfer1) { - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; @@ -5699,7 +5699,7 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad } if (!transfer2) { - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; @@ -6406,7 +6406,7 @@ static void P_NiGHTSMovement(player_t *player) // scan the thinkers // to find the closest axis point - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -7216,7 +7216,7 @@ static void P_MovePlayer(player_t *player) thinker_t *th; mobj_t *mo2; - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -8124,7 +8124,7 @@ static void P_DoZoomTube(player_t *player) CONS_Debug(DBG_GAMELOGIC, "Looking for next waypoint...\n"); // Find next waypoint - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; @@ -8258,7 +8258,7 @@ static void P_DoRopeHang(player_t *player) CONS_Debug(DBG_GAMELOGIC, "Looking for next waypoint...\n"); // Find next waypoint - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; @@ -8283,7 +8283,7 @@ static void P_DoRopeHang(player_t *player) CONS_Debug(DBG_GAMELOGIC, "Next waypoint not found, wrapping to start...\n"); // Wrap around back to first waypoint - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; @@ -8349,7 +8349,7 @@ static void P_NukeAllPlayers(player_t *player) mobj_t *mo; thinker_t *think; - for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) + for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_MobjThinker) continue; // not a mobj thinker @@ -8397,7 +8397,7 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) } } - for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) + for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_MobjThinker) continue; // not a mobj thinker @@ -8448,7 +8448,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) const angle_t span = (bullet ? ANG30 : ANGLE_90); fixed_t dist, closestdist = 0; - for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) + for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_MobjThinker) continue; // not a mobj thinker @@ -8587,7 +8587,7 @@ void P_FindEmerald(void) // scan the remaining thinkers // to find all emeralds - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -10013,7 +10013,7 @@ void P_PlayerThink(player_t *player) fixed_t y = player->mo->y; fixed_t z = player->mo->z; - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; diff --git a/src/r_data.c b/src/r_data.c index dbbc615fc..755cc7bcd 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -2242,7 +2242,7 @@ void R_PrecacheLevel(void) spritepresent = calloc(numsprites, sizeof (*spritepresent)); if (spritepresent == NULL) I_Error("%s: Out of memory looking up sprites", "R_PrecacheLevel"); - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) if (th->function.acp1 == (actionf_p1)P_MobjThinker) spritepresent[((mobj_t *)th)->sprite] = 1; diff --git a/src/st_stuff.c b/src/st_stuff.c index a946bf516..007363b03 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2289,7 +2289,7 @@ static void ST_doItemFinderIconsAndSound(void) return; // Scan thinkers to find emblem mobj with these ids - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; From 134679c287d51311aa95ae73bf57e240110d70f0 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sun, 21 Apr 2019 11:08:24 +0200 Subject: [PATCH 009/128] Fix some of the polyobject thinkers being removed via P_RemoveThinkerDelayed() directly Signed-off-by: Nev3r --- src/p_local.h | 1 - src/p_polyobj.c | 18 +++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/p_local.h b/src/p_local.h index 1d5e7e36c..b0c22767b 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -61,7 +61,6 @@ #define P_GetPlayerHeight(player) FixedMul(player->height, player->mo->scale) #define P_GetPlayerSpinHeight(player) FixedMul(player->spinheight, player->mo->scale) -// both the head and tail of the thinker list typedef enum{ THINK_POLYOBJ, THINK_MAIN, diff --git a/src/p_polyobj.c b/src/p_polyobj.c index c04f57723..fc760372a 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1647,7 +1647,7 @@ void T_PolyObjRotate(polyrotate_t *th) #else { CONS_Debug(DBG_POLYOBJ, "T_PolyObjRotate: thinker with invalid id %d removed.\n", th->polyObjNum); - P_RemoveThinkerDelayed(&th->thinker); + P_RemoveThinker(&th->thinker); return; } #endif @@ -1732,7 +1732,7 @@ void T_PolyObjMove(polymove_t *th) #else { CONS_Debug(DBG_POLYOBJ, "T_PolyObjMove: thinker with invalid id %d removed.\n", th->polyObjNum); - P_RemoveThinkerDelayed(&th->thinker); + P_RemoveThinker(&th->thinker); return; } #endif @@ -1805,7 +1805,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) #else { CONS_Debug(DBG_POLYOBJ, "T_PolyObjWaypoint: thinker with invalid id %d removed.", th->polyObjNum); - P_RemoveThinkerDelayed(&th->thinker); + P_RemoveThinker(&th->thinker); return; } #endif @@ -2079,7 +2079,7 @@ void T_PolyDoorSlide(polyslidedoor_t *th) #else { CONS_Debug(DBG_POLYOBJ, "T_PolyDoorSlide: thinker with invalid id %d removed.\n", th->polyObjNum); - P_RemoveThinkerDelayed(&th->thinker); + P_RemoveThinker(&th->thinker); return; } #endif @@ -2184,7 +2184,7 @@ void T_PolyDoorSwing(polyswingdoor_t *th) #else { CONS_Debug(DBG_POLYOBJ, "T_PolyDoorSwing: thinker with invalid id %d removed.\n", th->polyObjNum); - P_RemoveThinkerDelayed(&th->thinker); + P_RemoveThinker(&th->thinker); return; } #endif @@ -2283,7 +2283,7 @@ void T_PolyObjDisplace(polydisplace_t *th) #else { CONS_Debug(DBG_POLYOBJ, "T_PolyObjDisplace: thinker with invalid id %d removed.\n", th->polyObjNum); - P_RemoveThinkerDelayed(&th->thinker); + P_RemoveThinker(&th->thinker); return; } #endif @@ -2323,7 +2323,7 @@ void T_PolyObjRotDisplace(polyrotdisplace_t *th) #else { CONS_Debug(DBG_POLYOBJ, "T_PolyObjRotDisplace: thinker with invalid id %d removed.\n", th->polyObjNum); - P_RemoveThinkerDelayed(&th->thinker); + P_RemoveThinker(&th->thinker); return; } #endif @@ -2865,7 +2865,7 @@ void T_PolyObjFlag(polymove_t *th) #else { CONS_Debug(DBG_POLYOBJ, "T_PolyObjFlag: thinker with invalid id %d removed.\n", th->polyObjNum); - P_RemoveThinkerDelayed(&th->thinker); + P_RemoveThinker(&th->thinker); return; } #endif @@ -2968,7 +2968,7 @@ void T_PolyObjFade(polyfade_t *th) #else { CONS_Debug(DBG_POLYOBJ, "T_PolyObjFade: thinker with invalid id %d removed.\n", th->polyObjNum); - P_RemoveThinkerDelayed(&th->thinker); + P_RemoveThinker(&th->thinker); return; } #endif From 11dba34f43d87baf2096dd67a5e2c10118de534d Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sun, 21 Apr 2019 11:52:18 +0200 Subject: [PATCH 010/128] Remove dynamic slope queue list due to now being unnecessary. Signed-off-by: Nev3r --- src/p_setup.c | 1 - src/p_slopes.c | 45 +-------------------------------------------- 2 files changed, 1 insertion(+), 45 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index e15ba833b..d6e96a3f5 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2912,7 +2912,6 @@ boolean P_SetupLevel(boolean skipprecip) #ifdef ESLOPE P_ResetDynamicSlopes(fromnetsave); - P_LinkSlopeThinkers(); // Spawn slope thinkers just after plane move thinkers to avoid movement/update delays. #endif P_LoadThings(loademblems); diff --git a/src/p_slopes.c b/src/p_slopes.c index 6c494c7b4..6aee9fcff 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -28,46 +28,6 @@ pslope_t *slopelist = NULL; UINT16 slopecount = 0; -thinker_t *dynthinklist; -size_t dynthinknum; - -/// Links previously queued thinker list to the main thinker list. -void P_LinkSlopeThinkers (void) -{ - size_t i; - thinker_t *th = dynthinklist; - - CONS_Printf("Number of dynamic thinkers: %d\n", dynthinknum); - - for (i = 0; i < dynthinknum; i++) - { - thinker_t *next = th->next; - P_AddThinker(th); - th = next; - } -} - -/// Queues a thinker to a partial linked list to be immediately incorporated later via P_LinkSlopeThinkers(). -static void P_QueueSlopeThinker (thinker_t* th) -{ - thinker_t* last = dynthinklist; - - // First entry. - if (!last) - { - dynthinklist = th; - dynthinknum++; - return; - } - - while (last->next) - last = last->next; - - last->next = th; - - dynthinknum++; -} - // Calculate line normal void P_CalculateSlopeNormal(pslope_t *slope) { slope->normal.z = FINECOSINE(slope->zangle>>ANGLETOFINESHIFT); @@ -211,7 +171,7 @@ static inline void P_AddDynSlopeThinker (pslope_t* slope, dynplanetype_t type, l th->slope = slope; th->type = type; - P_QueueSlopeThinker(&th->thinker); + P_AddThinker(THINK_MAIN, &th->thinker); } @@ -596,9 +556,6 @@ void P_ResetDynamicSlopes(const UINT32 fromsave) { slopelist = NULL; slopecount = 0; - dynthinklist = NULL; - dynthinknum = 0; - /// Generates line special-defined slopes. for (i = 0; i < numlines; i++) { From aad78d49856ba7e09a849318af5747f8ec6798e0 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sun, 21 Apr 2019 12:00:10 +0200 Subject: [PATCH 011/128] Give slope thinkers their own list right before mobjs'. Signed-off-by: Nev3r --- src/p_local.h | 1 + src/p_slopes.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/p_local.h b/src/p_local.h index b0c22767b..23de23c85 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -64,6 +64,7 @@ typedef enum{ THINK_POLYOBJ, THINK_MAIN, + THINK_DYNSLOPE, THINK_MOBJ, NUM_THINKERLISTS } thinklistnum_t; /**< Thinker lists. */ diff --git a/src/p_slopes.c b/src/p_slopes.c index 6aee9fcff..e4b41419d 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -171,7 +171,7 @@ static inline void P_AddDynSlopeThinker (pslope_t* slope, dynplanetype_t type, l th->slope = slope; th->type = type; - P_AddThinker(THINK_MAIN, &th->thinker); + P_AddThinker(THINK_DYNSLOPE, &th->thinker); } From 696ccbd943f299c73b51d183793177103a207c27 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sun, 21 Apr 2019 12:58:22 +0200 Subject: [PATCH 012/128] Fix mobj list iteration oversights. Signed-off-by: Nev3r --- src/d_clisrv.c | 4 ++-- src/d_netcmd.c | 2 +- src/f_finale.c | 2 +- src/g_game.c | 6 +++--- src/hardware/hw_light.c | 2 +- src/lua_script.c | 29 ++++++++++++++++------------- src/m_cheat.c | 6 +++--- src/p_inter.c | 16 ++++++++-------- src/p_mobj.c | 18 +++++++++--------- 9 files changed, 44 insertions(+), 41 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 6796389e1..483dd4091 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4228,12 +4228,12 @@ static INT16 Consistancy(void) ret += P_GetRandSeed(); #ifdef MOBJCONSISTANCY - if (!thlist[THINK_MAIN].next) + if (!thlist[THINK_MOBJ].next) { DEBFILE(va("Consistancy = %u\n", ret)); return ret; } - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 4a31070b9..4193db7cf 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -4260,7 +4260,7 @@ static void Command_Archivetest_f(void) // assign mobjnum i = 1; - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) if (th->function.acp1 == (actionf_p1)P_MobjThinker) ((mobj_t *)th)->mobjnum = i++; diff --git a/src/f_finale.c b/src/f_finale.c index 0d9fffabd..a7e2ff78b 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1661,7 +1661,7 @@ void F_TitleScreenTicker(boolean run) mobj_t *mo2; mobj_t *cameraref = NULL; - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker continue; diff --git a/src/g_game.c b/src/g_game.c index e02d545cb..322315e41 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2557,7 +2557,7 @@ void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo) I_Assert((oldmo != NULL) && (newmo != NULL)); // scan all thinkers - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -4455,7 +4455,7 @@ void G_ConsGhostTic(void) demo_p += sizeof(angle_t); // angle, unnecessary for cons. mobj = NULL; - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -5851,7 +5851,7 @@ void G_DoPlayMetal(void) metalbuffer = metal_p = W_CacheLumpNum(l, PU_STATIC); // find metal sonic - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 6e05d6feb..21c11848a 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -1335,7 +1335,7 @@ static void HWR_SearchLightsInMobjs(void) //mobj_t * mobj; // search in the list of thinkers - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { // a mobj ? if (th->function.acp1 == (actionf_p1)P_MobjThinker) diff --git a/src/lua_script.c b/src/lua_script.c index 5ec923159..85b9c4038 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -420,9 +420,9 @@ void LUA_InvalidateLevel(void) ffloor_t *rover = NULL; if (!gL) return; - - for (th = thlist[THINK_MAIN].next; th && th != &thlist[THINK_MAIN]; th = th->next) - LUA_InvalidateUserdata(th); + for (i = 0; i < NUM_THINKERLISTS; i++) + for (th = thlist[i].next; th && th != &thlist[i]; th = th->next) + LUA_InvalidateUserdata(th); LUA_InvalidateMapthings(); @@ -1127,13 +1127,15 @@ void LUA_Archive(void) ArchiveExtVars(&players[i], "player"); } - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) - if (th->function.acp1 == (actionf_p1)P_MobjThinker) - { - // archive function will determine when to skip mobjs, - // and write mobjnum in otherwise. - ArchiveExtVars(th, "mobj"); - } + for (i = 0; i < NUM_THINKERLISTS; i++) + for (th = thlist[i].next; th != &thlist[i]; th = th->next) + if (th->function.acp1 == (actionf_p1)P_MobjThinker) + { + // archive function will determine when to skip mobjs, + // and write mobjnum in otherwise. + ArchiveExtVars(th, "mobj"); + } + WRITEUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum. LUAh_NetArchiveHook(NetArchive); // call the NetArchive hook in archive mode @@ -1161,9 +1163,10 @@ void LUA_UnArchive(void) do { mobjnum = READUINT32(save_p); // read a mobjnum - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) - if (th->function.acp1 == (actionf_p1)P_MobjThinker - && ((mobj_t *)th)->mobjnum == mobjnum) // find matching mobj + for (i = 0; i < NUM_THINKERLISTS; i++) + for (th = thlist[i].next; th != &thlist[i]; th = th->next) + if (th->function.acp1 == (actionf_p1)P_MobjThinker + && ((mobj_t *)th)->mobjnum == mobjnum) // find matching mobj UnArchiveExtVars(th); // apply variables } while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker. diff --git a/src/m_cheat.c b/src/m_cheat.c index 92b953f7a..879ba32ec 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -577,7 +577,7 @@ void Command_Teleport_f(void) INT32 starpostmax = 0; intz = starpostpath; // variable reuse - counting down for selection purposes - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -600,7 +600,7 @@ void Command_Teleport_f(void) break; } - if (th == &thlist[THINK_MAIN]) + if (th == &thlist[THINK_MOBJ]) { if (intz == starpostpath) CONS_Alert(CONS_NOTICE, M_GetText("No starpost of position %d found (%d max).\n"), starpostnum, starpostmax); @@ -1069,7 +1069,7 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c thinker_t *th; mobj_t *mo; - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; diff --git a/src/p_inter.c b/src/p_inter.c index 0d8dfcbeb..6869a29a5 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -97,7 +97,7 @@ void P_ClearStarPost(INT32 postnum) mobj_t *mo2; // scan the thinkers - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -126,7 +126,7 @@ void P_ResetStarposts(void) thinker_t *th; mobj_t *post; - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -807,7 +807,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // The player might have two Ideyas: toucher->tracer and toucher->tracer->hnext // so handle their anchorpoints accordingly. // scan the thinkers to find the corresponding anchorpoint - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -901,7 +901,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) count = 1; // scan the remaining thinkers - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -951,7 +951,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // Now we RE-scan all the thinkers to find close objects to pull // in from the paraloop. Isn't this just so efficient? - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -1325,7 +1325,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) EV_DoElevator(&junk, bridgeFall, false); // scan the remaining thinkers to find koopa - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -1424,7 +1424,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) thinker_t *th; mobj_t *mo2; - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -2461,7 +2461,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget // scan the thinkers to make sure all the old pinch dummies are gone on death // this can happen if the boss was hurt earlier than expected - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; diff --git a/src/p_mobj.c b/src/p_mobj.c index 737b99e67..564a23b1e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -713,7 +713,7 @@ void P_EmeraldManager(void) spawnpoints[i] = NULL; } - for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) + for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_MobjThinker) continue; // not a mobj thinker @@ -3699,7 +3699,7 @@ void P_DestroyRobots(void) mobj_t *mo; thinker_t *think; - for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) + for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_MobjThinker) continue; // not a mobj thinker @@ -4483,7 +4483,7 @@ static void P_Boss3Thinker(mobj_t *mobj) // scan the thinkers to make sure all the old pinch dummies are gone before making new ones // this can happen if the boss was hurt earlier than expected - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -4574,7 +4574,7 @@ static void P_Boss3Thinker(mobj_t *mobj) // scan the thinkers // to find a point that matches // the number - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -5195,7 +5195,7 @@ static void P_Boss7Thinker(mobj_t *mobj) closestdist = INT32_MAX; // Just in case... // Find waypoint he is closest to - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -5250,7 +5250,7 @@ static void P_Boss7Thinker(mobj_t *mobj) // scan the thinkers to find // the waypoint to use - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -5382,7 +5382,7 @@ static void P_Boss9Thinker(mobj_t *mobj) // Run through the thinkers ONCE and find all of the MT_BOSS9GATHERPOINT in the map. // Build a hoop linked list of 'em! - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -5848,7 +5848,7 @@ mobj_t *P_GetClosestAxis(mobj_t *source) fixed_t dist1, dist2 = 0; // scan the thinkers to find the closest axis point - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; @@ -11085,7 +11085,7 @@ ML_EFFECT4 : Don't clip inside the ground mobj->health = (mthing->angle / 360) + 1; // See if other starposts exist in this level that have the same value. - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { if (th->function.acp1 != (actionf_p1)P_MobjThinker) continue; From 8cb0f55a902ed9732451434a811838b9e0700fb2 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 21 Apr 2019 13:52:55 +0100 Subject: [PATCH 013/128] Rename thinkers.iterate to mobjs.iterate, kill the "mobjs" arg (though you still need the parentheses). Done a bit messily/lazily, I'll clean up if we can confirm this works I do wonder whether this library can be extended for all of thlist's lists... but for now it's mobj-only, since we only have the ability to mess with mobjs anyway. --- src/lua_thinkerlib.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/lua_thinkerlib.c b/src/lua_thinkerlib.c index 29bf7bb56..63eb15846 100644 --- a/src/lua_thinkerlib.c +++ b/src/lua_thinkerlib.c @@ -18,7 +18,7 @@ #define META_ITERATIONSTATE "iteration state" -static const char *const iter_opt[] = { +/*static const char *const iter_opt[] = { "all", "mobj", NULL}; @@ -26,7 +26,7 @@ static const char *const iter_opt[] = { static const actionf_p1 iter_funcs[] = { NULL, (actionf_p1)P_MobjThinker -}; +};*/ struct iterationState { actionf_p1 filter; @@ -64,7 +64,7 @@ static int lib_iterateThinkers(lua_State *L) lua_settop(L, 2); if (lua_isnil(L, 2)) - th = &thlist[THINK_MAIN]; + th = &thlist[THINK_MOBJ]; else if (lua_isuserdata(L, 2)) { if (lua_islightuserdata(L, 2)) @@ -94,11 +94,11 @@ static int lib_iterateThinkers(lua_State *L) if (!next) return luaL_error(L, "next thinker invalidated during iteration"); - for (; next != &thlist[THINK_MAIN]; next = next->next) + for (; next != &thlist[THINK_MOBJ]; next = next->next) if (!it->filter || next->function.acp1 == it->filter) { push_thinker(next); - if (next->next != &thlist[THINK_MAIN]) + if (next->next != &thlist[THINK_MOBJ]) { push_thinker(next->next); it->next = luaL_ref(L, LUA_REGISTRYINDEX); @@ -120,7 +120,7 @@ static int lib_startIterate(lua_State *L) luaL_getmetatable(L, META_ITERATIONSTATE); lua_setmetatable(L, -2); - it->filter = iter_funcs[luaL_checkoption(L, 1, "mobj", iter_opt)]; + it->filter = (actionf_p1)P_MobjThinker; //iter_funcs[luaL_checkoption(L, 1, "mobj", iter_opt)]; it->next = LUA_REFNIL; return 2; } @@ -138,7 +138,7 @@ int LUA_ThinkerLib(lua_State *L) lua_pushcfunction(L, lib_iterateThinkers); lua_pushcclosure(L, lib_startIterate, 1); lua_setfield(L, -2, "iterate"); - lua_setglobal(L, "thinkers"); + lua_setglobal(L, "mobjs"); return 0; } From fc9e14146019a44ebb2eaafe9410e60d30600f48 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sun, 21 Apr 2019 14:58:13 +0200 Subject: [PATCH 014/128] Give precip. its own thinker list Signed-off-by: Nev3r --- src/p_local.h | 1 + src/p_mobj.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/p_local.h b/src/p_local.h index 23de23c85..431f7318f 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -66,6 +66,7 @@ typedef enum{ THINK_MAIN, THINK_DYNSLOPE, THINK_MOBJ, + THINK_PRECIP, NUM_THINKERLISTS } thinklistnum_t; /**< Thinker lists. */ extern thinker_t thlist[]; diff --git a/src/p_mobj.c b/src/p_mobj.c index 564a23b1e..0cf309e4e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9122,7 +9122,7 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype mobj->momz = mobjinfo[type].speed; mobj->thinker.function.acp1 = (actionf_p1)P_NullPrecipThinker; - P_AddThinker(THINK_MOBJ, &mobj->thinker); + P_AddThinker(THINK_PRECIP, &mobj->thinker); CalculatePrecipFloor(mobj); From a3174fb56f8c6e9e315ddfbd495fb42cde4cca83 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sun, 21 Apr 2019 16:17:47 +0200 Subject: [PATCH 015/128] Add a temporary limbo list for thinkers that need to be freed, in order to keep other lists clean, especially the mobj list. Signed-off-by: Nev3r --- src/p_local.h | 1 + src/p_tick.c | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/p_local.h b/src/p_local.h index 431f7318f..70a08c0cb 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -62,6 +62,7 @@ #define P_GetPlayerSpinHeight(player) FixedMul(player->spinheight, player->mo->scale) typedef enum{ + THINK_LIMBO, THINK_POLYOBJ, THINK_MAIN, THINK_DYNSLOPE, diff --git a/src/p_tick.c b/src/p_tick.c index 4a71e3cd5..ae1174b15 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -244,10 +244,23 @@ void P_RemoveThinkerDelayed(void *pthinker) // void P_RemoveThinker(thinker_t *thinker) { + thinker_t *next = thinker->next; #ifdef HAVE_BLUA LUA_InvalidateUserdata(thinker); #endif thinker->function.acp1 = P_RemoveThinkerDelayed; + + if (currentthinker == thinker) + currentthinker = thinker->prev; + + // Remove thinker from its current list. + (next->prev = thinker->prev)->next = next; + + // Now add it to the limbo list + thlist[THINK_LIMBO].prev->next = thinker; + thinker->next = &thlist[THINK_LIMBO]; + thinker->prev = thlist[THINK_LIMBO].prev; + thlist[THINK_LIMBO].prev = thinker; } /* @@ -298,7 +311,6 @@ static inline void P_RunThinkers(void) size_t i; for (i = 0; i < NUM_THINKERLISTS; i++) { - CONS_Printf("Running thinker list %d.\n", i); for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = currentthinker->next) { if (currentthinker->function.acp1) From a9110c0645f674cb7075062d839ee2a623dc5c12 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sun, 21 Apr 2019 16:39:57 +0200 Subject: [PATCH 016/128] Fixed more mobj thinker iterator oversights and removed all mobj thinker function checks Mobjs got their own thinker list after all, and disappearing thinkers are automatically purged from their lists and sent to the limbo list. So it's safe to assume all thinkers inside the mobj list must be mobjs. Signed-off-by: Nev3r --- src/d_clisrv.c | 3 - src/d_netcmd.c | 3 +- src/f_finale.c | 3 - src/g_game.c | 8 -- src/hardware/hw_light.c | 6 +- src/m_cheat.c | 6 -- src/p_enemy.c | 45 +++-------- src/p_floor.c | 5 +- src/p_inter.c | 24 ------ src/p_mobj.c | 27 ------- src/p_polyobj.c | 55 ++++--------- src/p_saveg.c | 170 +++++++++++++++++++--------------------- src/p_setup.c | 9 --- src/p_spec.c | 24 ------ src/p_tick.c | 6 -- src/p_user.c | 63 --------------- src/r_data.c | 3 +- src/st_stuff.c | 2 - 18 files changed, 109 insertions(+), 353 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 483dd4091..2f77c258b 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4235,9 +4235,6 @@ static INT16 Consistancy(void) } for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo = (mobj_t *)th; if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_MONITOR | MF_FIRE | MF_ENEMY | MF_PAIN | MF_STICKY)) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 4193db7cf..093f87286 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -4261,8 +4261,7 @@ static void Command_Archivetest_f(void) // assign mobjnum i = 1; for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - if (th->function.acp1 == (actionf_p1)P_MobjThinker) - ((mobj_t *)th)->mobjnum = i++; + ((mobj_t *)th)->mobjnum = i++; // allocate buffer buf = save_p = ZZ_Alloc(1024); diff --git a/src/f_finale.c b/src/f_finale.c index a7e2ff78b..be0cc4453 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1663,9 +1663,6 @@ void F_TitleScreenTicker(boolean run) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - mo2 = (mobj_t *)th; if (!mo2) diff --git a/src/g_game.c b/src/g_game.c index 322315e41..e88a20ae2 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2559,9 +2559,6 @@ void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo) // scan all thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (!(mo2->flags & MF_MISSILE)) @@ -4457,8 +4454,6 @@ void G_ConsGhostTic(void) mobj = NULL; for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; mobj = (mobj_t *)th; if (mobj->type == (mobjtype_t)type && mobj->x == x && mobj->y == y && mobj->z == z) break; @@ -5853,9 +5848,6 @@ void G_DoPlayMetal(void) // find metal sonic for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo = (mobj_t *)th; if (mo->type != MT_METALSONIC_RACE) continue; diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 21c11848a..ed3d72893 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -1336,11 +1336,7 @@ static void HWR_SearchLightsInMobjs(void) // search in the list of thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - { - // a mobj ? - if (th->function.acp1 == (actionf_p1)P_MobjThinker) - HWR_AddMobjLights((mobj_t *)th); - } + HWR_AddMobjLights((mobj_t *)th); } #endif diff --git a/src/m_cheat.c b/src/m_cheat.c index 879ba32ec..734a7ae18 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -579,9 +579,6 @@ void Command_Teleport_f(void) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type != MT_STARPOST) @@ -1071,9 +1068,6 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo = (mobj_t *)th; // get offset from mt, which points to old mapthings, then add new location if (mo->spawnpoint) diff --git a/src/p_enemy.c b/src/p_enemy.c index 5364c4207..cbeeb6b09 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3514,11 +3514,8 @@ void A_BossDeath(mobj_t *mo) // scan the remaining thinkers to see // if all bosses are dead - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2 != mo && (mo2->flags & MF_BOSS) && mo2->health > 0) goto bossjustdie; // other boss not dead - just go straight to dying! @@ -3573,11 +3570,8 @@ bossjustdie: // Flee! Flee! Find a point to escape to! If none, just shoot upward! // scan the thinkers to find the runaway point - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == MT_BOSSFLYPOINT) @@ -5759,11 +5753,8 @@ void A_RingExplode(mobj_t *actor) S_StartSound(actor, sfx_prloop); - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2 == actor) // Don't explode yourself! Endless loop! @@ -7435,11 +7426,8 @@ void A_Boss3Path(mobj_t *actor) // scan the thinkers // to find a point that matches // the number - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && mo2->spawnpoint->angle == actor->threshold) { @@ -7826,11 +7814,8 @@ void A_FindTarget(mobj_t *actor) CONS_Debug(DBG_GAMELOGIC, "A_FindTarget called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2); // scan the thinkers - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == (mobjtype_t)locvar1) @@ -7891,11 +7876,8 @@ void A_FindTracer(mobj_t *actor) CONS_Debug(DBG_GAMELOGIC, "A_FindTracer called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2); // scan the thinkers - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == (mobjtype_t)locvar1) @@ -8454,11 +8436,8 @@ void A_RemoteAction(mobj_t *actor) fixed_t dist1 = 0, dist2 = 0; // scan the thinkers - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == (mobjtype_t)locvar1) @@ -8720,11 +8699,8 @@ void A_SetObjectTypeState(mobj_t *actor) return; #endif - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == (mobjtype_t)loc2lw) @@ -9358,11 +9334,8 @@ void A_CheckThingCount(mobj_t *actor) return; #endif - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == (mobjtype_t)loc1up) diff --git a/src/p_floor.c b/src/p_floor.c index 131cc29d1..4a03f70c0 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1981,11 +1981,8 @@ void T_ThwompSector(levelspecthink_t *thwomp) if (!rover || (rover->flags & FF_EXISTS)) { // scan the thinkers to find players! - for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo = (mobj_t *)th; if (mo->type == MT_PLAYER && mo->health && mo->player && !mo->player->spectator && mo->z <= thwomp->sector->ceilingheight diff --git a/src/p_inter.c b/src/p_inter.c index 6869a29a5..95781e7ad 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -99,9 +99,6 @@ void P_ClearStarPost(INT32 postnum) // scan the thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type != MT_STARPOST) @@ -128,9 +125,6 @@ void P_ResetStarposts(void) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - post = (mobj_t *)th; if (post->type == MT_STARPOST) @@ -809,9 +803,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // scan the thinkers to find the corresponding anchorpoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == MT_IDEYAANCHOR) @@ -903,9 +894,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // scan the remaining thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2 == special) @@ -953,9 +941,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // in from the paraloop. Isn't this just so efficient? for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (P_AproxDistance(P_AproxDistance(mo2->x - x, mo2->y - y), mo2->z - z) > gatherradius) @@ -1327,9 +1312,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // scan the remaining thinkers to find koopa for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == MT_KOOPA) { @@ -1426,9 +1408,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type != MT_STARPOST) @@ -2463,9 +2442,6 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget // this can happen if the boss was hurt earlier than expected for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo = (mobj_t *)th; if (mo->type == (mobjtype_t)target->info->mass && mo->tracer == target) { diff --git a/src/p_mobj.c b/src/p_mobj.c index 0cf309e4e..bd650d60b 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -715,9 +715,6 @@ void P_EmeraldManager(void) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 != (actionf_p1)P_MobjThinker) - continue; // not a mobj thinker - mo = (mobj_t *)think; if (mo->type == MT_EMERALDSPAWN) @@ -3701,9 +3698,6 @@ void P_DestroyRobots(void) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 != (actionf_p1)P_MobjThinker) - continue; // not a mobj thinker - mo = (mobj_t *)think; if (mo->health <= 0 || !(mo->flags & (MF_ENEMY|MF_BOSS))) continue; // not a valid enemy @@ -4485,9 +4479,6 @@ static void P_Boss3Thinker(mobj_t *mobj) // this can happen if the boss was hurt earlier than expected for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == (mobjtype_t)mobj->info->mass && mo2->tracer == mobj) { @@ -4576,9 +4567,6 @@ static void P_Boss3Thinker(mobj_t *mobj) // the number for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && mo2->spawnpoint->angle == mobj->threshold) { @@ -5197,9 +5185,6 @@ static void P_Boss7Thinker(mobj_t *mobj) // Find waypoint he is closest to for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint) { @@ -5252,9 +5237,6 @@ static void P_Boss7Thinker(mobj_t *mobj) // the waypoint to use for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && (mo2->spawnpoint->options & 7) == waypointNum) { @@ -5384,9 +5366,6 @@ static void P_Boss9Thinker(mobj_t *mobj) // Build a hoop linked list of 'em! for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == MT_BOSS9GATHERPOINT) { @@ -5850,9 +5829,6 @@ mobj_t *P_GetClosestAxis(mobj_t *source) // scan the thinkers to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == MT_AXIS) @@ -11087,9 +11063,6 @@ ML_EFFECT4 : Don't clip inside the ground // See if other starposts exist in this level that have the same value. for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2 == mobj) diff --git a/src/p_polyobj.c b/src/p_polyobj.c index fc760372a..09d449b39 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1510,29 +1510,26 @@ void Polyobj_InitLevel(void) // the mobj_t pointers on a queue for use below. for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_MobjThinker) + mobj_t *mo = (mobj_t *)th; + + if (mo->info->doomednum == POLYOBJ_SPAWN_DOOMEDNUM || + mo->info->doomednum == POLYOBJ_SPAWNCRUSH_DOOMEDNUM) { - mobj_t *mo = (mobj_t *)th; + ++numPolyObjects; - if (mo->info->doomednum == POLYOBJ_SPAWN_DOOMEDNUM || - mo->info->doomednum == POLYOBJ_SPAWNCRUSH_DOOMEDNUM) - { - ++numPolyObjects; + qitem = malloc(sizeof(mobjqitem_t)); + memset(qitem, 0, sizeof(mobjqitem_t)); + qitem->mo = mo; + M_QueueInsert(&(qitem->mqitem), &spawnqueue); + } + else if (mo->info->doomednum == POLYOBJ_ANCHOR_DOOMEDNUM) + { + ++numAnchors; - qitem = malloc(sizeof(mobjqitem_t)); - memset(qitem, 0, sizeof(mobjqitem_t)); - qitem->mo = mo; - M_QueueInsert(&(qitem->mqitem), &spawnqueue); - } - else if (mo->info->doomednum == POLYOBJ_ANCHOR_DOOMEDNUM) - { - ++numAnchors; - - qitem = malloc(sizeof(mobjqitem_t)); - memset(qitem, 0, sizeof(mobjqitem_t)); - qitem->mo = mo; - M_QueueInsert(&(qitem->mqitem), &anchorqueue); - } + qitem = malloc(sizeof(mobjqitem_t)); + memset(qitem, 0, sizeof(mobjqitem_t)); + qitem->mo = mo; + M_QueueInsert(&(qitem->mqitem), &anchorqueue); } } @@ -1818,9 +1815,6 @@ void T_PolyObjWaypoint(polywaypoint_t *th) // We redo this each tic to make savegame compatibility easier. for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { - if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - mo2 = (mobj_t *)wp; if (mo2->type != MT_TUBEWAYPOINT) @@ -1899,9 +1893,6 @@ void T_PolyObjWaypoint(polywaypoint_t *th) // Find next waypoint for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { - if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - mo2 = (mobj_t *)wp; if (mo2->type != MT_TUBEWAYPOINT) @@ -1938,9 +1929,6 @@ void T_PolyObjWaypoint(polywaypoint_t *th) for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { - if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - mo2 = (mobj_t *)wp; if (mo2->type != MT_TUBEWAYPOINT) @@ -1975,9 +1963,6 @@ void T_PolyObjWaypoint(polywaypoint_t *th) for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { - if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - mo2 = (mobj_t *)wp; if (mo2->type != MT_TUBEWAYPOINT) @@ -2526,9 +2511,6 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) // Find the first waypoint we need to use for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { - if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - mo2 = (mobj_t *)wp; if (mo2->type != MT_TUBEWAYPOINT) @@ -2597,9 +2579,6 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) target = first; /*for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { - if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - mo2 = (mobj_t *)wp; if (mo2->type != MT_TUBEWAYPOINT) diff --git a/src/p_saveg.c b/src/p_saveg.c index 64da1d3cb..664aa2f64 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2424,9 +2424,6 @@ mobj_t *P_FindNewPosition(UINT32 oldposition) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mobj = (mobj_t *)th; if (mobj->mobjnum == oldposition) return mobj; @@ -3722,11 +3719,8 @@ static inline void P_FinishMobjs(void) for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ]; currentthinker = currentthinker->next) { - if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) - { - mobj = (mobj_t *)currentthinker; - mobj->info = &mobjinfo[mobj->type]; - } + mobj = (mobj_t *)currentthinker; + mobj->info = &mobjinfo[mobj->type]; } } @@ -3740,83 +3734,80 @@ static void P_RelinkPointers(void) for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ]; currentthinker = currentthinker->next) { - if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) + mobj = (mobj_t *)currentthinker; + + if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER) + continue; + + if (mobj->tracer) { - mobj = (mobj_t *)currentthinker; - - if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER) - continue; - - if (mobj->tracer) - { - temp = (UINT32)(size_t)mobj->tracer; - mobj->tracer = NULL; - if (!P_SetTarget(&mobj->tracer, P_FindNewPosition(temp))) - CONS_Debug(DBG_GAMELOGIC, "tracer not found on %d\n", mobj->type); - } - if (mobj->target) - { - temp = (UINT32)(size_t)mobj->target; - mobj->target = NULL; - if (!P_SetTarget(&mobj->target, P_FindNewPosition(temp))) - CONS_Debug(DBG_GAMELOGIC, "target not found on %d\n", mobj->type); - } - if (mobj->hnext) - { - temp = (UINT32)(size_t)mobj->hnext; - mobj->hnext = NULL; - if (!(mobj->hnext = P_FindNewPosition(temp))) - CONS_Debug(DBG_GAMELOGIC, "hnext not found on %d\n", mobj->type); - } - if (mobj->hprev) - { - temp = (UINT32)(size_t)mobj->hprev; - mobj->hprev = NULL; - if (!(mobj->hprev = P_FindNewPosition(temp))) - CONS_Debug(DBG_GAMELOGIC, "hprev not found on %d\n", mobj->type); - } - if (mobj->player && mobj->player->capsule) - { - temp = (UINT32)(size_t)mobj->player->capsule; - mobj->player->capsule = NULL; - if (!P_SetTarget(&mobj->player->capsule, P_FindNewPosition(temp))) - CONS_Debug(DBG_GAMELOGIC, "capsule not found on %d\n", mobj->type); - } - if (mobj->player && mobj->player->axis1) - { - temp = (UINT32)(size_t)mobj->player->axis1; - mobj->player->axis1 = NULL; - if (!P_SetTarget(&mobj->player->axis1, P_FindNewPosition(temp))) - CONS_Debug(DBG_GAMELOGIC, "axis1 not found on %d\n", mobj->type); - } - if (mobj->player && mobj->player->axis2) - { - temp = (UINT32)(size_t)mobj->player->axis2; - mobj->player->axis2 = NULL; - if (!P_SetTarget(&mobj->player->axis2, P_FindNewPosition(temp))) - CONS_Debug(DBG_GAMELOGIC, "axis2 not found on %d\n", mobj->type); - } - if (mobj->player && mobj->player->awayviewmobj) - { - temp = (UINT32)(size_t)mobj->player->awayviewmobj; - mobj->player->awayviewmobj = NULL; - if (!P_SetTarget(&mobj->player->awayviewmobj, P_FindNewPosition(temp))) - CONS_Debug(DBG_GAMELOGIC, "awayviewmobj not found on %d\n", mobj->type); - } - if (mobj->player && mobj->player->followmobj) - { - temp = (UINT32)(size_t)mobj->player->followmobj; - mobj->player->followmobj = NULL; - if (!P_SetTarget(&mobj->player->followmobj, P_FindNewPosition(temp))) - CONS_Debug(DBG_GAMELOGIC, "followmobj not found on %d\n", mobj->type); - } - if (mobj->player && mobj->player->drone) - { - temp = (UINT32)(size_t)mobj->player->drone; - mobj->player->drone = NULL; - if (!P_SetTarget(&mobj->player->drone, P_FindNewPosition(temp))) - CONS_Debug(DBG_GAMELOGIC, "drone not found on %d\n", mobj->type); - } + temp = (UINT32)(size_t)mobj->tracer; + mobj->tracer = NULL; + if (!P_SetTarget(&mobj->tracer, P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "tracer not found on %d\n", mobj->type); + } + if (mobj->target) + { + temp = (UINT32)(size_t)mobj->target; + mobj->target = NULL; + if (!P_SetTarget(&mobj->target, P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "target not found on %d\n", mobj->type); + } + if (mobj->hnext) + { + temp = (UINT32)(size_t)mobj->hnext; + mobj->hnext = NULL; + if (!(mobj->hnext = P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "hnext not found on %d\n", mobj->type); + } + if (mobj->hprev) + { + temp = (UINT32)(size_t)mobj->hprev; + mobj->hprev = NULL; + if (!(mobj->hprev = P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "hprev not found on %d\n", mobj->type); + } + if (mobj->player && mobj->player->capsule) + { + temp = (UINT32)(size_t)mobj->player->capsule; + mobj->player->capsule = NULL; + if (!P_SetTarget(&mobj->player->capsule, P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "capsule not found on %d\n", mobj->type); + } + if (mobj->player && mobj->player->axis1) + { + temp = (UINT32)(size_t)mobj->player->axis1; + mobj->player->axis1 = NULL; + if (!P_SetTarget(&mobj->player->axis1, P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "axis1 not found on %d\n", mobj->type); + } + if (mobj->player && mobj->player->axis2) + { + temp = (UINT32)(size_t)mobj->player->axis2; + mobj->player->axis2 = NULL; + if (!P_SetTarget(&mobj->player->axis2, P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "axis2 not found on %d\n", mobj->type); + } + if (mobj->player && mobj->player->awayviewmobj) + { + temp = (UINT32)(size_t)mobj->player->awayviewmobj; + mobj->player->awayviewmobj = NULL; + if (!P_SetTarget(&mobj->player->awayviewmobj, P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "awayviewmobj not found on %d\n", mobj->type); + } + if (mobj->player && mobj->player->followmobj) + { + temp = (UINT32)(size_t)mobj->player->followmobj; + mobj->player->followmobj = NULL; + if (!P_SetTarget(&mobj->player->followmobj, P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "followmobj not found on %d\n", mobj->type); + } + if (mobj->player && mobj->player->drone) + { + temp = (UINT32)(size_t)mobj->player->drone; + mobj->player->drone = NULL; + if (!P_SetTarget(&mobj->player->drone, P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "drone not found on %d\n", mobj->type); } } } @@ -4120,13 +4111,10 @@ void P_SaveNetGame(void) // Assign the mobjnumber for pointer tracking for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_MobjThinker) - { - mobj = (mobj_t *)th; - if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER) - continue; - mobj->mobjnum = i++; - } + mobj = (mobj_t *)th; + if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER) + continue; + mobj->mobjnum = i++; } P_NetArchivePlayers(); diff --git a/src/p_setup.c b/src/p_setup.c index d6e96a3f5..306511f5c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -816,9 +816,6 @@ void P_ReloadRings(void) // scan the thinkers to find rings/spheres/hoops to unset for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo = (mobj_t *)th; if (mo->type == MT_HOOPCENTER) @@ -885,9 +882,6 @@ void P_SwitchSpheresBonusMode(boolean bonustime) // scan the thinkers to find spheres to switch for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo = (mobj_t *)th; if (mo->type != MT_BLUESPHERE && mo->type != MT_NIGHTSCHIP @@ -2300,9 +2294,6 @@ void P_LoadThingsOnly(void) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 != (actionf_p1)P_MobjThinker) - continue; // not a mobj thinker - mo = (mobj_t *)think; if (mo) diff --git a/src/p_spec.c b/src/p_spec.c index 547fc5bc6..bd4155cfe 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3974,9 +3974,6 @@ void P_SetupSignExit(player_t *player) // spin all signposts in the level then. for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 != (actionf_p1)P_MobjThinker) - continue; // not a mobj thinker - thing = (mobj_t *)think; if (thing->type != MT_SIGN) continue; @@ -4006,9 +4003,6 @@ boolean P_IsFlagAtBase(mobjtype_t flag) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 != (actionf_p1)P_MobjThinker) - continue; // not a mobj thinker - mo = (mobj_t *)think; if (mo->type != flag) @@ -4439,9 +4433,6 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers // The chimps are my friends.. heeheeheheehehee..... - LouisJM for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == MT_EGGTRAP) P_KillMobj(mo2, NULL, player->mo, 0); @@ -4745,9 +4736,6 @@ DoneSection2: // to find the first waypoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == MT_TUBEWAYPOINT && mo2->threshold == sequence @@ -4824,9 +4812,6 @@ DoneSection2: // to find the last waypoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == MT_TUBEWAYPOINT && mo2->threshold == sequence) @@ -4976,9 +4961,6 @@ DoneSection2: // to find the first waypoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type != MT_TUBEWAYPOINT) @@ -5014,9 +4996,6 @@ DoneSection2: // Find waypoint before this one (waypointlow) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type != MT_TUBEWAYPOINT) @@ -5041,9 +5020,6 @@ DoneSection2: // Find waypoint after this one (waypointhigh) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type != MT_TUBEWAYPOINT) diff --git a/src/p_tick.c b/src/p_tick.c index ae1174b15..56f91d820 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -141,9 +141,6 @@ void Command_CountMobjs_f(void) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - if (((mobj_t *)th)->type == i) count++; } @@ -161,9 +158,6 @@ void Command_CountMobjs_f(void) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - if (((mobj_t *)th)->type == i) count++; } diff --git a/src/p_user.c b/src/p_user.c index 26d62f62a..02c76b1e8 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -345,9 +345,6 @@ UINT8 P_FindLowestMare(void) // to find the egg capsule with the lowest mare for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == MT_EGGCAPSULE && mo2->health > 0) @@ -394,9 +391,6 @@ boolean P_TransferToNextMare(player_t *player) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == MT_AXIS) @@ -445,9 +439,6 @@ static mobj_t *P_FindAxis(INT32 mare, INT32 axisnum) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; // Axis things are only at beginning of list. @@ -478,9 +469,6 @@ static mobj_t *P_FindAxisTransfer(INT32 mare, INT32 axisnum, mobjtype_t type) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; // Axis things are only at beginning of list. @@ -517,9 +505,6 @@ void P_TransferToAxis(player_t *player, INT32 axisnum) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == MT_AXIS) @@ -617,9 +602,6 @@ static void P_DeNightserizePlayer(player_t *player) // Check to see if the player should be killed. for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (!(mo2->type == MT_NIGHTSDRONE)) continue; @@ -1569,9 +1551,6 @@ void P_SpawnShieldOrb(player_t *player) // blaze through the thinkers to see if an orb already exists! for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - shieldobj = (mobj_t *)th; if (shieldobj->type == orbtype && shieldobj->target == player->mo) @@ -4440,9 +4419,6 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2 == player->mo) @@ -5637,9 +5613,6 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad // Find next waypoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - mo2 = (mobj_t *)th; // Axis things are only at beginning of list. @@ -5673,9 +5646,6 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad { for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - mo2 = (mobj_t *)th; // Axis things are only at beginning of list. @@ -5701,9 +5671,6 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad { for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - mo2 = (mobj_t *)th; // Axis things are only at beginning of list. @@ -6408,9 +6375,6 @@ static void P_NiGHTSMovement(player_t *player) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == MT_AXIS) @@ -7218,9 +7182,6 @@ static void P_MovePlayer(player_t *player) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == MT_EGGCAPSULE @@ -8126,9 +8087,6 @@ static void P_DoZoomTube(player_t *player) // Find next waypoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - mo2 = (mobj_t *)th; if (mo2->type != MT_TUBEWAYPOINT) @@ -8260,9 +8218,6 @@ static void P_DoRopeHang(player_t *player) // Find next waypoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - mo2 = (mobj_t *)th; if (mo2->type != MT_TUBEWAYPOINT) @@ -8285,9 +8240,6 @@ static void P_DoRopeHang(player_t *player) // Wrap around back to first waypoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - mo2 = (mobj_t *)th; if (mo2->type != MT_TUBEWAYPOINT) @@ -8351,9 +8303,6 @@ static void P_NukeAllPlayers(player_t *player) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 != (actionf_p1)P_MobjThinker) - continue; // not a mobj thinker - mo = (mobj_t *)think; if (!mo->player) @@ -8399,9 +8348,6 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 != (actionf_p1)P_MobjThinker) - continue; // not a mobj thinker - mo = (mobj_t *)think; if (!(mo->flags & MF_SHOOTABLE) && !(mo->type == MT_EGGGUARD || mo->type == MT_MINUS)) @@ -8450,9 +8396,6 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 != (actionf_p1)P_MobjThinker) - continue; // not a mobj thinker - mo = (mobj_t *)think; if (!(mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR|MF_SPRING)) == !(mo->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag continue; // not a valid target @@ -8589,9 +8532,6 @@ void P_FindEmerald(void) // to find all emeralds for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (mo2->type == MT_EMERHUNT) { @@ -10015,9 +9955,6 @@ void P_PlayerThink(player_t *player) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; if (!(mo2->type == MT_RING || mo2->type == MT_COIN diff --git a/src/r_data.c b/src/r_data.c index 755cc7bcd..d116cd15d 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -2243,8 +2243,7 @@ void R_PrecacheLevel(void) if (spritepresent == NULL) I_Error("%s: Out of memory looking up sprites", "R_PrecacheLevel"); for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - if (th->function.acp1 == (actionf_p1)P_MobjThinker) - spritepresent[((mobj_t *)th)->sprite] = 1; + spritepresent[((mobj_t *)th)->sprite] = 1; spritememory = 0; for (i = 0; i < numsprites; i++) diff --git a/src/st_stuff.c b/src/st_stuff.c index 007363b03..26af62eae 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2291,8 +2291,6 @@ static void ST_doItemFinderIconsAndSound(void) // Scan thinkers to find emblem mobj with these ids for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; mo2 = (mobj_t *)th; if (mo2->type == MT_EMBLEM) From 62875d6728cdf1fb57cb053f8129fa60da4922c8 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sun, 21 Apr 2019 17:16:35 +0200 Subject: [PATCH 017/128] Send the slope thinkers list after the mobj list Keeping the sector list before the mobj list stops the objects from "entering" or "floating" on slopes. However this induces a new slope adhesion problem in fast-moving slopes, so it is more desirable to leave the "indent/float-on" behavior for now since fixing this one seems like a big can of worms and falls off this branch's scope. Signed-off-by: Nev3r --- src/p_local.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/p_local.h b/src/p_local.h index 70a08c0cb..1d30fd57f 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -65,8 +65,10 @@ typedef enum{ THINK_LIMBO, THINK_POLYOBJ, THINK_MAIN, - THINK_DYNSLOPE, THINK_MOBJ, +#ifdef ESLOPE + THINK_DYNSLOPE, +#endif THINK_PRECIP, NUM_THINKERLISTS } thinklistnum_t; /**< Thinker lists. */ From 5c240eb9db285ada456dd4465c7e04b34dd3e1f6 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Sun, 21 Apr 2019 18:05:16 +0200 Subject: [PATCH 018/128] Add back the `p_slopes.h` header guard Signed-off-by: Nev3r --- src/p_slopes.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/p_slopes.h b/src/p_slopes.h index c5acd4e42..8f9e7d61e 100644 --- a/src/p_slopes.h +++ b/src/p_slopes.h @@ -10,6 +10,9 @@ /// \file p_slopes.c /// \brief ZDoom + Eternity Engine Slopes, ported and enhanced by Kalaron +#ifndef P_SLOPES_H__ +#define P_SLOPES_H__ + #include "m_fixed.h" // Vectors #ifdef ESLOPE @@ -72,3 +75,4 @@ typedef struct void T_DynamicSlopeLine (dynplanethink_t* th); void T_DynamicSlopeVert (dynplanethink_t* th); #endif // #ifdef ESLOPE +#endif // #ifndef P_SLOPES_H__ From 861d0d0b0a59e5a0151e2355fe971437a844e71b Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 18 Jun 2019 13:33:35 +0100 Subject: [PATCH 019/128] Improve rain/weather. * Like Kart, remove cv_precipdensity. * Like Kart, replace "Infinite" draw distance value with "None". * Better thinker with more return optimisation. * Better placement of thinking in rendering, to avoid ceiling-mounted sprite glitches. --- src/hardware/hw_main.c | 29 +++++++++++------------------ src/m_menu.c | 11 +++++------ src/p_mobj.c | 23 ++++++++++++----------- src/r_main.c | 14 ++++++++++---- src/r_main.h | 2 +- src/r_things.c | 32 +++++++++++++------------------- 6 files changed, 52 insertions(+), 59 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index c79452bb5..cb0009da7 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5431,7 +5431,7 @@ static void HWR_AddSprites(sector_t *sec) } #ifdef HWPRECIP - // Someone seriously wants infinite draw distance for precipitation? + // no, no infinite draw distance for precipitation. this option at zero is supposed to turn it off if ((limit_dist = (fixed_t)cv_drawdist_precip.value << FRACBITS)) { for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext) @@ -5447,13 +5447,6 @@ static void HWR_AddSprites(sector_t *sec) HWR_ProjectPrecipitationSprite(precipthing); } } - else - { - // Draw everything in sector, no checks - for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext) - if (!(precipthing->precipflags & PCF_INVISIBLE)) - HWR_ProjectPrecipitationSprite(precipthing); - } #endif } @@ -5774,16 +5767,6 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) x1 = tr_x + x1 * rightcos; x2 = tr_x - x2 * rightcos; - // okay, we can't return now... this is a hack, but weather isn't networked, so it should be ok - if (!(thing->precipflags & PCF_THUNK)) - { - if (thing->precipflags & PCF_RAIN) - P_RainThinker(thing); - else - P_SnowThinker(thing); - thing->precipflags |= PCF_THUNK; - } - // // store information in a vissprite // @@ -5804,6 +5787,16 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) vis->ty = FIXED_TO_FLOAT(thing->z + spritecachedinfo[lumpoff].topoffset); vis->precip = true; + + // okay... this is a hack, but weather isn't networked, so it should be ok + if (!(thing->precipflags & PCF_THUNK)) + { + if (thing->precipflags & PCF_RAIN) + P_RainThinker(thing); + else + P_SnowThinker(thing); + thing->precipflags |= PCF_THUNK; + } } #endif diff --git a/src/m_menu.c b/src/m_menu.c index 4f78d0adc..6fea99046 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1193,13 +1193,12 @@ static menuitem_t OP_VideoOptionsMenu[] = {IT_HEADER, NULL, "Level", NULL, 155}, {IT_STRING | IT_CVAR, NULL, "Draw Distance", &cv_drawdist, 161}, - {IT_STRING | IT_CVAR, NULL, "NiGHTS Draw Dist.", &cv_drawdist_nights, 166}, - {IT_STRING | IT_CVAR, NULL, "Weather Draw Dist.", &cv_drawdist_precip, 171}, - {IT_STRING | IT_CVAR, NULL, "Weather Density", &cv_precipdensity, 176}, + {IT_STRING | IT_CVAR, NULL, "Weather Draw Dist.", &cv_drawdist_precip, 166}, + {IT_STRING | IT_CVAR, NULL, "NiGHTS mode Draw Dist.", &cv_drawdist_nights, 171}, - {IT_HEADER, NULL, "Diagnostic", NULL, 185}, - {IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 191}, - {IT_STRING | IT_CVAR, NULL, "Clear Before Redraw", &cv_homremoval, 196}, + {IT_HEADER, NULL, "Diagnostic", NULL, 180}, + {IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 186}, + {IT_STRING | IT_CVAR, NULL, "Clear Before Redraw", &cv_homremoval, 191}, }; static menuitem_t OP_VideoModeMenu[] = diff --git a/src/p_mobj.c b/src/p_mobj.c index bc43fbe1e..e9c4d12cf 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -4101,17 +4101,18 @@ void P_RainThinker(precipmobj_t *mobj) } // adjust height - if ((mobj->z += mobj->momz) <= mobj->floorz) + if ((mobj->z += mobj->momz) > mobj->floorz) + return; + + // no splashes on sky or bottomless pits + if (mobj->precipflags & PCF_PIT) { - // no splashes on sky or bottomless pits - if (mobj->precipflags & PCF_PIT) - mobj->z = mobj->ceilingz; - else - { - mobj->z = mobj->floorz; - P_SetPrecipMobjState(mobj, S_SPLASH1); - } + mobj->z = mobj->ceilingz; + return; } + + mobj->z = mobj->floorz; + P_SetPrecipMobjState(mobj, S_SPLASH1); } static void P_RingThinker(mobj_t *mobj) @@ -9431,7 +9432,7 @@ void P_SpawnPrecipitation(void) subsector_t *precipsector = NULL; precipmobj_t *rainmo = NULL; - if (dedicated || !cv_precipdensity.value || curWeather == PRECIP_NONE) + if (dedicated || /*!cv_precipdensity*/!cv_drawdist_precip.value || curWeather == PRECIP_NONE) return; // Use the blockmap to narrow down our placing patterns @@ -9440,7 +9441,7 @@ void P_SpawnPrecipitation(void) basex = bmaporgx + (i % bmapwidth) * MAPBLOCKSIZE; basey = bmaporgy + (i / bmapwidth) * MAPBLOCKSIZE; - for (j = 0; j < cv_precipdensity.value; ++j) + //for (j = 0; j < cv_precipdensity.value; ++j) -- density is 1 for us always { x = basex + ((M_RandomKey(MAPBLOCKUNITS<<3)<>3); y = basey + ((M_RandomKey(MAPBLOCKUNITS<<3)<>3); diff --git a/src/r_main.c b/src/r_main.c index 273d13a56..db351e991 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -98,7 +98,14 @@ static CV_PossibleValue_t drawdist_cons_t[] = { {1024, "1024"}, {1536, "1536"}, {2048, "2048"}, {3072, "3072"}, {4096, "4096"}, {6144, "6144"}, {8192, "8192"}, {0, "Infinite"}, {0, NULL}}; -static CV_PossibleValue_t precipdensity_cons_t[] = {{0, "None"}, {1, "Light"}, {2, "Moderate"}, {4, "Heavy"}, {6, "Thick"}, {8, "V.Thick"}, {0, NULL}}; + +//static CV_PossibleValue_t precipdensity_cons_t[] = {{0, "None"}, {1, "Light"}, {2, "Moderate"}, {4, "Heavy"}, {6, "Thick"}, {8, "V.Thick"}, {0, NULL}}; + +static CV_PossibleValue_t drawdist_precip_cons_t[] = { + {256, "256"}, {512, "512"}, {768, "768"}, + {1024, "1024"}, {1536, "1536"}, {2048, "2048"}, + {0, "None"}, {0, NULL}}; + static CV_PossibleValue_t translucenthud_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}}; static CV_PossibleValue_t maxportals_cons_t[] = {{0, "MIN"}, {12, "MAX"}, {0, NULL}}; // lmao rendering 32 portals, you're a card static CV_PossibleValue_t homremoval_cons_t[] = {{0, "No"}, {1, "Yes"}, {2, "Flash"}, {0, NULL}}; @@ -126,8 +133,8 @@ consvar_t cv_translucenthud = {"translucenthud", "10", CV_SAVE, translucenthud_c consvar_t cv_translucency = {"translucency", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_drawdist = {"drawdist", "Infinite", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_drawdist_nights = {"drawdist_nights", "2048", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_drawdist_precip = {"drawdist_precip", "1024", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_precipdensity = {"precipdensity", "Moderate", CV_SAVE, precipdensity_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_drawdist_precip = {"drawdist_precip", "1024", CV_SAVE, drawdist_precip_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +//consvar_t cv_precipdensity = {"precipdensity", "Moderate", CV_SAVE, precipdensity_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; // Okay, whoever said homremoval causes a performance hit should be shot. consvar_t cv_homremoval = {"homremoval", "No", CV_SAVE, homremoval_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; @@ -1158,7 +1165,6 @@ void R_RegisterEngineStuff(void) if (dedicated) return; - CV_RegisterVar(&cv_precipdensity); CV_RegisterVar(&cv_translucency); CV_RegisterVar(&cv_drawdist); CV_RegisterVar(&cv_drawdist_nights); diff --git a/src/r_main.h b/src/r_main.h index 1d82a01b9..2c9b5cc3d 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -78,7 +78,7 @@ extern consvar_t cv_chasecam, cv_chasecam2; extern consvar_t cv_flipcam, cv_flipcam2; extern consvar_t cv_shadow, cv_shadowoffs; extern consvar_t cv_translucency; -extern consvar_t cv_precipdensity, cv_drawdist, cv_drawdist_nights, cv_drawdist_precip; +extern consvar_t cv_drawdist, cv_drawdist_nights, cv_drawdist_precip; extern consvar_t cv_skybox; extern consvar_t cv_tailspickup; diff --git a/src/r_things.c b/src/r_things.c index f5482683f..50ee8e6ef 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1527,16 +1527,6 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) return; } - // okay, we can't return now except for vertical clipping... this is a hack, but weather isn't networked, so it should be ok - if (!(thing->precipflags & PCF_THUNK)) - { - if (thing->precipflags & PCF_RAIN) - P_RainThinker(thing); - else - P_SnowThinker(thing); - thing->precipflags |= PCF_THUNK; - } - //SoM: 3/17/2000: Disregard sprites that are out of view.. gzt = thing->z + spritecachedinfo[lump].topoffset; @@ -1545,7 +1535,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) if (thing->subsector->sector->cullheight) { if (R_DoCulling(thing->subsector->sector->cullheight, viewsector->cullheight, viewz, gz, gzt)) - return; + goto weatherthink; } // store information in a vissprite @@ -1605,6 +1595,17 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) // Fullbright vis->colormap = colormaps; + +weatherthink: + // okay... this is a hack, but weather isn't networked, so it should be ok + if (!(thing->precipflags & PCF_THUNK)) + { + if (thing->precipflags & PCF_RAIN) + P_RainThinker(thing); + else + P_SnowThinker(thing); + thing->precipflags |= PCF_THUNK; + } } // R_AddSprites @@ -1669,7 +1670,7 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel) R_ProjectSprite(thing); } - // Someone seriously wants infinite draw distance for precipitation? + // no, no infinite draw distance for precipitation. this option at zero is supposed to turn it off if ((limit_dist = (fixed_t)cv_drawdist_precip.value << FRACBITS)) { for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext) @@ -1685,13 +1686,6 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel) R_ProjectPrecipitationSprite(precipthing); } } - else - { - // Draw everything in sector, no checks - for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext) - if (!(precipthing->precipflags & PCF_INVISIBLE)) - R_ProjectPrecipitationSprite(precipthing); - } } // From 96d6cea569c646d48039d693a745ab4a80a31d07 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 18 Jun 2019 14:36:06 +0100 Subject: [PATCH 020/128] Support backspace for resetting various menu values, just like Kart. --- src/m_menu.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 6fea99046..f5b82d297 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2668,20 +2668,35 @@ static void M_ChangeCvar(INT32 choice) { consvar_t *cv = (consvar_t *)currentMenu->menuitems[itemOn].itemaction; + if (choice == -1) + { + if (cv == &cv_playercolor) + { + SINT8 skinno = R_SkinAvailable(cv_chooseskin.string); + if (skinno != -1) + CV_SetValue(cv,skins[skinno].prefcolor); + return; + } + CV_Set(cv,cv->defaultvalue); + return; + } + + choice = (choice<<1) - 1; + if (((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_SLIDER) ||((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_INVISSLIDER) ||((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_NOMOD)) { - CV_SetValue(cv,cv->value+(choice*2-1)); + CV_SetValue(cv,cv->value+(choice)); } else if (cv->flags & CV_FLOAT) { char s[20]; - sprintf(s,"%f",FIXED_TO_FLOAT(cv->value)+(choice*2-1)*(1.0f/16.0f)); + sprintf(s,"%f",FIXED_TO_FLOAT(cv->value)+(choice)*(1.0f/16.0f)); CV_Set(cv,s); } else - CV_AddValue(cv,choice*2-1); + CV_AddValue(cv,choice); } static boolean M_ChangeStringCvar(INT32 choice) @@ -3117,6 +3132,23 @@ boolean M_Responder(event_t *ev) S_StartSound(NULL, sfx_shldls); return true; } + + if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS + || (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR)) + { + consvar_t *cv = (consvar_t *)currentMenu->menuitems[itemOn].itemaction; + + if (cv == &cv_chooseskin + || cv == &cv_nextmap + || cv == &cv_newgametype) + return true; + + if (currentMenu != &OP_SoundOptionsDef || itemOn > 3) + S_StartSound(NULL, sfx_menu1); + routine(-1); + return true; + } + // Why _does_ backspace go back anyway? //currentMenu->lastOn = itemOn; //if (currentMenu->prevMenu) @@ -9557,6 +9589,16 @@ static void M_HandleSetupMultiPlayer(INT32 choice) S_StartSound(NULL,sfx_menu1); // Tails setupm_name[l-1] = 0; } + else if (itemOn == 2) + { + UINT8 col = skins[setupm_fakeskin].prefcolor; + if (setupm_fakecolor != col) + { + S_StartSound(NULL,sfx_menu1); // Tails + setupm_fakecolor = col; + } + } + break; break; case KEY_DEL: From 1d65caa250a0231bee8efffe9f6e354f9191b5d6 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 18 Jun 2019 17:55:57 +0100 Subject: [PATCH 021/128] With permission from Kart Krew (Sal and Sryder specifically - they don't know WHY vanilla's using it): * Port across the additional colour translation maps, including mobj-level support for "colorized" objects. * Make Fangboss and both Metal Sonic objects greyscale if, on spawn, there is a player in the game who is not a spectator whose skin is that character. * Allow bosses with MF_GRENADEBOUNCE to opt out of the MF2_FRET colour-flashing tomfoolery, and give this flag to Fang. --- src/dehacked.c | 9 +++ src/hardware/hw_main.c | 6 +- src/hardware/hw_md2.c | 166 ++++++++++++++++++++++++++++++++--------- src/info.c | 2 +- src/lua_hudlib.c | 4 +- src/lua_mobjlib.c | 14 +++- src/p_mobj.c | 27 ++++++- src/p_mobj.h | 2 + src/p_saveg.c | 14 ++-- src/r_draw.c | 87 +++++++++++++++++++-- src/r_draw.h | 2 + src/r_things.c | 10 ++- 12 files changed, 286 insertions(+), 57 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 6d1f58990..b8417ea59 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -28,6 +28,7 @@ #include "p_local.h" // for var1 and var2, and some constants #include "p_setup.h" #include "r_data.h" +#include "r_draw.h" #include "r_sky.h" #include "fastcmp.h" #include "lua_script.h" @@ -8728,6 +8729,14 @@ struct { {"KR_TIMEOUT",KR_TIMEOUT}, {"KR_BAN",KR_BAN}, {"KR_LEAVE",KR_LEAVE}, + + // translation colormaps + {"TC_DEFAULT",TC_DEFAULT}, + {"TC_BOSS",TC_BOSS}, + {"TC_METALSONIC",TC_METALSONIC}, + {"TC_ALLWHITE",TC_ALLWHITE}, + {"TC_RAINBOW",TC_RAINBOW}, + {"TC_BLINK",TC_BLINK}, #endif {NULL,0} diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index cb0009da7..a76c9e1c8 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5660,7 +5660,7 @@ static void HWR_ProjectSprite(mobj_t *thing) vis->z2 = z2; //Hurdler: 25/04/2000: now support colormap in hardware mode - if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash" + if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash" { if (vis->mobj->type == MT_CYBRAKDEMON) vis->colormap = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE); @@ -5672,7 +5672,9 @@ static void HWR_ProjectSprite(mobj_t *thing) else if (thing->color) { // New colormap stuff for skins Tails 06-07-2002 - if (thing->skin && thing->sprite == SPR_PLAY) // This thing is a player! + if (thing->colorized) + vis->colormap = R_GetTranslationColormap(TC_RAINBOW, thing->color, GTC_CACHE); + else if (thing->skin && thing->sprite == SPR_PLAY) // This thing is a player! { size_t skinnum = (skin_t*)thing->skin-skins; vis->colormap = R_GetTranslationColormap((INT32)skinnum, thing->color, GTC_CACHE); diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index d69233a9b..6db5d5f08 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -40,6 +40,8 @@ #include "../w_wad.h" #include "../z_zone.h" #include "../r_things.h" +#include "../r_draw.h" +#include "../p_tick.h" #include "hw_main.h" #include "../v_video.h" @@ -978,8 +980,18 @@ spritemd2found: fclose(f); } -static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, GLMipmap_t *grmip, skincolors_t color) +// Define for getting accurate color brightness readings according to how the human eye sees them. +// https://en.wikipedia.org/wiki/Relative_luminance +// 0.2126 to red +// 0.7152 to green +// 0.0722 to blue +// (See this same define in k_kart.c!) +#define SETBRIGHTNESS(brightness,r,g,b) \ + brightness = (UINT8)(((1063*((UINT16)r)/5000) + (3576*((UINT16)g)/5000) + (361*((UINT16)b)/5000)) / 3) + +static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, GLMipmap_t *grmip, INT32 skinnum, skincolors_t color) { + UINT8 i; UINT16 w = gpatch->width, h = gpatch->height; UINT32 size = w*h; RGBA_t *image, *blendimage, *cur, blendcolor; @@ -1005,50 +1017,112 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, image = gpatch->mipmap.grInfo.data; blendimage = blendgpatch->mipmap.grInfo.data; + // Average all of the translation's colors if (color == SKINCOLOR_NONE || color >= MAXTRANSLATIONS) blendcolor = V_GetColor(0xff); else - blendcolor = V_GetColor(Color_Index[color-1][4]); - - while (size--) { - if (blendimage->s.alpha == 0) - { - // Don't bother with blending the pixel if the alpha of the blend pixel is 0 - cur->rgba = image->rgba; - } - else - { - INT32 tempcolor; - INT16 tempmult, tempalpha; - tempalpha = -(abs(blendimage->s.red-127)-127)*2; - if (tempalpha > 255) - tempalpha = 255; - else if (tempalpha < 0) - tempalpha = 0; + const UINT8 div = 6; + const UINT8 start = 4; + UINT32 r, g, b; - tempmult = (blendimage->s.red-127)*2; - if (tempmult > 255) - tempmult = 255; - else if (tempmult < 0) - tempmult = 0; + blendcolor = V_GetColor(Color_Index[color-1][start]); + r = (UINT32)(blendcolor.s.red*blendcolor.s.red); + g = (UINT32)(blendcolor.s.green*blendcolor.s.green); + b = (UINT32)(blendcolor.s.blue*blendcolor.s.blue); - tempcolor = (image->s.red*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.red)/255)) * blendimage->s.alpha)/255; - cur->s.red = (UINT8)tempcolor; - tempcolor = (image->s.green*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.green)/255)) * blendimage->s.alpha)/255; - cur->s.green = (UINT8)tempcolor; - tempcolor = (image->s.blue*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.blue)/255)) * blendimage->s.alpha)/255; - cur->s.blue = (UINT8)tempcolor; - cur->s.alpha = image->s.alpha; + for (i = 1; i < div; i++) + { + RGBA_t nextcolor = V_GetColor(Color_Index[color-1][start+i]); + r += (UINT32)(nextcolor.s.red*nextcolor.s.red); + g += (UINT32)(nextcolor.s.green*nextcolor.s.green); + b += (UINT32)(nextcolor.s.blue*nextcolor.s.blue); } - cur++; image++; blendimage++; + blendcolor.s.red = (UINT8)(FixedSqrt((r/div)<>FRACBITS); + blendcolor.s.green = (UINT8)(FixedSqrt((g/div)<>FRACBITS); + blendcolor.s.blue = (UINT8)(FixedSqrt((b/div)<>FRACBITS); + } + + // rainbow support, could theoretically support boss ones too + if (skinnum == TC_RAINBOW) + { + while (size--) + { + if (image->s.alpha == 0 && blendimage->s.alpha == 0) + { + // Don't bother with blending the pixel if the alpha of the blend pixel is 0 + cur->rgba = image->rgba; + } + else + { + UINT32 tempcolor; + UINT16 imagebright, blendbright, finalbright, colorbright; + SETBRIGHTNESS(imagebright,image->s.red,image->s.green,image->s.blue); + SETBRIGHTNESS(blendbright,blendimage->s.red,blendimage->s.green,blendimage->s.blue); + // slightly dumb average between the blend image color and base image colour, usually one or the other will be fully opaque anyway + finalbright = (imagebright*(255-blendimage->s.alpha))/255 + (blendbright*blendimage->s.alpha)/255; + SETBRIGHTNESS(colorbright,blendcolor.s.red,blendcolor.s.green,blendcolor.s.blue); + + tempcolor = (finalbright*blendcolor.s.red)/colorbright; + tempcolor = min(255, tempcolor); + cur->s.red = (UINT8)tempcolor; + tempcolor = (finalbright*blendcolor.s.green)/colorbright; + tempcolor = min(255, tempcolor); + cur->s.green = (UINT8)tempcolor; + tempcolor = (finalbright*blendcolor.s.blue)/colorbright; + tempcolor = min(255, tempcolor); + cur->s.blue = (UINT8)tempcolor; + cur->s.alpha = image->s.alpha; + } + + cur++; image++; blendimage++; + } + } + else + { + while (size--) + { + if (blendimage->s.alpha == 0) + { + // Don't bother with blending the pixel if the alpha of the blend pixel is 0 + cur->rgba = image->rgba; + } + else + { + INT32 tempcolor; + INT16 tempmult, tempalpha; + tempalpha = -(abs(blendimage->s.red-127)-127)*2; + if (tempalpha > 255) + tempalpha = 255; + else if (tempalpha < 0) + tempalpha = 0; + + tempmult = (blendimage->s.red-127)*2; + if (tempmult > 255) + tempmult = 255; + else if (tempmult < 0) + tempmult = 0; + + tempcolor = (image->s.red*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.red)/255)) * blendimage->s.alpha)/255; + cur->s.red = (UINT8)tempcolor; + tempcolor = (image->s.green*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.green)/255)) * blendimage->s.alpha)/255; + cur->s.green = (UINT8)tempcolor; + tempcolor = (image->s.blue*(255-blendimage->s.alpha))/255 + ((tempmult + ((tempalpha*blendcolor.s.blue)/255)) * blendimage->s.alpha)/255; + cur->s.blue = (UINT8)tempcolor; + cur->s.alpha = image->s.alpha; + } + + cur++; image++; blendimage++; + } } return; } -static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, const UINT8 *colormap, skincolors_t color) +#undef SETBRIGHTNESS + +static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT32 skinnum, const UINT8 *colormap, skincolors_t color) { // mostly copied from HWR_GetMappedPatch, hence the similarities and comment GLMipmap_t *grmip, *newmip; @@ -1089,13 +1163,14 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, con grmip->nextcolormap = newmip; newmip->colormap = colormap; - HWR_CreateBlendedTexture(gpatch, blendgpatch, newmip, color); + HWR_CreateBlendedTexture(gpatch, blendgpatch, newmip, skinnum, color); HWD.pfnSetTexture(newmip); Z_ChangeTag(newmip->grInfo.data, PU_HWRCACHE_UNLOCKED); } + // -----------------+ // HWR_DrawMD2 : Draw MD2 // : (monsters, bonuses, weapons, lights, ...) @@ -1285,7 +1360,30 @@ void HWR_DrawMD2(gr_vissprite_t *spr) md2->blendgrpatch && ((GLPatch_t *)md2->blendgrpatch)->mipmap.grInfo.format && gpatch->width == ((GLPatch_t *)md2->blendgrpatch)->width && gpatch->height == ((GLPatch_t *)md2->blendgrpatch)->height) { - HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, spr->colormap, (skincolors_t)spr->mobj->color); + INT32 skinnum = TC_DEFAULT; + if ((spr->mobj->flags & (MF_ENEMY|MF_BOSS)) && (spr->mobj->flags2 & MF2_FRET) && !(spr->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash" + { + if (spr->mobj->type == MT_CYBRAKDEMON) + skinnum = TC_ALLWHITE; + else if (spr->mobj->type == MT_METALSONIC_BATTLE) + skinnum = TC_METALSONIC; + else + skinnum = TC_BOSS; + } + else if (spr->mobj->color) + { + if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) + { + if (spr->mobj->colorized) + skinnum = TC_RAINBOW; + else + { + skinnum = (INT32)((skin_t*)spr->mobj->skin-skins); + } + } + else skinnum = TC_DEFAULT; + } + HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, skinnum, spr->colormap, (skincolors_t)spr->mobj->color); } else { diff --git a/src/info.c b/src/info.c index e03b63a65..f1d570fa0 100644 --- a/src/info.c +++ b/src/info.c @@ -5397,7 +5397,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // mass 3, // damage sfx_boingf, // activesound - MF_SPECIAL|MF_BOSS|MF_SHOOTABLE, // flags + MF_SPECIAL|MF_BOSS|MF_SHOOTABLE|MF_GRENADEBOUNCE, // flags S_NULL // raisestate }, diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index f3a1ba210..8c1134bca 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -670,8 +670,8 @@ static int libd_getColormap(lua_State *L) else if (lua_type(L, 1) == LUA_TNUMBER) // skin number { skinnum = (INT32)luaL_checkinteger(L, 1); - if (skinnum < TC_ALLWHITE || skinnum >= MAXSKINS) - return luaL_error(L, "skin number %d is out of range (%d - %d)", skinnum, TC_ALLWHITE, MAXSKINS-1); + if (skinnum < TC_BLINK || skinnum >= MAXSKINS) + return luaL_error(L, "skin number %d is out of range (%d - %d)", skinnum, TC_BLINK, MAXSKINS-1); } else // skin name { diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 0835e5cc0..0a3d356c9 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -83,12 +83,11 @@ enum mobj_e { mobj_extravalue1, mobj_extravalue2, mobj_cusval, -#ifdef ESLOPE mobj_cvmem, - mobj_standingslope -#else - mobj_cvmem +#ifdef ESLOPE + mobj_standingslope, #endif + mobj_colorized }; static const char *const mobj_opt[] = { @@ -154,6 +153,7 @@ static const char *const mobj_opt[] = { #ifdef ESLOPE "standingslope", #endif + "colorized", NULL}; #define UNIMPLEMENTED luaL_error(L, LUA_QL("mobj_t") " field " LUA_QS " is not implemented for Lua and cannot be accessed.", mobj_opt[field]) @@ -371,6 +371,9 @@ static int mobj_get(lua_State *L) LUA_PushUserdata(L, mo->standingslope, META_SLOPE); break; #endif + case mobj_colorized: + lua_pushboolean(L, mo->colorized); + break; default: // extra custom variables in Lua memory lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); @@ -692,6 +695,9 @@ static int mobj_set(lua_State *L) case mobj_standingslope: return NOSET; #endif + case mobj_colorized: + mo->colorized = luaL_checkboolean(L, 3); + break; default: lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS); I_Assert(lua_istable(L, -1)); diff --git a/src/p_mobj.c b/src/p_mobj.c index e9c4d12cf..fd679857e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8894,6 +8894,7 @@ void P_SceneryThinker(mobj_t *mobj) mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) { const mobjinfo_t *info = &mobjinfo[type]; + UINT8 sc = -1; state_t *st; mobj_t *mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); @@ -9150,6 +9151,13 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) if (nummaprings >= 0) nummaprings++; break; + case MT_METALSONIC_BATTLE: + case MT_METALSONIC_RACE: + sc = 3; + break; + case MT_FANG: + sc = 4; + break; case MT_FBOMB: mobj->flags2 |= MF2_EXPLOSION; break; @@ -9157,6 +9165,23 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) break; } + if (sc != -1) + { + UINT8 i; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + continue; + + if (players[i].skin == sc) + { + mobj->color = SKINCOLOR_SILVER; + mobj->colorized = true; + break; + } + } + } + if (!(mobj->flags & MF_NOTHINK)) P_AddThinker(&mobj->thinker); @@ -9427,7 +9452,7 @@ consvar_t cv_flagtime = {"flagtime", "30", CV_NETVAR|CV_CHEAT, flagtime_cons_t, void P_SpawnPrecipitation(void) { - INT32 i, j, mrand; + INT32 i, /*j,*/ mrand; fixed_t basex, basey, x, y, height; subsector_t *precipsector = NULL; precipmobj_t *rainmo = NULL; diff --git a/src/p_mobj.h b/src/p_mobj.h index 936be3bb0..bfcb09210 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -371,6 +371,8 @@ typedef struct mobj_s struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?) #endif + boolean colorized; // Whether the mobj uses the rainbow colormap + // WARNING: New fields must be added separately to savegame and Lua. } mobj_t; diff --git a/src/p_saveg.c b/src/p_saveg.c index 0d58387b9..d587cba17 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1262,12 +1262,11 @@ typedef enum MD2_HNEXT = 1<<7, MD2_HPREV = 1<<8, MD2_FLOORROVER = 1<<9, -#ifdef ESLOPE MD2_CEILINGROVER = 1<<10, - MD2_SLOPE = 1<<11 -#else - MD2_CEILINGROVER = 1<<10 +#ifdef ESLOPE + MD2_SLOPE = 1<<11, #endif + MD2_COLORIZED = 1<<12, } mobj_diff2_t; typedef enum @@ -1473,6 +1472,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) if (mobj->standingslope) diff2 |= MD2_SLOPE; #endif + if (mobj->colorized) + diff2 |= MD2_COLORIZED; if (diff2 != 0) diff |= MD_MORE; @@ -1635,6 +1636,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) if (diff2 & MD2_SLOPE) WRITEUINT16(save_p, mobj->standingslope->id); #endif + if (diff2 & MD2_COLORIZED) + WRITEUINT8(save_p, mobj->colorized); WRITEUINT32(save_p, mobj->mobjnum); } @@ -2660,7 +2663,8 @@ static void LoadMobjThinker(actionf_p1 thinker) if (diff2 & MD2_SLOPE) mobj->standingslope = P_SlopeById(READUINT16(save_p)); #endif - + if (diff2 & MD2_COLORIZED) + mobj->colorized = READUINT8(save_p); if (diff & MD_REDFLAG) { diff --git a/src/r_draw.c b/src/r_draw.c index 13ac691d5..77bb1b6e7 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -126,10 +126,12 @@ UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask; #define BOSS_TT_CACHE_INDEX (MAXSKINS + 1) #define METALSONIC_TT_CACHE_INDEX (MAXSKINS + 2) #define ALLWHITE_TT_CACHE_INDEX (MAXSKINS + 3) +#define RAINBOW_TT_CACHE_INDEX (MAXSKINS + 4) +#define BLINK_TT_CACHE_INDEX (MAXSKINS + 5) #define DEFAULT_STARTTRANSCOLOR 96 #define NUM_PALETTE_ENTRIES 256 -static UINT8** translationtablecache[MAXSKINS + 4] = {NULL}; +static UINT8** translationtablecache[MAXSKINS + 6] = {NULL}; const UINT8 Color_Index[MAXTRANSLATIONS-1][16] = { // {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, // SKINCOLOR_NONE @@ -457,17 +459,85 @@ void R_InitTranslationTables(void) \return void */ + +// Define for getting accurate color brightness readings according to how the human eye sees them. +// https://en.wikipedia.org/wiki/Relative_luminance +// 0.2126 to red +// 0.7152 to green +// 0.0722 to blue +// (See this same define in hw_md2.c!) +#define SETBRIGHTNESS(brightness,r,g,b) \ + brightness = (UINT8)(((1063*((UINT16)r)/5000) + (3576*((UINT16)g)/5000) + (361*((UINT16)b)/5000)) / 3) + +/** \brief Generates the rainbow colourmaps that are used when a player has the invincibility power... stolen from kart, with permission + + \param dest_colormap colormap to populate + \param skincolor translation color +*/ +static void R_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor) +{ + INT32 i; + RGBA_t color; + UINT8 brightness; + INT32 j; + UINT8 colorbrightnesses[16]; + UINT16 brightdif; + INT32 temp; + + // first generate the brightness of all the colours of that skincolour + for (i = 0; i < 16; i++) + { + color = V_GetColor(Color_Index[skincolor-1][i]); + SETBRIGHTNESS(colorbrightnesses[i], color.s.red, color.s.green, color.s.blue); + } + + // next, for every colour in the palette, choose the transcolor that has the closest brightness + for (i = 0; i < NUM_PALETTE_ENTRIES; i++) + { + if (i == 0 || i == 31) // pure black and pure white don't change + { + dest_colormap[i] = (UINT8)i; + continue; + } + color = V_GetColor(i); + SETBRIGHTNESS(brightness, color.s.red, color.s.green, color.s.blue); + brightdif = 256; + for (j = 0; j < 16; j++) + { + temp = abs((INT16)brightness - (INT16)colorbrightnesses[j]); + if (temp < brightdif) + { + brightdif = (UINT16)temp; + dest_colormap[i] = Color_Index[skincolor-1][j]; + } + } + } +} + +#undef SETBRIGHTNESS + static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color) { INT32 i, starttranscolor, skinramplength; // Handle a couple of simple special cases - if (skinnum == TC_BOSS || skinnum == TC_ALLWHITE || skinnum == TC_METALSONIC || color == SKINCOLOR_NONE) + if (skinnum == TC_BOSS + || skinnum == TC_ALLWHITE + || skinnum == TC_METALSONIC + || skinnum == TC_BLINK + || color == SKINCOLOR_NONE) { - for (i = 0; i < NUM_PALETTE_ENTRIES; i++) + if (skinnum == TC_ALLWHITE) + memset(dest_colormap, 0, NUM_PALETTE_ENTRIES * sizeof(UINT8**)); + else if (skinnum == TC_BLINK && color != SKINCOLOR_NONE) { - if (skinnum == TC_ALLWHITE) dest_colormap[i] = 0; - else dest_colormap[i] = (UINT8)i; + for (i = 0; i < NUM_PALETTE_ENTRIES; i++) + dest_colormap[i] = Color_Index[color-1][3]; + } + else + { + for (i = 0; i < NUM_PALETTE_ENTRIES; i++) + dest_colormap[i] = (UINT8)i; } // White! @@ -478,6 +548,11 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U return; } + else if (skinnum == TC_RAINBOW) + { + R_RainbowColormap(dest_colormap, color); + return; + } if (color >= MAXTRANSLATIONS) I_Error("Invalid skin color #%hu.", (UINT16)color); @@ -522,6 +597,8 @@ UINT8* R_GetTranslationColormap(INT32 skinnum, skincolors_t color, UINT8 flags) else if (skinnum == TC_BOSS) skintableindex = BOSS_TT_CACHE_INDEX; else if (skinnum == TC_METALSONIC) skintableindex = METALSONIC_TT_CACHE_INDEX; else if (skinnum == TC_ALLWHITE) skintableindex = ALLWHITE_TT_CACHE_INDEX; + else if (skinnum == TC_RAINBOW) skintableindex = RAINBOW_TT_CACHE_INDEX; + else if (skinnum == TC_BLINK) skintableindex = BLINK_TT_CACHE_INDEX; else skintableindex = skinnum; if (flags & GTC_CACHE) diff --git a/src/r_draw.h b/src/r_draw.h index 0c04fee2a..82498eb11 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -105,6 +105,8 @@ extern lumpnum_t viewborderlump[8]; #define TC_BOSS -2 #define TC_METALSONIC -3 // For Metal Sonic battle #define TC_ALLWHITE -4 // For Cy-Brak-demon +#define TC_RAINBOW -5 // For single colour +#define TC_BLINK -6 // For item blinking, according to kart // Initialize color translation tables, for player rendering etc. void R_InitTranslationTables(void); diff --git a/src/r_things.c b/src/r_things.c index 50ee8e6ef..115e49600 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -719,7 +719,7 @@ static void R_DrawVisSprite(vissprite_t *vis) colfunc = basecolfunc; // hack: this isn't resetting properly somewhere. dc_colormap = vis->colormap; - if (!(vis->cut & SC_PRECIP) && (vis->mobj->flags & (MF_ENEMY|MF_BOSS)) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash" + if (!(vis->cut & SC_PRECIP) && (vis->mobj->flags & (MF_ENEMY|MF_BOSS)) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash" { // translate certain pixels to white colfunc = transcolfunc; @@ -734,7 +734,9 @@ static void R_DrawVisSprite(vissprite_t *vis) { colfunc = transtransfunc; dc_transmap = vis->transmap; - if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // MT_GHOST LOOKS LIKE A PLAYER SO USE THE PLAYER TRANSLATION TABLES. >_> + if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized) + dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); + else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // MT_GHOST LOOKS LIKE A PLAYER SO USE THE PLAYER TRANSLATION TABLES. >_> { size_t skinnum = (skin_t*)vis->mobj->skin-skins; dc_translation = R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE); @@ -753,7 +755,9 @@ static void R_DrawVisSprite(vissprite_t *vis) colfunc = transcolfunc; // New colormap stuff for skins Tails 06-07-2002 - if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player! + if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized) + dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); + else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player! { size_t skinnum = (skin_t*)vis->mobj->skin-skins; dc_translation = R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE); From b0326b6dec5065f90f9798ae4fb3801f8f03c920 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 18 Jun 2019 18:51:24 +0100 Subject: [PATCH 022/128] Do some minor HUD fixes. * Move HUD text's anchoring to underneath STR instead of above Lives. * Adjust chat position slightly, to take advantage of SRB2's HUD layout having less content towards the bottom (unlike Kart, where it has roughly equal). * Fix Match emeralds not displaying while in tab rankings with all-seven invuln/shoes bonus active. --- src/hu_stuff.c | 25 ++++++++++---- src/st_stuff.c | 94 +++++++++++++++++++++++++++++--------------------- 2 files changed, 72 insertions(+), 47 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index cec0cfe1f..1a77774c8 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1327,7 +1327,7 @@ static char *CHAT_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) // 30/7/18: chaty is now the distance at which the lowest point of the chat will be drawn if that makes any sense. -INT16 chatx = 13, chaty = 169; // let's use this as our coordinates, shh +INT16 chatx = 14, chaty = 180; // let's use this as our coordinates // chat stuff by VincyTM LOL XD! @@ -1502,8 +1502,8 @@ static void HU_drawChatLog(INT32 offset) if (splitscreen) { y -= BASEVIDHEIGHT/2; - if (splitscreen > 1) - y += 16; + //if (splitscreen > 1) + //y += 16; } #endif y -= (G_RingSlingerGametype() ? 16 : 0); @@ -2302,7 +2302,9 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I | V_ALLOWLOWERCASE, tab[i].name); // Draw emeralds - if (!players[tab[i].num].powers[pw_super] + if (players[tab[i].num].powers[pw_invulnerability] && (players[tab[i].num].powers[pw_invulnerability] == players[tab[i].num].powers[pw_sneakers]) && ((leveltime/7) & 1)) + HU_DrawEmeralds(x-12,y+2,255); + else if (!players[tab[i].num].powers[pw_super] || ((leveltime/7) & 1)) { HU_DrawEmeralds(x-12,y+2,tab[i].emeralds); @@ -2574,7 +2576,9 @@ void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) } // Draw emeralds - if (!players[tab[i].num].powers[pw_super] + if (players[tab[i].num].powers[pw_invulnerability] && (players[tab[i].num].powers[pw_invulnerability] == players[tab[i].num].powers[pw_sneakers]) && ((leveltime/7) & 1)) + HU_DrawEmeralds(x-12,y+2,255); + else if (!players[tab[i].num].powers[pw_super] || ((leveltime/7) & 1)) { HU_DrawEmeralds(x-12,y+2,tab[i].emeralds); @@ -2646,7 +2650,9 @@ void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scoreline V_DrawSmallScaledPatch(x - SHORT(exiticon->width)/2 - 1, y-3, 0, exiticon); // Draw emeralds - if (!players[tab[i].num].powers[pw_super] + if (players[tab[i].num].powers[pw_invulnerability] && (players[tab[i].num].powers[pw_invulnerability] == players[tab[i].num].powers[pw_sneakers]) && ((leveltime/7) & 1)) + HU_DrawEmeralds(x-12,y+2,255); + else if (!players[tab[i].num].powers[pw_super] || ((leveltime/7) & 1)) { HU_DrawEmeralds(x-12,y+2,tab[i].emeralds); @@ -2746,7 +2752,12 @@ static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scor V_DrawFixedPatch((x-10)*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, tagico, 0); // Draw emeralds - if (!players[tab[i].num].powers[pw_super] + if (players[tab[i].num].powers[pw_invulnerability] && players[tab[i].num].powers[pw_invulnerability] && (players[tab[i].num].powers[pw_invulnerability] == players[tab[i].num].powers[pw_sneakers]) && ((leveltime/7) & 1)) + { + HU_Draw32Emeralds(x+60, y+2, 255); + //HU_DrawEmeralds(x-12,y+2,255); + } + else if (!players[tab[i].num].powers[pw_super] || ((leveltime/7) & 1)) { HU_Draw32Emeralds(x+60, y+2, tab[i].emeralds); diff --git a/src/st_stuff.c b/src/st_stuff.c index 4509ed849..f0f40ed32 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1968,37 +1968,27 @@ static void ST_drawMatchHUD(void) static void ST_drawTextHUD(void) { - INT32 y = 176 - 16; // HUD_LIVES - boolean dof12 = false, dospecheader = false; + INT32 y = 42 + 16; // HUD_RINGS + boolean donef12 = false; #define textHUDdraw(str) \ {\ V_DrawThinString(16, y, V_PERPLAYER|V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOBOTTOM, str);\ - y -= 8;\ + y += 8;\ } if (F_GetPromptHideHud(y)) return; - if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (!stplyr->spectator)) + if (stplyr->spectator && (gametype != GT_COOP || stplyr->playerstate == PST_LIVE)) + textHUDdraw(M_GetText("\x86""Spectator mode:")) + + if (circuitmap) { - if (leveltime < hidetime * TICRATE) - { - if (stplyr->pflags & PF_TAGIT) - { - textHUDdraw(M_GetText("Waiting for players to hide...")) - textHUDdraw(M_GetText("\x82""You are blindfolded!")) - } - else if (gametype == GT_HIDEANDSEEK) - textHUDdraw(M_GetText("Hide before time runs out!")) - else - textHUDdraw(M_GetText("Flee before you are hunted!")) - } - else if (gametype == GT_HIDEANDSEEK && !(stplyr->pflags & PF_TAGIT)) - { - textHUDdraw(M_GetText("You cannot move while hiding.")) - dof12 = true; - } + if (stplyr->exiting) + textHUDdraw(M_GetText("\x82""FINISHED!")) + else + textHUDdraw(va("Lap:""\x82 %u/%d", stplyr->laps+1, cv_numlaps.value)) } if (!stplyr->spectator && stplyr->exiting && cv_playersforexit.value && gametype == GT_COOP) @@ -2027,13 +2017,23 @@ static void ST_drawTextHUD(void) if (exiting < total) { + if (!splitscreen && !donef12) + { + textHUDdraw(M_GetText("\x82""VIEWPOINT:""\x80 Switch view")) + donef12 = true; + } total -= exiting; textHUDdraw(va(M_GetText("%d player%s remaining"), total, ((total == 1) ? "" : "s"))) - dof12 = true; } } else if (gametype != GT_COOP && (stplyr->exiting || (G_GametypeUsesLives() && stplyr->lives <= 0 && countdown != 1))) - dof12 = true; + { + if (!splitscreen && !donef12) + { + textHUDdraw(M_GetText("\x82""VIEWPOINT:""\x80 Switch view")) + donef12 = true; + } + } else if (!G_PlatformGametype() && stplyr->playerstate == PST_DEAD && stplyr->lives) //Death overrides spectator text. { INT32 respawntime = cv_respawntime.value - stplyr->deadtimer/TICRATE; @@ -2045,6 +2045,15 @@ static void ST_drawTextHUD(void) } else if (stplyr->spectator && (gametype != GT_COOP || stplyr->playerstate == PST_LIVE)) { + if (!splitscreen && !donef12) + { + textHUDdraw(M_GetText("\x82""VIEWPOINT:""\x80 Switch view")) + donef12 = true; + } + + textHUDdraw(M_GetText("\x82""JUMP:""\x80 Rise")) + textHUDdraw(M_GetText("\x82""SPIN:""\x80 Lower")) + if (G_IsSpecialStage(gamemap) && (maptol & TOL_NIGHTS)) textHUDdraw(M_GetText("\x82""Wait for the stage to end...")) else if (gametype == GT_COOP) @@ -2076,28 +2085,33 @@ static void ST_drawTextHUD(void) } else textHUDdraw(M_GetText("\x82""FIRE:""\x80 Enter game")) - - textHUDdraw(M_GetText("\x82""SPIN:""\x80 Lower")) - textHUDdraw(M_GetText("\x82""JUMP:""\x80 Rise")) - - dof12 = true; - dospecheader = true; } - if (!splitscreen && dof12) - textHUDdraw(M_GetText("\x82""VIEWPOINT:""\x80 Switch view")) - - if (circuitmap) + if ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && (!stplyr->spectator)) { - if (stplyr->exiting) - textHUDdraw(M_GetText("\x82""FINISHED!")) - else - textHUDdraw(va("Lap:""\x82 %u/%d", stplyr->laps+1, cv_numlaps.value)) + if (leveltime < hidetime * TICRATE) + { + if (stplyr->pflags & PF_TAGIT) + { + textHUDdraw(M_GetText("\x82""You are blindfolded!")) + textHUDdraw(M_GetText("Waiting for players to hide...")) + } + else if (gametype == GT_HIDEANDSEEK) + textHUDdraw(M_GetText("Hide before time runs out!")) + else + textHUDdraw(M_GetText("Flee before you are hunted!")) + } + else if (gametype == GT_HIDEANDSEEK && !(stplyr->pflags & PF_TAGIT)) + { + if (!splitscreen && !donef12) + { + textHUDdraw(M_GetText("\x82""VIEWPOINT:""\x80 Switch view")) + donef12 = true; + } + textHUDdraw(M_GetText("You cannot move while hiding.")) + } } - if (dospecheader) - textHUDdraw(M_GetText("\x86""Spectator mode:")) - #undef textHUDdraw } From ef6e00e8a28a7f8a471b871e2c0fe485a9f6d4df Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 19 Jun 2019 12:09:02 +0100 Subject: [PATCH 023/128] P_PlayerCanDamage(player_t*, mobj_t*), ported from the abandoned project_birthday because GOD the code looks awful with those huge monolith conditions in it. Available to Lua. (Also, minor fixes to lib_pSpawnLockOn, and removing the SH_OP fuckery.) --- src/lua_baselib.c | 17 ++++++++++++ src/p_inter.c | 19 +++++-------- src/p_local.h | 1 + src/p_map.c | 70 ++++++++++++++++++++--------------------------- src/p_mobj.c | 9 +++--- src/p_user.c | 36 ++++++++++++++++++++++++ 6 files changed, 95 insertions(+), 57 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 755b76835..192e2b6cb 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -540,6 +540,7 @@ static int lib_pSpawnLockOn(lua_State *L) { mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker visual->target = lockon; + visual->flags2 |= MF2_DONTDRAW; P_SetMobjStateNF(visual, state); } return 0; @@ -951,6 +952,21 @@ static int lib_pResetPlayer(lua_State *L) return 0; } +static int lib_pPlayerCanDamage(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + //HUDSAFE + INLEVEL + if (!player) + return LUA_ErrInvalid(L, "player_t"); + if (!thing) + return LUA_ErrInvalid(L, "mobj_t"); + lua_pushboolean(L, P_PlayerCanDamage(player, thing)); + return 1; +} + + static int lib_pIsObjectInGoop(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); @@ -2774,6 +2790,7 @@ static luaL_Reg lib[] = { {"P_PlayerInPain",lib_pPlayerInPain}, {"P_DoPlayerPain",lib_pDoPlayerPain}, {"P_ResetPlayer",lib_pResetPlayer}, + {"P_PlayerCanDamage",lib_pPlayerCanDamage}, {"P_IsObjectInGoop",lib_pIsObjectInGoop}, {"P_IsObjectOnGround",lib_pIsObjectOnGround}, {"P_InSpaceSector",lib_pInSpaceSector}, diff --git a/src/p_inter.c b/src/p_inter.c index 68f1782c5..42722e6d1 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -453,13 +453,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) break; } - if (((player->powers[pw_carry] == CR_NIGHTSMODE) && (player->pflags & PF_DRILLING)) - || ((player->pflags & PF_JUMPED) && (!(player->pflags & PF_NOJUMPDAMAGE) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY))) - || (player->pflags & (PF_SPINNING|PF_GLIDING)) - || (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) - || ((player->charflags & SF_STOMPDAMAGE || player->pflags & PF_BOUNCING) && (P_MobjFlip(toucher)*(toucher->z - (special->z + special->height/2)) > 0) && (P_MobjFlip(toucher)*toucher->momz < 0)) - || player->powers[pw_invulnerability] || player->powers[pw_super] - || elementalpierce) // Do you possess the ability to subdue the object? + if (player->powers[pw_invulnerability] || player->powers[pw_super] + || P_PlayerCanDamage(player, special)) // Do you possess the ability to subdue the object? { if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1)) { @@ -1750,6 +1745,10 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour deadtarget = (player->mo->health <= 0); + // Don't log every hazard hit if they don't want us to. + if (!deadtarget && !cv_hazardlog.value) + return; + // Target's name snprintf(targetname, sizeof(targetname), "%s%s%s", CTFTEAMCODE(player), @@ -1853,7 +1852,7 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour switch (damagetype) { case DMG_WATER: - str = M_GetText("%s was %s by chemical water.\n"); + str = M_GetText("%s was %s by dangerous water.\n"); break; case DMG_FIRE: str = M_GetText("%s was %s by molten lava.\n"); @@ -1901,10 +1900,6 @@ static void P_HitDeathMessages(player_t *player, mobj_t *inflictor, mobj_t *sour if (!str) // Should not happen! Unless we missed catching something above. return; - // Don't log every hazard hit if they don't want us to. - if (!deadtarget && !cv_hazardlog.value) - return; - if (deathonly) { if (!deadtarget) diff --git a/src/p_local.h b/src/p_local.h index b686b9f09..f93ea7147 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -128,6 +128,7 @@ pflags_t P_GetJumpFlags(player_t *player); boolean P_PlayerInPain(player_t *player); void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor); void P_ResetPlayer(player_t *player); +boolean P_PlayerCanDamage(player_t *player, mobj_t *thing); boolean P_IsLocalPlayer(player_t *player); boolean P_IsObjectInGoop(mobj_t *mo); diff --git a/src/p_map.c b/src/p_map.c index ffe6cf916..3db3db4e3 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1405,51 +1405,41 @@ static boolean PIT_CheckThing(mobj_t *thing) } // Monitor? else if (thing->flags & MF_MONITOR - && !((thing->type == MT_RING_REDBOX && tmthing->player->ctfteam != 1) || (thing->type == MT_RING_BLUEBOX && tmthing->player->ctfteam != 2))) + && !((thing->type == MT_RING_REDBOX && tmthing->player->ctfteam != 1) || (thing->type == MT_RING_BLUEBOX && tmthing->player->ctfteam != 2)) + && (!(thing->flags & MF_SOLID) || P_PlayerCanDamage(tmthing->player, thing))) { - // 0 = none, 1 = elemental pierce, 2 = bubble bounce - UINT8 elementalpierce = (((tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (tmthing->player->pflags & PF_SHIELDABILITY) - ? (((tmthing->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) ? 1 : 2) - : 0); - if (!(thing->flags & MF_SOLID) - || tmthing->player->pflags & (PF_SPINNING|PF_GLIDING) - || ((tmthing->player->pflags & PF_JUMPED) - && (!(tmthing->player->pflags & PF_NOJUMPDAMAGE) - || (tmthing->player->charability == CA_TWINSPIN && tmthing->player->panim == PA_ABILITY))) - || (tmthing->player->charability2 == CA2_MELEE && tmthing->player->panim == PA_ABILITY2) - || ((tmthing->player->charflags & SF_STOMPDAMAGE || tmthing->player->pflags & PF_BOUNCING) - && (P_MobjFlip(tmthing)*(tmthing->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(tmthing)*tmthing->momz < 0)) - || elementalpierce) + if (thing->z - thing->scale <= tmthing->z + tmthing->height + && thing->z + thing->height + thing->scale >= tmthing->z) { - if (thing->z - thing->scale <= tmthing->z + tmthing->height - && thing->z + thing->height + thing->scale >= tmthing->z) + player_t *player = tmthing->player; + // 0 = none, 1 = elemental pierce, 2 = bubble bounce + UINT8 elementalpierce = (((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (player->pflags & PF_SHIELDABILITY) + ? (((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) ? 1 : 2) + : 0); + SINT8 flipval = P_MobjFlip(thing); // Save this value in case monitor gets removed. + fixed_t *momz = &tmthing->momz; // tmthing gets changed by P_DamageMobj, so we need a new pointer?! X_x;; + fixed_t *z = &tmthing->z; // aau. + // Going down? Then bounce back up. + if (P_DamageMobj(thing, tmthing, tmthing, 1, 0) // break the monitor + && (flipval*(*momz) < 0) // monitor is on the floor and you're going down, or on the ceiling and you're going up + && (elementalpierce != 1)) // you're not piercing through the monitor... { - player_t *player = tmthing->player; - SINT8 flipval = P_MobjFlip(thing); // Save this value in case monitor gets removed. - fixed_t *momz = &tmthing->momz; // tmthing gets changed by P_DamageMobj, so we need a new pointer?! X_x;; - fixed_t *z = &tmthing->z; // aau. - // Going down? Then bounce back up. - if (P_DamageMobj(thing, tmthing, tmthing, 1, 0) // break the monitor - && (flipval*(*momz) < 0) // monitor is on the floor and you're going down, or on the ceiling and you're going up - && (elementalpierce != 1)) // you're not piercing through the monitor... - { - if (elementalpierce == 2) - P_DoBubbleBounce(player); - else if (!(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)) - *momz = -*momz; // Therefore, you should be thrust in the opposite direction, vertically. - } - if (!(elementalpierce == 1 && thing->flags & MF_GRENADEBOUNCE)) // prevent gold monitor clipthrough. - { - if (player->pflags & PF_BOUNCING) - P_DoAbilityBounce(player, false); - return false; - } - else - *z -= *momz; // to ensure proper collision. + if (elementalpierce == 2) + P_DoBubbleBounce(player); + else if (!(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)) + *momz = -*momz; // Therefore, you should be thrust in the opposite direction, vertically. } - - return true; + if (!(elementalpierce == 1 && thing->flags & MF_GRENADEBOUNCE)) // prevent gold monitor clipthrough. + { + if (player->pflags & PF_BOUNCING) + P_DoAbilityBounce(player, false); + return false; + } + else + *z -= *momz; // to ensure proper collision. } + + return true; } } diff --git a/src/p_mobj.c b/src/p_mobj.c index fd679857e..70a40592d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3396,11 +3396,7 @@ void P_MobjCheckWater(mobj_t *mobj) if (!((p->powers[pw_super]) || (p->powers[pw_invulnerability]))) { boolean electric = !!(p->powers[pw_shield] & SH_PROTECTELECTRIC); -#define SH_OP (SH_PROTECTFIRE|SH_PROTECTWATER|SH_PROTECTELECTRIC) - if ((p->powers[pw_shield] & SH_OP) == SH_OP) // No. - P_KillMobj(mobj, NULL, NULL, DMG_INSTAKILL); -#undef SH_OP - else if (electric || ((p->powers[pw_shield] & SH_PROTECTFIRE) && !(p->powers[pw_shield] & SH_PROTECTWATER))) + if (electric || ((p->powers[pw_shield] & SH_PROTECTFIRE) && !(p->powers[pw_shield] & SH_PROTECTWATER))) { // Water removes electric and non-water fire shields... P_FlashPal(p, electric @@ -7109,6 +7105,9 @@ void P_MobjThinker(mobj_t *mobj) P_RemoveMobj(mobj); return; } + + mobj->flags2 &= ~MF2_DONTDRAW; + mobj->x = mobj->target->x; mobj->y = mobj->target->y; diff --git a/src/p_user.c b/src/p_user.c index ca14c64d4..b1b755204 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -977,6 +977,42 @@ void P_ResetPlayer(player_t *player) CV_SetValue(&cv_analog2, true); } +// P_PlayerCanDamage +// +// Can player do damage? +// Doesn't count invincibility or super, for the sake of monitors. +// +boolean P_PlayerCanDamage(player_t *player, mobj_t *thing) +{ + if (!player->mo || player->spectator || !thing || P_MobjWasRemoved(thing)) + return false; + + if ((player->powers[pw_carry] == CR_NIGHTSMODE) && (player->pflags & PF_DRILLING)) + return true; + + if ((player->pflags & PF_JUMPED) + && (!(player->pflags & PF_NOJUMPDAMAGE) + || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY))) + return true; + + if (player->pflags & (PF_SPINNING|PF_GLIDING)) + return true; + + if (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) + return true; + + if ((player->charflags & SF_STOMPDAMAGE || player->pflags & PF_BOUNCING) + && (P_MobjFlip(player->mo)*(player->mo->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(player->mo)*player->mo->momz < 0)) + return true; + + if (((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (player->pflags & PF_SHIELDABILITY)) + return true; + + return false; +} + + + // // P_GivePlayerRings // From 28dfeb344b5955345e8319286065d8e134cc1d80 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 19 Jun 2019 12:28:57 +0100 Subject: [PATCH 024/128] Instead of only performing a hook if the Lua Hook loop determines its type to be the one we want, actively continue through the loop if it's NOT. This optimisation was performed while preparing the following commit; I have generously split them out for less shitty commit-by-commit review. --- src/lua_hooklib.c | 1135 ++++++++++++++++++++++++--------------------- 1 file changed, 594 insertions(+), 541 deletions(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index d605499e2..de8d29be4 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -250,44 +250,48 @@ boolean LUAh_MobjHook(mobj_t *mo, enum hook which) // Look for all generic mobj hooks for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - if (hookp->type == which) - { - if (lua_gettop(gL) == 0) - LUA_PushUserdata(gL, mo, META_MOBJ); - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; + { + if (hookp->type != which) + continue; + + if (lua_gettop(gL) == 0) + LUA_PushUserdata(gL, mo, META_MOBJ); + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -2); + if (lua_pcall(gL, 1, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); + hookp->error = true; + continue; } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } for (hookp = mobjhooks[mo->type]; hookp; hookp = hookp->next) - if (hookp->type == which) - { - if (lua_gettop(gL) == 0) - LUA_PushUserdata(gL, mo, META_MOBJ); - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; + { + if (hookp->type != which) + continue; + + if (lua_gettop(gL) == 0) + LUA_PushUserdata(gL, mo, META_MOBJ); + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -2); + if (lua_pcall(gL, 1, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); + hookp->error = true; + continue; } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } lua_settop(gL, 0); return hooked; @@ -303,24 +307,26 @@ boolean LUAh_PlayerHook(player_t *plr, enum hook which) lua_settop(gL, 0); for (hookp = playerhooks; hookp; hookp = hookp->next) - if (hookp->type == which) - { - if (lua_gettop(gL) == 0) - LUA_PushUserdata(gL, plr, META_PLAYER); - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; + { + if (hookp->type != which) + continue; + + if (lua_gettop(gL) == 0) + LUA_PushUserdata(gL, plr, META_PLAYER); + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -2); + if (lua_pcall(gL, 1, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); + hookp->error = true; + continue; } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } lua_settop(gL, 0); return hooked; @@ -337,13 +343,15 @@ void LUAh_MapChange(INT16 mapnumber) lua_pushinteger(gL, mapnumber); for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_MapChange) - { - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -2); - LUA_Call(gL, 1); - } + { + if (hookp->type != hook_MapChange) + continue; + + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -2); + LUA_Call(gL, 1); + } lua_settop(gL, 0); } @@ -359,13 +367,15 @@ void LUAh_MapLoad(void) lua_pushinteger(gL, gamemap); for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_MapLoad) - { - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -2); - LUA_Call(gL, 1); - } + { + if (hookp->type != hook_MapLoad) + continue; + + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -2); + LUA_Call(gL, 1); + } lua_settop(gL, 0); } @@ -381,13 +391,15 @@ void LUAh_PlayerJoin(int playernum) lua_pushinteger(gL, playernum); for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_PlayerJoin) - { - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -2); - LUA_Call(gL, 1); - } + { + if (hookp->type != hook_PlayerJoin) + continue; + + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -2); + LUA_Call(gL, 1); + } lua_settop(gL, 0); } @@ -400,17 +412,19 @@ void LUAh_ThinkFrame(void) return; for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_ThinkFrame) - { - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - if (lua_pcall(gL, 0, 0, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - } + { + if (hookp->type != hook_ThinkFrame) + continue; + + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + if (lua_pcall(gL, 0, 0, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; } + } } // Hook for mobj collisions @@ -427,62 +441,66 @@ UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which) // Look for all generic mobj collision hooks for (hookp = mobjcollidehooks[MT_NULL]; hookp; hookp = hookp->next) - if (hookp->type == which) + { + if (hookp->type != which) + continue; + + if (lua_gettop(gL) == 0) { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, thing1, META_MOBJ); - LUA_PushUserdata(gL, thing2, META_MOBJ); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { // if nil, leave shouldCollide = 0. - if (lua_toboolean(gL, -1)) - shouldCollide = 1; // Force yes - else - shouldCollide = 2; // Force no - } - lua_pop(gL, 1); + LUA_PushUserdata(gL, thing1, META_MOBJ); + LUA_PushUserdata(gL, thing2, META_MOBJ); } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1)) + { // if nil, leave shouldCollide = 0. + if (lua_toboolean(gL, -1)) + shouldCollide = 1; // Force yes + else + shouldCollide = 2; // Force no + } + lua_pop(gL, 1); + } for (hookp = mobjcollidehooks[thing1->type]; hookp; hookp = hookp->next) - if (hookp->type == which) + { + if (hookp->type != which) + continue; + + if (lua_gettop(gL) == 0) { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, thing1, META_MOBJ); - LUA_PushUserdata(gL, thing2, META_MOBJ); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { // if nil, leave shouldCollide = 0. - if (lua_toboolean(gL, -1)) - shouldCollide = 1; // Force yes - else - shouldCollide = 2; // Force no - } - lua_pop(gL, 1); + LUA_PushUserdata(gL, thing1, META_MOBJ); + LUA_PushUserdata(gL, thing2, META_MOBJ); } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1)) + { // if nil, leave shouldCollide = 0. + if (lua_toboolean(gL, -1)) + shouldCollide = 1; // Force yes + else + shouldCollide = 2; // Force no + } + lua_pop(gL, 1); + } lua_settop(gL, 0); return shouldCollide; @@ -557,52 +575,56 @@ boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher) // Look for all generic touch special hooks for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - if (hookp->type == hook_TouchSpecial) + { + if (hookp->type != hook_TouchSpecial) + continue; + + if (lua_gettop(gL) == 0) { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, special, META_MOBJ); - LUA_PushUserdata(gL, toucher, META_MOBJ); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); + LUA_PushUserdata(gL, special, META_MOBJ); + LUA_PushUserdata(gL, toucher, META_MOBJ); } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } for (hookp = mobjhooks[special->type]; hookp; hookp = hookp->next) - if (hookp->type == hook_TouchSpecial) + { + if (hookp->type != hook_TouchSpecial) + continue; + + if (lua_gettop(gL) == 0) { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, special, META_MOBJ); - LUA_PushUserdata(gL, toucher, META_MOBJ); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); + LUA_PushUserdata(gL, special, META_MOBJ); + LUA_PushUserdata(gL, toucher, META_MOBJ); } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } lua_settop(gL, 0); return hooked; @@ -622,72 +644,75 @@ UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 // Look for all generic should damage hooks for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - if (hookp->type == hook_ShouldDamage) + { + if (hookp->type != hook_ShouldDamage) + continue; + + if (lua_gettop(gL) == 0) { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damage); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { - if (lua_toboolean(gL, -1)) - shouldDamage = 1; // Force yes - else - shouldDamage = 2; // Force no - } - lua_pop(gL, 1); + LUA_PushUserdata(gL, target, META_MOBJ); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + lua_pushinteger(gL, damage); } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + if (lua_pcall(gL, 4, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1)) + { + if (lua_toboolean(gL, -1)) + shouldDamage = 1; // Force yes + else + shouldDamage = 2; // Force no + } + lua_pop(gL, 1); + } for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next) - if (hookp->type == hook_ShouldDamage) + { + if (hookp->type != hook_ShouldDamage) + continue; + if (lua_gettop(gL) == 0) { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damage); - lua_pushinteger(gL, damagetype); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - if (lua_pcall(gL, 5, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { - if (lua_toboolean(gL, -1)) - shouldDamage = 1; // Force yes - else - shouldDamage = 2; // Force no - } - lua_pop(gL, 1); + LUA_PushUserdata(gL, target, META_MOBJ); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + lua_pushinteger(gL, damage); + lua_pushinteger(gL, damagetype); } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + if (lua_pcall(gL, 5, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1)) + { + if (lua_toboolean(gL, -1)) + shouldDamage = 1; // Force yes + else + shouldDamage = 2; // Force no + } + lua_pop(gL, 1); + } lua_settop(gL, 0); return shouldDamage; @@ -707,62 +732,66 @@ boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 // Look for all generic mobj damage hooks for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - if (hookp->type == hook_MobjDamage) + { + if (hookp->type != hook_MobjDamage) + continue; + + if (lua_gettop(gL) == 0) { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damage); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); + LUA_PushUserdata(gL, target, META_MOBJ); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + lua_pushinteger(gL, damage); } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + if (lua_pcall(gL, 4, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next) - if (hookp->type == hook_MobjDamage) + { + if (hookp->type != hook_MobjDamage) + continue; + + if (lua_gettop(gL) == 0) { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damage); - lua_pushinteger(gL, damagetype); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - if (lua_pcall(gL, 5, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); + LUA_PushUserdata(gL, target, META_MOBJ); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + lua_pushinteger(gL, damage); + lua_pushinteger(gL, damagetype); } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + if (lua_pcall(gL, 5, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } lua_settop(gL, 0); return hooked; @@ -782,58 +811,62 @@ boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 // Look for all generic mobj death hooks for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - if (hookp->type == hook_MobjDeath) + { + if (hookp->type != hook_MobjDeath) + continue; + + if (lua_gettop(gL) == 0) { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); + LUA_PushUserdata(gL, target, META_MOBJ); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -4); + lua_pushvalue(gL, -4); + lua_pushvalue(gL, -4); + if (lua_pcall(gL, 3, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next) - if (hookp->type == hook_MobjDeath) + { + if (hookp->type != hook_MobjDeath) + continue; + + if (lua_gettop(gL) == 0) { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damagetype); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); + LUA_PushUserdata(gL, target, META_MOBJ); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + lua_pushinteger(gL, damagetype); } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + if (lua_pcall(gL, 4, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } lua_settop(gL, 0); return hooked; @@ -850,28 +883,30 @@ boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd) lua_settop(gL, 0); for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_BotTiccmd) + { + if (hookp->type != hook_BotTiccmd) + continue; + + if (lua_gettop(gL) == 0) { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, bot, META_PLAYER); - LUA_PushUserdata(gL, cmd, META_TICCMD); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); + LUA_PushUserdata(gL, bot, META_PLAYER); + LUA_PushUserdata(gL, cmd, META_TICCMD); } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } lua_settop(gL, 0); return hooked; @@ -888,51 +923,53 @@ boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) lua_settop(gL, 0); for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_BotAI - && (hookp->s.skinname == NULL || !strcmp(hookp->s.skinname, ((skin_t*)tails->skin)->name))) + { + if (hookp->type != hook_BotAI + || (hookp->s.skinname && strcmp(hookp->s.skinname, ((skin_t*)tails->skin)->name))) + continue; + + if (lua_gettop(gL) == 0) { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, sonic, META_MOBJ); - LUA_PushUserdata(gL, tails, META_MOBJ); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 8, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - - // This turns forward, backward, left, right, jump, and spin into a proper ticcmd for tails. - if (lua_istable(gL, 2+1)) { - boolean forward=false, backward=false, left=false, right=false, strafeleft=false, straferight=false, jump=false, spin=false; -#define CHECKFIELD(field) \ - lua_getfield(gL, 2+1, #field);\ - if (lua_toboolean(gL, -1))\ - field = true;\ - lua_pop(gL, 1); - - CHECKFIELD(forward) - CHECKFIELD(backward) - CHECKFIELD(left) - CHECKFIELD(right) - CHECKFIELD(strafeleft) - CHECKFIELD(straferight) - CHECKFIELD(jump) - CHECKFIELD(spin) -#undef CHECKFIELD - B_KeysToTiccmd(tails, cmd, forward, backward, left, right, strafeleft, straferight, jump, spin); - } else - B_KeysToTiccmd(tails, cmd, lua_toboolean(gL, 2+1), lua_toboolean(gL, 2+2), lua_toboolean(gL, 2+3), lua_toboolean(gL, 2+4), lua_toboolean(gL, 2+5), lua_toboolean(gL, 2+6), lua_toboolean(gL, 2+7), lua_toboolean(gL, 2+8)); - - lua_pop(gL, 8); - hooked = true; + LUA_PushUserdata(gL, sonic, META_MOBJ); + LUA_PushUserdata(gL, tails, META_MOBJ); } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 8, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + + // This turns forward, backward, left, right, jump, and spin into a proper ticcmd for tails. + if (lua_istable(gL, 2+1)) { + boolean forward=false, backward=false, left=false, right=false, strafeleft=false, straferight=false, jump=false, spin=false; +#define CHECKFIELD(field) \ + lua_getfield(gL, 2+1, #field);\ + if (lua_toboolean(gL, -1))\ + field = true;\ + lua_pop(gL, 1); + + CHECKFIELD(forward) + CHECKFIELD(backward) + CHECKFIELD(left) + CHECKFIELD(right) + CHECKFIELD(strafeleft) + CHECKFIELD(straferight) + CHECKFIELD(jump) + CHECKFIELD(spin) +#undef CHECKFIELD + B_KeysToTiccmd(tails, cmd, forward, backward, left, right, strafeleft, straferight, jump, spin); + } else + B_KeysToTiccmd(tails, cmd, lua_toboolean(gL, 2+1), lua_toboolean(gL, 2+2), lua_toboolean(gL, 2+3), lua_toboolean(gL, 2+4), lua_toboolean(gL, 2+5), lua_toboolean(gL, 2+6), lua_toboolean(gL, 2+7), lua_toboolean(gL, 2+8)); + + lua_pop(gL, 8); + hooked = true; + } lua_settop(gL, 0); return hooked; @@ -949,22 +986,24 @@ boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector) lua_settop(gL, 0); for (hookp = linedefexecutorhooks; hookp; hookp = hookp->next) - if (!strcmp(hookp->s.funcname, line->text)) + { + if (strcmp(hookp->s.funcname, line->text)) + continue; + + if (lua_gettop(gL) == 0) { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, line, META_LINE); - LUA_PushUserdata(gL, mo, META_MOBJ); - LUA_PushUserdata(gL, sector, META_SECTOR); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - LUA_Call(gL, 3); - hooked = true; + LUA_PushUserdata(gL, line, META_LINE); + LUA_PushUserdata(gL, mo, META_MOBJ); + LUA_PushUserdata(gL, sector, META_SECTOR); } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -4); + lua_pushvalue(gL, -4); + lua_pushvalue(gL, -4); + LUA_Call(gL, 3); + hooked = true; + } lua_settop(gL, 0); return hooked; @@ -981,43 +1020,45 @@ boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg) lua_settop(gL, 0); for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_PlayerMsg) + { + if (hookp->type != hook_PlayerMsg) + continue; + + if (lua_gettop(gL) == 0) { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, &players[source], META_PLAYER); // Source player - if (flags & 2 /*HU_CSAY*/) { // csay TODO: make HU_CSAY accessible outside hu_stuff.c - lua_pushinteger(gL, 3); // type - lua_pushnil(gL); // target - } else if (target == -1) { // sayteam - lua_pushinteger(gL, 1); // type - lua_pushnil(gL); // target - } else if (target == 0) { // say - lua_pushinteger(gL, 0); // type - lua_pushnil(gL); // target - } else { // sayto - lua_pushinteger(gL, 2); // type - LUA_PushUserdata(gL, &players[target-1], META_PLAYER); // target - } - lua_pushstring(gL, msg); // msg + LUA_PushUserdata(gL, &players[source], META_PLAYER); // Source player + if (flags & 2 /*HU_CSAY*/) { // csay TODO: make HU_CSAY accessible outside hu_stuff.c + lua_pushinteger(gL, 3); // type + lua_pushnil(gL); // target + } else if (target == -1) { // sayteam + lua_pushinteger(gL, 1); // type + lua_pushnil(gL); // target + } else if (target == 0) { // say + lua_pushinteger(gL, 0); // type + lua_pushnil(gL); // target + } else { // sayto + lua_pushinteger(gL, 2); // type + LUA_PushUserdata(gL, &players[target-1], META_PLAYER); // target } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); + lua_pushstring(gL, msg); // msg } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + if (lua_pcall(gL, 4, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } lua_settop(gL, 0); return hooked; @@ -1035,33 +1076,35 @@ boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 lua_settop(gL, 0); for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_HurtMsg - && (hookp->s.mt == MT_NULL || (inflictor && hookp->s.mt == inflictor->type))) + { + if (hookp->type != hook_HurtMsg + || (hookp->s.mt && !(inflictor && hookp->s.mt == inflictor->type))) + continue; + + if (lua_gettop(gL) == 0) { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damagetype); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + lua_pushinteger(gL, damagetype); } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + if (lua_pcall(gL, 4, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } lua_settop(gL, 0); return hooked; @@ -1084,13 +1127,15 @@ void LUAh_NetArchiveHook(lua_CFunction archFunc) // stack: tables, archFunc for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_NetVars) - { - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -2); // archFunc - LUA_Call(gL, 1); - } + { + if (hookp->type != hook_NetVars) + continue; + + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -2); // archFunc + LUA_Call(gL, 1); + } lua_pop(gL, 1); // pop archFunc // stack: tables @@ -1107,52 +1152,56 @@ boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing) // Look for all generic mobj map thing spawn hooks for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - if (hookp->type == hook_MapThingSpawn) + { + if (hookp->type != hook_MapThingSpawn) + continue; + + if (lua_gettop(gL) == 0) { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, mo, META_MOBJ); - LUA_PushUserdata(gL, mthing, META_MAPTHING); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); + LUA_PushUserdata(gL, mo, META_MOBJ); + LUA_PushUserdata(gL, mthing, META_MAPTHING); } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } for (hookp = mobjhooks[mo->type]; hookp; hookp = hookp->next) - if (hookp->type == hook_MapThingSpawn) + { + if (hookp->type != hook_MapThingSpawn) + continue; + + if (lua_gettop(gL) == 0) { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, mo, META_MOBJ); - LUA_PushUserdata(gL, mthing, META_MAPTHING); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); + LUA_PushUserdata(gL, mo, META_MOBJ); + LUA_PushUserdata(gL, mthing, META_MAPTHING); } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } lua_settop(gL, 0); return hooked; @@ -1169,28 +1218,30 @@ boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj) lua_settop(gL, 0); for (hookp = playerhooks; hookp; hookp = hookp->next) - if (hookp->type == hook_FollowMobj) + { + if (hookp->type != hook_FollowMobj) + continue; + + if (lua_gettop(gL) == 0) { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, mobj, META_MOBJ); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, mobj, META_MOBJ); } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } lua_settop(gL, 0); return hooked; @@ -1205,19 +1256,21 @@ void LUAh_PlayerQuit(player_t *plr, int reason) lua_settop(gL, 0); for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_PlayerQuit) - { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, plr, META_PLAYER); // Player that quit - lua_pushinteger(gL, reason); // Reason for quitting - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - LUA_Call(gL, 2); - } + { + if (hookp->type != hook_PlayerQuit) + continue; + + if (lua_gettop(gL) == 0) + { + LUA_PushUserdata(gL, plr, META_PLAYER); // Player that quit + lua_pushinteger(gL, reason); // Reason for quitting + } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + LUA_Call(gL, 2); + } lua_settop(gL, 0); } From 3eb9b85fd4d3bbf43d5f1cf9f53e47367fcece11 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 19 Jun 2019 12:55:05 +0100 Subject: [PATCH 025/128] "PlayerCanDamage" hook! * Takes function(player, mo) input. * Return TRUE for stating that yes, the player is in a state that can cause contact damage, do with that what you will. * Return FALSE for stating that no, the player is weak and vulnerable and cannot cause contact damage, do with that what you will. * Return NIL for allowing the function to continue regular operation. Fills a different ideological niche than ShouldDamage - that's for determining whether damage dished between two objects should happen, this is for determining which way around damage should be dished when considering a player-object interaction. Or, in other words, think of it as "ShouldDamage is whether damage that has been requested should be granted, for object-object interaction, while PlayerCanDamage is for whether global player properties should cause damage to enemies and monitors in the first place, like spinning, hammering or stomping." --- src/lua_baselib.c | 2 +- src/lua_hook.h | 4 +++- src/lua_hooklib.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ src/p_user.c | 12 ++++++++++++ 4 files changed, 63 insertions(+), 2 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 192e2b6cb..e6119cd6c 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -956,7 +956,7 @@ static int lib_pPlayerCanDamage(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); - //HUDSAFE + NOHUD // was hud safe but then i added a lua hook INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); diff --git a/src/lua_hook.h b/src/lua_hook.h index 9fcc36594..45e116c34 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -48,6 +48,7 @@ enum hook { hook_MobjMoveBlocked, hook_MapThingSpawn, hook_FollowMobj, + hook_PlayerCanDamage, hook_PlayerQuit, hook_MAX // last hook @@ -87,7 +88,8 @@ boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 #define LUAh_ShieldSpecial(player) LUAh_PlayerHook(player, hook_ShieldSpecial) // Hook for shield abilities #define LUAh_MobjMoveBlocked(mo) LUAh_MobjHook(mo, hook_MobjMoveBlocked) // Hook for P_XYMovement (when movement is blocked) boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing); // Hook for P_SpawnMapThing by mobj type -boolean LUAh_FollowMobj(player_t *player, mobj_t *mo); // Hook for P_PlayerAfterThink Smiles mobj-following +boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj); // Hook for P_PlayerAfterThink Smiles mobj-following +UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj); // Hook for P_PlayerCanDamage void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting #endif diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index de8d29be4..7f7e8adc6 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -59,6 +59,7 @@ const char *const hookNames[hook_MAX+1] = { "MobjMoveBlocked", "MapThingSpawn", "FollowMobj", + "PlayerCanDamage", "PlayerQuit", NULL }; @@ -200,6 +201,7 @@ static int lib_addHook(lua_State *L) case hook_JumpSpinSpecial: case hook_PlayerSpawn: case hook_FollowMobj: + case hook_PlayerCanDamage: case hook_ShieldSpawn: case hook_ShieldSpecial: lastp = &playerhooks; @@ -1247,6 +1249,51 @@ boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj) return hooked; } +// Hook for P_PlayerCanDamage +UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj) +{ + hook_p hookp; + UINT8 shouldCollide = 0; // 0 = default, 1 = force yes, 2 = force no. + if (!gL || !(hooksAvailable[hook_PlayerCanDamage/8] & (1<<(hook_PlayerCanDamage%8)))) + return 0; + + lua_settop(gL, 0); + + for (hookp = playerhooks; hookp; hookp = hookp->next) + { + if (hookp->type != hook_PlayerCanDamage) + continue; + + if (lua_gettop(gL) == 0) + { + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, mobj, META_MOBJ); + } + lua_pushfstring(gL, FMT_HOOKID, hookp->id); + lua_gettable(gL, LUA_REGISTRYINDEX); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 0)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1)) + { // if nil, leave shouldCollide = 0. + if (lua_toboolean(gL, -1)) + shouldCollide = 1; // Force yes + else + shouldCollide = 2; // Force no + } + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return shouldCollide; +} + void LUAh_PlayerQuit(player_t *plr, int reason) { hook_p hookp; diff --git a/src/p_user.c b/src/p_user.c index b1b755204..9a5d315a3 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -987,6 +987,18 @@ boolean P_PlayerCanDamage(player_t *player, mobj_t *thing) if (!player->mo || player->spectator || !thing || P_MobjWasRemoved(thing)) return false; +#ifdef HAVE_BLUA + { + UINT8 shouldCollide = LUAh_PlayerCanDamage(player, thing); + if (P_MobjWasRemoved(thing)) + return false; // removed??? + if (shouldCollide == 1) + return true; // force yes + else if (shouldCollide == 2) + return false; // force no + } +#endif + if ((player->powers[pw_carry] == CR_NIGHTSMODE) && (player->pflags & PF_DRILLING)) return true; From 6a58ae34d1498d86e0b3b7155505a3f67c2010f3 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 19 Jun 2019 13:20:34 +0100 Subject: [PATCH 026/128] In order to make P_PlayerCanDamage more flexible, I ended up bundling the invincibility/super checks into there. Also, the start of my improvements to CA2_MELEE. Users of that abiliy can only damage enemies/monitors if they touch the front of the player object, but to make up for it, the player is no longer forced away from the direction of the screen at bigger movement speeds. --- src/p_inter.c | 3 +-- src/p_user.c | 20 +++++++++++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index 42722e6d1..4cbd9185c 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -453,8 +453,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) break; } - if (player->powers[pw_invulnerability] || player->powers[pw_super] - || P_PlayerCanDamage(player, special)) // Do you possess the ability to subdue the object? + if (P_PlayerCanDamage(player, special)) // Do you possess the ability to subdue the object? { if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1)) { diff --git a/src/p_user.c b/src/p_user.c index 9a5d315a3..b879df48a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -980,7 +980,6 @@ void P_ResetPlayer(player_t *player) // P_PlayerCanDamage // // Can player do damage? -// Doesn't count invincibility or super, for the sake of monitors. // boolean P_PlayerCanDamage(player_t *player, mobj_t *thing) { @@ -999,24 +998,35 @@ boolean P_PlayerCanDamage(player_t *player, mobj_t *thing) } #endif + // Invinc/super. Not for Monitors. + if (!(thing->flags & MF_MONITOR) && (player->powers[pw_invulnerability] || player->powers[pw_super])) + return true; + + // NiGHTS drill. Wasn't originally for monitors, but that's more an oversight being corrected than anything else. if ((player->powers[pw_carry] == CR_NIGHTSMODE) && (player->pflags & PF_DRILLING)) return true; + // Jumping. if ((player->pflags & PF_JUMPED) && (!(player->pflags & PF_NOJUMPDAMAGE) || (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY))) return true; - if (player->pflags & (PF_SPINNING|PF_GLIDING)) + // Spinning. + if (player->pflags & PF_SPINNING) return true; - if (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) + // From the front. + if (((player->pflags & PF_GLIDING) || (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)) + && (player->drawangle - R_PointToAngle2(player->mo->x - player->mo->momx, player->mo->y - player->mo->momy, thing->x, thing->y) + + ANGLE_90) < ANGLE_180) return true; + // From the top. if ((player->charflags & SF_STOMPDAMAGE || player->pflags & PF_BOUNCING) && (P_MobjFlip(player->mo)*(player->mo->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(player->mo)*player->mo->momz < 0)) return true; + // Shield stomp. if (((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (player->pflags & PF_SHIELDABILITY)) return true; @@ -4336,7 +4346,11 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) P_SetObjectMomZ(player->mo, player->mindash, false); if (player->mo->eflags & MFE_UNDERWATER) player->mo->momz >>= 1; +#if 0 if (FixedMul(player->speed, FINECOSINE(((player->mo->angle - R_PointToAngle2(0, 0, player->rmomx, player->rmomy)) >> ANGLETOFINESHIFT) & FINEMASK)) < FixedMul(player->maxdash, player->mo->scale)) +#else + if (player->speed < FixedMul(player->maxdash, player->mo->scale)) +#endif { player->drawangle = player->mo->angle; P_InstaThrust(player->mo, player->mo->angle, FixedMul(player->maxdash, player->mo->scale)); From 2e6898f29ed312b940ac1bbcce1fc6162c0ccf15 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 19 Jun 2019 23:20:24 +0100 Subject: [PATCH 027/128] PITY IN PINK! * Smoothen Pity Shield animation to go with sphere's updates to Nev3r's sprites. * Added LHRT object, designed to be summoned with CA2_MELEE. * Gives a pink Pity Shield (SH_PINK) on same-team player contact. * Deals damage to non-player enemies. * Harmlessly fades into nothing when touching an enemy player, players with SH_PINK already, and players capable of applying SH_PINK to others (through non-Lua methods). * Basically, you-know-who is the Healer of the party whenever they're around. Fun consequences for the Co-op and CTF metas. --- src/d_player.h | 1 + src/dehacked.c | 9 +++++++ src/hardware/hw_light.c | 1 + src/info.c | 49 ++++++++++++++++++++++++++++++------ src/info.h | 9 +++++++ src/p_inter.c | 56 +++++++++++++++++++++++++++++++++++------ src/p_map.c | 2 +- src/p_mobj.c | 7 ++++++ src/p_user.c | 51 ++++++++++++++++++++++++++++++++++--- src/r_things.c | 3 +++ 10 files changed, 170 insertions(+), 18 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index e68992e15..15cb14e80 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -196,6 +196,7 @@ typedef enum SH_PITY = 1, // the world's most basic shield ever, given to players who suck at Match SH_WHIRLWIND, SH_ARMAGEDDON, + SH_PINK, // PITY IN PINK! // Normal shields that use flags SH_ATTRACT = SH_PITY|SH_PROTECTELECTRIC, diff --git a/src/dehacked.c b/src/dehacked.c index b8417ea59..0fbdfbc31 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -6027,6 +6027,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_PITY4", "S_PITY5", "S_PITY6", + "S_PITY7", + "S_PITY8", + "S_PITY9", + "S_PITY10", + "S_PITY11", + "S_PITY12", "S_FIRS1", "S_FIRS2", @@ -6519,6 +6525,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_GOTFLAG", "S_CORK", + "S_LHRT", // Red Ring "S_RRNG1", @@ -7579,6 +7586,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_MACHINEAMBIENCE", "MT_CORK", + "MT_LHRT", // Ring Weapons "MT_REDRING", @@ -8342,6 +8350,7 @@ struct { {"SH_PITY",SH_PITY}, {"SH_WHIRLWIND",SH_WHIRLWIND}, {"SH_ARMAGEDDON",SH_ARMAGEDDON}, + {"SH_PINK",SH_PINK}, // normal shields that use flags {"SH_ATTRACT",SH_ATTRACT}, {"SH_ELEMENTAL",SH_ELEMENTAL}, diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 90d02fdf8..7efbc11d7 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -469,6 +469,7 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_GFLG &lspr[NOLIGHT], // SPR_CORK + &lspr[NOLIGHT], // SPR_LHRT // Ring Weapons &lspr[RINGLIGHT_L], // SPR_RRNG diff --git a/src/info.c b/src/info.c index f1d570fa0..4dbe2c31f 100644 --- a/src/info.c +++ b/src/info.c @@ -364,6 +364,7 @@ char sprnames[NUMSPRITES + 1][5] = "GFLG", // Got Flag sign "CORK", + "LHRT", // Ring Weapons "RRNG", // Red Ring @@ -2664,12 +2665,18 @@ state_t states[NUMSTATES] = {SPR_ELEM, FF_FULLBRIGHT|20, 1, {NULL}, 0, 0, S_ELEMF10}, // S_ELEMF9 {SPR_NULL, 0, 1, {NULL}, 0, 0, S_ELEMF1 }, // S_ELEMF10 - {SPR_PITY, FF_TRANS30 , 2, {NULL}, 0, 0, S_PITY2}, // S_PITY1 - {SPR_PITY, FF_TRANS30|1, 2, {NULL}, 0, 0, S_PITY3}, // S_PITY2 - {SPR_PITY, FF_TRANS30|2, 2, {NULL}, 0, 0, S_PITY4}, // S_PITY3 - {SPR_PITY, FF_TRANS20|3, 2, {NULL}, 0, 0, S_PITY5}, // S_PITY4 - {SPR_PITY, FF_TRANS30|4, 2, {NULL}, 0, 0, S_PITY6}, // S_PITY5 - {SPR_PITY, FF_TRANS20|5, 2, {NULL}, 0, 0, S_PITY1}, // S_PITY6 + {SPR_PITY, FF_TRANS30 , 2, {NULL}, 0, 0, S_PITY2}, // S_PITY1 + {SPR_PITY, FF_TRANS30| 1, 2, {NULL}, 0, 0, S_PITY3}, // S_PITY2 + {SPR_PITY, FF_TRANS30| 2, 2, {NULL}, 0, 0, S_PITY4}, // S_PITY3 + {SPR_PITY, FF_TRANS30| 3, 2, {NULL}, 0, 0, S_PITY5}, // S_PITY4 + {SPR_PITY, FF_TRANS30| 4, 2, {NULL}, 0, 0, S_PITY6}, // S_PITY5 + {SPR_PITY, FF_TRANS30| 5, 2, {NULL}, 0, 0, S_PITY7}, // S_PITY6 + {SPR_PITY, FF_TRANS30| 6, 2, {NULL}, 0, 0, S_PITY8}, // S_PITY7 + {SPR_PITY, FF_TRANS30| 7, 2, {NULL}, 0, 0, S_PITY9}, // S_PITY8 + {SPR_PITY, FF_TRANS30| 8, 2, {NULL}, 0, 0, S_PITY10}, // S_PITY9 + {SPR_PITY, FF_TRANS30| 9, 2, {NULL}, 0, 0, S_PITY11}, // S_PITY10 + {SPR_PITY, FF_TRANS30|10, 2, {NULL}, 0, 0, S_PITY12}, // S_PITY11 + {SPR_PITY, FF_TRANS30|11, 2, {NULL}, 0, 0, S_PITY1}, // S_PITY12 {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40 , 2, {NULL}, 0, 0, S_FIRS2}, // S_FIRS1 {SPR_FIRS, FF_FULLBRIGHT|FF_TRANS40|1, 2, {NULL}, 0, 0, S_FIRS3}, // S_FIRS2 @@ -3165,7 +3172,8 @@ state_t states[NUMSTATES] = // CTF Sign {SPR_GFLG, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_GOTFLAG - {SPR_CORK, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CORK + {SPR_CORK, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CORK + {SPR_LHRT, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LHRT // Red Rings (thrown) {SPR_RRNG, FF_FULLBRIGHT, 1, {A_ThrownRing}, 0, 0, S_RRNG2}, // S_RRNG1 @@ -16099,6 +16107,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_LHRT + -1, // doomednum + S_LHRT, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_SPRK1, // deathstate + S_SPRK1, // xdeathstate + sfx_None, // deathsound + 60*FRACUNIT, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 0, // display offset + 0, // mass + 1, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_MISSILE, // flags + S_NULL // raisestate + }, + { // MT_REDRING -1, // doomednum S_RRNG1, // spawnstate diff --git a/src/info.h b/src/info.h index 5482af60b..84b1a7ce1 100644 --- a/src/info.h +++ b/src/info.h @@ -595,6 +595,7 @@ typedef enum sprite SPR_GFLG, // Got Flag sign SPR_CORK, + SPR_LHRT, // Ring Weapons SPR_RRNG, // Red Ring @@ -2771,6 +2772,12 @@ typedef enum state S_PITY4, S_PITY5, S_PITY6, + S_PITY7, + S_PITY8, + S_PITY9, + S_PITY10, + S_PITY11, + S_PITY12, S_FIRS1, S_FIRS2, @@ -3263,6 +3270,7 @@ typedef enum state S_GOTFLAG, S_CORK, + S_LHRT, // Red Ring S_RRNG1, @@ -4343,6 +4351,7 @@ typedef enum mobj_type MT_MACHINEAMBIENCE, MT_CORK, + MT_LHRT, // Ring Weapons MT_REDRING, diff --git a/src/p_inter.c b/src/p_inter.c index 4cbd9185c..5a841807a 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2813,26 +2813,47 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou if (player->powers[pw_flashing] || player->powers[pw_invulnerability]) return false; - // Ignore IT players shooting each other, unless friendlyfire is on. - if ((player->pflags & PF_TAGIT && !((cv_friendlyfire.value || (damagetype & DMG_CANHURTSELF)) && - source && source->player && source->player->pflags & PF_TAGIT))) - return false; - // Don't allow any damage before the round starts. if (leveltime <= hidetime * TICRATE) return false; + // Ignore IT players shooting each other, unless friendlyfire is on. + if ((player->pflags & PF_TAGIT && !((cv_friendlyfire.value || (damagetype & DMG_CANHURTSELF)) && + source && source->player && source->player->pflags & PF_TAGIT))) + { + if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) + { + if (player->spinitem != MT_LHRT && player->revitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers. + { + P_SwitchShield(player, SH_PINK); + S_StartSound(target, mobjinfo[MT_PITY_ICON].seesound); + } + } + return false; + } + // Don't allow players on the same team to hurt one another, // unless cv_friendlyfire is on. if (!(cv_friendlyfire.value || (damagetype & DMG_CANHURTSELF)) && (player->pflags & PF_TAGIT) == (source->player->pflags & PF_TAGIT)) { - if (!(inflictor->flags & MF_FIRE)) + if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) + { + if (player->spinitem != MT_LHRT && player->revitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers. + { + P_SwitchShield(player, SH_PINK); + S_StartSound(target, mobjinfo[MT_PITY_ICON].seesound); + } + } + else if (!(inflictor->flags & MF_FIRE)) P_GivePlayerRings(player, 1); if (inflictor->flags2 & MF2_BOUNCERING) inflictor->fuse = 0; // bounce ring disappears at -1 not 0 return false; } + if (inflictor->type == MT_LHRT) + return false; + // The tag occurs so long as you aren't shooting another tagger with friendlyfire on. if (source->player->pflags & PF_TAGIT && !(player->pflags & PF_TAGIT)) { @@ -2899,7 +2920,17 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj // In COOP/RACE, you can't hurt other players unless cv_friendlyfire is on if (!cv_friendlyfire.value && (G_PlatformGametype())) + { + if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) + { + if (player->spinitem != MT_LHRT && player->revitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers. + { + P_SwitchShield(player, SH_PINK); + S_StartSound(target, mobjinfo[MT_PITY_ICON].seesound); + } + } return false; + } } // Tag handling @@ -2913,7 +2944,15 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj // unless cv_friendlyfire is on. if (!cv_friendlyfire.value && target->player->ctfteam == source->player->ctfteam) { - if (!(inflictor->flags & MF_FIRE)) + if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) + { + if (player->spinitem != MT_LHRT && player->revitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers. + { + P_SwitchShield(player, SH_PINK); + S_StartSound(target, mobjinfo[MT_PITY_ICON].seesound); + } + } + else if (!(inflictor->flags & MF_FIRE)) P_GivePlayerRings(target->player, 1); if (inflictor->flags2 & MF2_BOUNCERING) inflictor->fuse = 0; // bounce ring disappears at -1 not 0 @@ -2922,6 +2961,9 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj } } + if (inflictor->type == MT_LHRT) + return false; + // Add pity. if (!player->powers[pw_flashing] && !player->powers[pw_invulnerability] && !player->powers[pw_super] && source->player->score > player->score) diff --git a/src/p_map.c b/src/p_map.c index 3db3db4e3..97f7712f3 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1076,7 +1076,7 @@ static boolean PIT_CheckThing(mobj_t *thing) tmthing->y = thing->y; P_SetThingPosition(tmthing); } - else if (!(tmthing->type == MT_SHELL && thing->player)) // player collision handled in touchspecial + else if (!(tmthing->type == MT_SHELL && thing->player)) // player collision handled in touchspecial for shell { UINT8 damagetype = tmthing->info->mass; if (!damagetype && tmthing->flags & MF_FIRE) // BURN! diff --git a/src/p_mobj.c b/src/p_mobj.c index 70a40592d..f29da4ec5 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7861,6 +7861,10 @@ void P_MobjThinker(mobj_t *mobj) } } break; + case MT_LHRT: + mobj->momx = FixedMul(mobj->momx, (48*FRACUNIT)/50); + mobj->momy = FixedMul(mobj->momy, (48*FRACUNIT)/50); + break; case MT_EGGCAPSULE: if (!mobj->reactiontime) { @@ -8547,6 +8551,9 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s case MT_CYBRAKDEMON_NAPALM_BOMB_LARGE: P_SetMobjState(mobj, mobj->info->deathstate); break; + case MT_LHRT: + P_KillMobj(mobj, NULL, NULL, 0); + break; case MT_BLUEFLAG: case MT_REDFLAG: if (mobj->spawnpoint) diff --git a/src/p_user.c b/src/p_user.c index b879df48a..534f281ff 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1609,6 +1609,7 @@ void P_SpawnShieldOrb(player_t *player) orbtype = MT_ARMAGEDDON_ORB; break; case SH_PITY: + case SH_PINK: // PITY IN PINK orbtype = MT_PITY_ORB; break; case SH_FLAMEAURA: @@ -1639,7 +1640,13 @@ void P_SpawnShieldOrb(player_t *player) shieldobj = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, orbtype); shieldobj->flags2 |= MF2_SHIELD; P_SetTarget(&shieldobj->target, player->mo); - shieldobj->color = (UINT8)shieldobj->info->painchance; + if ((player->powers[pw_shield] & SH_NOSTACK) == SH_PINK) + { + shieldobj->color = SKINCOLOR_PINK; + shieldobj->colorized = true; + } + else + shieldobj->color = (UINT8)shieldobj->info->painchance; shieldobj->threshold = (player->powers[pw_shield] & SH_FORCE) ? SH_FORCE : (player->powers[pw_shield] & SH_NOSTACK); if (shieldobj->info->seestate) @@ -1787,6 +1794,9 @@ void P_SpawnThokMobj(player_t *player) if (player->spectator) return; + if (!type) + return; + if (type == MT_GHOST) mobj = P_SpawnGhostMobj(player->mo); // virtually does everything here for us else @@ -1847,6 +1857,9 @@ void P_SpawnSpinMobj(player_t *player, mobjtype_t type) if (player->spectator) return; + if (!type) + return; + if (type == MT_GHOST) mobj = P_SpawnGhostMobj(player->mo); // virtually does everything here for us else @@ -2002,10 +2015,42 @@ boolean P_PlayerHitFloor(player_t *player) } else if (player->charability2 == CA2_MELEE && (player->panim == PA_ABILITY2 && player->mo->state-states != S_PLAY_MELEE_LANDING)) { + mobjtype_t type = player->spinitem; P_SetPlayerMobjState(player->mo, S_PLAY_MELEE_LANDING); player->mo->tics = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS; S_StartSound(player->mo, sfx_s3k8b); player->pflags |= PF_FULLSTASIS; + + // hearticles + if (type) + { + UINT8 i = 0; + angle_t throwang = -(2*ANG30); + fixed_t xo = P_ReturnThrustX(player->mo, player->drawangle, 16*player->mo->scale); + fixed_t yo = P_ReturnThrustY(player->mo, player->drawangle, 16*player->mo->scale); + fixed_t zo = 6*player->mo->scale; + fixed_t mu = FixedMul(player->maxdash, player->mo->scale); + fixed_t mu2 = FixedHypot(player->mo->momx, player->mo->momy); + mobj_t *missile; + if (mu2 < mu) + mu2 = mu; + while (i < 5) + { + missile = P_SpawnMobjFromMobj(player->mo, xo, yo, zo, type); + P_SetTarget(&missile->target, player->mo); + missile->angle = throwang + player->drawangle; + P_Thrust(missile, player->drawangle + ANGLE_90, + P_ReturnThrustY(missile, throwang, mu)); // side to side component + P_Thrust(missile, player->drawangle, mu2); // forward component + P_SetObjectMomZ(missile, (4 + ((i&1)<<1))*FRACUNIT, true); + missile->fuse = TICRATE/2; + + i++; + throwang += ANG30; + } + if (mobjinfo[type].seesound) + S_StartSound(missile, missile->info->seesound); + } } else if (player->pflags & PF_JUMPED || !(player->pflags & PF_SPINNING) || player->powers[pw_tailsfly] || player->mo->state-states == S_PLAY_FLY_TIRED) @@ -9806,12 +9851,12 @@ void P_DoPityCheck(player_t *player) // Apply pity shield if available. if ((player->pity >= 3 || player->pity < 0) && player->powers[pw_shield] == SH_NONE) { + P_SwitchShield(player, SH_PITY); + if (player->pity > 0) S_StartSound(player->mo, mobjinfo[MT_PITY_ICON].seesound); player->pity = 0; - player->powers[pw_shield] = SH_PITY; - P_SpawnShieldOrb(player); } } diff --git a/src/r_things.c b/src/r_things.c index 115e49600..9b5cbc09a 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2704,6 +2704,9 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) player->revitem = skin->revitem < 0 ? (mobjtype_t)mobjinfo[MT_PLAYER].raisestate : (UINT32)skin->revitem; player->followitem = skin->followitem; + if (((player->powers[pw_shield] & SH_NOSTACK) == SH_PINK) && (player->spinitem == MT_LHRT)) // Healers can't keep their buff. + player->powers[pw_shield] &= SH_STACK; + player->actionspd = skin->actionspd; player->mindash = skin->mindash; player->maxdash = skin->maxdash; From 84ff2a57a177c16718ef2314a98aee5cea429f40 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 19 Jun 2019 23:29:39 +0100 Subject: [PATCH 028/128] As I wanted MI to do but he was too exhausted at the time from hardcoding, make the Fang bullet knockback less hardcoded and instead give it MF2_SUPERFIRE. --- src/p_inter.c | 8 ++------ src/p_mobj.c | 3 +++ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index 5a841807a..abe3a9061 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3423,14 +3423,10 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da return true; } } - else if (player->powers[pw_invulnerability] || player->powers[pw_flashing] // ignore bouncing & such in invulnerability - || player->powers[pw_super]) + else if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super]) // ignore bouncing & such in invulnerability { if (force - || (player->powers[pw_super] - && inflictor && inflictor->flags & MF_MISSILE && inflictor->flags2 & MF2_SUPERFIRE) // Super Sonic is stunned! - || (player->powers[pw_flashing] - && source && source->type == MT_FANG && inflictor && inflictor->type == MT_CORK)) // Fang's cork bullets knock you back even when flashing + || (inflictor && inflictor->flags & MF_MISSILE && inflictor->flags2 & MF2_SUPERFIRE)) // Super Sonic is stunned! { #ifdef HAVE_BLUA if (!LUAh_MobjDamage(target, inflictor, source, damage, damagetype)) diff --git a/src/p_mobj.c b/src/p_mobj.c index f29da4ec5..c4211be85 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9164,6 +9164,9 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) case MT_FANG: sc = 4; break; + case MT_CORK: + mobj->flags2 |= MF2_SUPERFIRE; + break; case MT_FBOMB: mobj->flags2 |= MF2_EXPLOSION; break; From f9e09ec31fe70efa7dab0e1ecb0205dd87bc4256 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 19 Jun 2019 23:35:18 +0100 Subject: [PATCH 029/128] Tweak Boss5MakeItRain's bomb launch angles to properly smash the ceiling in the new arena. --- src/p_enemy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 664e3b9b0..46669ad94 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -12414,7 +12414,7 @@ void A_Boss5MakeItRain(mobj_t *actor) actor->angle += ANGLE_45; var1 = locvar1; - var2 = offset + (i & 1) ? 55 : 70; + var2 = offset + (i & 1) ? 80 : 85; A_TrapShot(actor); } From 460632ad3b315e0e28edaf4c16b6d315d3c010b2 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 20 Jun 2019 00:24:13 +0100 Subject: [PATCH 030/128] Some preliminary work to make multiple bosses in the same map work nicely together, by allowing parameter to alter the linedef executor tag to call in increments of 100. Also: Making sure every single reserved tag is recorded as an LE_ constant. --- src/dehacked.c | 8 ++++++++ src/doomdef.h | 18 +++++++++++++----- src/info.c | 4 ++-- src/p_enemy.c | 40 +++++++++++++++++++++++++--------------- src/p_inter.c | 13 +++++++------ 5 files changed, 55 insertions(+), 28 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 0fbdfbc31..a3752ece5 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8228,6 +8228,14 @@ struct { {"LE_BOSSDEAD",LE_BOSSDEAD}, // A boss in the map died (Chaos mode boss tally) {"LE_BOSS4DROP",LE_BOSS4DROP}, // CEZ boss dropped its cage {"LE_BRAKVILEATACK",LE_BRAKVILEATACK}, // Brak's doing his LOS attack, oh noes + {"LE_TURRET",LE_TURRET}, // THZ turret + {"LE_BRAKPLATFORM",LE_BRAKPLATFORM}, // v2.0 Black Eggman destroys platform + {"LE_CAPSULE2",LE_CAPSULE2}, // Egg Capsule + {"LE_CAPSULE1",LE_CAPSULE1}, // Egg Capsule + {"LE_CAPSULE0",LE_CAPSULE0}, // Egg Capsule + {"LE_KOOPA",LE_KOOPA}, // Distant cousin to Gay Bowser + {"LE_AXE",LE_AXE}, // MKB Axe object + {"LE_PARAMWIDTH",LE_PARAMWIDTH}, // If an object that calls LinedefExecute has a nonzero parameter value, this times the parameter will be subtracted. (Mostly for the purpose of coexisting bosses...) /// \todo Get all this stuff into its own sections, maybe. Maybe. diff --git a/src/doomdef.h b/src/doomdef.h index 512c90f86..475328918 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -381,11 +381,19 @@ typedef enum // Special linedef executor tag numbers! enum { - LE_PINCHPHASE = -2, // A boss entered pinch phase (and, in most cases, is preparing their pinch phase attack!) - LE_ALLBOSSESDEAD = -3, // All bosses in the map are dead (Egg capsule raise) - LE_BOSSDEAD = -4, // A boss in the map died (Chaos mode boss tally) - LE_BOSS4DROP = -5, // CEZ boss dropped its cage - LE_BRAKVILEATACK = -6 // Brak's doing his LOS attack, oh noes + LE_PINCHPHASE = -2, // A boss entered pinch phase (and, in most cases, is preparing their pinch phase attack!) + LE_ALLBOSSESDEAD = -3, // All bosses in the map are dead (Egg capsule raise) + LE_BOSSDEAD = -4, // A boss in the map died (Chaos mode boss tally) + LE_BOSS4DROP = -5, // CEZ boss dropped its cage + LE_BRAKVILEATACK = -6, // Brak's doing his LOS attack, oh noes + LE_TURRET = 32000, // THZ turret + LE_BRAKPLATFORM = 4200, // v2.0 Black Eggman destroys platform + LE_CAPSULE2 = 682, // Egg Capsule + LE_CAPSULE1 = 681, // Egg Capsule + LE_CAPSULE0 = 680, // Egg Capsule + LE_KOOPA = 650, // Distant cousin to Gay Bowser + LE_AXE = 649, // MKB Axe object + LE_PARAMWIDTH = -100 // If an object that calls LinedefExecute has a nonzero parameter value, this times the parameter will be subtracted. (Mostly for the purpose of coexisting bosses...) }; // Name of local directory for config files and savegames diff --git a/src/info.c b/src/info.c index 4dbe2c31f..5a8633233 100644 --- a/src/info.c +++ b/src/info.c @@ -898,7 +898,7 @@ state_t states[NUMSTATES] = {SPR_TRET, FF_FULLBRIGHT|2, 7, {A_Pain}, 0, 0, S_TURRETSHOCK7}, // S_TURRETSHOCK6 {SPR_TRET, FF_FULLBRIGHT|3, 7, {NULL}, 0, 0, S_TURRETSHOCK8}, // S_TURRETSHOCK7 {SPR_TRET, FF_FULLBRIGHT|4, 7, {NULL}, 0, 0, S_TURRETSHOCK9}, // S_TURRETSHOCK8 - {SPR_TRET, FF_FULLBRIGHT|4, 7, {A_LinedefExecute}, 32000, 0, S_XPLD1}, // S_TURRETSHOCK9 + {SPR_TRET, FF_FULLBRIGHT|4, 7, {A_LinedefExecute}, LE_TURRET, 0, S_XPLD1}, // S_TURRETSHOCK9 {SPR_TURR, 0, 1, {A_Look}, 1, 0, S_TURRETPOPDOWN8}, // S_TURRETLOOK {SPR_TURR, 0, 0, {A_FaceTarget}, 0, 0, S_TURRETPOPUP1}, // S_TURRETSEE @@ -1501,7 +1501,7 @@ state_t states[NUMSTATES] = {SPR_BRAK, 21, 3*TICRATE, {NULL}, 0, 0, S_BLACKEGG_DESTROYPLAT2}, // S_BLACKEGG_DESTROYPLAT1 {SPR_BRAK, 21, 1, {A_PlaySound}, sfx_s3k54, 0, S_BLACKEGG_DESTROYPLAT3}, // S_BLACKEGG_DESTROYPLAT2 - {SPR_BRAK, 21, 14, {A_LinedefExecute}, 4200, 0, S_BLACKEGG_STND}, // S_BLACKEGG_DESTROYPLAT3 + {SPR_BRAK, 21, 14, {A_LinedefExecute}, LE_BRAKPLATFORM, 0, S_BLACKEGG_STND}, // S_BLACKEGG_DESTROYPLAT3 {SPR_NULL, 0, 1, {A_CapeChase}, (160 - 20) << 16, 0, S_BLACKEGG_HELPER}, // S_BLACKEGG_HELPER diff --git a/src/p_enemy.c b/src/p_enemy.c index 46669ad94..5de14e0a7 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3510,7 +3510,10 @@ void A_BossDeath(mobj_t *mo) return; #endif - P_LinedefExecute(LE_BOSSDEAD, mo, NULL); + if (mo->spawnpoint && mo->spawnpoint->extrainfo) + P_LinedefExecute(LE_BOSSDEAD+(mo->spawnpoint->extrainfo*LE_PARAMWIDTH), mo, NULL); + else + P_LinedefExecute(LE_BOSSDEAD, mo, NULL); mo->health = 0; // Boss is dead (but not necessarily fleeing...) @@ -3548,11 +3551,11 @@ void A_BossDeath(mobj_t *mo) else { // Bring the egg trap up to the surface - junk.tag = 680; + junk.tag = LE_CAPSULE0; EV_DoElevator(&junk, elevateHighest, false); - junk.tag = 681; + junk.tag = LE_CAPSULE1; EV_DoElevator(&junk, elevateUp, false); - junk.tag = 682; + junk.tag = LE_CAPSULE2; EV_DoElevator(&junk, elevateHighest, false); } @@ -3576,7 +3579,7 @@ bossjustdie: } case MT_KOOPA: { - junk.tag = 650; + junk.tag = LE_KOOPA; EV_DoCeiling(&junk, raiseToHighest); return; } @@ -3636,15 +3639,17 @@ bossjustdie: mo2 = (mobj_t *)th; - if (mo2->type == MT_BOSSFLYPOINT) - { - // If this one's closer then the last one, go for it. - if (!mo->target || - P_AproxDistance(P_AproxDistance(mo->x - mo2->x, mo->y - mo2->y), mo->z - mo2->z) < - P_AproxDistance(P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y), mo->z - mo->target->z)) - P_SetTarget(&mo->target, mo2); - // Otherwise... Don't! - } + if (mo2->type != MT_BOSSFLYPOINT) + continue; + + // If this one's further then the last one, don't go for it. + if (mo->target && + P_AproxDistance(P_AproxDistance(mo->x - mo2->x, mo->y - mo2->y), mo->z - mo2->z) > + P_AproxDistance(P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y), mo->z - mo->target->z)) + continue; + + // Otherwise... Do! + P_SetTarget(&mo->target, mo2); } mo->flags |= MF_NOGRAVITY|MF_NOCLIP; @@ -6390,7 +6395,10 @@ void A_Boss1Chase(mobj_t *actor) } else { - P_LinedefExecute(LE_PINCHPHASE, actor, NULL); + if (actor->spawnpoint && actor->spawnpoint->extrainfo) + P_LinedefExecute(LE_PINCHPHASE+(actor->spawnpoint->extrainfo*LE_PARAMWIDTH), actor, NULL); + else + P_LinedefExecute(LE_PINCHPHASE, actor, NULL); P_SetMobjState(actor, actor->info->raisestate); } @@ -7595,6 +7603,8 @@ void A_LinedefExecute(mobj_t *actor) if (locvar2) tagnum += locvar2*(AngleFixed(actor->angle)>>FRACBITS); + else if (actor->spawnpoint && actor->spawnpoint->extrainfo) + tagnum += (actor->spawnpoint->extrainfo*LE_PARAMWIDTH); CONS_Debug(DBG_GAMELOGIC, "A_LinedefExecute: Running mobjtype %d's sector with tag %d\n", actor->type, tagnum); diff --git a/src/p_inter.c b/src/p_inter.c index abe3a9061..a8e716123 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1353,7 +1353,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (player->bot) return; - junk.tag = 649; + junk.tag = LE_AXE; EV_DoElevator(&junk, bridgeFall, false); // scan the remaining thinkers to find koopa @@ -1363,11 +1363,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) continue; mo2 = (mobj_t *)th; - if (mo2->type == MT_KOOPA) - { - mo2->momz = 5*FRACUNIT; - break; - } + + if (mo2->type != MT_KOOPA) + continue; + + mo2->momz = 5*FRACUNIT; + break; } } break; From eac36e73a3a2199b7dcf917dc95396628013f1d0 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 20 Jun 2019 00:28:45 +0100 Subject: [PATCH 031/128] Correct some oversights where drawangle was incorrectly ignored. --- src/p_enemy.c | 18 +++++++++++++----- src/p_spec.c | 2 +- src/p_telept.c | 34 ++++++++++++++++++---------------- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 5de14e0a7..995635b3f 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -5977,7 +5977,7 @@ void A_MixUp(mobj_t *actor) else if (numplayers == 2) // Special case -- simple swap { fixed_t x, y, z; - angle_t angle; + angle_t angle, drawangle; INT32 one = -1, two = 0; // default value 0 to make the compiler shut up // Zoom tube stuff @@ -6027,6 +6027,7 @@ void A_MixUp(mobj_t *actor) y = players[one].mo->y; z = players[one].mo->z; angle = players[one].mo->angle; + drawangle = players[one].drawangle; starpostx = players[one].starpostx; starposty = players[one].starposty; @@ -6042,10 +6043,14 @@ void A_MixUp(mobj_t *actor) players[two].starpostnum, players[two].starposttime, players[two].starpostangle, players[two].mo->flags2); + players[one].drawangle = players[two].drawangle; + P_MixUp(players[two].mo, x, y, z, angle, starpostx, starposty, starpostz, starpostnum, starposttime, starpostangle, mflags2); + players[two].drawangle = drawangle; + //carry set after mixup. Stupid P_ResetPlayer() takes away some of the stuff we look for... //but not all of it! So we need to make sure they aren't set wrong or anything. players[one].powers[pw_carry] = carry2; @@ -6057,7 +6062,7 @@ void A_MixUp(mobj_t *actor) else { fixed_t position[MAXPLAYERS][3]; - angle_t anglepos[MAXPLAYERS]; + angle_t anglepos[MAXPLAYERS][2]; INT32 pindex[MAXPLAYERS], counter = 0, teleportfrom = 0; // Zoom tube stuff @@ -6076,7 +6081,7 @@ void A_MixUp(mobj_t *actor) for (i = 0; i < MAXPLAYERS; i++) { - position[i][0] = position[i][1] = position[i][2] = anglepos[i] = pindex[i] = -1; + position[i][0] = position[i][1] = position[i][2] = anglepos[i][0] = anglepos[i][1] = pindex[i] = -1; teleported[i] = false; } @@ -6092,7 +6097,8 @@ void A_MixUp(mobj_t *actor) position[counter][1] = players[i].mo->y; position[counter][2] = players[i].mo->z; pindex[counter] = i; - anglepos[counter] = players[i].mo->angle; + anglepos[counter][0] = players[i].mo->angle; + anglepos[counter][1] = players[i].drawangle; players[i].mo->momx = players[i].mo->momy = players[i].mo->momz = players[i].rmomx = players[i].rmomy = 1; players[i].cmomx = players[i].cmomy = 0; @@ -6144,11 +6150,13 @@ void A_MixUp(mobj_t *actor) players[i].speed = transspeed[teleportfrom]; P_SetTarget(&players[i].mo->tracer, transtracer[teleportfrom]); - P_MixUp(players[i].mo, position[teleportfrom][0], position[teleportfrom][1], position[teleportfrom][2], anglepos[teleportfrom], + P_MixUp(players[i].mo, position[teleportfrom][0], position[teleportfrom][1], position[teleportfrom][2], anglepos[teleportfrom][0], spposition[teleportfrom][0], spposition[teleportfrom][1], spposition[teleportfrom][2], starpostnum[teleportfrom], starposttime[teleportfrom], starpostangle[teleportfrom], flags2[teleportfrom]); + players[i].drawangle = anglepos[teleportfrom][1]; + //...carry after. same reasoning. players[i].powers[pw_carry] = transcarry[teleportfrom]; diff --git a/src/p_spec.c b/src/p_spec.c index e47b5cc03..1ec97a2f9 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4514,7 +4514,7 @@ DoneSection2: break; } - player->mo->angle = lineangle; + player->mo->angle = player->drawangle = lineangle; if (!demoplayback || P_AnalogMove(player)) { diff --git a/src/p_telept.c b/src/p_telept.c index 2e070d14b..3e135aee7 100644 --- a/src/p_telept.c +++ b/src/p_telept.c @@ -130,7 +130,7 @@ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle if (!dontstopmove) thing->momx = thing->momy = thing->momz = 0; else // Change speed to match direction - P_InstaThrust(thing, thing->angle, P_AproxDistance(thing->momx, thing->momy)); + P_InstaThrust(thing, angle, FixedHypot(thing->momx, thing->momy)); if (thing->player) { @@ -139,21 +139,6 @@ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle else thing->player->viewz = thing->z + thing->player->viewheight; - if (!dontstopmove) - thing->reactiontime = TICRATE/2; // don't move for about half a second - - // absolute angle position - if (thing->player == &players[consoleplayer]) - localangle = angle; - if (thing->player == &players[secondarydisplayplayer]) - localangle2 = angle; - - // move chasecam at new player location - if (splitscreen && camera2.chase && thing->player == &players[secondarydisplayplayer]) - P_ResetCamera(thing->player, &camera2); - else if (camera.chase && thing->player == &players[displayplayer]) - P_ResetCamera(thing->player, &camera); - // don't run in place after a teleport if (!dontstopmove) { @@ -171,7 +156,24 @@ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle thing->player->speed = 0; P_ResetPlayer(thing->player); P_SetPlayerMobjState(thing, S_PLAY_STND); + + thing->reactiontime = TICRATE/2; // don't move for about half a second + thing->player->drawangle = angle; } + else + thing->player->drawangle += (angle - thing->angle); + + // absolute angle position + if (thing->player == &players[consoleplayer]) + localangle = angle; + if (thing->player == &players[secondarydisplayplayer]) + localangle2 = angle; + + // move chasecam at new player location + if (splitscreen && camera2.chase && thing->player == &players[secondarydisplayplayer]) + P_ResetCamera(thing->player, &camera2); + else if (camera.chase && thing->player == &players[displayplayer]) + P_ResetCamera(thing->player, &camera); if (flash) P_FlashPal(thing->player, PAL_MIXUP, 10); From f182bb867f30c4c4e58e14cf2cae06479ec94101 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 20 Jun 2019 15:34:27 +0100 Subject: [PATCH 032/128] HUD stuff. * Re-fix chat HUD position, and make it not move in match (which it needed to do in 2.1). * Fix HU_drawPing for the new palette. * Change the condition for greying out players, since the current one was buggy. * Allow for tokens on the coop MP HUD, and use the small emeralds so there's space for them. * Fix the mapping between skincolours and name colours in new chat, specifically to take into account every possible text colour (as opposed to the port previously done, which only used the 2.1 text colours and looked like ass as a result). --- src/dehacked.c | 2 + src/hu_stuff.c | 200 +++++++++++++++++++++++++++++++++++-------------- 2 files changed, 146 insertions(+), 56 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index a3752ece5..e90329417 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -8688,6 +8688,7 @@ struct { {"V_6WIDTHSPACE",V_6WIDTHSPACE}, {"V_OLDSPACING",V_OLDSPACING}, {"V_MONOSPACE",V_MONOSPACE}, + {"V_MAGENTAMAP",V_MAGENTAMAP}, {"V_YELLOWMAP",V_YELLOWMAP}, {"V_GREENMAP",V_GREENMAP}, @@ -8703,6 +8704,7 @@ struct { {"V_BROWNMAP",V_BROWNMAP}, {"V_ROSYMAP",V_ROSYMAP}, {"V_INVERTMAP",V_INVERTMAP}, + {"V_TRANSLUCENT",V_TRANSLUCENT}, {"V_10TRANS",V_10TRANS}, {"V_20TRANS",V_20TRANS}, diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 1a77774c8..a4eeafc6c 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -751,40 +751,102 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) cstart = "\x83"; // Follow palette order at r_draw.c Color_Names - if (color <= SKINCOLOR_SILVER - || color == SKINCOLOR_AETHER) - cstart = "\x80"; // White - else if (color <= SKINCOLOR_BLACK - || color == SKINCOLOR_SLATE) - cstart = "\x86"; // Grey - else if (color <= SKINCOLOR_YOGURT) - cstart = "\x85"; // Red - else if (color <= SKINCOLOR_BEIGE) - cstart = "\x86"; // Grey - else if (color <= SKINCOLOR_LAVENDER) - cstart = "\x81"; // Purple - else if (color <= SKINCOLOR_PEACHY) - cstart = "\x85"; // Red - else if (color <= SKINCOLOR_RUST) - cstart = "\x87"; // Orange - else if (color == SKINCOLOR_GOLD - || color == SKINCOLOR_YELLOW) - cstart = "\x82"; // Yellow - else if (color == SKINCOLOR_SANDY - || color == SKINCOLOR_OLIVE) - cstart = "\x81"; // Purple - else if (color <= SKINCOLOR_MINT) - cstart = "\x83"; // Green - else if (color <= SKINCOLOR_DUSK) - cstart = "\x84"; // Blue - else if (color == SKINCOLOR_PINK - || color == SKINCOLOR_PASTEL - || color == SKINCOLOR_BUBBLEGUM - || color == SKINCOLOR_MAGENTA - || color == SKINCOLOR_ROSY) - cstart = "\x85"; // Red - else if (color <= SKINCOLOR_PLUM) - cstart = "\x81"; // Purple + switch (color) + { + default: + case SKINCOLOR_WHITE: + case SKINCOLOR_BONE: + case SKINCOLOR_CLOUDY: + case SKINCOLOR_GREY: + case SKINCOLOR_SILVER: + case SKINCOLOR_AETHER: + case SKINCOLOR_SLATE: + cstart = "\x80"; // white + break; + case SKINCOLOR_CARBON: + case SKINCOLOR_JET: + case SKINCOLOR_BLACK: + cstart = "\x86"; // V_GRAYMAP + break; + case SKINCOLOR_PINK: + case SKINCOLOR_RUBY: + case SKINCOLOR_SALMON: + case SKINCOLOR_RED: + case SKINCOLOR_CRIMSON: + case SKINCOLOR_FLAME: + cstart = "\x85"; // V_REDMAP + break; + case SKINCOLOR_YOGURT: + case SKINCOLOR_BROWN: + case SKINCOLOR_TAN: + case SKINCOLOR_BEIGE: + case SKINCOLOR_QUAIL: + cstart = "\x8d"; // V_BROWNMAP + break; + case SKINCOLOR_MOSS: + case SKINCOLOR_GREEN: + case SKINCOLOR_FOREST: + case SKINCOLOR_EMERALD: + case SKINCOLOR_MINT: + cstart = "\x83"; // V_GREENMAP + break; + case SKINCOLOR_AZURE: + cstart = "\x8c"; // V_AZUREMAP + break; + case SKINCOLOR_LAVENDER: + case SKINCOLOR_PASTEL: + case SKINCOLOR_PURPLE: + cstart = "\x89"; // V_PURPLEMAP + break; + case SKINCOLOR_PEACHY: + case SKINCOLOR_LILAC: + case SKINCOLOR_PLUM: + case SKINCOLOR_ROSY: + cstart = "\x8e"; // V_ROSYMAP + break; + case SKINCOLOR_SUNSET: + case SKINCOLOR_APRICOT: + case SKINCOLOR_ORANGE: + case SKINCOLOR_RUST: + cstart = "\x87"; // V_ORANGEMAP + break; + case SKINCOLOR_GOLD: + case SKINCOLOR_SANDY: + case SKINCOLOR_YELLOW: + case SKINCOLOR_OLIVE: + cstart = "\x82"; // V_YELLOWMAP + break; + case SKINCOLOR_LIME: + case SKINCOLOR_PERIDOT: + cstart = "\x8b"; // V_PERIDOTMAP + break; + case SKINCOLOR_SEAFOAM: + case SKINCOLOR_AQUA: + cstart = "\x8a"; // V_AQUAMAP + break; + case SKINCOLOR_TEAL: + case SKINCOLOR_WAVE: + case SKINCOLOR_CYAN: + case SKINCOLOR_SKY: + case SKINCOLOR_CERULEAN: + case SKINCOLOR_ICY: + case SKINCOLOR_SAPPHIRE: + case SKINCOLOR_VAPOR: + cstart = "\x88"; // V_SKYMAP + break; + case SKINCOLOR_CORNFLOWER: + case SKINCOLOR_BLUE: + case SKINCOLOR_COBALT: + case SKINCOLOR_DUSK: + cstart = "\x84"; // V_BLUEMAP + break; + case SKINCOLOR_BUBBLEGUM: + case SKINCOLOR_MAGENTA: + case SKINCOLOR_NEON: + case SKINCOLOR_VIOLET: + cstart = "\x81"; // V_MAGENTAMAP + break; + } } prefix = cstart; @@ -1327,7 +1389,7 @@ static char *CHAT_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) // 30/7/18: chaty is now the distance at which the lowest point of the chat will be drawn if that makes any sense. -INT16 chatx = 14, chaty = 180; // let's use this as our coordinates +INT16 chatx = 13, chaty = 169; // let's use this as our coordinates // chat stuff by VincyTM LOL XD! @@ -1506,7 +1568,6 @@ static void HU_drawChatLog(INT32 offset) //y += 16; } #endif - y -= (G_RingSlingerGametype() ? 16 : 0); chat_topy = y + chat_scroll*charheight; chat_bottomy = chat_topy + boxh*charheight; @@ -2229,7 +2290,7 @@ void HU_Erase(void) //====================================================================== #define supercheckdef ((players[tab[i].num].powers[pw_super] && players[tab[i].num].mo && (players[tab[i].num].mo->state < &states[S_PLAY_SUPER_TRANS1] || players[tab[i].num].mo->state >= &states[S_PLAY_SUPER_TRANS6])) || (players[tab[i].num].powers[pw_carry] == CR_NIGHTSMODE && skins[players[tab[i].num].skin].flags & SF_SUPER)) -#define greycheckdef ((players[tab[i].num].mo && ((players[tab[i].num].rings <= 0 && !(maptol & TOL_NIGHTS)) || (players[tab[i].num].spheres <= 0 && (maptol & TOL_NIGHTS)))) || players[tab[i].num].spectator) +#define greycheckdef (players[tab[i].num].spectator || players[tab[i].num].playerstate == PST_DEAD || (G_IsSpecialStage(gamemap) && players[tab[i].num].exiting)) // // HU_drawPing @@ -2237,7 +2298,7 @@ void HU_Erase(void) void HU_drawPing(INT32 x, INT32 y, INT32 ping, boolean notext) { UINT8 numbars = 1; // how many ping bars do we draw? - UINT8 barcolor = 128; // color we use for the bars (green, yellow or red) + UINT8 barcolor = 35; // color we use for the bars (green, yellow or red) SINT8 i = 0; SINT8 yoffset = 6; INT32 dx = x+1 - (V_SmallStringWidth(va("%dms", ping), V_ALLOWLOWERCASE)/2); @@ -2245,12 +2306,12 @@ void HU_drawPing(INT32 x, INT32 y, INT32 ping, boolean notext) if (ping < 128) { numbars = 3; - barcolor = 184; + barcolor = 112; } else if (ping < 256) { numbars = 2; // Apparently ternaries w/ multiple statements don't look good in C so I decided against it. - barcolor = 103; + barcolor = 73; } if (!notext || vid.width >= 640) // how sad, we're using a shit resolution. @@ -2414,6 +2475,7 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer) INT32 redplayers = 0, blueplayers = 0; const UINT8 *colormap; char name[MAXPLAYERNAME+1]; + boolean greycheck, supercheck; V_DrawFill(160, 26, 1, 154, 0); //Draw a vertical line to separate the two teams. V_DrawFill(1, 26, 318, 1, 0); //And a horizontal line to make a T. @@ -2424,6 +2486,9 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer) if (players[tab[i].num].spectator) continue; //ignore them. + greycheck = greycheckdef; + supercheck = supercheckdef; + if (tab[i].color == skincolor_redteam) //red { redplayers++; @@ -2439,10 +2504,13 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer) else //er? not on red or blue, so ignore them continue; + greycheck = greycheckdef; + supercheck = supercheckdef; + strlcpy(name, tab[i].name, 8); V_DrawString(x + 10, y, ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) - | (((players[tab[i].num].rings > 0 && !(maptol & TOL_NIGHTS)) || (players[tab[i].num].spheres > 0 && (maptol & TOL_NIGHTS))) ? 0 : V_TRANSLUCENT) + | (greycheck ? 0 : V_TRANSLUCENT) | V_ALLOWLOWERCASE, name); if (gametype == GT_CTF) @@ -2454,13 +2522,19 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer) } // Draw emeralds - if (!players[tab[i].num].powers[pw_super] + if (players[tab[i].num].powers[pw_invulnerability] && (players[tab[i].num].powers[pw_invulnerability] == players[tab[i].num].powers[pw_sneakers]) && ((leveltime/7) & 1)) + { + HU_Draw32Emeralds(x+60, y+2, 255); + //HU_DrawEmeralds(x-12,y+2,255); + } + else if (!players[tab[i].num].powers[pw_super] || ((leveltime/7) & 1)) { HU_Draw32Emeralds(x+60, y+2, tab[i].emeralds); + //HU_DrawEmeralds(x-12,y+2,tab[i].emeralds); } - if (players[tab[i].num].powers[pw_super]) + if (supercheck) { colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE); V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT/4, 0, superprefix[players[tab[i].num].skin], colormap); @@ -2468,12 +2542,12 @@ static void HU_Draw32TeamTabRankings(playersort_t *tab, INT32 whiteplayer) else { colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE); - if ((players[tab[i].num].rings <= 0 && !(maptol & TOL_NIGHTS)) || (players[tab[i].num].spheres <= 0 && (maptol & TOL_NIGHTS))) + if (players[tab[i].num].spectator || players[tab[i].num].playerstate == PST_DEAD) V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT/4, V_HUDTRANSHALF, faceprefix[players[tab[i].num].skin], colormap); else V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT/4, 0, faceprefix[players[tab[i].num].skin], colormap); } - V_DrawRightAlignedThinString(x+128, y, (((players[tab[i].num].rings > 0 && !(maptol & TOL_NIGHTS)) || (players[tab[i].num].spheres > 0 && (maptol & TOL_NIGHTS))) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); + V_DrawRightAlignedThinString(x+128, y, ((players[tab[i].num].spectator || players[tab[i].num].playerstate == PST_DEAD) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); if (!splitscreen) { if (!(tab[i].num == serverplayer)) @@ -2722,6 +2796,7 @@ static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scor INT32 i; const UINT8 *colormap; char name[MAXPLAYERNAME+1]; + boolean greycheck, supercheck; V_DrawFill(160, 26, 1, 154, 0); //Draw a vertical line to separate the two sides. V_DrawFill(1, 26, 318, 1, 0); //And a horizontal line to make a T. @@ -2729,9 +2804,12 @@ static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scor for (i = 0; i < scorelines; i++) { - if (players[tab[i].num].spectator) + if (players[tab[i].num].spectator && gametype != GT_COOP) continue; //ignore them. + greycheck = greycheckdef; + supercheck = supercheckdef; + strlcpy(name, tab[i].name, 7); if (!splitscreen) // don't draw it on splitscreen, { @@ -2743,7 +2821,7 @@ static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scor V_DrawString(x + 10, y, ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) - | (((players[tab[i].num].rings > 0 && !(maptol & TOL_NIGHTS)) || (players[tab[i].num].spheres > 0 && (maptol & TOL_NIGHTS))) ? 0 : V_TRANSLUCENT) + | (greycheck ? 0 : V_TRANSLUCENT) | V_ALLOWLOWERCASE, name); if (G_GametypeUsesLives()) //show lives @@ -2752,7 +2830,7 @@ static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scor V_DrawFixedPatch((x-10)*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, tagico, 0); // Draw emeralds - if (players[tab[i].num].powers[pw_invulnerability] && players[tab[i].num].powers[pw_invulnerability] && (players[tab[i].num].powers[pw_invulnerability] == players[tab[i].num].powers[pw_sneakers]) && ((leveltime/7) & 1)) + if (players[tab[i].num].powers[pw_invulnerability] && (players[tab[i].num].powers[pw_invulnerability] == players[tab[i].num].powers[pw_sneakers]) && ((leveltime/7) & 1)) { HU_Draw32Emeralds(x+60, y+2, 255); //HU_DrawEmeralds(x-12,y+2,255); @@ -2772,7 +2850,7 @@ static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scor V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT/4, 0, superprefix[players[tab[i].num].skin], 0); else { - if ((players[tab[i].num].rings <= 0 && !(maptol & TOL_NIGHTS)) || (players[tab[i].num].spheres <= 0 && (maptol & TOL_NIGHTS))) + if (greycheck) V_DrawFixedPatch(x*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, V_HUDTRANSHALF, faceprefix[players[tab[i].num].skin], 0); else V_DrawFixedPatch(x*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, faceprefix[players[tab[i].num].skin], 0); @@ -2780,7 +2858,7 @@ static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scor } else { - if (players[tab[i].num].powers[pw_super]) + if (supercheck) { colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE); V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT/4, 0, superprefix[players[tab[i].num].skin], colormap); @@ -2788,7 +2866,7 @@ static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scor else { colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE); - if ((players[tab[i].num].rings <= 0 && !(maptol & TOL_NIGHTS)) || (players[tab[i].num].spheres <= 0 && (maptol & TOL_NIGHTS))) + if (greycheck) V_DrawFixedPatch(x*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, V_HUDTRANSHALF, faceprefix[players[tab[i].num].skin], colormap); else V_DrawFixedPatch(x*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, faceprefix[players[tab[i].num].skin], colormap); @@ -2803,13 +2881,13 @@ static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scor if (players[tab[i].num].exiting) V_DrawRightAlignedThinString(x+128, y, 0, va("%i:%02i.%02i", G_TicsToMinutes(players[tab[i].num].realtime,true), G_TicsToSeconds(players[tab[i].num].realtime), G_TicsToCentiseconds(players[tab[i].num].realtime))); else - V_DrawRightAlignedThinString(x+128, y, (((players[tab[i].num].rings > 0 && !(maptol & TOL_NIGHTS)) || (players[tab[i].num].spheres > 0 && (maptol & TOL_NIGHTS))) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); + V_DrawRightAlignedThinString(x+128, y, (greycheck ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); } else - V_DrawRightAlignedThinString(x+128, y, (((players[tab[i].num].rings > 0 && !(maptol & TOL_NIGHTS)) || (players[tab[i].num].spheres > 0 && (maptol & TOL_NIGHTS))) ? 0 : V_TRANSLUCENT), va("%i:%02i.%02i", G_TicsToMinutes(tab[i].count,true), G_TicsToSeconds(tab[i].count), G_TicsToCentiseconds(tab[i].count))); + V_DrawRightAlignedThinString(x+128, y, (greycheck ? 0 : V_TRANSLUCENT), va("%i:%02i.%02i", G_TicsToMinutes(tab[i].count,true), G_TicsToSeconds(tab[i].count), G_TicsToCentiseconds(tab[i].count))); } else - V_DrawRightAlignedThinString(x+128, y, (((players[tab[i].num].rings > 0 && !(maptol & TOL_NIGHTS)) || (players[tab[i].num].spheres > 0 && (maptol & TOL_NIGHTS))) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); + V_DrawRightAlignedThinString(x+128, y, (greycheck ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); y += 9; if (i == 16) @@ -3045,7 +3123,7 @@ static void HU_DrawRankings(void) // shush, we'll do it anyway. if (G_GametypeHasTeams()) - HU_DrawTeamTabRankings(tab, whiteplayer); //separate function for Spazzo's silly request + HU_DrawTeamTabRankings(tab, whiteplayer); else if (scorelines <= 9 && !cv_compactscoreboard.value) HU_DrawTabRankings(40, 32, tab, scorelines, whiteplayer); else if (scorelines <= 20 && !cv_compactscoreboard.value) @@ -3104,6 +3182,16 @@ static void HU_DrawNetplayCoopOverlay(void) { int i; + if (token +#ifdef HAVE_BLUA + && LUA_HudEnabled(hud_tokens) +#endif + ) + { + V_DrawString(168, 10, 0, va("- %d", token)); + V_DrawSmallScaledPatch(148, 6, 0, tokenicon); + } + #ifdef HAVE_BLUA if (!LUA_HudEnabled(hud_coopemeralds)) return; @@ -3112,7 +3200,7 @@ static void HU_DrawNetplayCoopOverlay(void) for (i = 0; i < 7; ++i) { if (emeralds & (1 << i)) - V_DrawScaledPatch(20 + (i * 20), 6, 0, emeraldpics[0][i]); + V_DrawScaledPatch(20 + (i * 10), 9, 0, emeraldpics[1][i]); } } From f7fe418f7c6819897a287a1ad5f0d3cb4ecec568 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 20 Jun 2019 23:43:05 +0100 Subject: [PATCH 033/128] Slight buff to MT_LHRT. --- src/p_mobj.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index c4211be85..9b25ba473 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7862,8 +7862,8 @@ void P_MobjThinker(mobj_t *mobj) } break; case MT_LHRT: - mobj->momx = FixedMul(mobj->momx, (48*FRACUNIT)/50); - mobj->momy = FixedMul(mobj->momy, (48*FRACUNIT)/50); + mobj->momx = FixedMul(mobj->momx, (49*FRACUNIT)/50); + mobj->momy = FixedMul(mobj->momy, (49*FRACUNIT)/50); break; case MT_EGGCAPSULE: if (!mobj->reactiontime) From 3597b1c4857c0e74289f01f132c7e9aab45a348a Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 21 Jun 2019 00:43:03 +0100 Subject: [PATCH 034/128] Make minor adjustments to the CA2_MELEE and CA_TWINSPIN stuff. --- src/info.c | 4 ++-- src/p_user.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/info.c b/src/info.c index 5a8633233..0dc0797c9 100644 --- a/src/info.c +++ b/src/info.c @@ -724,10 +724,10 @@ state_t states[NUMSTATES] = {SPR_PLAY, SPR2_FIRE, 15, {NULL}, S_PLAY_STND, 0, S_PLAY_STND}, // S_PLAY_FIRE_FINISH // CA_TWINSPIN - {SPR_PLAY, SPR2_TWIN|FF_SPR2ENDSTATE, 1, {NULL}, S_PLAY_JUMP, 0, S_PLAY_TWINSPIN}, // S_PLAY_TWINSPIN + {SPR_PLAY, SPR2_TWIN|FF_SPR2ENDSTATE, 2, {NULL}, S_PLAY_JUMP, 0, S_PLAY_TWINSPIN}, // S_PLAY_TWINSPIN // CA2_MELEE - {SPR_PLAY, SPR2_MLEE|FF_SPR2ENDSTATE, 1, {NULL}, S_PLAY_MELEE_FINISH, 0, S_PLAY_MELEE}, // S_PLAY_MELEE + {SPR_PLAY, SPR2_MLEE|FF_SPR2ENDSTATE, 2, {NULL}, S_PLAY_MELEE_FINISH, 0, S_PLAY_MELEE}, // S_PLAY_MELEE {SPR_PLAY, SPR2_MLEE, 70, {NULL}, 0, 0, S_PLAY_FALL}, // S_PLAY_MELEE_FINISH {SPR_PLAY, SPR2_MLEL, 35, {NULL}, 0, 0, S_PLAY_WALK}, // S_PLAY_MELEE_LANDING diff --git a/src/p_user.c b/src/p_user.c index 534f281ff..ae4876221 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2015,7 +2015,7 @@ boolean P_PlayerHitFloor(player_t *player) } else if (player->charability2 == CA2_MELEE && (player->panim == PA_ABILITY2 && player->mo->state-states != S_PLAY_MELEE_LANDING)) { - mobjtype_t type = player->spinitem; + mobjtype_t type = player->revitem; P_SetPlayerMobjState(player->mo, S_PLAY_MELEE_LANDING); player->mo->tics = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS; S_StartSound(player->mo, sfx_s3k8b); From d5e91ed8d77277fd355c15ab62d37193205fb5ea Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 21 Jun 2019 12:35:37 +0100 Subject: [PATCH 035/128] Don't give SH_PINK in Race/Competition. They're your opponents! --- src/p_inter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_inter.c b/src/p_inter.c index a8e716123..49916c858 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2922,7 +2922,7 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj // In COOP/RACE, you can't hurt other players unless cv_friendlyfire is on if (!cv_friendlyfire.value && (G_PlatformGametype())) { - if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) + if (gametype == GT_COOP && inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) // co-op only { if (player->spinitem != MT_LHRT && player->revitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers. { From 50e4a65f99f8ae57dcb453f791ec1c3352eafce0 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 21 Jun 2019 12:51:55 +0100 Subject: [PATCH 036/128] Correct some more oversights of switching to revitem for CA2_MELEE's particles. --- src/p_enemy.c | 3 +++ src/p_inter.c | 8 ++++---- src/r_things.c | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 995635b3f..07d1b9746 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -6329,6 +6329,9 @@ void A_RecyclePowers(mobj_t *actor) players[recv_pl].ringweapons = weapons[send_pl]; players[recv_pl].currentweapon = weaponheld[send_pl]; + if (((players[recv_pl].powers[pw_shield] & SH_NOSTACK) == SH_PINK) && (players[recv_pl].revitem == MT_LHRT)) // Healers can't keep their buff. + players[recv_pl].powers[pw_shield] &= SH_STACK; + P_SpawnShieldOrb(&players[recv_pl]); if (P_IsLocalPlayer(&players[recv_pl])) P_RestoreMusic(&players[recv_pl]); diff --git a/src/p_inter.c b/src/p_inter.c index 49916c858..81f046e2e 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2824,7 +2824,7 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou { if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) { - if (player->spinitem != MT_LHRT && player->revitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers. + if (player->revitem != MT_LHRT) // Healers do not get to heal other healers. { P_SwitchShield(player, SH_PINK); S_StartSound(target, mobjinfo[MT_PITY_ICON].seesound); @@ -2839,7 +2839,7 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou { if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) { - if (player->spinitem != MT_LHRT && player->revitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers. + if (player->revitem != MT_LHRT) // Healers do not get to heal other healers. { P_SwitchShield(player, SH_PINK); S_StartSound(target, mobjinfo[MT_PITY_ICON].seesound); @@ -2924,7 +2924,7 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj { if (gametype == GT_COOP && inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) // co-op only { - if (player->spinitem != MT_LHRT && player->revitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers. + if (player->revitem != MT_LHRT) // Healers do not get to heal other healers. { P_SwitchShield(player, SH_PINK); S_StartSound(target, mobjinfo[MT_PITY_ICON].seesound); @@ -2947,7 +2947,7 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj { if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) { - if (player->spinitem != MT_LHRT && player->revitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers. + if (player->revitem != MT_LHRT) // Healers do not get to heal other healers. { P_SwitchShield(player, SH_PINK); S_StartSound(target, mobjinfo[MT_PITY_ICON].seesound); diff --git a/src/r_things.c b/src/r_things.c index 9b5cbc09a..22c3d96c9 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2704,7 +2704,7 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) player->revitem = skin->revitem < 0 ? (mobjtype_t)mobjinfo[MT_PLAYER].raisestate : (UINT32)skin->revitem; player->followitem = skin->followitem; - if (((player->powers[pw_shield] & SH_NOSTACK) == SH_PINK) && (player->spinitem == MT_LHRT)) // Healers can't keep their buff. + if (((player->powers[pw_shield] & SH_NOSTACK) == SH_PINK) && (player->revitem == MT_LHRT)) // Healers can't keep their buff. player->powers[pw_shield] &= SH_STACK; player->actionspd = skin->actionspd; From 02e315a4ee83b3a10e049d56ab7dbdd47f35c8b0 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 22 Jun 2019 16:44:32 +0100 Subject: [PATCH 037/128] Add HUD icon for Pink shield. (Don't worry, this is my last expected commit in this branch. Gonna cherry pick everything unrelated to the Pink shield into a bunch of other branches now.) --- src/st_stuff.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/st_stuff.c b/src/st_stuff.c index f0f40ed32..1cf221bc9 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -95,6 +95,7 @@ static patch_t *ringshield; static patch_t *watershield; static patch_t *bombshield; static patch_t *pityshield; +static patch_t *pinkshield; static patch_t *flameshield; static patch_t *bubbleshield; static patch_t *thundershield; @@ -285,6 +286,7 @@ void ST_LoadGraphics(void) watershield = W_CachePatchName("TVELICON", PU_HUDGFX); bombshield = W_CachePatchName("TVARICON", PU_HUDGFX); pityshield = W_CachePatchName("TVPIICON", PU_HUDGFX); + pinkshield = W_CachePatchName("TVPPICON", PU_HUDGFX); flameshield = W_CachePatchName("TVFLICON", PU_HUDGFX); bubbleshield = W_CachePatchName("TVBBICON", PU_HUDGFX); thundershield = W_CachePatchName("TVZPICON", PU_HUDGFX); @@ -1250,6 +1252,7 @@ static void ST_drawPowerupHUD(void) case SH_ARMAGEDDON: p = bombshield; break; case SH_ATTRACT: p = ringshield; break; case SH_PITY: p = pityshield; break; + case SH_PINK: p = pinkshield; break; case SH_FLAMEAURA: p = flameshield; break; case SH_BUBBLEWRAP: p = bubbleshield; break; case SH_THUNDERCOIN: p = thundershield; break; From 29c4fa306ac79546fa78621548bacc84ff37dc62 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 22 Jun 2019 17:23:04 +0100 Subject: [PATCH 038/128] Realised I forgot to do this. Without this commit, the drawangle update stuff is useless :V --- src/p_telept.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_telept.c b/src/p_telept.c index 3e135aee7..e80dd0428 100644 --- a/src/p_telept.c +++ b/src/p_telept.c @@ -125,8 +125,6 @@ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle if (!P_TeleportMove(thing, x, y, z)) return false; - thing->angle = angle; - if (!dontstopmove) thing->momx = thing->momy = thing->momz = 0; else // Change speed to match direction @@ -179,5 +177,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; + return true; } From b02c21b818bf61c003ed66cfd7ab69d118196ee1 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 22 Jun 2019 20:15:48 +0100 Subject: [PATCH 039/128] Remove some more 2.1-related ringslinger offsets to the chat. --- src/hu_stuff.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/hu_stuff.c b/src/hu_stuff.c index a4eeafc6c..f86100e27 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -1468,7 +1468,6 @@ static void HU_drawMiniChat(void) if (splitscreen > 1) y += 16; }*/ - y -= (G_RingSlingerGametype() ? 16 : 0); dx = 0; dy = 0; @@ -1677,7 +1676,6 @@ static void HU_DrawChat(void) } } #endif - y -= (G_RingSlingerGametype() ? 16 : 0); if (teamtalk) { @@ -1770,7 +1768,6 @@ static void HU_DrawChat(void) p_dispy += 16; } #endif - p_dispy -= (G_RingSlingerGametype() ? 16 : 0); i = 0; for(i=0; (i Date: Wed, 26 Jun 2019 23:26:05 +0100 Subject: [PATCH 040/128] Now it's CA_TWINSPIN's turn to get the improvements! * Remove PF_THOKKED every time a successful damage bounce occours. * When this happens, spawn a number of particles based on thokitem at half scale! (Optimised, again, for MT_LHRT.) * Also spawn these particles when a successful spring boost occours, as well as playing a twisted spring sound. Also, some other related tweaks: * Optimisations to A_VultureBlast, which was used as a base for the particle creation. * Make the Metal Sonic boss use P_PlayerCanDamage instead of a custom, somewhat broken player damage detection mechanism. * P_SpawnGhostMobj takes colorized into account. * Fold Tails propeller damage into P_PlayerCanDamage. * When performing an Attraction Blast, place the player in roll frames. * Update all conditions preventing SH_PINK to incorporate thokitem and spinitem as well. * Buff MT_LHRT travel distance at slow speeds. --- src/p_enemy.c | 15 ++++++++---- src/p_inter.c | 22 ++++++----------- src/p_local.h | 1 + src/p_map.c | 27 ++++++++++++++++++--- src/p_mobj.c | 40 ++++++++++++++---------------- src/p_user.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++--- src/r_things.c | 2 +- src/sounds.c | 1 + src/sounds.h | 1 + 9 files changed, 126 insertions(+), 49 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 95138a3fa..23c9b88fc 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -2411,6 +2411,8 @@ void A_VultureBlast(mobj_t *actor) { mobj_t *dust; UINT8 i; + angle_t faa; + fixed_t faacos, faasin; #ifdef HAVE_BLUA if (LUA_CallAction("A_VultureBlast", actor)) @@ -2419,18 +2421,21 @@ void A_VultureBlast(mobj_t *actor) S_StartSound(actor, actor->info->attacksound); + faa = (actor->angle >> ANGLETOFINESHIFT) & FINEMASK; + faacos = FINECOSINE(faa); + faasin = FINESINE(faa); + for (i = 0; i <= 7; i++) { angle_t fa = ((i*(angle_t)ANGLE_45) >> ANGLETOFINESHIFT) & FINEMASK; - angle_t faa = (actor->angle >> ANGLETOFINESHIFT) & FINEMASK; - dust = P_SpawnMobj(actor->x + 48*FixedMul(FINECOSINE(fa), -FINESINE(faa)), actor->y + 48*FixedMul(FINECOSINE(fa), FINECOSINE(faa)), actor->z + actor->height/2 + 48*FINESINE(fa), MT_PARTICLE); + dust = P_SpawnMobj(actor->x + 48*FixedMul(FINECOSINE(fa), -faasin), actor->y + 48*FixedMul(FINECOSINE(fa), faacos), actor->z + actor->height/2 + 48*FINESINE(fa), MT_PARTICLE); P_SetScale(dust, 4*FRACUNIT); dust->destscale = FRACUNIT; dust->scalespeed = 4*FRACUNIT/TICRATE; dust->fuse = TICRATE; - dust->momx = FixedMul(FINECOSINE(fa), -FINESINE(faa))*3; - dust->momy = FixedMul(FINECOSINE(fa), FINECOSINE(faa))*3; + dust->momx = FixedMul(FINECOSINE(fa), -faasin)*3; + dust->momy = FixedMul(FINECOSINE(fa), faacos)*3; dust->momz = FINESINE(fa)*6; } } @@ -6631,7 +6636,7 @@ void A_RecyclePowers(mobj_t *actor) players[recv_pl].ringweapons = weapons[send_pl]; players[recv_pl].currentweapon = weaponheld[send_pl]; - if (((players[recv_pl].powers[pw_shield] & SH_NOSTACK) == SH_PINK) && (players[recv_pl].revitem == MT_LHRT)) // Healers can't keep their buff. + if (((players[recv_pl].powers[pw_shield] & SH_NOSTACK) == SH_PINK) && (players[recv_pl].revitem == MT_LHRT || players[recv_pl].spinitem == MT_LHRT || players[recv_pl].thokitem == MT_LHRT)) // Healers can't keep their buff. players[recv_pl].powers[pw_shield] &= SH_STACK; P_SpawnShieldOrb(&players[recv_pl]); diff --git a/src/p_inter.c b/src/p_inter.c index 42809c66b..3348696c0 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -468,18 +468,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) { toucher->momx = -toucher->momx; toucher->momy = -toucher->momy; + if (player->charability == CA_FLY && player->panim == PA_ABILITY) + toucher->momz = -toucher->momz/2; } P_DamageMobj(special, toucher, toucher, 1, 0); - } - else if (((toucher->z < special->z && !(toucher->eflags & MFE_VERTICALFLIP)) - || (toucher->z + toucher->height > special->z + special->height && (toucher->eflags & MFE_VERTICALFLIP))) - && player->charability == CA_FLY - && (player->powers[pw_tailsfly] - || toucher->state-states == S_PLAY_FLY_TIRED)) // Tails can shred stuff with her propeller. - { - toucher->momz = -toucher->momz/2; - - P_DamageMobj(special, toucher, toucher, 1, 0); + if (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY) + P_TwinSpinRejuvenate(player, player->thokitem); } else P_DamageMobj(toucher, special, special, 1, 0); @@ -2898,7 +2892,7 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou { if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) { - if (player->revitem != MT_LHRT) // Healers do not get to heal other healers. + if (player->revitem != MT_LHRT && player->spinitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers. { P_SwitchShield(player, SH_PINK); S_StartSound(target, mobjinfo[MT_PITY_ICON].seesound); @@ -2913,7 +2907,7 @@ static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *sou { if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) { - if (player->revitem != MT_LHRT) // Healers do not get to heal other healers. + if (player->revitem != MT_LHRT && player->spinitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers. { P_SwitchShield(player, SH_PINK); S_StartSound(target, mobjinfo[MT_PITY_ICON].seesound); @@ -2998,7 +2992,7 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj { if (gametype == GT_COOP && inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) // co-op only { - if (player->revitem != MT_LHRT) // Healers do not get to heal other healers. + if (player->revitem != MT_LHRT && player->spinitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers. { P_SwitchShield(player, SH_PINK); S_StartSound(target, mobjinfo[MT_PITY_ICON].seesound); @@ -3021,7 +3015,7 @@ static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj { if (inflictor->type == MT_LHRT && !(player->powers[pw_shield] & SH_NOSTACK)) { - if (player->revitem != MT_LHRT) // Healers do not get to heal other healers. + if (player->revitem != MT_LHRT && player->spinitem != MT_LHRT && player->thokitem != MT_LHRT) // Healers do not get to heal other healers. { P_SwitchShield(player, SH_PINK); S_StartSound(target, mobjinfo[MT_PITY_ICON].seesound); diff --git a/src/p_local.h b/src/p_local.h index d6f9d7648..8aeddf162 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -159,6 +159,7 @@ boolean P_AutoPause(void); void P_DoJumpShield(player_t *player); void P_DoBubbleBounce(player_t *player); void P_DoAbilityBounce(player_t *player, boolean changemomz); +void P_TwinSpinRejuvenate(player_t *player, mobjtype_t type); void P_BlackOw(player_t *player); void P_ElementalFire(player_t *player, boolean cropcircle); diff --git a/src/p_map.c b/src/p_map.c index 4d4d30356..76b6535b5 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -135,6 +135,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) fixed_t vertispeed = spring->info->mass; fixed_t horizspeed = spring->info->damage; boolean final = false; + UINT8 strong = 0; // Object was already sprung this tic if (object->eflags & MFE_SPRUNG) @@ -148,6 +149,14 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) if (!spring->health || !object->health) return false; + if (object->player) + { + if (object->player->charability == CA_TWINSPIN && object->player->panim == PA_ABILITY) + strong = 1; + else if (object->player->charability2 == CA2_MELEE && object->player->panim == PA_ABILITY2) + strong = 2; + } + if (spring->info->painchance == -1) // Pinball bumper mode. { // The first of the entirely different spring modes! @@ -188,6 +197,9 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) { fixed_t playervelocity; + if (strong) + vertispeed <<= 1; + if (!(object->player->pflags & PF_THOKKED) && !(object->player->homing) && ((playervelocity = FixedDiv(9*FixedHypot(object->player->speed, object->momz), 10< vertispeed)) vertispeed = playervelocity; @@ -260,11 +272,8 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) return false; } - if (object->player - && ((object->player->charability == CA_TWINSPIN && object->player->panim == PA_ABILITY) - || (object->player->charability2 == CA2_MELEE && object->player->panim == PA_ABILITY2))) + if (strong) { - S_StartSound(object, sfx_s3k8b); if (horizspeed) horizspeed = FixedMul(horizspeed, (4*FRACUNIT)/3); if (vertispeed) @@ -399,6 +408,12 @@ springstate: P_AddPlayerScore(object->player, 10); spring->reactiontime--; } + + if (strong) + { + P_TwinSpinRejuvenate(object->player, (strong == 1 ? object->player->thokitem : object->player->revitem)); + S_StartSound(object, sfx_sprong); // strong spring. sprong. + } } return final; @@ -1504,7 +1519,11 @@ static boolean PIT_CheckThing(mobj_t *thing) if (elementalpierce == 2) P_DoBubbleBounce(player); else if (!(player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2)) + { *momz = -*momz; // Therefore, you should be thrust in the opposite direction, vertically. + if (player->charability == CA_TWINSPIN && player->panim == PA_ABILITY) + P_TwinSpinRejuvenate(player, player->thokitem); + } } if (!(elementalpierce == 1 && thing->flags & MF_GRENADEBOUNCE)) // prevent gold monitor clipthrough. { diff --git a/src/p_mobj.c b/src/p_mobj.c index a78a83da1..70017546c 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -281,6 +281,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) player->panim = PA_FALL; break; case S_PLAY_FLY: + case S_PLAY_FLY_TIRED: case S_PLAY_SWIM: case S_PLAY_GLIDE: case S_PLAY_BOUNCE: @@ -1509,8 +1510,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) if (mo->player) { if ((mo->player->pflags & PF_GLIDING) - || (mo->player->charability == CA_FLY && (mo->player->powers[pw_tailsfly] - || mo->state-states == S_PLAY_FLY_TIRED))) + || (mo->player->charability == CA_FLY && mo->player->panim == PA_ABILITY)) gravityadd = gravityadd/3; // less gravity while flying/gliding if (mo->player->climbing || (mo->player->powers[pw_carry] == CR_NIGHTSMODE)) gravityadd = 0; @@ -5484,7 +5484,6 @@ static void P_Boss9Thinker(mobj_t *mobj) // AI goes here. { - boolean danger = true; angle_t angle; if (mobj->threshold) mobj->momz = (mobj->watertop-mobj->z)/16; // Float to your desired position FASTER @@ -5837,29 +5836,26 @@ static void P_Boss9Thinker(mobj_t *mobj) //A_FaceTarget(mobj); // Check if we're being attacked - if (!(mobj->target->player->pflags & (PF_JUMPED|PF_SPINNING) - || mobj->target->player->powers[pw_tailsfly] - || mobj->target->player->powers[pw_invulnerability] - || mobj->target->player->powers[pw_super])) - danger = false; + if (!mobj->target || !mobj->target->player || !P_PlayerCanDamage(mobj->target->player, mobj)) + goto nodanger; if (mobj->target->x+mobj->target->radius+abs(mobj->target->momx*2) < mobj->x-mobj->radius) - danger = false; + goto nodanger; if (mobj->target->x-mobj->target->radius-abs(mobj->target->momx*2) > mobj->x+mobj->radius) - danger = false; + goto nodanger; if (mobj->target->y+mobj->target->radius+abs(mobj->target->momy*2) < mobj->y-mobj->radius) - danger = false; + goto nodanger; if (mobj->target->y-mobj->target->radius-abs(mobj->target->momy*2) > mobj->y+mobj->radius) - danger = false; + goto nodanger; if (mobj->target->z+mobj->target->height+mobj->target->momz*2 < mobj->z) - danger = false; + goto nodanger; if (mobj->target->z+mobj->target->momz*2 > mobj->z+mobj->height) - danger = false; - if (danger) { - // An incoming attack is detected! What should we do?! - // Go into vector form! - vectorise; - return; - } + goto nodanger; + + // An incoming attack is detected! What should we do?! + // Go into vector form! + vectorise; + return; +nodanger: // Move normally: Approach the player using normal thrust and simulated friction. dist = P_AproxDistance(mobj->x-mobj->target->x, mobj->y-mobj->target->y); @@ -7920,8 +7916,8 @@ void P_MobjThinker(mobj_t *mobj) } break; case MT_LHRT: - mobj->momx = FixedMul(mobj->momx, (49*FRACUNIT)/50); - mobj->momy = FixedMul(mobj->momy, (49*FRACUNIT)/50); + mobj->momx = FixedMul(mobj->momx, mobj->extravalue2); + mobj->momy = FixedMul(mobj->momy, mobj->extravalue2); break; case MT_EGGCAPSULE: if (!mobj->reactiontime) diff --git a/src/p_user.c b/src/p_user.c index 9961d55dc..ac951a8fa 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1021,9 +1021,13 @@ boolean P_PlayerCanDamage(player_t *player, mobj_t *thing) && (player->drawangle - R_PointToAngle2(player->mo->x - player->mo->momx, player->mo->y - player->mo->momy, thing->x, thing->y) + + ANGLE_90) < ANGLE_180) return true; - // From the top. - if ((player->charflags & SF_STOMPDAMAGE || player->pflags & PF_BOUNCING) - && (P_MobjFlip(player->mo)*(player->mo->z - (thing->z + thing->height/2)) > 0) && (P_MobjFlip(player->mo)*player->mo->momz < 0)) + // From the top/bottom. + if (P_MobjFlip(player->mo)*(player->mo->z - (thing->z + thing->height/2)) > 0) + { + if ((player->charflags & SF_STOMPDAMAGE || player->pflags & PF_BOUNCING) && (P_MobjFlip(player->mo)*player->mo->momz < 0)) + return true; + } + else if (player->charability == CA_FLY && player->panim == PA_ABILITY) return true; // Shield stomp. @@ -1752,6 +1756,7 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) } ghost->color = mobj->color; + ghost->colorized = mobj->colorized; // alternatively, "true" for sonic advance style colourisation ghost->angle = (mobj->player ? mobj->player->drawangle : mobj->angle); ghost->sprite = mobj->sprite; @@ -2031,9 +2036,11 @@ boolean P_PlayerHitFloor(player_t *player) fixed_t zo = 6*player->mo->scale; fixed_t mu = FixedMul(player->maxdash, player->mo->scale); fixed_t mu2 = FixedHypot(player->mo->momx, player->mo->momy); + fixed_t ev; mobj_t *missile; if (mu2 < mu) mu2 = mu; + ev = (50*FRACUNIT - (mu/25))/50; while (i < 5) { missile = P_SpawnMobjFromMobj(player->mo, xo, yo, zo, type); @@ -2044,6 +2051,7 @@ boolean P_PlayerHitFloor(player_t *player) P_Thrust(missile, player->drawangle, mu2); // forward component P_SetObjectMomZ(missile, (4 + ((i&1)<<1))*FRACUNIT, true); missile->fuse = TICRATE/2; + missile->extravalue2 = ev; i++; throwang += ANG30; @@ -4529,6 +4537,57 @@ void P_DoAbilityBounce(player_t *player, boolean changemomz) player->pflags |= PF_BOUNCING|PF_THOKKED; } +// +// P_TwinSpinRejuvenate +// +// CA_TWINSPIN landing handling +// +void P_TwinSpinRejuvenate(player_t *player, mobjtype_t type) +{ + fixed_t actionspd; + angle_t movang, ang, fa; + fixed_t v, h; + UINT8 i; + + if (!player->mo || !type) + return; + + actionspd = FixedMul(player->actionspd, player->mo->scale); + + fa = (R_PointToAngle2(0, 0, player->mo->momz, FixedHypot(player->mo->momx, player->mo->momy))>>ANGLETOFINESHIFT) & FINEMASK; + movang = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); + ang = 0; + + v = FixedMul(actionspd, FINESINE(fa)); + h = actionspd - FixedMul(actionspd, FINECOSINE(fa)); + + // hearticles + for (i = 0; i <= 7; i++) + { + fixed_t side = actionspd - FixedMul(h, abs(FINESINE((ang>>ANGLETOFINESHIFT) & FINEMASK))); + fixed_t xo = P_ReturnThrustX(NULL, ang + movang, side); + fixed_t yo = P_ReturnThrustY(NULL, ang + movang, side); + fixed_t zo = -FixedMul(FINECOSINE(((ang>>ANGLETOFINESHIFT) & FINEMASK)), v); + mobj_t *missile = P_SpawnMobjFromMobj(player->mo, + xo, + yo, + player->mo->height/2 + zo, + type); + P_SetTarget(&missile->target, player->mo); + P_SetScale(missile, (missile->destscale >>= 1)); + missile->angle = ang + movang; + missile->fuse = TICRATE/2; + missile->extravalue2 = (99*FRACUNIT)/100; + missile->momx = xo; + missile->momy = yo; + missile->momz = zo; + + ang += ANGLE_45; + } + + player->pflags &= ~PF_THOKKED; +} + // // P_Telekinesis // @@ -7899,6 +7958,7 @@ static void P_MovePlayer(player_t *player) { player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, lockon->x, lockon->y); player->pflags &= ~PF_NOJUMPDAMAGE; + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); S_StartSound(player->mo, sfx_s3k40); player->homing = 3*TICRATE; } diff --git a/src/r_things.c b/src/r_things.c index 22c3d96c9..9fe1e96e4 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2704,7 +2704,7 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) player->revitem = skin->revitem < 0 ? (mobjtype_t)mobjinfo[MT_PLAYER].raisestate : (UINT32)skin->revitem; player->followitem = skin->followitem; - if (((player->powers[pw_shield] & SH_NOSTACK) == SH_PINK) && (player->revitem == MT_LHRT)) // Healers can't keep their buff. + if (((player->powers[pw_shield] & SH_NOSTACK) == SH_PINK) && (player->revitem == MT_LHRT || player->spinitem == MT_LHRT || player->thokitem == MT_LHRT)) // Healers can't keep their buff. player->powers[pw_shield] &= SH_STACK; player->actionspd = skin->actionspd; diff --git a/src/sounds.c b/src/sounds.c index 56de4a9c5..52dbee341 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -197,6 +197,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"corkh", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Cork hit"}, {"bowl", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bowling"}, {"chuchu", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Train horn"}, + {"sprong", false, 112, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power spring"}, // Menu, interface {"chchng", false, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Score"}, diff --git a/src/sounds.h b/src/sounds.h index 475309121..742febbba 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -263,6 +263,7 @@ typedef enum sfx_corkh, sfx_bowl, sfx_chuchu, + sfx_sprong, // Menu, interface sfx_chchng, From faebe0f9aff3dc2d803d45f4f9f66529bcfd05c3 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 28 Jun 2019 20:48:14 +0100 Subject: [PATCH 041/128] Metal Sonic fixes! * Add more context clues to his fight, including an indicator for which laser attack is being used after chargeup. * Make missiles able to vectorise him. * Add another laser orb attack - vertical slice - and change the laser orb sequence to accurately reflect that horizontal is the hardest of the ones in 2.1. * Optimise TC_BLINK, and fix an issue with TC_ALLWHITE that somehow avoided coming up in testing. * Fix colorized bosses losing their colorization when flashing, by forcing TC_ALLWHITE. --- src/dehacked.c | 5 +- src/hardware/hw_main.c | 2 +- src/hardware/hw_md2.c | 2 +- src/info.c | 27 ++-- src/info.h | 5 +- src/lua_baselib.c | 4 +- src/p_local.h | 2 +- src/p_map.c | 21 +++ src/p_mobj.c | 360 +++++++++++++++++++++++++++++++---------- src/p_user.c | 45 +++--- src/r_draw.c | 7 +- src/r_things.c | 2 +- src/sounds.c | 4 +- 13 files changed, 351 insertions(+), 135 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index f532bde68..7935c474f 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -5125,7 +5125,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_METALSONIC_BADBOUNCE", "S_METALSONIC_SHOOT", "S_METALSONIC_PAIN", - "S_METALSONIC_DEATH", + "S_METALSONIC_DEATH1", + "S_METALSONIC_DEATH2", + "S_METALSONIC_DEATH3", + "S_METALSONIC_DEATH4", "S_METALSONIC_FLEE1", "S_METALSONIC_FLEE2", "S_METALSONIC_FLEE3", diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index a76c9e1c8..d649eeb8e 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5662,7 +5662,7 @@ static void HWR_ProjectSprite(mobj_t *thing) //Hurdler: 25/04/2000: now support colormap in hardware mode if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash" { - if (vis->mobj->type == MT_CYBRAKDEMON) + if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized) vis->colormap = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE); else if (vis->mobj->type == MT_METALSONIC_BATTLE) vis->colormap = R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE); diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 6db5d5f08..e26aa98ff 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1363,7 +1363,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) INT32 skinnum = TC_DEFAULT; if ((spr->mobj->flags & (MF_ENEMY|MF_BOSS)) && (spr->mobj->flags2 & MF2_FRET) && !(spr->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash" { - if (spr->mobj->type == MT_CYBRAKDEMON) + if (spr->mobj->type == MT_CYBRAKDEMON || spr->mobj->colorized) skinnum = TC_ALLWHITE; else if (spr->mobj->type == MT_METALSONIC_BATTLE) skinnum = TC_METALSONIC; diff --git a/src/info.c b/src/info.c index 477c3f372..a58b2313c 100644 --- a/src/info.c +++ b/src/info.c @@ -1747,20 +1747,23 @@ state_t states[NUMSTATES] = {SPR_METL, 9, 2, {NULL}, 0, 0, S_METALSONIC_RUN1}, // S_METALSONIC_RUN4 {SPR_METL, 4, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_FLOAT - {SPR_METL, 12, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR - {SPR_METL, 0, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN - {SPR_METL, 13, 40, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE + {SPR_METL, 12|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR + {SPR_METL, 11, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN + {SPR_METL, 13, 20, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE {SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_GATHER {SPR_METL, 15, -1, {NULL}, 0, 0, S_METALSONIC_BOUNCE},// S_METALSONIC_DASH {SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BOUNCE {SPR_METL, 16, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BADBOUNCE {SPR_METL, 13, -1, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_SHOOT {SPR_METL, 11, 40, {A_Pain}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_PAIN - {SPR_METL, 11, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH - {SPR_METL, 3, 4, {NULL}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1 - {SPR_METL, 4, 4, {A_BossScream}, 0, 0, S_METALSONIC_FLEE3}, // S_METALSONIC_FLEE2 - {SPR_METL, 5, 4, {NULL}, 0, 0, S_METALSONIC_FLEE4}, // S_METALSONIC_FLEE3 - {SPR_METL, 4, 4, {NULL}, 0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE4 + {SPR_METL, 13, 8, {A_Fall}, 0, 0, S_METALSONIC_DEATH2},// S_METALSONIC_DEATH1 + {SPR_METL, 13, 8, {A_BossScream}, 0, 0, S_METALSONIC_DEATH3},// S_METALSONIC_DEATH2 + {SPR_METL, 13, 0, {A_Repeat}, 11, S_METALSONIC_DEATH2, S_METALSONIC_DEATH4}, // S_METALSONIC_DEATH3 + {SPR_METL, 13, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH4 + {SPR_METL, 11, 4, {NULL}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1 + {SPR_METL, 11, 4, {A_BossScream}, 0, 0, S_METALSONIC_FLEE3}, // S_METALSONIC_FLEE2 + {SPR_METL, 11, 4, {NULL}, 0, 0, S_METALSONIC_FLEE4}, // S_METALSONIC_FLEE3 + {SPR_METL, 11, 4, {NULL}, 0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE4 {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 0, 1, {NULL}, 0, 0, S_MSSHIELD_F2}, // S_MSSHIELD_F1 {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 1, 1, {NULL}, 0, 0, S_MSSHIELD_F3}, // S_MSSHIELD_F2 @@ -6259,13 +6262,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_METALSONIC_DASH, // seestate sfx_s3k54, // seesound 0, // reactiontime - sfx_trpowr, // attacksound + sfx_bechrg, // attacksound S_METALSONIC_PAIN, // painstate S_METALSONIC_VECTOR,// painchance sfx_dmpain, // painsound S_METALSONIC_BADBOUNCE, // meleestate S_METALSONIC_SHOOT, // missilestate - S_METALSONIC_DEATH, // deathstate + S_METALSONIC_DEATH1,// deathstate S_METALSONIC_FLEE1, // xdeathstate sfx_s3k6e, // deathsound MT_ENERGYBALL, // speed @@ -6297,7 +6300,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // deathsound 0, // speed 32*FRACUNIT, // radius - 64*FRACUNIT, // height + 52*FRACUNIT, // height 0, // display offset 0, // mass 0, // damage @@ -9140,7 +9143,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_ENERGYBALL1, // spawnstate 1000, // spawnhealth S_NULL, // seestate - sfx_s3k54, // seesound + sfx_bexpld, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate diff --git a/src/info.h b/src/info.h index a7f5d775a..c1891a766 100644 --- a/src/info.h +++ b/src/info.h @@ -1888,7 +1888,10 @@ typedef enum state S_METALSONIC_BADBOUNCE, S_METALSONIC_SHOOT, S_METALSONIC_PAIN, - S_METALSONIC_DEATH, + S_METALSONIC_DEATH1, + S_METALSONIC_DEATH2, + S_METALSONIC_DEATH3, + S_METALSONIC_DEATH4, S_METALSONIC_FLEE1, S_METALSONIC_FLEE2, S_METALSONIC_FLEE3, diff --git a/src/lua_baselib.c b/src/lua_baselib.c index e6119cd6c..81a17ef20 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1235,8 +1235,8 @@ static int lib_pHomingAttack(lua_State *L) INLEVEL if (!source || !enemy) return LUA_ErrInvalid(L, "mobj_t"); - P_HomingAttack(source, enemy); - return 0; + lua_pushboolean(L, P_HomingAttack(source, enemy)); + return 1; } static int lib_pSuperReady(lua_State *L) diff --git a/src/p_local.h b/src/p_local.h index 8aeddf162..479994079 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -176,7 +176,7 @@ void P_InstaThrustEvenIn2D(mobj_t *mo, angle_t angle, fixed_t move); mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet); void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius); -void P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user +boolean P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user boolean P_SuperReady(player_t *player); void P_DoJump(player_t *player, boolean soundandstate); #if 0 diff --git a/src/p_map.c b/src/p_map.c index 76b6535b5..a852a3933 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -725,6 +725,27 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; } + // vectorise metal - done in a special case as at this point neither has the right flags for touching + if (thing->type == MT_METALSONIC_BATTLE + && (tmthing->flags & MF_MISSILE) + && tmthing->target != thing + && thing->state == &states[thing->info->spawnstate]) + { + blockdist = thing->radius + tmthing->radius; + + if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) + return true; // didn't hit it + + if (tmthing->z > thing->z + thing->height) + return true; // overhead + if (tmthing->z + tmthing->height < thing->z) + return true; // underneath + + thing->flags2 |= MF2_CLASSICPUSH; + + return true; + } + if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_PAIN|MF_SHOOTABLE|MF_SPRING))) return true; diff --git a/src/p_mobj.c b/src/p_mobj.c index 70017546c..ff2bcc77f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5395,7 +5395,8 @@ static void P_Boss7Thinker(mobj_t *mobj) if (mobj->info->activesound)\ S_StartSound(mobj, mobj->info->activesound);\ if (mobj->info->painchance)\ - P_SetMobjState(mobj, mobj->info->painchance) + P_SetMobjState(mobj, mobj->info->painchance);\ + mobj->flags2 &= ~MF2_INVERTAIMABLE;\ // Metal Sonic battle boss // You CAN put multiple Metal Sonics in a single map @@ -5485,25 +5486,16 @@ static void P_Boss9Thinker(mobj_t *mobj) // AI goes here. { angle_t angle; - if (mobj->threshold) + if (mobj->threshold || mobj->movecount) mobj->momz = (mobj->watertop-mobj->z)/16; // Float to your desired position FASTER else mobj->momz = (mobj->watertop-mobj->z)/40; // Float to your desired position - if (mobj->movecount == 2) { + if (mobj->movecount == 2) + { mobj_t *spawner; fixed_t dist = 0; - angle = 0x06000000*leveltime; - - // Alter your energy bubble's size/position - if (mobj->health > 3) { - mobj->tracer->destscale = FRACUNIT + (4*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2); - P_SetScale(mobj->tracer, mobj->tracer->destscale); - P_TeleportMove(mobj->tracer, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->tracer->height/2); - mobj->tracer->momx = mobj->momx; - mobj->tracer->momy = mobj->momy; - mobj->tracer->momz = mobj->momz; - } + angle = 0x06000000*leveltime; // wtf? // Face your target P_BossTargetPlayer(mobj, true); @@ -5514,27 +5506,150 @@ static void P_Boss9Thinker(mobj_t *mobj) else mobj->angle -= InvAngle(angle)/8; + // Alter your energy bubble's size/position + if (mobj->health > 3) + { + mobj->tracer->destscale = FRACUNIT + (4*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2); + P_SetScale(mobj->tracer, mobj->tracer->destscale); + } + else + mobj->tracer->frame &= ~FF_TRANSMASK; // this causes a flicker but honestly i like it this way + P_TeleportMove(mobj->tracer, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->tracer->height/2); + mobj->tracer->momx = mobj->momx; + mobj->tracer->momy = mobj->momy; + mobj->tracer->momz = mobj->momz; + + // Firin' mah lazors - INDICATOR + if (mobj->fuse > TICRATE/2) + { + tic_t shoottime, worktime, calctime; + shoottime = (TICRATE/((mobj->extravalue1 == 3) ? 8 : 4)); + shoottime += (shoottime>>1); + worktime = shoottime*(mobj->threshold/2); + calctime = mobj->fuse-(TICRATE/2); + + if (calctime <= worktime && (calctime % shoottime == 0)) + { + mobj_t *missile; + + missile = P_SpawnMissile(mobj, mobj->target, MT_MSGATHER); + S_StopSound(missile); + if (mobj->extravalue1 >= 2) + P_SetScale(missile, FRACUNIT>>1); + missile->destscale = missile->scale>>1; + missile->fuse = TICRATE/2; + missile->scalespeed = abs(missile->destscale - missile->scale)/missile->fuse; + missile->z -= missile->height/2; + missile->momx *= -1; + missile->momy *= -1; + missile->momz *= -1; + + if (mobj->extravalue1 == 2) + { + UINT8 i; + mobj_t *spread; + for (i = 0; i < 5; i++) + { + if (i == 2) + continue; + spread = P_SpawnMobj(missile->x, missile->y, missile->z, missile->type); + spread->angle = missile->angle+(ANGLE_11hh/2)*(i-2); + P_InstaThrust(spread,spread->angle,-spread->info->speed); + spread->momz = missile->momz; + P_SetScale(spread, missile->scale); + spread->destscale = missile->destscale; + spread->scalespeed = missile->scalespeed; + spread->fuse = missile->fuse; + P_UnsetThingPosition(spread); + spread->x -= spread->fuse*spread->momx; + spread->y -= spread->fuse*spread->momy; + spread->z -= spread->fuse*spread->momz; + P_SetThingPosition(spread); + } + P_InstaThrust(missile,missile->angle,-missile->info->speed); + } + else if (mobj->extravalue1 >= 3) + { + UINT8 i; + mobj_t *spread; + mobj->target->z -= (4*missile->height); + for (i = 0; i < 5; i++) + { + if (i != 2) + { + spread = P_SpawnMissile(mobj, mobj->target, missile->type); + P_SetScale(spread, missile->scale); + spread->destscale = missile->destscale; + spread->fuse = missile->fuse; + spread->z -= spread->height/2; + spread->momx *= -1; + spread->momy *= -1; + spread->momz *= -1; + P_UnsetThingPosition(spread); + spread->x -= spread->fuse*spread->momx; + spread->y -= spread->fuse*spread->momy; + spread->z -= spread->fuse*spread->momz; + P_SetThingPosition(spread); + } + mobj->target->z += missile->height*2; + } + mobj->target->z -= (6*missile->height); + } + + P_UnsetThingPosition(missile); + missile->x -= missile->fuse*missile->momx; + missile->y -= missile->fuse*missile->momy; + missile->z -= missile->fuse*missile->momz; + P_SetThingPosition(missile); + + S_StartSound(mobj, sfx_s3kb3); + } + } + + // up... + mobj->z += mobj->height/2; + // Spawn energy particles - for (spawner = mobj->hnext; spawner; spawner = spawner->hnext) { + for (spawner = mobj->hnext; spawner; spawner = spawner->hnext) + { dist = P_AproxDistance(spawner->x - mobj->x, spawner->y - mobj->y); if (P_RandomRange(1,(dist>>FRACBITS)/16) == 1) break; } - if (spawner) { + if (spawner) + { mobj_t *missile = P_SpawnMissile(spawner, mobj, MT_MSGATHER); - if (mobj->health > mobj->info->damage) - missile->momz = FixedDiv(missile->momz, 7*FRACUNIT/5); + if (dist == 0) missile->fuse = 0; else missile->fuse = (dist/P_AproxDistance(missile->momx, missile->momy)); + if (missile->fuse > mobj->fuse) P_RemoveMobj(missile); + + if (mobj->health > mobj->info->damage) + { + P_SetScale(missile, FRACUNIT/2); + missile->color = SKINCOLOR_GOLD; // sonic cd electric power + } + else + { + P_SetScale(missile, FRACUNIT/4); + missile->color = SKINCOLOR_MAGENTA; // sonic OVA/4 purple power + } + missile->destscale = missile->scale*2; + missile->scalespeed = abs(missile->scale - missile->destscale)/missile->fuse; + missile->colorized = true; } + + // ...then down. easier than changing the missile's momz after-the-fact + mobj->z -= mobj->height/2; } // Pre-threshold reactiontime stuff for attack phases - if (mobj->reactiontime && mobj->movecount == 3) { + if (mobj->reactiontime && mobj->movecount == 3) + { mobj->reactiontime--; if (mobj->movedir == 0 || mobj->movedir == 2) { // Pausing between bounces in the pinball phase @@ -5555,13 +5670,15 @@ static void P_Boss9Thinker(mobj_t *mobj) } // threshold is used for attacks/maneuvers. - if (mobj->threshold) { + if (mobj->threshold && mobj->movecount != 2) { fixed_t speed = 20*FRACUNIT + FixedMul(40*FRACUNIT, FixedDiv((mobj->info->spawnhealth - mobj->health)<info->spawnhealth<movecount == 3 && mobj->movedir == 1) { - if (!(mobj->threshold&1)) { + if (mobj->movecount == 3 && mobj->movedir == 1) + { + if (!(mobj->threshold & 1)) + { mobj_t *missile; if (mobj->info->seesound) S_StartSound(mobj, mobj->info->seesound); @@ -5573,18 +5690,20 @@ static void P_Boss9Thinker(mobj_t *mobj) A_FaceTarget(mobj); missile = P_SpawnMissile(mobj, mobj->target, mobj->info->speed); - if (mobj->extravalue1 == 2 || mobj->extravalue1 == 3) { + if (mobj->extravalue1 >= 2) + { missile->destscale = FRACUNIT>>1; P_SetScale(missile, missile->destscale); } missile->fuse = 3*TICRATE; missile->z -= missile->height/2; - if (mobj->extravalue1 == 2) { - int i; + if (mobj->extravalue1 == 2) + { + UINT8 i; mobj_t *spread; - missile->flags |= MF_MISSILE; - for (i = 0; i < 5; i++) { + for (i = 0; i < 5; i++) + { if (i == 2) continue; spread = P_SpawnMobj(missile->x, missile->y, missile->z, missile->type); @@ -5593,11 +5712,32 @@ static void P_Boss9Thinker(mobj_t *mobj) spread->momz = missile->momz; spread->destscale = FRACUNIT>>1; P_SetScale(spread, spread->destscale); - spread->fuse = 3*TICRATE; + spread->fuse = missile->fuse; } - missile->flags &= ~MF_MISSILE; + P_InstaThrust(missile,missile->angle,missile->info->speed); } - } else { + else if (mobj->extravalue1 >= 3) + { + UINT8 i; + mobj_t *spread; + mobj->target->z -= (2*missile->height); + for (i = 0; i < 5; i++) + { + if (i != 2) + { + spread = P_SpawnMissile(mobj, mobj->target, missile->type); + spread->destscale = FRACUNIT>>1; + P_SetScale(spread, spread->destscale); + spread->fuse = missile->fuse; + spread->z -= spread->height/2; + } + mobj->target->z += missile->height; + } + mobj->target->z -= (3*missile->height); + } + } + else + { P_SetMobjState(mobj, mobj->state->nextstate); if (mobj->extravalue1 == 3) mobj->reactiontime = TICRATE/8; @@ -5611,7 +5751,8 @@ static void P_Boss9Thinker(mobj_t *mobj) P_SpawnGhostMobj(mobj); // Pinball attack! - if (mobj->movecount == 3 && (mobj->movedir == 0 || mobj->movedir == 2)) { + if (mobj->movecount == 3 && (mobj->movedir == 0 || mobj->movedir == 2)) + { if ((statenum_t)(mobj->state-states) != mobj->info->seestate) P_SetMobjState(mobj, mobj->info->seestate); if (mobj->movedir == 0) // mobj health == 1 @@ -5620,7 +5761,8 @@ static void P_Boss9Thinker(mobj_t *mobj) P_InstaThrust(mobj, mobj->angle, 22*FRACUNIT); else // mobj health == 2 P_InstaThrust(mobj, mobj->angle, 30*FRACUNIT); - if (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true)) { // Hit a wall? Find a direction to bounce + if (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true)) + { // Hit a wall? Find a direction to bounce mobj->threshold--; P_SetMobjState(mobj, mobj->state->nextstate); if (!mobj->threshold) { // failed bounce! @@ -5633,11 +5775,15 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->movecount = 0; P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_CYBRAKDEMON_VILE_EXPLOSION); P_SetMobjState(mobj, mobj->info->meleestate); - } else if (!(mobj->threshold%4)) { // We've decided to lock onto the player this bounce. + } + else if (!(mobj->threshold%4)) + { // We've decided to lock onto the player this bounce. S_StartSound(mobj, sfx_s3k5a); mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4); mobj->reactiontime = TICRATE - 5*(mobj->info->damage - mobj->health); // targetting time - } else { // No homing, just use P_BounceMove + } + else + { // No homing, just use P_BounceMove S_StartSound(mobj, sfx_s3kaa); // make the bounces distinct... P_BounceMove(mobj); mobj->angle = R_PointToAngle2(0,0,mobj->momx,mobj->momy); @@ -5651,7 +5797,8 @@ static void P_Boss9Thinker(mobj_t *mobj) // Vector form dodge! mobj->angle += mobj->movedir; P_InstaThrust(mobj, mobj->angle, -speed); - while (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true) && tries++ < 16) { + while (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true) && tries++ < 16) + { S_StartSound(mobj, sfx_mspogo); P_BounceMove(mobj); mobj->angle = R_PointToAngle2(mobj->momx, mobj->momy,0,0); @@ -5708,7 +5855,7 @@ static void P_Boss9Thinker(mobj_t *mobj) if (mobj->flags2 & MF2_FRET) return; - if (mobj->state == &states[mobj->info->raisestate]) + if (mobj->movecount == 1 || mobj->movecount == 2) { // Charging energy if (mobj->momx != 0 || mobj->momy != 0) { // Apply the air breaks if (abs(mobj->momx)+abs(mobj->momy) < FRACUNIT) @@ -5716,11 +5863,13 @@ static void P_Boss9Thinker(mobj_t *mobj) else P_Thrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), -6*FRACUNIT/8); } - return; + if (mobj->state == states+mobj->info->raisestate) + return; } if (mobj->fuse == 0) { + mobj->flags2 &= ~MF2_INVERTAIMABLE; // It's time to attack! What are we gonna do?! switch(mobj->movecount) { @@ -5728,6 +5877,7 @@ static void P_Boss9Thinker(mobj_t *mobj) default: // Fly up and prepare for an attack! // We have to charge up first, so let's go up into the air + S_StartSound(mobj, sfx_beflap); P_SetMobjState(mobj, mobj->info->raisestate); if (mobj->floorz >= mobj->target->floorz) mobj->watertop = mobj->floorz + 256*FRACUNIT; @@ -5735,33 +5885,69 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->watertop = mobj->target->floorz + 256*FRACUNIT; break; - case 1: { + case 1: // Okay, we're up? Good, time to gather energy... if (mobj->health > mobj->info->damage) { // No more bubble if we're broken (pinch phase) mobj_t *shield = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_MSSHIELD_FRONT); P_SetTarget(&mobj->tracer, shield); P_SetTarget(&shield->target, mobj); + + // Attack 2: Energy shot! + switch (mobj->health) + { + case 8: // shoot once + default: + mobj->extravalue1 = 0; + mobj->threshold = 2; + break; + case 7: // spread shot (vertical) + mobj->extravalue1 = 4; + mobj->threshold = 2; + break; + case 6: // three shots + mobj->extravalue1 = 1; + mobj->threshold = 3*2; + break; + case 5: // spread shot (horizontal) + mobj->extravalue1 = 2; + mobj->threshold = 2; + break; + case 4: // machine gun + mobj->extravalue1 = 3; + mobj->threshold = 5*2; + break; + } } else - P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); + { + mobj_t *shield = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_MSSHIELD_FRONT); + P_SetTarget(&mobj->tracer, shield); + P_SetTarget(&shield->target, mobj); + shield->height -= 20*FRACUNIT; // different offset... + shield->color = SKINCOLOR_MAGENTA; + shield->colorized = true; + P_SetMobjState(shield, S_FIRS1); + //P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); -- why does this happen twice? see case 2... + } mobj->fuse = 4*TICRATE; mobj->flags |= MF_PAIN; if (mobj->info->attacksound) S_StartSound(mobj, mobj->info->attacksound); A_FaceTarget(mobj); + break; - } case 2: // We're all charged and ready now! Unleash the fury!! - if (mobj->health > mobj->info->damage) + S_StopSound(mobj); + mobj_t *removemobj = mobj->tracer; + P_SetTarget(&mobj->tracer, mobj->hnext); + P_RemoveMobj(removemobj); + if (mobj->health <= mobj->info->damage) { - mobj_t *removemobj = mobj->tracer; - P_SetTarget(&mobj->tracer, mobj->hnext); - P_RemoveMobj(removemobj); - } - if (mobj->health <= mobj->info->damage) { + mobj_t *whoosh; + // Attack 1: Pinball dash! if (mobj->health == 1) mobj->movedir = 0; @@ -5776,32 +5962,23 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->threshold = 24; // bounce 24 times mobj->watertop = mobj->target->floorz + 16*FRACUNIT; P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); - } else { + + whoosh = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_GHOST); // done here so the offset is correct + whoosh->frame = FF_FULLBRIGHT; + whoosh->sprite = SPR_ARMA; + whoosh->destscale = whoosh->scale<<1; + whoosh->scalespeed = FixedMul(whoosh->scalespeed, whoosh->scale); + whoosh->height = 38*whoosh->scale; + whoosh->fuse = 10; + whoosh->color = SKINCOLOR_MAGENTA; + whoosh->colorized = true; + whoosh->flags |= MF_NOCLIPHEIGHT; + } + else + { // Attack 2: Energy shot! mobj->movedir = 1; - - if (mobj->health >= 8) - mobj->extravalue1 = 0; - else if (mobj->health >= 5) - mobj->extravalue1 = 2; - else if (mobj->health >= 4) - mobj->extravalue1 = 1; - else - mobj->extravalue1 = 3; - - switch(mobj->extravalue1) { - case 0: // shoot once - case 2: // spread-shot - default: - mobj->threshold = 2; - break; - case 1: // shoot 3 times - mobj->threshold = 3*2; - break; - case 3: // shoot like a goddamn machinegun - mobj->threshold = 8*2; - break; - } + // looking for the number of things to fire? that's done in case 1 now } break; @@ -5835,21 +6012,26 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->angle -= InvAngle(angle)/8; //A_FaceTarget(mobj); - // Check if we're being attacked - if (!mobj->target || !mobj->target->player || !P_PlayerCanDamage(mobj->target->player, mobj)) - goto nodanger; - if (mobj->target->x+mobj->target->radius+abs(mobj->target->momx*2) < mobj->x-mobj->radius) - goto nodanger; - if (mobj->target->x-mobj->target->radius-abs(mobj->target->momx*2) > mobj->x+mobj->radius) - goto nodanger; - if (mobj->target->y+mobj->target->radius+abs(mobj->target->momy*2) < mobj->y-mobj->radius) - goto nodanger; - if (mobj->target->y-mobj->target->radius-abs(mobj->target->momy*2) > mobj->y+mobj->radius) - goto nodanger; - if (mobj->target->z+mobj->target->height+mobj->target->momz*2 < mobj->z) - goto nodanger; - if (mobj->target->z+mobj->target->momz*2 > mobj->z+mobj->height) - goto nodanger; + if (mobj->flags2 & MF2_CLASSICPUSH) + mobj->flags2 &= ~MF2_CLASSICPUSH; // a missile caught us in PIT_CheckThing! + else + { + // Check if we're being attacked + if (!mobj->target || !mobj->target->player || !P_PlayerCanDamage(mobj->target->player, mobj)) + goto nodanger; + if (mobj->target->x+mobj->target->radius+abs(mobj->target->momx*2) < mobj->x-mobj->radius) + goto nodanger; + if (mobj->target->x-mobj->target->radius-abs(mobj->target->momx*2) > mobj->x+mobj->radius) + goto nodanger; + if (mobj->target->y+mobj->target->radius+abs(mobj->target->momy*2) < mobj->y-mobj->radius) + goto nodanger; + if (mobj->target->y-mobj->target->radius-abs(mobj->target->momy*2) > mobj->y+mobj->radius) + goto nodanger; + if (mobj->target->z+mobj->target->height+mobj->target->momz*2 < mobj->z) + goto nodanger; + if (mobj->target->z+mobj->target->momz*2 > mobj->z+mobj->height) + goto nodanger; + } // An incoming attack is detected! What should we do?! // Go into vector form! @@ -5857,13 +6039,17 @@ static void P_Boss9Thinker(mobj_t *mobj) return; nodanger: + mobj->flags2 |= MF2_INVERTAIMABLE; + // Move normally: Approach the player using normal thrust and simulated friction. dist = P_AproxDistance(mobj->x-mobj->target->x, mobj->y-mobj->target->y); P_Thrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), -3*FRACUNIT/8); - if (dist < 64*FRACUNIT) + if (dist < 64*FRACUNIT && !(mobj->target->player && mobj->target->player->homing)) P_Thrust(mobj, mobj->angle, -4*FRACUNIT); else if (dist > 180*FRACUNIT) P_Thrust(mobj, mobj->angle, FRACUNIT); + else + P_Thrust(mobj, mobj->angle + ANGLE_90, FINECOSINE((((angle_t)(leveltime*ANG1))>>ANGLETOFINESHIFT) & FINEMASK)>>1); mobj->momz += P_AproxDistance(mobj->momx, mobj->momy)/12; // Move up higher the faster you're going. } } diff --git a/src/p_user.c b/src/p_user.c index ac951a8fa..0d38fd876 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4803,10 +4803,10 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) player->mo->momx /= 2; player->mo->momy /= 2; } - else if (player->charability == CA_HOMINGTHOK) + if (player->charability == CA_HOMINGTHOK) { - player->mo->momx /= 3; - player->mo->momy /= 3; + player->mo->momx /= 2; + player->mo->momy /= 2; } if (player->charability == CA_HOMINGTHOK) @@ -7923,7 +7923,7 @@ static void P_MovePlayer(player_t *player) if (!(player->pflags & (PF_USEDOWN|PF_GLIDING|PF_SLIDING|PF_SHIELDABILITY)) // If the player is not holding down BT_USE, or having used an ability previously && (!(player->powers[pw_shield] & SH_NOSTACK) || !(player->pflags & PF_THOKKED) || ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP && player->secondjump == UINT8_MAX))) // thokked is optional if you're bubblewrapped/turning super { - // Force shield activation + // Force stop if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE) { player->pflags |= PF_THOKKED|PF_SHIELDABILITY; @@ -7939,17 +7939,17 @@ static void P_MovePlayer(player_t *player) if (P_SuperReady(player)) P_DoSuperTransformation(player, false); break; - // Whirlwind/Thundercoin shield activation + // Whirlwind jump/Thunder jump case SH_WHIRLWIND: case SH_THUNDERCOIN: P_DoJumpShield(player); break; - // Armageddon shield activation + // Armageddon pow case SH_ARMAGEDDON: player->pflags |= PF_THOKKED|PF_SHIELDABILITY; P_BlackOw(player); break; - // Attract shield activation + // Attraction blast case SH_ATTRACT: player->pflags |= PF_THOKKED|PF_SHIELDABILITY; player->homing = 2; @@ -7965,7 +7965,7 @@ static void P_MovePlayer(player_t *player) else S_StartSound(player->mo, sfx_s3ka6); break; - // Elemental/Bubblewrap shield activation + // Elemental stomp/Bubble bounce case SH_ELEMENTAL: case SH_BUBBLEWRAP: player->pflags |= PF_THOKKED|PF_SHIELDABILITY; @@ -7979,7 +7979,7 @@ static void P_MovePlayer(player_t *player) ? sfx_s3k43 : sfx_s3k44); break; - // Flame shield activation + // Flame burst case SH_FLAMEAURA: player->pflags |= PF_THOKKED|PF_SHIELDABILITY; P_Thrust(player->mo, player->mo->angle, FixedMul(30*FRACUNIT - FixedSqrt(FixedDiv(player->speed, player->mo->scale)), player->mo->scale)); @@ -8000,8 +8000,7 @@ static void P_MovePlayer(player_t *player) { if (player->homing && player->mo->tracer) { - P_HomingAttack(player->mo, player->mo->tracer); - if (player->mo->tracer->health <= 0 || (player->mo->tracer->flags2 & MF2_FRET)) + if (!P_HomingAttack(player->mo, player->mo->tracer)) { P_SetObjectMomZ(player->mo, 6*FRACUNIT, false); if (player->mo->eflags & MFE_UNDERWATER) @@ -8020,10 +8019,9 @@ static void P_MovePlayer(player_t *player) if (player->homing && player->mo->tracer) { P_SpawnThokMobj(player); - P_HomingAttack(player->mo, player->mo->tracer); // But if you don't, then stop homing. - if (player->mo->tracer->health <= 0 || (player->mo->tracer->flags2 & MF2_FRET)) + if (!P_HomingAttack(player->mo, player->mo->tracer)) { if (player->mo->eflags & MFE_UNDERWATER) P_SetObjectMomZ(player->mo, FixedDiv(457*FRACUNIT,72*FRACUNIT), false); @@ -8621,7 +8619,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) continue; // not a mobj thinker mo = (mobj_t *)think; - if (!(mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR|MF_SPRING)) == !(mo->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag + if (!((mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR) && (mo->flags & MF_SHOOTABLE)) || (mo->flags & MF_SPRING)) == !(mo->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag continue; // not a valid target if (mo->health <= 0) // dead @@ -8633,9 +8631,6 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) if (mo->flags2 & MF2_FRET) continue; - if ((mo->flags & (MF_ENEMY|MF_BOSS)) && !(mo->flags & MF_SHOOTABLE)) // don't aim at something you can't shoot at anyway (see Egg Guard or Minus) - continue; - if (!nonenemies && mo->flags & (MF_MONITOR|MF_SPRING)) continue; @@ -8689,17 +8684,23 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) return closestmo; } -void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target +boolean P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target { fixed_t zdist; fixed_t dist; fixed_t ns = 0; if (!enemy) - return; + return false; - if (!(enemy->health)) - return; + if (!enemy->health) + return false; + + if (enemy->flags2 & MF2_FRET) + return false; + + if (!(enemy->flags & (MF_SHOOTABLE|MF_SPRING)) == !(enemy->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag + return false; // change angle source->angle = R_PointToAngle2(source->x, source->y, enemy->x, enemy->y); @@ -8742,6 +8743,8 @@ void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target source->momx = FixedMul(FixedDiv(enemy->x - source->x, dist), ns); source->momy = FixedMul(FixedDiv(enemy->y - source->y, dist), ns); source->momz = FixedMul(FixedDiv(zdist, dist), ns); + + return true; } // Search for emeralds diff --git a/src/r_draw.c b/src/r_draw.c index 77bb1b6e7..f8e435624 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -528,12 +528,9 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U || color == SKINCOLOR_NONE) { if (skinnum == TC_ALLWHITE) - memset(dest_colormap, 0, NUM_PALETTE_ENTRIES * sizeof(UINT8**)); + memset(dest_colormap, 0, NUM_PALETTE_ENTRIES * sizeof(UINT8)); else if (skinnum == TC_BLINK && color != SKINCOLOR_NONE) - { - for (i = 0; i < NUM_PALETTE_ENTRIES; i++) - dest_colormap[i] = Color_Index[color-1][3]; - } + memset(dest_colormap, Color_Index[color-1][3], NUM_PALETTE_ENTRIES * sizeof(UINT8)); else { for (i = 0; i < NUM_PALETTE_ENTRIES; i++) diff --git a/src/r_things.c b/src/r_things.c index 9fe1e96e4..155d0f83f 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -723,7 +723,7 @@ static void R_DrawVisSprite(vissprite_t *vis) { // translate certain pixels to white colfunc = transcolfunc; - if (vis->mobj->type == MT_CYBRAKDEMON) + if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized) dc_translation = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE); else if (vis->mobj->type == MT_METALSONIC_BATTLE) dc_translation = R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE); diff --git a/src/sounds.c b/src/sounds.c index 52dbee341..aa1c841d6 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -137,7 +137,7 @@ sfxinfo_t S_sfx[NUMSFX] = // Game objects, etc {"appear", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Appearing platform"}, - {"bkpoof", false, 70, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Armageddon explosion"}, + {"bkpoof", false, 70, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Armageddon pow"}, {"bnce1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bounce"}, // Boing! {"bnce2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Scatter"}, // Boing! {"cannon", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Powerful shot"}, @@ -304,7 +304,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3k3e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flame Shield"}, {"s3k3f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bubble Shield"}, {"s3k40", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Attraction blast"}, - {"s3k41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Lightning Shield"}, + {"s3k41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Thunder Shield"}, {"s3k42", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Twinspin"}, {"s3k43", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flame burst"}, {"s3k44", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bubble bounce"}, From 164e797670a7e7c0036f36c8c4668b8ba7a76cfc Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sat, 29 Jun 2019 20:35:31 -0400 Subject: [PATCH 042/128] Better loading code for modules --- src/sdl/mixer_sound.c | 59 +++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 3932d23d3..8127edd60 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -1112,6 +1112,32 @@ boolean I_LoadSong(char *data, size_t len) } #endif +#ifdef HAVE_OPENMPT + size_t probesize; + int result; + + if (len > openmpt_probe_file_header_get_recommended_size()) + probesize = openmpt_probe_file_header_get_recommended_size(); + else + probesize = len; + + result = openmpt_probe_file_header(OPENMPT_PROBE_FILE_HEADER_FLAGS_DEFAULT, data, probesize, len, NULL, NULL, NULL, NULL, NULL, NULL); + + if (result == OPENMPT_PROBE_FILE_HEADER_RESULT_SUCCESS) // We only cared if it succeeded, continue on if not. + { + openmpt_mhandle = openmpt_module_create_from_memory2(data, len, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + if (!openmpt_mhandle) + { + mod_err = openmpt_module_error_get_last(openmpt_mhandle); + mod_err_str = openmpt_error_string(mod_err); + CONS_Alert(CONS_ERROR, "openmpt_module_create_from_memory2: %s\n", mod_err_str); + return false; + } + else + return true; + } +#endif + rw = SDL_RWFromMem(data, len); if (rw != NULL) { @@ -1123,39 +1149,6 @@ boolean I_LoadSong(char *data, size_t len) return false; } -#ifdef HAVE_OPENMPT - switch(Mix_GetMusicType(music)) - { - case MUS_MODPLUG: - case MUS_MOD: - openmpt_mhandle = openmpt_module_create_from_memory2(data, len, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - if (!openmpt_mhandle) - { - mod_err = openmpt_module_error_get_last(openmpt_mhandle); - mod_err_str = openmpt_error_string(mod_err); - CONS_Alert(CONS_ERROR, "openmpt_module_create_from_memory2: %s\n", mod_err_str); - Mix_FreeMusic(music); - music = NULL; - return false; - } - else - { - Mix_FreeMusic(music); - music = NULL; - return true; - } - break; - case MUS_WAV: - case MUS_MID: - case MUS_OGG: - case MUS_MP3: - case MUS_FLAC: - Mix_HookMusic(NULL, NULL); - break; - default: - break; - } -#endif // Find the OGG loop point. loop_point = 0.0f; From f9f92abc442851b1eeb49a9a258109d2ca4be0e3 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 29 Jun 2019 14:10:32 +0100 Subject: [PATCH 043/128] ha ha ha ha ha ha ha ha Sea Egg is majorly changed according to Mystic's ancient instructions (excepting the flying FOF rock, I cared not for fucking around with FOFs). Specifically: * Faster paced fight. * Instantly travels horizontal distance. * Fakes no longer hurt papa, and spin out like a deflating balloon when he dies. * New attack: When surfacing, produces an electric shockwave. Replaces underwater shock. Designed for new, shallow arena. * Support for multiple bosses in the same map distinguished by parameter. Will upload map to fight the new battle in on the MR. --- src/dehacked.c | 15 +-- src/info.c | 59 ++++++--- src/info.h | 15 +-- src/p_enemy.c | 115 +++++++++-------- src/p_inter.c | 19 ++- src/p_mobj.c | 335 +++++++++++++++++++++++++------------------------ src/p_user.c | 1 + 7 files changed, 305 insertions(+), 254 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 8057f26d8..f01eadf3d 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -4666,6 +4666,11 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit // Boss 3 "S_EGGMOBILE3_STND", + "S_EGGMOBILE3_LAUGH1", + "S_EGGMOBILE3_LAUGH2", + "S_EGGMOBILE3_LAUGH3", + "S_EGGMOBILE3_LAUGH4", + "S_EGGMOBILE3_LAUGH5", "S_EGGMOBILE3_ATK1", "S_EGGMOBILE3_ATK2", "S_EGGMOBILE3_ATK3A", @@ -4674,11 +4679,6 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_EGGMOBILE3_ATK3D", "S_EGGMOBILE3_ATK4", "S_EGGMOBILE3_ATK5", - "S_EGGMOBILE3_LAUGH1", - "S_EGGMOBILE3_LAUGH2", - "S_EGGMOBILE3_LAUGH3", - "S_EGGMOBILE3_LAUGH4", - "S_EGGMOBILE3_LAUGH5", "S_EGGMOBILE3_LAUGH6", "S_EGGMOBILE3_LAUGH7", "S_EGGMOBILE3_LAUGH8", @@ -4731,8 +4731,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_FAKEMOBILE_ATK3B", "S_FAKEMOBILE_ATK3C", "S_FAKEMOBILE_ATK3D", - "S_FAKEMOBILE_ATK4", - "S_FAKEMOBILE_ATK5", + "S_FAKEMOBILE_DIE1", + "S_FAKEMOBILE_DIE2", // Boss 4 "S_EGGMOBILE4_STND", @@ -7251,6 +7251,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_EGGMOBILE3", "MT_PROPELLER", "MT_FAKEMOBILE", + "MT_SHOCK", // Boss 4 "MT_EGGMOBILE4", diff --git a/src/info.c b/src/info.c index 074e31ba2..aaf66229b 100644 --- a/src/info.c +++ b/src/info.c @@ -1268,6 +1268,11 @@ state_t states[NUMSTATES] = // Boss 3 {SPR_EGGO, 0, 1, {NULL}, 0, 0, S_EGGMOBILE3_STND}, // S_EGGMOBILE3_STND + {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH2}, // S_EGGMOBILE3_LAUGH1 + {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH3}, // S_EGGMOBILE3_LAUGH2 + {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH4}, // S_EGGMOBILE3_LAUGH3 + {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH5}, // S_EGGMOBILE3_LAUGH4 + {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_ATK1}, // S_EGGMOBILE3_LAUGH5 {SPR_EGGO, 1, 2, {NULL}, 0, 0, S_EGGMOBILE3_ATK2}, // S_EGGMOBILE3_ATK1 {SPR_EGGO, 2, 2, {NULL}, 0, 0, S_EGGMOBILE3_ATK3A}, // S_EGGMOBILE3_ATK2 {SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 2, S_EGGMOBILE3_ATK3B}, // S_EGGMOBILE3_ATK3A @@ -1275,12 +1280,7 @@ state_t states[NUMSTATES] = {SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 3, S_EGGMOBILE3_ATK3D}, // S_EGGMOBILE3_ATK3C {SPR_EGGO, 3, 2, {A_BossFireShot}, MT_TORPEDO, 5, S_EGGMOBILE3_ATK4}, // S_EGGMOBILE3_ATK3D {SPR_EGGO, 4, 2, {NULL}, 0, 0, S_EGGMOBILE3_ATK5}, // S_EGGMOBILE3_ATK4 - {SPR_EGGO, 5, 2, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH1}, // S_EGGMOBILE3_ATK5 - {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH2}, // S_EGGMOBILE3_LAUGH1 - {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH3}, // S_EGGMOBILE3_LAUGH2 - {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH4}, // S_EGGMOBILE3_LAUGH3 - {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH5}, // S_EGGMOBILE3_LAUGH4 - {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH6}, // S_EGGMOBILE3_LAUGH5 + {SPR_EGGO, 5, 2, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH6}, // S_EGGMOBILE3_ATK5 {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH7}, // S_EGGMOBILE3_LAUGH6 {SPR_EGGO, 6, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH8}, // S_EGGMOBILE3_LAUGH7 {SPR_EGGO, 7, 4, {NULL}, 0, 0, S_EGGMOBILE3_LAUGH9}, // S_EGGMOBILE3_LAUGH8 @@ -1327,14 +1327,14 @@ state_t states[NUMSTATES] = // Boss 3 Pinch {SPR_FAKE, 0, 1, {A_BossJetFume}, 1, 0, S_FAKEMOBILE}, // S_FAKEMOBILE_INIT {SPR_FAKE, 0, 1, {A_Boss3Path}, 0, 0, S_FAKEMOBILE}, // S_FAKEMOBILE - {SPR_FAKE, 0, 2, {NULL}, 0, 0, S_FAKEMOBILE_ATK2}, // S_FAKEMOBILE_ATK1 + {SPR_FAKE, 0, 22, {NULL}, 0, 0, S_FAKEMOBILE_ATK2}, // S_FAKEMOBILE_ATK1 {SPR_FAKE, 0, 2, {NULL}, 0, 0, S_FAKEMOBILE_ATK3A}, // S_FAKEMOBILE_ATK2 {SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 2, S_FAKEMOBILE_ATK3B}, // S_FAKEMOBILE_ATK3A {SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 4, S_FAKEMOBILE_ATK3C}, // S_FAKEMOBILE_ATK3B {SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 3, S_FAKEMOBILE_ATK3D}, // S_FAKEMOBILE_ATK3C - {SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 5, S_FAKEMOBILE_ATK4}, // S_FAKEMOBILE_ATK3D - {SPR_FAKE, 0, 2, {NULL}, 0, 0, S_FAKEMOBILE_ATK5}, // S_FAKEMOBILE_ATK4 - {SPR_FAKE, 0, 2, {NULL}, 0, 0, S_FAKEMOBILE}, // S_FAKEMOBILE_ATK5 + {SPR_FAKE, 0, 2, {A_BossFireShot}, MT_TORPEDO2, 5, S_FAKEMOBILE}, // S_FAKEMOBILE_ATK3D + {SPR_FAKE, 0, 1, {NULL}, 0, 0, S_FAKEMOBILE_DIE2}, // S_FAKEMOBILE_DIE1 + {SPR_NULL, 0, 1, {NULL}, 0, 0, S_FAKEMOBILE_DIE1}, // S_FAKEMOBILE_DIE2 // Boss 4 {SPR_EGGP, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGMOBILE4_STND @@ -2886,7 +2886,7 @@ state_t states[NUMSTATES] = {SPR_NULL, 0, 15*2, {NULL}, 0, 0, S_ZAPSB2 }, // S_ZAPSB11 // Thunder spark - {SPR_SSPK, FF_ANIMATE, 18, {NULL}, 1, 2, S_NULL}, // S_THUNDERCOIN_SPARK + {SPR_SSPK, FF_ANIMATE, -1, {NULL}, 1, 2, S_NULL}, // S_THUNDERCOIN_SPARK // Invincibility Sparkles {SPR_IVSP, FF_ANIMATE, 32, {NULL}, 31, 1, S_NULL}, // S_IVSP @@ -5500,7 +5500,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = MT_PROPELLER, // painchance sfx_dmpain, // painsound S_NULL, // meleestate - S_EGGMOBILE3_ATK1, // missilestate + S_EGGMOBILE3_LAUGH1,// missilestate S_EGGMOBILE3_DIE1, // deathstate S_EGGMOBILE3_FLEE1, // xdeathstate sfx_cybdth, // deathsound @@ -5555,9 +5555,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_s3k7b, // painsound S_NULL, // meleestate S_FAKEMOBILE_ATK1, // missilestate - S_XPLD1, // deathstate + S_FAKEMOBILE_DIE1, // deathstate S_NULL, // xdeathstate - sfx_pop, // deathsound + sfx_mswarp, // deathsound 8*FRACUNIT, // speed 32*FRACUNIT, // radius 116*FRACUNIT, // height @@ -5569,6 +5569,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_SHOCK + -1, // doomednum + S_THUNDERCOIN_SPARK, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_SPRK1, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 10*FRACUNIT, // speed + 16*FRACUNIT, // radius + 35*FRACUNIT, // height + 0, // display offset + DMG_ELECTRIC|(sfx_buzz2<<8), // mass + 20, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_MISSILE|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + { // MT_EGGMOBILE4 203, // doomednum S_EGGMOBILE4_STND, // spawnstate @@ -9086,7 +9113,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_MINE_BOOM1, // deathstate + S_XPLD1, // deathstate S_NULL, // xdeathstate sfx_cybdth, // deathsound 20*FRACUNIT, // speed @@ -9113,7 +9140,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_MINE_BOOM1, // deathstate + S_XPLD1, // deathstate S_NULL, // xdeathstate sfx_cybdth, // deathsound 20*FRACUNIT, // speed diff --git a/src/info.h b/src/info.h index 13abfa5f6..4dac405ba 100644 --- a/src/info.h +++ b/src/info.h @@ -1421,6 +1421,11 @@ typedef enum state // Boss 3 S_EGGMOBILE3_STND, + S_EGGMOBILE3_LAUGH1, + S_EGGMOBILE3_LAUGH2, + S_EGGMOBILE3_LAUGH3, + S_EGGMOBILE3_LAUGH4, + S_EGGMOBILE3_LAUGH5, S_EGGMOBILE3_ATK1, S_EGGMOBILE3_ATK2, S_EGGMOBILE3_ATK3A, @@ -1429,11 +1434,6 @@ typedef enum state S_EGGMOBILE3_ATK3D, S_EGGMOBILE3_ATK4, S_EGGMOBILE3_ATK5, - S_EGGMOBILE3_LAUGH1, - S_EGGMOBILE3_LAUGH2, - S_EGGMOBILE3_LAUGH3, - S_EGGMOBILE3_LAUGH4, - S_EGGMOBILE3_LAUGH5, S_EGGMOBILE3_LAUGH6, S_EGGMOBILE3_LAUGH7, S_EGGMOBILE3_LAUGH8, @@ -1486,8 +1486,8 @@ typedef enum state S_FAKEMOBILE_ATK3B, S_FAKEMOBILE_ATK3C, S_FAKEMOBILE_ATK3D, - S_FAKEMOBILE_ATK4, - S_FAKEMOBILE_ATK5, + S_FAKEMOBILE_DIE1, + S_FAKEMOBILE_DIE2, // Boss 4 S_EGGMOBILE4_STND, @@ -4026,6 +4026,7 @@ typedef enum mobj_type MT_EGGMOBILE3, MT_PROPELLER, MT_FAKEMOBILE, + MT_SHOCK, // Boss 4 MT_EGGMOBILE4, diff --git a/src/p_enemy.c b/src/p_enemy.c index 2861f4480..38035ab7f 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -2858,6 +2858,7 @@ void A_BossFireShot(mobj_t *actor) fixed_t x, y, z; INT32 locvar1 = var1; INT32 locvar2 = var2; + mobj_t *missile; #ifdef HAVE_BLUA if (LUA_CallAction("A_BossFireShot", actor)) @@ -2925,7 +2926,10 @@ void A_BossFireShot(mobj_t *actor) break; } - P_SpawnXYZMissile(actor, actor->target, locvar1, x, y, z); + missile = P_SpawnXYZMissile(actor, actor->target, locvar1, x, y, z); + + if (missile && actor->tracer && (actor->tracer->flags & MF_BOSS)) // Don't harm your papa. + P_SetTarget(&missile->target, actor->tracer); } // Function: A_Boss7FireMissiles @@ -7762,9 +7766,11 @@ void A_Boss3TakeDamage(mobj_t *actor) return; #endif actor->movecount = var1; + actor->movefactor = -512*FRACUNIT; + + /*if (actor->target && actor->target->spawnpoint) + actor->threshold = actor->target->spawnpoint->extrainfo;*/ - if (actor->target && actor->target->spawnpoint) - actor->threshold = actor->target->spawnpoint->extrainfo; } // Function: A_Boss3Path @@ -7801,24 +7807,34 @@ void A_Boss3Path(mobj_t *actor) } else if (actor->threshold >= 0) // Traveling mode { - thinker_t *th; - mobj_t *mo2; - fixed_t dist, dist2; + fixed_t dist = 0; fixed_t speed; - P_SetTarget(&actor->target, NULL); - - // scan the thinkers - // to find a point that matches - // the number - for (th = thinkercap.next; th != &thinkercap; th = th->next) + if (!(actor->flags2 & MF2_STRONGBOX)) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; + thinker_t *th; + mobj_t *mo2; - mo2 = (mobj_t *)th; - if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && mo2->spawnpoint->angle == actor->threshold) + P_SetTarget(&actor->target, NULL); + + // scan the thinkers + // to find a point that matches + // the number + for (th = thinkercap.next; th != &thinkercap; th = th->next) { + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + mo2 = (mobj_t *)th; + if (mo2->type != MT_BOSS3WAYPOINT) + continue; + if (!mo2->spawnpoint) + continue; + if (mo2->spawnpoint->angle != actor->threshold) + continue; + if (mo2->spawnpoint->extrainfo != actor->cusval) + continue; + P_SetTarget(&actor->target, mo2); break; } @@ -7826,67 +7842,62 @@ void A_Boss3Path(mobj_t *actor) if (!actor->target) // Should NEVER happen { - CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 Dummy was unable to find specified waypoint: %d\n", actor->threshold); + CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 Dummy was unable to find specified waypoint: %d, %d\n", actor->threshold, actor->cusval); return; } - dist = P_AproxDistance(P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y), actor->target->z - actor->z); - - if (dist < 1) - dist = 1; - if (actor->tracer && ((actor->tracer->movedir) || (actor->tracer->health <= actor->tracer->info->damage))) speed = actor->info->speed * 2; else speed = actor->info->speed; - actor->momx = FixedMul(FixedDiv(actor->target->x - actor->x, dist), speed); - actor->momy = FixedMul(FixedDiv(actor->target->y - actor->y, dist), speed); - actor->momz = FixedMul(FixedDiv(actor->target->z - actor->z, dist), speed); + if (actor->target->x == actor->x && actor->target->y == actor->y) + { + dist = P_AproxDistance(P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y), actor->target->z + actor->movefactor - actor->z); - if (actor->momx != 0 || actor->momy != 0) - actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy); + if (dist < 1) + dist = 1; - dist2 = P_AproxDistance(P_AproxDistance(actor->target->x - (actor->x + actor->momx), actor->target->y - (actor->y + actor->momy)), actor->target->z - (actor->z + actor->momz)); + actor->momx = FixedMul(FixedDiv(actor->target->x - actor->x, dist), speed); + actor->momy = FixedMul(FixedDiv(actor->target->y - actor->y, dist), speed); + actor->momz = FixedMul(FixedDiv(actor->target->z + actor->movefactor - actor->z, dist), speed); - if (dist2 < 1) - dist2 = 1; + if (actor->momx != 0 || actor->momy != 0) + actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy); + } - if ((dist >> FRACBITS) <= (dist2 >> FRACBITS)) + if (dist <= speed) { // If further away, set XYZ of mobj to waypoint location P_UnsetThingPosition(actor); actor->x = actor->target->x; actor->y = actor->target->y; - actor->z = actor->target->z; + actor->z = actor->target->z + actor->movefactor; actor->momx = actor->momy = actor->momz = 0; P_SetThingPosition(actor); - if (actor->threshold == 0) + if (!actor->movefactor) // firing mode + { + actor->movecount |= 2; + actor->movefactor = -512*FRACUNIT; + actor->flags2 &= ~MF2_STRONGBOX; + } + else if (!(actor->flags2 & MF2_STRONGBOX)) // just spawned or going down + { + actor->flags2 |= MF2_STRONGBOX; + actor->movefactor = -512*FRACUNIT; + } + else if (!(actor->flags2 & MF2_AMBUSH)) // just shifted tube + { + actor->flags2 |= MF2_AMBUSH; + actor->movefactor = 0; + } + else // just hit the bottom of your tube { P_RemoveMobj(actor); // Cycle completed. Dummy removed. return; } - - // Set to next waypoint in sequence - if (actor->target->spawnpoint) - { - // From the center point, choose one of the five paths - if (actor->target->spawnpoint->angle == 0) - { - P_RemoveMobj(actor); // Cycle completed. Dummy removed. - return; - } - else - actor->threshold = actor->target->spawnpoint->extrainfo; - - // If the deaf flag is set, go into firing mode - if (actor->target->spawnpoint->options & MTF_AMBUSH) - actor->movecount |= 2; - } - else // This should never happen, as well - CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 Dummy waypoint has no spawnpoint associated with it.\n"); } } } diff --git a/src/p_inter.c b/src/p_inter.c index cd1e80de2..0e832324a 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2574,13 +2574,20 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget continue; mo = (mobj_t *)th; - if (mo->type == (mobjtype_t)target->info->mass && mo->tracer == target) - { - P_RemoveMobj(mo); - i++; - } - if (i == 2) // we've already removed 2 of these, let's stop now + if (mo->type != (mobjtype_t)target->info->mass) + continue; + if (mo->tracer != target) + continue; + + P_KillMobj(mo, inflictor, source, damagetype); + mo->destscale = mo->scale/8; + mo->scalespeed = (mo->scale - mo->destscale)/(2*TICRATE); + mo->momz = mo->info->speed; + mo->angle = FixedAngle((P_RandomKey(36)*10)<info->deathsound); // done once to prevent sound stacking } } break; diff --git a/src/p_mobj.c b/src/p_mobj.c index 5bf11134c..942096726 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -4384,6 +4384,8 @@ static void P_Boss3Thinker(mobj_t *mobj) } if (mobj->health <= 0) + return; + /* { mobj->movecount = 0; mobj->reactiontime = 0; @@ -4396,89 +4398,37 @@ static void P_Boss3Thinker(mobj_t *mobj) mobj->momz = mobj->info->speed; return; } - } + else + { + mobj->flags |= MF_NOGRAVITY|MF_NOCLIP; + mobj->flags |= MF_NOCLIPHEIGHT; + mobj->threshold = -1; + return; + } + }*/ - if (mobj->reactiontime) // Shock mode + if (mobj->reactiontime) // At the bottom of the water { UINT32 i; + SINT8 curpath = mobj->threshold; + + // Choose one of the paths you're not already on + mobj->threshold = P_RandomKey(8-1); + if (mobj->threshold >= curpath) + mobj->threshold++; if (mobj->state != &states[mobj->info->spawnstate]) P_SetMobjState(mobj, mobj->info->spawnstate); mobj->reactiontime--; - if (!mobj->reactiontime) - { - ffloor_t *rover; - - // Shock the water - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - if (!players[i].mo) - continue; - - if (players[i].mo->health <= 0) - continue; - - if (players[i].mo->eflags & MFE_UNDERWATER) - P_DamageMobj(players[i].mo, mobj, mobj, 1, 0); - } - - // Make the water flash - for (i = 0; i < numsectors; i++) - { - if (!sectors[i].ffloors) - continue; - - for (rover = sectors[i].ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS)) - continue; - - if (!(rover->flags & FF_SWIMMABLE)) - continue; - - P_SpawnLightningFlash(rover->master->frontsector); - break; - } - } - - if ((UINT32)mobj->extravalue1 + TICRATE*2 < leveltime) - { - mobj->extravalue1 = (INT32)leveltime; - S_StartSound(0, sfx_buzz1); - } - - // If in the center, check to make sure - // none of the players are in the water - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - if (!players[i].mo || players[i].bot) - continue; - - if (players[i].mo->health <= 0) - continue; - - if (players[i].mo->eflags & MFE_UNDERWATER) - { // Stay put - mobj->reactiontime = 2*TICRATE; - return; - } - } - } if (!mobj->reactiontime && mobj->health <= mobj->info->damage) { // Spawn pinch dummies from the center when we're leaving it. thinker_t *th; mobj_t *mo2; mobj_t *dummy; - SINT8 way = mobj->threshold - 1; // 0 through 4. - SINT8 way2; + SINT8 way0 = mobj->threshold; // 0 through 4. + SINT8 way1, way2; i = 0; // reset i to 0 so we can check how many clones we've removed @@ -4490,63 +4440,68 @@ static void P_Boss3Thinker(mobj_t *mobj) continue; mo2 = (mobj_t *)th; - if (mo2->type == (mobjtype_t)mobj->info->mass && mo2->tracer == mobj) - { - P_RemoveMobj(mo2); - i++; - } - if (i == 2) // we've already removed 2 of these, let's stop now + if (mo2->type != (mobjtype_t)mobj->info->mass) + continue; + if (mo2->tracer != mobj) + continue; + + P_RemoveMobj(mo2); + if (++i == 2) // we've already removed 2 of these, let's stop now break; } - way = (way + P_RandomRange(1,3)) % 5; // dummy 1 at one of the first three options after eggmobile + way1 = P_RandomKey(8-2); + if (way1 >= curpath) + way1++; + if (way1 >= way0) + { + way1++; + if (way1 == curpath) + way1++; + } + dummy = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->info->mass); dummy->angle = mobj->angle; - dummy->threshold = way + 1; - dummy->tracer = mobj; + dummy->threshold = way1; + P_SetTarget(&dummy->tracer, mobj); + dummy->movefactor = mobj->movefactor; + dummy->cusval = mobj->cusval; + + way2 = P_RandomKey(8-3); + if (way2 >= curpath) + way2++; + if (way2 >= way0) + { + way2++; + if (way2 == curpath) + way2++; + } + if (way2 >= way1) + { + way2++; + if (way2 == curpath || way2 == way0) + way2++; + } - do - way2 = (way + P_RandomRange(1,3)) % 5; // dummy 2 has to be careful, - while (way2 == mobj->threshold - 1); // to make sure it doesn't try to go the Eggman Way if dummy 1 rolled high. dummy = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->info->mass); dummy->angle = mobj->angle; - dummy->threshold = way2 + 1; - dummy->tracer = mobj; + dummy->threshold = way2; + P_SetTarget(&dummy->tracer, mobj); + dummy->movefactor = mobj->movefactor; + dummy->cusval = mobj->cusval; - CONS_Debug(DBG_GAMELOGIC, "Eggman path %d - Dummy selected paths %d and %d\n", mobj->threshold, way + 1, dummy->threshold); - P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); + CONS_Debug(DBG_GAMELOGIC, "Eggman path %d - Dummy selected paths %d and %d\n", way0, way1, way2); + P_LinedefExecute(LE_PINCHPHASE+(mobj->cusval*LE_PARAMWIDTH), mobj, NULL); } } else if (mobj->movecount) // Firing mode { - UINT32 i; - // look for a new target P_BossTargetPlayer(mobj, false); if (!mobj->target || !mobj->target->player) return; - // Are there any players underwater? If so, shock them! - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - if (!players[i].mo || players[i].bot) - continue; - - if (players[i].mo->health <= 0) - continue; - - if (players[i].mo->eflags & MFE_UNDERWATER) - { - mobj->movecount = 0; - P_SetMobjState(mobj, mobj->info->spawnstate); - return; - } - } - // Always face your target. A_FaceTarget(mobj); @@ -4561,9 +4516,7 @@ static void P_Boss3Thinker(mobj_t *mobj) } else if (mobj->threshold >= 0) // Traveling mode { - thinker_t *th; - mobj_t *mo2; - fixed_t dist, dist2; + fixed_t dist = 0; fixed_t speed; P_SetTarget(&mobj->target, NULL); @@ -4572,89 +4525,104 @@ static void P_Boss3Thinker(mobj_t *mobj) && !(mobj->flags2 & MF2_FRET)) P_SetMobjState(mobj, mobj->info->spawnstate); - // scan the thinkers - // to find a point that matches - // the number - for (th = thinkercap.next; th != &thinkercap; th = th->next) + if (!(mobj->flags2 & MF2_STRONGBOX)) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; + thinker_t *th; + mobj_t *mo2; - mo2 = (mobj_t *)th; - if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && mo2->spawnpoint->angle == mobj->threshold) + P_SetTarget(&mobj->tracer, NULL); + + // scan the thinkers + // to find a point that matches + // the number + for (th = thinkercap.next; th != &thinkercap; th = th->next) { - P_SetTarget(&mobj->target, mo2); + if (th->function.acp1 != (actionf_p1)P_MobjThinker) + continue; + + mo2 = (mobj_t *)th; + if (mo2->type != MT_BOSS3WAYPOINT) + continue; + if (!mo2->spawnpoint) + continue; + if (mo2->spawnpoint->angle != mobj->threshold) + continue; + if (mo2->spawnpoint->extrainfo != mobj->cusval) + continue; + + P_SetTarget(&mobj->tracer, mo2); break; } } - if (!mobj->target) // Should NEVER happen + if (!mobj->tracer) // Should NEVER happen { - CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 was unable to find specified waypoint: %d\n", mobj->threshold); + CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 was unable to find specified waypoint: %d, %d\n", mobj->threshold, mobj->cusval); return; } - dist = P_AproxDistance(P_AproxDistance(mobj->target->x - mobj->x, mobj->target->y - mobj->y), mobj->target->z - mobj->z); - - if (dist < 1) - dist = 1; - if ((mobj->movedir) || (mobj->health <= mobj->info->damage)) speed = mobj->info->speed * 2; else speed = mobj->info->speed; - mobj->momx = FixedMul(FixedDiv(mobj->target->x - mobj->x, dist), speed); - mobj->momy = FixedMul(FixedDiv(mobj->target->y - mobj->y, dist), speed); - mobj->momz = FixedMul(FixedDiv(mobj->target->z - mobj->z, dist), speed); - - if (mobj->momx != 0 || mobj->momy != 0) - mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); - - dist2 = P_AproxDistance(P_AproxDistance(mobj->target->x - (mobj->x + mobj->momx), mobj->target->y - (mobj->y + mobj->momy)), mobj->target->z - (mobj->z + mobj->momz)); - - if (dist2 < 1) - dist2 = 1; - - if ((dist >> FRACBITS) <= (dist2 >> FRACBITS)) + if (mobj->tracer->x == mobj->x && mobj->tracer->y == mobj->y) { - // If further away, set XYZ of mobj to waypoint location + // apply ambush for old routing, otherwise whack a mole only + dist = P_AproxDistance(P_AproxDistance(mobj->tracer->x - mobj->x, mobj->tracer->y - mobj->y), mobj->tracer->z + mobj->movefactor - mobj->z); + + if (dist < 1) + dist = 1; + + mobj->momx = FixedMul(FixedDiv(mobj->tracer->x - mobj->x, dist), speed); + mobj->momy = FixedMul(FixedDiv(mobj->tracer->y - mobj->y, dist), speed); + mobj->momz = FixedMul(FixedDiv(mobj->tracer->z + mobj->movefactor - mobj->z, dist), speed); + + if (mobj->momx != 0 || mobj->momy != 0) + mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); + } + + if (dist <= speed) + { + // If distance to point is less than travel in that frame, set XYZ of mobj to waypoint location P_UnsetThingPosition(mobj); - mobj->x = mobj->target->x; - mobj->y = mobj->target->y; - mobj->z = mobj->target->z; + mobj->x = mobj->tracer->x; + mobj->y = mobj->tracer->y; + mobj->z = mobj->tracer->z + mobj->movefactor; mobj->momx = mobj->momy = mobj->momz = 0; P_SetThingPosition(mobj); - if (mobj->threshold == 0) + if (!mobj->movefactor) // to firing mode { - mobj->reactiontime = 1; // Bzzt! Shock the water! - mobj->movedir = 0; + UINT8 i; + angle_t ang = 0; - if (mobj->health <= 0) + mobj->movecount = mobj->health+1; + mobj->movefactor = -512*FRACUNIT; + + // shock the water! + for (i = 0; i < 64; i++) { - mobj->flags |= MF_NOGRAVITY|MF_NOCLIP; - mobj->flags |= MF_NOCLIPHEIGHT; - mobj->threshold = -1; - return; + mobj_t *shock = P_SpawnMobjFromMobj(mobj, 0, 0, 4*FRACUNIT, MT_SHOCK); + P_SetTarget(&shock->target, mobj); + P_InstaThrust(shock, ang, shock->info->speed); + P_CheckMissileSpawn(shock); + ang += (ANGLE_MAX/64); } + S_StartSound(mobj, sfx_fizzle); } - - // Set to next waypoint in sequence - if (mobj->target->spawnpoint) + else if (mobj->flags2 & (MF2_STRONGBOX|MF2_CLASSICPUSH)) // just hit the bottom of your tube { - // From the center point, choose one of the five paths - if (mobj->target->spawnpoint->angle == 0) - mobj->threshold = P_RandomRange(1,5); - else - mobj->threshold = mobj->target->spawnpoint->extrainfo; - - // If the deaf flag is set, go into firing mode - if (mobj->target->spawnpoint->options & MTF_AMBUSH) - mobj->movecount = mobj->health+1; + mobj->flags2 &= ~(MF2_STRONGBOX|MF2_CLASSICPUSH); + mobj->reactiontime = 1; // spawn pinch dummies + mobj->movedir = 0; + } + else // just shifted to another tube + { + mobj->flags2 |= MF2_STRONGBOX; + if (mobj->health > 0) + mobj->movefactor = 0; } - else // This should never happen, as well - CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 waypoint has no spawnpoint associated with it.\n"); } } } @@ -7520,6 +7488,34 @@ void P_MobjThinker(mobj_t *mobj) return; } break; + case MT_FAKEMOBILE: + if (mobj->scale == mobj->destscale) + { + if (!mobj->fuse) + { + S_StartSound(mobj, sfx_s3k77); + mobj->flags2 |= MF2_DONTDRAW; + mobj->fuse = TICRATE; + } + return; + } + if (!mobj->reactiontime) + { + if (P_RandomChance(FRACUNIT/2)) + mobj->movefactor = FRACUNIT; + else + mobj->movefactor = -FRACUNIT; + if (P_RandomChance(FRACUNIT/2)) + mobj->movedir = ANG20; + else + mobj->movedir = -ANG20; + mobj->reactiontime = 5; + } + mobj->momz += mobj->movefactor; + mobj->angle += mobj->movedir; + P_InstaThrust(mobj, mobj->angle, -mobj->info->speed); + mobj->reactiontime--; + break; case MT_EGGSHIELD: mobj->flags2 ^= MF2_DONTDRAW; break; @@ -9278,6 +9274,10 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) // Special condition for the 2nd boss. mobj->watertop = mobj->info->speed; break; + case MT_EGGMOBILE3: + mobj->movefactor = -512*FRACUNIT; + mobj->flags2 |= MF2_CLASSICPUSH; + break; case MT_FLICKY_08: mobj->color = (P_RandomChance(FRACUNIT/2) ? SKINCOLOR_RED : SKINCOLOR_AQUA); break; @@ -9624,7 +9624,7 @@ consvar_t cv_flagtime = {"flagtime", "30", CV_NETVAR|CV_CHEAT, flagtime_cons_t, void P_SpawnPrecipitation(void) { - INT32 i, j, mrand; + INT32 i, mrand; fixed_t basex, basey, x, y, height; subsector_t *precipsector = NULL; precipmobj_t *rainmo = NULL; @@ -10665,6 +10665,9 @@ You should think about modifying the deathmatch starts to take full advantage of else skyboxviewpnts[mthing->extrainfo] = mobj; break; + case MT_EGGMOBILE3: + mobj->cusval = mthing->extrainfo; + break; case MT_FAN: if (mthing->options & MTF_OBJECTSPECIAL) { diff --git a/src/p_user.c b/src/p_user.c index 54ca6c78c..95fcf35aa 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4362,6 +4362,7 @@ void P_DoJumpShield(player_t *player) P_InstaThrust(spark, travelangle + i*(ANGLE_MAX/numangles), FixedMul(4*FRACUNIT, spark->scale)); if (i % 2) P_SetObjectMomZ(spark, -4*FRACUNIT, false); + spark->fuse = 18; } #undef limitangle #undef numangles From 658a3f2eea90a1f764c257fd4dd18dba0a51f0e0 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 30 Jun 2019 19:33:41 +0100 Subject: [PATCH 044/128] comment out unused variable --- src/p_mobj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 584403408..4f46116ca 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9624,7 +9624,7 @@ consvar_t cv_flagtime = {"flagtime", "30", CV_NETVAR|CV_CHEAT, flagtime_cons_t, void P_SpawnPrecipitation(void) { - INT32 i, j, mrand; + INT32 i /*, j*/, mrand; fixed_t basex, basey, x, y, height; subsector_t *precipsector = NULL; precipmobj_t *rainmo = NULL; From 726b0f6c83995ec5c2c63be6a36b858a33bc72d1 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 30 Jun 2019 22:22:12 +0100 Subject: [PATCH 045/128] correctly use P_UnsetThingPosition, P_SetThingPosition + P_DelSeclist around MF_NOBLOCKMAP addition in the TNT explosion code --- src/p_enemy.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 2861f4480..a817ee8a6 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -13015,7 +13015,14 @@ static boolean PIT_TNTExplode(mobj_t *nearby) nearby->momx = FixedMul(FixedDiv(dx, dm), explodethrust); nearby->momy = FixedMul(FixedDiv(dy, dm), explodethrust); nearby->momz = FixedMul(FixedDiv(dz, dm), explodethrust); + P_UnsetThingPosition(nearby); + if (sector_list) + { + P_DelSeclist(sector_list); + sector_list = NULL; + } nearby->flags = MF_NOBLOCKMAP|MF_MISSILE; + P_SetThingPosition(nearby); P_SetMobjState(nearby, nearby->info->missilestate); } } @@ -13059,8 +13066,14 @@ void A_TNTExplode(mobj_t *actor) if (LUA_CallAction("A_TNTExplode", actor)) return; #endif - + P_UnsetThingPosition(actor); + if (sector_list) + { + P_DelSeclist(sector_list); + sector_list = NULL; + } actor->flags = MF_NOCLIP|MF_NOGRAVITY|MF_NOBLOCKMAP; + P_SetThingPosition(actor); actor->flags2 = MF2_EXPLOSION; if (actor->info->deathsound) S_StartSound(actor, actor->info->deathsound); From 5cec737985765a825595dc3fe8914183c8f3bb90 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 3 Jul 2019 00:10:22 +0200 Subject: [PATCH 046/128] Remove character-specific flags, replace them with net-only/no-net flags --- src/dehacked.c | 5 ----- src/doomdata.h | 8 +++----- src/p_slopes.c | 10 +++++----- src/p_spec.c | 36 ++++++++++++------------------------ 4 files changed, 20 insertions(+), 39 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index d86161390..ac1709cbf 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -9573,11 +9573,6 @@ static inline int lib_getenum(lua_State *L) lua_pushinteger(L, ((lua_Integer)1<flags & ML_NOSONIC) + if (line->flags & ML_NETONLY) flags |= SL_NOPHYSICS; - if (line->flags & ML_NOTAILS) + if (line->flags & ML_NONET) flags |= SL_DYNAMIC; if(!frontfloor && !backfloor && !frontceil && !backceil) @@ -468,9 +468,9 @@ static void line_SpawnViaVertexes(const int linenum, const boolean spawnthinker) UINT16 tag1, tag2, tag3; UINT8 flags = 0; - if (line->flags & ML_NOSONIC) + if (line->flags & ML_NETONLY) flags |= SL_NOPHYSICS; - if (line->flags & ML_NOTAILS) + if (line->flags & ML_NONET) flags |= SL_DYNAMIC; switch(line->special) @@ -494,7 +494,7 @@ static void line_SpawnViaVertexes(const int linenum, const boolean spawnthinker) return; } - if (line->flags & ML_NOKNUX) + if (line->flags & ML_EFFECT6) { tag1 = line->tag; tag2 = side->textureoffset >> FRACBITS; diff --git a/src/p_spec.c b/src/p_spec.c index c6679e190..ae63e53bf 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6322,7 +6322,7 @@ void P_InitSpecials(void) static void P_ApplyFlatAlignment(line_t *master, sector_t *sector, angle_t flatangle, fixed_t xoffs, fixed_t yoffs) { - if (!(master->flags & ML_NOSONIC)) // Modify floor flat alignment unless NOSONIC flag is set + if (!(master->flags & ML_NETONLY)) // Modify floor flat alignment unless ML_NETONLY flag is set { sector->spawn_flrpic_angle = sector->floorpic_angle = flatangle; sector->floor_xoffs += xoffs; @@ -6332,7 +6332,7 @@ static void P_ApplyFlatAlignment(line_t *master, sector_t *sector, angle_t flata sector->spawn_flr_yoffs = sector->floor_yoffs; } - if (!(master->flags & ML_NOTAILS)) // Modify ceiling flat alignment unless NOTAILS flag is set + if (!(master->flags & ML_NONET)) // Modify ceiling flat alignment unless ML_NONET flag is set { sector->spawn_ceilpic_angle = sector->ceilingpic_angle = flatangle; sector->ceiling_xoffs += xoffs; @@ -6463,28 +6463,22 @@ void P_SpawnSpecials(INT32 fromnetsave) // Init line EFFECTs for (i = 0; i < numlines; i++) { - if (lines[i].special != 7) // This is a hack. I can at least hope nobody wants to prevent flat alignment with arbitrary skin setups... + if (lines[i].special != 7) // This is a hack. I can at least hope nobody wants to prevent flat alignment in netgames... { // set line specials to 0 here too, same reason as above if (netgame || multiplayer) { - // future: nonet flag? + if ((lines[i].flags & ML_NONET) == ML_NONET) + { + lines[i].special = 0; + continue; + } } else if ((lines[i].flags & ML_NETONLY) == ML_NETONLY) { lines[i].special = 0; continue; } - else - { - if ((players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC)) - || (players[consoleplayer].charability == CA_FLY && (lines[i].flags & ML_NOTAILS)) - || (players[consoleplayer].charability == CA_GLIDEANDCLIMB && (lines[i].flags & ML_NOKNUX))) - { - lines[i].special = 0; - continue; - } - } } switch (lines[i].special) @@ -6530,13 +6524,13 @@ void P_SpawnSpecials(INT32 fromnetsave) #endif case 7: // Flat alignment - redone by toast - if ((lines[i].flags & (ML_NOSONIC|ML_NOTAILS)) != (ML_NOSONIC|ML_NOTAILS)) // If you can do something... + if ((lines[i].flags & (ML_NETONLY|ML_NONET)) != (ML_NETONLY|ML_NONET)) // If you can do something... { angle_t flatangle = InvAngle(R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y)); fixed_t xoffs; fixed_t yoffs; - if (lines[i].flags & ML_NOKNUX) // Set offset through x and y texture offsets if NOKNUX flag is set + if (lines[i].flags & ML_EFFECT6) // Set offset through x and y texture offsets if ML_EFFECT6 flag is set { xoffs = sides[lines[i].sidenum[0]].textureoffset; yoffs = sides[lines[i].sidenum[0]].rowoffset; @@ -9194,19 +9188,13 @@ static void P_SearchForDisableLinedefs(void) // that P_InitTagLists literally just created! lines[i].special = 0; - // Ability flags can disable disable linedefs now, lol if (netgame || multiplayer) { - // future: nonet flag? + if ((lines[i].flags & ML_NONET) == ML_NONET) + continue; } else if ((lines[i].flags & ML_NETONLY) == ML_NETONLY) continue; // Net-only never triggers in single player - else if (players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC)) - continue; - else if (players[consoleplayer].charability == CA_FLY && (lines[i].flags & ML_NOTAILS)) - continue; - else if (players[consoleplayer].charability == CA_GLIDEANDCLIMB && (lines[i].flags & ML_NOKNUX)) - continue; // Disable any linedef specials with our tag. for (j = -1; (j = P_FindLineFromLineTag(&lines[i], j)) >= 0;) From c04b560e9260ae1f57834cd2e68e3f3bfca19c18 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Tue, 2 Jul 2019 23:49:10 +0000 Subject: [PATCH 047/128] Revert "Merge branch 'metalfixes' into 'toast_cleanup'" This reverts merge request !239 --- src/dehacked.c | 5 +- src/hardware/hw_main.c | 2 +- src/hardware/hw_md2.c | 2 +- src/info.c | 27 ++-- src/info.h | 5 +- src/lua_baselib.c | 4 +- src/p_local.h | 2 +- src/p_map.c | 21 --- src/p_mobj.c | 360 ++++++++++------------------------------- src/p_user.c | 45 +++--- src/r_draw.c | 7 +- src/r_things.c | 2 +- src/sounds.c | 4 +- 13 files changed, 135 insertions(+), 351 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 7935c474f..f532bde68 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -5125,10 +5125,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_METALSONIC_BADBOUNCE", "S_METALSONIC_SHOOT", "S_METALSONIC_PAIN", - "S_METALSONIC_DEATH1", - "S_METALSONIC_DEATH2", - "S_METALSONIC_DEATH3", - "S_METALSONIC_DEATH4", + "S_METALSONIC_DEATH", "S_METALSONIC_FLEE1", "S_METALSONIC_FLEE2", "S_METALSONIC_FLEE3", diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index d649eeb8e..a76c9e1c8 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5662,7 +5662,7 @@ static void HWR_ProjectSprite(mobj_t *thing) //Hurdler: 25/04/2000: now support colormap in hardware mode if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash" { - if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized) + if (vis->mobj->type == MT_CYBRAKDEMON) vis->colormap = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE); else if (vis->mobj->type == MT_METALSONIC_BATTLE) vis->colormap = R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE); diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index e26aa98ff..6db5d5f08 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1363,7 +1363,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) INT32 skinnum = TC_DEFAULT; if ((spr->mobj->flags & (MF_ENEMY|MF_BOSS)) && (spr->mobj->flags2 & MF2_FRET) && !(spr->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash" { - if (spr->mobj->type == MT_CYBRAKDEMON || spr->mobj->colorized) + if (spr->mobj->type == MT_CYBRAKDEMON) skinnum = TC_ALLWHITE; else if (spr->mobj->type == MT_METALSONIC_BATTLE) skinnum = TC_METALSONIC; diff --git a/src/info.c b/src/info.c index a58b2313c..477c3f372 100644 --- a/src/info.c +++ b/src/info.c @@ -1747,23 +1747,20 @@ state_t states[NUMSTATES] = {SPR_METL, 9, 2, {NULL}, 0, 0, S_METALSONIC_RUN1}, // S_METALSONIC_RUN4 {SPR_METL, 4, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_FLOAT - {SPR_METL, 12|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR - {SPR_METL, 11, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN - {SPR_METL, 13, 20, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE + {SPR_METL, 12, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR + {SPR_METL, 0, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN + {SPR_METL, 13, 40, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE {SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_GATHER {SPR_METL, 15, -1, {NULL}, 0, 0, S_METALSONIC_BOUNCE},// S_METALSONIC_DASH {SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BOUNCE {SPR_METL, 16, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BADBOUNCE {SPR_METL, 13, -1, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_SHOOT {SPR_METL, 11, 40, {A_Pain}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_PAIN - {SPR_METL, 13, 8, {A_Fall}, 0, 0, S_METALSONIC_DEATH2},// S_METALSONIC_DEATH1 - {SPR_METL, 13, 8, {A_BossScream}, 0, 0, S_METALSONIC_DEATH3},// S_METALSONIC_DEATH2 - {SPR_METL, 13, 0, {A_Repeat}, 11, S_METALSONIC_DEATH2, S_METALSONIC_DEATH4}, // S_METALSONIC_DEATH3 - {SPR_METL, 13, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH4 - {SPR_METL, 11, 4, {NULL}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1 - {SPR_METL, 11, 4, {A_BossScream}, 0, 0, S_METALSONIC_FLEE3}, // S_METALSONIC_FLEE2 - {SPR_METL, 11, 4, {NULL}, 0, 0, S_METALSONIC_FLEE4}, // S_METALSONIC_FLEE3 - {SPR_METL, 11, 4, {NULL}, 0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE4 + {SPR_METL, 11, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH + {SPR_METL, 3, 4, {NULL}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1 + {SPR_METL, 4, 4, {A_BossScream}, 0, 0, S_METALSONIC_FLEE3}, // S_METALSONIC_FLEE2 + {SPR_METL, 5, 4, {NULL}, 0, 0, S_METALSONIC_FLEE4}, // S_METALSONIC_FLEE3 + {SPR_METL, 4, 4, {NULL}, 0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE4 {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 0, 1, {NULL}, 0, 0, S_MSSHIELD_F2}, // S_MSSHIELD_F1 {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 1, 1, {NULL}, 0, 0, S_MSSHIELD_F3}, // S_MSSHIELD_F2 @@ -6262,13 +6259,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_METALSONIC_DASH, // seestate sfx_s3k54, // seesound 0, // reactiontime - sfx_bechrg, // attacksound + sfx_trpowr, // attacksound S_METALSONIC_PAIN, // painstate S_METALSONIC_VECTOR,// painchance sfx_dmpain, // painsound S_METALSONIC_BADBOUNCE, // meleestate S_METALSONIC_SHOOT, // missilestate - S_METALSONIC_DEATH1,// deathstate + S_METALSONIC_DEATH, // deathstate S_METALSONIC_FLEE1, // xdeathstate sfx_s3k6e, // deathsound MT_ENERGYBALL, // speed @@ -6300,7 +6297,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // deathsound 0, // speed 32*FRACUNIT, // radius - 52*FRACUNIT, // height + 64*FRACUNIT, // height 0, // display offset 0, // mass 0, // damage @@ -9143,7 +9140,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_ENERGYBALL1, // spawnstate 1000, // spawnhealth S_NULL, // seestate - sfx_bexpld, // seesound + sfx_s3k54, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate diff --git a/src/info.h b/src/info.h index c1891a766..a7f5d775a 100644 --- a/src/info.h +++ b/src/info.h @@ -1888,10 +1888,7 @@ typedef enum state S_METALSONIC_BADBOUNCE, S_METALSONIC_SHOOT, S_METALSONIC_PAIN, - S_METALSONIC_DEATH1, - S_METALSONIC_DEATH2, - S_METALSONIC_DEATH3, - S_METALSONIC_DEATH4, + S_METALSONIC_DEATH, S_METALSONIC_FLEE1, S_METALSONIC_FLEE2, S_METALSONIC_FLEE3, diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 81a17ef20..e6119cd6c 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1235,8 +1235,8 @@ static int lib_pHomingAttack(lua_State *L) INLEVEL if (!source || !enemy) return LUA_ErrInvalid(L, "mobj_t"); - lua_pushboolean(L, P_HomingAttack(source, enemy)); - return 1; + P_HomingAttack(source, enemy); + return 0; } static int lib_pSuperReady(lua_State *L) diff --git a/src/p_local.h b/src/p_local.h index 479994079..8aeddf162 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -176,7 +176,7 @@ void P_InstaThrustEvenIn2D(mobj_t *mo, angle_t angle, fixed_t move); mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet); void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius); -boolean P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user +void P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user boolean P_SuperReady(player_t *player); void P_DoJump(player_t *player, boolean soundandstate); #if 0 diff --git a/src/p_map.c b/src/p_map.c index a852a3933..76b6535b5 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -725,27 +725,6 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; } - // vectorise metal - done in a special case as at this point neither has the right flags for touching - if (thing->type == MT_METALSONIC_BATTLE - && (tmthing->flags & MF_MISSILE) - && tmthing->target != thing - && thing->state == &states[thing->info->spawnstate]) - { - blockdist = thing->radius + tmthing->radius; - - if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) - return true; // didn't hit it - - if (tmthing->z > thing->z + thing->height) - return true; // overhead - if (tmthing->z + tmthing->height < thing->z) - return true; // underneath - - thing->flags2 |= MF2_CLASSICPUSH; - - return true; - } - if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_PAIN|MF_SHOOTABLE|MF_SPRING))) return true; diff --git a/src/p_mobj.c b/src/p_mobj.c index ff2bcc77f..70017546c 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5395,8 +5395,7 @@ static void P_Boss7Thinker(mobj_t *mobj) if (mobj->info->activesound)\ S_StartSound(mobj, mobj->info->activesound);\ if (mobj->info->painchance)\ - P_SetMobjState(mobj, mobj->info->painchance);\ - mobj->flags2 &= ~MF2_INVERTAIMABLE;\ + P_SetMobjState(mobj, mobj->info->painchance) // Metal Sonic battle boss // You CAN put multiple Metal Sonics in a single map @@ -5486,16 +5485,25 @@ static void P_Boss9Thinker(mobj_t *mobj) // AI goes here. { angle_t angle; - if (mobj->threshold || mobj->movecount) + if (mobj->threshold) mobj->momz = (mobj->watertop-mobj->z)/16; // Float to your desired position FASTER else mobj->momz = (mobj->watertop-mobj->z)/40; // Float to your desired position - if (mobj->movecount == 2) - { + if (mobj->movecount == 2) { mobj_t *spawner; fixed_t dist = 0; - angle = 0x06000000*leveltime; // wtf? + angle = 0x06000000*leveltime; + + // Alter your energy bubble's size/position + if (mobj->health > 3) { + mobj->tracer->destscale = FRACUNIT + (4*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2); + P_SetScale(mobj->tracer, mobj->tracer->destscale); + P_TeleportMove(mobj->tracer, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->tracer->height/2); + mobj->tracer->momx = mobj->momx; + mobj->tracer->momy = mobj->momy; + mobj->tracer->momz = mobj->momz; + } // Face your target P_BossTargetPlayer(mobj, true); @@ -5506,150 +5514,27 @@ static void P_Boss9Thinker(mobj_t *mobj) else mobj->angle -= InvAngle(angle)/8; - // Alter your energy bubble's size/position - if (mobj->health > 3) - { - mobj->tracer->destscale = FRACUNIT + (4*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2); - P_SetScale(mobj->tracer, mobj->tracer->destscale); - } - else - mobj->tracer->frame &= ~FF_TRANSMASK; // this causes a flicker but honestly i like it this way - P_TeleportMove(mobj->tracer, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->tracer->height/2); - mobj->tracer->momx = mobj->momx; - mobj->tracer->momy = mobj->momy; - mobj->tracer->momz = mobj->momz; - - // Firin' mah lazors - INDICATOR - if (mobj->fuse > TICRATE/2) - { - tic_t shoottime, worktime, calctime; - shoottime = (TICRATE/((mobj->extravalue1 == 3) ? 8 : 4)); - shoottime += (shoottime>>1); - worktime = shoottime*(mobj->threshold/2); - calctime = mobj->fuse-(TICRATE/2); - - if (calctime <= worktime && (calctime % shoottime == 0)) - { - mobj_t *missile; - - missile = P_SpawnMissile(mobj, mobj->target, MT_MSGATHER); - S_StopSound(missile); - if (mobj->extravalue1 >= 2) - P_SetScale(missile, FRACUNIT>>1); - missile->destscale = missile->scale>>1; - missile->fuse = TICRATE/2; - missile->scalespeed = abs(missile->destscale - missile->scale)/missile->fuse; - missile->z -= missile->height/2; - missile->momx *= -1; - missile->momy *= -1; - missile->momz *= -1; - - if (mobj->extravalue1 == 2) - { - UINT8 i; - mobj_t *spread; - for (i = 0; i < 5; i++) - { - if (i == 2) - continue; - spread = P_SpawnMobj(missile->x, missile->y, missile->z, missile->type); - spread->angle = missile->angle+(ANGLE_11hh/2)*(i-2); - P_InstaThrust(spread,spread->angle,-spread->info->speed); - spread->momz = missile->momz; - P_SetScale(spread, missile->scale); - spread->destscale = missile->destscale; - spread->scalespeed = missile->scalespeed; - spread->fuse = missile->fuse; - P_UnsetThingPosition(spread); - spread->x -= spread->fuse*spread->momx; - spread->y -= spread->fuse*spread->momy; - spread->z -= spread->fuse*spread->momz; - P_SetThingPosition(spread); - } - P_InstaThrust(missile,missile->angle,-missile->info->speed); - } - else if (mobj->extravalue1 >= 3) - { - UINT8 i; - mobj_t *spread; - mobj->target->z -= (4*missile->height); - for (i = 0; i < 5; i++) - { - if (i != 2) - { - spread = P_SpawnMissile(mobj, mobj->target, missile->type); - P_SetScale(spread, missile->scale); - spread->destscale = missile->destscale; - spread->fuse = missile->fuse; - spread->z -= spread->height/2; - spread->momx *= -1; - spread->momy *= -1; - spread->momz *= -1; - P_UnsetThingPosition(spread); - spread->x -= spread->fuse*spread->momx; - spread->y -= spread->fuse*spread->momy; - spread->z -= spread->fuse*spread->momz; - P_SetThingPosition(spread); - } - mobj->target->z += missile->height*2; - } - mobj->target->z -= (6*missile->height); - } - - P_UnsetThingPosition(missile); - missile->x -= missile->fuse*missile->momx; - missile->y -= missile->fuse*missile->momy; - missile->z -= missile->fuse*missile->momz; - P_SetThingPosition(missile); - - S_StartSound(mobj, sfx_s3kb3); - } - } - - // up... - mobj->z += mobj->height/2; - // Spawn energy particles - for (spawner = mobj->hnext; spawner; spawner = spawner->hnext) - { + for (spawner = mobj->hnext; spawner; spawner = spawner->hnext) { dist = P_AproxDistance(spawner->x - mobj->x, spawner->y - mobj->y); if (P_RandomRange(1,(dist>>FRACBITS)/16) == 1) break; } - if (spawner) - { + if (spawner) { mobj_t *missile = P_SpawnMissile(spawner, mobj, MT_MSGATHER); - + if (mobj->health > mobj->info->damage) + missile->momz = FixedDiv(missile->momz, 7*FRACUNIT/5); if (dist == 0) missile->fuse = 0; else missile->fuse = (dist/P_AproxDistance(missile->momx, missile->momy)); - if (missile->fuse > mobj->fuse) P_RemoveMobj(missile); - - if (mobj->health > mobj->info->damage) - { - P_SetScale(missile, FRACUNIT/2); - missile->color = SKINCOLOR_GOLD; // sonic cd electric power - } - else - { - P_SetScale(missile, FRACUNIT/4); - missile->color = SKINCOLOR_MAGENTA; // sonic OVA/4 purple power - } - missile->destscale = missile->scale*2; - missile->scalespeed = abs(missile->scale - missile->destscale)/missile->fuse; - missile->colorized = true; } - - // ...then down. easier than changing the missile's momz after-the-fact - mobj->z -= mobj->height/2; } // Pre-threshold reactiontime stuff for attack phases - if (mobj->reactiontime && mobj->movecount == 3) - { + if (mobj->reactiontime && mobj->movecount == 3) { mobj->reactiontime--; if (mobj->movedir == 0 || mobj->movedir == 2) { // Pausing between bounces in the pinball phase @@ -5670,15 +5555,13 @@ static void P_Boss9Thinker(mobj_t *mobj) } // threshold is used for attacks/maneuvers. - if (mobj->threshold && mobj->movecount != 2) { + if (mobj->threshold) { fixed_t speed = 20*FRACUNIT + FixedMul(40*FRACUNIT, FixedDiv((mobj->info->spawnhealth - mobj->health)<info->spawnhealth<movecount == 3 && mobj->movedir == 1) - { - if (!(mobj->threshold & 1)) - { + if (mobj->movecount == 3 && mobj->movedir == 1) { + if (!(mobj->threshold&1)) { mobj_t *missile; if (mobj->info->seesound) S_StartSound(mobj, mobj->info->seesound); @@ -5690,20 +5573,18 @@ static void P_Boss9Thinker(mobj_t *mobj) A_FaceTarget(mobj); missile = P_SpawnMissile(mobj, mobj->target, mobj->info->speed); - if (mobj->extravalue1 >= 2) - { + if (mobj->extravalue1 == 2 || mobj->extravalue1 == 3) { missile->destscale = FRACUNIT>>1; P_SetScale(missile, missile->destscale); } missile->fuse = 3*TICRATE; missile->z -= missile->height/2; - if (mobj->extravalue1 == 2) - { - UINT8 i; + if (mobj->extravalue1 == 2) { + int i; mobj_t *spread; - for (i = 0; i < 5; i++) - { + missile->flags |= MF_MISSILE; + for (i = 0; i < 5; i++) { if (i == 2) continue; spread = P_SpawnMobj(missile->x, missile->y, missile->z, missile->type); @@ -5712,32 +5593,11 @@ static void P_Boss9Thinker(mobj_t *mobj) spread->momz = missile->momz; spread->destscale = FRACUNIT>>1; P_SetScale(spread, spread->destscale); - spread->fuse = missile->fuse; + spread->fuse = 3*TICRATE; } - P_InstaThrust(missile,missile->angle,missile->info->speed); + missile->flags &= ~MF_MISSILE; } - else if (mobj->extravalue1 >= 3) - { - UINT8 i; - mobj_t *spread; - mobj->target->z -= (2*missile->height); - for (i = 0; i < 5; i++) - { - if (i != 2) - { - spread = P_SpawnMissile(mobj, mobj->target, missile->type); - spread->destscale = FRACUNIT>>1; - P_SetScale(spread, spread->destscale); - spread->fuse = missile->fuse; - spread->z -= spread->height/2; - } - mobj->target->z += missile->height; - } - mobj->target->z -= (3*missile->height); - } - } - else - { + } else { P_SetMobjState(mobj, mobj->state->nextstate); if (mobj->extravalue1 == 3) mobj->reactiontime = TICRATE/8; @@ -5751,8 +5611,7 @@ static void P_Boss9Thinker(mobj_t *mobj) P_SpawnGhostMobj(mobj); // Pinball attack! - if (mobj->movecount == 3 && (mobj->movedir == 0 || mobj->movedir == 2)) - { + if (mobj->movecount == 3 && (mobj->movedir == 0 || mobj->movedir == 2)) { if ((statenum_t)(mobj->state-states) != mobj->info->seestate) P_SetMobjState(mobj, mobj->info->seestate); if (mobj->movedir == 0) // mobj health == 1 @@ -5761,8 +5620,7 @@ static void P_Boss9Thinker(mobj_t *mobj) P_InstaThrust(mobj, mobj->angle, 22*FRACUNIT); else // mobj health == 2 P_InstaThrust(mobj, mobj->angle, 30*FRACUNIT); - if (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true)) - { // Hit a wall? Find a direction to bounce + if (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true)) { // Hit a wall? Find a direction to bounce mobj->threshold--; P_SetMobjState(mobj, mobj->state->nextstate); if (!mobj->threshold) { // failed bounce! @@ -5775,15 +5633,11 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->movecount = 0; P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_CYBRAKDEMON_VILE_EXPLOSION); P_SetMobjState(mobj, mobj->info->meleestate); - } - else if (!(mobj->threshold%4)) - { // We've decided to lock onto the player this bounce. + } else if (!(mobj->threshold%4)) { // We've decided to lock onto the player this bounce. S_StartSound(mobj, sfx_s3k5a); mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4); mobj->reactiontime = TICRATE - 5*(mobj->info->damage - mobj->health); // targetting time - } - else - { // No homing, just use P_BounceMove + } else { // No homing, just use P_BounceMove S_StartSound(mobj, sfx_s3kaa); // make the bounces distinct... P_BounceMove(mobj); mobj->angle = R_PointToAngle2(0,0,mobj->momx,mobj->momy); @@ -5797,8 +5651,7 @@ static void P_Boss9Thinker(mobj_t *mobj) // Vector form dodge! mobj->angle += mobj->movedir; P_InstaThrust(mobj, mobj->angle, -speed); - while (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true) && tries++ < 16) - { + while (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true) && tries++ < 16) { S_StartSound(mobj, sfx_mspogo); P_BounceMove(mobj); mobj->angle = R_PointToAngle2(mobj->momx, mobj->momy,0,0); @@ -5855,7 +5708,7 @@ static void P_Boss9Thinker(mobj_t *mobj) if (mobj->flags2 & MF2_FRET) return; - if (mobj->movecount == 1 || mobj->movecount == 2) + if (mobj->state == &states[mobj->info->raisestate]) { // Charging energy if (mobj->momx != 0 || mobj->momy != 0) { // Apply the air breaks if (abs(mobj->momx)+abs(mobj->momy) < FRACUNIT) @@ -5863,13 +5716,11 @@ static void P_Boss9Thinker(mobj_t *mobj) else P_Thrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), -6*FRACUNIT/8); } - if (mobj->state == states+mobj->info->raisestate) - return; + return; } if (mobj->fuse == 0) { - mobj->flags2 &= ~MF2_INVERTAIMABLE; // It's time to attack! What are we gonna do?! switch(mobj->movecount) { @@ -5877,7 +5728,6 @@ static void P_Boss9Thinker(mobj_t *mobj) default: // Fly up and prepare for an attack! // We have to charge up first, so let's go up into the air - S_StartSound(mobj, sfx_beflap); P_SetMobjState(mobj, mobj->info->raisestate); if (mobj->floorz >= mobj->target->floorz) mobj->watertop = mobj->floorz + 256*FRACUNIT; @@ -5885,69 +5735,33 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->watertop = mobj->target->floorz + 256*FRACUNIT; break; - case 1: + case 1: { // Okay, we're up? Good, time to gather energy... if (mobj->health > mobj->info->damage) { // No more bubble if we're broken (pinch phase) mobj_t *shield = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_MSSHIELD_FRONT); P_SetTarget(&mobj->tracer, shield); P_SetTarget(&shield->target, mobj); - - // Attack 2: Energy shot! - switch (mobj->health) - { - case 8: // shoot once - default: - mobj->extravalue1 = 0; - mobj->threshold = 2; - break; - case 7: // spread shot (vertical) - mobj->extravalue1 = 4; - mobj->threshold = 2; - break; - case 6: // three shots - mobj->extravalue1 = 1; - mobj->threshold = 3*2; - break; - case 5: // spread shot (horizontal) - mobj->extravalue1 = 2; - mobj->threshold = 2; - break; - case 4: // machine gun - mobj->extravalue1 = 3; - mobj->threshold = 5*2; - break; - } } else - { - mobj_t *shield = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_MSSHIELD_FRONT); - P_SetTarget(&mobj->tracer, shield); - P_SetTarget(&shield->target, mobj); - shield->height -= 20*FRACUNIT; // different offset... - shield->color = SKINCOLOR_MAGENTA; - shield->colorized = true; - P_SetMobjState(shield, S_FIRS1); - //P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); -- why does this happen twice? see case 2... - } + P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); mobj->fuse = 4*TICRATE; mobj->flags |= MF_PAIN; if (mobj->info->attacksound) S_StartSound(mobj, mobj->info->attacksound); A_FaceTarget(mobj); - break; + } case 2: // We're all charged and ready now! Unleash the fury!! - S_StopSound(mobj); - mobj_t *removemobj = mobj->tracer; - P_SetTarget(&mobj->tracer, mobj->hnext); - P_RemoveMobj(removemobj); - if (mobj->health <= mobj->info->damage) + if (mobj->health > mobj->info->damage) { - mobj_t *whoosh; - + mobj_t *removemobj = mobj->tracer; + P_SetTarget(&mobj->tracer, mobj->hnext); + P_RemoveMobj(removemobj); + } + if (mobj->health <= mobj->info->damage) { // Attack 1: Pinball dash! if (mobj->health == 1) mobj->movedir = 0; @@ -5962,23 +5776,32 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->threshold = 24; // bounce 24 times mobj->watertop = mobj->target->floorz + 16*FRACUNIT; P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); - - whoosh = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_GHOST); // done here so the offset is correct - whoosh->frame = FF_FULLBRIGHT; - whoosh->sprite = SPR_ARMA; - whoosh->destscale = whoosh->scale<<1; - whoosh->scalespeed = FixedMul(whoosh->scalespeed, whoosh->scale); - whoosh->height = 38*whoosh->scale; - whoosh->fuse = 10; - whoosh->color = SKINCOLOR_MAGENTA; - whoosh->colorized = true; - whoosh->flags |= MF_NOCLIPHEIGHT; - } - else - { + } else { // Attack 2: Energy shot! mobj->movedir = 1; - // looking for the number of things to fire? that's done in case 1 now + + if (mobj->health >= 8) + mobj->extravalue1 = 0; + else if (mobj->health >= 5) + mobj->extravalue1 = 2; + else if (mobj->health >= 4) + mobj->extravalue1 = 1; + else + mobj->extravalue1 = 3; + + switch(mobj->extravalue1) { + case 0: // shoot once + case 2: // spread-shot + default: + mobj->threshold = 2; + break; + case 1: // shoot 3 times + mobj->threshold = 3*2; + break; + case 3: // shoot like a goddamn machinegun + mobj->threshold = 8*2; + break; + } } break; @@ -6012,26 +5835,21 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->angle -= InvAngle(angle)/8; //A_FaceTarget(mobj); - if (mobj->flags2 & MF2_CLASSICPUSH) - mobj->flags2 &= ~MF2_CLASSICPUSH; // a missile caught us in PIT_CheckThing! - else - { - // Check if we're being attacked - if (!mobj->target || !mobj->target->player || !P_PlayerCanDamage(mobj->target->player, mobj)) - goto nodanger; - if (mobj->target->x+mobj->target->radius+abs(mobj->target->momx*2) < mobj->x-mobj->radius) - goto nodanger; - if (mobj->target->x-mobj->target->radius-abs(mobj->target->momx*2) > mobj->x+mobj->radius) - goto nodanger; - if (mobj->target->y+mobj->target->radius+abs(mobj->target->momy*2) < mobj->y-mobj->radius) - goto nodanger; - if (mobj->target->y-mobj->target->radius-abs(mobj->target->momy*2) > mobj->y+mobj->radius) - goto nodanger; - if (mobj->target->z+mobj->target->height+mobj->target->momz*2 < mobj->z) - goto nodanger; - if (mobj->target->z+mobj->target->momz*2 > mobj->z+mobj->height) - goto nodanger; - } + // Check if we're being attacked + if (!mobj->target || !mobj->target->player || !P_PlayerCanDamage(mobj->target->player, mobj)) + goto nodanger; + if (mobj->target->x+mobj->target->radius+abs(mobj->target->momx*2) < mobj->x-mobj->radius) + goto nodanger; + if (mobj->target->x-mobj->target->radius-abs(mobj->target->momx*2) > mobj->x+mobj->radius) + goto nodanger; + if (mobj->target->y+mobj->target->radius+abs(mobj->target->momy*2) < mobj->y-mobj->radius) + goto nodanger; + if (mobj->target->y-mobj->target->radius-abs(mobj->target->momy*2) > mobj->y+mobj->radius) + goto nodanger; + if (mobj->target->z+mobj->target->height+mobj->target->momz*2 < mobj->z) + goto nodanger; + if (mobj->target->z+mobj->target->momz*2 > mobj->z+mobj->height) + goto nodanger; // An incoming attack is detected! What should we do?! // Go into vector form! @@ -6039,17 +5857,13 @@ static void P_Boss9Thinker(mobj_t *mobj) return; nodanger: - mobj->flags2 |= MF2_INVERTAIMABLE; - // Move normally: Approach the player using normal thrust and simulated friction. dist = P_AproxDistance(mobj->x-mobj->target->x, mobj->y-mobj->target->y); P_Thrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), -3*FRACUNIT/8); - if (dist < 64*FRACUNIT && !(mobj->target->player && mobj->target->player->homing)) + if (dist < 64*FRACUNIT) P_Thrust(mobj, mobj->angle, -4*FRACUNIT); else if (dist > 180*FRACUNIT) P_Thrust(mobj, mobj->angle, FRACUNIT); - else - P_Thrust(mobj, mobj->angle + ANGLE_90, FINECOSINE((((angle_t)(leveltime*ANG1))>>ANGLETOFINESHIFT) & FINEMASK)>>1); mobj->momz += P_AproxDistance(mobj->momx, mobj->momy)/12; // Move up higher the faster you're going. } } diff --git a/src/p_user.c b/src/p_user.c index 0d38fd876..ac951a8fa 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4803,10 +4803,10 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) player->mo->momx /= 2; player->mo->momy /= 2; } - if (player->charability == CA_HOMINGTHOK) + else if (player->charability == CA_HOMINGTHOK) { - player->mo->momx /= 2; - player->mo->momy /= 2; + player->mo->momx /= 3; + player->mo->momy /= 3; } if (player->charability == CA_HOMINGTHOK) @@ -7923,7 +7923,7 @@ static void P_MovePlayer(player_t *player) if (!(player->pflags & (PF_USEDOWN|PF_GLIDING|PF_SLIDING|PF_SHIELDABILITY)) // If the player is not holding down BT_USE, or having used an ability previously && (!(player->powers[pw_shield] & SH_NOSTACK) || !(player->pflags & PF_THOKKED) || ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP && player->secondjump == UINT8_MAX))) // thokked is optional if you're bubblewrapped/turning super { - // Force stop + // Force shield activation if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE) { player->pflags |= PF_THOKKED|PF_SHIELDABILITY; @@ -7939,17 +7939,17 @@ static void P_MovePlayer(player_t *player) if (P_SuperReady(player)) P_DoSuperTransformation(player, false); break; - // Whirlwind jump/Thunder jump + // Whirlwind/Thundercoin shield activation case SH_WHIRLWIND: case SH_THUNDERCOIN: P_DoJumpShield(player); break; - // Armageddon pow + // Armageddon shield activation case SH_ARMAGEDDON: player->pflags |= PF_THOKKED|PF_SHIELDABILITY; P_BlackOw(player); break; - // Attraction blast + // Attract shield activation case SH_ATTRACT: player->pflags |= PF_THOKKED|PF_SHIELDABILITY; player->homing = 2; @@ -7965,7 +7965,7 @@ static void P_MovePlayer(player_t *player) else S_StartSound(player->mo, sfx_s3ka6); break; - // Elemental stomp/Bubble bounce + // Elemental/Bubblewrap shield activation case SH_ELEMENTAL: case SH_BUBBLEWRAP: player->pflags |= PF_THOKKED|PF_SHIELDABILITY; @@ -7979,7 +7979,7 @@ static void P_MovePlayer(player_t *player) ? sfx_s3k43 : sfx_s3k44); break; - // Flame burst + // Flame shield activation case SH_FLAMEAURA: player->pflags |= PF_THOKKED|PF_SHIELDABILITY; P_Thrust(player->mo, player->mo->angle, FixedMul(30*FRACUNIT - FixedSqrt(FixedDiv(player->speed, player->mo->scale)), player->mo->scale)); @@ -8000,7 +8000,8 @@ static void P_MovePlayer(player_t *player) { if (player->homing && player->mo->tracer) { - if (!P_HomingAttack(player->mo, player->mo->tracer)) + P_HomingAttack(player->mo, player->mo->tracer); + if (player->mo->tracer->health <= 0 || (player->mo->tracer->flags2 & MF2_FRET)) { P_SetObjectMomZ(player->mo, 6*FRACUNIT, false); if (player->mo->eflags & MFE_UNDERWATER) @@ -8019,9 +8020,10 @@ static void P_MovePlayer(player_t *player) if (player->homing && player->mo->tracer) { P_SpawnThokMobj(player); + P_HomingAttack(player->mo, player->mo->tracer); // But if you don't, then stop homing. - if (!P_HomingAttack(player->mo, player->mo->tracer)) + if (player->mo->tracer->health <= 0 || (player->mo->tracer->flags2 & MF2_FRET)) { if (player->mo->eflags & MFE_UNDERWATER) P_SetObjectMomZ(player->mo, FixedDiv(457*FRACUNIT,72*FRACUNIT), false); @@ -8619,7 +8621,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) continue; // not a mobj thinker mo = (mobj_t *)think; - if (!((mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR) && (mo->flags & MF_SHOOTABLE)) || (mo->flags & MF_SPRING)) == !(mo->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag + if (!(mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR|MF_SPRING)) == !(mo->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag continue; // not a valid target if (mo->health <= 0) // dead @@ -8631,6 +8633,9 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) if (mo->flags2 & MF2_FRET) continue; + if ((mo->flags & (MF_ENEMY|MF_BOSS)) && !(mo->flags & MF_SHOOTABLE)) // don't aim at something you can't shoot at anyway (see Egg Guard or Minus) + continue; + if (!nonenemies && mo->flags & (MF_MONITOR|MF_SPRING)) continue; @@ -8684,23 +8689,17 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) return closestmo; } -boolean P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target +void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target { fixed_t zdist; fixed_t dist; fixed_t ns = 0; if (!enemy) - return false; + return; - if (!enemy->health) - return false; - - if (enemy->flags2 & MF2_FRET) - return false; - - if (!(enemy->flags & (MF_SHOOTABLE|MF_SPRING)) == !(enemy->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag - return false; + if (!(enemy->health)) + return; // change angle source->angle = R_PointToAngle2(source->x, source->y, enemy->x, enemy->y); @@ -8743,8 +8742,6 @@ boolean P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target source->momx = FixedMul(FixedDiv(enemy->x - source->x, dist), ns); source->momy = FixedMul(FixedDiv(enemy->y - source->y, dist), ns); source->momz = FixedMul(FixedDiv(zdist, dist), ns); - - return true; } // Search for emeralds diff --git a/src/r_draw.c b/src/r_draw.c index f8e435624..77bb1b6e7 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -528,9 +528,12 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U || color == SKINCOLOR_NONE) { if (skinnum == TC_ALLWHITE) - memset(dest_colormap, 0, NUM_PALETTE_ENTRIES * sizeof(UINT8)); + memset(dest_colormap, 0, NUM_PALETTE_ENTRIES * sizeof(UINT8**)); else if (skinnum == TC_BLINK && color != SKINCOLOR_NONE) - memset(dest_colormap, Color_Index[color-1][3], NUM_PALETTE_ENTRIES * sizeof(UINT8)); + { + for (i = 0; i < NUM_PALETTE_ENTRIES; i++) + dest_colormap[i] = Color_Index[color-1][3]; + } else { for (i = 0; i < NUM_PALETTE_ENTRIES; i++) diff --git a/src/r_things.c b/src/r_things.c index 155d0f83f..9fe1e96e4 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -723,7 +723,7 @@ static void R_DrawVisSprite(vissprite_t *vis) { // translate certain pixels to white colfunc = transcolfunc; - if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized) + if (vis->mobj->type == MT_CYBRAKDEMON) dc_translation = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE); else if (vis->mobj->type == MT_METALSONIC_BATTLE) dc_translation = R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE); diff --git a/src/sounds.c b/src/sounds.c index aa1c841d6..52dbee341 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -137,7 +137,7 @@ sfxinfo_t S_sfx[NUMSFX] = // Game objects, etc {"appear", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Appearing platform"}, - {"bkpoof", false, 70, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Armageddon pow"}, + {"bkpoof", false, 70, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Armageddon explosion"}, {"bnce1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bounce"}, // Boing! {"bnce2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Scatter"}, // Boing! {"cannon", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Powerful shot"}, @@ -304,7 +304,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3k3e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flame Shield"}, {"s3k3f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bubble Shield"}, {"s3k40", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Attraction blast"}, - {"s3k41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Thunder Shield"}, + {"s3k41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Lightning Shield"}, {"s3k42", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Twinspin"}, {"s3k43", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flame burst"}, {"s3k44", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bubble bounce"}, From 4ad1703ae34d3d76fca1455a365f41edee055f25 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 3 Jul 2019 00:58:02 +0100 Subject: [PATCH 048/128] Revert "Revert "Merge branch 'metalfixes' into 'toast_cleanup'"" This reverts commit c04b560e9260ae1f57834cd2e68e3f3bfca19c18. --- src/dehacked.c | 5 +- src/hardware/hw_main.c | 2 +- src/hardware/hw_md2.c | 2 +- src/info.c | 27 ++-- src/info.h | 5 +- src/lua_baselib.c | 4 +- src/p_local.h | 2 +- src/p_map.c | 21 +++ src/p_mobj.c | 360 +++++++++++++++++++++++++++++++---------- src/p_user.c | 45 +++--- src/r_draw.c | 7 +- src/r_things.c | 2 +- src/sounds.c | 4 +- 13 files changed, 351 insertions(+), 135 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index f532bde68..7935c474f 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -5125,7 +5125,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_METALSONIC_BADBOUNCE", "S_METALSONIC_SHOOT", "S_METALSONIC_PAIN", - "S_METALSONIC_DEATH", + "S_METALSONIC_DEATH1", + "S_METALSONIC_DEATH2", + "S_METALSONIC_DEATH3", + "S_METALSONIC_DEATH4", "S_METALSONIC_FLEE1", "S_METALSONIC_FLEE2", "S_METALSONIC_FLEE3", diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index a76c9e1c8..d649eeb8e 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5662,7 +5662,7 @@ static void HWR_ProjectSprite(mobj_t *thing) //Hurdler: 25/04/2000: now support colormap in hardware mode if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash" { - if (vis->mobj->type == MT_CYBRAKDEMON) + if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized) vis->colormap = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE); else if (vis->mobj->type == MT_METALSONIC_BATTLE) vis->colormap = R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE); diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index 6db5d5f08..e26aa98ff 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1363,7 +1363,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) INT32 skinnum = TC_DEFAULT; if ((spr->mobj->flags & (MF_ENEMY|MF_BOSS)) && (spr->mobj->flags2 & MF2_FRET) && !(spr->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash" { - if (spr->mobj->type == MT_CYBRAKDEMON) + if (spr->mobj->type == MT_CYBRAKDEMON || spr->mobj->colorized) skinnum = TC_ALLWHITE; else if (spr->mobj->type == MT_METALSONIC_BATTLE) skinnum = TC_METALSONIC; diff --git a/src/info.c b/src/info.c index 477c3f372..a58b2313c 100644 --- a/src/info.c +++ b/src/info.c @@ -1747,20 +1747,23 @@ state_t states[NUMSTATES] = {SPR_METL, 9, 2, {NULL}, 0, 0, S_METALSONIC_RUN1}, // S_METALSONIC_RUN4 {SPR_METL, 4, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_FLOAT - {SPR_METL, 12, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR - {SPR_METL, 0, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN - {SPR_METL, 13, 40, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE + {SPR_METL, 12|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR + {SPR_METL, 11, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN + {SPR_METL, 13, 20, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE {SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_GATHER {SPR_METL, 15, -1, {NULL}, 0, 0, S_METALSONIC_BOUNCE},// S_METALSONIC_DASH {SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BOUNCE {SPR_METL, 16, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BADBOUNCE {SPR_METL, 13, -1, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_SHOOT {SPR_METL, 11, 40, {A_Pain}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_PAIN - {SPR_METL, 11, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH - {SPR_METL, 3, 4, {NULL}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1 - {SPR_METL, 4, 4, {A_BossScream}, 0, 0, S_METALSONIC_FLEE3}, // S_METALSONIC_FLEE2 - {SPR_METL, 5, 4, {NULL}, 0, 0, S_METALSONIC_FLEE4}, // S_METALSONIC_FLEE3 - {SPR_METL, 4, 4, {NULL}, 0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE4 + {SPR_METL, 13, 8, {A_Fall}, 0, 0, S_METALSONIC_DEATH2},// S_METALSONIC_DEATH1 + {SPR_METL, 13, 8, {A_BossScream}, 0, 0, S_METALSONIC_DEATH3},// S_METALSONIC_DEATH2 + {SPR_METL, 13, 0, {A_Repeat}, 11, S_METALSONIC_DEATH2, S_METALSONIC_DEATH4}, // S_METALSONIC_DEATH3 + {SPR_METL, 13, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH4 + {SPR_METL, 11, 4, {NULL}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1 + {SPR_METL, 11, 4, {A_BossScream}, 0, 0, S_METALSONIC_FLEE3}, // S_METALSONIC_FLEE2 + {SPR_METL, 11, 4, {NULL}, 0, 0, S_METALSONIC_FLEE4}, // S_METALSONIC_FLEE3 + {SPR_METL, 11, 4, {NULL}, 0, 0, S_METALSONIC_FLEE1}, // S_METALSONIC_FLEE4 {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 0, 1, {NULL}, 0, 0, S_MSSHIELD_F2}, // S_MSSHIELD_F1 {SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30| 1, 1, {NULL}, 0, 0, S_MSSHIELD_F3}, // S_MSSHIELD_F2 @@ -6259,13 +6262,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_METALSONIC_DASH, // seestate sfx_s3k54, // seesound 0, // reactiontime - sfx_trpowr, // attacksound + sfx_bechrg, // attacksound S_METALSONIC_PAIN, // painstate S_METALSONIC_VECTOR,// painchance sfx_dmpain, // painsound S_METALSONIC_BADBOUNCE, // meleestate S_METALSONIC_SHOOT, // missilestate - S_METALSONIC_DEATH, // deathstate + S_METALSONIC_DEATH1,// deathstate S_METALSONIC_FLEE1, // xdeathstate sfx_s3k6e, // deathsound MT_ENERGYBALL, // speed @@ -6297,7 +6300,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // deathsound 0, // speed 32*FRACUNIT, // radius - 64*FRACUNIT, // height + 52*FRACUNIT, // height 0, // display offset 0, // mass 0, // damage @@ -9140,7 +9143,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_ENERGYBALL1, // spawnstate 1000, // spawnhealth S_NULL, // seestate - sfx_s3k54, // seesound + sfx_bexpld, // seesound 8, // reactiontime sfx_None, // attacksound S_NULL, // painstate diff --git a/src/info.h b/src/info.h index a7f5d775a..c1891a766 100644 --- a/src/info.h +++ b/src/info.h @@ -1888,7 +1888,10 @@ typedef enum state S_METALSONIC_BADBOUNCE, S_METALSONIC_SHOOT, S_METALSONIC_PAIN, - S_METALSONIC_DEATH, + S_METALSONIC_DEATH1, + S_METALSONIC_DEATH2, + S_METALSONIC_DEATH3, + S_METALSONIC_DEATH4, S_METALSONIC_FLEE1, S_METALSONIC_FLEE2, S_METALSONIC_FLEE3, diff --git a/src/lua_baselib.c b/src/lua_baselib.c index e6119cd6c..81a17ef20 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1235,8 +1235,8 @@ static int lib_pHomingAttack(lua_State *L) INLEVEL if (!source || !enemy) return LUA_ErrInvalid(L, "mobj_t"); - P_HomingAttack(source, enemy); - return 0; + lua_pushboolean(L, P_HomingAttack(source, enemy)); + return 1; } static int lib_pSuperReady(lua_State *L) diff --git a/src/p_local.h b/src/p_local.h index 8aeddf162..479994079 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -176,7 +176,7 @@ void P_InstaThrustEvenIn2D(mobj_t *mo, angle_t angle, fixed_t move); mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet); void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius); -void P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user +boolean P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user boolean P_SuperReady(player_t *player); void P_DoJump(player_t *player, boolean soundandstate); #if 0 diff --git a/src/p_map.c b/src/p_map.c index 76b6535b5..a852a3933 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -725,6 +725,27 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; } + // vectorise metal - done in a special case as at this point neither has the right flags for touching + if (thing->type == MT_METALSONIC_BATTLE + && (tmthing->flags & MF_MISSILE) + && tmthing->target != thing + && thing->state == &states[thing->info->spawnstate]) + { + blockdist = thing->radius + tmthing->radius; + + if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) + return true; // didn't hit it + + if (tmthing->z > thing->z + thing->height) + return true; // overhead + if (tmthing->z + tmthing->height < thing->z) + return true; // underneath + + thing->flags2 |= MF2_CLASSICPUSH; + + return true; + } + if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_PAIN|MF_SHOOTABLE|MF_SPRING))) return true; diff --git a/src/p_mobj.c b/src/p_mobj.c index 70017546c..ff2bcc77f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5395,7 +5395,8 @@ static void P_Boss7Thinker(mobj_t *mobj) if (mobj->info->activesound)\ S_StartSound(mobj, mobj->info->activesound);\ if (mobj->info->painchance)\ - P_SetMobjState(mobj, mobj->info->painchance) + P_SetMobjState(mobj, mobj->info->painchance);\ + mobj->flags2 &= ~MF2_INVERTAIMABLE;\ // Metal Sonic battle boss // You CAN put multiple Metal Sonics in a single map @@ -5485,25 +5486,16 @@ static void P_Boss9Thinker(mobj_t *mobj) // AI goes here. { angle_t angle; - if (mobj->threshold) + if (mobj->threshold || mobj->movecount) mobj->momz = (mobj->watertop-mobj->z)/16; // Float to your desired position FASTER else mobj->momz = (mobj->watertop-mobj->z)/40; // Float to your desired position - if (mobj->movecount == 2) { + if (mobj->movecount == 2) + { mobj_t *spawner; fixed_t dist = 0; - angle = 0x06000000*leveltime; - - // Alter your energy bubble's size/position - if (mobj->health > 3) { - mobj->tracer->destscale = FRACUNIT + (4*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2); - P_SetScale(mobj->tracer, mobj->tracer->destscale); - P_TeleportMove(mobj->tracer, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->tracer->height/2); - mobj->tracer->momx = mobj->momx; - mobj->tracer->momy = mobj->momy; - mobj->tracer->momz = mobj->momz; - } + angle = 0x06000000*leveltime; // wtf? // Face your target P_BossTargetPlayer(mobj, true); @@ -5514,27 +5506,150 @@ static void P_Boss9Thinker(mobj_t *mobj) else mobj->angle -= InvAngle(angle)/8; + // Alter your energy bubble's size/position + if (mobj->health > 3) + { + mobj->tracer->destscale = FRACUNIT + (4*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2); + P_SetScale(mobj->tracer, mobj->tracer->destscale); + } + else + mobj->tracer->frame &= ~FF_TRANSMASK; // this causes a flicker but honestly i like it this way + P_TeleportMove(mobj->tracer, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->tracer->height/2); + mobj->tracer->momx = mobj->momx; + mobj->tracer->momy = mobj->momy; + mobj->tracer->momz = mobj->momz; + + // Firin' mah lazors - INDICATOR + if (mobj->fuse > TICRATE/2) + { + tic_t shoottime, worktime, calctime; + shoottime = (TICRATE/((mobj->extravalue1 == 3) ? 8 : 4)); + shoottime += (shoottime>>1); + worktime = shoottime*(mobj->threshold/2); + calctime = mobj->fuse-(TICRATE/2); + + if (calctime <= worktime && (calctime % shoottime == 0)) + { + mobj_t *missile; + + missile = P_SpawnMissile(mobj, mobj->target, MT_MSGATHER); + S_StopSound(missile); + if (mobj->extravalue1 >= 2) + P_SetScale(missile, FRACUNIT>>1); + missile->destscale = missile->scale>>1; + missile->fuse = TICRATE/2; + missile->scalespeed = abs(missile->destscale - missile->scale)/missile->fuse; + missile->z -= missile->height/2; + missile->momx *= -1; + missile->momy *= -1; + missile->momz *= -1; + + if (mobj->extravalue1 == 2) + { + UINT8 i; + mobj_t *spread; + for (i = 0; i < 5; i++) + { + if (i == 2) + continue; + spread = P_SpawnMobj(missile->x, missile->y, missile->z, missile->type); + spread->angle = missile->angle+(ANGLE_11hh/2)*(i-2); + P_InstaThrust(spread,spread->angle,-spread->info->speed); + spread->momz = missile->momz; + P_SetScale(spread, missile->scale); + spread->destscale = missile->destscale; + spread->scalespeed = missile->scalespeed; + spread->fuse = missile->fuse; + P_UnsetThingPosition(spread); + spread->x -= spread->fuse*spread->momx; + spread->y -= spread->fuse*spread->momy; + spread->z -= spread->fuse*spread->momz; + P_SetThingPosition(spread); + } + P_InstaThrust(missile,missile->angle,-missile->info->speed); + } + else if (mobj->extravalue1 >= 3) + { + UINT8 i; + mobj_t *spread; + mobj->target->z -= (4*missile->height); + for (i = 0; i < 5; i++) + { + if (i != 2) + { + spread = P_SpawnMissile(mobj, mobj->target, missile->type); + P_SetScale(spread, missile->scale); + spread->destscale = missile->destscale; + spread->fuse = missile->fuse; + spread->z -= spread->height/2; + spread->momx *= -1; + spread->momy *= -1; + spread->momz *= -1; + P_UnsetThingPosition(spread); + spread->x -= spread->fuse*spread->momx; + spread->y -= spread->fuse*spread->momy; + spread->z -= spread->fuse*spread->momz; + P_SetThingPosition(spread); + } + mobj->target->z += missile->height*2; + } + mobj->target->z -= (6*missile->height); + } + + P_UnsetThingPosition(missile); + missile->x -= missile->fuse*missile->momx; + missile->y -= missile->fuse*missile->momy; + missile->z -= missile->fuse*missile->momz; + P_SetThingPosition(missile); + + S_StartSound(mobj, sfx_s3kb3); + } + } + + // up... + mobj->z += mobj->height/2; + // Spawn energy particles - for (spawner = mobj->hnext; spawner; spawner = spawner->hnext) { + for (spawner = mobj->hnext; spawner; spawner = spawner->hnext) + { dist = P_AproxDistance(spawner->x - mobj->x, spawner->y - mobj->y); if (P_RandomRange(1,(dist>>FRACBITS)/16) == 1) break; } - if (spawner) { + if (spawner) + { mobj_t *missile = P_SpawnMissile(spawner, mobj, MT_MSGATHER); - if (mobj->health > mobj->info->damage) - missile->momz = FixedDiv(missile->momz, 7*FRACUNIT/5); + if (dist == 0) missile->fuse = 0; else missile->fuse = (dist/P_AproxDistance(missile->momx, missile->momy)); + if (missile->fuse > mobj->fuse) P_RemoveMobj(missile); + + if (mobj->health > mobj->info->damage) + { + P_SetScale(missile, FRACUNIT/2); + missile->color = SKINCOLOR_GOLD; // sonic cd electric power + } + else + { + P_SetScale(missile, FRACUNIT/4); + missile->color = SKINCOLOR_MAGENTA; // sonic OVA/4 purple power + } + missile->destscale = missile->scale*2; + missile->scalespeed = abs(missile->scale - missile->destscale)/missile->fuse; + missile->colorized = true; } + + // ...then down. easier than changing the missile's momz after-the-fact + mobj->z -= mobj->height/2; } // Pre-threshold reactiontime stuff for attack phases - if (mobj->reactiontime && mobj->movecount == 3) { + if (mobj->reactiontime && mobj->movecount == 3) + { mobj->reactiontime--; if (mobj->movedir == 0 || mobj->movedir == 2) { // Pausing between bounces in the pinball phase @@ -5555,13 +5670,15 @@ static void P_Boss9Thinker(mobj_t *mobj) } // threshold is used for attacks/maneuvers. - if (mobj->threshold) { + if (mobj->threshold && mobj->movecount != 2) { fixed_t speed = 20*FRACUNIT + FixedMul(40*FRACUNIT, FixedDiv((mobj->info->spawnhealth - mobj->health)<info->spawnhealth<movecount == 3 && mobj->movedir == 1) { - if (!(mobj->threshold&1)) { + if (mobj->movecount == 3 && mobj->movedir == 1) + { + if (!(mobj->threshold & 1)) + { mobj_t *missile; if (mobj->info->seesound) S_StartSound(mobj, mobj->info->seesound); @@ -5573,18 +5690,20 @@ static void P_Boss9Thinker(mobj_t *mobj) A_FaceTarget(mobj); missile = P_SpawnMissile(mobj, mobj->target, mobj->info->speed); - if (mobj->extravalue1 == 2 || mobj->extravalue1 == 3) { + if (mobj->extravalue1 >= 2) + { missile->destscale = FRACUNIT>>1; P_SetScale(missile, missile->destscale); } missile->fuse = 3*TICRATE; missile->z -= missile->height/2; - if (mobj->extravalue1 == 2) { - int i; + if (mobj->extravalue1 == 2) + { + UINT8 i; mobj_t *spread; - missile->flags |= MF_MISSILE; - for (i = 0; i < 5; i++) { + for (i = 0; i < 5; i++) + { if (i == 2) continue; spread = P_SpawnMobj(missile->x, missile->y, missile->z, missile->type); @@ -5593,11 +5712,32 @@ static void P_Boss9Thinker(mobj_t *mobj) spread->momz = missile->momz; spread->destscale = FRACUNIT>>1; P_SetScale(spread, spread->destscale); - spread->fuse = 3*TICRATE; + spread->fuse = missile->fuse; } - missile->flags &= ~MF_MISSILE; + P_InstaThrust(missile,missile->angle,missile->info->speed); } - } else { + else if (mobj->extravalue1 >= 3) + { + UINT8 i; + mobj_t *spread; + mobj->target->z -= (2*missile->height); + for (i = 0; i < 5; i++) + { + if (i != 2) + { + spread = P_SpawnMissile(mobj, mobj->target, missile->type); + spread->destscale = FRACUNIT>>1; + P_SetScale(spread, spread->destscale); + spread->fuse = missile->fuse; + spread->z -= spread->height/2; + } + mobj->target->z += missile->height; + } + mobj->target->z -= (3*missile->height); + } + } + else + { P_SetMobjState(mobj, mobj->state->nextstate); if (mobj->extravalue1 == 3) mobj->reactiontime = TICRATE/8; @@ -5611,7 +5751,8 @@ static void P_Boss9Thinker(mobj_t *mobj) P_SpawnGhostMobj(mobj); // Pinball attack! - if (mobj->movecount == 3 && (mobj->movedir == 0 || mobj->movedir == 2)) { + if (mobj->movecount == 3 && (mobj->movedir == 0 || mobj->movedir == 2)) + { if ((statenum_t)(mobj->state-states) != mobj->info->seestate) P_SetMobjState(mobj, mobj->info->seestate); if (mobj->movedir == 0) // mobj health == 1 @@ -5620,7 +5761,8 @@ static void P_Boss9Thinker(mobj_t *mobj) P_InstaThrust(mobj, mobj->angle, 22*FRACUNIT); else // mobj health == 2 P_InstaThrust(mobj, mobj->angle, 30*FRACUNIT); - if (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true)) { // Hit a wall? Find a direction to bounce + if (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true)) + { // Hit a wall? Find a direction to bounce mobj->threshold--; P_SetMobjState(mobj, mobj->state->nextstate); if (!mobj->threshold) { // failed bounce! @@ -5633,11 +5775,15 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->movecount = 0; P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_CYBRAKDEMON_VILE_EXPLOSION); P_SetMobjState(mobj, mobj->info->meleestate); - } else if (!(mobj->threshold%4)) { // We've decided to lock onto the player this bounce. + } + else if (!(mobj->threshold%4)) + { // We've decided to lock onto the player this bounce. S_StartSound(mobj, sfx_s3k5a); mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4); mobj->reactiontime = TICRATE - 5*(mobj->info->damage - mobj->health); // targetting time - } else { // No homing, just use P_BounceMove + } + else + { // No homing, just use P_BounceMove S_StartSound(mobj, sfx_s3kaa); // make the bounces distinct... P_BounceMove(mobj); mobj->angle = R_PointToAngle2(0,0,mobj->momx,mobj->momy); @@ -5651,7 +5797,8 @@ static void P_Boss9Thinker(mobj_t *mobj) // Vector form dodge! mobj->angle += mobj->movedir; P_InstaThrust(mobj, mobj->angle, -speed); - while (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true) && tries++ < 16) { + while (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true) && tries++ < 16) + { S_StartSound(mobj, sfx_mspogo); P_BounceMove(mobj); mobj->angle = R_PointToAngle2(mobj->momx, mobj->momy,0,0); @@ -5708,7 +5855,7 @@ static void P_Boss9Thinker(mobj_t *mobj) if (mobj->flags2 & MF2_FRET) return; - if (mobj->state == &states[mobj->info->raisestate]) + if (mobj->movecount == 1 || mobj->movecount == 2) { // Charging energy if (mobj->momx != 0 || mobj->momy != 0) { // Apply the air breaks if (abs(mobj->momx)+abs(mobj->momy) < FRACUNIT) @@ -5716,11 +5863,13 @@ static void P_Boss9Thinker(mobj_t *mobj) else P_Thrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), -6*FRACUNIT/8); } - return; + if (mobj->state == states+mobj->info->raisestate) + return; } if (mobj->fuse == 0) { + mobj->flags2 &= ~MF2_INVERTAIMABLE; // It's time to attack! What are we gonna do?! switch(mobj->movecount) { @@ -5728,6 +5877,7 @@ static void P_Boss9Thinker(mobj_t *mobj) default: // Fly up and prepare for an attack! // We have to charge up first, so let's go up into the air + S_StartSound(mobj, sfx_beflap); P_SetMobjState(mobj, mobj->info->raisestate); if (mobj->floorz >= mobj->target->floorz) mobj->watertop = mobj->floorz + 256*FRACUNIT; @@ -5735,33 +5885,69 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->watertop = mobj->target->floorz + 256*FRACUNIT; break; - case 1: { + case 1: // Okay, we're up? Good, time to gather energy... if (mobj->health > mobj->info->damage) { // No more bubble if we're broken (pinch phase) mobj_t *shield = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_MSSHIELD_FRONT); P_SetTarget(&mobj->tracer, shield); P_SetTarget(&shield->target, mobj); + + // Attack 2: Energy shot! + switch (mobj->health) + { + case 8: // shoot once + default: + mobj->extravalue1 = 0; + mobj->threshold = 2; + break; + case 7: // spread shot (vertical) + mobj->extravalue1 = 4; + mobj->threshold = 2; + break; + case 6: // three shots + mobj->extravalue1 = 1; + mobj->threshold = 3*2; + break; + case 5: // spread shot (horizontal) + mobj->extravalue1 = 2; + mobj->threshold = 2; + break; + case 4: // machine gun + mobj->extravalue1 = 3; + mobj->threshold = 5*2; + break; + } } else - P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); + { + mobj_t *shield = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_MSSHIELD_FRONT); + P_SetTarget(&mobj->tracer, shield); + P_SetTarget(&shield->target, mobj); + shield->height -= 20*FRACUNIT; // different offset... + shield->color = SKINCOLOR_MAGENTA; + shield->colorized = true; + P_SetMobjState(shield, S_FIRS1); + //P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); -- why does this happen twice? see case 2... + } mobj->fuse = 4*TICRATE; mobj->flags |= MF_PAIN; if (mobj->info->attacksound) S_StartSound(mobj, mobj->info->attacksound); A_FaceTarget(mobj); + break; - } case 2: // We're all charged and ready now! Unleash the fury!! - if (mobj->health > mobj->info->damage) + S_StopSound(mobj); + mobj_t *removemobj = mobj->tracer; + P_SetTarget(&mobj->tracer, mobj->hnext); + P_RemoveMobj(removemobj); + if (mobj->health <= mobj->info->damage) { - mobj_t *removemobj = mobj->tracer; - P_SetTarget(&mobj->tracer, mobj->hnext); - P_RemoveMobj(removemobj); - } - if (mobj->health <= mobj->info->damage) { + mobj_t *whoosh; + // Attack 1: Pinball dash! if (mobj->health == 1) mobj->movedir = 0; @@ -5776,32 +5962,23 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->threshold = 24; // bounce 24 times mobj->watertop = mobj->target->floorz + 16*FRACUNIT; P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); - } else { + + whoosh = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_GHOST); // done here so the offset is correct + whoosh->frame = FF_FULLBRIGHT; + whoosh->sprite = SPR_ARMA; + whoosh->destscale = whoosh->scale<<1; + whoosh->scalespeed = FixedMul(whoosh->scalespeed, whoosh->scale); + whoosh->height = 38*whoosh->scale; + whoosh->fuse = 10; + whoosh->color = SKINCOLOR_MAGENTA; + whoosh->colorized = true; + whoosh->flags |= MF_NOCLIPHEIGHT; + } + else + { // Attack 2: Energy shot! mobj->movedir = 1; - - if (mobj->health >= 8) - mobj->extravalue1 = 0; - else if (mobj->health >= 5) - mobj->extravalue1 = 2; - else if (mobj->health >= 4) - mobj->extravalue1 = 1; - else - mobj->extravalue1 = 3; - - switch(mobj->extravalue1) { - case 0: // shoot once - case 2: // spread-shot - default: - mobj->threshold = 2; - break; - case 1: // shoot 3 times - mobj->threshold = 3*2; - break; - case 3: // shoot like a goddamn machinegun - mobj->threshold = 8*2; - break; - } + // looking for the number of things to fire? that's done in case 1 now } break; @@ -5835,21 +6012,26 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->angle -= InvAngle(angle)/8; //A_FaceTarget(mobj); - // Check if we're being attacked - if (!mobj->target || !mobj->target->player || !P_PlayerCanDamage(mobj->target->player, mobj)) - goto nodanger; - if (mobj->target->x+mobj->target->radius+abs(mobj->target->momx*2) < mobj->x-mobj->radius) - goto nodanger; - if (mobj->target->x-mobj->target->radius-abs(mobj->target->momx*2) > mobj->x+mobj->radius) - goto nodanger; - if (mobj->target->y+mobj->target->radius+abs(mobj->target->momy*2) < mobj->y-mobj->radius) - goto nodanger; - if (mobj->target->y-mobj->target->radius-abs(mobj->target->momy*2) > mobj->y+mobj->radius) - goto nodanger; - if (mobj->target->z+mobj->target->height+mobj->target->momz*2 < mobj->z) - goto nodanger; - if (mobj->target->z+mobj->target->momz*2 > mobj->z+mobj->height) - goto nodanger; + if (mobj->flags2 & MF2_CLASSICPUSH) + mobj->flags2 &= ~MF2_CLASSICPUSH; // a missile caught us in PIT_CheckThing! + else + { + // Check if we're being attacked + if (!mobj->target || !mobj->target->player || !P_PlayerCanDamage(mobj->target->player, mobj)) + goto nodanger; + if (mobj->target->x+mobj->target->radius+abs(mobj->target->momx*2) < mobj->x-mobj->radius) + goto nodanger; + if (mobj->target->x-mobj->target->radius-abs(mobj->target->momx*2) > mobj->x+mobj->radius) + goto nodanger; + if (mobj->target->y+mobj->target->radius+abs(mobj->target->momy*2) < mobj->y-mobj->radius) + goto nodanger; + if (mobj->target->y-mobj->target->radius-abs(mobj->target->momy*2) > mobj->y+mobj->radius) + goto nodanger; + if (mobj->target->z+mobj->target->height+mobj->target->momz*2 < mobj->z) + goto nodanger; + if (mobj->target->z+mobj->target->momz*2 > mobj->z+mobj->height) + goto nodanger; + } // An incoming attack is detected! What should we do?! // Go into vector form! @@ -5857,13 +6039,17 @@ static void P_Boss9Thinker(mobj_t *mobj) return; nodanger: + mobj->flags2 |= MF2_INVERTAIMABLE; + // Move normally: Approach the player using normal thrust and simulated friction. dist = P_AproxDistance(mobj->x-mobj->target->x, mobj->y-mobj->target->y); P_Thrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), -3*FRACUNIT/8); - if (dist < 64*FRACUNIT) + if (dist < 64*FRACUNIT && !(mobj->target->player && mobj->target->player->homing)) P_Thrust(mobj, mobj->angle, -4*FRACUNIT); else if (dist > 180*FRACUNIT) P_Thrust(mobj, mobj->angle, FRACUNIT); + else + P_Thrust(mobj, mobj->angle + ANGLE_90, FINECOSINE((((angle_t)(leveltime*ANG1))>>ANGLETOFINESHIFT) & FINEMASK)>>1); mobj->momz += P_AproxDistance(mobj->momx, mobj->momy)/12; // Move up higher the faster you're going. } } diff --git a/src/p_user.c b/src/p_user.c index ac951a8fa..0d38fd876 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4803,10 +4803,10 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) player->mo->momx /= 2; player->mo->momy /= 2; } - else if (player->charability == CA_HOMINGTHOK) + if (player->charability == CA_HOMINGTHOK) { - player->mo->momx /= 3; - player->mo->momy /= 3; + player->mo->momx /= 2; + player->mo->momy /= 2; } if (player->charability == CA_HOMINGTHOK) @@ -7923,7 +7923,7 @@ static void P_MovePlayer(player_t *player) if (!(player->pflags & (PF_USEDOWN|PF_GLIDING|PF_SLIDING|PF_SHIELDABILITY)) // If the player is not holding down BT_USE, or having used an ability previously && (!(player->powers[pw_shield] & SH_NOSTACK) || !(player->pflags & PF_THOKKED) || ((player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP && player->secondjump == UINT8_MAX))) // thokked is optional if you're bubblewrapped/turning super { - // Force shield activation + // Force stop if ((player->powers[pw_shield] & ~(SH_FORCEHP|SH_STACK)) == SH_FORCE) { player->pflags |= PF_THOKKED|PF_SHIELDABILITY; @@ -7939,17 +7939,17 @@ static void P_MovePlayer(player_t *player) if (P_SuperReady(player)) P_DoSuperTransformation(player, false); break; - // Whirlwind/Thundercoin shield activation + // Whirlwind jump/Thunder jump case SH_WHIRLWIND: case SH_THUNDERCOIN: P_DoJumpShield(player); break; - // Armageddon shield activation + // Armageddon pow case SH_ARMAGEDDON: player->pflags |= PF_THOKKED|PF_SHIELDABILITY; P_BlackOw(player); break; - // Attract shield activation + // Attraction blast case SH_ATTRACT: player->pflags |= PF_THOKKED|PF_SHIELDABILITY; player->homing = 2; @@ -7965,7 +7965,7 @@ static void P_MovePlayer(player_t *player) else S_StartSound(player->mo, sfx_s3ka6); break; - // Elemental/Bubblewrap shield activation + // Elemental stomp/Bubble bounce case SH_ELEMENTAL: case SH_BUBBLEWRAP: player->pflags |= PF_THOKKED|PF_SHIELDABILITY; @@ -7979,7 +7979,7 @@ static void P_MovePlayer(player_t *player) ? sfx_s3k43 : sfx_s3k44); break; - // Flame shield activation + // Flame burst case SH_FLAMEAURA: player->pflags |= PF_THOKKED|PF_SHIELDABILITY; P_Thrust(player->mo, player->mo->angle, FixedMul(30*FRACUNIT - FixedSqrt(FixedDiv(player->speed, player->mo->scale)), player->mo->scale)); @@ -8000,8 +8000,7 @@ static void P_MovePlayer(player_t *player) { if (player->homing && player->mo->tracer) { - P_HomingAttack(player->mo, player->mo->tracer); - if (player->mo->tracer->health <= 0 || (player->mo->tracer->flags2 & MF2_FRET)) + if (!P_HomingAttack(player->mo, player->mo->tracer)) { P_SetObjectMomZ(player->mo, 6*FRACUNIT, false); if (player->mo->eflags & MFE_UNDERWATER) @@ -8020,10 +8019,9 @@ static void P_MovePlayer(player_t *player) if (player->homing && player->mo->tracer) { P_SpawnThokMobj(player); - P_HomingAttack(player->mo, player->mo->tracer); // But if you don't, then stop homing. - if (player->mo->tracer->health <= 0 || (player->mo->tracer->flags2 & MF2_FRET)) + if (!P_HomingAttack(player->mo, player->mo->tracer)) { if (player->mo->eflags & MFE_UNDERWATER) P_SetObjectMomZ(player->mo, FixedDiv(457*FRACUNIT,72*FRACUNIT), false); @@ -8621,7 +8619,7 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) continue; // not a mobj thinker mo = (mobj_t *)think; - if (!(mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR|MF_SPRING)) == !(mo->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag + if (!((mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR) && (mo->flags & MF_SHOOTABLE)) || (mo->flags & MF_SPRING)) == !(mo->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag continue; // not a valid target if (mo->health <= 0) // dead @@ -8633,9 +8631,6 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) if (mo->flags2 & MF2_FRET) continue; - if ((mo->flags & (MF_ENEMY|MF_BOSS)) && !(mo->flags & MF_SHOOTABLE)) // don't aim at something you can't shoot at anyway (see Egg Guard or Minus) - continue; - if (!nonenemies && mo->flags & (MF_MONITOR|MF_SPRING)) continue; @@ -8689,17 +8684,23 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) return closestmo; } -void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target +boolean P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target { fixed_t zdist; fixed_t dist; fixed_t ns = 0; if (!enemy) - return; + return false; - if (!(enemy->health)) - return; + if (!enemy->health) + return false; + + if (enemy->flags2 & MF2_FRET) + return false; + + if (!(enemy->flags & (MF_SHOOTABLE|MF_SPRING)) == !(enemy->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag + return false; // change angle source->angle = R_PointToAngle2(source->x, source->y, enemy->x, enemy->y); @@ -8742,6 +8743,8 @@ void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target source->momx = FixedMul(FixedDiv(enemy->x - source->x, dist), ns); source->momy = FixedMul(FixedDiv(enemy->y - source->y, dist), ns); source->momz = FixedMul(FixedDiv(zdist, dist), ns); + + return true; } // Search for emeralds diff --git a/src/r_draw.c b/src/r_draw.c index 77bb1b6e7..f8e435624 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -528,12 +528,9 @@ static void R_GenerateTranslationColormap(UINT8 *dest_colormap, INT32 skinnum, U || color == SKINCOLOR_NONE) { if (skinnum == TC_ALLWHITE) - memset(dest_colormap, 0, NUM_PALETTE_ENTRIES * sizeof(UINT8**)); + memset(dest_colormap, 0, NUM_PALETTE_ENTRIES * sizeof(UINT8)); else if (skinnum == TC_BLINK && color != SKINCOLOR_NONE) - { - for (i = 0; i < NUM_PALETTE_ENTRIES; i++) - dest_colormap[i] = Color_Index[color-1][3]; - } + memset(dest_colormap, Color_Index[color-1][3], NUM_PALETTE_ENTRIES * sizeof(UINT8)); else { for (i = 0; i < NUM_PALETTE_ENTRIES; i++) diff --git a/src/r_things.c b/src/r_things.c index 9fe1e96e4..155d0f83f 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -723,7 +723,7 @@ static void R_DrawVisSprite(vissprite_t *vis) { // translate certain pixels to white colfunc = transcolfunc; - if (vis->mobj->type == MT_CYBRAKDEMON) + if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized) dc_translation = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE); else if (vis->mobj->type == MT_METALSONIC_BATTLE) dc_translation = R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE); diff --git a/src/sounds.c b/src/sounds.c index 52dbee341..aa1c841d6 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -137,7 +137,7 @@ sfxinfo_t S_sfx[NUMSFX] = // Game objects, etc {"appear", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Appearing platform"}, - {"bkpoof", false, 70, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Armageddon explosion"}, + {"bkpoof", false, 70, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Armageddon pow"}, {"bnce1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bounce"}, // Boing! {"bnce2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Scatter"}, // Boing! {"cannon", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Powerful shot"}, @@ -304,7 +304,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3k3e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flame Shield"}, {"s3k3f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bubble Shield"}, {"s3k40", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Attraction blast"}, - {"s3k41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Lightning Shield"}, + {"s3k41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Thunder Shield"}, {"s3k42", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Twinspin"}, {"s3k43", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flame burst"}, {"s3k44", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bubble bounce"}, From a5074a846be7391fc9bf90f27f5556643e5ac5c3 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Wed, 3 Jul 2019 09:19:29 +0200 Subject: [PATCH 049/128] Implemented a skin-based linedef executor trigger --- src/p_setup.c | 6 ++++++ src/p_spec.c | 18 ++++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index e7dc271a4..7aaad233d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1282,6 +1282,9 @@ static void P_LoadLineDefs2(void) // Compile linedef 'text' from both sidedefs 'text' for appropriate specials. switch(ld->special) { + case 331: // Trigger linedef executor: Skin - Continuous + case 332: // Trigger linedef executor: Skin - Each time + case 333: // Trigger linedef executor: Skin - Once case 443: // Calls a named Lua function if (sides[ld->sidenum[0]].text) { @@ -1492,6 +1495,9 @@ static void P_LoadRawSideDefs2(void *data) break; } + case 331: // Trigger linedef executor: Skin - Continuous + case 332: // Trigger linedef executor: Skin - Each time + case 333: // Trigger linedef executor: Skin - Once case 443: // Calls a named Lua function case 459: // Control text prompt (named tag) { diff --git a/src/p_spec.c b/src/p_spec.c index ae63e53bf..68bdf0c82 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -36,6 +36,7 @@ #include "m_cond.h" //unlock triggers #include "lua_hook.h" // LUAh_LinedefExecute #include "f_finale.h" // control text prompt +#include "r_things.h" // skins #ifdef HW3SOUND #include "hardware/hw3sound.h" @@ -2008,7 +2009,12 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (!P_CheckNightsTriggerLine(triggerline, actor)) return false; break; - + case 331: // continuous + case 332: // each time + case 333: // once + if (!(actor && actor->player && ((stricmp(triggerline->text, skins[actor->player->skin].name) == 0) ^ ((triggerline->flags & ML_NOCLIMB) == ML_NOCLIMB)))) + return false; + break; default: break; } @@ -2141,6 +2147,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller || specialtype == 326 // DeNightserize - Once || specialtype == 328 // Nights lap - Once || specialtype == 330 // Nights Bonus Time - Once + || specialtype == 333 // Skin - Once || specialtype == 399) // Level Load triggerline->special = 0; // Clear it out @@ -2181,7 +2188,8 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) || lines[masterline].special == 306 // Character ability - Each time || lines[masterline].special == 310 // CTF Red team - Each time || lines[masterline].special == 312 // CTF Blue team - Each time - || lines[masterline].special == 322) // Trigger on X calls - Each Time + || lines[masterline].special == 322 // Trigger on X calls - Each Time + || lines[masterline].special == 332)// Skin - Each time continue; if (lines[masterline].special < 300 @@ -7169,6 +7177,7 @@ void P_SpawnSpecials(INT32 fromnetsave) case 301: case 310: case 312: + case 332: sec = sides[*lines[i].sidenum].sector - sectors; P_AddEachTimeThinker(§ors[sec], &lines[i]); break; @@ -7217,6 +7226,11 @@ void P_SpawnSpecials(INT32 fromnetsave) case 330: break; + // Skin trigger executors + case 331: + case 333: + break; + case 399: // Linedef execute on map load // This is handled in P_RunLevelLoadExecutors. break; From 3efb49487e77cc4c5a85abfda9768e2cf832d909 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 3 Jul 2019 00:50:12 +0100 Subject: [PATCH 050/128] Pre-pinch behaviour complete - heavily reliant on a new map, which I won't be sharing until everything is ready. Just making this commit now so I can merge in master... --- src/dehacked.c | 7 +++ src/doomdef.h | 2 +- src/info.c | 41 ++++++++++++- src/info.h | 7 +++ src/p_enemy.c | 6 +- src/p_mobj.c | 160 ++++++++++++++++++++++++++++++------------------- 6 files changed, 158 insertions(+), 65 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 8057f26d8..4673f2799 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -6654,6 +6654,12 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_LOCKON1", "S_LOCKON2", + "S_LOCKON3", + "S_LOCKON4", + "S_LOCKONINF1", + "S_LOCKONINF2", + "S_LOCKONINF3", + "S_LOCKONINF4", // Tag Sign "S_TTAG", @@ -7732,6 +7738,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_DROWNNUMBERS", // Drowning Timer "MT_GOTEMERALD", // Chaos Emerald (intangible) "MT_LOCKON", // Target + "MT_LOCKONINF", // In-level Target "MT_TAG", // Tag Sign "MT_GOTFLAG", // Got Flag sign diff --git a/src/doomdef.h b/src/doomdef.h index 475328918..7bcc533c2 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -384,7 +384,7 @@ enum { LE_PINCHPHASE = -2, // A boss entered pinch phase (and, in most cases, is preparing their pinch phase attack!) LE_ALLBOSSESDEAD = -3, // All bosses in the map are dead (Egg capsule raise) LE_BOSSDEAD = -4, // A boss in the map died (Chaos mode boss tally) - LE_BOSS4DROP = -5, // CEZ boss dropped its cage + LE_BOSS4DROP = -5, // CEZ boss dropped its cage (also subtract the number of hitpoints it's lost) LE_BRAKVILEATACK = -6, // Brak's doing his LOS attack, oh noes LE_TURRET = 32000, // THZ turret LE_BRAKPLATFORM = 4200, // v2.0 Black Eggman destroys platform diff --git a/src/info.c b/src/info.c index 074e31ba2..5af1586b4 100644 --- a/src/info.c +++ b/src/info.c @@ -1352,14 +1352,15 @@ state_t states[NUMSTATES] = {SPR_EGGP,10, 2, {NULL}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_RATK6 {SPR_EGGP, 0, 20, {A_Boss4Raise}, sfx_doord1, 0, S_EGGMOBILE4_RAISE2}, // S_EGGMOBILE4_RAISE1 {SPR_EGGP,13, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE3}, // S_EGGMOBILE4_RAISE2 - {SPR_EGGP,14, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE4}, // S_EGGMOBILE4_RAISE3 + {SPR_EGGP,14, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE2}, // S_EGGMOBILE4_RAISE3 {SPR_EGGP,13, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE5}, // S_EGGMOBILE4_RAISE4 {SPR_EGGP,14, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE6}, // S_EGGMOBILE4_RAISE5 {SPR_EGGP,13, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE7}, // S_EGGMOBILE4_RAISE6 {SPR_EGGP,14, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE8}, // S_EGGMOBILE4_RAISE7 {SPR_EGGP,13, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE9}, // S_EGGMOBILE4_RAISE8 {SPR_EGGP,14, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE10},// S_EGGMOBILE4_RAISE9 - {SPR_EGGP,13, 10, {NULL}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_RAISE10 + // rename eventually + {SPR_EGGP,11, 0, {A_Boss4Reverse}, sfx_mswing, 0, S_EGGMOBILE4_PAIN}, // S_EGGMOBILE4_RAISE10 {SPR_EGGP,11, 24, {A_Pain}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_PAIN {SPR_EGGP,12, 8, {A_Fall}, 0, 0, S_EGGMOBILE4_DIE2}, // S_EGGMOBILE4_DIE1 {SPR_EGGP,12, 8, {A_BossScream}, 0, 0, S_EGGMOBILE4_DIE3}, // S_EGGMOBILE4_DIE2 @@ -3298,6 +3299,13 @@ state_t states[NUMSTATES] = {SPR_LCKN, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON1 {SPR_LCKN, 1|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON2 + {SPR_LCKN, 2|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON3 + {SPR_LCKN, 3|FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_LOCKON4 + + {SPR_LCKN, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LOCKONINF1 + {SPR_LCKN, 1|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LOCKONINF2 + {SPR_LCKN, 2|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LOCKONINF3 + {SPR_LCKN, 3|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_LOCKONINF4 {SPR_TTAG, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_TTAG @@ -5577,7 +5585,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // seesound 0, // reactiontime sfx_None, // attacksound - S_EGGMOBILE4_PAIN, // painstate + S_EGGMOBILE4_RAISE10, // painstate 0, // painchance sfx_dmpain, // painsound S_EGGMOBILE4_LATK1,// meleestate @@ -16529,6 +16537,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_LOCKONINF + 1126, // doomednum + S_INVISIBLE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 8, // speed + 16*FRACUNIT, // radius + 32*FRACUNIT, // height + 111, // display offset + 16, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + S_NULL // raisestate + }, + { // MT_TAG -1, // doomednum S_TTAG, // spawnstate diff --git a/src/info.h b/src/info.h index 13abfa5f6..75091ce1e 100644 --- a/src/info.h +++ b/src/info.h @@ -3409,6 +3409,12 @@ typedef enum state S_LOCKON1, S_LOCKON2, + S_LOCKON3, + S_LOCKON4, + S_LOCKONINF1, + S_LOCKONINF2, + S_LOCKONINF3, + S_LOCKONINF4, // Tag Sign S_TTAG, @@ -4507,6 +4513,7 @@ typedef enum mobj_type MT_DROWNNUMBERS, // Drowning Timer MT_GOTEMERALD, // Chaos Emerald (intangible) MT_LOCKON, // Target + MT_LOCKONINF, // In-level Target MT_TAG, // Tag Sign MT_GOTFLAG, // Got Flag sign diff --git a/src/p_enemy.c b/src/p_enemy.c index a817ee8a6..05915c0b3 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3167,8 +3167,12 @@ void A_Boss4Reverse(mobj_t *actor) actor->reactiontime = 0; if (actor->movedir == 1) actor->movedir = 2; - else + else if (actor->movedir == 2) actor->movedir = 1; + else if (actor->movedir == 4) + actor->movedir = 5; + else + actor->movedir = 4; } // Function: A_Boss4SpeedUp diff --git a/src/p_mobj.c b/src/p_mobj.c index 4f46116ca..a3e0d7704 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -4660,9 +4660,9 @@ static void P_Boss3Thinker(mobj_t *mobj) } // Move Boss4's sectors by delta. -static boolean P_Boss4MoveCage(fixed_t delta) +static boolean P_Boss4MoveCage(mobj_t *mobj, fixed_t delta) { - const UINT16 tag = 65534; + const UINT16 tag = 65534 + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0); INT32 snum; sector_t *sector; for (snum = sectors[tag%numsectors].firsttag; snum != -1; snum = sector->nexttag) @@ -4682,7 +4682,7 @@ static void P_Boss4MoveSpikeballs(mobj_t *mobj, angle_t angle, fixed_t fz) { INT32 s; mobj_t *base = mobj, *seg; - fixed_t dist, bz = mobj->watertop+(16<watertop+(8<tracer)) { for (seg = base, dist = 172*FRACUNIT, s = 9; seg; seg = seg->hnext, dist += 124*FRACUNIT, --s) @@ -4692,26 +4692,44 @@ static void P_Boss4MoveSpikeballs(mobj_t *mobj, angle_t angle, fixed_t fz) } // Pull them closer. -static void P_Boss4PinchSpikeballs(mobj_t *mobj, angle_t angle, fixed_t fz) +static void P_Boss4PinchSpikeballs(mobj_t *mobj, angle_t angle, fixed_t dz) { INT32 s; mobj_t *base = mobj, *seg; - fixed_t dist, bz = mobj->watertop+(16<tracer)) + fixed_t originx, originy, workx, worky, dx, dy, bz = mobj->watertop+(8<spawnpoint) { - for (seg = base, dist = 112*FRACUNIT, s = 9; seg; seg = seg->hnext, dist += 132*FRACUNIT, --s) + originx = mobj->spawnpoint->x << FRACBITS; + originy = mobj->spawnpoint->y << FRACBITS; + } + else + { + originx = mobj->x; + originy = mobj->y; + } + + dz /= 9; + + while ((base = base->tracer)) // there are 10 per spoke, remember that + { + dx = (originx + P_ReturnThrustX(mobj, angle, (9*132)<x)/9; + dy = (originy + P_ReturnThrustY(mobj, angle, (9*132)<y)/9; + workx = mobj->x + P_ReturnThrustX(mobj, angle, (112)<y + P_ReturnThrustY(mobj, angle, (112)<hnext, --s) { - seg->z = bz + FixedMul(fz, FixedDiv(s<x + P_ReturnThrustX(mobj, angle, dist), mobj->y + P_ReturnThrustY(mobj, angle, dist), true); + seg->z = bz + (dz*(9-s)); + P_TryMove(seg, workx + (dx*s), worky + (dy*s), true); } angle += ANGLE_MAX/3; } } // Destroy cage FOFs. -static void P_Boss4DestroyCage(void) +static void P_Boss4DestroyCage(mobj_t *mobj) { - const UINT16 tag = 65534; + const UINT16 tag = 65534 + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0); INT32 snum, next; size_t a; sector_t *sector, *rsec; @@ -4776,7 +4794,7 @@ static void P_Boss4Thinker(mobj_t *mobj) { if ((statenum_t)(mobj->state-states) == mobj->info->spawnstate) { - if (mobj->health > mobj->info->damage || mobj->movedir == 4) + if (mobj->flags2 & MF2_FRET && (mobj->health > mobj->info->damage || mobj->movedir == 4)) mobj->flags2 &= ~MF2_FRET; mobj->reactiontime = 0; // Drop the cage immediately. } @@ -4786,7 +4804,7 @@ static void P_Boss4Thinker(mobj_t *mobj) { if (mobj->tracer) // need to clean up! { - P_Boss4DestroyCage(); // Just in case pinch phase was skipped. + P_Boss4DestroyCage(mobj); // Just in case pinch phase was skipped. P_Boss4PopSpikeballs(mobj); } return; @@ -4813,6 +4831,7 @@ static void P_Boss4Thinker(mobj_t *mobj) mobj_t *seg, *base = mobj; // First frame init, spawn all the things. mobj->watertop = mobj->z; + mobj->flags2 |= MF2_STRONGBOX; // don't perform the linedef executor at start z = mobj->z + mobj->height/2 - mobjinfo[MT_EGGMOBILE4_MACE].height/2; for (arm = 0; arm <3 ; arm++) { @@ -4829,10 +4848,10 @@ static void P_Boss4Thinker(mobj_t *mobj) } // Move the cage up to the sky. mobj->movecount = 800*FRACUNIT; - if (!P_Boss4MoveCage(mobj->movecount)) + if (!P_Boss4MoveCage(mobj, mobj->movecount)) { mobj->movecount = 0; - mobj->threshold = 3*TICRATE; + //mobj->threshold = 3*TICRATE; mobj->extravalue1 = 1; mobj->movedir++; // We don't have a cage, just continue. } @@ -4846,13 +4865,18 @@ static void P_Boss4Thinker(mobj_t *mobj) mobj->movecount += mobj->threshold; if (mobj->movecount < 0) mobj->movecount = 0; - P_Boss4MoveCage(mobj->movecount - oldz); + P_Boss4MoveCage(mobj, mobj->movecount - oldz); P_Boss4MoveSpikeballs(mobj, 0, mobj->movecount); if (mobj->movecount == 0) { - mobj->threshold = 3*TICRATE; + //mobj->threshold = 3*TICRATE; mobj->extravalue1 = 1; - P_LinedefExecute(LE_BOSS4DROP, mobj, NULL); + //P_LinedefExecute(LE_BOSS4DROP + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0), mobj, NULL); -- oh no you don't + S_StartSound(NULL, sfx_doorc2); + quake.intensity = 10<movedir++; // Initialization complete, next phase! } } @@ -4875,10 +4899,10 @@ static void P_Boss4Thinker(mobj_t *mobj) mobj->momz = 0; mobj->movedir++; } - mobj->movecount += 400<<(FRACBITS>>1); + mobj->movecount -= 210<<(FRACBITS>>1); mobj->movecount %= 360*FRACUNIT; z = mobj->z - mobj->watertop - mobjinfo[MT_EGGMOBILE4_MACE].height - mobj->height/2; - if (z < 0) // We haven't risen high enough to pull the spikeballs along yet + if (z < (8<movecount), 0); // So don't pull the spikeballs along yet. else P_Boss4PinchSpikeballs(mobj, FixedAngle(mobj->movecount), z); @@ -4886,12 +4910,19 @@ static void P_Boss4Thinker(mobj_t *mobj) } // Pinch phase! case 4: + case 5: { + fixed_t movespeed = 420<<(FRACBITS>>1); + movespeed += (420*(mobj->info->damage-mobj->health)<<(FRACBITS>>1)); + if (mobj->movedir == 4) + mobj->movecount -= movespeed; + else + mobj->movecount += movespeed; + if (mobj->z < (mobj->watertop + ((512+128*(mobj->info->damage-mobj->health))<momz = 8*FRACUNIT; else mobj->momz = 0; - mobj->movecount += (800+800*(mobj->info->damage-mobj->health))<<(FRACBITS>>1); mobj->movecount %= 360*FRACUNIT; P_Boss4PinchSpikeballs(mobj, FixedAngle(mobj->movecount), mobj->z - mobj->watertop - mobjinfo[MT_EGGMOBILE4_MACE].height - mobj->height/2); @@ -4917,10 +4948,20 @@ static void P_Boss4Thinker(mobj_t *mobj) if (mobj->reactiontime == 1) { fixed_t oldz = mobj->movefactor; - mobj->movefactor += 8*FRACUNIT; - if (mobj->movefactor > 128*FRACUNIT) + if (mobj->movefactor < 128*FRACUNIT) + { + mobj->movefactor += 8*FRACUNIT; + P_Boss4MoveCage(mobj, mobj->movefactor - oldz); + // 5 -> 2.5 second timer + mobj->threshold = 5*TICRATE-(TICRATE/2)*(mobj->info->spawnhealth-mobj->health); + if (mobj->threshold < 1) + mobj->threshold = 1; + } + else if (mobj->movefactor > 128*FRACUNIT) + { mobj->movefactor = 128*FRACUNIT; - P_Boss4MoveCage(mobj->movefactor - oldz); + P_Boss4MoveCage(mobj, mobj->movefactor - oldz); + } } // Drop the cage! else if (mobj->movefactor) @@ -4929,24 +4970,32 @@ static void P_Boss4Thinker(mobj_t *mobj) mobj->movefactor -= 4*FRACUNIT; if (mobj->movefactor < 0) mobj->movefactor = 0; - P_Boss4MoveCage(mobj->movefactor - oldz); - if (!mobj->movefactor) + P_Boss4MoveCage(mobj, mobj->movefactor - oldz); + if (mobj->flags2 & MF2_STRONGBOX) + mobj->flags2 &= ~MF2_STRONGBOX; + else if (!mobj->movefactor) { if (mobj->health <= mobj->info->damage) { // Proceed to pinch phase! - P_Boss4DestroyCage(); + P_Boss4DestroyCage(mobj); mobj->movedir = 3; - P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); + P_LinedefExecute(LE_PINCHPHASE + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0), mobj, NULL); return; } - P_LinedefExecute(LE_BOSS4DROP, mobj, NULL); + P_LinedefExecute(LE_BOSS4DROP - (mobj->info->spawnhealth-mobj->health) + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0), mobj, NULL); + S_StartSound(NULL, sfx_doorc2); + quake.intensity = 10<>1); - if (mobj->reactiontime == 2) - movespeed *= 3; + movespeed += ((50*(mobj->info->spawnhealth-mobj->health))<<(FRACBITS>>1)); + if (mobj->movefactor) + movespeed /= 2; if (mobj->movedir == 2) mobj->movecount -= movespeed; else @@ -4956,37 +5005,14 @@ static void P_Boss4Thinker(mobj_t *mobj) P_Boss4MoveSpikeballs(mobj, FixedAngle(mobj->movecount), mobj->movefactor); // Check for attacks, always tick the timer even while animating!! - if (!(mobj->flags2 & MF2_FRET) // but pause for pain so we don't interrupt pinch phase, eep! - && mobj->threshold-- == 0) + if (mobj->threshold) { - // 5 -> 2.5 second timer - mobj->threshold = 5*TICRATE-(TICRATE/2)*(mobj->info->spawnhealth-mobj->health); - if (mobj->threshold < 1) - mobj->threshold = 1; - - if (mobj->extravalue1-- == 0) - { - P_SetMobjState(mobj, mobj->info->raisestate); - mobj->extravalue1 = 3; - } - else + if (!(mobj->flags2 & MF2_FRET) && !(--mobj->threshold)) // but pause for pain so we don't interrupt pinch phase, eep! { if (mobj->reactiontime == 1) // Cage is raised? - mobj->reactiontime = 0; // Drop it! - switch(P_RandomKey(10)) { - // Telegraph Right (Speed Up!!) - case 1: - case 3: - case 4: - case 5: - case 6: - P_SetMobjState(mobj, mobj->info->missilestate); - break; - // Telegraph Left (Reverse Direction) - default: - P_SetMobjState(mobj, mobj->info->meleestate); - break; + P_SetMobjState(mobj, mobj->info->spawnstate); + mobj->reactiontime = 0; // Drop it! } } } @@ -4998,13 +5024,13 @@ static void P_Boss4Thinker(mobj_t *mobj) // Map allows us to get killed despite cage being down? if (mobj->health <= mobj->info->damage) { // Proceed to pinch phase! - P_Boss4DestroyCage(); + P_Boss4DestroyCage(mobj); // spawn jet's flame now you're flying upwards // tracer is already used, so if this ever gets reached again we've got problems var1 = 3; A_BossJetFume(mobj); mobj->movedir = 3; - P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); + P_LinedefExecute(LE_PINCHPHASE + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0), mobj, NULL); return; } @@ -7183,6 +7209,17 @@ void P_MobjThinker(mobj_t *mobj) else mobj->z = mobj->target->z - FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->target->scale) - mobj->height; break; + case MT_LOCKONINF: + if (!(mobj->flags2 & MF2_STRONGBOX)) + { + mobj->threshold = mobj->z; + mobj->flags2 |= MF2_STRONGBOX; + } + if (!(mobj->eflags & MFE_VERTICALFLIP)) + mobj->z = mobj->threshold + FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->scale); + else + mobj->z = mobj->threshold - FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->scale); + break; case MT_DROWNNUMBERS: if (!mobj->target) { @@ -9184,6 +9221,9 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) case MT_ALTVIEWMAN: if (titlemapinaction) mobj->flags &= ~MF_NOTHINK; break; + case MT_LOCKONINF: + P_SetScale(mobj, (mobj->destscale = 3*mobj->scale)); + break; case MT_CYBRAKDEMON_NAPALM_BOMB_LARGE: mobj->fuse = mobj->info->painchance; break; From 5baaba1d9e6ad2629eba3a0b98fa8e5b61735afc Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 4 Jul 2019 14:43:18 +0100 Subject: [PATCH 051/128] Realised I accidentially broke rain in the rainfixes branch (oh, the irony!), realised it needed a few additional P_RecalcPrecipInSector calls to properly work with the new arena, and increased its speed. If you must, I can cherrypick this into another branch - but it's required for this one, at least. --- src/info.c | 6 ++-- src/p_floor.c | 2 +- src/p_mobj.c | 81 +++++++++++++++++++++++++-------------------------- src/p_spec.c | 4 +++ 4 files changed, 47 insertions(+), 46 deletions(-) diff --git a/src/info.c b/src/info.c index 5af1586b4..51d41806b 100644 --- a/src/info.c +++ b/src/info.c @@ -3188,8 +3188,8 @@ state_t states[NUMSTATES] = {SPR_SSWB, 1, 1, {NULL}, 0, 0, S_BHORIZ1}, // S_BHORIZ8 // Rain - {SPR_RAIN, FF_TRANS50, -1, {NULL}, 0, 0, S_NULL}, // S_RAIN1 - {SPR_RAIN, FF_TRANS50, 1, {NULL}, 0, 0, S_RAIN1}, // S_RAINRETURN + {SPR_RAIN, FF_FULLBRIGHT|FF_TRANS50, -1, {NULL}, 0, 0, S_NULL}, // S_RAIN1 + {SPR_RAIN, FF_FULLBRIGHT|FF_TRANS50, 1, {NULL}, 0, 0, S_RAIN1}, // S_RAINRETURN // Snowflake {SPR_SNO1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SNOW1 @@ -16121,7 +16121,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound - -24*FRACUNIT, // speed + -72*FRACUNIT, // speed 1*FRACUNIT, // radius 8*FRACUNIT, // height 0, // display offset diff --git a/src/p_floor.c b/src/p_floor.c index 4a03f70c0..ed2afd13d 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -3130,7 +3130,7 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover) // no longer exists (can't collide with again) rover->flags &= ~FF_EXISTS; rover->master->frontsector->moved = true; - sec->moved = true; + P_RecalcPrecipInSector(sec); } // Used for bobbing platforms on the water diff --git a/src/p_mobj.c b/src/p_mobj.c index d35f5018d..df3081bdf 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9640,12 +9640,12 @@ consvar_t cv_flagtime = {"flagtime", "30", CV_NETVAR|CV_CHEAT, flagtime_cons_t, void P_SpawnPrecipitation(void) { - INT32 i /*, j*/, mrand; + INT32 i, mrand; fixed_t basex, basey, x, y, height; subsector_t *precipsector = NULL; precipmobj_t *rainmo = NULL; - if (dedicated || /*!cv_precipdensity*/!cv_drawdist_precip.value || curWeather == PRECIP_NONE) + if (dedicated || !(cv_drawdist_precip.value) || curWeather == PRECIP_NONE) return; // Use the blockmap to narrow down our placing patterns @@ -9654,50 +9654,47 @@ void P_SpawnPrecipitation(void) basex = bmaporgx + (i % bmapwidth) * MAPBLOCKSIZE; basey = bmaporgy + (i / bmapwidth) * MAPBLOCKSIZE; - //for (j = 0; j < cv_precipdensity.value; ++j) -- density is 1 for us always + x = basex + ((M_RandomKey(MAPBLOCKUNITS<<3)<>3); + y = basey + ((M_RandomKey(MAPBLOCKUNITS<<3)<>3); + + precipsector = R_IsPointInSubsector(x, y); + + // No sector? Stop wasting time, + // move on to the next entry in the blockmap + if (!precipsector) + continue; + + // Exists, but is too small for reasonable precipitation. + if (!(precipsector->sector->floorheight <= precipsector->sector->ceilingheight - (32<sector->ceilingheight; + + if (curWeather == PRECIP_SNOW) { - x = basex + ((M_RandomKey(MAPBLOCKUNITS<<3)<>3); - y = basey + ((M_RandomKey(MAPBLOCKUNITS<<3)<>3); - - precipsector = R_IsPointInSubsector(x, y); - - // No sector? Stop wasting time, - // move on to the next entry in the blockmap - if (!precipsector) - break; - - // Exists, but is too small for reasonable precipitation. - if (!(precipsector->sector->floorheight <= precipsector->sector->ceilingheight - (32<sector->ceilingpic != skyflatnum) continue; - // Don't set height yet... - height = precipsector->sector->ceilingheight; - - if (curWeather == PRECIP_SNOW) - { - // Not in a sector with visible sky -- exception for NiGHTS. - if (!(maptol & TOL_NIGHTS) && precipsector->sector->ceilingpic != skyflatnum) - continue; - - rainmo = P_SpawnSnowMobj(x, y, height, MT_SNOWFLAKE); - mrand = M_RandomByte(); - if (mrand < 64) - P_SetPrecipMobjState(rainmo, S_SNOW3); - else if (mrand < 144) - P_SetPrecipMobjState(rainmo, S_SNOW2); - } - else // everything else. - { - // Not in a sector with visible sky. - if (precipsector->sector->ceilingpic != skyflatnum) - continue; - - rainmo = P_SpawnRainMobj(x, y, height, MT_RAIN); - } - - // Randomly assign a height, now that floorz is set. - rainmo->z = M_RandomRange(rainmo->floorz>>FRACBITS, rainmo->ceilingz>>FRACBITS)<sector->ceilingpic != skyflatnum) + continue; + + rainmo = P_SpawnRainMobj(x, y, height, MT_RAIN); + } + + // Randomly assign a height, now that floorz is set. + rainmo->z = M_RandomRange(rainmo->floorz>>FRACBITS, rainmo->ceilingz>>FRACBITS)<flags != oldflags) + { sec->moved = true; + P_RecalcPrecipInSector(sec); + } } } @@ -7879,6 +7882,7 @@ void T_Disappear(disappear_t *d) } } sectors[s].moved = true; + P_RecalcPrecipInSector(§ors[s]); } if (d->exists) From ec8f64100eef29843c85488faa9bd3983e3955d8 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sat, 6 Jul 2019 00:31:02 -0400 Subject: [PATCH 052/128] Hardcode brick debris --- src/dehacked.c | 2 ++ src/hardware/hw_light.c | 3 +++ src/info.c | 32 ++++++++++++++++++++++++++++++++ src/info.h | 6 ++++++ 4 files changed, 43 insertions(+) diff --git a/src/dehacked.c b/src/dehacked.c index d86161390..f851f4963 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7167,6 +7167,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_ROCKCRUMBLEN", "S_ROCKCRUMBLEO", "S_ROCKCRUMBLEP", + "S_BRICKDEBRIS", #ifdef SEENAMES "S_NAMECHECK", @@ -7881,6 +7882,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_ROCKCRUMBLE14", "MT_ROCKCRUMBLE15", "MT_ROCKCRUMBLE16", + "MT_BRICKDEBRIS", #ifdef SEENAMES "MT_NAMECHECK", diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 949f38064..2feda1f1f 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -580,6 +580,9 @@ light_t *t_lspr[NUMSPRITES] = &lspr[NOLIGHT], // SPR_ROIO &lspr[NOLIGHT], // SPR_ROIP + // Bricks + &lspr[NOLIGHT], // SPR_BRIC + // Gravity Well Objects &lspr[NOLIGHT], // SPR_GWLG &lspr[NOLIGHT], // SPR_GWLR diff --git a/src/info.c b/src/info.c index 074e31ba2..0dee208f8 100644 --- a/src/info.c +++ b/src/info.c @@ -475,6 +475,9 @@ char sprnames[NUMSPRITES + 1][5] = "ROIO", "ROIP", + // Bricks + "BRIC", + // Gravity Well Objects "GWLG", "GWLR", @@ -3861,6 +3864,8 @@ state_t states[NUMSTATES] = {SPR_ROIO, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEO {SPR_ROIP, FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 4, 2, S_NULL}, // S_ROCKCRUMBLEP + {SPR_BRIC, FF_ANIMATE, -1, {A_DebrisRandom}, 7, 2, S_NULL}, // S_BRICKDEBRIS + #ifdef SEENAMES {SPR_NULL, 0, 1, {NULL}, 0, 0, S_NULL}, // S_NAMECHECK #endif @@ -19970,6 +19975,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_BRICKDEBRIS + -1, // doomednum + S_BRICKDEBRIS, // spawnstate + 1, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 255, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 16*FRACUNIT, // radius + 16*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_RUNSPAWNFUNC|MF_NOCLIPHEIGHT|MF_SCENERY, // flags + S_NULL // raisestate + }, + #ifdef SEENAMES { // MT_NAMECHECK -1, // doomednum diff --git a/src/info.h b/src/info.h index 13abfa5f6..75cb00906 100644 --- a/src/info.h +++ b/src/info.h @@ -720,6 +720,9 @@ typedef enum sprite SPR_ROIO, SPR_ROIP, + // Bricks + SPR_BRIC, + // Gravity Well Objects SPR_GWLG, SPR_GWLR, @@ -3923,6 +3926,9 @@ typedef enum state S_ROCKCRUMBLEO, S_ROCKCRUMBLEP, + // Bricks + S_BRICKDEBRIS, + #ifdef SEENAMES S_NAMECHECK, #endif From ef05d81a4c7efcf4bec0eddbc7aa366bc9e8b2d3 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sat, 6 Jul 2019 00:39:36 -0400 Subject: [PATCH 053/128] Change this, not that it really matters but --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index 0dee208f8..49f6d4c8f 100644 --- a/src/info.c +++ b/src/info.c @@ -19984,7 +19984,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // reactiontime sfx_None, // attacksound S_NULL, // painstate - 255, // painchance + 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate From d2adb5e829cce48fad6952aa4f7ff6784568e224 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sat, 6 Jul 2019 18:11:49 -0400 Subject: [PATCH 054/128] Update info.h Also add a case for MT_BRICKDEBRIS to P_MobjThinker --- src/info.h | 3 +++ src/p_mobj.c | 1 + 2 files changed, 4 insertions(+) diff --git a/src/info.h b/src/info.h index 75cb00906..4af76907f 100644 --- a/src/info.h +++ b/src/info.h @@ -4663,6 +4663,9 @@ typedef enum mobj_type MT_ROCKCRUMBLE15, MT_ROCKCRUMBLE16, + // Bricks + MT_BRICKDEBRIS, + #ifdef SEENAMES MT_NAMECHECK, #endif diff --git a/src/p_mobj.c b/src/p_mobj.c index 69550fa73..46f3ef49f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7309,6 +7309,7 @@ void P_MobjThinker(mobj_t *mobj) case MT_ROCKCRUMBLE15: case MT_ROCKCRUMBLE16: case MT_WOODDEBRIS: + case MT_BRICKDEBRIS: if (mobj->z <= P_FloorzAtPos(mobj->x, mobj->y, mobj->z, mobj->height) && mobj->state != &states[mobj->info->deathstate]) { From 867f7ecfcaee37266254a100f5bdcbee63f4e8db Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 8 Jul 2019 13:26:40 +0100 Subject: [PATCH 055/128] ha ha ha how can i possibly describe this commit Just wait for the MR, it won't be far behind. --- src/dehacked.c | 28 ++-- src/hardware/hw_light.c | 1 + src/info.c | 96 +++++++++--- src/info.h | 29 ++-- src/p_enemy.c | 58 +++++-- src/p_inter.c | 44 +++++- src/p_mobj.c | 324 +++++++++++++++++++++++++++++++--------- src/p_user.c | 3 + src/sounds.c | 7 +- src/sounds.h | 1 + 10 files changed, 465 insertions(+), 126 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 6014add3a..97af54f8b 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -4750,15 +4750,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_EGGMOBILE4_RATK6", "S_EGGMOBILE4_RAISE1", "S_EGGMOBILE4_RAISE2", - "S_EGGMOBILE4_RAISE3", - "S_EGGMOBILE4_RAISE4", - "S_EGGMOBILE4_RAISE5", - "S_EGGMOBILE4_RAISE6", - "S_EGGMOBILE4_RAISE7", - "S_EGGMOBILE4_RAISE8", - "S_EGGMOBILE4_RAISE9", - "S_EGGMOBILE4_RAISE10", - "S_EGGMOBILE4_PAIN", + "S_EGGMOBILE4_PAIN1", + "S_EGGMOBILE4_PAIN2", "S_EGGMOBILE4_DIE1", "S_EGGMOBILE4_DIE2", "S_EGGMOBILE4_DIE3", @@ -4776,10 +4769,21 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_EGGMOBILE4_FLEE1", "S_EGGMOBILE4_FLEE2", "S_EGGMOBILE4_MACE", + "S_EGGMOBILE4_MACE_DIE1", + "S_EGGMOBILE4_MACE_DIE2", + "S_EGGMOBILE4_MACE_DIE3", // Boss 4 jet flame - "S_JETFLAME1", - "S_JETFLAME2", + "S_JETFLAME", + + // Boss 4 Spectator Eggrobo + "S_EGGROBO1_IDLE", + "S_EGGROBO1_BSLAP1", + "S_EGGROBO2_BSLAP2", + "S_EGGROBO1_PISSED", + + // Boss 4 Spectator Eggrobo jet flame + "S_EGGROBOJET", // Boss 5 "S_FANG_IDLE1", @@ -7262,6 +7266,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_EGGMOBILE4", "MT_EGGMOBILE4_MACE", "MT_JETFLAME", + "MT_EGGROBO1", + "MT_EGGROBO1JET", // Boss 5 "MT_FANG", diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 949f38064..8147681f9 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -202,6 +202,7 @@ light_t *t_lspr[NUMSPRITES] = // Boss 4 (Castle Eggman) &lspr[NOLIGHT], // SPR_EGGP &lspr[REDBALL_L], // SPR_EFIR + &lspr[NOLIGHT], // SPR_EGR1 // Boss 5 (Arid Canyon) &lspr[NOLIGHT], //SPR_FANG // replaces EGGQ diff --git a/src/info.c b/src/info.c index 51d41806b..1da0922a4 100644 --- a/src/info.c +++ b/src/info.c @@ -90,6 +90,7 @@ char sprnames[NUMSPRITES + 1][5] = // Boss 4 (Castle Eggman) "EGGP", "EFIR", // Boss 4 jet flame + "EGR1", // Boss 4 Spectator Eggrobo // Boss 5 (Arid Canyon) "FANG", // replaces EGGQ @@ -1351,17 +1352,9 @@ state_t states[NUMSTATES] = {SPR_EGGP, 9,150, {A_Boss4SpeedUp}, sfx_mswing, 0, S_EGGMOBILE4_RATK6}, // S_EGGMOBILE4_RATK5 {SPR_EGGP,10, 2, {NULL}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_RATK6 {SPR_EGGP, 0, 20, {A_Boss4Raise}, sfx_doord1, 0, S_EGGMOBILE4_RAISE2}, // S_EGGMOBILE4_RAISE1 - {SPR_EGGP,13, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE3}, // S_EGGMOBILE4_RAISE2 - {SPR_EGGP,14, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE2}, // S_EGGMOBILE4_RAISE3 - {SPR_EGGP,13, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE5}, // S_EGGMOBILE4_RAISE4 - {SPR_EGGP,14, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE6}, // S_EGGMOBILE4_RAISE5 - {SPR_EGGP,13, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE7}, // S_EGGMOBILE4_RAISE6 - {SPR_EGGP,14, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE8}, // S_EGGMOBILE4_RAISE7 - {SPR_EGGP,13, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE9}, // S_EGGMOBILE4_RAISE8 - {SPR_EGGP,14, 10, {NULL}, 0, 0, S_EGGMOBILE4_RAISE10},// S_EGGMOBILE4_RAISE9 - // rename eventually - {SPR_EGGP,11, 0, {A_Boss4Reverse}, sfx_mswing, 0, S_EGGMOBILE4_PAIN}, // S_EGGMOBILE4_RAISE10 - {SPR_EGGP,11, 24, {A_Pain}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_PAIN + {SPR_EGGP,13|FF_ANIMATE, -1, {NULL}, 1, 10, S_NULL}, // S_EGGMOBILE4_RAISE2 + {SPR_EGGP,11, 0, {A_Boss4Reverse}, sfx_alarm, sfx_s3k60, S_EGGMOBILE4_PAIN2}, // S_EGGMOBILE4_PAIN1 + {SPR_EGGP,11, 24, {A_Pain}, 0, 0, S_EGGMOBILE4_STND}, // S_EGGMOBILE4_PAIN2 {SPR_EGGP,12, 8, {A_Fall}, 0, 0, S_EGGMOBILE4_DIE2}, // S_EGGMOBILE4_DIE1 {SPR_EGGP,12, 8, {A_BossScream}, 0, 0, S_EGGMOBILE4_DIE3}, // S_EGGMOBILE4_DIE2 {SPR_EGGP,12, 8, {A_BossScream}, 0, 0, S_EGGMOBILE4_DIE4}, // S_EGGMOBILE4_DIE3 @@ -1379,10 +1372,21 @@ state_t states[NUMSTATES] = {SPR_EGGP,13, 5, {NULL}, 0, 0, S_EGGMOBILE4_FLEE2}, // S_EGGMOBILE4_FLEE1 {SPR_EGGP,14, 5, {NULL}, 0, 0, S_EGGMOBILE4_FLEE1}, // S_EGGMOBILE4_FLEE2 {SPR_BMCE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGMOBILE4_MACE + {SPR_BMCE, 0, 2, {A_BossScream}, 1, MT_SONIC3KBOSSEXPLODE, S_EGGMOBILE4_MACE_DIE2}, // S_EGGMOBILE4_MACE_DIE1 + {SPR_NULL, 0, 2, {A_BossScream}, 1, MT_SONIC3KBOSSEXPLODE, S_EGGMOBILE4_MACE_DIE3}, // S_EGGMOBILE4_MACE_DIE2 + {SPR_NULL, 0, 0, {A_Repeat}, 7, S_EGGMOBILE4_MACE_DIE1, S_BOSSEXPLODE}, // S_EGGMOBILE4_MACE_DIE3 - // Boss 4 Jet flame - {SPR_EFIR, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_JETFLAME2}, // S_JETFLAME1 - {SPR_EFIR, FF_FULLBRIGHT|1, 1, {NULL}, 0, 0, S_JETFLAME1}, // S_JETFLAME2 + // Boss 4 jet flame + {SPR_EFIR, FF_FULLBRIGHT|FF_ANIMATE, -1, {NULL}, 1, 1, S_NULL}, // S_JETFLAME + + // Boss 4 Spectator Eggrobo + {SPR_EGR1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_EGGROBO1_STND + {SPR_EGR1, 5, 2, {NULL}, 0, 0, S_EGGROBO1_BSLAP2}, // S_EGGROBO1_BSLAP1 + {SPR_EGR1, FF_ANIMATE|6, 35, {NULL}, 1, 2, S_EGGROBO1_STND}, // S_EGGROBO1_BSLAP2 + {SPR_EGR1, FF_ANIMATE|3, -1, {NULL}, 1, 2, S_NULL}, // S_EGGROBO1_PISSED + + // Boss 4 Spectator Eggrobo jet flame + {SPR_EFIR, FF_FULLBRIGHT|2, -1, {NULL}, 0, 0, S_NULL}, // S_EGGROBOJET // Boss 5 {SPR_FANG, 2, 16, {A_Look}, 1, 0, S_FANG_IDLE2}, // S_FANG_IDLE1 @@ -5585,7 +5589,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // seesound 0, // reactiontime sfx_None, // attacksound - S_EGGMOBILE4_RAISE10, // painstate + S_EGGMOBILE4_PAIN1,// painstate 0, // painchance sfx_dmpain, // painsound S_EGGMOBILE4_LATK1,// meleestate @@ -5617,9 +5621,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_BOSSEXPLODE, // deathstate + S_EGGMOBILE4_MACE_DIE1, // deathstate S_NULL, // xdeathstate - sfx_cybdth, // deathsound + sfx_None, // deathsound 48*FRACUNIT, // speed 34*FRACUNIT, // radius 68*FRACUNIT, // height @@ -5633,7 +5637,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = { // MT_JETFLAME -1, // doomednum - S_JETFLAME1, // spawnstate + S_JETFLAME, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -5654,7 +5658,61 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = DMG_FIRE, // mass 0, // damage sfx_None, // activesound - MF_NOGRAVITY|MF_PAIN|MF_FIRE, // flags + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags + S_NULL // raisestate + }, + + { // MT_EGGROBO1 + 1127, // doomednum + S_EGGROBO1_STND,// spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_s3ka0, // seesound + 8, // reactiontime + sfx_bsnipe, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_EGGROBO1_BSLAP1, // meleestate + S_NULL, // missilestate + S_EGGROBO1_PISSED, // deathstate + S_NULL, // xdeathstate + sfx_s3ka0, // deathsound + 12*FRACUNIT, // speed + 20*FRACUNIT, // radius + 72*FRACUNIT, // height + 0, // display offset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT, // flags + S_NULL // raisestate + }, + + { // MT_EGGROBOJET + -1, // doomednum + S_EGGROBOJET, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 1, // speed + 10*FRACUNIT, // radius + 28*FRACUNIT, // height + 0, // display offset + 0, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY, // flags S_NULL // raisestate }, diff --git a/src/info.h b/src/info.h index 75091ce1e..6034dfc7e 100644 --- a/src/info.h +++ b/src/info.h @@ -335,6 +335,7 @@ typedef enum sprite // Boss 4 (Castle Eggman) SPR_EGGP, SPR_EFIR, // Boss 4 jet flame + SPR_EGR1, // Boss 4 Spectator Eggrobo // Boss 5 (Arid Canyon) SPR_FANG, // replaces EGGQ @@ -1505,15 +1506,8 @@ typedef enum state S_EGGMOBILE4_RATK6, S_EGGMOBILE4_RAISE1, S_EGGMOBILE4_RAISE2, - S_EGGMOBILE4_RAISE3, - S_EGGMOBILE4_RAISE4, - S_EGGMOBILE4_RAISE5, - S_EGGMOBILE4_RAISE6, - S_EGGMOBILE4_RAISE7, - S_EGGMOBILE4_RAISE8, - S_EGGMOBILE4_RAISE9, - S_EGGMOBILE4_RAISE10, - S_EGGMOBILE4_PAIN, + S_EGGMOBILE4_PAIN1, + S_EGGMOBILE4_PAIN2, S_EGGMOBILE4_DIE1, S_EGGMOBILE4_DIE2, S_EGGMOBILE4_DIE3, @@ -1531,10 +1525,21 @@ typedef enum state S_EGGMOBILE4_FLEE1, S_EGGMOBILE4_FLEE2, S_EGGMOBILE4_MACE, + S_EGGMOBILE4_MACE_DIE1, + S_EGGMOBILE4_MACE_DIE2, + S_EGGMOBILE4_MACE_DIE3, // Boss 4 jet flame - S_JETFLAME1, - S_JETFLAME2, + S_JETFLAME, + + // Boss 4 Spectator Eggrobo + S_EGGROBO1_STND, + S_EGGROBO1_BSLAP1, + S_EGGROBO1_BSLAP2, + S_EGGROBO1_PISSED, + + // Boss 4 Spectator Eggrobo jet flame + S_EGGROBOJET, // Boss 5 S_FANG_IDLE1, @@ -4037,6 +4042,8 @@ typedef enum mobj_type MT_EGGMOBILE4, MT_EGGMOBILE4_MACE, MT_JETFLAME, + MT_EGGROBO1, + MT_EGGROBO1JET, // Boss 5 MT_FANG, diff --git a/src/p_enemy.c b/src/p_enemy.c index fa6e5e1b0..175431df5 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3154,25 +3154,35 @@ void A_FocusTarget(mobj_t *actor) // Description: Reverse arms direction. // // var1 = sfx to play -// var2 = unused +// var2 = sfx to play in pinch // void A_Boss4Reverse(mobj_t *actor) { sfxenum_t locvar1 = (sfxenum_t)var1; + sfxenum_t locvar2 = (sfxenum_t)var2; #ifdef HAVE_BLUA if (LUA_CallAction("A_Boss4Reverse", actor)) return; #endif - S_StartSound(NULL, locvar1); actor->reactiontime = 0; - if (actor->movedir == 1) - actor->movedir = 2; - else if (actor->movedir == 2) - actor->movedir = 1; - else if (actor->movedir == 4) - actor->movedir = 5; + if (actor->movedir < 3) + { + S_StartSound(NULL, locvar1); + if (actor->movedir == 1) + actor->movedir = 2; + else + actor->movedir = 1; + } else - actor->movedir = 4; + { + S_StartSound(NULL, locvar2); + if (actor->movedir == 4) + actor->movedir = 5; + else + actor->movedir = 4; + actor->angle += ANGLE_180; + actor->movefactor = -actor->movefactor; + } } // Function: A_Boss4SpeedUp @@ -8670,8 +8680,8 @@ void A_BossJetFume(mobj_t *actor) { fixed_t jetx, jety, jetz; - jetx = actor->x + P_ReturnThrustX(actor, actor->angle, -FixedMul(60*FRACUNIT, actor->scale)); - jety = actor->y + P_ReturnThrustY(actor, actor->angle, -FixedMul(60*FRACUNIT, actor->scale)); + jetx = actor->x + P_ReturnThrustX(actor, actor->angle, -60*actor->scale); + jety = actor->y + P_ReturnThrustY(actor, actor->angle, -60*actor->scale); if (actor->eflags & MFE_VERTICALFLIP) jetz = actor->z + actor->height - FixedMul(17*FRACUNIT + mobjinfo[MT_PROPELLER].height, actor->scale); else @@ -8704,7 +8714,7 @@ void A_BossJetFume(mobj_t *actor) if (actor->eflags & MFE_VERTICALFLIP) jetz = actor->z + actor->height + FixedMul(50*FRACUNIT - mobjinfo[MT_JETFLAME].height, actor->scale); else - jetz = actor->z - FixedMul(50*FRACUNIT, actor->scale); + jetz = actor->z - 50*actor->scale; filler = P_SpawnMobj(actor->x, actor->y, jetz, MT_JETFLAME); P_SetTarget(&filler->target, actor); // Boss 4 already uses its tracer for other things @@ -8713,6 +8723,30 @@ void A_BossJetFume(mobj_t *actor) if (actor->eflags & MFE_VERTICALFLIP) filler->flags2 |= MF2_OBJECTFLIP; } + else if (locvar1 == 4) // Boss 4 Spectator Eggrobo jet flame + { + fixed_t jetx, jety, jetz, movefactor = 12; + + jetz = actor->z; + if (actor->eflags & MFE_VERTICALFLIP) + jetz += (actor->height - FixedMul(mobjinfo[MT_EGGROBO1JET].height, actor->scale)); + + while (true) + { + jetx = actor->x + P_ReturnThrustX(actor, actor->angle+ANGLE_90, movefactor*actor->scale) - P_ReturnThrustX(actor, actor->angle, 19*actor->scale); + jety = actor->y + P_ReturnThrustY(actor, actor->angle+ANGLE_90, movefactor*actor->scale) - P_ReturnThrustY(actor, actor->angle, 19*actor->scale); + filler = P_SpawnMobj(jetx, jety, jetz, MT_EGGROBO1JET); + filler->movefactor = movefactor; + P_SetTarget(&filler->target, actor); + filler->destscale = actor->scale; + P_SetScale(filler, filler->destscale); + if (actor->eflags & MFE_VERTICALFLIP) + filler->flags2 |= MF2_OBJECTFLIP; + if (movefactor <= 0) + break; + movefactor = -movefactor; + } + } } // Function: A_RandomState diff --git a/src/p_inter.c b/src/p_inter.c index b6bb3ba49..3e1b74e56 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -315,6 +315,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // Can happen with a sliding player corpse. if (toucher->health <= 0) return; + if (special->health <= 0) + return; if (heightcheck) { @@ -340,9 +342,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } } - if (special->health <= 0) - return; - player = toucher->player; I_Assert(player != NULL); // Only players can touch stuff! @@ -1557,6 +1556,45 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } return; + case MT_EGGROBO1: + if (special->state == &states[special->info->deathstate]) + return; + if (P_PlayerInPain(player)) + return; + + P_SetMobjState(special, special->info->meleestate); + special->angle = special->movedir; + special->momx = special->momy = 0; + + // Buenos Dias Mandy + P_SetPlayerMobjState(toucher, S_PLAY_STUN); + player->pflags &= ~PF_APPLYAUTOBRAKE; + player->drawangle = special->angle + ANGLE_180; + P_InstaThrust(toucher, special->angle, FixedMul(3*special->info->speed, special->scale/2)); + toucher->z += P_MobjFlip(toucher); + if (toucher->eflags & MFE_UNDERWATER) // unlikely. + P_SetObjectMomZ(toucher, FixedDiv(10511*FRACUNIT,2600*FRACUNIT), false); + else + P_SetObjectMomZ(toucher, FixedDiv(69*FRACUNIT,10*FRACUNIT), false); + if (P_IsLocalPlayer(player)) + { + quake.intensity = 9*FRACUNIT; + quake.time = TICRATE/2; + quake.epicenter = NULL; + } + +#if 0 // camera redirection - deemed unnecessary + toucher->angle = special->angle; + if (player == &players[consoleplayer]) + localangle = toucher->angle; + else if (player == &players[secondarydisplayplayer]) + localangle2 = toucher->angle; +#endif + + S_StartSound(toucher, special->info->attacksound); // home run + + return; + case MT_BIGTUMBLEWEED: case MT_LITTLETUMBLEWEED: if (toucher->momx || toucher->momy) diff --git a/src/p_mobj.c b/src/p_mobj.c index df3081bdf..dd7479060 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -4780,9 +4780,11 @@ static void P_Boss4PopSpikeballs(mobj_t *mobj) // static void P_Boss4Thinker(mobj_t *mobj) { + fixed_t movespeed = 0; + if ((statenum_t)(mobj->state-states) == mobj->info->spawnstate) { - if (mobj->flags2 & MF2_FRET && (mobj->health > mobj->info->damage || mobj->movedir == 4)) + if (mobj->flags2 & MF2_FRET && (mobj->health > mobj->info->damage)) mobj->flags2 &= ~MF2_FRET; mobj->reactiontime = 0; // Drop the cage immediately. } @@ -4798,6 +4800,44 @@ static void P_Boss4Thinker(mobj_t *mobj) return; } + if (mobj->movedir) // only not during init + { + INT32 oldmovecount = mobj->movecount; + if (mobj->movedir == 3) // pinch start + movespeed = -210<<(FRACBITS>>1); + else if (mobj->movedir > 3) // pinch + { + movespeed = 420<<(FRACBITS>>1); + movespeed += (420*(mobj->info->damage-mobj->health)<<(FRACBITS>>1)); + if (mobj->movedir == 4) + movespeed = -movespeed; + } + else // normal + { + movespeed = 170<<(FRACBITS>>1); + movespeed += ((50*(mobj->info->spawnhealth-mobj->health))<<(FRACBITS>>1)); + if (mobj->movedir == 2) + movespeed = -movespeed; + if (mobj->movefactor) + movespeed /= 2; + else if (mobj->threshold) + { + // 1 -> 1.5 second timer + INT32 maxtimer = TICRATE+(TICRATE*(mobj->info->spawnhealth-mobj->health)/10); + if (maxtimer < 1) + maxtimer = 1; + maxtimer = ((mobj->threshold*movespeed)/(2*maxtimer)); + movespeed -= maxtimer; + } + } + + mobj->movecount += movespeed + 360*FRACUNIT; + mobj->movecount %= 360*FRACUNIT; + + if (((oldmovecount>>FRACBITS)%120 >= 60) && !((mobj->movecount>>FRACBITS)%120 >= 60)) + S_StartSound(NULL, sfx_mswing); + } + // movedir == battle stage: // 0: initialization // 1: phase 1 forward @@ -4819,7 +4859,6 @@ static void P_Boss4Thinker(mobj_t *mobj) mobj_t *seg, *base = mobj; // First frame init, spawn all the things. mobj->watertop = mobj->z; - mobj->flags2 |= MF2_STRONGBOX; // don't perform the linedef executor at start z = mobj->z + mobj->height/2 - mobjinfo[MT_EGGMOBILE4_MACE].height/2; for (arm = 0; arm <3 ; arm++) { @@ -4851,22 +4890,13 @@ static void P_Boss4Thinker(mobj_t *mobj) fixed_t oldz = mobj->movecount; mobj->threshold -= 5*FRACUNIT; mobj->movecount += mobj->threshold; - if (mobj->movecount < 0) - mobj->movecount = 0; - P_Boss4MoveCage(mobj, mobj->movecount - oldz); - P_Boss4MoveSpikeballs(mobj, 0, mobj->movecount); - if (mobj->movecount == 0) + if (mobj->movecount <= 0) { - //mobj->threshold = 3*TICRATE; - mobj->extravalue1 = 1; - //P_LinedefExecute(LE_BOSS4DROP + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0), mobj, NULL); -- oh no you don't - S_StartSound(NULL, sfx_doorc2); - quake.intensity = 10<movecount = 0; mobj->movedir++; // Initialization complete, next phase! } + P_Boss4MoveCage(mobj, mobj->movecount - oldz); + P_Boss4MoveSpikeballs(mobj, 0, mobj->movecount); } return; } @@ -4880,15 +4910,16 @@ static void P_Boss4Thinker(mobj_t *mobj) case 3: { fixed_t z; - if (mobj->z < mobj->watertop+(512<z < mobj->watertop+(400<momz = 8*FRACUNIT; else { - mobj->momz = 0; + mobj->momz = mobj->movefactor = 0; + mobj->threshold = 1110<movedir++; } - mobj->movecount -= 210<<(FRACBITS>>1); - mobj->movecount %= 360*FRACUNIT; + z = mobj->z - mobj->watertop - mobjinfo[MT_EGGMOBILE4_MACE].height - mobj->height/2; if (z < (8<movecount), 0); // So don't pull the spikeballs along yet. @@ -4900,23 +4931,30 @@ static void P_Boss4Thinker(mobj_t *mobj) case 4: case 5: { - fixed_t movespeed = 420<<(FRACBITS>>1); - movespeed += (420*(mobj->info->damage-mobj->health)<<(FRACBITS>>1)); - if (mobj->movedir == 4) - mobj->movecount -= movespeed; - else - mobj->movecount += movespeed; + mobj->angle -= FixedAngle(movespeed/8); + + if (mobj->movefactor != mobj->threshold) + { + if (mobj->threshold - mobj->movefactor < FRACUNIT) + { + mobj->movefactor = mobj->threshold; + mobj->flags2 &= ~MF2_FRET; + } + else + mobj->movefactor += (mobj->threshold - mobj->movefactor)/8; + } + + if (mobj->spawnpoint) + P_TryMove(mobj, + (mobj->spawnpoint->x<angle, mobj->movefactor), + (mobj->spawnpoint->y<angle, mobj->movefactor), + true); - if (mobj->z < (mobj->watertop + ((512+128*(mobj->info->damage-mobj->health))<momz = 8*FRACUNIT; - else - mobj->momz = 0; - mobj->movecount %= 360*FRACUNIT; P_Boss4PinchSpikeballs(mobj, FixedAngle(mobj->movecount), mobj->z - mobj->watertop - mobjinfo[MT_EGGMOBILE4_MACE].height - mobj->height/2); if (!mobj->target || !mobj->target->health) P_SupermanLook4Players(mobj); - A_FaceTarget(mobj); + //A_FaceTarget(mobj); return; } @@ -4936,18 +4974,21 @@ static void P_Boss4Thinker(mobj_t *mobj) if (mobj->reactiontime == 1) { fixed_t oldz = mobj->movefactor; - if (mobj->movefactor < 128*FRACUNIT) + if (mobj->movefactor != 128*FRACUNIT) { - mobj->movefactor += 8*FRACUNIT; - P_Boss4MoveCage(mobj, mobj->movefactor - oldz); - // 5 -> 2.5 second timer - mobj->threshold = 5*TICRATE-(TICRATE/2)*(mobj->info->spawnhealth-mobj->health); - if (mobj->threshold < 1) - mobj->threshold = 1; - } - else if (mobj->movefactor > 128*FRACUNIT) - { - mobj->movefactor = 128*FRACUNIT; + if (mobj->movefactor < 128*FRACUNIT) + { + mobj->movefactor += 8*FRACUNIT; + if (!oldz) + { + // 5 -> 2.5 second timer + mobj->threshold = 5*TICRATE-(TICRATE*(mobj->info->spawnhealth-mobj->health)/2); + if (mobj->threshold < 1) + mobj->threshold = 1; + } + } + else + mobj->movefactor = 128*FRACUNIT; P_Boss4MoveCage(mobj, mobj->movefactor - oldz); } } @@ -4959,37 +5000,26 @@ static void P_Boss4Thinker(mobj_t *mobj) if (mobj->movefactor < 0) mobj->movefactor = 0; P_Boss4MoveCage(mobj, mobj->movefactor - oldz); - if (mobj->flags2 & MF2_STRONGBOX) - mobj->flags2 &= ~MF2_STRONGBOX; - else if (!mobj->movefactor) + if (!mobj->movefactor) { if (mobj->health <= mobj->info->damage) { // Proceed to pinch phase! P_Boss4DestroyCage(mobj); mobj->movedir = 3; P_LinedefExecute(LE_PINCHPHASE + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0), mobj, NULL); + P_Boss4MoveSpikeballs(mobj, FixedAngle(mobj->movecount), 0); + var1 = 3; + A_BossJetFume(mobj); return; } P_LinedefExecute(LE_BOSS4DROP - (mobj->info->spawnhealth-mobj->health) + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0), mobj, NULL); - S_StartSound(NULL, sfx_doorc2); - quake.intensity = 10< 1.5 second timer + mobj->threshold = TICRATE+(TICRATE*(mobj->info->spawnhealth-mobj->health)/10); + if (mobj->threshold < 1) + mobj->threshold = 1; } } - { - fixed_t movespeed = 170<<(FRACBITS>>1); - movespeed += ((50*(mobj->info->spawnhealth-mobj->health))<<(FRACBITS>>1)); - if (mobj->movefactor) - movespeed /= 2; - if (mobj->movedir == 2) - mobj->movecount -= movespeed; - else - mobj->movecount += movespeed; - } - mobj->movecount %= 360*FRACUNIT; P_Boss4MoveSpikeballs(mobj, FixedAngle(mobj->movecount), mobj->movefactor); // Check for attacks, always tick the timer even while animating!! @@ -5013,12 +5043,10 @@ static void P_Boss4Thinker(mobj_t *mobj) if (mobj->health <= mobj->info->damage) { // Proceed to pinch phase! P_Boss4DestroyCage(mobj); - // spawn jet's flame now you're flying upwards - // tracer is already used, so if this ever gets reached again we've got problems - var1 = 3; - A_BossJetFume(mobj); mobj->movedir = 3; P_LinedefExecute(LE_PINCHPHASE + (mobj->spawnpoint ? mobj->spawnpoint->extrainfo*LE_PARAMWIDTH : 0), mobj, NULL); + var1 = 3; + A_BossJetFume(mobj); return; } @@ -8097,7 +8125,166 @@ void P_MobjThinker(mobj_t *mobj) P_UnsetThingPosition(mobj); mobj->x = mobj->target->x; mobj->y = mobj->target->y; - mobj->z = mobj->target->z - FixedMul(50*FRACUNIT, mobj->target->scale); + mobj->z = mobj->target->z - 50*mobj->target->scale; + mobj->floorz = mobj->z; + mobj->ceilingz = mobj->z+mobj->height; + P_SetThingPosition(mobj); + } + break; + case MT_EGGROBO1: +#define SPECTATORRADIUS (96*mobj->scale) + { + if (!(mobj->flags2 & MF2_STRONGBOX)) + { + mobj->cusval = mobj->x; // eat my SOCs, p_mobj.h warning, we have lua now + mobj->cvmem = mobj->y; // ditto + mobj->movedir = mobj->angle; + mobj->threshold = P_MobjFlip(mobj)*10*mobj->scale; + if (mobj->threshold < 0) + mobj->threshold += (mobj->ceilingz - mobj->height); + else + mobj->threshold += mobj->floorz; + var1 = 4; + A_BossJetFume(mobj); + mobj->flags2 |= MF2_STRONGBOX; + } + + if (mobj->state == &states[mobj->info->deathstate]) // todo: make map actually set health to 0 for these + { + if (mobj->movecount) + { + if (!(--mobj->movecount)) + S_StartSound(mobj, mobj->info->deathsound); + } + else + { + mobj->momz += P_MobjFlip(mobj)*mobj->scale; + if (mobj->momz > 0) + { + if (mobj->z + mobj->momz > mobj->ceilingz + (1000<z + mobj->height + mobj->momz < mobj->floorz - (1000<z = mobj->threshold + FixedMul(FINESINE(((leveltime + mobj->movecount)*ANG2>>(ANGLETOFINESHIFT-2)) & FINEMASK), 8*mobj->scale); + if (mobj->state != &states[mobj->info->meleestate]) + { + boolean didmove = false; + + if (mobj->state == &states[mobj->info->spawnstate]) + { + UINT8 i; + fixed_t dist = INT32_MAX; + + for (i = 0; i < MAXPLAYERS; i++) + { + fixed_t compdist; + if (!playeringame[i]) + continue; + if (players[i].spectator) + continue; + if (!players[i].mo) + continue; + if (!players[i].mo->health) + continue; + if (P_PlayerInPain(&players[i])) + continue; + if (players[i].mo->z > mobj->z + mobj->height + 8*mobj->scale) + continue; + if (players[i].mo->z + players[i].mo->height < mobj->z - 8*mobj->scale) + continue; + compdist = P_AproxDistance( + players[i].mo->x + players[i].mo->momx - mobj->cusval, + players[i].mo->y + players[i].mo->momy - mobj->cvmem); + if (compdist >= dist) + continue; + dist = compdist; + P_SetTarget(&mobj->target, players[i].mo); + } + + if (dist < (SPECTATORRADIUS<<1)) + { + didmove = true; + mobj->frame = 3 + ((leveltime & 2)>>1); + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); + + if (P_AproxDistance( + mobj->x - mobj->cusval, + mobj->y - mobj->cvmem) + < mobj->scale) + S_StartSound(mobj, mobj->info->seesound); + + P_TeleportMove(mobj, + (15*(mobj->x>>4)) + (mobj->cusval>>4) + P_ReturnThrustX(mobj, mobj->angle, SPECTATORRADIUS>>4), + (15*(mobj->y>>4)) + (mobj->cvmem>>4) + P_ReturnThrustY(mobj, mobj->angle, SPECTATORRADIUS>>4), + mobj->z); + } + else + { + angle_t diff = (mobj->movedir - mobj->angle); + if (diff > ANGLE_180) + diff = InvAngle(InvAngle(diff)/8); + else + diff /= 8; + mobj->angle += diff; + + dist = FINECOSINE(((leveltime + mobj->movecount)*ANG2>>(ANGLETOFINESHIFT-2)) & FINEMASK); + + if (abs(dist) < FRACUNIT/2) + mobj->frame = 0; + else + mobj->frame = (dist > 0) ? 1 : 2; + } + } + + if (!didmove) + { + if (P_AproxDistance( + mobj->x - mobj->cusval, + mobj->y - mobj->cvmem) + < mobj->scale) + P_TeleportMove(mobj, + mobj->cusval, + mobj->cvmem, + mobj->z); + else + P_TeleportMove(mobj, + (15*(mobj->x>>4)) + (mobj->cusval>>4), + (15*(mobj->y>>4)) + (mobj->cvmem>>4), + mobj->z); + } + } + } + } + break; +#undef SPECTATORRADIUS + case MT_EGGROBO1JET: + { + if (!mobj->target || P_MobjWasRemoved(mobj->target) // if you have no target + || (mobj->target->health <= 0)) // or your target isn't a boss and it's popped now + { // then remove yourself as well! + P_RemoveMobj(mobj); + return; + } + + mobj->flags2 ^= MF2_DONTDRAW; + + P_UnsetThingPosition(mobj); + mobj->x = mobj->target->x + P_ReturnThrustX(mobj, mobj->target->angle+ANGLE_90, mobj->movefactor*mobj->target->scale) - P_ReturnThrustX(mobj, mobj->target->angle, 19*mobj->target->scale); + mobj->y = mobj->target->y + P_ReturnThrustY(mobj, mobj->target->angle+ANGLE_90, mobj->movefactor*mobj->target->scale) - P_ReturnThrustY(mobj, mobj->target->angle, 19*mobj->target->scale); + mobj->z = mobj->target->z; + if (mobj->target->eflags & MFE_VERTICALFLIP) + mobj->z += (mobj->target->height - mobj->height); mobj->floorz = mobj->z; mobj->ceilingz = mobj->z+mobj->height; P_SetThingPosition(mobj); @@ -9300,6 +9487,9 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) case MT_BALLOON: mobj->color = SKINCOLOR_RED; break; + case MT_EGGROBO1: + mobj->movecount = P_RandomKey(13); + mobj->color = SKINCOLOR_RUBY + P_RandomKey(MAXSKINCOLORS - SKINCOLOR_RUBY); case MT_HIVEELEMENTAL: mobj->extravalue1 = 5; break; @@ -10126,7 +10316,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) { x = mthing->x << FRACBITS; y = mthing->y << FRACBITS; - angle = FixedAngle(mthing->angle*FRACUNIT); + angle = FixedAngle(mthing->angle<pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate] && player->powers[pw_flashing]) return true; + if (player->mo->state == &states[S_PLAY_STUN]) + return true; + return false; } diff --git a/src/sounds.c b/src/sounds.c index 56de4a9c5..de043493a 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -197,6 +197,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"corkh", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Cork hit"}, {"bowl", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bowling"}, {"chuchu", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Train horn"}, + {"bsnipe", false, 200, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Home-run smash"}, // Menu, interface {"chchng", false, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Score"}, @@ -334,7 +335,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3k5d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Heavy hit"}, {"s3k5e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Firing laser"}, {"s3k5f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Crusher stomp"}, - {"s3k60", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flying away"}, + {"s3k60", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Accelerating"}, {"s3k61", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drilling"}, {"s3k62", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Jump"}, {"s3k63", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Starpost"}, @@ -430,8 +431,8 @@ sfxinfo_t S_sfx[NUMSFX] = {"s3kbcl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // long version of previous {"s3kbds", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flying fortress"}, {"s3kbdl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flying fortress"}, // ditto - {"s3kbes", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flying away"}, - {"s3kbel", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flying away"}, // ditto + {"s3kbes", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flying"}, + {"s3kbel", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flying"}, // ditto {"s3kbfs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Turbine"}, {"s3kbfl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Turbine"}, // ditto {"s3kc0s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Turbine"}, diff --git a/src/sounds.h b/src/sounds.h index 475309121..a9f28ffb2 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -263,6 +263,7 @@ typedef enum sfx_corkh, sfx_bowl, sfx_chuchu, + sfx_bsnipe, // Menu, interface sfx_chchng, From 5e0d18be2d0aee0576e6ceba23f9221a04e89c0d Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 8 Jul 2019 13:35:15 +0100 Subject: [PATCH 056/128] Before I forget... --- src/f_finale.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/f_finale.c b/src/f_finale.c index 5b21ad95a..1cae457a2 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1022,6 +1022,7 @@ static const char *credits[] = { "", "\1Boss Design", "Ben \"Mystic\" Geyer", + "Vivian \"toaster\" Grannell", "Thomas \"Shadow Hog\" Igoe", "John \"JTE\" Muniz", "Samuel \"Prime 2.0\" Peters", From a65925aeca428939e03506302ccbda670e090ce7 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 4 Jul 2019 14:43:18 +0100 Subject: [PATCH 057/128] Realised I accidentially broke rain in the rainfixes branch (oh, the irony!), realised it needed a few additional P_RecalcPrecipInSector calls to properly work with the new arena, and increased its speed. If you must, I can cherrypick this into another branch - but it's required for this one, at least. --- src/info.c | 6 ++-- src/p_floor.c | 2 +- src/p_mobj.c | 81 +++++++++++++++++++++++++-------------------------- src/p_spec.c | 4 +++ 4 files changed, 47 insertions(+), 46 deletions(-) diff --git a/src/info.c b/src/info.c index 074e31ba2..8a699f91a 100644 --- a/src/info.c +++ b/src/info.c @@ -3187,8 +3187,8 @@ state_t states[NUMSTATES] = {SPR_SSWB, 1, 1, {NULL}, 0, 0, S_BHORIZ1}, // S_BHORIZ8 // Rain - {SPR_RAIN, FF_TRANS50, -1, {NULL}, 0, 0, S_NULL}, // S_RAIN1 - {SPR_RAIN, FF_TRANS50, 1, {NULL}, 0, 0, S_RAIN1}, // S_RAINRETURN + {SPR_RAIN, FF_FULLBRIGHT|FF_TRANS50, -1, {NULL}, 0, 0, S_NULL}, // S_RAIN1 + {SPR_RAIN, FF_FULLBRIGHT|FF_TRANS50, 1, {NULL}, 0, 0, S_RAIN1}, // S_RAINRETURN // Snowflake {SPR_SNO1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SNOW1 @@ -16113,7 +16113,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound - -24*FRACUNIT, // speed + -72*FRACUNIT, // speed 1*FRACUNIT, // radius 8*FRACUNIT, // height 0, // display offset diff --git a/src/p_floor.c b/src/p_floor.c index 4a03f70c0..ed2afd13d 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -3130,7 +3130,7 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover) // no longer exists (can't collide with again) rover->flags &= ~FF_EXISTS; rover->master->frontsector->moved = true; - sec->moved = true; + P_RecalcPrecipInSector(sec); } // Used for bobbing platforms on the water diff --git a/src/p_mobj.c b/src/p_mobj.c index 69550fa73..187766dcb 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9600,12 +9600,12 @@ consvar_t cv_flagtime = {"flagtime", "30", CV_NETVAR|CV_CHEAT, flagtime_cons_t, void P_SpawnPrecipitation(void) { - INT32 i /*, j*/, mrand; + INT32 i, mrand; fixed_t basex, basey, x, y, height; subsector_t *precipsector = NULL; precipmobj_t *rainmo = NULL; - if (dedicated || /*!cv_precipdensity*/!cv_drawdist_precip.value || curWeather == PRECIP_NONE) + if (dedicated || !(cv_drawdist_precip.value) || curWeather == PRECIP_NONE) return; // Use the blockmap to narrow down our placing patterns @@ -9614,50 +9614,47 @@ void P_SpawnPrecipitation(void) basex = bmaporgx + (i % bmapwidth) * MAPBLOCKSIZE; basey = bmaporgy + (i / bmapwidth) * MAPBLOCKSIZE; - //for (j = 0; j < cv_precipdensity.value; ++j) -- density is 1 for us always + x = basex + ((M_RandomKey(MAPBLOCKUNITS<<3)<>3); + y = basey + ((M_RandomKey(MAPBLOCKUNITS<<3)<>3); + + precipsector = R_IsPointInSubsector(x, y); + + // No sector? Stop wasting time, + // move on to the next entry in the blockmap + if (!precipsector) + continue; + + // Exists, but is too small for reasonable precipitation. + if (!(precipsector->sector->floorheight <= precipsector->sector->ceilingheight - (32<sector->ceilingheight; + + if (curWeather == PRECIP_SNOW) { - x = basex + ((M_RandomKey(MAPBLOCKUNITS<<3)<>3); - y = basey + ((M_RandomKey(MAPBLOCKUNITS<<3)<>3); - - precipsector = R_IsPointInSubsector(x, y); - - // No sector? Stop wasting time, - // move on to the next entry in the blockmap - if (!precipsector) - break; - - // Exists, but is too small for reasonable precipitation. - if (!(precipsector->sector->floorheight <= precipsector->sector->ceilingheight - (32<sector->ceilingpic != skyflatnum) continue; - // Don't set height yet... - height = precipsector->sector->ceilingheight; - - if (curWeather == PRECIP_SNOW) - { - // Not in a sector with visible sky -- exception for NiGHTS. - if (!(maptol & TOL_NIGHTS) && precipsector->sector->ceilingpic != skyflatnum) - continue; - - rainmo = P_SpawnSnowMobj(x, y, height, MT_SNOWFLAKE); - mrand = M_RandomByte(); - if (mrand < 64) - P_SetPrecipMobjState(rainmo, S_SNOW3); - else if (mrand < 144) - P_SetPrecipMobjState(rainmo, S_SNOW2); - } - else // everything else. - { - // Not in a sector with visible sky. - if (precipsector->sector->ceilingpic != skyflatnum) - continue; - - rainmo = P_SpawnRainMobj(x, y, height, MT_RAIN); - } - - // Randomly assign a height, now that floorz is set. - rainmo->z = M_RandomRange(rainmo->floorz>>FRACBITS, rainmo->ceilingz>>FRACBITS)<sector->ceilingpic != skyflatnum) + continue; + + rainmo = P_SpawnRainMobj(x, y, height, MT_RAIN); + } + + // Randomly assign a height, now that floorz is set. + rainmo->z = M_RandomRange(rainmo->floorz>>FRACBITS, rainmo->ceilingz>>FRACBITS)<flags != oldflags) + { sec->moved = true; + P_RecalcPrecipInSector(sec); + } } } @@ -7879,6 +7882,7 @@ void T_Disappear(disappear_t *d) } } sectors[s].moved = true; + P_RecalcPrecipInSector(§ors[s]); } if (d->exists) From 4da108748b4823b458104388953f5ea99f800b7d Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 8 Jul 2019 21:17:40 +0100 Subject: [PATCH 058/128] Use M_SetupNextMenu to actually set up the Sound Options menu "properly" instead of the old hacks. If you wanted the game to reset the item selected to the top option like before though, I left a line commented out that would do that for you. Unlike the old item = 0 way, it would automatically be corrected for headers and other spaces (thus kind of future-proofing this code) --- src/m_menu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index cebdd1bbd..dca2e552d 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2953,8 +2953,9 @@ boolean M_Responder(event_t *ev) return true; M_StartControlPanel(); M_Options(0); - currentMenu = &OP_SoundOptionsDef; - itemOn = 0; + // Uncomment the below if you want the menu to reset to the top each time like before. M_SetupNextMenu will fix it automatically. + //OP_SoundOptionsDef.lastOn = 0; + M_SetupNextMenu(&OP_SoundOptionsDef); return true; case KEY_F5: // Video Mode From 5b741d823292d987c7c333bb541acc1af0bc8df4 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 8 Jul 2019 22:56:00 +0200 Subject: [PATCH 059/128] Simplified checks for ML_NETONLY and ML_NONET --- src/p_spec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 68bdf0c82..d67d5e035 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6476,13 +6476,13 @@ void P_SpawnSpecials(INT32 fromnetsave) // set line specials to 0 here too, same reason as above if (netgame || multiplayer) { - if ((lines[i].flags & ML_NONET) == ML_NONET) + if (lines[i].flags & ML_NONET) { lines[i].special = 0; continue; } } - else if ((lines[i].flags & ML_NETONLY) == ML_NETONLY) + else if (lines[i].flags & ML_NETONLY) { lines[i].special = 0; continue; @@ -9204,10 +9204,10 @@ static void P_SearchForDisableLinedefs(void) if (netgame || multiplayer) { - if ((lines[i].flags & ML_NONET) == ML_NONET) + if (lines[i].flags & ML_NONET) continue; } - else if ((lines[i].flags & ML_NETONLY) == ML_NETONLY) + else if (lines[i].flags & ML_NETONLY) continue; // Net-only never triggers in single player // Disable any linedef specials with our tag. From d3d24bc0bde6f0c1fcd719ac6546ad1fcf22dc94 Mon Sep 17 00:00:00 2001 From: MascaraSnake Date: Mon, 8 Jul 2019 22:58:31 +0200 Subject: [PATCH 060/128] Removed the "disable" linedef effect, since it's useless now that the character flags are gone --- src/p_spec.c | 41 +---------------------------------------- 1 file changed, 1 insertion(+), 40 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index d67d5e035..3c81552d8 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -99,7 +99,6 @@ typedef struct thinker_t **thinkers; } thinkerlist_t; -static void P_SearchForDisableLinedefs(void); static void P_SpawnScrollers(void); static void P_SpawnFriction(void); static void P_SpawnPushers(void); @@ -6421,8 +6420,6 @@ void P_SpawnSpecials(INT32 fromnetsave) } } - P_SearchForDisableLinedefs(); // Disable linedefs are now allowed to disable *any* line - P_SpawnScrollers(); // Add generalized scrollers P_SpawnFriction(); // Friction model using linedefs P_SpawnPushers(); // Pusher model using linedefs @@ -6525,12 +6522,6 @@ void P_SpawnSpecials(INT32 fromnetsave) P_AddCameraScanner(§ors[sec], §ors[s], R_PointToAngle2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y)); break; -#ifdef PARANOIA - case 6: // Disable tags if level not cleared - I_Error("Failed to catch a disable linedef"); - break; -#endif - case 7: // Flat alignment - redone by toast if ((lines[i].flags & (ML_NETONLY|ML_NONET)) != (ML_NETONLY|ML_NONET)) // If you can do something... { @@ -9185,34 +9176,4 @@ static void P_SpawnPushers(void) Add_Pusher(p_downwind, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; } -} - -static void P_SearchForDisableLinedefs(void) -{ - size_t i; - INT32 j; - - // Look for disable linedefs - for (i = 0; i < numlines; i++) - { - if (lines[i].special == 6) - { - // Remove special - // Do *not* remove tag. That would mess with the tag lists - // that P_InitTagLists literally just created! - lines[i].special = 0; - - if (netgame || multiplayer) - { - if (lines[i].flags & ML_NONET) - continue; - } - else if (lines[i].flags & ML_NETONLY) - continue; // Net-only never triggers in single player - - // Disable any linedef specials with our tag. - for (j = -1; (j = P_FindLineFromLineTag(&lines[i], j)) >= 0;) - lines[j].special = 0; - } - } -} +} \ No newline at end of file From 21c6836fe070e2ea1dc810c0b036ee952b6d2f98 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 9 Jul 2019 00:19:21 -0400 Subject: [PATCH 061/128] Some few comments --- src/sdl/mixer_sound.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 8127edd60..28cedcf27 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -1116,6 +1116,12 @@ boolean I_LoadSong(char *data, size_t len) size_t probesize; int result; + /* + If the size of the data to be checked is bigger than the recommended size (> 2048) + Let's just set the probe size to the recommended size + Otherwise let's give it the full data size + */ + if (len > openmpt_probe_file_header_get_recommended_size()) probesize = openmpt_probe_file_header_get_recommended_size(); else @@ -1126,7 +1132,7 @@ boolean I_LoadSong(char *data, size_t len) if (result == OPENMPT_PROBE_FILE_HEADER_RESULT_SUCCESS) // We only cared if it succeeded, continue on if not. { openmpt_mhandle = openmpt_module_create_from_memory2(data, len, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - if (!openmpt_mhandle) + if (!openmpt_mhandle) // Failed to create module handle? Show error and return! { mod_err = openmpt_module_error_get_last(openmpt_mhandle); mod_err_str = openmpt_error_string(mod_err); @@ -1134,10 +1140,11 @@ boolean I_LoadSong(char *data, size_t len) return false; } else - return true; + return true; // All good and we're ready for music playback! } -#endif +#endif + // Let's see if Mixer is able to load this. rw = SDL_RWFromMem(data, len); if (rw != NULL) { @@ -1149,7 +1156,6 @@ boolean I_LoadSong(char *data, size_t len) return false; } - // Find the OGG loop point. loop_point = 0.0f; song_length = 0.0f; From 848061d517137bc715892508469d73c83ebda0f5 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 9 Jul 2019 15:42:14 -0400 Subject: [PATCH 062/128] Fix compiling on Linux --- src/p_enemy.c | 2 +- src/r_things.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index f49d60f0d..f58924e2c 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -2348,7 +2348,7 @@ void A_VultureHover(mobj_t *actor) fixed_t targetz; fixed_t distdif; fixed_t memz = actor->z; - INT8 i; + SINT8 i; #ifdef HAVE_BLUA if (LUA_CallAction("A_VultureHover", actor)) diff --git a/src/r_things.c b/src/r_things.c index 155d0f83f..4b1586455 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2447,7 +2447,7 @@ static void R_DrawMaskedList (drawnode_t* head) void R_DrawMasked(maskcount_t* masks, UINT8 nummasks) { drawnode_t heads[nummasks]; /**< Drawnode lists; as many as number of views/portals. */ - INT8 i; + SINT8 i; for (i = 0; i < nummasks; i++) { From 60cb2de6a07944430cedf1f4173f4d6b0a16b4c3 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Tue, 9 Jul 2019 15:51:11 -0400 Subject: [PATCH 063/128] Seperate declarations from code --- src/sdl/mixer_sound.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 28cedcf27..883ba992a 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -111,6 +111,8 @@ static UINT16 current_track; int mod_err = OPENMPT_ERROR_OK; static const char *mod_err_str; static UINT16 current_subsong; +size_t probesize; +int result; #endif static void var_cleanup(void) @@ -1113,9 +1115,6 @@ boolean I_LoadSong(char *data, size_t len) #endif #ifdef HAVE_OPENMPT - size_t probesize; - int result; - /* If the size of the data to be checked is bigger than the recommended size (> 2048) Let's just set the probe size to the recommended size From dc71e297bbd16c0c7b3359877d2fc518ae91e398 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 9 Jul 2019 21:15:12 +0100 Subject: [PATCH 064/128] Fixed mixed-code-and-declaration, shadowed variables, etc ...and the compiler doesn't like P_AddEachTimeThinker being inline anymore for some reason, oh well --- src/p_mobj.c | 7 ++-- src/p_spec.c | 112 +++++++++++++++++++++++++-------------------------- 2 files changed, 60 insertions(+), 59 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index ad85dfc86..1668d8ba1 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5918,9 +5918,10 @@ static void P_Boss9Thinker(mobj_t *mobj) break; case 2: + { // We're all charged and ready now! Unleash the fury!! - S_StopSound(mobj); mobj_t *removemobj = mobj->tracer; + S_StopSound(mobj); P_SetTarget(&mobj->tracer, mobj->hnext); P_RemoveMobj(removemobj); if (mobj->health <= mobj->info->damage) @@ -5960,7 +5961,7 @@ static void P_Boss9Thinker(mobj_t *mobj) // looking for the number of things to fire? that's done in case 1 now } break; - + } case 3: // Return to idle. mobj->watertop = mobj->target->floorz + 32*FRACUNIT; @@ -9239,7 +9240,7 @@ void P_SceneryThinker(mobj_t *mobj) mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) { const mobjinfo_t *info = &mobjinfo[type]; - UINT8 sc = -1; + SINT8 sc = -1; state_t *st; mobj_t *mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); diff --git a/src/p_spec.c b/src/p_spec.c index 3dd3b22bb..4a7ec59e9 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5621,26 +5621,26 @@ ffloor_t *P_GetFFloorByID(sector_t *sec, UINT16 id) /** Adds a newly formed 3Dfloor structure to a sector's ffloors list. * * \param sec Target sector. - * \param ffloor Newly formed 3Dfloor structure. + * \param fflr Newly formed 3Dfloor structure. * \sa P_AddFakeFloor */ -static inline void P_AddFFloorToList(sector_t *sec, ffloor_t *ffloor) +static inline void P_AddFFloorToList(sector_t *sec, ffloor_t *fflr) { ffloor_t *rover; if (!sec->ffloors) { - sec->ffloors = ffloor; - ffloor->next = 0; - ffloor->prev = 0; + sec->ffloors = fflr; + fflr->next = 0; + fflr->prev = 0; return; } for (rover = sec->ffloors; rover->next; rover = rover->next); - rover->next = ffloor; - ffloor->prev = rover; - ffloor->next = 0; + rover->next = fflr; + fflr->prev = rover; + fflr->next = 0; } /** Adds a 3Dfloor. @@ -5655,7 +5655,7 @@ static inline void P_AddFFloorToList(sector_t *sec, ffloor_t *ffloor) */ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, ffloortype_e flags, thinkerlist_t *secthinkers) { - ffloor_t *ffloor; + ffloor_t *fflr; thinker_t *th; friction_t *f; pusher_t *p; @@ -5665,8 +5665,8 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f if (sec == sec2) return NULL; //Don't need a fake floor on a control sector. - if ((ffloor = (P_GetFFloorBySec(sec, sec2)))) - return ffloor; // If this ffloor already exists, return it + if ((fflr = (P_GetFFloorBySec(sec, sec2)))) + return fflr; // If this ffloor already exists, return it if (sec2->ceilingheight < sec2->floorheight) { @@ -5705,27 +5705,27 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f } // Add the floor - ffloor = Z_Calloc(sizeof (*ffloor), PU_LEVEL, NULL); - ffloor->secnum = sec2 - sectors; - ffloor->target = sec; - ffloor->bottomheight = &sec2->floorheight; - ffloor->bottompic = &sec2->floorpic; - ffloor->bottomxoffs = &sec2->floor_xoffs; - ffloor->bottomyoffs = &sec2->floor_yoffs; - ffloor->bottomangle = &sec2->floorpic_angle; + fflr = Z_Calloc(sizeof (*fflr), PU_LEVEL, NULL); + fflr->secnum = sec2 - sectors; + fflr->target = sec; + fflr->bottomheight = &sec2->floorheight; + fflr->bottompic = &sec2->floorpic; + fflr->bottomxoffs = &sec2->floor_xoffs; + fflr->bottomyoffs = &sec2->floor_yoffs; + fflr->bottomangle = &sec2->floorpic_angle; // Add the ceiling - ffloor->topheight = &sec2->ceilingheight; - ffloor->toppic = &sec2->ceilingpic; - ffloor->toplightlevel = &sec2->lightlevel; - ffloor->topxoffs = &sec2->ceiling_xoffs; - ffloor->topyoffs = &sec2->ceiling_yoffs; - ffloor->topangle = &sec2->ceilingpic_angle; + fflr->topheight = &sec2->ceilingheight; + fflr->toppic = &sec2->ceilingpic; + fflr->toplightlevel = &sec2->lightlevel; + fflr->topxoffs = &sec2->ceiling_xoffs; + fflr->topyoffs = &sec2->ceiling_yoffs; + fflr->topangle = &sec2->ceilingpic_angle; #ifdef ESLOPE // Add slopes - ffloor->t_slope = &sec2->c_slope; - ffloor->b_slope = &sec2->f_slope; + fflr->t_slope = &sec2->c_slope; + fflr->b_slope = &sec2->f_slope; // mark the target sector as having slopes, if the FOF has any of its own // (this fixes FOF slopes glitching initially at level load in software mode) if (sec2->hasslope) @@ -5738,10 +5738,10 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f if ((flags & FF_SOLID) && (master->flags & ML_EFFECT2)) // Block all BUT player flags &= ~FF_BLOCKPLAYER; - ffloor->spawnflags = ffloor->flags = flags; - ffloor->master = master; - ffloor->norender = INFTICS; - ffloor->fadingdata = NULL; + fflr->spawnflags = fflr->flags = flags; + fflr->master = master; + fflr->norender = INFTICS; + fflr->fadingdata = NULL; // Scan the thinkers to check for special conditions applying to this FOF. // If we have thinkers sorted by sector, just check the relevant ones; @@ -5797,14 +5797,14 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f if (flags & FF_TRANSLUCENT) { if (sides[master->sidenum[0]].toptexture > 0) - ffloor->alpha = sides[master->sidenum[0]].toptexture; // for future reference, "#0" is 1, and "#255" is 256. Be warned + fflr->alpha = sides[master->sidenum[0]].toptexture; // for future reference, "#0" is 1, and "#255" is 256. Be warned else - ffloor->alpha = 0x80; + fflr->alpha = 0x80; } else - ffloor->alpha = 0xff; + fflr->alpha = 0xff; - ffloor->spawnalpha = ffloor->alpha; // save for netgames + fflr->spawnalpha = fflr->alpha; // save for netgames if (flags & FF_QUICKSAND) CheckForQuicksand = true; @@ -5828,9 +5828,9 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f CheckForFloatBob = true; } - P_AddFFloorToList(sec, ffloor); + P_AddFFloorToList(sec, fflr); - return ffloor; + return fflr; } // @@ -6141,7 +6141,7 @@ static inline void P_AddNoEnemiesThinker(sector_t *sec, line_t *sourceline) * \sa P_SpawnSpecials, T_EachTimeThinker * \author SSNTails */ -static inline void P_AddEachTimeThinker(sector_t *sec, line_t *sourceline) +static void P_AddEachTimeThinker(sector_t *sec, line_t *sourceline) { levelspecthink_t *eachtime; @@ -6193,30 +6193,30 @@ void T_LaserFlash(laserthink_t *flash) msecnode_t *node; mobj_t *thing; sector_t *sourcesec; - ffloor_t *ffloor = flash->ffloor; + ffloor_t *fflr = flash->ffloor; sector_t *sector = flash->sector; fixed_t top, bottom; - if (!ffloor || !(ffloor->flags & FF_EXISTS)) + if (!fflr || !(fflr->flags & FF_EXISTS)) return; if (leveltime & 2) - //ffloor->flags |= FF_RENDERALL; - ffloor->alpha = 0xB0; + //fflr->flags |= FF_RENDERALL; + fflr->alpha = 0xB0; else - //ffloor->flags &= ~FF_RENDERALL; - ffloor->alpha = 0x90; + //fflr->flags &= ~FF_RENDERALL; + fflr->alpha = 0x90; - sourcesec = ffloor->master->frontsector; // Less to type! + sourcesec = fflr->master->frontsector; // Less to type! #ifdef ESLOPE - top = (*ffloor->t_slope) ? P_GetZAt(*ffloor->t_slope, sector->soundorg.x, sector->soundorg.y) - : *ffloor->topheight; - bottom = (*ffloor->b_slope) ? P_GetZAt(*ffloor->b_slope, sector->soundorg.x, sector->soundorg.y) - : *ffloor->bottomheight; + top = (*fflr->t_slope) ? P_GetZAt(*fflr->t_slope, sector->soundorg.x, sector->soundorg.y) + : *fflr->topheight; + bottom = (*fflr->b_slope) ? P_GetZAt(*fflr->b_slope, sector->soundorg.x, sector->soundorg.y) + : *fflr->bottomheight; sector->soundorg.z = (top + bottom)/2; #else - sector->soundorg.z = (*ffloor->topheight + *ffloor->bottomheight)/2; + sector->soundorg.z = (*fflr->topheight + *fflr->bottomheight)/2; #endif S_StartSound(§or->soundorg, sfx_laser); @@ -6225,7 +6225,7 @@ void T_LaserFlash(laserthink_t *flash) { thing = node->m_thing; - if ((ffloor->master->flags & ML_EFFECT1) + if ((fflr->master->flags & ML_EFFECT1) && thing->flags & MF_BOSS) continue; // Don't hurt bosses @@ -6249,7 +6249,7 @@ void T_LaserFlash(laserthink_t *flash) /** Adds a laser thinker to a 3Dfloor. * - * \param ffloor 3Dfloor to turn into a laser block. + * \param fflr 3Dfloor to turn into a laser block. * \param sector Target sector. * \param secthkiners Lists of thinkers sorted by sector. May be NULL. * \sa T_LaserFlash @@ -6258,9 +6258,9 @@ void T_LaserFlash(laserthink_t *flash) static inline void EV_AddLaserThinker(sector_t *sec, sector_t *sec2, line_t *line, thinkerlist_t *secthinkers) { laserthink_t *flash; - ffloor_t *ffloor = P_AddFakeFloor(sec, sec2, line, laserflags, secthinkers); + ffloor_t *fflr = P_AddFakeFloor(sec, sec2, line, laserflags, secthinkers); - if (!ffloor) + if (!fflr) return; flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL); @@ -6268,7 +6268,7 @@ static inline void EV_AddLaserThinker(sector_t *sec, sector_t *sec2, line_t *lin P_AddThinker(THINK_MAIN, &flash->thinker); flash->thinker.function.acp1 = (actionf_p1)T_LaserFlash; - flash->ffloor = ffloor; + flash->ffloor = fflr; flash->sector = sec; // For finding mobjs flash->sec = sec2; flash->sourceline = line; @@ -8230,7 +8230,7 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor d->ffloornum = (UINT32)ffloornum; d->alpha = d->sourcevalue = rover->alpha; - d->destvalue = max(1, min(256, relative ? rover->alpha + destvalue : destvalue)); // ffloor->alpha is 1-256 + d->destvalue = max(1, min(256, relative ? rover->alpha + destvalue : destvalue)); // rover->alpha is 1-256 if (ticbased) { From f62087ef3067ef978febe94e4e630aeeb0224b5c Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 9 Jul 2019 21:43:38 +0100 Subject: [PATCH 065/128] Fix MascaraSnake's issues with sign-compare (hopefully) --- src/hardware/hw_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index d649eeb8e..c600800fd 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -580,7 +580,7 @@ static void HWR_RenderPlane(sector_t *sector, extrasubsector_t *xsub, boolean is if (nrPlaneVerts < 3) //not even a triangle ? return; - if (nrPlaneVerts > UINT16_MAX) // FIXME: exceeds plVerts size + if (nrPlaneVerts > (INT32)UINT16_MAX) // FIXME: exceeds plVerts size { CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, UINT16_MAX); return; @@ -3190,7 +3190,7 @@ static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, if (nrPlaneVerts < 3) //not even a triangle ? return; - if (nrPlaneVerts > UINT16_MAX) // FIXME: exceeds plVerts size + if (nrPlaneVerts > (size_t)UINT16_MAX) // FIXME: exceeds plVerts size { CONS_Debug(DBG_RENDER, "polygon size of %s exceeds max value of %d vertices\n", sizeu1(nrPlaneVerts), UINT16_MAX); return; From 35adf2ce4a83cc5b64034e9508e109838f6eb95a Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Tue, 9 Jul 2019 21:48:18 +0100 Subject: [PATCH 066/128] fix leftshift of negative value MascaraSnake also gets --- src/p_mobj.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 8077cff87..a57998ea0 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -4768,7 +4768,7 @@ static void P_Boss4Thinker(mobj_t *mobj) { INT32 oldmovecount = mobj->movecount; if (mobj->movedir == 3) // pinch start - movespeed = -210<<(FRACBITS>>1); + movespeed = -(210<<(FRACBITS>>1)); else if (mobj->movedir > 3) // pinch { movespeed = 420<<(FRACBITS>>1); From 166f1fac66ada844ec29d4cfe3aeaa2be702fe54 Mon Sep 17 00:00:00 2001 From: Jonas Sauer Date: Sat, 13 Jul 2019 01:42:03 +0200 Subject: [PATCH 067/128] Fixed the thinkerlist issues by removing THINK_LIMBO. Delay-removed thinkers now stay in their list. Also includes toaster's assorted fixes and improvements from target_painted_on_your_ass. --- src/d_clisrv.c | 8 +- src/d_netcmd.c | 3 +- src/f_finale.c | 3 + src/g_game.c | 13 +- src/hardware/hw_light.c | 3 +- src/lua_baselib.c | 2 +- src/lua_script.c | 30 ++-- src/m_cheat.c | 11 +- src/p_enemy.c | 52 ++++-- src/p_floor.c | 31 ++-- src/p_inter.c | 51 ++++-- src/p_local.h | 4 +- src/p_mobj.c | 124 ++++++++------ src/p_polyobj.c | 171 +++++++++++-------- src/p_saveg.c | 51 +++--- src/p_setup.c | 14 +- src/p_spec.c | 78 ++++++--- src/p_tick.c | 84 +++++---- src/p_tick.h | 2 +- src/p_user.c | 367 ++++++++++++++++++++++++---------------- src/r_data.c | 3 +- src/st_stuff.c | 30 ++-- 22 files changed, 697 insertions(+), 438 deletions(-) diff --git a/src/d_clisrv.c b/src/d_clisrv.c index bd9158468..74b3339fc 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -4270,13 +4270,11 @@ static INT16 Consistancy(void) ret += P_GetRandSeed(); #ifdef MOBJCONSISTANCY - if (!thlist[THINK_MOBJ].next) - { - DEBFILE(va("Consistancy = %u\n", ret)); - return ret; - } for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo = (mobj_t *)th; if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_MONITOR | MF_FIRE | MF_ENEMY | MF_PAIN | MF_STICKY)) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 5e070dcd7..e6f5244f0 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -4261,7 +4261,8 @@ static void Command_Archivetest_f(void) // assign mobjnum i = 1; for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - ((mobj_t *)th)->mobjnum = i++; + if (th->function.acp1 != (actionf_p1)P_RemoveThinkerDelayed) + ((mobj_t *)th)->mobjnum = i++; // allocate buffer buf = save_p = ZZ_Alloc(1024); diff --git a/src/f_finale.c b/src/f_finale.c index 1cae457a2..27c9ebd68 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1695,6 +1695,9 @@ void F_TitleScreenTicker(boolean run) { for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (!mo2) diff --git a/src/g_game.c b/src/g_game.c index f963cae35..95cc2288d 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2567,6 +2567,9 @@ void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo) // scan all thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (!(mo2->flags & MF_MISSILE)) @@ -4466,12 +4469,13 @@ void G_ConsGhostTic(void) mobj = NULL; for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; mobj = (mobj_t *)th; if (mobj->type == (mobjtype_t)type && mobj->x == x && mobj->y == y && mobj->z == z) break; - mobj = NULL; // wasn't this one, keep searching. } - if (mobj && mobj->health != health) // Wasn't damaged?! This is desync! Fix it! + if (th != &thlist[THINK_MOBJ] && mobj->health != health) // Wasn't damaged?! This is desync! Fix it! { if (demosynced) CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); @@ -5860,13 +5864,16 @@ void G_DoPlayMetal(void) // find metal sonic for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo = (mobj_t *)th; if (mo->type != MT_METALSONIC_RACE) continue; break; } - if (!mo) + if (th == &thlist[THINK_MOBJ]) { CONS_Alert(CONS_ERROR, M_GetText("Failed to find bot entity.\n")); Z_Free(metalbuffer); diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index b87fe65de..8a945fd9e 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -1367,7 +1367,8 @@ static void HWR_SearchLightsInMobjs(void) // search in the list of thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - HWR_AddMobjLights((mobj_t *)th); + if (th->function.acp1 != (actionf_p1)P_RemoveThinkerDelayed) + HWR_AddMobjLights((mobj_t *)th); } #endif diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 81a17ef20..1d69b238b 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -539,7 +539,7 @@ static int lib_pSpawnLockOn(lua_State *L) if (P_IsLocalPlayer(player)) // Only display it on your own view. { mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker - visual->target = lockon; + P_SetTarget(&visual->target, lockon); visual->flags2 |= MF2_DONTDRAW; P_SetMobjStateNF(visual, state); } diff --git a/src/lua_script.c b/src/lua_script.c index 85b9c4038..deb644dc0 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -1127,14 +1127,15 @@ void LUA_Archive(void) ArchiveExtVars(&players[i], "player"); } - for (i = 0; i < NUM_THINKERLISTS; i++) - for (th = thlist[i].next; th != &thlist[i]; th = th->next) - if (th->function.acp1 == (actionf_p1)P_MobjThinker) - { - // archive function will determine when to skip mobjs, - // and write mobjnum in otherwise. - ArchiveExtVars(th, "mobj"); - } + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + // archive function will determine when to skip mobjs, + // and write mobjnum in otherwise. + ArchiveExtVars(th, "mobj"); + } WRITEUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum. @@ -1163,11 +1164,14 @@ void LUA_UnArchive(void) do { mobjnum = READUINT32(save_p); // read a mobjnum - for (i = 0; i < NUM_THINKERLISTS; i++) - for (th = thlist[i].next; th != &thlist[i]; th = th->next) - if (th->function.acp1 == (actionf_p1)P_MobjThinker - && ((mobj_t *)th)->mobjnum == mobjnum) // find matching mobj - UnArchiveExtVars(th); // apply variables + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + if (((mobj_t *)th)->mobjnum != mobjnum) // find matching mobj + continue; + UnArchiveExtVars(th); // apply variables + } } while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker. LUAh_NetArchiveHook(NetUnArchive); // call the NetArchive hook in unarchive mode diff --git a/src/m_cheat.c b/src/m_cheat.c index 734a7ae18..29e8c8a02 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -579,6 +579,9 @@ void Command_Teleport_f(void) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_STARPOST) @@ -1068,10 +1071,14 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo = (mobj_t *)th; // get offset from mt, which points to old mapthings, then add new location - if (mo->spawnpoint) - mo->spawnpoint = (mo->spawnpoint - mt) + mapthings; + if (!mo->spawnpoint) + continue; + mo->spawnpoint = (mo->spawnpoint - mt) + mapthings; } } diff --git a/src/p_enemy.c b/src/p_enemy.c index f33ce6810..88405437c 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -1391,7 +1391,7 @@ void A_StatueBurst(mobj_t *actor) return; new->angle = actor->angle; - new->target = actor->target; + P_SetTarget(&new->target, actor->target); if (locvar2) P_SetMobjState(new, (statenum_t)locvar2); S_StartSound(new, new->info->attacksound); @@ -2155,7 +2155,7 @@ void A_CrushclawLaunch(mobj_t *actor) for (i = 0; (i < CSEGS); i++) { mobj_t *newchain = P_SpawnMobjFromMobj(actor, 0, 0, 0, actor->info->raisestate); - prevchain->target = newchain; + P_SetTarget(&prevchain->target, newchain); prevchain = newchain; } actor->target->angle = R_PointToAngle2(actor->target->x, actor->target->y, crab->target->x, crab->target->y); @@ -3088,7 +3088,7 @@ void A_Boss1Laser(mobj_t *actor) if (z - floorz < mobjinfo[MT_EGGMOBILE_FIRE].height>>1) { point = P_SpawnMobj(x, y, floorz+1, MT_EGGMOBILE_FIRE); - point->target = actor; + P_SetTarget(&point->target, actor); point->destscale = 3*FRACUNIT; point->scalespeed = FRACUNIT>>2; point->fuse = TICRATE; @@ -3488,9 +3488,11 @@ void A_1upThinker(mobj_t *actor) if (closestplayer == -1 || skins[players[closestplayer].skin].sprites[SPR2_LIFE].numframes == 0) { // Closest player not found (no players in game?? may be empty dedicated server!), or does not have correct sprite. - if (actor->tracer) { - P_RemoveMobj(actor->tracer); - actor->tracer = NULL; + if (actor->tracer) + { + mobj_t *tracer = actor->tracer; + P_SetTarget(&actor->tracer, NULL); + P_RemoveMobj(tracer); } return; } @@ -3786,6 +3788,9 @@ void A_BossDeath(mobj_t *mo) // if all bosses are dead for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2 != mo && (mo2->flags & MF_BOSS) && mo2->health > 0) goto bossjustdie; // other boss not dead - just go straight to dying! @@ -3884,6 +3889,9 @@ bossjustdie: // scan the thinkers to find the runaway point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_BOSSFLYPOINT) @@ -6137,6 +6145,9 @@ void A_RingExplode(mobj_t *actor) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2 == actor) // Don't explode yourself! Endless loop! @@ -7263,7 +7274,7 @@ void A_Boss2PogoTarget(mobj_t *actor) if (actor->info->missilestate) // spawn the pogo stick collision box { mobj_t *pogo = P_SpawnMobj(actor->x, actor->y, actor->z - mobjinfo[actor->info->missilestate].height, (mobjtype_t)actor->info->missilestate); - pogo->target = actor; + P_SetTarget(&pogo->target, actor); } actor->reactiontime = 1; @@ -7835,6 +7846,9 @@ void A_Boss3Path(mobj_t *actor) // the number for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_BOSS3WAYPOINT) continue; @@ -8227,6 +8241,9 @@ void A_FindTarget(mobj_t *actor) // scan the thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type == (mobjtype_t)locvar1) @@ -8289,6 +8306,9 @@ void A_FindTracer(mobj_t *actor) // scan the thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type == (mobjtype_t)locvar1) @@ -8873,6 +8893,9 @@ void A_RemoteAction(mobj_t *actor) // scan the thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type == (mobjtype_t)locvar1) @@ -9136,6 +9159,9 @@ void A_SetObjectTypeState(mobj_t *actor) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type == (mobjtype_t)loc2lw) @@ -9771,6 +9797,9 @@ void A_CheckThingCount(mobj_t *actor) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type == (mobjtype_t)loc1up) @@ -13061,9 +13090,10 @@ static boolean PIT_TNTExplode(mobj_t *nearby) if (barrel->target == nearby) { mobj_t *tar = barrel->target; // temporarily store barrel's target - barrel->target = NULL; + P_SetTarget(&barrel->target, NULL); P_DamageMobj(nearby, barrel, NULL, 1, 0); - barrel->target = tar; + if (!P_MobjWasRemoved(barrel)) + P_SetTarget(&barrel->target, tar); } else { @@ -13565,7 +13595,7 @@ void A_SaloonDoorSpawn(mobj_t *actor) door->extravalue2 = 0; // Origin door - door->tracer = actor; + P_SetTarget(&door->tracer, actor); //Back door = P_SpawnMobj(x - c*d, y - s*d, z, MT_SALOONDOOR); @@ -13578,7 +13608,7 @@ void A_SaloonDoorSpawn(mobj_t *actor) door->extravalue2 = 0; // Origin door - door->tracer = actor; + P_SetTarget(&door->tracer, actor); } // Function: A_MinecartSparkThink diff --git a/src/p_floor.c b/src/p_floor.c index ed2afd13d..c01e568d0 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1975,22 +1975,27 @@ void T_ThwompSector(levelspecthink_t *thwomp) } else // Not going anywhere, so look for players. { - thinker_t *th; - mobj_t *mo; - if (!rover || (rover->flags & FF_EXISTS)) { - // scan the thinkers to find players! - for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + UINT8 i; + // scan the players to find victims! + for (i = 0; i < MAXPLAYERS; i++) { - mo = (mobj_t *)th; - if (mo->type == MT_PLAYER && mo->health && mo->player && !mo->player->spectator - && mo->z <= thwomp->sector->ceilingheight - && P_AproxDistance(thwompx - mo->x, thwompy - mo->y) <= 96*FRACUNIT) - { - thwomp->direction = -1; - break; - } + if (!playeringame[i]) + continue; + if (players[i].spectator) + continue; + if (!players[i].mo) + continue; + if (!players[i].mo->health) + continue; + if (players[i].mo->z > thwomp->sector->ceilingheight) + continue; + if (P_AproxDistance(thwompx - players[i].mo->x, thwompy - players[i].mo->y) > 96 * FRACUNIT) + continue; + + thwomp->direction = -1; + break; } } diff --git a/src/p_inter.c b/src/p_inter.c index bdf88ff44..abf33429f 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -99,6 +99,9 @@ void P_ClearStarPost(INT32 postnum) // scan the thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_STARPOST) @@ -125,10 +128,15 @@ void P_ResetStarposts(void) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + post = (mobj_t *)th; - if (post->type == MT_STARPOST) - P_SetMobjState(post, post->info->spawnstate); + if (post->type != MT_STARPOST) + continue; + + P_SetMobjState(post, post->info->spawnstate); } } @@ -828,19 +836,22 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // scan the thinkers to find the corresponding anchorpoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; - if (mo2->type == MT_IDEYAANCHOR) - { - if (mo2->health == toucher->tracer->health) // do ideya numberes match? - anchorpoint = mo2; - else if (toucher->tracer->hnext && mo2->health == toucher->tracer->hnext->health) - anchorpoint2 = mo2; + if (mo2->type != MT_IDEYAANCHOR) + continue; - if ((!toucher->tracer->hnext && anchorpoint) - || (toucher->tracer->hnext && anchorpoint && anchorpoint2)) - break; - } + if (mo2->health == toucher->tracer->health) // do ideya numberes match? + anchorpoint = mo2; + else if (toucher->tracer->hnext && mo2->health == toucher->tracer->hnext->health) + anchorpoint2 = mo2; + + if ((!toucher->tracer->hnext && anchorpoint) + || (toucher->tracer->hnext && anchorpoint && anchorpoint2)) + break; } if (anchorpoint) @@ -919,6 +930,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // scan the remaining thinkers for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2 == special) @@ -966,6 +980,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // in from the paraloop. Isn't this just so efficient? for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (P_AproxDistance(P_AproxDistance(mo2->x - x, mo2->y - y), mo2->z - z) > gatherradius) @@ -1337,6 +1354,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // scan the remaining thinkers to find koopa for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_KOOPA) @@ -1434,6 +1454,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_STARPOST) @@ -2572,9 +2595,11 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget UINT32 i = 0; // to check how many clones we've removed // scan the thinkers to make sure all the old pinch dummies are gone on death - // this can happen if the boss was hurt earlier than expected for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo = (mobj_t *)th; if (mo->type != (mobjtype_t)target->info->mass) continue; diff --git a/src/p_local.h b/src/p_local.h index 5216286c0..cb8f95533 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -61,8 +61,8 @@ #define P_GetPlayerHeight(player) FixedMul(player->height, player->mo->scale) #define P_GetPlayerSpinHeight(player) FixedMul(player->spinheight, player->mo->scale) -typedef enum{ - THINK_LIMBO, +typedef enum +{ THINK_POLYOBJ, THINK_MAIN, THINK_MOBJ, diff --git a/src/p_mobj.c b/src/p_mobj.c index a57998ea0..9a6e0f2bb 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -716,6 +716,9 @@ void P_EmeraldManager(void) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { + if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo = (mobj_t *)think; if (mo->type == MT_EMERALDSPAWN) @@ -3694,6 +3697,9 @@ void P_DestroyRobots(void) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { + if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo = (mobj_t *)think; if (mo->health <= 0 || !(mo->flags & (MF_ENEMY|MF_BOSS))) continue; // not a valid enemy @@ -4426,6 +4432,9 @@ static void P_Boss3Thinker(mobj_t *mobj) // this can happen if the boss was hurt earlier than expected for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != (mobjtype_t)mobj->info->mass) continue; @@ -4524,6 +4533,9 @@ static void P_Boss3Thinker(mobj_t *mobj) // the number for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_BOSS3WAYPOINT) continue; @@ -4832,8 +4844,8 @@ static void P_Boss4Thinker(mobj_t *mobj) P_SetTarget(&seg->target, mobj); for (i = 0; i < 9; i++) { - seg->hnext = P_SpawnMobj(mobj->x, mobj->y, z, MT_EGGMOBILE4_MACE); - seg->hnext->hprev = seg; + P_SetTarget(&seg->hnext, P_SpawnMobj(mobj->x, mobj->y, z, MT_EGGMOBILE4_MACE)); + P_SetTarget(&seg->hnext->hprev, seg); seg = seg->hnext; } } @@ -5245,6 +5257,9 @@ static void P_Boss7Thinker(mobj_t *mobj) // Find waypoint he is closest to for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint) { @@ -5297,6 +5312,9 @@ static void P_Boss7Thinker(mobj_t *mobj) // the waypoint to use for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && (mo2->spawnpoint->options & 7) == waypointNum) { @@ -5427,14 +5445,17 @@ static void P_Boss9Thinker(mobj_t *mobj) // Build a hoop linked list of 'em! for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type == MT_BOSS9GATHERPOINT) { if (last) - last->hnext = mo2; + P_SetTarget(&last->hnext, mo2); else - mobj->hnext = mo2; - mo2->hprev = last; + P_SetTarget(&mobj->hnext, mo2); + P_SetTarget(&mo2->hprev, last); last = mo2; } } @@ -6072,6 +6093,9 @@ mobj_t *P_GetClosestAxis(mobj_t *source) // scan the thinkers to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type == MT_AXIS) @@ -6841,12 +6865,14 @@ static void P_RemoveOverlay(mobj_t *thing) { mobj_t *mo; for (mo = overlaycap; mo; mo = mo->hnext) - if (mo->hnext == thing) - { - P_SetTarget(&mo->hnext, thing->hnext); - P_SetTarget(&thing->hnext, NULL); - return; - } + { + if (mo->hnext != thing) + continue; + + P_SetTarget(&mo->hnext, thing->hnext); + P_SetTarget(&thing->hnext, NULL); + return; + } } void A_BossDeath(mobj_t *mo); @@ -9751,7 +9777,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->momx = 1; //stack hack break; case MT_MINECARTEND: - mobj->tracer = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_MINECARTENDSOLID); + P_SetTarget(&mobj->tracer, P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_MINECARTENDSOLID)); mobj->tracer->angle = mobj->angle + ANGLE_90; break; default: @@ -9960,37 +9986,28 @@ void P_RemoveMobj(mobj_t *mobj) P_SetTarget(&mobj->hnext, P_SetTarget(&mobj->hprev, NULL)); - // free block // DBG: set everything in mobj_t to 0xFF instead of leaving it. debug memory error. - if (mobj->flags & MF_NOTHINK && !mobj->thinker.next) +#ifdef SCRAMBLE_REMOVED + // Invalidate mobj_t data to cause crashes if accessed! + memset((UINT8 *)mobj + sizeof(thinker_t), 0xff, sizeof(mobj_t) - sizeof(thinker_t)); +#endif + + // free block + if (!mobj->thinker.next) { // Uh-oh, the mobj doesn't think, P_RemoveThinker would never go through! + INT32 prevreferences; if (!mobj->thinker.references) { -#ifdef SCRAMBLE_REMOVED - // Invalidate mobj_t data to cause crashes if accessed! - memset(mobj, 0xff, sizeof(mobj_t)); -#endif - Z_Free(mobj); // No refrences? Can be removed immediately! :D - } - else - { // Add thinker just to delay removing it until refrences are gone. - mobj->flags &= ~MF_NOTHINK; - P_AddThinker(THINK_MOBJ, (thinker_t *)mobj); -#ifdef SCRAMBLE_REMOVED - // Invalidate mobj_t data to cause crashes if accessed! - memset((UINT8 *)mobj + sizeof(thinker_t), 0xff, sizeof(mobj_t) - sizeof(thinker_t)); -#endif - P_RemoveThinker((thinker_t *)mobj); + Z_Free(mobj); // No refrrences? Can be removed immediately! :D + return; } + + prevreferences = mobj->thinker.references; + P_AddThinker(THINK_MOBJ, (thinker_t *)mobj); + mobj->thinker.references = prevreferences; } - else - { -#ifdef SCRAMBLE_REMOVED - // Invalidate mobj_t data to cause crashes if accessed! - memset((UINT8 *)mobj + sizeof(thinker_t), 0xff, sizeof(mobj_t) - sizeof(thinker_t)); -#endif - P_RemoveThinker((thinker_t *)mobj); - } + + P_RemoveThinker((thinker_t *)mobj); } // This does not need to be added to Lua. @@ -11821,6 +11838,9 @@ ML_EFFECT5 : Don't stop thinking when too far away // See if other starposts exist in this level that have the same value. for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2 == mobj) @@ -12124,11 +12144,11 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) // Link all the sprites in the hoop together if (nextmobj) { - mobj->hprev = nextmobj; - mobj->hprev->hnext = mobj; + P_SetTarget(&mobj->hprev, nextmobj); + P_SetTarget(&mobj->hprev->hnext, mobj); } else - mobj->hprev = mobj->hnext = NULL; + P_SetTarget(&mobj->hprev, P_SetTarget(&mobj->hnext, NULL)); nextmobj = mobj; } @@ -12154,9 +12174,9 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) mobj->z -= mobj->height/2; // Link all the collision sprites together. - mobj->hnext = NULL; - mobj->hprev = nextmobj; - mobj->hprev->hnext = mobj; + P_SetTarget(&mobj->hnext, NULL); + P_SetTarget(&mobj->hprev, nextmobj); + P_SetTarget(&mobj->hprev->hnext, mobj); nextmobj = mobj; } @@ -12181,9 +12201,9 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) mobj->z -= mobj->height/2; // Link all the collision sprites together. - mobj->hnext = NULL; - mobj->hprev = nextmobj; - mobj->hprev->hnext = mobj; + P_SetTarget(&mobj->hnext, NULL); + P_SetTarget(&mobj->hprev, nextmobj); + P_SetTarget(&mobj->hprev->hnext, mobj); nextmobj = mobj; } @@ -12266,11 +12286,11 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) // Link all the sprites in the hoop together if (nextmobj) { - mobj->hprev = nextmobj; - mobj->hprev->hnext = mobj; + P_SetTarget(&mobj->hprev, nextmobj); + P_SetTarget(&mobj->hprev->hnext, mobj); } else - mobj->hprev = mobj->hnext = NULL; + P_SetTarget(&mobj->hprev, P_SetTarget(&mobj->hnext, NULL)); nextmobj = mobj; } @@ -12307,9 +12327,9 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) mobj->z -= mobj->height/2; // Link all the collision sprites together. - mobj->hnext = NULL; - mobj->hprev = nextmobj; - mobj->hprev->hnext = mobj; + P_SetTarget(&mobj->hnext, NULL); + P_SetTarget(&mobj->hprev, nextmobj); + P_SetTarget(&mobj->hprev->hnext, mobj); nextmobj = mobj; } diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 09d449b39..3de7c4390 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1510,6 +1510,9 @@ void Polyobj_InitLevel(void) // the mobj_t pointers on a queue for use below. for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mobj_t *mo = (mobj_t *)th; if (mo->info->doomednum == POLYOBJ_SPAWN_DOOMEDNUM || @@ -1815,6 +1818,9 @@ void T_PolyObjWaypoint(polywaypoint_t *th) // We redo this each tic to make savegame compatibility easier. for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { + if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)wp; if (mo2->type != MT_TUBEWAYPOINT) @@ -1893,28 +1899,31 @@ void T_PolyObjWaypoint(polywaypoint_t *th) // Find next waypoint for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { + if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)wp; if (mo2->type != MT_TUBEWAYPOINT) continue; - if (mo2->threshold == th->sequence) + if (mo2->threshold != th->sequence) + continue; + + if (th->direction == -1) { - if (th->direction == -1) + if (mo2->health == target->health - 1) { - if (mo2->health == target->health - 1) - { - waypoint = mo2; - break; - } + waypoint = mo2; + break; } - else + } + else + { + if (mo2->health == target->health + 1) { - if (mo2->health == target->health + 1) - { - waypoint = mo2; - break; - } + waypoint = mo2; + break; } } } @@ -1929,27 +1938,30 @@ void T_PolyObjWaypoint(polywaypoint_t *th) for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { + if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)wp; if (mo2->type != MT_TUBEWAYPOINT) continue; - if (mo2->threshold == th->sequence) + if (mo2->threshold != th->sequence) + continue; + + if (th->direction == -1) { - if (th->direction == -1) + if (waypoint == NULL) + waypoint = mo2; + else if (mo2->health > waypoint->health) + waypoint = mo2; + } + else + { + if (mo2->health == 0) { - if (waypoint == NULL) - waypoint = mo2; - else if (mo2->health > waypoint->health) - waypoint = mo2; - } - else - { - if (mo2->health == 0) - { - waypoint = mo2; - break; - } + waypoint = mo2; + break; } } } @@ -1963,28 +1975,31 @@ void T_PolyObjWaypoint(polywaypoint_t *th) for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { + if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)wp; if (mo2->type != MT_TUBEWAYPOINT) continue; - if (mo2->threshold == th->sequence) + if (mo2->threshold != th->sequence) + continue; + + if (th->direction == -1) { - if (th->direction == -1) + if (mo2->health == target->health - 1) { - if (mo2->health == target->health - 1) - { - waypoint = mo2; - break; - } + waypoint = mo2; + break; } - else + } + else + { + if (mo2->health == target->health + 1) { - if (mo2->health == target->health + 1) - { - waypoint = mo2; - break; - } + waypoint = mo2; + break; } } } @@ -2511,36 +2526,39 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) // Find the first waypoint we need to use for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { + if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)wp; if (mo2->type != MT_TUBEWAYPOINT) continue; - if (mo2->threshold == th->sequence) + if (mo2->threshold != th->sequence) + continue; + + if (th->direction == -1) // highest waypoint # { - if (th->direction == -1) // highest waypoint # + if (mo2->health == 0) + last = mo2; + else { - if (mo2->health == 0) - last = mo2; - else - { - if (first == NULL) - first = mo2; - else if (mo2->health > first->health) - first = mo2; - } - } - else // waypoint 0 - { - if (mo2->health == 0) + if (first == NULL) first = mo2; - else - { - if (last == NULL) - last = mo2; - else if (mo2->health > last->health) - last = mo2; - } + else if (mo2->health > first->health) + first = mo2; + } + } + else // waypoint 0 + { + if (mo2->health == 0) + first = mo2; + else + { + if (last == NULL) + last = mo2; + else if (mo2->health > last->health) + last = mo2; } } } @@ -2579,28 +2597,31 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) target = first; /*for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next) { + if (wp->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)wp; if (mo2->type != MT_TUBEWAYPOINT) continue; - if (mo2->threshold == th->sequence) + if (mo2->threshold != th->sequence) + continue; + + if (th->direction == -1) // highest waypoint # { - if (th->direction == -1) // highest waypoint # + if (mo2->health == first->health - 1) { - if (mo2->health == first->health - 1) - { - target = mo2; - break; - } + target = mo2; + break; } - else // waypoint 0 + } + else // waypoint 0 + { + if (mo2->health == first->health + 1) { - if (mo2->health == first->health + 1) - { - target = mo2; - break; - } + target = mo2; + break; } } }*/ diff --git a/src/p_saveg.c b/src/p_saveg.c index 06baa9528..2e4ba9228 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2174,7 +2174,6 @@ static void P_NetArchiveThinkers(void) for (i = 0; i < NUM_THINKERLISTS; i++) { UINT32 numsaved = 0; - // save off the current thinkers for (th = thlist[i].next; th != &thlist[i]; th = th->next) { @@ -2405,12 +2404,12 @@ static void P_NetArchiveThinkers(void) } #endif // ESLOPE #ifdef PARANOIA - else if (th->function.acv != P_RemoveThinkerDelayed) // wait garbage collection + else if (th->function.acp1 != P_RemoveThinkerDelayed) // wait garbage collection I_Error("unknown thinker type %p", th->function.acp1); #endif } - CONS_Debug(DBG_NETPLAY, "%u thinkers saved\n", numsaved); + CONS_Debug(DBG_NETPLAY, "%u thinkers saved in list %d\n", numsaved, i); WRITEUINT8(save_p, tc_end); } @@ -2427,9 +2426,14 @@ mobj_t *P_FindNewPosition(UINT32 oldposition) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mobj = (mobj_t *)th; - if (mobj->mobjnum == oldposition) - return mobj; + if (mobj->mobjnum != oldposition) + continue; + + return mobj; } CONS_Debug(DBG_GAMELOGIC, "mobj not found\n"); return NULL; @@ -3597,22 +3601,22 @@ static void P_NetUnArchiveThinkers(void) P_AddThinker(i, th); } - CONS_Debug(DBG_NETPLAY, "%u thinkers loaded\n", numloaded); + CONS_Debug(DBG_NETPLAY, "%u thinkers loaded in list %d\n", numloaded, i); + } - if (restoreNum) + if (restoreNum) + { + executor_t *delay = NULL; + UINT32 mobjnum; + for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; + currentthinker = currentthinker->next) { - executor_t *delay = NULL; - UINT32 mobjnum; - for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; - currentthinker = currentthinker->next) - { - if (currentthinker->function.acp1 == (actionf_p1)T_ExecutorDelay) - { - delay = (void *)currentthinker; - if ((mobjnum = (UINT32)(size_t)delay->caller)) - delay->caller = P_FindNewPosition(mobjnum); - } - } + if (currentthinker->function.acp1 != (actionf_p1)T_ExecutorDelay) + continue; + delay = (void *)currentthinker; + if (!(mobjnum = (UINT32)(size_t)delay->caller)) + continue; + delay->caller = P_FindNewPosition(mobjnum); } } } @@ -3723,6 +3727,9 @@ static inline void P_FinishMobjs(void) for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ]; currentthinker = currentthinker->next) { + if (currentthinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mobj = (mobj_t *)currentthinker; mobj->info = &mobjinfo[mobj->type]; } @@ -3738,6 +3745,9 @@ static void P_RelinkPointers(void) for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ]; currentthinker = currentthinker->next) { + if (currentthinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mobj = (mobj_t *)currentthinker; if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER) @@ -4115,6 +4125,9 @@ void P_SaveNetGame(void) // Assign the mobjnumber for pointer tracking for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mobj = (mobj_t *)th; if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER) continue; diff --git a/src/p_setup.c b/src/p_setup.c index 7aaad233d..e112e7cd7 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -817,6 +817,9 @@ void P_ReloadRings(void) // scan the thinkers to find rings/spheres/hoops to unset for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo = (mobj_t *)th; if (mo->type == MT_HOOPCENTER) @@ -883,6 +886,9 @@ void P_SwitchSpheresBonusMode(boolean bonustime) // scan the thinkers to find spheres to switch for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo = (mobj_t *)th; if (mo->type != MT_BLUESPHERE && mo->type != MT_NIGHTSCHIP @@ -2284,7 +2290,6 @@ static void P_LevelInitStuff(void) void P_LoadThingsOnly(void) { // Search through all the thinkers. - mobj_t *mo; thinker_t *think; INT32 i, viewid = -1, centerid = -1; // for skyboxes @@ -2301,10 +2306,9 @@ void P_LoadThingsOnly(void) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - mo = (mobj_t *)think; - - if (mo) - P_RemoveMobj(mo); + if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + P_RemoveMobj((mobj_t *)think); } P_LevelInitStuff(); diff --git a/src/p_spec.c b/src/p_spec.c index 4a7ec59e9..3cd0461e2 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2260,7 +2260,7 @@ void P_SwitchWeather(INT32 weathernum) thinker_t *think; precipmobj_t *precipmobj; - for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) + for (think = thlist[THINK_PRECIP].next; think != &thlist[THINK_PRECIP]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker) continue; // not a precipmobj thinker @@ -2276,7 +2276,7 @@ void P_SwitchWeather(INT32 weathernum) precipmobj_t *precipmobj; state_t *st; - for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) + for (think = thlist[THINK_PRECIP].next; think != &thlist[THINK_PRECIP]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker) continue; // not a precipmobj thinker @@ -3992,6 +3992,9 @@ void P_SetupSignExit(player_t *player) // spin all signposts in the level then. for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { + if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + thing = (mobj_t *)think; if (thing->type != MT_SIGN) continue; @@ -4017,20 +4020,18 @@ boolean P_IsFlagAtBase(mobjtype_t flag) { thinker_t *think; mobj_t *mo; - INT32 specialnum = 0; + INT32 specialnum = (flag == MT_REDFLAG) ? 3 : 4; for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { + if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo = (mobj_t *)think; if (mo->type != flag) continue; - if (mo->type == MT_REDFLAG) - specialnum = 3; - else if (mo->type == MT_BLUEFLAG) - specialnum = 4; - if (GETSECSPECIAL(mo->subsector->sector->special, 4) == specialnum) return true; else if (mo->subsector->sector->ffloors) // Check the 3D floors @@ -4045,9 +4046,11 @@ boolean P_IsFlagAtBase(mobjtype_t flag) if (GETSECSPECIAL(rover->master->frontsector->special, 4) != specialnum) continue; - if (mo->z <= P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector) - && mo->z >= P_GetSpecialBottomZ(mo, sectors + rover->secnum, mo->subsector->sector)) - return true; + if (!(mo->z <= P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector) + && mo->z >= P_GetSpecialBottomZ(mo, sectors + rover->secnum, mo->subsector->sector))) + continue; + + return true; } } } @@ -4451,9 +4454,12 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers // The chimps are my friends.. heeheeheheehehee..... - LouisJM for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; mo2 = (mobj_t *)th; - if (mo2->type == MT_EGGTRAP) - P_KillMobj(mo2, NULL, player->mo, 0); + if (mo2->type != MT_EGGTRAP) + continue; + P_KillMobj(mo2, NULL, player->mo, 0); } // clear the special so you can't push the button twice. @@ -4754,14 +4760,20 @@ DoneSection2: // to find the first waypoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; - if (mo2->type == MT_TUBEWAYPOINT && mo2->threshold == sequence - && mo2->health == 0) - { - waypoint = mo2; - break; - } + if (mo2->type != MT_TUBEWAYPOINT) + continue; + if (mo2->threshold != sequence) + continue; + if (mo2->health != 0) + continue; + + waypoint = mo2; + break; } if (!waypoint) @@ -4830,15 +4842,20 @@ DoneSection2: // to find the last waypoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; - if (mo2->type == MT_TUBEWAYPOINT && mo2->threshold == sequence) - { - if (!waypoint) - waypoint = mo2; - else if (mo2->health > waypoint->health) - waypoint = mo2; - } + if (mo2->type != MT_TUBEWAYPOINT) + continue; + if (mo2->threshold != sequence) + continue; + + if (!waypoint) + waypoint = mo2; + else if (mo2->health > waypoint->health) + waypoint = mo2; } if (!waypoint) @@ -4979,6 +4996,9 @@ DoneSection2: // to find the first waypoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_TUBEWAYPOINT) @@ -5014,6 +5034,9 @@ DoneSection2: // Find waypoint before this one (waypointlow) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_TUBEWAYPOINT) @@ -5038,6 +5061,9 @@ DoneSection2: // Find waypoint after this one (waypointhigh) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_TUBEWAYPOINT) diff --git a/src/p_tick.c b/src/p_tick.c index 56f91d820..1d248d2ae 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -44,6 +44,9 @@ void Command_Numthinkers_f(void) INT32 count = 0; actionf_p1 action; thinker_t *think; + thinklistnum_t start = 0; + thinklistnum_t end = NUM_THINKERLISTS - 1; + thinklistnum_t i; if (gamestate != GS_LEVEL) { @@ -70,6 +73,7 @@ void Command_Numthinkers_f(void) switch (num) { case 1: + start = end = THINK_MOBJ; action = (actionf_p1)P_MobjThinker; CONS_Printf(M_GetText("Number of %s: "), "P_MobjThinker"); break; @@ -82,14 +86,17 @@ void Command_Numthinkers_f(void) CONS_Printf(M_GetText("Number of %s: "), "P_SnowThinker"); break;*/ case 2: + start = end = THINK_PRECIP; action = (actionf_p1)P_NullPrecipThinker; CONS_Printf(M_GetText("Number of %s: "), "P_NullPrecipThinker"); break; case 3: + start = end = THINK_MAIN; action = (actionf_p1)T_Friction; CONS_Printf(M_GetText("Number of %s: "), "T_Friction"); break; case 4: + start = end = THINK_MAIN; action = (actionf_p1)T_Pusher; CONS_Printf(M_GetText("Number of %s: "), "T_Pusher"); break; @@ -102,12 +109,15 @@ void Command_Numthinkers_f(void) return; } - for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) + for (i = start; i <= end; i++) { - if (think->function.acp1 != action) - continue; + for (think = thlist[i].next; think != &thlist[i]; think = think->next) + { + if (think->function.acp1 != action) + continue; - count++; + count++; + } } CONS_Printf("%d\n", count); @@ -141,6 +151,9 @@ void Command_CountMobjs_f(void) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + if (((mobj_t *)th)->type == i) count++; } @@ -158,6 +171,9 @@ void Command_CountMobjs_f(void) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + if (((mobj_t *)th)->type == i) count++; } @@ -180,6 +196,10 @@ void P_InitThinkers(void) // Adds a new thinker at the end of the list. void P_AddThinker(const thinklistnum_t n, thinker_t *thinker) { +#ifdef PARANOIA + I_Assert(n >= 0 && n < NUM_THINKERLISTS); +#endif + thlist[n].prev->next = thinker; thinker->next = &thlist[n]; thinker->prev = thlist[n].prev; @@ -206,22 +226,27 @@ static thinker_t *currentthinker; // remove it, and set currentthinker to one node preceeding it, so // that the next step in P_RunThinkers() will get its successor. // -void P_RemoveThinkerDelayed(void *pthinker) +void P_RemoveThinkerDelayed(thinker_t *thinker) { - thinker_t *thinker = pthinker; - if (!thinker->references) - { - { - /* Remove from main thinker list */ - thinker_t *next = thinker->next; - /* Note that currentthinker is guaranteed to point to us, - * and since we're freeing our memory, we had better change that. So - * point it to thinker->prev, so the iterator will correctly move on to - * thinker->prev->next = thinker->next */ - (next->prev = currentthinker = thinker->prev)->next = next; - } - Z_Free(thinker); - } + thinker_t *next; +#ifdef PARANOIA + if (thinker->next) + thinker->next = NULL; + else if (thinker->references) // Usually gets cleared up in one frame; what's going on here, then? + CONS_Printf("Number of potentially faulty references: %d\n", thinker->references); +#endif + if (thinker->references) + return; + + /* Remove from main thinker list */ + next = thinker->next; + /* Note that currentthinker is guaranteed to point to us, + * and since we're freeing our memory, we had better change that. So + * point it to thinker->prev, so the iterator will correctly move on to + * thinker->prev->next = thinker->next */ + (next->prev = currentthinker = thinker->prev)->next = next; + + Z_Free(thinker); } // @@ -238,23 +263,10 @@ void P_RemoveThinkerDelayed(void *pthinker) // void P_RemoveThinker(thinker_t *thinker) { - thinker_t *next = thinker->next; #ifdef HAVE_BLUA LUA_InvalidateUserdata(thinker); #endif - thinker->function.acp1 = P_RemoveThinkerDelayed; - - if (currentthinker == thinker) - currentthinker = thinker->prev; - - // Remove thinker from its current list. - (next->prev = thinker->prev)->next = next; - - // Now add it to the limbo list - thlist[THINK_LIMBO].prev->next = thinker; - thinker->next = &thlist[THINK_LIMBO]; - thinker->prev = thlist[THINK_LIMBO].prev; - thlist[THINK_LIMBO].prev = thinker; + thinker->function.acp1 = (actionf_p1)P_RemoveThinkerDelayed; } /* @@ -307,8 +319,10 @@ static inline void P_RunThinkers(void) { for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = currentthinker->next) { - if (currentthinker->function.acp1) - currentthinker->function.acp1(currentthinker); +#ifdef PARANOIA + I_Assert(currentthinker->function.acp1 != NULL) +#endif + currentthinker->function.acp1(currentthinker); } } diff --git a/src/p_tick.h b/src/p_tick.h index 169c54c8e..8551ccc76 100644 --- a/src/p_tick.h +++ b/src/p_tick.h @@ -27,7 +27,7 @@ void Command_CountMobjs_f(void); void P_Ticker(boolean run); void P_PreTicker(INT32 frames); void P_DoTeamscrambling(void); -void P_RemoveThinkerDelayed(void *pthinker); //killed +void P_RemoveThinkerDelayed(thinker_t *thinker); //killed mobj_t *P_SetTarget(mobj_t **mo, mobj_t *target); // killough 11/98 #endif diff --git a/src/p_user.c b/src/p_user.c index 79a726fe6..4c35a3257 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -345,9 +345,16 @@ UINT8 P_FindLowestMare(void) // to find the egg capsule with the lowest mare for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; - if (mo2->type == MT_EGGCAPSULE && mo2->health > 0) + if (mo2->type != MT_EGGCAPSULE) + continue; + if (mo2->health <= 0) + continue; + { const UINT8 threshold = (UINT8)mo2->threshold; if (mare == 255) @@ -391,29 +398,32 @@ boolean P_TransferToNextMare(player_t *player) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; - if (mo2->type == MT_AXIS) - { - if (mo2->threshold == mare) - { - if (closestaxis == NULL) - { - closestaxis = mo2; - lowestaxisnum = mo2->health; - dist2 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y)-mo2->radius; - } - else if (mo2->health < lowestaxisnum) - { - dist1 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y)-mo2->radius; + if (mo2->type != MT_AXIS) + continue; - if (dist1 < dist2) - { - closestaxis = mo2; - lowestaxisnum = mo2->health; - dist2 = dist1; - } - } + if (mo2->threshold != mare) + continue; + + if (closestaxis == NULL) + { + closestaxis = mo2; + lowestaxisnum = mo2->health; + dist2 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y) - mo2->radius; + } + else if (mo2->health < lowestaxisnum) + { + dist1 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y) - mo2->radius; + + if (dist1 < dist2) + { + closestaxis = mo2; + lowestaxisnum = mo2->health; + dist2 = dist1; } } } @@ -439,17 +449,22 @@ static mobj_t *P_FindAxis(INT32 mare, INT32 axisnum) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; // Axis things are only at beginning of list. if (!(mo2->flags2 & MF2_AXIS)) return NULL; - if (mo2->type == MT_AXIS) - { - if (mo2->health == axisnum && mo2->threshold == mare) - return mo2; - } + if (mo2->type != MT_AXIS) + continue; + if (mo2->health != axisnum) + continue; + if (mo2->threshold != mare) + continue; + return mo2; } return NULL; @@ -469,17 +484,22 @@ static mobj_t *P_FindAxisTransfer(INT32 mare, INT32 axisnum, mobjtype_t type) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; // Axis things are only at beginning of list. if (!(mo2->flags2 & MF2_AXIS)) return NULL; - if (mo2->type == type) - { - if (mo2->health == axisnum && mo2->threshold == mare) - return mo2; - } + if (mo2->type != type) + continue; + if (mo2->health != axisnum) + continue; + if (mo2->threshold != mare) + continue; + return mo2; } return NULL; @@ -505,27 +525,31 @@ void P_TransferToAxis(player_t *player, INT32 axisnum) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; - if (mo2->type == MT_AXIS) - { - if (mo2->health == axisnum && mo2->threshold == mare) - { - if (closestaxis == NULL) - { - closestaxis = mo2; - dist2 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y)-mo2->radius; - } - else - { - dist1 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y)-mo2->radius; + if (mo2->type != MT_AXIS) + continue; + if (mo2->health != axisnum) + continue; + if (mo2->threshold != mare) + continue; - if (dist1 < dist2) - { - closestaxis = mo2; - dist2 = dist1; - } - } + if (closestaxis == NULL) + { + closestaxis = mo2; + dist2 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y) - mo2->radius; + } + else + { + dist1 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y) - mo2->radius; + + if (dist1 < dist2) + { + closestaxis = mo2; + dist2 = dist1; } } } @@ -602,6 +626,9 @@ static void P_DeNightserizePlayer(player_t *player) // Check to see if the player should be killed. for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (!(mo2->type == MT_NIGHTSDRONE)) continue; @@ -1617,6 +1644,9 @@ void P_SpawnShieldOrb(player_t *player) // blaze through the thinkers to see if an orb already exists! for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + shieldobj = (mobj_t *)th; if (shieldobj->type == orbtype && shieldobj->target == player->mo) @@ -4314,7 +4344,7 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) if (P_IsLocalPlayer(player)) // Only display it on your own view. { mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker - visual->target = lockon; + P_SetTarget(&visual->target, lockon); } } if ((cmd->buttons & BT_USE) && !(player->pflags & PF_USEDOWN)) @@ -4589,6 +4619,9 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2 == player->mo) @@ -4637,7 +4670,7 @@ static void P_DoJumpStuff(player_t *player, ticcmd_t *cmd) if (P_IsLocalPlayer(player)) // Only display it on your own view. { mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker - visual->target = lockon; + P_SetTarget(&visual->target, lockon); } } @@ -5783,29 +5816,32 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad // Find next waypoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; // Axis things are only at beginning of list. if (!(mo2->flags2 & MF2_AXIS)) break; + if (!(mo2->type == MT_AXISTRANSFER || mo2->type == MT_AXISTRANSFERLINE)) + continue; + if (mo2->threshold != sequence) + continue; - if ((mo2->type == MT_AXISTRANSFER || mo2->type == MT_AXISTRANSFERLINE) - && mo2->threshold == sequence) + if (player->pflags & PF_TRANSFERTOCLOSEST) { - if (player->pflags & PF_TRANSFERTOCLOSEST) - { - if (mo2->health == player->axis1->health) - transfer1 = mo2; - else if (mo2->health == player->axis2->health) - transfer2 = mo2; - } - else - { - if (mo2->health == player->mo->target->health) - transfer1 = mo2; - else if (mo2->health == player->mo->target->health + 1) - transfer2 = mo2; - } + if (mo2->health == player->axis1->health) + transfer1 = mo2; + else if (mo2->health == player->axis2->health) + transfer2 = mo2; + } + else + { + if (mo2->health == player->mo->target->health) + transfer1 = mo2; + else if (mo2->health == player->mo->target->health + 1) + transfer2 = mo2; } } @@ -5816,24 +5852,28 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad { for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; // Axis things are only at beginning of list. if (!(mo2->flags2 & MF2_AXIS)) break; + if (!(mo2->type == MT_AXISTRANSFER || mo2->type == MT_AXISTRANSFERLINE)) + continue; + if (mo2->threshold != sequence) + continue; - if (mo2->threshold == sequence && (mo2->type == MT_AXISTRANSFER || mo2->type == MT_AXISTRANSFERLINE)) + if (!transfer1) { - if (!transfer1) - { - transfer1 = mo2; - transfer1last = true; - } - else if (mo2->health > transfer1->health) - { - transfer1 = mo2; - transfer1last = true; - } + transfer1 = mo2; + transfer1last = true; + } + else if (mo2->health > transfer1->health) + { + transfer1 = mo2; + transfer1last = true; } } } @@ -5841,24 +5881,28 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad { for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; // Axis things are only at beginning of list. if (!(mo2->flags2 & MF2_AXIS)) break; + if (!(mo2->type == MT_AXISTRANSFER || mo2->type == MT_AXISTRANSFERLINE)) + continue; + if (mo2->threshold != sequence) + continue; - if (mo2->threshold == sequence && (mo2->type == MT_AXISTRANSFER || mo2->type == MT_AXISTRANSFERLINE)) + if (!transfer2) { - if (!transfer2) - { - transfer2 = mo2; - transfer2last = true; - } - else if (mo2->health > transfer2->health) - { - transfer2 = mo2; - transfer2last = true; - } + transfer2 = mo2; + transfer2last = true; + } + else if (mo2->health > transfer2->health) + { + transfer2 = mo2; + transfer2last = true; } } } @@ -6545,31 +6589,32 @@ static void P_NiGHTSMovement(player_t *player) // to find the closest axis point for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; - if (mo2->type == MT_AXIS) - { - if (mo2->threshold == player->mare) - { - if (closestaxis == NULL) - { - closestaxis = mo2; - dist2 = R_PointToDist2(newx, newy, mo2->x, mo2->y)-mo2->radius; - } - else - { - dist1 = R_PointToDist2(newx, newy, mo2->x, mo2->y)-mo2->radius; + if (mo2->type != MT_AXIS) + continue; + if (mo2->threshold != player->mare) + continue; - if (dist1 < dist2) - { - closestaxis = mo2; - dist2 = dist1; - } - } + if (closestaxis == NULL) + { + closestaxis = mo2; + dist2 = R_PointToDist2(newx, newy, mo2->x, mo2->y) - mo2->radius; + } + else + { + dist1 = R_PointToDist2(newx, newy, mo2->x, mo2->y) - mo2->radius; + + if (dist1 < dist2) + { + closestaxis = mo2; + dist2 = dist1; } } } - P_SetTarget(&player->mo->target, closestaxis); } @@ -7352,6 +7397,9 @@ static void P_MovePlayer(player_t *player) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type == MT_EGGCAPSULE @@ -7855,7 +7903,7 @@ static void P_MovePlayer(player_t *player) if (P_IsLocalPlayer(player)) // Only display it on your own view. { mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker - visual->target = lockon; + P_SetTarget(&visual->target, lockon); P_SetMobjStateNF(visual, visual->info->spawnstate+1); } } @@ -8256,20 +8304,25 @@ static void P_DoZoomTube(player_t *player) // Find next waypoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_TUBEWAYPOINT) continue; - if (mo2->threshold == sequence) - { - if ((reverse && mo2->health == player->mo->tracer->health - 1) - || (!reverse && mo2->health == player->mo->tracer->health + 1)) - { - waypoint = mo2; - break; - } - } + if (mo2->threshold != sequence) + continue; + + if (reverse && mo2->health != player->mo->tracer->health - 1) + continue; + + if (!reverse && mo2->health != player->mo->tracer->health + 1) + continue; + + waypoint = mo2; + break; } if (waypoint) @@ -8387,19 +8440,22 @@ static void P_DoRopeHang(player_t *player) // Find next waypoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_TUBEWAYPOINT) continue; - if (mo2->threshold == sequence) - { - if (mo2->health == player->mo->tracer->health + 1) - { - waypoint = mo2; - break; - } - } + if (mo2->threshold != sequence) + continue; + + if (mo2->health != player->mo->tracer->health + 1) + continue; + + waypoint = mo2; + break; } if (!(player->mo->tracer->flags & MF_SLIDEME) && !waypoint) @@ -8409,19 +8465,22 @@ static void P_DoRopeHang(player_t *player) // Wrap around back to first waypoint for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type != MT_TUBEWAYPOINT) continue; - if (mo2->threshold == sequence) - { - if (mo2->health == 0) - { - waypoint = mo2; - break; - } - } + if (mo2->threshold != sequence) + continue; + + if (mo2->health != 0) + continue; + + waypoint = mo2; + break; } } @@ -8468,22 +8527,22 @@ static void P_DoRopeHang(player_t *player) static void P_NukeAllPlayers(player_t *player) { mobj_t *mo; - thinker_t *think; + UINT8 i; - for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) + for (i = 0; i < MAXPLAYERS; i++) { - mo = (mobj_t *)think; - - if (!mo->player) + if (!playeringame[i]) + continue; + if (players[i].spectator) + continue; + if (!players[i].mo) + continue; + if (players[i].mo == player->mo) + continue; + if (players[i].mo->health <= 0) continue; - if (mo->health <= 0) // dead - continue; - - if (mo == player->mo) - continue; - - P_DamageMobj(mo, player->mo, player->mo, 1, 0); + P_DamageMobj(players[i].mo, player->mo, player->mo, 1, 0); } CONS_Printf(M_GetText("%s caused a world of pain.\n"), player_names[player-players]); @@ -8517,6 +8576,9 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { + if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo = (mobj_t *)think; if (!(mo->flags & MF_SHOOTABLE) && !(mo->type == MT_EGGGUARD || mo->type == MT_MINUS)) @@ -8565,6 +8627,9 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet) for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { + if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo = (mobj_t *)think; if (!((mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR) && (mo->flags & MF_SHOOTABLE)) || (mo->flags & MF_SPRING)) == !(mo->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag continue; // not a valid target @@ -8706,6 +8771,9 @@ void P_FindEmerald(void) // to find all emeralds for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (mo2->type == MT_EMERHUNT) { @@ -9931,6 +9999,9 @@ static mobj_t *P_GetAxis(INT32 num) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mobj = (mobj_t *)th; // NiGHTS axes spawn before anything else. If this mobj doesn't have MF2_AXIS, it means we reached the axes' end. @@ -9943,6 +10014,7 @@ static mobj_t *P_GetAxis(INT32 num) return mobj; } + CONS_Alert(CONS_WARNING, "P_GetAxis: Track segment %d is missing!\n", num); return NULL; } @@ -10569,6 +10641,9 @@ void P_PlayerThink(player_t *player) for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; if (!(mo2->type == MT_RING || mo2->type == MT_COIN diff --git a/src/r_data.c b/src/r_data.c index c490cc7da..6889bddde 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -2276,7 +2276,8 @@ void R_PrecacheLevel(void) if (spritepresent == NULL) I_Error("%s: Out of memory looking up sprites", "R_PrecacheLevel"); for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) - spritepresent[((mobj_t *)th)->sprite] = 1; + if (th->function.acp1 != (actionf_p1)P_RemoveThinkerDelayed) + spritepresent[((mobj_t *)th)->sprite] = 1; spritememory = 0; for (i = 0; i < numsprites; i++) diff --git a/src/st_stuff.c b/src/st_stuff.c index 132eada06..4122793ad 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2308,27 +2308,31 @@ static void ST_doItemFinderIconsAndSound(void) // Scan thinkers to find emblem mobj with these ids for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mo2 = (mobj_t *)th; - if (mo2->type == MT_EMBLEM) + if (mo2->type != MT_EMBLEM) + continue; + + if (!(mo2->flags & MF_SPECIAL)) + continue; + + for (i = 0; i < stemblems; ++i) { - if (!(mo2->flags & MF_SPECIAL)) - continue; - - for (i = 0; i < stemblems; ++i) + if (mo2->health == emblems[i] + 1) { - if (mo2->health == emblems[i]+1) - { - soffset = (i * 20) - ((stemblems-1) * 10); + soffset = (i * 20) - ((stemblems - 1) * 10); - newinterval = ST_drawEmeraldHuntIcon(mo2, itemhoming, soffset); - if (newinterval && (!interval || newinterval < interval)) - interval = newinterval; + newinterval = ST_drawEmeraldHuntIcon(mo2, itemhoming, soffset); + if (newinterval && (!interval || newinterval < interval)) + interval = newinterval; - break; - } + break; } } + } if (!(P_AutoPause() || paused) && interval > 0 && leveltime && leveltime % interval == 0) From 47f138ac34a64795e30f466717e454cab701470d Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 13 Jul 2019 13:43:22 +0100 Subject: [PATCH 068/128] I know this isn't my branch, but found several reference haemmoragers and figured it'd be appropriate to commit here. --- src/hardware/hw_light.c | 31 +++++++++++++++++++++---------- src/lua_blockmaplib.c | 2 ++ src/lua_mobjlib.c | 11 ++++++++++- src/lua_playerlib.c | 21 ++++++++++++++++++--- src/p_maputl.c | 3 +++ src/p_user.c | 5 +++-- 6 files changed, 57 insertions(+), 16 deletions(-) diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 8a945fd9e..fc1f46539 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -804,6 +804,14 @@ void HWR_WallLighting(FOutVector *wlVerts) FSurfaceInfo Surf; float dist_p2d, d[4], s; + if (!dynlights->mo[j]) + continue; + if (P_MobjWasRemoved(dynlights->mo[j])) + { + P_SetTarget(&dynlights->mo[j], NULL); + continue; + } + // check bounding box first if (SphereTouchBBox3D(&wlVerts[2], &wlVerts[0], &LIGHT_POS(j), DL_RADIUS(j))==false) continue; @@ -854,8 +862,6 @@ void HWR_WallLighting(FOutVector *wlVerts) #ifdef DL_HIGH_QUALITY Surf.FlatColor.s.alpha = (UINT8)((1-dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha); #endif - if (!dynlights->mo[j]->state) - return; // next state is null so fade out with alpha if (dynlights->mo[j]->state->nextstate == S_NULL) Surf.FlatColor.s.alpha = (UINT8)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha); @@ -886,6 +892,14 @@ void HWR_PlaneLighting(FOutVector *clVerts, int nrClipVerts) FSurfaceInfo Surf; float dist_p2d, s; + if (!dynlights->mo[j]) + continue; + if (P_MobjWasRemoved(dynlights->mo[j])) + { + P_SetTarget(&dynlights->mo[j], NULL); + continue; + } + // BP: The kickass Optimization: check if light touch bounding box if (SphereTouchBBox3D(&p1, &p2, &dynlights->position[j], DL_RADIUS(j))==false) continue; @@ -917,8 +931,6 @@ void HWR_PlaneLighting(FOutVector *clVerts, int nrClipVerts) #ifdef DL_HIGH_QUALITY Surf.FlatColor.s.alpha = (unsigned char)((1 - dist_p2d/DL_SQRRADIUS(j))*Surf.FlatColor.s.alpha); #endif - if (!dynlights->mo[j]->state) - return; // next state is null so fade out with alpha if ((dynlights->mo[j]->state->nextstate == S_NULL)) Surf.FlatColor.s.alpha = (unsigned char)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.FlatColor.s.alpha); @@ -1110,7 +1122,8 @@ void HWR_DrawCoronas(void) // -------------------------------------------------------------------------- void HWR_ResetLights(void) { - dynlights->nb = 0; + while (dynlights->nb) + P_SetTarget(&dynlights->mo[--dynlights->nb], NULL); } // -------------------------------------------------------------------------- @@ -1145,9 +1158,7 @@ void HWR_DL_AddLight(gr_vissprite_t *spr, GLPatch_t *patch) p_lspr = t_lspr[spr->mobj->sprite]; if ((p_lspr->type&DYNLIGHT_SPR) && ((p_lspr->type != LIGHT_SPR) || cv_grstaticlighting.value) - && (dynlights->nb < DL_MAX_LIGHT) - - && spr->mobj->state) + && (dynlights->nb < DL_MAX_LIGHT)) { LIGHT_POS(dynlights->nb).x = FIXED_TO_FLOAT(spr->mobj->x); LIGHT_POS(dynlights->nb).y = FIXED_TO_FLOAT(spr->mobj->z)+FIXED_TO_FLOAT(spr->mobj->height>>1)+p_lspr->light_yoffset; @@ -1380,7 +1391,7 @@ void HWR_CreateStaticLightmaps(int bspnum) #ifdef STATICLIGHT CONS_Debug(DBG_RENDER, "HWR_CreateStaticLightmaps\n"); - dynlights->nb = 0; + HWR_ResetLights(); // First: Searching for lights // BP: if i was you, I will make it in create mobj since mobj can be create @@ -1392,7 +1403,7 @@ void HWR_CreateStaticLightmaps(int bspnum) validcount++; // to be sure HWR_ComputeLightMapsInBSPNode(bspnum, NULL); - dynlights->nb = 0; + HWR_ResetLights(); #else (void)bspnum; #endif diff --git a/src/lua_blockmaplib.c b/src/lua_blockmaplib.c index dabbdd9f6..2383bb32e 100644 --- a/src/lua_blockmaplib.c +++ b/src/lua_blockmaplib.c @@ -54,10 +54,12 @@ static UINT8 lib_searchBlockmap_Objects(lua_State *L, INT32 x, INT32 y, mobj_t * CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); blockfuncerror = true; + P_SetTarget(&bnext, NULL); return 0; // *shrugs* } if (!lua_isnil(gL, -1)) { // if nil, continue + P_SetTarget(&bnext, NULL); if (lua_toboolean(gL, -1)) return 2; // stop whole search else diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 0a3d356c9..8bbbebe1d 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -274,10 +274,19 @@ static int mobj_get(lua_State *L) // bprev -- same deal as sprev above, but for the blockmap. return UNIMPLEMENTED; case mobj_hnext: + if (mo->hnext && P_MobjWasRemoved(mo->hnext)) + { // don't put invalid mobj back into Lua. + P_SetTarget(&mo->hnext, NULL); + return 0; + } LUA_PushUserdata(L, mo->hnext, META_MOBJ); break; case mobj_hprev: - // implimented differently from sprev and bprev because SSNTails. + if (mo->hprev && P_MobjWasRemoved(mo->hprev)) + { // don't put invalid mobj back into Lua. + P_SetTarget(&mo->hprev, NULL); + return 0; + } LUA_PushUserdata(L, mo->hprev, META_MOBJ); break; case mobj_type: diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index f3eb978f6..700dab211 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -476,7 +476,12 @@ static int player_set(lua_State *L) else if (fastcmp(field,"followitem")) plr->followitem = luaL_checkinteger(L, 3); else if (fastcmp(field,"followmobj")) - P_SetTarget(&plr->followmobj, *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ))); + { + mobj_t *mo = NULL; + if (!lua_isnil(L, 3)) + mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + P_SetTarget(&plr->followmobj, mo); + } else if (fastcmp(field,"actionspd")) plr->actionspd = (INT32)luaL_checkinteger(L, 3); else if (fastcmp(field,"mindash")) @@ -560,9 +565,19 @@ static int player_set(lua_State *L) else if (fastcmp(field,"old_angle_pos")) plr->old_angle_pos = luaL_checkangle(L, 3); else if (fastcmp(field,"axis1")) - P_SetTarget(&plr->axis1, *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ))); + { + mobj_t *mo = NULL; + if (!lua_isnil(L, 3)) + mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + P_SetTarget(&plr->axis1, mo); + } else if (fastcmp(field,"axis2")) - P_SetTarget(&plr->axis2, *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ))); + { + mobj_t *mo = NULL; + if (!lua_isnil(L, 3)) + mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + P_SetTarget(&plr->axis2, mo); + } else if (fastcmp(field,"bumpertime")) plr->bumpertime = (tic_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"flyangle")) diff --git a/src/p_maputl.c b/src/p_maputl.c index 1be57399c..0ca84096a 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -1093,7 +1093,10 @@ boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean (*func)(mobj_t *)) { P_SetTarget(&bnext, mobj->bnext); // We want to note our reference to bnext here incase it is MF_NOTHINK and gets removed! if (!func(mobj)) + { + P_SetTarget(&bnext, NULL); return false; + } if (P_MobjWasRemoved(tmthing) // func just popped our tmthing, cannot continue. || (bnext && P_MobjWasRemoved(bnext))) // func just broke blockmap chain, cannot continue. { diff --git a/src/p_user.c b/src/p_user.c index 4c35a3257..6761d567d 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3655,7 +3655,8 @@ static void P_DoTeeter(player_t *player) if (teeter) // only bother with objects as a last resort if you were already teetering { mobj_t *oldtmthing = tmthing; - tmthing = teeterer = player->mo; + teeterer = player->mo; + P_SetTarget(&tmthing, teeterer); teeterxl = teeterxh = player->mo->x; teeteryl = teeteryh = player->mo->y; couldteeter = false; @@ -3669,7 +3670,7 @@ static void P_DoTeeter(player_t *player) } teeterdone: teeter = solidteeter; - tmthing = oldtmthing; // restore old tmthing, goodness knows what the game does with this before mobj thinkers + P_SetTarget(&tmthing, oldtmthing); // restore old tmthing, goodness knows what the game does with this before mobj thinkers } } if (teeter) From 323d5d61d38c2e809648488cfec227c873ef4808 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 13 Jul 2019 14:07:40 +0100 Subject: [PATCH 069/128] Correct some more minor issues with hw_light.c and the ALAM_LIGHTING. (Hi Alam! ^u^) --- src/hardware/hw_light.c | 65 ++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index fc1f46539..2456be311 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -1061,6 +1061,14 @@ void HWR_DrawCoronas(void) if (!(p_lspr->type & CORONA_SPR)) continue; + if (!dynlights->mo[j]) + continue; + if (P_MobjWasRemoved(dynlights->mo[j])) + { + P_SetTarget(&dynlights->mo[j], NULL); + continue; + } + transform(&cx,&cy,&cz); // more realistique corona ! @@ -1154,22 +1162,25 @@ void HWR_DL_AddLight(gr_vissprite_t *spr, GLPatch_t *patch) return; #endif + if (dynlights->nb >= DL_MAX_LIGHT) + return; + // check if sprite contain dynamic light p_lspr = t_lspr[spr->mobj->sprite]; - if ((p_lspr->type&DYNLIGHT_SPR) - && ((p_lspr->type != LIGHT_SPR) || cv_grstaticlighting.value) - && (dynlights->nb < DL_MAX_LIGHT)) - { - LIGHT_POS(dynlights->nb).x = FIXED_TO_FLOAT(spr->mobj->x); - LIGHT_POS(dynlights->nb).y = FIXED_TO_FLOAT(spr->mobj->z)+FIXED_TO_FLOAT(spr->mobj->height>>1)+p_lspr->light_yoffset; - LIGHT_POS(dynlights->nb).z = FIXED_TO_FLOAT(spr->mobj->y); + if (!(p_lspr->type & DYNLIGHT_SPR)) + return; + if ((p_lspr->type != LIGHT_SPR) || cv_grstaticlighting.value) + return; - P_SetTarget(&dynlights->mo[dynlights->nb], spr->mobj); + LIGHT_POS(dynlights->nb).x = FIXED_TO_FLOAT(spr->mobj->x); + LIGHT_POS(dynlights->nb).y = FIXED_TO_FLOAT(spr->mobj->z)+FIXED_TO_FLOAT(spr->mobj->height>>1)+p_lspr->light_yoffset; + LIGHT_POS(dynlights->nb).z = FIXED_TO_FLOAT(spr->mobj->y); - dynlights->p_lspr[dynlights->nb] = p_lspr; + P_SetTarget(&dynlights->mo[dynlights->nb], spr->mobj); - dynlights->nb++; - } + dynlights->p_lspr[dynlights->nb] = p_lspr; + + dynlights->nb++; } static GLPatch_t lightmappatch; @@ -1323,6 +1334,14 @@ static void HWR_CheckSubsector(size_t num, fixed_t *bbox) // if (CircleTouchBBox(&p1, &p2, &LIGHT_POS(lightnum), DL_RADIUS(lightnum))==false) // continue; + if (!dynlights->mo[lightnum]) + continue; + if (P_MobjWasRemoved(dynlights->mo[lightnum])) + { + P_SetTarget(&dynlights->mo[lightnum], NULL); + continue; + } + count = sub->numlines; // how many linedefs line = &segs[sub->firstline]; // first line seg while (count--) @@ -1340,18 +1359,20 @@ static void HWR_CheckSubsector(size_t num, fixed_t *bbox) // -------------------------------------------------------------------------- static void HWR_AddMobjLights(mobj_t *thing) { - if (t_lspr[thing->sprite]->type & CORONA_SPR) - { - LIGHT_POS(dynlights->nb).x = FIXED_TO_FLOAT(thing->x); - LIGHT_POS(dynlights->nb).y = FIXED_TO_FLOAT(thing->z) + t_lspr[thing->sprite]->light_yoffset; - LIGHT_POS(dynlights->nb).z = FIXED_TO_FLOAT(thing->y); + if (dynlights->nb >= DL_MAX_LIGHT) + return; + if (!(t_lspr[thing->sprite]->type & CORONA_SPR)) + return; - dynlights->p_lspr[dynlights->nb] = t_lspr[thing->sprite]; + LIGHT_POS(dynlights->nb).x = FIXED_TO_FLOAT(thing->x); + LIGHT_POS(dynlights->nb).y = FIXED_TO_FLOAT(thing->z) + t_lspr[thing->sprite]->light_yoffset; + LIGHT_POS(dynlights->nb).z = FIXED_TO_FLOAT(thing->y); - dynlights->nb++; - if (dynlights->nb > DL_MAX_LIGHT) - dynlights->nb = DL_MAX_LIGHT; - } + P_SetTarget(&dynlights->mo[dynlights->nb], thing); + + dynlights->p_lspr[dynlights->nb] = t_lspr[thing->sprite]; + + dynlights->nb++; } //Hurdler: The goal of this function is to walk through all the bsp starting @@ -1402,8 +1423,6 @@ void HWR_CreateStaticLightmaps(int bspnum) // Second: Build all lightmap for walls covered by lights validcount++; // to be sure HWR_ComputeLightMapsInBSPNode(bspnum, NULL); - - HWR_ResetLights(); #else (void)bspnum; #endif From e68e510ca26c469efdeb978fedb0485d114a6993 Mon Sep 17 00:00:00 2001 From: sphere Date: Sat, 13 Jul 2019 23:15:56 +0200 Subject: [PATCH 070/128] Assign sound to the wood debris object. --- src/info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/info.c b/src/info.c index 631f40cdc..0cbe8d82e 100644 --- a/src/info.c +++ b/src/info.c @@ -19642,7 +19642,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // display offset 100, // mass 0, // damage - sfx_None, // activesound + sfx_wbreak, // activesound MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_RUNSPAWNFUNC|MF_NOCLIPHEIGHT|MF_SCENERY, // flags S_NULL // raisestate }, From 106f6498e25abf529b6d27bf1d1359946285a959 Mon Sep 17 00:00:00 2001 From: sphere Date: Sun, 14 Jul 2019 01:29:36 +0200 Subject: [PATCH 071/128] Add meleestate to MT_WALLSPIKE. --- src/info.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/info.c b/src/info.c index 631f40cdc..7606f27a1 100644 --- a/src/info.c +++ b/src/info.c @@ -7492,7 +7492,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // painstate 0, // painchance sfx_s3k64, // painsound - S_NULL, // meleestate + S_WALLSPIKE4, // meleestate S_NULL, // missilestate S_WALLSPIKED1, // deathstate S_WALLSPIKED2, // xdeathstate @@ -19642,7 +19642,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 0, // display offset 100, // mass 0, // damage - sfx_None, // activesound + sfx_wbreak, // activesound MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_RUNSPAWNFUNC|MF_NOCLIPHEIGHT|MF_SCENERY, // flags S_NULL // raisestate }, From 9c73424b4b6038a90db53a44a5b8d4784b6fa4ea Mon Sep 17 00:00:00 2001 From: sphere Date: Sun, 14 Jul 2019 02:17:44 +0200 Subject: [PATCH 072/128] Add spring flags: float for horizontal & no gravity for diagonal. --- src/p_mobj.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index a57998ea0..0428dd83b 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -4662,7 +4662,7 @@ static void P_Boss4PinchSpikeballs(mobj_t *mobj, angle_t angle, fixed_t dz) } dz /= 9; - + while ((base = base->tracer)) // there are 10 per spoke, remember that { dx = (originx + P_ReturnThrustX(mobj, angle, (9*132)<x)/9; @@ -11964,6 +11964,15 @@ ML_EFFECT5 : Don't stop thinking when too far away if (i == MT_YELLOWDIAG || i == MT_REDDIAG) mobj->angle += ANGLE_22h; + if (i == MT_YELLOWHORIZ || i == MT_REDHORIZ || i == MT_BLUEHORIZ) + { + if (mthing->options & MTF_OBJECTFLIP) + mobj->z -= 16*FRACUNIT; + else + mobj->z += 16*FRACUNIT; + } + + if (mobj->flags & MF_NIGHTSITEM) { // Spawn already displayed @@ -11991,6 +12000,9 @@ ML_EFFECT5 : Don't stop thinking when too far away if (mthing->options & MTF_OBJECTSPECIAL) { + if (i == MT_YELLOWDIAG || i == MT_REDDIAG) + mobj->flags |= MF_NOGRAVITY; + if ((mobj->flags & MF_MONITOR) && mobj->info->speed != 0) { // flag for strong/weak random boxes @@ -12570,9 +12582,9 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) if (mthing->options & MTF_AMBUSH) // Special flag for rings { if (mthing->options & MTF_OBJECTFLIP) - z -= 24*FRACUNIT; + z -= 64*FRACUNIT; else - z += 24*FRACUNIT; + z += 64*FRACUNIT; } mthing->z = (INT16)(z>>FRACBITS); From 911b0262ee77cdae5ac71df98496e3232fc1a4d4 Mon Sep 17 00:00:00 2001 From: sphere Date: Sun, 14 Jul 2019 02:31:33 +0200 Subject: [PATCH 073/128] Whoops, forgot to revert this. --- src/p_mobj.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 0428dd83b..d13b9a57c 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12582,9 +12582,9 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) if (mthing->options & MTF_AMBUSH) // Special flag for rings { if (mthing->options & MTF_OBJECTFLIP) - z -= 64*FRACUNIT; + z -= 24*FRACUNIT; else - z += 64*FRACUNIT; + z += 24*FRACUNIT; } mthing->z = (INT16)(z>>FRACBITS); From b3e953c8c34689c82d1ea589b1e9c34a2217dce1 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 14 Jul 2019 14:21:32 +0100 Subject: [PATCH 074/128] Correct some extant fuckups. --- src/hardware/hw_light.c | 2 +- src/p_tick.c | 16 +++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 2456be311..a52d72869 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -1170,7 +1170,7 @@ void HWR_DL_AddLight(gr_vissprite_t *spr, GLPatch_t *patch) if (!(p_lspr->type & DYNLIGHT_SPR)) return; if ((p_lspr->type != LIGHT_SPR) || cv_grstaticlighting.value) - return; + return; LIGHT_POS(dynlights->nb).x = FIXED_TO_FLOAT(spr->mobj->x); LIGHT_POS(dynlights->nb).y = FIXED_TO_FLOAT(spr->mobj->z)+FIXED_TO_FLOAT(spr->mobj->height>>1)+p_lspr->light_yoffset; diff --git a/src/p_tick.c b/src/p_tick.c index 1d248d2ae..a0f6edef9 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -230,13 +230,19 @@ void P_RemoveThinkerDelayed(thinker_t *thinker) { thinker_t *next; #ifdef PARANOIA - if (thinker->next) - thinker->next = NULL; - else if (thinker->references) // Usually gets cleared up in one frame; what's going on here, then? - CONS_Printf("Number of potentially faulty references: %d\n", thinker->references); -#endif +#define BEENAROUNDBIT (0x40000000) // has to be sufficiently high that it's unlikely to happen in regular gameplay. If you change this, pay attention to the bit pattern of INT32_MIN. + if (thinker->references & ~BEENAROUNDBIT) + { + if (thinker->references & BEENAROUNDBIT) // Usually gets cleared up in one frame; what's going on here, then? + CONS_Printf("Number of potentially faulty references: %d\n", (thinker->references & ~BEENAROUNDBIT)); + thinker->references |= BEENAROUNDBIT; + return; + } +#undef BEENAROUNDBIT +#else if (thinker->references) return; +#endif /* Remove from main thinker list */ next = thinker->next; From cfc56c954144275ad94038e8c8462798ad486d5d Mon Sep 17 00:00:00 2001 From: sphere Date: Sun, 14 Jul 2019 15:30:00 +0200 Subject: [PATCH 075/128] Don't upscale the waving flags, make them twice as large instead --- src/info.c | 6 +++--- src/p_mobj.c | 4 +--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/info.c b/src/info.c index 0cbe8d82e..08b1ab5e9 100644 --- a/src/info.c +++ b/src/info.c @@ -11278,8 +11278,8 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 4*FRACUNIT, // radius - 104*FRACUNIT, // height + 8*FRACUNIT, // radius + 208*FRACUNIT, // height 0, // display offset 100, // mass 0, // damage @@ -11305,7 +11305,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // xdeathstate sfx_None, // deathsound 0, // speed - 4*FRACUNIT, // radius + 8*FRACUNIT, // radius 1, // height -- this is not a typo 0, // display offset 100, // mass diff --git a/src/p_mobj.c b/src/p_mobj.c index a57998ea0..acc995dd0 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -4662,7 +4662,7 @@ static void P_Boss4PinchSpikeballs(mobj_t *mobj, angle_t angle, fixed_t dz) } dz /= 9; - + while ((base = base->tracer)) // there are 10 per spoke, remember that { dx = (originx + P_ReturnThrustX(mobj, angle, (9*132)<x)/9; @@ -9653,8 +9653,6 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) { mobj_t *prev = mobj, *cur; UINT8 i; - mobj->destscale <<= 2; - P_SetScale(mobj, mobj->destscale); for (i = 0; i <= 16; i++) // probably should be < but staying authentic to the Lua version { cur = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_WAVINGFLAGSEG); From ee937c4df038b60614a248039bc7ed2914368b2c Mon Sep 17 00:00:00 2001 From: sphere Date: Sun, 14 Jul 2019 16:50:45 +0200 Subject: [PATCH 076/128] Add a blue variant of the waving flags. --- src/dehacked.c | 9 +++++--- src/info.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++---- src/info.h | 9 +++++--- src/p_mobj.c | 8 ++++--- 4 files changed, 76 insertions(+), 13 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 31c17f188..18d0b2243 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -5708,7 +5708,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_FLAMEHOLDER", "S_FIRETORCH", "S_WAVINGFLAG", - "S_WAVINGFLAGSEG", + "S_WAVINGFLAGSEG1", + "S_WAVINGFLAGSEG2", "S_CRAWLASTATUE", "S_FACESTABBERSTATUE", "S_SUSPICIOUSFACESTABBERSTATUE_WAIT", @@ -7523,8 +7524,10 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_CANDLEPRICKET", // Candle pricket "MT_FLAMEHOLDER", // Flame holder "MT_FIRETORCH", // Fire torch - "MT_WAVINGFLAG", // Waving flag - "MT_WAVINGFLAGSEG", // Waving flag segment + "MT_WAVINGFLAG1", // Waving flag (red) + "MT_WAVINGFLAG2", // Waving flag (blue) + "MT_WAVINGFLAGSEG1", // Waving flag segment (red) + "MT_WAVINGFLAGSEG2", // Waving flag segment (blue) "MT_CRAWLASTATUE", // Crawla statue "MT_FACESTABBERSTATUE", // Facestabber statue "MT_SUSPICIOUSFACESTABBERSTATUE", // :eggthinking: diff --git a/src/info.c b/src/info.c index 08b1ab5e9..4733329f3 100644 --- a/src/info.c +++ b/src/info.c @@ -2338,7 +2338,8 @@ state_t states[NUMSTATES] = {SPR_CTRC, FF_FULLBRIGHT|FF_ANIMATE, 8*3, {A_FlameParticle}, 3, 3, S_FIRETORCH}, // S_FIRETORCH {SPR_CFLG, 0, -1, {NULL}, 0, 0, S_NULL}, // S_WAVINGFLAG - {SPR_CFLG, FF_PAPERSPRITE|1, -1, {NULL}, 0, 0, S_NULL}, // S_WAVINGFLAGSEG + {SPR_CFLG, FF_PAPERSPRITE|1, -1, {NULL}, 0, 0, S_NULL}, // S_WAVINGFLAGSEG1 + {SPR_CFLG, FF_PAPERSPRITE|2, -1, {NULL}, 0, 0, S_NULL}, // S_WAVINGFLAGSEG2 {SPR_CSTA, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CRAWLASTATUE @@ -11261,7 +11262,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_WAVINGFLAG + { // MT_WAVINGFLAG1 1118, // doomednum S_WAVINGFLAG, // spawnstate 1000, // spawnhealth @@ -11288,9 +11289,63 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_WAVINGFLAGSEG + { // MT_WAVINGFLAG2 + 1128, // doomednum + S_WAVINGFLAG, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 8*FRACUNIT, // radius + 208*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_SOLID, // flags + S_NULL // raisestate + }, + + { // MT_WAVINGFLAGSEG1 -1, // doomednum - S_WAVINGFLAGSEG, // spawnstate + S_WAVINGFLAGSEG1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 8*FRACUNIT, // radius + 1, // height -- this is not a typo + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_WAVINGFLAGSEG2 + -1, // doomednum + S_WAVINGFLAGSEG2, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound diff --git a/src/info.h b/src/info.h index 44f08a4e9..536034867 100644 --- a/src/info.h +++ b/src/info.h @@ -2467,7 +2467,8 @@ typedef enum state S_FLAMEHOLDER, S_FIRETORCH, S_WAVINGFLAG, - S_WAVINGFLAGSEG, + S_WAVINGFLAGSEG1, + S_WAVINGFLAGSEG2, S_CRAWLASTATUE, S_FACESTABBERSTATUE, S_SUSPICIOUSFACESTABBERSTATUE_WAIT, @@ -4304,8 +4305,10 @@ typedef enum mobj_type MT_CANDLEPRICKET, // Candle pricket MT_FLAMEHOLDER, // Flame holder MT_FIRETORCH, // Fire torch - MT_WAVINGFLAG, // Waving flag - MT_WAVINGFLAGSEG, // Waving flag segment + MT_WAVINGFLAG1, // Waving flag (red) + MT_WAVINGFLAG2, // Waving flag (blue) + MT_WAVINGFLAGSEG1, // Waving flag segment (red) + MT_WAVINGFLAGSEG2, // Waving flag segment (blue) MT_CRAWLASTATUE, // Crawla statue MT_FACESTABBERSTATUE, // Facestabber statue MT_SUSPICIOUSFACESTABBERSTATUE, // :eggthinking: diff --git a/src/p_mobj.c b/src/p_mobj.c index acc995dd0..5e0509a0f 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8046,7 +8046,8 @@ void P_MobjThinker(mobj_t *mobj) mobj->tracer->z += mobj->height; } break; - case MT_WAVINGFLAG: + case MT_WAVINGFLAG1: + case MT_WAVINGFLAG2: { fixed_t base = (leveltime<<(FRACBITS+1)); mobj_t *seg = mobj->tracer, *prev = mobj; @@ -9649,13 +9650,14 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) case MT_BIGMINE: mobj->extravalue1 = FixedHypot(mobj->x, mobj->y)>>FRACBITS; break; - case MT_WAVINGFLAG: + case MT_WAVINGFLAG1: + case MT_WAVINGFLAG2: { mobj_t *prev = mobj, *cur; UINT8 i; for (i = 0; i <= 16; i++) // probably should be < but staying authentic to the Lua version { - cur = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_WAVINGFLAGSEG); + cur = P_SpawnMobjFromMobj(mobj, 0, 0, 0, ((mobj->type == MT_WAVINGFLAG1) ? MT_WAVINGFLAGSEG1 : MT_WAVINGFLAGSEG2));; P_SetTarget(&prev->tracer, cur); cur->extravalue1 = i; prev = cur; From 794235a848aecd2424d30386ab652cb8bfa222d8 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 14 Jul 2019 16:19:48 +0100 Subject: [PATCH 077/128] Fix mixed code-and-declaration error --- src/p_polyobj.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 3de7c4390..475fa41b7 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1495,6 +1495,7 @@ void Polyobj_InitLevel(void) mqueue_t anchorqueue; mobjqitem_t *qitem; INT32 i, numAnchors = 0; + mobj_t *mo; M_QueueInit(&spawnqueue); M_QueueInit(&anchorqueue); @@ -1513,7 +1514,7 @@ void Polyobj_InitLevel(void) if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; - mobj_t *mo = (mobj_t *)th; + mo = (mobj_t *)th; if (mo->info->doomednum == POLYOBJ_SPAWN_DOOMEDNUM || mo->info->doomednum == POLYOBJ_SPAWNCRUSH_DOOMEDNUM) From 5c54022a8994ca457ec8b67bb767eb01037866ec Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 14 Jul 2019 16:23:01 +0100 Subject: [PATCH 078/128] Add static keyword to these variables for correctness --- src/sdl/mixer_sound.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 883ba992a..004c60605 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -108,11 +108,11 @@ static UINT16 current_track; #endif #ifdef HAVE_OPENMPT -int mod_err = OPENMPT_ERROR_OK; +static int mod_err = OPENMPT_ERROR_OK; static const char *mod_err_str; static UINT16 current_subsong; -size_t probesize; -int result; +static size_t probesize; +static int result; #endif static void var_cleanup(void) From 79cf8eb08def9d48f770325bd2c3fb217ff1dc63 Mon Sep 17 00:00:00 2001 From: sphere Date: Sun, 14 Jul 2019 17:30:33 +0200 Subject: [PATCH 079/128] Add a blue variant of the pole banner & change some doomednums. --- src/dehacked.c | 9 ++++--- src/info.c | 69 +++++++++++++++++++++++++++++++++++++++++++++----- src/info.h | 9 ++++--- src/p_mobj.c | 5 ++-- 4 files changed, 77 insertions(+), 15 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 18d0b2243..01e2b0bde 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -5699,7 +5699,8 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_CEZFLOWER", "S_CEZPOLE", - "S_CEZBANNER", + "S_CEZBANNER1", + "S_CEZBANNER2", "S_PINETREE", "S_CEZBUSH1", "S_CEZBUSH2", @@ -7515,8 +7516,10 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_SMALLFIREBAR", // Small Firebar "MT_BIGFIREBAR", // Big Firebar "MT_CEZFLOWER", // Flower - "MT_CEZPOLE", // Pole - "MT_CEZBANNER", // Banner + "MT_CEZPOLE1", // Pole (with red banner) + "MT_CEZPOLE2", // Pole (with blue banner) + "MT_CEZBANNER1", // Banner (red) + "MT_CEZBANNER2", // Banner (blue) "MT_PINETREE", // Pine Tree "MT_CEZBUSH1", // Bush 1 "MT_CEZBUSH2", // Bush 2 diff --git a/src/info.c b/src/info.c index 4733329f3..8796eca91 100644 --- a/src/info.c +++ b/src/info.c @@ -2322,9 +2322,10 @@ state_t states[NUMSTATES] = {SPR_BFBR, FF_FULLBRIGHT|15, 1, {NULL}, 0, 0, S_BIGFIREBAR1}, // S_BIGFIREBAR16 {SPR_FWR4, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZFLOWER - {SPR_BANR, 1, -1, {NULL}, 0, 0, S_NULL}, // S_CEZPOLE + {SPR_BANR, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZPOLE - {SPR_BANR, FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_CEZBANNER + {SPR_BANR, FF_PAPERSPRITE|1, -1, {NULL}, 0, 0, S_NULL}, // S_CEZBANNER1 + {SPR_BANR, FF_PAPERSPRITE|2, -1, {NULL}, 0, 0, S_NULL}, // S_CEZBANNER2 {SPR_PINE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_PINETREE {SPR_CEZB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_CEZBUSH1 @@ -11019,7 +11020,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_CEZPOLE + { // MT_CEZPOLE1 1117, // doomednum S_CEZPOLE, // spawnstate 1000, // spawnhealth @@ -11046,9 +11047,63 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_CEZBANNER + { // MT_CEZPOLE2 + 1118, // doomednum + S_CEZPOLE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 40*FRACUNIT, // radius + 224*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_CEZBANNER1 -1, // doomednum - S_CEZBANNER, // spawnstate + S_CEZBANNER1, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 8, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 0, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 40*FRACUNIT, // radius + 224*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOTHINK|MF_NOBLOCKMAP|MF_NOCLIP|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_CEZBANNER2 + -1, // doomednum + S_CEZBANNER2, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -11263,7 +11318,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = }, { // MT_WAVINGFLAG1 - 1118, // doomednum + 1128, // doomednum S_WAVINGFLAG, // spawnstate 1000, // spawnhealth S_NULL, // seestate @@ -11290,7 +11345,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = }, { // MT_WAVINGFLAG2 - 1128, // doomednum + 1129, // doomednum S_WAVINGFLAG, // spawnstate 1000, // spawnhealth S_NULL, // seestate diff --git a/src/info.h b/src/info.h index 536034867..a9a0321ec 100644 --- a/src/info.h +++ b/src/info.h @@ -2458,7 +2458,8 @@ typedef enum state S_CEZFLOWER, S_CEZPOLE, - S_CEZBANNER, + S_CEZBANNER1, + S_CEZBANNER2, S_PINETREE, S_CEZBUSH1, S_CEZBUSH2, @@ -4296,8 +4297,10 @@ typedef enum mobj_type MT_SMALLFIREBAR, // Small Firebar MT_BIGFIREBAR, // Big Firebar MT_CEZFLOWER, // Flower - MT_CEZPOLE, // Pole - MT_CEZBANNER, // Banner + MT_CEZPOLE1, // Pole (with red banner) + MT_CEZPOLE2, // Pole (with blue banner) + MT_CEZBANNER1, // Banner (red) + MT_CEZBANNER2, // Banner (blue) MT_PINETREE, // Pine Tree MT_CEZBUSH1, // Bush 1 MT_CEZBUSH2, // Bush 2 diff --git a/src/p_mobj.c b/src/p_mobj.c index 5e0509a0f..396fd3583 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11737,13 +11737,14 @@ ML_EFFECT5 : Don't stop thinking when too far away P_SpawnMobjFromMobj(mobj, -1*FRACUNIT, 0, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_270; } break; - case MT_CEZPOLE: + case MT_CEZPOLE1: + case MT_CEZPOLE2: { // Spawn the banner angle_t mobjangle = FixedAngle(mthing->angle<angle = mobjangle + ANGLE_90; + 0, ((mobj->type == MT_CEZPOLE1) ? MT_CEZBANNER1 : MT_CEZBANNER2))->angle = mobjangle + ANGLE_90; } break; case MT_HHZTREE_TOP: From fac6de9c2e218593aa1e6686088f5baec2a856a6 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 14 Jul 2019 18:10:03 +0100 Subject: [PATCH 080/128] The titlemap glitches turned out to be linked to deathmatchstarts, which wasn't actually properly cleared out each level load ...let's actually fix that, lol. (Neither were the CTF starts but those didn't directly cause any problems luckily) --- src/p_setup.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index e112e7cd7..c0aa7ffa3 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2868,7 +2868,10 @@ boolean P_SetupLevel(boolean skipprecip) // reset the player starts for (i = 0; i < MAXPLAYERS; i++) - playerstarts[i] = NULL; + playerstarts[i] = bluectfstarts[i] = redctfstarts[i] = NULL; + + for (i = 0; i < MAX_DM_STARTS; i++) + deathmatchstarts[i] = NULL; for (i = 0; i < 2; i++) skyboxmo[i] = NULL; @@ -2904,7 +2907,10 @@ boolean P_SetupLevel(boolean skipprecip) // reset the player starts for (i = 0; i < MAXPLAYERS; i++) - playerstarts[i] = NULL; + playerstarts[i] = bluectfstarts[i] = redctfstarts[i] = NULL; + + for (i = 0; i < MAX_DM_STARTS; i++) + deathmatchstarts[i] = NULL; for (i = 0; i < 2; i++) skyboxmo[i] = NULL; From 4e839596a1c8dd677bc94f9aad1a0f3e74e84955 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Sun, 14 Jul 2019 14:55:04 -0400 Subject: [PATCH 081/128] Fix crash with GME sounds when being freed --- src/sdl/mixer_sound.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 045e82b15..a1319dbec 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -362,7 +362,7 @@ void *I_GetSfx(sfxinfo_t *sfx) gme_track_info(emu, &info, 0); len = (info->play_length * 441 / 10) << 2; - mem = malloc(len); + mem = Z_Malloc(len, PU_SOUND, 0); gme_play(emu, len >> 1, mem); gme_free_info(info); gme_delete(emu); @@ -435,7 +435,7 @@ void *I_GetSfx(sfxinfo_t *sfx) gme_track_info(emu, &info, 0); len = (info->play_length * 441 / 10) << 2; - mem = malloc(len); + mem = Z_Malloc(len, PU_SOUND, 0); gme_play(emu, len >> 1, mem); gme_free_info(info); gme_delete(emu); From f6842a80b462ff9ec0c7a58fd598dc94a0d3f2e1 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 14 Jul 2019 21:58:48 +0100 Subject: [PATCH 082/128] Fixes for menus: * add gamestate != GS_TIMEATTACK checks to prevent Record Attack or NiGHTS Mode losing their backgrounds * increase bgname to 9 to include the extra NULL byte? (is this a good idea actually) * make M_IterateMenuTree ignore menu levels without a menutype value --- src/f_finale.c | 2 +- src/f_finale.h | 2 +- src/m_menu.c | 8 +++++--- src/m_menu.h | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index 27c9ebd68..134bc9fcc 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -67,7 +67,7 @@ static INT32 menuanimtimer; // Title screen: background animation timing mobj_t *titlemapcameraref = NULL; // menu presentation state -char curbgname[8]; +char curbgname[9]; SINT8 curfadevalue; boolean curhidepics; INT32 curbgcolor; diff --git a/src/f_finale.h b/src/f_finale.h index c0c6360c3..663a45412 100644 --- a/src/f_finale.h +++ b/src/f_finale.h @@ -84,7 +84,7 @@ typedef enum extern UINT8 titlemapinaction; extern mobj_t *titlemapcameraref; -extern char curbgname[8]; +extern char curbgname[9]; extern SINT8 curfadevalue; extern boolean curhidepics; extern INT32 curbgcolor; diff --git a/src/m_menu.c b/src/m_menu.c index dca2e552d..53e0182fd 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2247,6 +2247,8 @@ static INT32 M_IterateMenuTree(menutree_iterator itfunc, void *input) { bitmask = ((1 << MENUBITS) - 1) << (MENUBITS*i); menutype = (activeMenuId & bitmask) >> (MENUBITS*i); + if (!menutype) + continue; if (itfunc(menutype, i, &retval, &input, false)) break; } @@ -2300,7 +2302,7 @@ static boolean MIT_SetCurBackground(UINT32 menutype, INT32 level, INT32 *retval, curbgyspeed = menupres[menutype].titlescrollyspeed != INT32_MAX ? menupres[menutype].titlescrollyspeed : titlescrollyspeed; return true; } - else if (menupres[menutype].bghide && titlemapinaction) // hide the background + else if (gamestate != GS_TIMEATTACK && menupres[menutype].bghide && titlemapinaction) // hide the background { curbghide = true; return true; @@ -2309,7 +2311,7 @@ static boolean MIT_SetCurBackground(UINT32 menutype, INT32 level, INT32 *retval, { if (M_GetYoungestChildMenu() == MN_SP_PLAYER || !defaultname || !defaultname[0]) curbgcolor = 31; - else if (titlemapinaction) // hide the background by default in titlemap + else if (gamestate != GS_TIMEATTACK && titlemapinaction) // hide the background by default in titlemap curbghide = true; else { @@ -2469,7 +2471,7 @@ static void M_HandleMenuPresState(menu_t *newMenu) curbgcolor = -1; curbgxspeed = titlescrollxspeed; curbgyspeed = titlescrollyspeed; - curbghide = true; + curbghide = (gamestate != GS_TIMEATTACK); // show in time attack, hide in other menus // don't do the below during the in-game menus if (gamestate != GS_TITLESCREEN && gamestate != GS_TIMEATTACK) diff --git a/src/m_menu.h b/src/m_menu.h index 04146ebdc..06631dc39 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -123,7 +123,7 @@ typedef enum typedef struct { - char bgname[8]; // name for background gfx lump; lays over titlemap if this is set + char bgname[9]; // name for background gfx lump; lays over titlemap if this is set SINT8 hidetitlepics; // hide title gfx per menu; -1 means undefined, inherits global setting INT32 titlescrollxspeed; // background gfx scroll per menu; inherits global setting INT32 titlescrollyspeed; // y scroll From a1e6f5bdb3406e578c5082908a03b15b592e5450 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 14 Jul 2019 22:28:19 +0100 Subject: [PATCH 083/128] remove some of the GS_TIMEATTACK hacks I added because I now realise I can just turn titlemapinaction off when entering the menus \o/ --- src/m_menu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 53e0182fd..932df65fe 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2302,7 +2302,7 @@ static boolean MIT_SetCurBackground(UINT32 menutype, INT32 level, INT32 *retval, curbgyspeed = menupres[menutype].titlescrollyspeed != INT32_MAX ? menupres[menutype].titlescrollyspeed : titlescrollyspeed; return true; } - else if (gamestate != GS_TIMEATTACK && menupres[menutype].bghide && titlemapinaction) // hide the background + else if (menupres[menutype].bghide && titlemapinaction) // hide the background { curbghide = true; return true; @@ -2311,7 +2311,7 @@ static boolean MIT_SetCurBackground(UINT32 menutype, INT32 level, INT32 *retval, { if (M_GetYoungestChildMenu() == MN_SP_PLAYER || !defaultname || !defaultname[0]) curbgcolor = 31; - else if (gamestate != GS_TIMEATTACK && titlemapinaction) // hide the background by default in titlemap + else if (titlemapinaction) // hide the background by default in titlemap curbghide = true; else { @@ -8236,6 +8236,7 @@ static void M_TimeAttack(INT32 choice) M_PatchSkinNameTable(); G_SetGamestate(GS_TIMEATTACK); // do this before M_SetupNextMenu so that menu meta state knows that we're switching + titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please M_SetupNextMenu(&SP_TimeAttackDef); if (!M_CanShowLevelInList(cv_nextmap.value-1, -1) && levelselect.rows[0].maplist[0]) CV_SetValue(&cv_nextmap, levelselect.rows[0].maplist[0]); @@ -8417,6 +8418,7 @@ static void M_NightsAttack(INT32 choice) G_SetGamestate(GS_TIMEATTACK); // do this before M_SetupNextMenu so that menu meta state knows that we're switching M_SetupNextMenu(&SP_NightsAttackDef); + titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please if (!M_CanShowLevelInList(cv_nextmap.value-1, -1) && levelselect.rows[0].maplist[0]) CV_SetValue(&cv_nextmap, levelselect.rows[0].maplist[0]); else From d44a8ab78ef5869575f545184f5147b39117cd20 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 14 Jul 2019 22:36:14 +0100 Subject: [PATCH 084/128] Slightly unrelated tweak: bghide && titlemapinaction clearly takes precedence over bgname if both are present, so reorder these if statement blocks --- src/m_menu.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 932df65fe..adf2e0cdb 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2295,18 +2295,18 @@ static boolean MIT_SetCurBackground(UINT32 menutype, INT32 level, INT32 *retval, curbgcolor = menupres[menutype].bgcolor; return true; } - else if (menupres[menutype].bgname[0] && (!menupres[menutype].bghide || !titlemapinaction)) + else if (menupres[menutype].bghide && titlemapinaction) // hide the background + { + curbghide = true; + return true; + } + else if (menupres[menutype].bgname[0]) { strncpy(curbgname, menupres[menutype].bgname, 8); curbgxspeed = menupres[menutype].titlescrollxspeed != INT32_MAX ? menupres[menutype].titlescrollxspeed : titlescrollxspeed; curbgyspeed = menupres[menutype].titlescrollyspeed != INT32_MAX ? menupres[menutype].titlescrollyspeed : titlescrollyspeed; return true; } - else if (menupres[menutype].bghide && titlemapinaction) // hide the background - { - curbghide = true; - return true; - } else if (!level) { if (M_GetYoungestChildMenu() == MN_SP_PLAYER || !defaultname || !defaultname[0]) From 5ef4dda9b933e4a117582c78b259300f52a5ab27 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Mon, 15 Jul 2019 20:25:57 +0100 Subject: [PATCH 085/128] Instead of ignoring blank menutypes in M_IterateMenuTree, ignore them in the MIT_ functions instead. (I'm doing this because MIT_GetMenuAtLevel appears to actually care about whether menutype is zero or not unlike the others; I don't want to break the code designed around that) --- src/m_menu.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index adf2e0cdb..d9d3a6ba0 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2247,8 +2247,6 @@ static INT32 M_IterateMenuTree(menutree_iterator itfunc, void *input) { bitmask = ((1 << MENUBITS) - 1) << (MENUBITS*i); menutype = (activeMenuId & bitmask) >> (MENUBITS*i); - if (!menutype) - continue; if (itfunc(menutype, i, &retval, &input, false)) break; } @@ -2290,6 +2288,9 @@ static boolean MIT_SetCurBackground(UINT32 menutype, INT32 level, INT32 *retval, (void)retval; (void)fromoldest; + if (!menutype) // if there's nothing in this level, do nothing + return false; + if (menupres[menutype].bgcolor >= 0) { curbgcolor = menupres[menutype].bgcolor; @@ -2330,6 +2331,9 @@ static boolean MIT_ChangeMusic(UINT32 menutype, INT32 level, INT32 *retval, void (void)retval; (void)fromoldest; + if (!menutype) // if there's nothing in this level, do nothing + return false; + if (menupres[menutype].musname[0]) { S_ChangeMusic(menupres[menutype].musname, menupres[menutype].mustrack, menupres[menutype].muslooping); @@ -2354,6 +2358,9 @@ static boolean MIT_SetCurFadeValue(UINT32 menutype, INT32 level, INT32 *retval, (void)retval; (void)fromoldest; + if (!menutype) // if there's nothing in this level, do nothing + return false; + if (menupres[menutype].fadestrength >= 0) { curfadevalue = (menupres[menutype].fadestrength % 32); @@ -2370,6 +2377,9 @@ static boolean MIT_SetCurHideTitlePics(UINT32 menutype, INT32 level, INT32 *retv (void)retval; (void)fromoldest; + if (!menutype) // if there's nothing in this level, do nothing + return false; + if (menupres[menutype].hidetitlepics >= 0) { curhidepics = menupres[menutype].hidetitlepics; From 438c4d1d51502c7cc81bb6379ac58988e47422cb Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 17 Jul 2019 21:33:18 +0100 Subject: [PATCH 086/128] Fix spindash being broken in quicksand # Conflicts: # src/p_mobj.c # src/p_user.c --- src/p_local.h | 2 +- src/p_mobj.c | 2 +- src/p_user.c | 160 ++++++++++++++++++++++++++------------------------ 3 files changed, 84 insertions(+), 80 deletions(-) diff --git a/src/p_local.h b/src/p_local.h index cb8f95533..3c62d6277 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -142,7 +142,7 @@ boolean P_IsObjectOnGround(mobj_t *mo); boolean P_IsObjectOnGroundIn(mobj_t *mo, sector_t *sec); boolean P_InSpaceSector(mobj_t *mo); boolean P_InQuicksand(mobj_t *mo); -boolean P_PlayerHitFloor(player_t *player); +boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff); void P_SetObjectMomZ(mobj_t *mo, fixed_t value, boolean relative); void P_RestoreMusic(player_t *player); diff --git a/src/p_mobj.c b/src/p_mobj.c index 9a6e0f2bb..a7ab4e30d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3047,7 +3047,7 @@ static void P_PlayerZMovement(mobj_t *mo) } } - clipmomz = P_PlayerHitFloor(mo->player); + clipmomz = P_PlayerHitFloor(mo->player, true); if (!(mo->player->pflags & PF_SPINNING) && mo->player->powers[pw_carry] != CR_NIGHTSMODE) mo->player->pflags &= ~PF_STARTDASH; diff --git a/src/p_user.c b/src/p_user.c index 6761d567d..3427ed168 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2007,7 +2007,7 @@ boolean P_InSpaceSector(mobj_t *mo) // Returns true if you are in space // // Handles player hitting floor surface. // Returns whether to clip momz. -boolean P_PlayerHitFloor(player_t *player) +boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) { boolean clipmomz; @@ -2015,92 +2015,96 @@ boolean P_PlayerHitFloor(player_t *player) if ((clipmomz = !(P_CheckDeathPitCollide(player->mo))) && player->mo->health && !player->spectator) { - if ((player->charability2 == CA2_SPINDASH) && !(player->pflags & PF_THOKKED) && (player->cmd.buttons & BT_USE) && (FixedHypot(player->mo->momx, player->mo->momy) > (5*player->mo->scale))) + if (dorollstuff) { - player->pflags |= PF_SPINNING; - P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); - S_StartSound(player->mo, sfx_spin); + if ((player->charability2 == CA2_SPINDASH) && !(player->pflags & PF_THOKKED) && (player->cmd.buttons & BT_USE) && (FixedHypot(player->mo->momx, player->mo->momy) > (5*player->mo->scale))) + { + player->pflags |= PF_SPINNING; + P_SetPlayerMobjState(player->mo, S_PLAY_ROLL); + S_StartSound(player->mo, sfx_spin); + } + else + player->pflags &= ~PF_SPINNING; } - else + + if (player->pflags & PF_GLIDING) // ground gliding { - player->pflags &= ~PF_SPINNING; - - if (player->pflags & PF_GLIDING) // ground gliding - { + if (!player->skidtime) player->skidtime = TICRATE; - player->mo->tics = -1; - } - else if (player->charability2 == CA2_MELEE && (player->panim == PA_ABILITY2 && player->mo->state-states != S_PLAY_MELEE_LANDING)) + player->mo->tics = -1; + } + else if (player->charability2 == CA2_MELEE && (player->panim == PA_ABILITY2 && player->mo->state-states != S_PLAY_MELEE_LANDING)) + { + mobjtype_t type = player->revitem; + P_SetPlayerMobjState(player->mo, S_PLAY_MELEE_LANDING); + player->mo->tics = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS; + S_StartSound(player->mo, sfx_s3k8b); + player->pflags |= PF_FULLSTASIS; + + // hearticles + if (type) { - mobjtype_t type = player->revitem; - P_SetPlayerMobjState(player->mo, S_PLAY_MELEE_LANDING); - player->mo->tics = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS; - S_StartSound(player->mo, sfx_s3k8b); - player->pflags |= PF_FULLSTASIS; - - // hearticles - if (type) + UINT8 i = 0; + angle_t throwang = -(2*ANG30); + fixed_t xo = P_ReturnThrustX(player->mo, player->drawangle, 16*player->mo->scale); + fixed_t yo = P_ReturnThrustY(player->mo, player->drawangle, 16*player->mo->scale); + fixed_t zo = 6*player->mo->scale; + fixed_t mu = FixedMul(player->maxdash, player->mo->scale); + fixed_t mu2 = FixedHypot(player->mo->momx, player->mo->momy); + fixed_t ev; + mobj_t *missile; + if (mu2 < mu) + mu2 = mu; + ev = (50*FRACUNIT - (mu/25))/50; + while (i < 5) { - UINT8 i = 0; - angle_t throwang = -(2*ANG30); - fixed_t xo = P_ReturnThrustX(player->mo, player->drawangle, 16*player->mo->scale); - fixed_t yo = P_ReturnThrustY(player->mo, player->drawangle, 16*player->mo->scale); - fixed_t zo = 6*player->mo->scale; - fixed_t mu = FixedMul(player->maxdash, player->mo->scale); - fixed_t mu2 = FixedHypot(player->mo->momx, player->mo->momy); - fixed_t ev; - mobj_t *missile; - if (mu2 < mu) - mu2 = mu; - ev = (50*FRACUNIT - (mu/25))/50; - while (i < 5) - { - missile = P_SpawnMobjFromMobj(player->mo, xo, yo, zo, type); - P_SetTarget(&missile->target, player->mo); - missile->angle = throwang + player->drawangle; - P_Thrust(missile, player->drawangle + ANGLE_90, - P_ReturnThrustY(missile, throwang, mu)); // side to side component - P_Thrust(missile, player->drawangle, mu2); // forward component - P_SetObjectMomZ(missile, (4 + ((i&1)<<1))*FRACUNIT, true); - missile->fuse = TICRATE/2; - missile->extravalue2 = ev; + missile = P_SpawnMobjFromMobj(player->mo, xo, yo, zo, type); + P_SetTarget(&missile->target, player->mo); + missile->angle = throwang + player->drawangle; + P_Thrust(missile, player->drawangle + ANGLE_90, + P_ReturnThrustY(missile, throwang, mu)); // side to side component + P_Thrust(missile, player->drawangle, mu2); // forward component + P_SetObjectMomZ(missile, (4 + ((i&1)<<1))*FRACUNIT, true); + missile->fuse = TICRATE/2; + missile->extravalue2 = ev; - i++; - throwang += ANG30; - } - if (mobjinfo[type].seesound) - S_StartSound(missile, missile->info->seesound); + i++; + throwang += ANG30; } + if (mobjinfo[type].seesound) + S_StartSound(missile, missile->info->seesound); } - else if (player->pflags & PF_JUMPED || !(player->pflags & PF_SPINNING) + } + else if (player->charability2 == CA2_GUNSLINGER && player->panim == PA_ABILITY2) + ; + else if (player->pflags & PF_JUMPED || !(player->pflags & PF_SPINNING) || player->powers[pw_tailsfly] || player->mo->state-states == S_PLAY_FLY_TIRED) + { + if (player->cmomx || player->cmomy) { - if (player->cmomx || player->cmomy) - { - if (player->charflags & SF_DASHMODE && player->dashmode >= 3*TICRATE && player->panim != PA_DASH) - P_SetPlayerMobjState(player->mo, S_PLAY_DASH); - else if (player->speed >= FixedMul(player->runspeed, player->mo->scale) - && (player->panim != PA_RUN || player->mo->state-states == S_PLAY_FLOAT_RUN)) - P_SetPlayerMobjState(player->mo, S_PLAY_RUN); - else if ((player->rmomx || player->rmomy) - && (player->panim != PA_WALK || player->mo->state-states == S_PLAY_FLOAT)) - P_SetPlayerMobjState(player->mo, S_PLAY_WALK); - else if (!player->rmomx && !player->rmomy && player->panim != PA_IDLE) - P_SetPlayerMobjState(player->mo, S_PLAY_STND); - } - else - { - if (player->charflags & SF_DASHMODE && player->dashmode >= 3*TICRATE && player->panim != PA_DASH) - P_SetPlayerMobjState(player->mo, S_PLAY_DASH); - else if (player->speed >= FixedMul(player->runspeed, player->mo->scale) - && (player->panim != PA_RUN || player->mo->state-states == S_PLAY_FLOAT_RUN)) - P_SetPlayerMobjState(player->mo, S_PLAY_RUN); - else if ((player->mo->momx || player->mo->momy) - && (player->panim != PA_WALK || player->mo->state-states == S_PLAY_FLOAT)) - P_SetPlayerMobjState(player->mo, S_PLAY_WALK); - else if (!player->mo->momx && !player->mo->momy && player->panim != PA_IDLE) - P_SetPlayerMobjState(player->mo, S_PLAY_STND); - } + if (player->charflags & SF_DASHMODE && player->dashmode >= 3*TICRATE && player->panim != PA_DASH) + P_SetPlayerMobjState(player->mo, S_PLAY_DASH); + else if (player->speed >= FixedMul(player->runspeed, player->mo->scale) + && (player->panim != PA_RUN || player->mo->state-states == S_PLAY_FLOAT_RUN)) + P_SetPlayerMobjState(player->mo, S_PLAY_RUN); + else if ((player->rmomx || player->rmomy) + && (player->panim != PA_WALK || player->mo->state-states == S_PLAY_FLOAT)) + P_SetPlayerMobjState(player->mo, S_PLAY_WALK); + else if (!player->rmomx && !player->rmomy && player->panim != PA_IDLE) + P_SetPlayerMobjState(player->mo, S_PLAY_STND); + } + else + { + if (player->charflags & SF_DASHMODE && player->dashmode >= 3*TICRATE && player->panim != PA_DASH) + P_SetPlayerMobjState(player->mo, S_PLAY_DASH); + else if (player->speed >= FixedMul(player->runspeed, player->mo->scale) + && (player->panim != PA_RUN || player->mo->state-states == S_PLAY_FLOAT_RUN)) + P_SetPlayerMobjState(player->mo, S_PLAY_RUN); + else if ((player->mo->momx || player->mo->momy) + && (player->panim != PA_WALK || player->mo->state-states == S_PLAY_FLOAT)) + P_SetPlayerMobjState(player->mo, S_PLAY_WALK); + else if (!player->mo->momx && !player->mo->momy && player->panim != PA_IDLE) + P_SetPlayerMobjState(player->mo, S_PLAY_STND); } } @@ -2537,7 +2541,7 @@ static void P_CheckQuicksand(player_t *player) player->mo->z = ceilingheight - player->mo->height; if (player->mo->momz <= 0) - P_PlayerHitFloor(player); + P_PlayerHitFloor(player, false); } else { @@ -2549,7 +2553,7 @@ static void P_CheckQuicksand(player_t *player) player->mo->z = floorheight; if (player->mo->momz >= 0) - P_PlayerHitFloor(player); + P_PlayerHitFloor(player, false); } friction = abs(rover->master->v1->y - rover->master->v2->y)>>6; From 385d34e67ec7780d7fb57d2c7e00a78e4e04f56b Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 25 Sep 2017 20:35:04 +0100 Subject: [PATCH 087/128] * Make busting a FOF through any in-game means (or not providing a target sector to EV_CrumbleChain) bust all FOFs with the same control sector. * Make CA2_GUNSLINGER not get overridden by being in quicksand. --- src/lua_baselib.c | 4 ++-- src/p_floor.c | 46 +++++++++++++++++++++++++++++++++------------- src/p_mobj.c | 4 ++-- src/p_user.c | 4 ++-- 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 1d69b238b..712bc4045 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2051,8 +2051,8 @@ static int lib_evCrumbleChain(lua_State *L) ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR)); NOHUD INLEVEL - if (!sec) - return LUA_ErrInvalid(L, "sector_t"); + /*if (!sec) + return LUA_ErrInvalid(L, "sector_t");*/ if (!rover) return LUA_ErrInvalid(L, "ffloor_t"); EV_CrumbleChain(sec, rover); diff --git a/src/p_floor.c b/src/p_floor.c index c01e568d0..0b20a3b17 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -3029,20 +3029,40 @@ INT32 EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed) void EV_CrumbleChain(sector_t *sec, ffloor_t *rover) { - size_t i; - size_t leftmostvertex = 0, rightmostvertex = 0; - size_t topmostvertex = 0, bottommostvertex = 0; - fixed_t leftx, rightx; - fixed_t topy, bottomy; - fixed_t topz, bottomz; - fixed_t widthfactor = FRACUNIT, heightfactor = FRACUNIT; - fixed_t a, b, c; - mobjtype_t type = MT_ROCKCRUMBLE1; - fixed_t spacing = (32<master->frontsector + sector_t *controlsec = rover->master->frontsector; + + if (sec == NULL) + { + if (controlsec->numattached) + { + for (i = 0; i < controlsec->numattached; i++) + { + sec = §ors[controlsec->attached[i]]; + if (!sec->ffloors) + continue; + + for (rover = sec->ffloors; rover; rover = rover->next) + { + if (rover->master->frontsector == controlsec) + EV_CrumbleChain(sec, rover); + } + } + } + return; + } + + leftmostvertex = rightmostvertex = topmostvertex = bottommostvertex = 0; + widthfactor = heightfactor = FRACUNIT; + spacing = (32<tag != 0) { diff --git a/src/p_mobj.c b/src/p_mobj.c index a7ab4e30d..6cfad95a0 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1784,7 +1784,7 @@ static void P_PushableCheckBustables(mobj_t *mo) continue; } - EV_CrumbleChain(node->m_sector, rover); + EV_CrumbleChain(NULL, rover); // node->m_sector // Run a linedef executor?? if (rover->master->flags & ML_EFFECT5) @@ -3129,7 +3129,7 @@ nightsdone: { // DO THE MARIO! if (rover->flags & FF_SHATTERBOTTOM) // Brick block! - EV_CrumbleChain(node->m_sector, rover); + EV_CrumbleChain(NULL, rover); // node->m_sector else // Question block! EV_MarioBlock(rover, node->m_sector, mo); } diff --git a/src/p_user.c b/src/p_user.c index 3427ed168..706260a61 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2033,7 +2033,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) player->skidtime = TICRATE; player->mo->tics = -1; } - else if (player->charability2 == CA2_MELEE && (player->panim == PA_ABILITY2 && player->mo->state-states != S_PLAY_MELEE_LANDING)) + else if (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2 && player->mo->state-states != S_PLAY_MELEE_LANDING) { mobjtype_t type = player->revitem; P_SetPlayerMobjState(player->mo, S_PLAY_MELEE_LANDING); @@ -2324,7 +2324,7 @@ static void P_CheckBustableBlocks(player_t *player) //if (metalrecording) // G_RecordBustup(rover); - EV_CrumbleChain(node->m_sector, rover); + EV_CrumbleChain(NULL, rover); // node->m_sector // Run a linedef executor?? if (rover->master->flags & ML_EFFECT5) From 82acf2de6b8aa607cf84ce991f53b4386a92568f Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 17 Jul 2019 23:24:44 +0100 Subject: [PATCH 088/128] Fix Knuckles-in-quicksand messup. --- src/p_user.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 706260a61..9c4e5b6b9 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2029,9 +2029,13 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) if (player->pflags & PF_GLIDING) // ground gliding { - if (!player->skidtime) + if (dorollstuff) + { player->skidtime = TICRATE; - player->mo->tics = -1; + player->mo->tics = -1; + } + else + player->pflags &= ~PF_GLIDING; } else if (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2 && player->mo->state-states != S_PLAY_MELEE_LANDING) { From 1d5e8e249e2195ea4e0c9c6d7a971bd494261aee Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 17 Jul 2019 23:25:49 +0100 Subject: [PATCH 089/128] Successfully cause landing events when the ground moves up to hit you, as opposed to just when you move down to the ground. --- src/p_map.c | 8 +++++++- src/p_user.c | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/p_map.c b/src/p_map.c index e78dd1e84..767370587 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2820,7 +2820,7 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y) static boolean P_ThingHeightClip(mobj_t *thing) { boolean floormoved; - fixed_t oldfloorz = thing->floorz; + fixed_t oldfloorz = thing->floorz, oldz = thing->z; ffloor_t *oldfloorrover = thing->floorrover; ffloor_t *oldceilingrover = thing->ceilingrover; boolean onfloor = P_IsObjectOnGround(thing);//(thing->z <= thing->floorz); @@ -2879,6 +2879,12 @@ static boolean P_ThingHeightClip(mobj_t *thing) thing->z = thing->ceilingz - thing->height; } + if (thing->z != oldz) + { + if (thing->player) + P_PlayerHitFloor(thing->player, false); + } + // debug: be sure it falls to the floor thing->eflags &= ~MFE_ONGROUND; diff --git a/src/p_user.c b/src/p_user.c index 9c4e5b6b9..1e293d24c 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2069,6 +2069,7 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) P_ReturnThrustY(missile, throwang, mu)); // side to side component P_Thrust(missile, player->drawangle, mu2); // forward component P_SetObjectMomZ(missile, (4 + ((i&1)<<1))*FRACUNIT, true); + missile->momz += player->mo->pmomz; missile->fuse = TICRATE/2; missile->extravalue2 = ev; @@ -4418,6 +4419,10 @@ static void P_DoSpinAbility(player_t *player, ticcmd_t *cmd) { player->mo->z += P_MobjFlip(player->mo); P_SetObjectMomZ(player->mo, player->mindash, false); + if (P_MobjFlip(player->mo)*player->mo->pmomz > 0) + player->mo->momz += player->mo->pmomz; // Add the platform's momentum to your jump. + else + player->mo->pmomz = 0; if (player->mo->eflags & MFE_UNDERWATER) player->mo->momz >>= 1; #if 0 From 64517a136229c251f3e6a94678909a94ff02b1b2 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 18 Jul 2019 00:16:01 +0100 Subject: [PATCH 090/128] Fix !150, too --- src/p_floor.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/p_floor.c b/src/p_floor.c index 0b20a3b17..7887dc530 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -719,6 +719,8 @@ void T_ContinuousFalling(levelspecthink_t *faller) } } + P_CheckSector(faller->sector, false); // you might think this is irrelevant. you would be wrong + faller->sector->floorspeed = faller->speed*faller->direction; faller->sector->ceilspeed = 42; faller->sector->moved = true; From 6c2ef839c1cf3b6aca7797d76a73e09c273b907b Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Thu, 18 Jul 2019 22:42:46 -0400 Subject: [PATCH 091/128] New award rings linedef executor --- src/p_spec.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/p_spec.c b/src/p_spec.c index 3cd0461e2..48079b9e5 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3916,6 +3916,21 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) F_StartTextPrompt(promptnum, pagenum, mo, runpostexec ? postexectag : 0, blockcontrols, freezerealtime); } } + case 460: // Award rings + { + INT16 rings = (sides[line->sidenum[0]].textureoffset>>FRACBITS); + INT16 delay = (sides[line->sidenum[0]].rowoffset>>FRACBITS); + if (mo && mo->player) + { + if (delay > 0) + { + if (!(leveltime % (delay*TICRATE))) + P_GivePlayerRings(mo->player, rings); + } + else + P_GivePlayerRings(mo->player, rings); + } + } break; #ifdef POLYOBJECTS From 0f8c046c6f1a0d408d13173905fc2c40506e558c Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 20 Jul 2019 16:30:30 +0100 Subject: [PATCH 092/128] On second thoughts I'll go back to 8 for length in these variables, since as far as I can tell the code doesn't need it to be longer anyway --- src/f_finale.c | 2 +- src/f_finale.h | 2 +- src/m_menu.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index 134bc9fcc..27c9ebd68 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -67,7 +67,7 @@ static INT32 menuanimtimer; // Title screen: background animation timing mobj_t *titlemapcameraref = NULL; // menu presentation state -char curbgname[9]; +char curbgname[8]; SINT8 curfadevalue; boolean curhidepics; INT32 curbgcolor; diff --git a/src/f_finale.h b/src/f_finale.h index 663a45412..c0c6360c3 100644 --- a/src/f_finale.h +++ b/src/f_finale.h @@ -84,7 +84,7 @@ typedef enum extern UINT8 titlemapinaction; extern mobj_t *titlemapcameraref; -extern char curbgname[9]; +extern char curbgname[8]; extern SINT8 curfadevalue; extern boolean curhidepics; extern INT32 curbgcolor; diff --git a/src/m_menu.h b/src/m_menu.h index 06631dc39..04146ebdc 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -123,7 +123,7 @@ typedef enum typedef struct { - char bgname[9]; // name for background gfx lump; lays over titlemap if this is set + char bgname[8]; // name for background gfx lump; lays over titlemap if this is set SINT8 hidetitlepics; // hide title gfx per menu; -1 means undefined, inherits global setting INT32 titlescrollxspeed; // background gfx scroll per menu; inherits global setting INT32 titlescrollyspeed; // y scroll From 60ffef9830f82b4ac948e13e504da7d4906cc9c0 Mon Sep 17 00:00:00 2001 From: Steel Titanium Date: Wed, 24 Jul 2019 21:18:07 -0400 Subject: [PATCH 093/128] More simplified code Also delay is in tics, per MS' request. --- src/p_spec.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index 48079b9e5..f712f4b23 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3917,20 +3917,15 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } } case 460: // Award rings - { - INT16 rings = (sides[line->sidenum[0]].textureoffset>>FRACBITS); - INT16 delay = (sides[line->sidenum[0]].rowoffset>>FRACBITS); - if (mo && mo->player) { - if (delay > 0) + INT16 rings = (sides[line->sidenum[0]].textureoffset>>FRACBITS); + tic_t delay = (sides[line->sidenum[0]].rowoffset>>FRACBITS); + if (mo && mo->player) { - if (!(leveltime % (delay*TICRATE))) + if (delay <= 0 || !(leveltime % (delay))) P_GivePlayerRings(mo->player, rings); } - else - P_GivePlayerRings(mo->player, rings); } - } break; #ifdef POLYOBJECTS From 063e350c63b244a97bd0c12ebb017267883bc3ab Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 28 Jul 2019 00:32:57 +0100 Subject: [PATCH 094/128] A good and bad ending cutscene now exist. Also: * SPR2_XTRA - instead of defining lumpnames in S_SKIN, those kinds of assets can just be bundled into the spriteset. Required for ending cutscene stuff, I guess, but also done for HUD life icon and character select image (aside from Sonic&Tails, still SOC'd in). * Minor oversights in SPR2 support corrected. * Better evaluation, featuring ending assets. * Intro has warping-in blackrock, reusing ending assets. * Cutscene text now supports lowercase (intro and custom). * Disable the asset-fucking "gamma correction" I put in over two years ago when implementing colour cube. (This is the only thing I could move into another branch if you MUST, but it's basically invisble in the diff so w/e.) * Don't blank the screen if the top left pixel of a screen-covering patch is transparent. (Checked via nonzero topdelta for first column) Bugs: * OPENGL ONLY: The first ~20 frames of both endings are fucked. A little help here? Might be HWR_DrawFadeFill's fault, which I just created. OR it could be in f_finale, but I doubt it, since it doesn't appear in Software. --- src/console.c | 2 +- src/d_main.c | 6 + src/dehacked.c | 4 + src/f_finale.c | 750 ++++++++++++++++++++++++++++++++++++++--- src/f_finale.h | 10 +- src/f_wipe.c | 2 + src/g_game.c | 21 +- src/g_state.h | 4 +- src/hardware/hw_draw.c | 305 +++++++++++++++-- src/hardware/hw_main.h | 1 + src/hardware/hw_md2.c | 11 +- src/hu_stuff.c | 2 +- src/info.c | 12 +- src/info.h | 1 + src/lua_infolib.c | 25 +- src/lua_skinlib.c | 24 -- src/m_menu.c | 37 +- src/m_menu.h | 1 + src/p_setup.c | 2 +- src/r_things.c | 48 ++- src/r_things.h | 1 - src/s_sound.c | 12 +- src/st_stuff.c | 24 +- src/st_stuff.h | 2 +- src/v_video.c | 336 ++++++++++++++++-- src/v_video.h | 2 + 26 files changed, 1445 insertions(+), 200 deletions(-) diff --git a/src/console.c b/src/console.c index c1c5557b9..09a6cab45 100644 --- a/src/console.c +++ b/src/console.c @@ -1608,7 +1608,7 @@ void CON_Drawer(void) if (con_curlines > 0) CON_DrawConsole(); else if (gamestate == GS_LEVEL - || gamestate == GS_INTERMISSION || gamestate == GS_CUTSCENE + || gamestate == GS_INTERMISSION || gamestate == GS_ENDING || gamestate == GS_CUTSCENE || gamestate == GS_CREDITS || gamestate == GS_EVALUATION) CON_DrawHudlines(); } diff --git a/src/d_main.c b/src/d_main.c index c7d709aec..32e874f07 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -310,6 +310,12 @@ static void D_Display(void) wipe = true; break; + case GS_ENDING: + F_EndingDrawer(); + HU_Erase(); + HU_Drawer(); + break; + case GS_CUTSCENE: F_CutsceneDrawer(); HU_Erase(); diff --git a/src/dehacked.c b/src/dehacked.c index 31c17f188..b4e00de87 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -517,7 +517,9 @@ static void readfreeslots(MYFILE *f) continue; // Copy in the spr2 name and increment free_spr2. if (free_spr2 < NUMPLAYERSPRITES) { + CONS_Printf("Sprite SPR2_%s allocated.\n",word); strncpy(spr2names[free_spr2],word,4); + spr2defaults[free_spr2] = 0; spr2names[free_spr2++][4] = 0; } else CONS_Alert(CONS_WARNING, "Ran out of free SPR2 slots!\n"); @@ -1108,6 +1110,7 @@ static void readlevelheader(MYFILE *f, INT32 num) if (fastcmp(word2, "TITLE")) i = 1100; else if (fastcmp(word2, "EVALUATION")) i = 1101; else if (fastcmp(word2, "CREDITS")) i = 1102; + else if (fastcmp(word2, "ENDING")) i = 1103; else // Support using the actual map name, // i.e., Nextlevel = AB, Nextlevel = FZ, etc. @@ -9493,6 +9496,7 @@ static inline int lib_freeslot(lua_State *L) { CONS_Printf("Sprite SPR2_%s allocated.\n",word); strncpy(spr2names[free_spr2],word,4); + spr2defaults[free_spr2] = 0; spr2names[free_spr2++][4] = 0; } else CONS_Alert(CONS_WARNING, "Ran out of free SPR2 slots!\n"); diff --git a/src/f_finale.c b/src/f_finale.c index 27c9ebd68..bac50dcec 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -14,6 +14,7 @@ #include "doomdef.h" #include "doomstat.h" #include "d_main.h" +#include "d_netcmd.h" #include "f_finale.h" #include "g_game.h" #include "hu_stuff.h" @@ -36,6 +37,7 @@ #include "p_setup.h" #include "st_stuff.h" // hud hiding #include "fastcmp.h" +#include "console.h" #ifdef HAVE_BLUA #include "lua_hud.h" @@ -53,7 +55,6 @@ static INT32 continuetime; // Short delay when continuing static tic_t animtimer; // Used for some animation timings static INT16 skullAnimCounter; // Prompts: Chevron animation -static INT32 roidtics; // Asteroid spinning static INT32 deplete; static tic_t stoptimer; @@ -95,6 +96,17 @@ static patch_t *ttspop5; static patch_t *ttspop6; static patch_t *ttspop7; +static boolean goodending; +static patch_t *endbrdr[2]; // border - blue, white, pink - where have i seen those colours before? +static patch_t *endbgsp[3]; // nebula, sun, planet +static patch_t *endegrk[2]; // eggrock - replaced midway through good ending +static patch_t *endfwrk[3]; // firework - replaced with skin when good ending +static patch_t *endspkl[3]; // sparkle +static patch_t *endglow[2]; // glow aura - replaced with black rock's midway through good ending +static patch_t *endxpld[4]; // mini explosion +static INT32 sparkloffs[8][3][2]; // seven emerald sparkles + eggrock explosions +static INT32 sparklloop; + // // PROMPT STATE // @@ -230,6 +242,7 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset void F_StartIntro(void) { S_StopMusic(); + S_StopSounds(); if (introtoplay) { @@ -393,7 +406,6 @@ void F_StartIntro(void) intro_scenenum = 0; finalecount = animtimer = skullAnimCounter = stoptimer = 0; - roidtics = BASEVIDWIDTH - 64; timetonext = introscenetime[intro_scenenum]; } @@ -676,11 +688,42 @@ static void F_IntroDrawScene(void) if (intro_scenenum == 4) // The asteroid SPINS! { - if (roidtics >= 0) + if (intro_curtime > 1) { - V_DrawScaledPatch(roidtics, 24, 0, - (patch = W_CachePatchName(va("ROID00%.2d", intro_curtime%35), PU_CACHE))); - W_UnlockCachedPatch(patch); + INT32 worktics = intro_curtime - 1; + INT32 scale = FRACUNIT; + patch_t *rockpat; + UINT8 *colormap = NULL; + patch_t *glow; + INT32 trans = 0; + + INT32 x = ((BASEVIDWIDTH - 64)<= 5) + trans = (worktics-5)>>1; + if (trans < 10) + V_DrawFixedPatch(x, y, scale, trans<type != ev_keydown) @@ -1240,10 +1279,8 @@ boolean F_CreditResponder(event_t *event) // ============ // EVALUATION // ============ -#define INTERVAL 50 +#define INTERVAL (360/7) #define TRANSLEVEL V_80TRANS -static INT32 eemeralds_start; -static boolean drawemblem = false, drawchaosemblem = false; void F_StartGameEvaluation(void) { @@ -1265,17 +1302,18 @@ void F_StartGameEvaluation(void) if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && cursaveslot > 0) G_SaveGame((UINT32)cursaveslot); + goodending = (ALL7EMERALDS(emeralds)); + gameaction = ga_nothing; paused = false; CON_ToggleOff(); - finalecount = 0; + finalecount = -1; } void F_GameEvaluationDrawer(void) { INT32 x, y, i; - const fixed_t radius = 48*FRACUNIT; angle_t fa; INT32 eemeralds_cur; char patchname[7] = "CEMGx0"; @@ -1283,57 +1321,94 @@ void F_GameEvaluationDrawer(void) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // Draw all the good crap here. - if (ALL7EMERALDS(emeralds)) + if (goodending) V_DrawString(114, 16, 0, "GOT THEM ALL!"); else V_DrawString(124, 16, 0, "TRY AGAIN!"); - eemeralds_start++; - eemeralds_cur = eemeralds_start; + if (finalecount > 0) + { + INT32 scale = FRACUNIT; + patch_t *rockpat; + UINT8 *colormap[2] = {NULL, NULL}; + patch_t *glow; + INT32 trans = 0; + + x = (((BASEVIDWIDTH-82)/2)+11)<= 5) + trans = (finalecount-5)>>1; + if (trans < 10) + V_DrawFixedPatch(x, y, scale, trans<>ANGLETOFINESHIFT) & FINEMASK; - x = 160 + FixedInt(FixedMul(FINECOSINE(fa),radius)); - y = 100 + FixedInt(FixedMul(FINESINE(fa),radius)); + x = (BASEVIDWIDTH<<(FRACBITS-1)) + (60*FINECOSINE(fa)); + y = ((BASEVIDHEIGHT+16)<<(FRACBITS-1)) + (60*FINESINE(fa)); + eemeralds_cur += INTERVAL; + if (i & 1) + eemeralds_cur++; patchname[4] = 'A'+(char)i; - if (emeralds & (1<= 360) - eemeralds_start -= 360; - - if (finalecount == 5*TICRATE) - { - if ((!modifiedgame || savemoddata) && !(netgame || multiplayer)) - { - ++timesBeaten; - - if (ALL7EMERALDS(emeralds)) - ++timesBeatenWithEmeralds; - - if (ultimatemode) - ++timesBeatenUltimate; - - if (M_UpdateUnlockablesAndExtraEmblems()) - S_StartSound(NULL, sfx_s3k68); - - G_SaveGameData(); - } + V_DrawFixedPatch(x, y, FRACUNIT, ((emeralds & (1<= 5*TICRATE) { +#if 0 if (drawemblem) V_DrawScaledPatch(120, 192, 0, W_CachePatchName("NWNGA0", PU_CACHE)); if (drawchaosemblem) V_DrawScaledPatch(200, 192, 0, W_CachePatchName("NWNGA0", PU_CACHE)); +#endif V_DrawString(8, 16, V_YELLOWMAP, "Unlocked:"); @@ -1363,10 +1438,579 @@ void F_GameEvaluationTicker(void) { finalecount++; + if (sparklloop) + sparklloop--; + + if (!goodending + && (finalecount == (5*TICRATE)/2 + || finalecount == (7*TICRATE)/2 + || finalecount == ((7*TICRATE)/2)+5)) + { + S_StartSound(NULL, sfx_s3k5c); + sparklloop = 10; + } + + if (finalecount == 5*TICRATE) + { + if ((!modifiedgame || savemoddata) && !(netgame || multiplayer)) + { + ++timesBeaten; + + if (ALL7EMERALDS(emeralds)) + ++timesBeatenWithEmeralds; + + if (ultimatemode) + ++timesBeatenUltimate; + + if (M_UpdateUnlockablesAndExtraEmblems()) + S_StartSound(NULL, sfx_s3k68); + + G_SaveGameData(); + } + } + if (finalecount > 10*TICRATE) F_StartGameEnd(); } +// ========== +// ENDING +// ========== + +void F_StartEnding(void) +{ + G_SetGamestate(GS_ENDING); + wipetypepost = INT16_MAX; + + // Just in case they're open ... somehow + M_ClearMenus(true); + + // Save before the credits sequence. + if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && cursaveslot > 0) + G_SaveGame((UINT32)cursaveslot); + + gameaction = ga_nothing; + paused = false; + CON_ToggleOff(); + S_StopMusic(); // todo: placeholder + S_StopSounds(); + + finalecount = -10; // what? this totally isn't a hack. why are you asking? + + memset(sparkloffs, 0, sizeof(INT32)*8*3*2); + sparklloop = 0; + + endbrdr[1] = W_CachePatchName("ENDBRDR1", PU_LEVEL); + + endegrk[0] = W_CachePatchName("ENDEGRK0", PU_LEVEL); + endegrk[1] = W_CachePatchName("ENDEGRK1", PU_LEVEL); + + endglow[0] = W_CachePatchName("ENDGLOW0", PU_LEVEL); + endglow[1] = W_CachePatchName("ENDGLOW1", PU_LEVEL); + + endbgsp[0] = W_CachePatchName("ENDBGSP0", PU_LEVEL); + endbgsp[1] = W_CachePatchName("ENDBGSP1", PU_LEVEL); + endbgsp[2] = W_CachePatchName("ENDBGSP2", PU_LEVEL); + + endspkl[0] = W_CachePatchName("ENDSPKL0", PU_LEVEL); + endspkl[1] = W_CachePatchName("ENDSPKL1", PU_LEVEL); + endspkl[2] = W_CachePatchName("ENDSPKL2", PU_LEVEL); + + endxpld[0] = W_CachePatchName("ENDXPLD0", PU_LEVEL); + endxpld[1] = W_CachePatchName("ENDXPLD1", PU_LEVEL); + endxpld[2] = W_CachePatchName("ENDXPLD2", PU_LEVEL); + endxpld[3] = W_CachePatchName("ENDXPLD3", PU_LEVEL); + + // so we only need to check once + if ((goodending = ALL7EMERALDS(emeralds))) + { + UINT8 skinnum = players[consoleplayer].skin; + spritedef_t *sprdef; + spriteframe_t *sprframe; + if (skins[skinnum].sprites[SPR2_XTRA].numframes >= 5) + { + sprdef = &skins[skinnum].sprites[SPR2_XTRA]; + // character head, skin specific + sprframe = &sprdef->spriteframes[2]; + endfwrk[0] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); + sprframe = &sprdef->spriteframes[3]; + endfwrk[1] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); + sprframe = &sprdef->spriteframes[4]; + endfwrk[2] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); + } + else // eh, yknow what? too lazy to put MISSINGs here. eggman wins if you don't give your character an ending firework display. + { + endfwrk[0] = W_CachePatchName("ENDFWRK0", PU_LEVEL); + endfwrk[1] = W_CachePatchName("ENDFWRK1", PU_LEVEL); + endfwrk[2] = W_CachePatchName("ENDFWRK2", PU_LEVEL); + } + + endbrdr[0] = W_CachePatchName("ENDBRDR2", PU_LEVEL); + } + else + { + // eggman, skin nonspecific + endfwrk[0] = W_CachePatchName("ENDFWRK0", PU_LEVEL); + endfwrk[1] = W_CachePatchName("ENDFWRK1", PU_LEVEL); + endfwrk[2] = W_CachePatchName("ENDFWRK2", PU_LEVEL); + + endbrdr[0] = W_CachePatchName("ENDBRDR0", PU_LEVEL); + } + +#define colset(map, a, b, c) \ + map[1] = (UINT8)a;\ + map[3] = (UINT8)b;\ + map[9] = (UINT8)c + + colset(purplemap, 164, 165, 169); +} + +#define SPARKLLOOPTIME 15 // must be odd +#define INFLECTIONPOINT (6*TICRATE) + +void F_EndingTicker(void) +{ + angle_t workingangle; + fixed_t workingradius; + + if (++finalecount == INFLECTIONPOINT && goodending) // time to swap some assets + { + Z_Free(endegrk[0]); + endegrk[0] = W_CachePatchName("ENDEGRK2", PU_LEVEL); + Z_Free(endegrk[1]); + endegrk[1] = W_CachePatchName("ENDEGRK3", PU_LEVEL); + + Z_Free(endglow[0]); + endglow[0] = W_CachePatchName("ENDGLOW2", PU_LEVEL); + Z_Free(endglow[1]); + endglow[1] = W_CachePatchName("ENDGLOW3", PU_LEVEL); + + Z_Free(endxpld[0]); + endxpld[0] = W_CachePatchName("ENDEGRK4", PU_LEVEL); + } + + if (++sparklloop == SPARKLLOOPTIME) // time to roll the randomisation again + { + sparklloop = 0; + if (goodending) + { + UINT8 i; + for (i = 0; i < 7; ++i) + { + sparkloffs[i][2][0] = sparkloffs[i][1][0]; + sparkloffs[i][2][1] = sparkloffs[i][1][1]; + sparkloffs[i][1][0] = sparkloffs[i][0][0]; + sparkloffs[i][1][1] = sparkloffs[i][0][1]; + sparkloffs[i][0][0] = M_RandomRange(-11, 11)<>ANGLETOFINESHIFT; + workingradius = M_RandomKey(26); + sparkloffs[7][0][0] = (30< INFLECTIONPOINT*2) + { + F_StartCredits(); + wipetypepre = INT16_MAX; + colset(purplemap, 160, 161, 163); +#undef colset + } +} + +void F_EndingDrawer(void) +{ + INT32 x, y, i, j, parallaxticker; + patch_t *rockpat; + + if (!goodending || finalecount < INFLECTIONPOINT) + rockpat = W_CachePatchName("ROID0000", PU_LEVEL); + else + rockpat = W_CachePatchName(va("ROID00%.2d", (finalecount - INFLECTIONPOINT)%35), PU_LEVEL); + + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); + + parallaxticker = finalecount - INFLECTIONPOINT; + x = -((parallaxticker*20)< 0) // gunchedrock + { + if (parallaxticker < 10) + { + tweakx = parallaxticker<>2; + UINT8 *colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_JET, GTC_CACHE); +#endif + + x <<= 1; + y <<= 1; + + // center detritrus + V_DrawFixedPatch(i-x, j-y, FRACUNIT, 0, endegrk[0], +#ifdef TFTMOPTIMUSFADE + colormap); + if (trans < 10) + V_DrawFixedPatch(i-x, j-y, FRACUNIT, trans< 0) + { + i -= (3+(tweakx<<1)); + j += tweaky<<2; + } + + if (parallaxticker <= 70) + { + INT32 trans; + fixed_t scale = FRACUNIT; + UINT8 *colormap[2] = {NULL, NULL}; + + x += i; + y += j; + + if (parallaxticker > 66) + { + scale = ((70 - parallaxticker)<<(FRACBITS-2)); + x += (30*(FRACUNIT-scale)); + y += (30*(FRACUNIT-scale)); + } + else if ((parallaxticker > 60) || (goodending && parallaxticker > 0)) + ; + else + { + doexplosions = true; + if (!sparklloop) + { + x += ((sparkloffs[7][0][0] < 30< INFLECTIONPOINT) + parallaxticker -= 40; + + if ((-parallaxticker/4) < 5) + { + trans = (-parallaxticker/4) + 5; + if (trans < 0) + trans = 0; + V_DrawFixedPatch(x, y, scale, trans< INFLECTIONPOINT) + { + if (finalecount < INFLECTIONPOINT+10) + V_DrawFadeFill(24, 24, BASEVIDWIDTH-48, BASEVIDHEIGHT-48, 0, 0, INFLECTIONPOINT+10-finalecount); + parallaxticker -= 30; + } + + if ((parallaxticker/2) > -15) + colormap[0] = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE); + V_DrawFixedPatch(x, y, scale, 0, rockpat, colormap[0]); + if ((parallaxticker/2) > -25) + { + trans = (parallaxticker/2) + 15; + if (trans < 0) + trans = -trans; + if (trans < 10) + V_DrawFixedPatch(x, y, scale, trans< INFLECTIONPOINT) + { + if (finalecount < INFLECTIONPOINT+10) + V_DrawFixedPatch(x, y, scale, (finalecount-INFLECTIONPOINT)<= 3 && doexplosions) + { + INT32 boomtime = parallaxticker - sparklloop; + + x = ((((BASEVIDWIDTH-82)/2)+11)< INFLECTIONPOINT && finalecount < INFLECTIONPOINT+10) + V_DrawScaledPatch(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, (finalecount-INFLECTIONPOINT)<= TICRATE && finalecount < INFLECTIONPOINT) + { + INT32 workingtime = finalecount - TICRATE; + fixed_t radius[4]; + angle_t fa; + INT32 eemeralds_cur[4]; + char patchname[7] = "CEMGx0"; + + for (i = 0; i < 4; ++i) + { + if (i == 1) + workingtime -= sparklloop; + else if (i) + workingtime -= SPARKLLOOPTIME; + eemeralds_cur[i] = workingtime % 360; + radius[i] = ((vid.width/vid.dupx)*(INFLECTIONPOINT - TICRATE - workingtime))/(INFLECTIONPOINT - TICRATE); + radius[i] <<= FRACBITS; + } + + for (i = 0; i < 7; ++i) + { + fa = (FixedAngle(eemeralds_cur[0]*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK; + x = (BASEVIDWIDTH<<(FRACBITS-1)) + FixedMul(FINECOSINE(fa),radius[0]); + y = ((BASEVIDHEIGHT+16)<<(FRACBITS-1)) + FixedMul(FINESINE(fa),radius[0]); + eemeralds_cur[0] += INTERVAL; + if (i & 1) + eemeralds_cur[0]++; + + patchname[4] = 'A'+(char)i; + V_DrawFixedPatch(x, y, FRACUNIT, 0, W_CachePatchName(patchname, PU_LEVEL), NULL); + } + for (i = 0; i < 7; ++i) + { + UINT8* colormap; + skincolors_t col = SKINCOLOR_GREEN; + switch (i) + { + case 1: + col = SKINCOLOR_MAGENTA; + break; + case 2: + col = SKINCOLOR_BLUE; + break; + case 3: + col = SKINCOLOR_SKY; + break; + case 4: + col = SKINCOLOR_ORANGE; + break; + case 5: + col = SKINCOLOR_RED; + break; + case 6: + col = SKINCOLOR_GREY; + default: + case 0: + break; + } + + colormap = R_GetTranslationColormap(TC_DEFAULT, col, GTC_CACHE); + + j = (sparklloop & 1) ? 2 : 3; + while (j) + { + fa = (FixedAngle(eemeralds_cur[j]*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK; + x = (BASEVIDWIDTH<<(FRACBITS-1)) + FixedMul(FINECOSINE(fa),radius[j]) + sparkloffs[i][j-1][0]; + y = ((BASEVIDHEIGHT+16)<<(FRACBITS-1)) + FixedMul(FINESINE(fa),radius[j]) + sparkloffs[i][j-1][1]; + eemeralds_cur[j] += INTERVAL; + if (i & 1) + eemeralds_cur[j]++; + + // if j == 0 - alternate between 0 and 1 + // 1 - 1 and 2 + // 2 - 2 and not rendered + V_DrawFixedPatch(x, y, FRACUNIT, 0, endspkl[(j - ((sparklloop & 1) ? 0 : 1))], colormap); + + j--; + } + } + } // if (goodending... + } // (finalecount > 20) + + // look, i make an ending for you last-minute, the least you could do is let me have this + if (cv_soundtest.value == 413) + { + INT32 trans = 0; + boolean donttouch = false; + const char *str; + if (goodending) + str = va("[S] %s: Engage.", skins[players[consoleplayer].skin].realname); + else + str = "[S] Eggman: Abscond."; + + if (finalecount < 10) + trans = (10-finalecount)/2; + else if (finalecount > (2*INFLECTIONPOINT) - 20) + { + trans = 10 + (finalecount/2) - INFLECTIONPOINT; + donttouch = true; + } + + if (trans != 10) + { + V_DrawCenteredString(BASEVIDWIDTH/2, 8, V_ALLOWLOWERCASE|(trans<'|(trans<= (2*INFLECTIONPOINT)-TICRATE) ? V_PURPLEMAP : V_BLUEMAP)|(trans<"); + } + + if (finalecount > (2*INFLECTIONPOINT)-(20+(2*TICRATE))) + { + INT32 trans2 = abs((5*FINECOSINE((FixedAngle((finalecount*5)<>ANGLETOFINESHIFT & FINEMASK)))>>FRACBITS)+2; + if (!donttouch) + { + trans = 10 + ((2*INFLECTIONPOINT)-(20+(2*TICRATE))) - finalecount; + if (trans > trans2) + trans2 = trans; + } + else + trans2 += 2*trans; + if (trans2 < 10) + V_DrawCharacter(26, BASEVIDHEIGHT-33, '\x1C'|(trans2<scene[scenenum].musswitchposition, 0, 0); else S_StopMusic(); + S_StopSounds(); } // @@ -2044,7 +2690,7 @@ void F_CutsceneDrawer(void) F_RunWipe(cutscenes[cutnum]->scene[scenenum].fadeoutid, true); } - V_DrawString(textxpos, textypos, 0, cutscene_disptext); + V_DrawString(textxpos, textypos, V_ALLOWLOWERCASE, cutscene_disptext); } void F_CutsceneTicker(void) diff --git a/src/f_finale.h b/src/f_finale.h index c0c6360c3..0d5bc2475 100644 --- a/src/f_finale.h +++ b/src/f_finale.h @@ -46,6 +46,9 @@ void F_GameEvaluationDrawer(void); void F_StartGameEvaluation(void); void F_GameEvaluationTicker(void); +void F_EndingTicker(void); +void F_EndingDrawer(void); + void F_CreditTicker(void); void F_CreditDrawer(void); @@ -63,6 +66,7 @@ boolean F_GetPromptHideHud(fixed_t y); void F_StartGameEnd(void); void F_StartIntro(void); void F_StartTitleScreen(void); +void F_StartEnding(void); void F_StartCredits(void); boolean F_ContinueResponder(event_t *event); @@ -126,6 +130,7 @@ enum wipe_evaluation_toblack, wipe_gameend_toblack, wipe_intro_toblack, + wipe_ending_toblack, wipe_cutscene_toblack, // custom intermissions @@ -142,15 +147,16 @@ enum wipe_evaluation_final, wipe_gameend_final, wipe_intro_final, + wipe_ending_final, wipe_cutscene_final, // custom intermissions wipe_specinter_final, wipe_multinter_final, - NUMWIPEDEFS + NUMWIPEDEFS, + WIPEFINALSHIFT = (wipe_level_final-wipe_level_toblack) }; -#define WIPEFINALSHIFT 13 extern UINT8 wipedefs[NUMWIPEDEFS]; #endif diff --git a/src/f_wipe.c b/src/f_wipe.c index 26c65ad91..05229f844 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -54,6 +54,7 @@ UINT8 wipedefs[NUMWIPEDEFS] = { 0, // wipe_evaluation_toblack 0, // wipe_gameend_toblack 99, // wipe_intro_toblack (hardcoded) + 0, // wipe_ending_toblack 99, // wipe_cutscene_toblack (hardcoded) 0, // wipe_specinter_toblack @@ -69,6 +70,7 @@ UINT8 wipedefs[NUMWIPEDEFS] = { 0, // wipe_evaluation_final 0, // wipe_gameend_final 99, // wipe_intro_final (hardcoded) + 0, // wipe_ending_final 99, // wipe_cutscene_final (hardcoded) 0, // wipe_specinter_final diff --git a/src/g_game.c b/src/g_game.c index 95cc2288d..c6af0f48d 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1842,7 +1842,7 @@ boolean G_Responder(event_t *ev) return true; } } - else if (gamestate == GS_CREDITS) + else if (gamestate == GS_CREDITS || gamestate == GS_ENDING) // todo: keep ending here? { if (HU_Responder(ev)) return true; // chat ate the event @@ -2032,6 +2032,12 @@ void G_Ticker(boolean run) F_IntroTicker(); break; + case GS_ENDING: + if (run) + F_EndingTicker(); + HU_Ticker(); + break; + case GS_CUTSCENE: if (run) F_CutsceneTicker(); @@ -2849,6 +2855,10 @@ void G_ExitLevel(void) // Remove CEcho text on round end. HU_ClearCEcho(); } + else if (gamestate == GS_ENDING) + { + F_StartCredits(); + } else if (gamestate == GS_CREDITS) { F_StartGameEvaluation(); @@ -3116,7 +3126,7 @@ static void G_DoCompleted(void) nextmap = cm; } - if (nextmap < 0 || (nextmap >= NUMMAPS && nextmap < 1100-1) || nextmap > 1102-1) + if (nextmap < 0 || (nextmap >= NUMMAPS && nextmap < 1100-1) || nextmap > 1103-1) I_Error("Followed map %d to invalid map %d\n", prevmap + 1, nextmap + 1); // wrap around in race @@ -3282,6 +3292,11 @@ void G_EndGame(void) // Only do evaluation and credits in coop games. if (gametype == GT_COOP) { + if (nextmap == 1103-1) // end game with ending + { + F_StartEnding(); + return; + } if (nextmap == 1102-1) // end game with credits { F_StartCredits(); @@ -3700,7 +3715,7 @@ void G_SaveGame(UINT32 slot) backup = va("%s",savename); // save during evaluation or credits? game's over, folks! - if (gamestate == GS_CREDITS || gamestate == GS_EVALUATION) + if (gamestate == GS_ENDING || gamestate == GS_CREDITS || gamestate == GS_EVALUATION) gamecomplete = true; gameaction = ga_nothing; diff --git a/src/g_state.h b/src/g_state.h index 76c9bd16f..dd08c4a83 100644 --- a/src/g_state.h +++ b/src/g_state.h @@ -27,12 +27,14 @@ typedef enum GS_TITLESCREEN, // title screen GS_TIMEATTACK, // time attack menu + GS_CREDITS, // credit sequence GS_EVALUATION, // Evaluation at the end of a game. - GS_GAMEEND, // game end sequence + GS_GAMEEND, // game end sequence - "did you get all those chaos emeralds?" // Hardcoded fades or other fading methods GS_INTRO, // introduction + GS_ENDING, // currently shared between bad and good endings GS_CUTSCENE, // custom cutscene // Not fadable diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index dd9fa8423..6bfd2a4dc 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -283,7 +283,7 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, if (!(option & V_SCALEPATCHMASK)) { - // if it's meant to cover the whole screen, black out the rest + // if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT) // cx and cy are possibly *slightly* off from float maths // This is done before here compared to software because we directly alter cx and cy to centre if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT) @@ -291,8 +291,11 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, // Need to temporarily cache the real patch to get the colour of the top left pixel patch_t *realpatch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0])); - const UINT8 *source = (const UINT8 *)(column) + 3; - HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); + if (!column->topdelta) + { + const UINT8 *source = (const UINT8 *)(column) + 3; + HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); + } Z_Free(realpatch); } // centre screen @@ -439,7 +442,7 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal if (!(option & V_SCALEPATCHMASK)) { - // if it's meant to cover the whole screen, black out the rest + // if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT) // cx and cy are possibly *slightly* off from float maths // This is done before here compared to software because we directly alter cx and cy to centre if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT) @@ -447,8 +450,11 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal // Need to temporarily cache the real patch to get the colour of the top left pixel patch_t *realpatch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0])); - const UINT8 *source = (const UINT8 *)(column) + 3; - HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); + if (!column->topdelta) + { + const UINT8 *source = (const UINT8 *)(column) + 3; + HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); + } Z_Free(realpatch); } // centre screen @@ -683,12 +689,191 @@ void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength) } else // Do TRANSMAP** fade. { - Surf.FlatColor.rgba = pLocalPalette[color].rgba; - Surf.FlatColor.s.alpha = (UINT8)(strength*25.5f); + Surf.FlatColor.rgba = V_GetColor(color).rgba; + Surf.FlatColor.s.alpha = softwaretranstogl[strength]; } HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } +// -----------------+ +// HWR_DrawFadeFill : draw flat coloured rectangle, with transparency +// -----------------+ +void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 actualcolor, UINT8 strength) +{ + FOutVector v[4]; + FSurfaceInfo Surf; + float fx, fy, fw, fh; + + UINT8 perplayershuffle = 0; + + if (w < 0 || h < 0) + return; // consistency w/ software + +// 3--2 +// | /| +// |/ | +// 0--1 + + if (splitscreen && (color & V_PERPLAYER)) + { + fixed_t adjusty = ((color & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)/2.0f; + h >>= 1; + y >>= 1; +#ifdef QUADS + if (splitscreen > 1) // 3 or 4 players + { + fixed_t adjustx = ((color & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)/2.0f; + w >>= 1; + x >>= 1; + if (stplyr == &players[displayplayer]) + { + if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 1; + if (!(color & (V_SNAPTOLEFT|V_SNAPTORIGHT))) + perplayershuffle |= 4; + color &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT; + } + else if (stplyr == &players[secondarydisplayplayer]) + { + if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 1; + if (!(color & (V_SNAPTOLEFT|V_SNAPTORIGHT))) + perplayershuffle |= 8; + x += adjustx; + color &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT; + } + else if (stplyr == &players[thirddisplayplayer]) + { + if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 2; + if (!(color & (V_SNAPTOLEFT|V_SNAPTORIGHT))) + perplayershuffle |= 4; + y += adjusty; + color &= ~V_SNAPTOTOP|V_SNAPTORIGHT; + } + else //if (stplyr == &players[fourthdisplayplayer]) + { + if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 2; + if (!(color & (V_SNAPTOLEFT|V_SNAPTORIGHT))) + perplayershuffle |= 8; + x += adjustx; + y += adjusty; + color &= ~V_SNAPTOTOP|V_SNAPTOLEFT; + } + } + else +#endif + // 2 players + { + if (stplyr == &players[displayplayer]) + { + if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 1; + color &= ~V_SNAPTOBOTTOM; + } + else //if (stplyr == &players[secondarydisplayplayer]) + { + if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 2; + y += adjusty; + color &= ~V_SNAPTOTOP; + } + } + } + + fx = (float)x; + fy = (float)y; + fw = (float)w; + fh = (float)h; + + if (!(color & V_NOSCALESTART)) + { + float dupx = (float)vid.dupx, dupy = (float)vid.dupy; + + fx *= dupx; + fy *= dupy; + fw *= dupx; + fh *= dupy; + + if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f) + { + if (color & V_SNAPTORIGHT) + fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)); + else if (!(color & V_SNAPTOLEFT)) + fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2; + if (perplayershuffle & 4) + fx -= ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4; + else if (perplayershuffle & 8) + fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4; + } + if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f) + { + // same thing here + if (color & V_SNAPTOBOTTOM) + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)); + else if (!(color & V_SNAPTOTOP)) + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2; + if (perplayershuffle & 1) + fy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4; + else if (perplayershuffle & 2) + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4; + } + } + + if (fx >= vid.width || fy >= vid.height) + return; + if (fx < 0) + { + fw += fx; + fx = 0; + } + if (fy < 0) + { + fh += fy; + fy = 0; + } + + if (fw <= 0 || fh <= 0) + return; + if (fx + fw > vid.width) + fw = (float)vid.width - fx; + if (fy + fh > vid.height) + fh = (float)vid.height - fy; + + fx = -1 + fx / (vid.width / 2); + fy = 1 - fy / (vid.height / 2); + fw = fw / (vid.width / 2); + fh = fh / (vid.height / 2); + + v[0].x = v[3].x = fx; + v[2].x = v[1].x = fx + fw; + v[0].y = v[1].y = fy; + v[2].y = v[3].y = fy - fh; + + //Hurdler: do we still use this argb color? if not, we should remove it + v[0].argb = v[1].argb = v[2].argb = v[3].argb = 0xff00ff00; //; + v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; + + v[0].sow = v[3].sow = 0.0f; + v[2].sow = v[1].sow = 1.0f; + v[0].tow = v[1].tow = 0.0f; + v[2].tow = v[3].tow = 1.0f; + + if (actualcolor & 0xFF00) // Do COLORMAP fade. + { + Surf.FlatColor.rgba = UINT2RGBA(0x01010160); + Surf.FlatColor.s.alpha = (strength*8); + } + else // Do TRANSMAP** fade. + { + Surf.FlatColor.rgba = V_GetColor(actualcolor).rgba; + Surf.FlatColor.s.alpha = softwaretranstogl[strength]; + } + + HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); +} + // Draw the console background with translucency support void HWR_DrawConsoleBack(UINT32 color, INT32 height) { @@ -905,6 +1090,8 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32 FSurfaceInfo Surf; float fx, fy, fw, fh; + UINT8 perplayershuffle = 0; + if (w < 0 || h < 0) return; // consistency w/ software @@ -913,46 +1100,110 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32 // |/ | // 0--1 + if (splitscreen && (color & V_PERPLAYER)) + { + fixed_t adjusty = ((color & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)/2.0f; + h >>= 1; + y >>= 1; +#ifdef QUADS + if (splitscreen > 1) // 3 or 4 players + { + fixed_t adjustx = ((color & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)/2.0f; + w >>= 1; + x >>= 1; + if (stplyr == &players[displayplayer]) + { + if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 1; + if (!(color & (V_SNAPTOLEFT|V_SNAPTORIGHT))) + perplayershuffle |= 4; + color &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT; + } + else if (stplyr == &players[secondarydisplayplayer]) + { + if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 1; + if (!(color & (V_SNAPTOLEFT|V_SNAPTORIGHT))) + perplayershuffle |= 8; + x += adjustx; + color &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT; + } + else if (stplyr == &players[thirddisplayplayer]) + { + if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 2; + if (!(color & (V_SNAPTOLEFT|V_SNAPTORIGHT))) + perplayershuffle |= 4; + y += adjusty; + color &= ~V_SNAPTOTOP|V_SNAPTORIGHT; + } + else //if (stplyr == &players[fourthdisplayplayer]) + { + if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 2; + if (!(color & (V_SNAPTOLEFT|V_SNAPTORIGHT))) + perplayershuffle |= 8; + x += adjustx; + y += adjusty; + color &= ~V_SNAPTOTOP|V_SNAPTOLEFT; + } + } + else +#endif + // 2 players + { + if (stplyr == &players[displayplayer]) + { + if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 1; + color &= ~V_SNAPTOBOTTOM; + } + else //if (stplyr == &players[secondarydisplayplayer]) + { + if (!(color & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 2; + y += adjusty; + color &= ~V_SNAPTOTOP; + } + } + } + fx = (float)x; fy = (float)y; fw = (float)w; fh = (float)h; - if (!(options & V_NOSCALESTART)) + if (!(color & V_NOSCALESTART)) { float dupx = (float)vid.dupx, dupy = (float)vid.dupy; - if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) - { - RGBA_t rgbaColour = V_GetColor(color); - FRGBAFloat clearColour; - clearColour.red = (float)rgbaColour.s.red / 255; - clearColour.green = (float)rgbaColour.s.green / 255; - clearColour.blue = (float)rgbaColour.s.blue / 255; - clearColour.alpha = 1; - HWD.pfnClearBuffer(true, false, &clearColour); - return; - } - fx *= dupx; fy *= dupy; fw *= dupx; fh *= dupy; - if (fabsf((float)vid.width - ((float)BASEVIDWIDTH * dupx)) > 1.0E-36f) + if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f) { - if (options & V_SNAPTORIGHT) + if (color & V_SNAPTORIGHT) fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)); - else if (!(options & V_SNAPTOLEFT)) + else if (!(color & V_SNAPTOLEFT)) fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2; + if (perplayershuffle & 4) + fx -= ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4; + else if (perplayershuffle & 8) + fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4; } - if (fabsf((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) > 1.0E-36f) + if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f) { // same thing here - if (options & V_SNAPTOBOTTOM) + if (color & V_SNAPTOBOTTOM) fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)); - else if (!(options & V_SNAPTOTOP)) + else if (!(color & V_SNAPTOTOP)) fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2; + if (perplayershuffle & 1) + fy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4; + else if (perplayershuffle & 2) + fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4; } } diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index fdfc1d257..fab18e08a 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -49,6 +49,7 @@ void HWR_CreatePlanePolygons(INT32 bspnum); void HWR_CreateStaticLightmaps(INT32 bspnum); void HWR_PrepLevelCache(size_t pnumtextures); void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color); +void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 actualcolor, UINT8 strength); void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32 options); // Lat: separate flags from color since color needs to be an uint to work right. void HWR_DrawPic(INT32 x,INT32 y,lumpnum_t lumpnum); diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index e26aa98ff..c2faa8b86 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1198,6 +1198,9 @@ static UINT8 P_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t *p if (!md2 || !skin) return 0; + if ((spr2 & ~FF_SPR2SUPER) >= free_spr2) + return 0; + while (!(md2->model->spr2frames[spr2*2 + 1]) && spr2 != SPR2_STND && ++i != 32) // recursion limiter @@ -1220,7 +1223,10 @@ static UINT8 P_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t *p & SF_NOJUMPSPIN) ? SPR2_SPNG : SPR2_ROLL; break; case SPR2_TIRE: - spr2 = (player && player->charability == CA_SWIM) ? SPR2_SWIM : SPR2_FLY; + spr2 = ((player + ? player->charability + : skin->ability) + == CA_SWIM) ? SPR2_SWIM : SPR2_FLY; break; // Use the handy list, that's what it's there for! @@ -1232,6 +1238,9 @@ static UINT8 P_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t *p spr2 |= super; } + if (i >= 32) // probably an infinite loop... + return 0; + return spr2; } diff --git a/src/hu_stuff.c b/src/hu_stuff.c index f86100e27..3bc643c3c 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2138,7 +2138,7 @@ void HU_Drawer(void) if (!Playing() || gamestate == GS_INTERMISSION || gamestate == GS_CUTSCENE || gamestate == GS_CREDITS || gamestate == GS_EVALUATION - || gamestate == GS_GAMEEND) + || gamestate == GS_ENDING || gamestate == GS_GAMEEND) return; // draw multiplayer rankings diff --git a/src/info.c b/src/info.c index 7606f27a1..83a205be4 100644 --- a/src/info.c +++ b/src/info.c @@ -578,7 +578,8 @@ char spr2names[NUMPLAYERSPRITES][5] = "TALB", "SIGN", - "LIFE" + "LIFE", + "XTRA", }; playersprite_t free_spr2 = SPR2_FIRSTFREESLOT; @@ -595,7 +596,7 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { SPR2_DEAD, // SPR2_DRWN, 0, // SPR2_ROLL, SPR2_SPNG, // SPR2_GASP, - 0, // SPR2_JUMP, (conditional) + 0, // SPR2_JUMP, (conditional, will never be referenced) SPR2_FALL, // SPR2_SPNG, SPR2_WALK, // SPR2_FALL, 0, // SPR2_EDGE, @@ -605,7 +606,7 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { SPR2_SPNG, // SPR2_FLY , SPR2_FLY , // SPR2_SWIM, - 0, // SPR2_TIRE, (conditional) + 0, // SPR2_TIRE, (conditional, will never be referenced) SPR2_FLY , // SPR2_GLID, SPR2_CLMB, // SPR2_CLNG, @@ -632,7 +633,7 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { SPR2_NSTN, // SPR2_NPUL, FF_SPR2SUPER|SPR2_ROLL, // SPR2_NATK, - 0, // SPR2_NGT0, (should never be referenced) + 0, // SPR2_NGT0, (will never be referenced unless skin 0 lacks this) SPR2_NGT0, // SPR2_NGT1, SPR2_NGT1, // SPR2_NGT2, SPR2_NGT2, // SPR2_NGT3, @@ -660,7 +661,7 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { SPR2_NGTB, // SPR2_DRLB, SPR2_NGTC, // SPR2_DRLC, - 0, // SPR2_TAL0, + 0, // SPR2_TAL0, (this will look mighty stupid but oh well) SPR2_TAL0, // SPR2_TAL1, SPR2_TAL1, // SPR2_TAL2, SPR2_TAL2, // SPR2_TAL3, @@ -675,6 +676,7 @@ playersprite_t spr2defaults[NUMPLAYERSPRITES] = { 0, // SPR2_SIGN, 0, // SPR2_LIFE, + 0, // SPR2_XTRA (should never be referenced) }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) diff --git a/src/info.h b/src/info.h index 44f08a4e9..b25f21e09 100644 --- a/src/info.h +++ b/src/info.h @@ -834,6 +834,7 @@ typedef enum playersprite SPR2_SIGN, // end sign head SPR2_LIFE, // life monitor icon + SPR2_XTRA, // stuff that isn't in-game - keep this last in the list SPR2_FIRSTFREESLOT, SPR2_LASTFREESLOT = 0x7f, diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 55afa3874..8bd4ce9ff 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -157,6 +157,18 @@ static int lib_setSpr2default(lua_State *L) playersprite_t i; UINT8 j = 0; + if (hud_running) + return luaL_error(L, "Do not alter spr2defaults[] in HUD rendering code!"); + +// todo: maybe allow setting below first freeslot..? step 1 is toggling this, step 2 is testing to see whether it's net-safe +#ifdef SETALLSPR2DEFAULTS +#define FIRSTMODIFY 0 +#else +#define FIRSTMODIFY SPR2_FIRSTFREESLOT + if (free_spr2 == SPR2_FIRSTFREESLOT) + return luaL_error(L, "You can only modify the spr2defaults[] entries of sprite2 freeslots, and none are currently added."); +#endif + lua_remove(L, 1); // don't care about spr2defaults[] dummy userdata. if (lua_isnumber(L, 1)) @@ -175,8 +187,9 @@ static int lib_setSpr2default(lua_State *L) else return luaL_error(L, "spr2defaults[] invalid index"); - if (i < SPR2_FIRSTFREESLOT || i >= free_spr2) - return luaL_error(L, "spr2defaults[] index %d out of range (%d - %d)", i, SPR2_FIRSTFREESLOT, free_spr2-1); + if (i < FIRSTMODIFY || i >= free_spr2) + return luaL_error(L, "spr2defaults[] index %d out of range (%d - %d)", i, FIRSTMODIFY, free_spr2-1); +#undef FIRSTMODIFY if (lua_isnumber(L, 2)) j = lua_tonumber(L, 2); @@ -189,11 +202,13 @@ static int lib_setSpr2default(lua_State *L) break; } if (j == free_spr2) - return luaL_error(L, "spr2defaults[] invalid index"); + return luaL_error(L, "spr2defaults[] invalid set"); } + else + return luaL_error(L, "spr2defaults[] invalid set"); - if (j >= free_spr2) - j = 0; // return luaL_error(L, "spr2defaults[] set %d out of range (%d - %d)", j, 0, free_spr2-1); + if (j < 0 || j >= free_spr2) + return luaL_error(L, "spr2defaults[] set %d out of range (%d - %d)", j, 0, free_spr2-1); spr2defaults[i] = j; return 0; diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index a8f785c5a..cc18ce860 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -27,9 +27,6 @@ enum skin { skin_flags, skin_realname, skin_hudname, - skin_charsel, - skin_face, - skin_superface, skin_ability, skin_ability2, skin_thokitem, @@ -66,9 +63,6 @@ static const char *const skin_opt[] = { "flags", "realname", "hudname", - "charsel", - "face", - "superface", "ability", "ability2", "thokitem", @@ -131,24 +125,6 @@ static int skin_get(lua_State *L) case skin_hudname: lua_pushstring(L, skin->hudname); break; - case skin_charsel: - for (i = 0; i < 8; i++) - if (!skin->charsel[i]) - break; - lua_pushlstring(L, skin->charsel, i); - break; - case skin_face: - for (i = 0; i < 8; i++) - if (!skin->face[i]) - break; - lua_pushlstring(L, skin->face, i); - break; - case skin_superface: - for (i = 0; i < 8; i++) - if (!skin->superface[i]) - break; - lua_pushlstring(L, skin->superface, i); - break; case skin_ability: lua_pushinteger(L, skin->ability); break; diff --git a/src/m_menu.c b/src/m_menu.c index d9d3a6ba0..38326257b 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -2810,8 +2810,8 @@ boolean M_Responder(event_t *ev) void (*routine)(INT32 choice); // for some casting problem if (dedicated || (demoplayback && titledemo) - || gamestate == GS_INTRO || gamestate == GS_CUTSCENE || gamestate == GS_GAMEEND - || gamestate == GS_CREDITS || gamestate == GS_EVALUATION) + || gamestate == GS_INTRO || gamestate == GS_ENDING || gamestate == GS_CUTSCENE + || gamestate == GS_CREDITS || gamestate == GS_EVALUATION || gamestate == GS_GAMEEND) return false; if (noFurtherInput) @@ -3511,6 +3511,7 @@ void M_InitCharacterTables(void) strcpy(description[i].picname, ""); strcpy(description[i].skinname, ""); description[i].prev = description[i].next = 0; + description[i].pic = NULL; } } @@ -7557,8 +7558,19 @@ static void M_SetupChoosePlayer(INT32 choice) if (i == char_on) allowed = true; - if (description[i].picname[0] == '\0') - strncpy(description[i].picname, skins[skinnum].charsel, 8); + if (!(description[i].picname[0])) + { + if (skins[skinnum].sprites[SPR2_XTRA].numframes >= 2) + { + spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA]; + spriteframe_t *sprframe = &sprdef->spriteframes[1]; + description[i].pic = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); + } + else + description[i].pic = W_CachePatchName("MISSING", PU_CACHE); + } + else + description[i].pic = W_CachePatchName(description[i].picname, PU_CACHE); } // else -- Technically, character select icons without corresponding skins get bundled away behind this too. Sucks to be them. Z_Free(name); @@ -7712,7 +7724,7 @@ static void M_DrawSetupChoosePlayerMenu(void) // Draw prev character if it's visible and its number isn't greater than the current one or there's more than two if (o < 32) { - patch = W_CachePatchName(description[prev].picname, PU_CACHE); + patch = description[prev].pic; if (SHORT(patch->width) >= 256) V_DrawCroppedPatch(8<height) + 2*(o-32), SHORT(patch->width), 64 - 2*o); else @@ -7723,7 +7735,7 @@ static void M_DrawSetupChoosePlayerMenu(void) // Draw next character if it's visible and its number isn't less than the current one or there's more than two if (o < 128) // (next != i) was previously a part of this, but it's implicitly true if (prev != i) is true. { - patch = W_CachePatchName(description[next].picname, PU_CACHE); + patch = description[next].pic; if (SHORT(patch->width) >= 256) V_DrawCroppedPatch(8<width), 2*o); else @@ -7732,7 +7744,7 @@ static void M_DrawSetupChoosePlayerMenu(void) } } - patch = W_CachePatchName(description[i].picname, PU_CACHE); + patch = description[i].pic; if (o >= 0 && o <= 32) { if (SHORT(patch->width) >= 256) @@ -8124,9 +8136,16 @@ void M_DrawTimeAttackMenu(void) V_DrawString(currentMenu->x, cursory, V_YELLOWMAP, currentMenu->menuitems[itemOn].text); // Character face! - if (W_CheckNumForName(skins[cv_chooseskin.value-1].charsel) != LUMPERROR) { - PictureOfUrFace = W_CachePatchName(skins[cv_chooseskin.value-1].charsel, PU_CACHE); + if (skins[cv_chooseskin.value-1].sprites[SPR2_XTRA].numframes >= 2) + { + spritedef_t *sprdef = &skins[cv_chooseskin.value-1].sprites[SPR2_XTRA]; + spriteframe_t *sprframe = &sprdef->spriteframes[1]; + PictureOfUrFace = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); + } + else + PictureOfUrFace = W_CachePatchName("MISSING", PU_CACHE); + if (PictureOfUrFace->width >= 256) V_DrawTinyScaledPatch(224, 120, 0, PictureOfUrFace); else diff --git a/src/m_menu.h b/src/m_menu.h index 04146ebdc..347725e10 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -316,6 +316,7 @@ typedef struct char notes[441]; char picname[8]; char skinname[SKINNAMESIZE*2+2]; // skin&skin\0 + patch_t *pic; UINT8 prev; UINT8 next; } description_t; diff --git a/src/p_setup.c b/src/p_setup.c index c0aa7ffa3..f38ba9334 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3437,13 +3437,13 @@ boolean P_AddWadFile(const char *wadfilename) ST_UnloadGraphics(); HU_LoadGraphics(); ST_LoadGraphics(); - ST_ReloadSkinFaceGraphics(); // // look for skins // R_AddSkins(wadnum); // faB: wadfile index in wadfiles[] R_PatchSkins(wadnum); // toast: PATCH PATCH + ST_ReloadSkinFaceGraphics(); // // search for maps diff --git a/src/r_things.c b/src/r_things.c index 4b1586455..458d15b7f 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -486,7 +486,11 @@ void R_InitSprites(void) // it can be is do before loading config for skin cvar possible value R_InitSkins(); for (i = 0; i < numwadfiles; i++) + { R_AddSkins((UINT16)i); + R_PatchSkins((UINT16)i); + } + ST_ReloadSkinFaceGraphics(); // // check if all sprites have frames @@ -2503,6 +2507,9 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player) if (!skin) return 0; + if ((spr2 & ~FF_SPR2SUPER) >= free_spr2) + return 0; + while (!(skin->sprites[spr2].numframes) && spr2 != SPR2_STND && ++i < 32) // recursion limiter @@ -2525,8 +2532,10 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player) & SF_NOJUMPSPIN) ? SPR2_SPNG : SPR2_ROLL; break; case SPR2_TIRE: - spr2 = (player && player->charability == CA_SWIM) ? SPR2_SWIM : SPR2_FLY; - break; + spr2 = ((player + ? player->charability + : skin->ability) + == CA_SWIM) ? SPR2_SWIM : SPR2_FLY; // Use the handy list, that's what it's there for! default: @@ -2537,6 +2546,9 @@ UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player) spr2 |= super; } + if (i >= 32) // probably an infinite loop... + return 0; + return spr2; } @@ -2556,9 +2568,6 @@ static void Sk_SetDefaultValue(skin_t *skin) strcpy(skin->realname, "Someone"); strcpy(skin->hudname, "???"); - strncpy(skin->charsel, "CHRSONIC", 9); - strncpy(skin->face, "MISSING", 8); - strncpy(skin->superface, "MISSING", 8); skin->starttranscolor = 96; skin->prefcolor = SKINCOLOR_GREEN; @@ -2988,7 +2997,7 @@ void R_AddSkins(UINT16 wadnum) char *value; size_t size; skin_t *skin; - boolean hudname, realname, superface; + boolean hudname, realname; // // search for all skin markers in pwad @@ -3018,7 +3027,7 @@ void R_AddSkins(UINT16 wadnum) skin = &skins[numskins]; Sk_SetDefaultValue(skin); skin->wadnum = wadnum; - hudname = realname = superface = false; + hudname = realname = false; // parse stoken = strtok (buf2, "\r\n= "); while (stoken) @@ -3094,24 +3103,6 @@ void R_AddSkins(UINT16 wadnum) if (!realname) STRBUFCPY(skin->realname, skin->hudname); } - else if (!stricmp(stoken, "charsel")) - { - strupr(value); - strncpy(skin->charsel, value, sizeof skin->charsel); - } - else if (!stricmp(stoken, "face")) - { - strupr(value); - strncpy(skin->face, value, sizeof skin->face); - if (!superface) - strncpy(skin->superface, value, sizeof skin->superface); - } - else if (!stricmp(stoken, "superface")) - { - superface = true; - strupr(value); - strncpy(skin->superface, value, sizeof skin->superface); - } else if (!stricmp(stoken, "availability")) { skin->availability = atoi(value); @@ -3130,6 +3121,7 @@ next_token: // Add sprites R_LoadSkinSprites(wadnum, &lump, &lastlump, skin); + //ST_LoadFaceGraphics(numskins); -- nah let's do this elsewhere R_FlushTranslationColormapCache(); @@ -3140,9 +3132,6 @@ next_token: skin_cons_t[numskins].strvalue = skin->name; #endif - // add face graphics - ST_LoadFaceGraphics(skin->face, skin->superface, numskins); - #ifdef HWRENDER if (rendermode == render_opengl) HWR_AddPlayerMD2(numskins); @@ -3265,6 +3254,9 @@ next_token: // Patch sprites R_LoadSkinSprites(wadnum, &lump, &lastlump, skin); + //ST_LoadFaceGraphics(skinnum); -- nah let's do this elsewhere + + R_FlushTranslationColormapCache(); if (!skin->availability) // Safe to print... CONS_Printf(M_GetText("Patched skin '%s'\n"), skin->name); diff --git a/src/r_things.h b/src/r_things.h index d287df832..9c3d16ab0 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -88,7 +88,6 @@ typedef struct char realname[SKINNAMESIZE+1]; // Display name for level completion. char hudname[SKINNAMESIZE+1]; // HUD name to display (officially exactly 5 characters long) - char charsel[9], face[9], superface[9]; // Arbitrarily named patch lumps UINT8 ability; // ability definition UINT8 ability2; // secondary ability definition diff --git a/src/s_sound.c b/src/s_sound.c index 2db8392d7..120ba5e50 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1682,7 +1682,17 @@ void S_StopMusic(void) if (cv_closedcaptioning.value) { if (closedcaptions[0].s-S_sfx == sfx_None) - closedcaptions[0].t = CAPTIONFADETICS; + { + if (gamestate != wipegamestate) + { + closedcaptions[0].c = NULL; + closedcaptions[0].s = NULL; + closedcaptions[0].t = 0; + closedcaptions[0].b = 0; + } + else + closedcaptions[0].t = CAPTIONFADETICS; + } } } diff --git a/src/st_stuff.c b/src/st_stuff.c index 4122793ad..fc634fe39 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -226,7 +226,7 @@ void ST_doPaletteStuff(void) void ST_UnloadGraphics(void) { - Z_FreeTags(PU_HUDGFX, PU_HUDGFX); + Z_FreeTag(PU_HUDGFX); } void ST_LoadGraphics(void) @@ -341,10 +341,24 @@ void ST_LoadGraphics(void) } // made separate so that skins code can reload custom face graphics -void ST_LoadFaceGraphics(char *facestr, char *superstr, INT32 skinnum) +void ST_LoadFaceGraphics(INT32 skinnum) { - faceprefix[skinnum] = W_CachePatchName(facestr, PU_HUDGFX); - superprefix[skinnum] = W_CachePatchName(superstr, PU_HUDGFX); + if (skins[skinnum].sprites[SPR2_XTRA].numframes) + { + spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA]; + spriteframe_t *sprframe = &sprdef->spriteframes[0]; + faceprefix[skinnum] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX); + if (skins[skinnum].sprites[(SPR2_XTRA|FF_SPR2SUPER)].numframes) + { + sprdef = &skins[skinnum].sprites[SPR2_XTRA|FF_SPR2SUPER]; + sprframe = &sprdef->spriteframes[0]; + superprefix[skinnum] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX); + } + else + superprefix[skinnum] = faceprefix[skinnum]; // not manually freed, okay to set to same pointer + } + else + faceprefix[skinnum] = superprefix[skinnum] = W_CachePatchName("MISSING", PU_HUDGFX); // ditto facefreed[skinnum] = false; } @@ -353,7 +367,7 @@ void ST_ReloadSkinFaceGraphics(void) INT32 i; for (i = 0; i < numskins; i++) - ST_LoadFaceGraphics(skins[i].face, skins[i].superface, i); + ST_LoadFaceGraphics(i); } static inline void ST_InitData(void) diff --git a/src/st_stuff.h b/src/st_stuff.h index aca4e60d2..40574f46c 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -42,7 +42,7 @@ void ST_UnloadGraphics(void); void ST_LoadGraphics(void); // face load graphics, called when skin changes -void ST_LoadFaceGraphics(char *facestr, char *superstr, INT32 playernum); +void ST_LoadFaceGraphics(INT32 playernum); void ST_ReloadSkinFaceGraphics(void); void ST_doPaletteStuff(void); diff --git a/src/v_video.c b/src/v_video.c index df342e74b..1c56770e5 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -309,12 +309,14 @@ static boolean InitCube(void) return true; } +#ifdef BACKWARDSCOMPATCORRECTION /* So it turns out that the way gamma was implemented previously, the default colour profile of the game was messed up. Since this bad decision has been around for a long time, and the intent is to keep the base game looking the same, I'm not gonna be the one to remove this base modification. toast 20/04/17 +... welp yes i am (27/07/19, see the ifdef around it) */ const UINT8 correctiontable[256] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16, @@ -333,6 +335,7 @@ const UINT8 correctiontable[256] = 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255}; +#endif // keep a copy of the palette so that we can get the RGB value for a color index at any time. static void LoadPalette(const char *lumpname) @@ -351,12 +354,18 @@ static void LoadPalette(const char *lumpname) pal = W_CacheLumpNum(lumpnum, PU_CACHE); for (i = 0; i < palsize; i++) { +#ifdef BACKWARDSCOMPATCORRECTION pMasterPalette[i].s.red = pLocalPalette[i].s.red = correctiontable[*pal++]; pMasterPalette[i].s.green = pLocalPalette[i].s.green = correctiontable[*pal++]; pMasterPalette[i].s.blue = pLocalPalette[i].s.blue = correctiontable[*pal++]; +#else + pMasterPalette[i].s.red = pLocalPalette[i].s.red = *pal++; + pMasterPalette[i].s.green = pLocalPalette[i].s.green = *pal++; + pMasterPalette[i].s.blue = pLocalPalette[i].s.blue = *pal++; +#endif pMasterPalette[i].s.alpha = pLocalPalette[i].s.alpha = 0xFF; - // lerp of colour cubing! + // lerp of colour cubing! if you want, make it smoother yourself if (cube) { float working[4][3]; @@ -732,12 +741,15 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t // Center it if necessary if (!(scrn & V_SCALEPATCHMASK)) { - // if it's meant to cover the whole screen, black out the rest + // if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT) if (x == 0 && SHORT(patch->width) == BASEVIDWIDTH && y == 0 && SHORT(patch->height) == BASEVIDHEIGHT) { column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[0])); - source = (const UINT8 *)(column) + 3; - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); + if (!column->topdelta) + { + source = (const UINT8 *)(column) + 3; + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, source[0]); + } } if (vid.width != BASEVIDWIDTH * dupx) @@ -1349,13 +1361,16 @@ static UINT32 V_GetHWConsBackColor(void) // THANK YOU MPC!!! +// and thanks toaster for cleaning it up. void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) { UINT8 *dest; - INT32 u, v; + const UINT8 *deststop; + INT32 u; UINT8 *fadetable; UINT32 alphalevel = 0; + UINT8 perplayershuffle = 0; if (rendermode == render_none) return; @@ -1369,16 +1384,91 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) } #endif + if ((alphalevel = ((c & V_ALPHAMASK) >> V_ALPHASHIFT))) + { + if (alphalevel == 13) + alphalevel = hudminusalpha[cv_translucenthud.value]; + else if (alphalevel == 14) + alphalevel = 10 - cv_translucenthud.value; + else if (alphalevel == 15) + alphalevel = hudplusalpha[cv_translucenthud.value]; + + if (alphalevel >= 10) + return; // invis + } + + if (splitscreen && (c & V_PERPLAYER)) + { + fixed_t adjusty = ((c & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)>>1; + h >>= 1; + y >>= 1; +#ifdef QUADS + if (splitscreen > 1) // 3 or 4 players + { + fixed_t adjustx = ((c & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)>>1; + w >>= 1; + x >>= 1; + if (stplyr == &players[displayplayer]) + { + if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 1; + if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT))) + perplayershuffle |= 4; + c &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT; + } + else if (stplyr == &players[secondarydisplayplayer]) + { + if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 1; + if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT))) + perplayershuffle |= 8; + x += adjustx; + c &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT; + } + else if (stplyr == &players[thirddisplayplayer]) + { + if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 2; + if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT))) + perplayershuffle |= 4; + y += adjusty; + c &= ~V_SNAPTOTOP|V_SNAPTORIGHT; + } + else //if (stplyr == &players[fourthdisplayplayer]) + { + if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 2; + if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT))) + perplayershuffle |= 8; + x += adjustx; + y += adjusty; + c &= ~V_SNAPTOTOP|V_SNAPTOLEFT; + } + } + else +#endif + // 2 players + { + if (stplyr == &players[displayplayer]) + { + if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 1; + c &= ~V_SNAPTOBOTTOM; + } + else //if (stplyr == &players[secondarydisplayplayer]) + { + if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 2; + y += adjusty; + c &= ~V_SNAPTOTOP; + } + } + } + if (!(c & V_NOSCALESTART)) { INT32 dupx = vid.dupx, dupy = vid.dupy; - if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) - { // Clear the entire screen, from dest to deststop. Yes, this really works. - memset(screens[0], (UINT8)(c&255), vid.width * vid.height * vid.bpp); - return; - } - x *= dupx; y *= dupy; w *= dupx; @@ -1393,6 +1483,10 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) x += (vid.width - (BASEVIDWIDTH * dupx)); else if (!(c & V_SNAPTOLEFT)) x += (vid.width - (BASEVIDWIDTH * dupx)) / 2; + if (perplayershuffle & 4) + x -= (vid.width - (BASEVIDWIDTH * dupx)) / 4; + else if (perplayershuffle & 8) + x += (vid.width - (BASEVIDWIDTH * dupx)) / 4; } if (vid.height != BASEVIDHEIGHT * dupy) { @@ -1401,6 +1495,10 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) y += (vid.height - (BASEVIDHEIGHT * dupy)); else if (!(c & V_SNAPTOTOP)) y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2; + if (perplayershuffle & 1) + y -= (vid.height - (BASEVIDHEIGHT * dupy)) / 4; + else if (perplayershuffle & 2) + y += (vid.height - (BASEVIDHEIGHT * dupy)) / 4; } } @@ -1423,34 +1521,208 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) h = vid.height-y; dest = screens[0] + y*vid.width + x; - - if ((alphalevel = ((c & V_ALPHAMASK) >> V_ALPHASHIFT))) - { - if (alphalevel == 13) - alphalevel = hudminusalpha[cv_translucenthud.value]; - else if (alphalevel == 14) - alphalevel = 10 - cv_translucenthud.value; - else if (alphalevel == 15) - alphalevel = hudplusalpha[cv_translucenthud.value]; - - if (alphalevel >= 10) - return; // invis - } + deststop = screens[0] + vid.rowbytes * vid.height; c &= 255; // Jimita (12-04-2018) - w = min(w, vid.width); - h = min(h, vid.height); - fadetable = ((UINT8 *)transtables + ((alphalevel-1)<= 0) && dest < deststop; dest += vid.width) { - if (!alphalevel) - dest[u] = consolebgmap[dest[u]]; - else + u = 0; + while (u < w) + { dest[u] = fadetable[consolebgmap[dest[u]]]; + u++; + } } + } + else + { + for (;(--h >= 0) && dest < deststop; dest += vid.width) + { + u = 0; + while (u < w) + { + dest[u] = consolebgmap[dest[u]]; + u++; + } + } + } +} + +// +// If color is 0x00 to 0xFF, draw transtable (strength range 0-9). +// Else, use COLORMAP lump (strength range 0-31). +// c is not color, it is for flags only. transparency flags will be ignored. +// IF YOU ARE NOT CAREFUL, THIS CAN AND WILL CRASH! +// I have kept the safety checks for strength out of this function; +// I don't trust Lua users with it, so it doesn't matter. +// +void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, UINT8 strength) +{ + UINT8 *dest; + const UINT8 *deststop; + INT32 u; + UINT8 *fadetable; + UINT8 perplayershuffle = 0; + + if (rendermode == render_none) + return; + +#ifdef HWRENDER + if (rendermode != render_soft && rendermode != render_none) + { + // ughhhhh please can someone else do this? thanks ~toast 25/7/19 in 38 degrees centigrade w/o AC + HWR_DrawFadeFill(x, y, w, h, c, color, strength); // toast two days later - left above comment in 'cause it's funny + return; + } +#endif + +#if 0 // only if for use in-game, otherwise not worth the processor time + if (splitscreen && (c & V_PERPLAYER)) + { + fixed_t adjusty = ((c & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)>>1; + h >>= 1; + y >>= 1; +#ifdef QUADS + if (splitscreen > 1) // 3 or 4 players + { + fixed_t adjustx = ((c & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)>>1; + w >>= 1; + x >>= 1; + if (stplyr == &players[displayplayer]) + { + if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 1; + if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT))) + perplayershuffle |= 4; + c &= ~V_SNAPTOBOTTOM|V_SNAPTORIGHT; + } + else if (stplyr == &players[secondarydisplayplayer]) + { + if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 1; + if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT))) + perplayershuffle |= 8; + x += adjustx; + c &= ~V_SNAPTOBOTTOM|V_SNAPTOLEFT; + } + else if (stplyr == &players[thirddisplayplayer]) + { + if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 2; + if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT))) + perplayershuffle |= 4; + y += adjusty; + c &= ~V_SNAPTOTOP|V_SNAPTORIGHT; + } + else //if (stplyr == &players[fourthdisplayplayer]) + { + if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 2; + if (!(c & (V_SNAPTOLEFT|V_SNAPTORIGHT))) + perplayershuffle |= 8; + x += adjustx; + y += adjusty; + c &= ~V_SNAPTOTOP|V_SNAPTOLEFT; + } + } + else +#endif + // 2 players + { + if (stplyr == &players[displayplayer]) + { + if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 1; + c &= ~V_SNAPTOBOTTOM; + } + else //if (stplyr == &players[secondarydisplayplayer]) + { + if (!(c & (V_SNAPTOTOP|V_SNAPTOBOTTOM))) + perplayershuffle |= 2; + y += adjusty; + c &= ~V_SNAPTOTOP; + } + } + } +#endif + + if (!(c & V_NOSCALESTART)) + { + INT32 dupx = vid.dupx, dupy = vid.dupy; + + x *= dupx; + y *= dupy; + w *= dupx; + h *= dupy; + + // Center it if necessary + if (vid.width != BASEVIDWIDTH * dupx) + { + // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, + // so center this imaginary screen + if (c & V_SNAPTORIGHT) + x += (vid.width - (BASEVIDWIDTH * dupx)); + else if (!(c & V_SNAPTOLEFT)) + x += (vid.width - (BASEVIDWIDTH * dupx)) / 2; + if (perplayershuffle & 4) + x -= (vid.width - (BASEVIDWIDTH * dupx)) / 4; + else if (perplayershuffle & 8) + x += (vid.width - (BASEVIDWIDTH * dupx)) / 4; + } + if (vid.height != BASEVIDHEIGHT * dupy) + { + // same thing here + if (c & V_SNAPTOBOTTOM) + y += (vid.height - (BASEVIDHEIGHT * dupy)); + else if (!(c & V_SNAPTOTOP)) + y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2; + if (perplayershuffle & 1) + y -= (vid.height - (BASEVIDHEIGHT * dupy)) / 4; + else if (perplayershuffle & 2) + y += (vid.height - (BASEVIDHEIGHT * dupy)) / 4; + } + } + + if (x >= vid.width || y >= vid.height) + return; // off the screen + if (x < 0) { + w += x; + x = 0; + } + if (y < 0) { + h += y; + y = 0; + } + + if (w <= 0 || h <= 0) + return; // zero width/height wouldn't draw anything + if (x + w > vid.width) + w = vid.width-x; + if (y + h > vid.height) + h = vid.height-y; + + dest = screens[0] + y*vid.width + x; + deststop = screens[0] + vid.rowbytes * vid.height; + + c &= 255; + + fadetable = ((color & 0xFF00) // Color is not palette index? + ? ((UINT8 *)colormaps + strength*256) // Do COLORMAP fade. + : ((UINT8 *)transtables + ((9-strength)<= 0) && dest < deststop; dest += vid.width) + { + u = 0; + while (u < w) + { + dest[u] = fadetable[dest[u]]; + u++; + } + } } // diff --git a/src/v_video.h b/src/v_video.h index 43748692e..7eb990295 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -158,6 +158,8 @@ void V_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatnum); // fade down the screen buffer before drawing the menu over void V_DrawFadeScreen(UINT16 color, UINT8 strength); +// available to lua over my dead body, which will probably happen in this heat +void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, UINT8 strength); void V_DrawFadeConsBack(INT32 plines); void V_DrawPromptBack(INT32 boxheight, INT32 color); From 7569e0b184d10b739913325fa9f3cbd758391c4a Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 28 Jul 2019 10:41:00 +0100 Subject: [PATCH 095/128] Good morning, fix three little things. * Made the black rock animate backwards through its anim again, to match the 2.1 and earlier intro. * Rid branch of mixed code declaration warnings. * Other cleanup. --- src/f_finale.c | 52 +++++++++++++++----------------------------------- 1 file changed, 15 insertions(+), 37 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index bac50dcec..e17c1118a 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -707,7 +707,7 @@ static void F_IntroDrawScene(void) y += (30*(FRACUNIT-scale)); } - rockpat = W_CachePatchName(va("ROID00%.2d", worktics % 35), PU_LEVEL); + rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (worktics % 35)), PU_LEVEL); glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(worktics & 1)), PU_LEVEL); if (worktics >= 5) @@ -1346,9 +1346,9 @@ void F_GameEvaluationDrawer(void) if (goodending) { - rockpat = W_CachePatchName(va("ROID00%.2d", finalecount % 35), PU_LEVEL); + rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (finalecount % 35)), PU_LEVEL); glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(finalecount & 1)), PU_LEVEL); - x -= 3< 0) // gunchedrock { + INT32 scale = FRACUNIT + ((parallaxticker-10)<<7); + INT32 trans = parallaxticker>>2; + UINT8 *colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_JET, GTC_CACHE); + if (parallaxticker < 10) { tweakx = parallaxticker<>2; - UINT8 *colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_JET, GTC_CACHE); -#endif x <<= 1; y <<= 1; // center detritrus - V_DrawFixedPatch(i-x, j-y, FRACUNIT, 0, endegrk[0], -#ifdef TFTMOPTIMUSFADE - colormap); + V_DrawFixedPatch(i-x, j-y, FRACUNIT, 0, endegrk[0], colormap); if (trans < 10) - V_DrawFixedPatch(i-x, j-y, FRACUNIT, trans<'|(trans<= (2*INFLECTIONPOINT)-TICRATE) ? V_PURPLEMAP : V_BLUEMAP)|(trans<"); From bebaf6f984894e0215ca2819ed9204d9d438e77f Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 28 Jul 2019 11:40:19 +0100 Subject: [PATCH 096/128] * Add comments for maintenence. * Fix not-guaranteed-to-be-set-to-zero-ness of sparklloop * Add blackrock sparkles to good ending. * Don't have emerald sparkles be randomised. * Adjust credits to include Sal (credits sprites + four merged internal MRs and a bunch of public ones) and a few other known contributors, plus remove oni's name (he requested i do it a whiiile ago) --- src/f_finale.c | 165 +++++++++++++++++++++++++++++-------------------- 1 file changed, 97 insertions(+), 68 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index e17c1118a..64a6503e7 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -104,7 +104,7 @@ static patch_t *endfwrk[3]; // firework - replaced with skin when good ending static patch_t *endspkl[3]; // sparkle static patch_t *endglow[2]; // glow aura - replaced with black rock's midway through good ending static patch_t *endxpld[4]; // mini explosion -static INT32 sparkloffs[8][3][2]; // seven emerald sparkles + eggrock explosions +static INT32 sparkloffs[3][2]; // eggrock explosions/blackrock sparkles static INT32 sparklloop; // @@ -985,6 +985,7 @@ static const char *credits[] = { "\1Assistance", "\"chi.miru\"", // helped port slope drawing code from ZDoom "Andrew \"orospakr\" Clunis", + "Sally \"TehRealSalt\" Cochenour", "Gregor \"Oogaland\" Dick", "Louis-Antoine \"LJSonic\" de Moulins", // for fixing 2.1's netcode (de Rochefort doesn't quite fit on the screen sorry lol) "Victor \"Steel Titanium\" Fuentes", @@ -1004,8 +1005,9 @@ static const char *credits[] = { // Everyone else is acknowledged under "Special Thanks > SRB2 Community Contributors". "", "\1Sprite Artists", - "Odi \"Iceman404\" Atunzu", + "\"Iceman404\"", "Victor \"VAdaPEGA\" Ara\x1Fjo", // Araújo -- sorry for our limited font! D: + "Sally \"TehRealSalt\" Cochenour", "Jim \"MotorRoach\" DeMello", "Desmond \"Blade\" DesJardins", "Sherman \"CoatRack\" DesJardins", @@ -1087,7 +1089,10 @@ static const char *credits[] = { "Simon \"sirjuddington\" Judd", // SLADE developer // Acknowledged here are the following: // Minor merge request authors, see guideline above - // Golden - Expanded thin font + // - Golden - Expanded thin font + // Creators of small quantities of sprite/texture assets + // - Arietty - New Green Hill-styled textures + // - Scizor300 - the only other contributor to the 2.0 SRB2 Asset Pack "SRB2 Community Contributors", "", "\1Produced By", @@ -1279,8 +1284,7 @@ boolean F_CreditResponder(event_t *event) // ============ // EVALUATION // ============ -#define INTERVAL (360/7) -#define TRANSLEVEL V_80TRANS +#define SPARKLLOOPTIME 7 // must be odd void F_StartGameEvaluation(void) { @@ -1309,6 +1313,7 @@ void F_StartGameEvaluation(void) CON_ToggleOff(); finalecount = -1; + sparklloop = 0; } void F_GameEvaluationDrawer(void) @@ -1373,7 +1378,24 @@ void F_GameEvaluationDrawer(void) colormap[1] = R_GetTranslationColormap(TC_BLINK, SKINCOLOR_AQUA, GTC_CACHE); V_DrawFixedPatch(x, y, scale, trans< (finalecount/SPARKLLOOPTIME)) + j = (finalecount/SPARKLLOOPTIME); + while (j) + { + if (j > 1 || sparklloop >= 2) + { + // if j == 0 - alternate between 0 and 1 + // 1 - 1 and 2 + // 2 - 2 and not rendered + V_DrawFixedPatch(x+sparkloffs[j-1][0], y+sparkloffs[j-1][1], FRACUNIT, 0, W_CachePatchName(va("ENDSPKL%.1d", (j - ((sparklloop & 1) ? 0 : 1))), PU_LEVEL), R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_AQUA, GTC_CACHE)); + } + j--; + } + } + else { patch_t *eggrock = W_CachePatchName("ENDEGRK5", PU_LEVEL); V_DrawFixedPatch(x, y, scale, 0, eggrock, colormap[0]); @@ -1392,24 +1414,16 @@ void F_GameEvaluationDrawer(void) fa = (FixedAngle(eemeralds_cur*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK; x = (BASEVIDWIDTH<<(FRACBITS-1)) + (60*FINECOSINE(fa)); y = ((BASEVIDHEIGHT+16)<<(FRACBITS-1)) + (60*FINESINE(fa)); - eemeralds_cur += INTERVAL; + eemeralds_cur += (360/7); if (i & 1) eemeralds_cur++; patchname[4] = 'A'+(char)i; - V_DrawFixedPatch(x, y, FRACUNIT, ((emeralds & (1<= 5*TICRATE) { -#if 0 - if (drawemblem) - V_DrawScaledPatch(120, 192, 0, W_CachePatchName("NWNGA0", PU_CACHE)); - - if (drawchaosemblem) - V_DrawScaledPatch(200, 192, 0, W_CachePatchName("NWNGA0", PU_CACHE)); -#endif - V_DrawString(8, 16, V_YELLOWMAP, "Unlocked:"); if (!(netgame) && (!modifiedgame || savemoddata)) @@ -1438,16 +1452,33 @@ void F_GameEvaluationTicker(void) { finalecount++; - if (sparklloop) - sparklloop--; - - if (!goodending - && (finalecount == (5*TICRATE)/2 - || finalecount == (7*TICRATE)/2 - || finalecount == ((7*TICRATE)/2)+5)) + if (goodending) { - S_StartSound(NULL, sfx_s3k5c); - sparklloop = 10; + if (++sparklloop == SPARKLLOOPTIME) // time to roll the randomisation again + { + angle_t workingangle = FixedAngle((M_RandomKey(360))<>ANGLETOFINESHIFT; + fixed_t workingradius = M_RandomKey(26); + sparkloffs[2][0] = sparkloffs[1][0]; + sparkloffs[2][1] = sparkloffs[1][1]; + sparkloffs[1][0] = sparkloffs[0][0]; + sparkloffs[1][1] = sparkloffs[0][1]; + sparkloffs[0][0] = (30<>ANGLETOFINESHIFT; workingradius = M_RandomKey(26); - sparkloffs[7][0][0] = (30< INFLECTIONPOINT*2) @@ -1668,7 +1688,7 @@ void F_EndingDrawer(void) boolean borderstuff = false; INT32 tweakx = 0, tweaky = 0; - if (parallaxticker < 75) + if (parallaxticker < 75) // f background's supposed to be visible { V_DrawFixedPatch(-(x/10), -(y/10), FRACUNIT, 0, endbgsp[0], NULL); // nebula V_DrawFixedPatch(-(x/5), -(y/5), FRACUNIT, 0, endbgsp[1], NULL); // sun @@ -1730,7 +1750,7 @@ void F_EndingDrawer(void) j += tweaky<<2; } - if (parallaxticker <= 70) + if (parallaxticker <= 70) // eggrock/blackrock { INT32 trans; fixed_t scale = FRACUNIT; @@ -1752,8 +1772,8 @@ void F_EndingDrawer(void) doexplosions = true; if (!sparklloop) { - x += ((sparkloffs[7][0][0] < 30<= 3 && doexplosions) { INT32 boomtime = parallaxticker - sparklloop; @@ -1843,10 +1864,11 @@ void F_EndingDrawer(void) x = ((((BASEVIDWIDTH-82)/2)+11)<= TICRATE && finalecount < INFLECTIONPOINT) { INT32 workingtime = finalecount - TICRATE; - fixed_t radius[4]; + fixed_t radius = ((vid.width/vid.dupx)*(INFLECTIONPOINT - TICRATE - workingtime))/(INFLECTIONPOINT - TICRATE); angle_t fa; INT32 eemeralds_cur[4]; char patchname[7] = "CEMGx0"; + radius <<= FRACBITS; + for (i = 0; i < 4; ++i) { if (i == 1) @@ -1878,22 +1903,9 @@ void F_EndingDrawer(void) else if (i) workingtime -= SPARKLLOOPTIME; eemeralds_cur[i] = workingtime % 360; - radius[i] = ((vid.width/vid.dupx)*(INFLECTIONPOINT - TICRATE - workingtime))/(INFLECTIONPOINT - TICRATE); - radius[i] <<= FRACBITS; } - for (i = 0; i < 7; ++i) - { - fa = (FixedAngle(eemeralds_cur[0]*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK; - x = (BASEVIDWIDTH<<(FRACBITS-1)) + FixedMul(FINECOSINE(fa),radius[0]); - y = ((BASEVIDHEIGHT+16)<<(FRACBITS-1)) + FixedMul(FINESINE(fa),radius[0]); - eemeralds_cur[0] += INTERVAL; - if (i & 1) - eemeralds_cur[0]++; - - patchname[4] = 'A'+(char)i; - V_DrawFixedPatch(x, y, FRACUNIT, 0, W_CachePatchName(patchname, PU_LEVEL), NULL); - } + // sparkles for (i = 0; i < 7; ++i) { UINT8* colormap; @@ -1928,9 +1940,9 @@ void F_EndingDrawer(void) while (j) { fa = (FixedAngle(eemeralds_cur[j]*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK; - x = (BASEVIDWIDTH<<(FRACBITS-1)) + FixedMul(FINECOSINE(fa),radius[j]) + sparkloffs[i][j-1][0]; - y = ((BASEVIDHEIGHT+16)<<(FRACBITS-1)) + FixedMul(FINESINE(fa),radius[j]) + sparkloffs[i][j-1][1]; - eemeralds_cur[j] += INTERVAL; + x = (BASEVIDWIDTH<<(FRACBITS-1)) + FixedMul(FINECOSINE(fa),radius); + y = (BASEVIDHEIGHT<<(FRACBITS-1)) + FixedMul(FINESINE(fa),radius); + eemeralds_cur[j] += (360/7); if (i & 1) eemeralds_cur[j]++; @@ -1942,6 +1954,20 @@ void F_EndingDrawer(void) j--; } } + + // ...then emeralds themselves + for (i = 0; i < 7; ++i) + { + fa = (FixedAngle(eemeralds_cur[0]*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK; + x = (BASEVIDWIDTH<<(FRACBITS-1)) + FixedMul(FINECOSINE(fa),radius); + y = ((BASEVIDHEIGHT+16)<<(FRACBITS-1)) + FixedMul(FINESINE(fa),radius); + eemeralds_cur[0] += (360/7); + if (i & 1) + eemeralds_cur[0]++; + + patchname[4] = 'A'+(char)i; + V_DrawFixedPatch(x, y, FRACUNIT, 0, W_CachePatchName(patchname, PU_LEVEL), NULL); + } } // if (goodending... } // (finalecount > 20) @@ -1989,6 +2015,9 @@ void F_EndingDrawer(void) } } +#undef SPARKLLOOPTIME +#undef INFLECTIONPOINT + // ========== // GAME END // ========== From f47c3f40d104974446e52ba73185a74ef4d4a614 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 28 Jul 2019 14:59:42 +0100 Subject: [PATCH 097/128] Smoothen emerald rotation a tad. (Not gonna upload a new test exe, it's basically identical...) --- src/f_finale.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index 64a6503e7..a93163fcc 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1407,16 +1407,14 @@ void F_GameEvaluationDrawer(void) } } - eemeralds_cur = finalecount % 360; + eemeralds_cur = (finalecount % 360)<>ANGLETOFINESHIFT) & FINEMASK; + fa = (FixedAngle(eemeralds_cur)>>ANGLETOFINESHIFT) & FINEMASK; x = (BASEVIDWIDTH<<(FRACBITS-1)) + (60*FINECOSINE(fa)); y = ((BASEVIDHEIGHT+16)<<(FRACBITS-1)) + (60*FINESINE(fa)); - eemeralds_cur += (360/7); - if (i & 1) - eemeralds_cur++; + eemeralds_cur += (360<>ANGLETOFINESHIFT) & FINEMASK; + fa = (FixedAngle(eemeralds_cur[j])>>ANGLETOFINESHIFT) & FINEMASK; x = (BASEVIDWIDTH<<(FRACBITS-1)) + FixedMul(FINECOSINE(fa),radius); y = (BASEVIDHEIGHT<<(FRACBITS-1)) + FixedMul(FINESINE(fa),radius); - eemeralds_cur[j] += (360/7); - if (i & 1) - eemeralds_cur[j]++; + eemeralds_cur[j] += (360<>ANGLETOFINESHIFT) & FINEMASK; + fa = (FixedAngle(eemeralds_cur[0])>>ANGLETOFINESHIFT) & FINEMASK; x = (BASEVIDWIDTH<<(FRACBITS-1)) + FixedMul(FINECOSINE(fa),radius); y = ((BASEVIDHEIGHT+16)<<(FRACBITS-1)) + FixedMul(FINESINE(fa),radius); - eemeralds_cur[0] += (360/7); - if (i & 1) - eemeralds_cur[0]++; + eemeralds_cur[0] += (360< Date: Sun, 28 Jul 2019 17:47:57 +0100 Subject: [PATCH 098/128] * Fix crash error in GL. * Re-enable the perplayer stuff in V_DrawFadeFill - not worth having it disabled when it'll just have to be re-enabled later. * Remove some "consistency with software" stuff in hw_draw.c that already has equivalents --- src/f_finale.c | 5 ----- src/hardware/hw_draw.c | 10 ---------- src/v_video.c | 9 +-------- 3 files changed, 1 insertion(+), 23 deletions(-) diff --git a/src/f_finale.c b/src/f_finale.c index a93163fcc..72bf17f1f 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1599,17 +1599,12 @@ void F_EndingTicker(void) if (++finalecount == INFLECTIONPOINT && goodending) // time to swap some assets { - Z_Free(endegrk[0]); endegrk[0] = W_CachePatchName("ENDEGRK2", PU_LEVEL); - Z_Free(endegrk[1]); endegrk[1] = W_CachePatchName("ENDEGRK3", PU_LEVEL); - Z_Free(endglow[0]); endglow[0] = W_CachePatchName("ENDGLOW2", PU_LEVEL); - Z_Free(endglow[1]); endglow[1] = W_CachePatchName("ENDGLOW3", PU_LEVEL); - Z_Free(endxpld[0]); endxpld[0] = W_CachePatchName("ENDEGRK4", PU_LEVEL); } diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 6bfd2a4dc..1ba357105 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -706,9 +706,6 @@ void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 ac UINT8 perplayershuffle = 0; - if (w < 0 || h < 0) - return; // consistency w/ software - // 3--2 // | /| // |/ | @@ -870,7 +867,6 @@ void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 ac Surf.FlatColor.rgba = V_GetColor(actualcolor).rgba; Surf.FlatColor.s.alpha = softwaretranstogl[strength]; } - HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } @@ -1092,9 +1088,6 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32 UINT8 perplayershuffle = 0; - if (w < 0 || h < 0) - return; // consistency w/ software - // 3--2 // | /| // |/ | @@ -1263,9 +1256,6 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) UINT8 perplayershuffle = 0; - if (w < 0 || h < 0) - return; // consistency w/ software - // 3--2 // | /| // |/ | diff --git a/src/v_video.c b/src/v_video.c index 1c56770e5..85f22eccb 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -996,12 +996,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ if (!(scrn & V_SCALEPATCHMASK)) { // if it's meant to cover the whole screen, black out the rest - if (x == 0 && SHORT(patch->width) == BASEVIDWIDTH && y == 0 && SHORT(patch->height) == BASEVIDHEIGHT) - { - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[0])); - source = (const UINT8 *)(column) + 3; - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); - } + // no the patch is cropped do not do this ever if (vid.width != BASEVIDWIDTH * dupx) { @@ -1581,7 +1576,6 @@ void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, U } #endif -#if 0 // only if for use in-game, otherwise not worth the processor time if (splitscreen && (c & V_PERPLAYER)) { fixed_t adjusty = ((c & V_NOSCALESTART) ? vid.height : BASEVIDHEIGHT)>>1; @@ -1649,7 +1643,6 @@ void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, U } } } -#endif if (!(c & V_NOSCALESTART)) { From 1d799630af754e7aec7aa01745c21e1d152f0e49 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 28 Jul 2019 22:45:20 +0100 Subject: [PATCH 099/128] Made it possible to just call `EV_CrumbleChain(rover)` in Lua --- src/lua_baselib.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 712bc4045..97d2fdc24 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2047,12 +2047,19 @@ static int lib_pStartQuake(lua_State *L) static int lib_evCrumbleChain(lua_State *L) { - sector_t *sec = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); - ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR)); + sector_t *sec = NULL; + ffloor_t *rover = NULL; NOHUD INLEVEL - /*if (!sec) - return LUA_ErrInvalid(L, "sector_t");*/ + if (lua_isuserdata(L, 2)) + { + sec = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); + rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR)); + if (!sec) + return LUA_ErrInvalid(L, "sector_t"); + } + else + rover = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR)); if (!rover) return LUA_ErrInvalid(L, "ffloor_t"); EV_CrumbleChain(sec, rover); From 5dc095a47d3ae35c189c482f5ee5c1ad6a8051f9 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 28 Jul 2019 22:53:27 +0100 Subject: [PATCH 100/128] Further improvements on MI's request, just to be safe. --- src/lua_baselib.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 97d2fdc24..767ab2dd3 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2051,12 +2051,15 @@ static int lib_evCrumbleChain(lua_State *L) ffloor_t *rover = NULL; NOHUD INLEVEL - if (lua_isuserdata(L, 2)) + if (!lua_isnone(L, 2)) { - sec = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); + if (!lua_isnil(L, 1)) + { + sec = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); + if (!sec) + return LUA_ErrInvalid(L, "sector_t"); + } rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR)); - if (!sec) - return LUA_ErrInvalid(L, "sector_t"); } else rover = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR)); From 47554b57e4bce237e7092a3c77c959cf1d029b05 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 29 Jul 2019 14:55:36 +0100 Subject: [PATCH 101/128] * Made the evaluation screen even more attractive. * Fixed an unused variable warning in lua_skinlib.c. - fixed post-level cutscenes playing when you get game over in MP (still kinda on-topic) Also with apologies to MI: - golden egg statue mode for tutorial, since the grey doesn't contrast enough with the blue and lime green - fixed closed captions for replaced player sounds being incorrect - fixed closed captions overlapping tutorial text --- src/doomstat.h | 2 +- src/f_finale.c | 91 +++++++++++++++++++++++++++-------------------- src/g_game.c | 6 ++-- src/g_game.h | 2 ++ src/lua_baselib.c | 4 +-- src/lua_skinlib.c | 1 - src/m_cond.c | 2 +- src/p_mobj.c | 6 ++++ src/p_setup.c | 2 +- src/p_spec.c | 2 +- src/s_sound.c | 5 +-- src/screen.c | 4 ++- 12 files changed, 76 insertions(+), 51 deletions(-) diff --git a/src/doomstat.h b/src/doomstat.h index 87b98ab40..18300967c 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -234,7 +234,7 @@ extern textprompt_t *textprompts[MAX_PROMPTS]; // For the Custom Exit linedef. extern INT16 nextmapoverride; -extern boolean skipstats; +extern UINT8 skipstats; extern UINT32 ssspheres; // Total # of spheres in a level diff --git a/src/f_finale.c b/src/f_finale.c index 72bf17f1f..cb315be03 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -110,7 +110,7 @@ static INT32 sparklloop; // // PROMPT STATE // -static boolean promptactive = false; +boolean promptactive = false; static mobj_t *promptmo; static INT16 promptpostexectag; static boolean promptblockcontrols; @@ -1284,6 +1284,7 @@ boolean F_CreditResponder(event_t *event) // ============ // EVALUATION // ============ + #define SPARKLLOOPTIME 7 // must be odd void F_StartGameEvaluation(void) @@ -1322,14 +1323,11 @@ void F_GameEvaluationDrawer(void) angle_t fa; INT32 eemeralds_cur; char patchname[7] = "CEMGx0"; + const char* endingtext = (goodending ? "CONGRATULATIONS!" : "TRY AGAIN..."); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // Draw all the good crap here. - if (goodending) - V_DrawString(114, 16, 0, "GOT THEM ALL!"); - else - V_DrawString(124, 16, 0, "TRY AGAIN!"); if (finalecount > 0) { @@ -1420,6 +1418,9 @@ void F_GameEvaluationDrawer(void) V_DrawFixedPatch(x, y, FRACUNIT, ((emeralds & (1<= 5*TICRATE) { V_DrawString(8, 16, V_YELLOWMAP, "Unlocked:"); @@ -1444,28 +1445,18 @@ void F_GameEvaluationDrawer(void) else V_DrawString(8, 96, V_YELLOWMAP, "Prizes not\nawarded in\nmodified games!"); } +#endif } void F_GameEvaluationTicker(void) { - finalecount++; - - if (goodending) + if (++finalecount > 10*TICRATE) { - if (++sparklloop == SPARKLLOOPTIME) // time to roll the randomisation again - { - angle_t workingangle = FixedAngle((M_RandomKey(360))<>ANGLETOFINESHIFT; - fixed_t workingradius = M_RandomKey(26); - sparkloffs[2][0] = sparkloffs[1][0]; - sparkloffs[2][1] = sparkloffs[1][1]; - sparkloffs[1][0] = sparkloffs[0][0]; - sparkloffs[1][1] = sparkloffs[0][1]; - sparkloffs[0][0] = (30<>ANGLETOFINESHIFT; + fixed_t workingradius = M_RandomKey(26); + + sparkloffs[2][0] = sparkloffs[1][0]; + sparkloffs[2][1] = sparkloffs[1][1]; + sparkloffs[1][0] = sparkloffs[0][0]; + sparkloffs[1][1] = sparkloffs[0][1]; + + sparkloffs[0][0] = (30< 10*TICRATE) - F_StartGameEnd(); } #undef SPARKLLOOPTIME @@ -1508,8 +1524,8 @@ void F_GameEvaluationTicker(void) // ENDING // ========== -#define SPARKLLOOPTIME 15 // must be odd #define INFLECTIONPOINT (6*TICRATE) +#define SPARKLLOOPTIME 15 // must be odd void F_StartEnding(void) { @@ -1594,10 +1610,14 @@ void F_StartEnding(void) void F_EndingTicker(void) { - angle_t workingangle; - fixed_t workingradius; + if (++finalecount > INFLECTIONPOINT*2) + { + F_StartCredits(); + wipetypepre = INT16_MAX; + return; + } - if (++finalecount == INFLECTIONPOINT && goodending) // time to swap some assets + if (goodending && finalecount == INFLECTIONPOINT) // time to swap some assets { endegrk[0] = W_CachePatchName("ENDEGRK2", PU_LEVEL); endegrk[1] = W_CachePatchName("ENDEGRK3", PU_LEVEL); @@ -1610,17 +1630,13 @@ void F_EndingTicker(void) if (++sparklloop == SPARKLLOOPTIME) // time to roll the randomisation again { - sparklloop = 0; - workingangle = FixedAngle((M_RandomRange(-170, 80))<>ANGLETOFINESHIFT; - workingradius = M_RandomKey(26); + angle_t workingangle = FixedAngle((M_RandomRange(-170, 80))<>ANGLETOFINESHIFT; + fixed_t workingradius = M_RandomKey(26); + sparkloffs[0][0] = (30< INFLECTIONPOINT*2) - { - F_StartCredits(); - wipetypepre = INT16_MAX; + sparklloop = 0; } } @@ -2005,7 +2021,6 @@ void F_EndingDrawer(void) } #undef SPARKLLOOPTIME -#undef INFLECTIONPOINT // ========== // GAME END diff --git a/src/g_game.c b/src/g_game.c index c6af0f48d..60262161a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -152,7 +152,7 @@ cutscene_t *cutscenes[128]; textprompt_t *textprompts[MAX_PROMPTS]; INT16 nextmapoverride; -boolean skipstats; +UINT8 skipstats; // Pointers to each CTF flag mobj_t *redflag; @@ -2651,7 +2651,7 @@ void G_DoReborn(INT32 playernum) //nextmapoverride = spstage_start; nextmapoverride = gamemap; countdown2 = TICRATE; - skipstats = true; + skipstats = 2; for (i = 0; i < MAXPLAYERS; i++) { @@ -3180,7 +3180,7 @@ void G_AfterIntermission(void) { HU_ClearCEcho(); - if (mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking) // Start a custom cutscene. + if (mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking && skipstats <= 1) // Start a custom cutscene. F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false); else { diff --git a/src/g_game.h b/src/g_game.h index 3cbde9a3c..f03014439 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -56,6 +56,8 @@ extern INT16 rw_maximums[NUM_WEAPONS]; extern INT32 pausedelay; extern boolean pausebreakkey; +extern boolean promptactive; + // used in game menu extern consvar_t cv_tutorialprompt; extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, cv_consolechat, cv_chatbacktint, cv_chatspamprotection, cv_compactscoreboard; diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 1d69b238b..98f2ba3b8 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2601,12 +2601,12 @@ static int lib_gSetCustomExitVars(lua_State *L) nextmapoverride = (INT16)luaL_checknumber(L, 1); lua_remove(L, 1); // remove nextmapoverride; skipstats now 1 if available } - skipstats = lua_optboolean(L, 1); + skipstats = luaL_optinteger(L, 2, 0); } else { nextmapoverride = 0; - skipstats = false; + skipstats = 0; } // --- diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index cc18ce860..a28f6a359 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -98,7 +98,6 @@ static int skin_get(lua_State *L) { skin_t *skin = *((skin_t **)luaL_checkudata(L, 1, META_SKIN)); enum skin field = luaL_checkoption(L, 2, NULL, skin_opt); - INT32 i; // skins are always valid, only added, never removed I_Assert(skin != NULL); diff --git a/src/m_cond.c b/src/m_cond.c index e03542bf3..539c6d1f6 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -240,7 +240,7 @@ UINT8 M_UpdateUnlockablesAndExtraEmblems(void) if (cechoLines) { char slashed[1024] = ""; - for (i = 0; (i < 21) && (i < 24 - cechoLines); ++i) + for (i = 0; (i < 19) && (i < 24 - cechoLines); ++i) slashed[i] = '\\'; slashed[i] = 0; diff --git a/src/p_mobj.c b/src/p_mobj.c index 9a6e0f2bb..a48ebfc40 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11100,6 +11100,12 @@ You should think about modifying the deathmatch starts to take full advantage of else skyboxviewpnts[mthing->extrainfo] = mobj; break; + case MT_EGGSTATUE: + if (tutorialmode != (mthing->options & MTF_OBJECTSPECIAL)) + { + mobj->color = SKINCOLOR_GOLD; + mobj->colorized = true; + } case MT_EGGMOBILE3: mobj->cusval = mthing->extrainfo; break; diff --git a/src/p_setup.c b/src/p_setup.c index f38ba9334..dfbba0252 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3126,7 +3126,7 @@ boolean P_SetupLevel(boolean skipprecip) R_PrecacheLevel(); nextmapoverride = 0; - skipstats = false; + skipstats = 0; if (!(netgame || multiplayer) && (!modifiedgame || savemoddata)) mapvisited[gamemap-1] |= MV_VISITED; diff --git a/src/p_spec.c b/src/p_spec.c index 3cd0461e2..88dfad70e 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4624,7 +4624,7 @@ DoneSection2: nextmapoverride = (INT16)(lines[lineindex].frontsector->floorheight>>FRACBITS); if (lines[lineindex].flags & ML_NOCLIMB) - skipstats = true; + skipstats = 1; } } break; diff --git a/src/s_sound.c b/src/s_sound.c index 120ba5e50..9b5df072c 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -519,6 +519,7 @@ void S_StartCaption(sfxenum_t sfx_id, INT32 cnum, UINT16 lifespan) void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) { INT32 sep, pitch, priority, cnum; + const sfxenum_t actual_id = sfx_id; sfxinfo_t *sfx; const mobj_t *origin = (const mobj_t *)origin_p; @@ -657,7 +658,7 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) #endif // Handle closed caption input. - S_StartCaption(sfx_id, cnum, MAXCAPTIONTICS); + S_StartCaption(actual_id, cnum, MAXCAPTIONTICS); // Assigns the handle to one of the channels in the // mix/output buffer. @@ -710,7 +711,7 @@ dontplay: #endif // Handle closed caption input. - S_StartCaption(sfx_id, cnum, MAXCAPTIONTICS); + S_StartCaption(actual_id, cnum, MAXCAPTIONTICS); // Assigns the handle to one of the channels in the // mix/output buffer. diff --git a/src/screen.c b/src/screen.c index ac7878c4a..fc3f5b8e8 100644 --- a/src/screen.c +++ b/src/screen.c @@ -438,7 +438,9 @@ void SCR_ClosedCaptions(void) if (gamestate == GS_LEVEL) { - if (splitscreen) + if (promptactive) + basey -= 28; + else if (splitscreen) basey -= 8; else if ((modeattacking == ATTACKING_NIGHTS) || (!(maptol & TOL_NIGHTS) From 62c708e64a6ec889f8b0107dc0b07cd641ee14d3 Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 29 Jul 2019 20:29:02 +0100 Subject: [PATCH 102/128] Two one liners related to angles, so doin' em in a single branch. * If a spring has vertical speed AND horizontal speed, always set the player's angle when touching it. * If you have less than 32 rings and spill them, they now get launched away from the player's motion, rather than in the direction of the camera. --- src/p_inter.c | 9 +++++++-- src/p_map.c | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index abf33429f..5b52f2ffb 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -3652,7 +3652,7 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) { INT32 i; mobj_t *mo; - angle_t fa; + angle_t fa, va; fixed_t ns; fixed_t z; boolean nightsreplace = ((maptol & TOL_NIGHTS) && !G_IsSpecialStage(gamemap)); @@ -3674,6 +3674,11 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) // Spill weapons first P_PlayerWeaponPanelOrAmmoBurst(player); + if (abs(player->mo->momx) > player->mo->scale || abs(player->mo->momy) > player->mo->scale) + va = R_PointToAngle2(player->mo->momx, player->mo->momy, 0, 0)>>ANGLETOFINESHIFT; + else + va = player->mo->angle>>ANGLETOFINESHIFT; + for (i = 0; i < num_rings; i++) { INT32 objType = mobjinfo[MT_RING].reactiontime; @@ -3695,7 +3700,7 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) P_SetScale(mo, player->mo->scale); // Angle offset by player angle, then slightly offset by amount of rings - fa = ((i*FINEANGLES/16) + (player->mo->angle>>ANGLETOFINESHIFT) - ((num_rings-1)*FINEANGLES/32)) & FINEMASK; + fa = ((i*FINEANGLES/16) + va - ((num_rings-1)*FINEANGLES/32)) & FINEMASK; // Make rings spill out around the player in 16 directions like SA, but spill like Sonic 2. // Technically a non-SA way of spilling rings. They just so happen to be a little similar. diff --git a/src/p_map.c b/src/p_map.c index e78dd1e84..8fe9fb4ae 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -342,7 +342,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) if (horizspeed) { object->player->drawangle = spring->angle; - if (object->player->cmd.forwardmove == 0 && object->player->cmd.sidemove == 0) + if (vertispeed || (object->player->cmd.forwardmove == 0 && object->player->cmd.sidemove == 0)) { object->angle = spring->angle; From a6a3048c8f9ae1c8dd914754789f12713f84c1af Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 29 Jul 2019 21:03:28 +0100 Subject: [PATCH 103/128] * Fix diagonal spring ring assortments being forced up/down with slopes. --- src/p_mobj.c | 82 +++++++++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 36 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 1cb7f742d..7c50967cb 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -12355,28 +12355,33 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) if (nightsreplace) ringthing = MT_NIGHTSSTAR; + if (mthing->options & MTF_OBJECTFLIP) + { + z = ( +#ifdef ESLOPE + sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : +#endif + sec->ceilingheight) - mobjinfo[ringthing].height; + if (mthing->options >> ZSHIFT) + z -= ((mthing->options >> ZSHIFT) << FRACBITS); + } + else + { + z = ( +#ifdef ESLOPE + sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : +#endif + sec->floorheight); + if (mthing->options >> ZSHIFT) + z += ((mthing->options >> ZSHIFT) << FRACBITS); + } + for (r = 1; r <= 5; r++) { if (mthing->options & MTF_OBJECTFLIP) - { - z = ( -#ifdef ESLOPE - sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : -#endif - sec->ceilingheight) - mobjinfo[ringthing].height - dist*r; - if (mthing->options >> ZSHIFT) - z -= ((mthing->options >> ZSHIFT) << FRACBITS); - } + z -= dist; else - { - z = ( -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight) + dist*r; - if (mthing->options >> ZSHIFT) - z += ((mthing->options >> ZSHIFT) << FRACBITS); - } + z += dist; mobj = P_SpawnMobj(x, y, z, ringthing); @@ -12410,31 +12415,36 @@ void P_SpawnHoopsAndRings(mapthing_t *mthing, boolean bonustime) closestangle = FixedAngle(mthing->angle*FRACUNIT); fa = (closestangle >> ANGLETOFINESHIFT); + if (mthing->options & MTF_OBJECTFLIP) + { + z = ( +#ifdef ESLOPE + sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : +#endif + sec->ceilingheight) - mobjinfo[ringthing].height; + if (mthing->options >> ZSHIFT) + z -= ((mthing->options >> ZSHIFT) << FRACBITS); + } + else + { + z = ( +#ifdef ESLOPE + sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : +#endif + sec->floorheight); + if (mthing->options >> ZSHIFT) + z += ((mthing->options >> ZSHIFT) << FRACBITS); + } + for (r = 1; r <= iterations; r++) { x += FixedMul(64*FRACUNIT, FINECOSINE(fa)); y += FixedMul(64*FRACUNIT, FINESINE(fa)); if (mthing->options & MTF_OBJECTFLIP) - { - z = ( -#ifdef ESLOPE - sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : -#endif - sec->ceilingheight) - mobjinfo[ringthing].height - 64*FRACUNIT*r; - if (mthing->options >> ZSHIFT) - z -= ((mthing->options >> ZSHIFT) << FRACBITS); - } + z -= 64*FRACUNIT; else - { - z = ( -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight) + 64*FRACUNIT*r; - if (mthing->options >> ZSHIFT) - z += ((mthing->options >> ZSHIFT) << FRACBITS); - } + z += 64*FRACUNIT; mobj = P_SpawnMobj(x, y, z, ringthing); From deaee586ed035859662037d10f2f5c152fda0c0e Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 29 Jul 2019 21:05:30 +0100 Subject: [PATCH 104/128] Make MANIASPHERES' #define'd away stuff also recreatable with SOC, since I want to release it publically if the team don't want it. --- src/info.c | 6 +++++- src/p_setup.c | 12 +----------- src/st_stuff.c | 6 +----- 3 files changed, 7 insertions(+), 17 deletions(-) diff --git a/src/info.c b/src/info.c index a4446d657..0ae723546 100644 --- a/src/info.c +++ b/src/info.c @@ -1791,7 +1791,11 @@ state_t states[NUMSTATES] = // Blue Sphere for special stages {SPR_SPHR, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_BLUESPHERE - {SPR_SPHR, FF_FULLBRIGHT|FF_ANIMATE|FF_RANDOMANIM, -1, {NULL}, 1, 4, S_NULL}, // S_BLUESPHEREBONUS + {SPR_SPHR, FF_FULLBRIGHT +#ifdef MANIASPHERES + |FF_ANIMATE|FF_RANDOMANIM +#endif + , -1, {NULL}, 1, 4, S_NULL}, // S_BLUESPHEREBONUS {SPR_SPHR, 0, 20, {NULL}, 0, 0, S_NULL}, // S_BLUESPHERESPARK // Bomb Sphere diff --git a/src/p_setup.c b/src/p_setup.c index c0aa7ffa3..0b391f390 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -859,12 +859,7 @@ void P_ReloadRings(void) mt->z = (INT16)(R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS) ->sector->floorheight>>FRACBITS); - P_SpawnHoopsAndRings(mt, -#ifdef MANIASPHERES - true); -#else - !G_IsSpecialStage(gamemap)); // prevent flashing spheres in special stages -#endif + P_SpawnHoopsAndRings(mt, true); } } for (i = 0; i < numHoops; i++) @@ -878,11 +873,6 @@ void P_SwitchSpheresBonusMode(boolean bonustime) mobj_t *mo; thinker_t *th; -#ifndef MANIASPHERES - if (G_IsSpecialStage(gamemap)) // prevent flashing spheres in special stages - return; -#endif - // scan the thinkers to find spheres to switch for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { diff --git a/src/st_stuff.c b/src/st_stuff.c index 4122793ad..3b8fc749d 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1617,12 +1617,8 @@ static void ST_drawNiGHTSHUD(void) #endif ST_DrawTopLeftOverlayPatch(16, 8, nbracket); if (G_IsSpecialStage(gamemap)) -#ifdef MANIASPHERES ST_DrawTopLeftOverlayPatch(24, 16, ( - (stplyr->bonustime && (leveltime & 4)) ? nssbon : nsshud)); -#else - ST_DrawTopLeftOverlayPatch(24, 16, (nsshud)); -#endif + (stplyr->bonustime && (leveltime & 4) && (states[S_BLUESPHEREBONUS].frame & FF_ANIMATE)) ? nssbon : nsshud)); else ST_DrawTopLeftOverlayPatch(24, 16, *(((stplyr->bonustime) ? nbon : nhud)+((leveltime/2)%12))); From f141220e824363713ed758e129316976677e81df Mon Sep 17 00:00:00 2001 From: toaster Date: Mon, 29 Jul 2019 22:13:12 +0100 Subject: [PATCH 105/128] Added escape pod. Okay, now I'm truly done with this branch. https://cdn.discordapp.com/attachments/249925765423038464/605506507345362964/srb20033.gif --- src/f_finale.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/f_finale.c b/src/f_finale.c index cb315be03..3d1b2ab83 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -104,6 +104,7 @@ static patch_t *endfwrk[3]; // firework - replaced with skin when good ending static patch_t *endspkl[3]; // sparkle static patch_t *endglow[2]; // glow aura - replaced with black rock's midway through good ending static patch_t *endxpld[4]; // mini explosion +static patch_t *endescp[5]; // escape pod + flame static INT32 sparkloffs[3][2]; // eggrock explosions/blackrock sparkles static INT32 sparklloop; @@ -1571,6 +1572,12 @@ void F_StartEnding(void) endxpld[2] = W_CachePatchName("ENDXPLD2", PU_LEVEL); endxpld[3] = W_CachePatchName("ENDXPLD3", PU_LEVEL); + endescp[0] = W_CachePatchName("ENDESCP0", PU_LEVEL); + endescp[1] = W_CachePatchName("ENDESCP1", PU_LEVEL); + endescp[2] = W_CachePatchName("ENDESCP2", PU_LEVEL); + endescp[3] = W_CachePatchName("ENDESCP3", PU_LEVEL); + endescp[4] = W_CachePatchName("ENDESCP4", PU_LEVEL); + // so we only need to check once if ((goodending = ALL7EMERALDS(emeralds))) { @@ -1703,6 +1710,20 @@ void F_EndingDrawer(void) V_DrawFixedPatch(-(x/5), -(y/5), FRACUNIT, 0, endbgsp[1], NULL); // sun V_DrawFixedPatch( 0, -(y/2), FRACUNIT, 0, endbgsp[2], NULL); // planet + // player's escape pod + V_DrawFixedPatch((200< -19) + { + INT32 trans = (-parallaxticker)>>1; + if (trans < 0) + trans = 0; + V_DrawFixedPatch((200< 0) // gunchedrock { INT32 scale = FRACUNIT + ((parallaxticker-10)<<7); From 66f84efd02cf24f141d34d0ce31fe2b61b6cd776 Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Mon, 29 Jul 2019 17:56:35 -0400 Subject: [PATCH 106/128] SDL2: fixed compiling mixer interface with MSVC --- src/sdl/mixer_sound.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index a1319dbec..6e92a6f0b 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -98,8 +98,8 @@ static INT32 current_track; static void var_cleanup(void) { - loop_point = song_length =\ - music_bytes = fading_source = fading_target =\ + song_length = loop_point = 0.0f; + music_bytes = fading_source = fading_target =\ fading_timer = fading_duration = 0; songpaused = is_looping =\ @@ -569,7 +569,7 @@ static void music_loop(void) { Mix_PlayMusic(music, 0); Mix_SetMusicPosition(loop_point); - music_bytes = loop_point*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetSongPosition) + music_bytes = (UINT32)(loop_point*44100.0L*4); //assume 44.1khz, 4-byte length (see I_GetSongPosition) } else I_StopSong(); @@ -843,7 +843,7 @@ boolean I_SetSongPosition(UINT32 position) Mix_RewindMusic(); // needed for mp3 if(Mix_SetMusicPosition((float)(position/1000.0L)) == 0) - music_bytes = position/1000.0L*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetSongPosition) + music_bytes = (UINT32)(position/1000.0L*44100.0L*4); //assume 44.1khz, 4-byte length (see I_GetSongPosition) else // NOTE: This block fires on incorrect song format, // NOT if position input is greater than song length. @@ -887,7 +887,7 @@ UINT32 I_GetSongPosition(void) if (!music || I_SongType() == MU_MID) return 0; else - return music_bytes/44100.0L*1000.0L/4; //assume 44.1khz + return (UINT32)(music_bytes/44100.0L*1000.0L/4); //assume 44.1khz // 4 = byte length for 16-bit samples (AUDIO_S16SYS), stereo (2-channel) // This is hardcoded in I_StartupSound. Other formats for factor: // 8M: 1 | 8S: 2 | 16M: 2 | 16S: 4 From b77780e1e7bdff77a836f50c4e9ac9dde6a8b54c Mon Sep 17 00:00:00 2001 From: Alam Ed Arias Date: Mon, 29 Jul 2019 19:02:45 -0400 Subject: [PATCH 107/128] Fix building with MSVC --- src/p_saveg.c | 2 +- src/p_user.c | 2 +- src/r_things.c | 6 +++++- src/s_sound.c | 4 +++- src/sdl/Srb2SDL-vc10.vcxproj | 2 ++ src/sdl/Srb2SDL-vc10.vcxproj.filters | 7 +++++++ src/win32/Srb2win-vc10.vcxproj | 2 ++ src/win32/Srb2win-vc10.vcxproj.filters | 8 ++++++++ 8 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/p_saveg.c b/src/p_saveg.c index 2e4ba9228..09df38eb0 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -3408,7 +3408,7 @@ static void P_NetUnArchiveThinkers(void) { for (;;) { - thinker_t* th; + thinker_t* th = NULL; tclass = READUINT8(save_p); if (tclass == tc_end) diff --git a/src/p_user.c b/src/p_user.c index 6761d567d..b758cebe4 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2049,7 +2049,7 @@ boolean P_PlayerHitFloor(player_t *player) fixed_t mu = FixedMul(player->maxdash, player->mo->scale); fixed_t mu2 = FixedHypot(player->mo->momx, player->mo->momy); fixed_t ev; - mobj_t *missile; + mobj_t *missile = NULL; if (mu2 < mu) mu2 = mu; ev = (50*FRACUNIT - (mu/25))/50; diff --git a/src/r_things.c b/src/r_things.c index 4b1586455..c791571ac 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2446,9 +2446,11 @@ static void R_DrawMaskedList (drawnode_t* head) void R_DrawMasked(maskcount_t* masks, UINT8 nummasks) { - drawnode_t heads[nummasks]; /**< Drawnode lists; as many as number of views/portals. */ + drawnode_t *heads; /**< Drawnode lists; as many as number of views/portals. */ SINT8 i; + heads = calloc(nummasks, sizeof(drawnode_t)); + for (i = 0; i < nummasks; i++) { heads[i].next = heads[i].prev = &heads[i]; @@ -2474,6 +2476,8 @@ void R_DrawMasked(maskcount_t* masks, UINT8 nummasks) R_DrawMaskedList(&heads[nummasks - 1]); R_ClearDrawNodes(&heads[nummasks - 1]); } + + free(heads); } // ========================================================================== diff --git a/src/s_sound.c b/src/s_sound.c index 2db8392d7..66b5d4f72 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1988,8 +1988,10 @@ void GameMIDIMusic_OnChange(void) } } +#ifdef HAVE_OPENMPT void ModFilter_OnChange(void) { if (openmpt_mhandle) openmpt_module_set_render_param(openmpt_mhandle, OPENMPT_MODULE_RENDER_INTERPOLATIONFILTER_LENGTH, cv_modfilter.value); -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj index d05a0d324..72c38b3dc 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj +++ b/src/sdl/Srb2SDL-vc10.vcxproj @@ -277,6 +277,7 @@ + @@ -430,6 +431,7 @@ + diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters index ca6bd38d2..9e442000f 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj.filters +++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters @@ -453,6 +453,9 @@ Hw_Hardware + + R_Rend + @@ -894,6 +897,10 @@ Hw_Hardware + + + R_Rend + diff --git a/src/win32/Srb2win-vc10.vcxproj b/src/win32/Srb2win-vc10.vcxproj index acab2507a..c0fe8eda9 100644 --- a/src/win32/Srb2win-vc10.vcxproj +++ b/src/win32/Srb2win-vc10.vcxproj @@ -293,6 +293,7 @@ + @@ -443,6 +444,7 @@ + diff --git a/src/win32/Srb2win-vc10.vcxproj.filters b/src/win32/Srb2win-vc10.vcxproj.filters index c21cedb8a..93806e395 100644 --- a/src/win32/Srb2win-vc10.vcxproj.filters +++ b/src/win32/Srb2win-vc10.vcxproj.filters @@ -456,6 +456,10 @@ Hw_Hardware + + + R_Rend + @@ -857,6 +861,10 @@ Hw_Hardware + + + R_Rend + From 18e43a5cef6a45ee1f4c5c779bcf8e48ff9e7d65 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 30 Jul 2019 16:44:40 +0100 Subject: [PATCH 108/128] * Fix "exitlevel" being counted as a special stage success despite not giving you an emerald by inverting stagefailed's default value, since there's only a limited number of ways you can WIN at a special stage. * Correct a potential source of desync in P_GiveEmerald. --- src/p_inter.c | 3 +++ src/p_setup.c | 2 +- src/p_tick.c | 3 --- src/p_user.c | 37 ++++++++++++++++++++++++++++++------- 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/src/p_inter.c b/src/p_inter.c index abf33429f..486c39fb7 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -670,7 +670,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) P_DoMatchSuper(player); } else + { emeralds |= special->info->speed; + stagefailed = false; + } if (special->target && special->target->type == MT_EMERALDSPAWN) { diff --git a/src/p_setup.c b/src/p_setup.c index c0aa7ffa3..976d19190 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2215,7 +2215,7 @@ static void P_LevelInitStuff(void) ssspheres = timeinmap = 0; // special stage - stagefailed = false; + stagefailed = true; // assume failed unless proven otherwise - P_GiveEmerald or emerald touchspecial // Reset temporary record data memset(&ntemprecords, 0, sizeof(nightsdata_t)); diff --git a/src/p_tick.c b/src/p_tick.c index a0f6edef9..cfdd54eb2 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -518,10 +518,7 @@ static inline void P_DoSpecialStageStuff(void) } } else - { sstimer = 0; - stagefailed = true; - } } } diff --git a/src/p_user.c b/src/p_user.c index b758cebe4..cdf8c246c 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -302,15 +302,39 @@ void P_GiveEmerald(boolean spawnObj) S_StartSound(NULL, sfx_cgot); // Got the emerald! emeralds |= (1 << em); + stagefailed = false; - if (spawnObj && playeringame[consoleplayer]) + if (spawnObj) { // The Chaos Emerald begins to orbit us! - // Only give it to ONE person! - mobj_t *emmo = P_SpawnMobjFromMobj(players[consoleplayer].mo, 0, 0, players[consoleplayer].mo->height, MT_GOTEMERALD); - P_SetTarget(&emmo->target, players[consoleplayer].mo); - P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em); - P_SetTarget(&players[consoleplayer].mo->tracer, emmo); + // Only visibly give it to ONE person! + UINT8 i, pnum = ((playeringame[consoleplayer]) && (!players[consoleplayer].spectator) && (players[consoleplayer].mo)) ? consoleplayer : 255; + for (i = 0; i < MAXPLAYERS; i++) + { + mobj_t *emmo; + if (!playeringame[i]) + continue; + if (players[i].spectator) + continue; + if (!players[i].mo) + continue; + + emmo = P_SpawnMobjFromMobj(players[i].mo, 0, 0, players[i].mo->height, MT_GOTEMERALD); + P_SetTarget(&emmo->target, players[i].mo); + P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em); + P_SetTarget(&players[i].mo->tracer, emmo); + + if (pnum == 255) + { + i = pnum; + continue; + } + + if (i == pnum) + continue; + + emmo->flags2 |= MF2_DONTDRAW; + } } } @@ -615,7 +639,6 @@ static void P_DeNightserizePlayer(player_t *player) if (playeringame[i] && players[i].powers[pw_carry] == CR_NIGHTSMODE) players[i].nightstime = 1; // force everyone else to fall too. player->exiting = 3*TICRATE; - stagefailed = true; // NIGHT OVER // If you screwed up, kiss your score and ring bonus goodbye. // But only do this in special stage (and instakill!) In regular stages, wait til we hit the ground. From d541bb7eadb791416450d13cf7e2d28e541f2677 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 30 Jul 2019 17:24:21 +0100 Subject: [PATCH 109/128] * Fix something I neglected earlier when fixing Ghosts and Replays for 2.2 - the fact that the player's skin will change if they don't have NiGHTS sprites like Sonic does not being accomodated. --- src/g_game.c | 8 +++++++- src/g_game.h | 4 +++- src/p_user.c | 3 ++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 95cc2288d..3cb5da1b5 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4366,7 +4366,7 @@ void G_WriteGhostTic(mobj_t *ghost) ghostext.flags = 0; } - if (ghost->player && ghost->player->followmobj) + if (ghost->player && ghost->player->followmobj) // bloats tails runs but what can ya do { INT16 temp; @@ -4592,6 +4592,9 @@ void G_GhostTicker(void) switch(g->color) { default: + case GHC_RETURNSKIN: + g->mo->skin = g->oldmo.skin; + // fallthru case GHC_NORMAL: // Go back to skin color g->mo->color = g->oldmo.color; break; @@ -4602,6 +4605,9 @@ void G_GhostTicker(void) case GHC_FIREFLOWER: // Fireflower g->mo->color = SKINCOLOR_WHITE; break; + case GHC_NIGHTSSKIN: // not actually a colour + g->mo->skin = &skins[DEFAULTNIGHTSSKIN]; + break; } } if (xziptic & EZT_FLIP) diff --git a/src/g_game.h b/src/g_game.h index 3cbde9a3c..96a192ee8 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -140,7 +140,9 @@ typedef enum GHC_NORMAL = 0, GHC_SUPER, GHC_FIREFLOWER, - GHC_INVINCIBLE + GHC_INVINCIBLE, + GHC_NIGHTSSKIN, // not actually a colour + GHC_RETURNSKIN // ditto } ghostcolor_t; // Record/playback tics diff --git a/src/p_user.c b/src/p_user.c index cdf8c246c..7bd2af127 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -621,7 +621,7 @@ static void P_DeNightserizePlayer(player_t *player) player->mo->skin = &skins[player->skin]; player->followitem = skins[player->skin].followitem; player->mo->color = player->skincolor; - G_GhostAddColor(GHC_NORMAL); + G_GhostAddColor(GHC_RETURNSKIN); // Restore aiming angle if (player == &players[consoleplayer]) @@ -739,6 +739,7 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) if (!(cv_debug || devparm) && !(netgame || multiplayer || demoplayback)) player->mo->color = skins[DEFAULTNIGHTSSKIN].prefcolor; player->followitem = skins[DEFAULTNIGHTSSKIN].followitem; + G_GhostAddColor(GHC_NIGHTSSKIN); } player->nightstime = player->startedtime = player->lapstartedtime = nighttime*TICRATE; From 69e573517f31a9b3c19d31f0f42f6e3cbde32862 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 30 Jul 2019 17:48:13 +0100 Subject: [PATCH 110/128] Fix lua scripts erroring on the title screen because they're run there but it's not counted as GS_LEVEL (aka #168). --- src/f_finale.h | 1 - src/g_state.h | 1 + src/lua_baselib.c | 2 +- src/lua_consolelib.c | 2 +- src/lua_maplib.c | 51 +++++++++++++++++--------------------------- src/lua_mobjlib.c | 9 ++++---- src/lua_playerlib.c | 9 ++++---- src/lua_thinkerlib.c | 9 ++++---- 8 files changed, 37 insertions(+), 47 deletions(-) diff --git a/src/f_finale.h b/src/f_finale.h index c0c6360c3..29e9b4d8c 100644 --- a/src/f_finale.h +++ b/src/f_finale.h @@ -82,7 +82,6 @@ typedef enum // Current menu parameters -extern UINT8 titlemapinaction; extern mobj_t *titlemapcameraref; extern char curbgname[8]; extern SINT8 curfadevalue; diff --git a/src/g_state.h b/src/g_state.h index 76c9bd16f..7ee0cfb63 100644 --- a/src/g_state.h +++ b/src/g_state.h @@ -50,6 +50,7 @@ typedef enum } gameaction_t; extern gamestate_t gamestate; +extern UINT8 titlemapinaction; extern UINT8 ultimatemode; // was sk_insane extern gameaction_t gameaction; diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 1d69b238b..7592fdf48 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -33,7 +33,7 @@ #define NOHUD if (hud_running)\ return luaL_error(L, "HUD rendering code should not call this function!"); -#define INLEVEL if (gamestate != GS_LEVEL)\ +#define INLEVEL if (gamestate != GS_LEVEL && !titlemapinaction)\ return luaL_error(L, "This function can only be used in a level!"); boolean luaL_checkboolean(lua_State *L, int narg) { diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 98d18d8db..ed0295ca1 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -29,7 +29,7 @@ return luaL_error(L, "HUD rendering code should not call this function!"); #define NOHOOK if (!lua_lumploading)\ return luaL_error(L, "This function cannot be called from within a hook or coroutine!"); // for functions only allowed within a level -#define INLEVEL if (gamestate != GS_LEVEL)\ +#define INLEVEL if (gamestate != GS_LEVEL && !titlemapinaction)\ return luaL_error(L, "This function can only be used in a level!"); static const char *cvname = NULL; diff --git a/src/lua_maplib.c b/src/lua_maplib.c index ded90daf0..1ab2828bf 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -29,6 +29,9 @@ #include "fastcmp.h" #include "doomstat.h" +#define INLEVEL if (gamestate != GS_LEVEL && !titlemapinaction)\ +return luaL_error(L, "This function can only be used in a level!"); + enum sector_e { sector_valid = 0, sector_floorheight, @@ -333,8 +336,7 @@ static int lib_iterateSectorThinglist(lua_State *L) mobj_t *state = NULL; mobj_t *thing = NULL; - if (gamestate != GS_LEVEL) - return luaL_error(L, "This function can only be used in a level!"); + INLEVEL if (lua_gettop(L) < 2) return luaL_error(L, "Don't call sector.thinglist() directly, use it as 'for rover in sector.thinglist do end'."); @@ -369,8 +371,7 @@ static int lib_iterateSectorFFloors(lua_State *L) ffloor_t *state = NULL; ffloor_t *ffloor = NULL; - if (gamestate != GS_LEVEL) - return luaL_error(L, "This function can only be used in a level!"); + INLEVEL if (lua_gettop(L) < 2) return luaL_error(L, "Don't call sector.ffloors() directly, use it as 'for rover in sector.ffloors do end'."); @@ -1251,8 +1252,7 @@ static int bbox_get(lua_State *L) static int lib_iterateSectors(lua_State *L) { size_t i = 0; - if (gamestate != GS_LEVEL) - return luaL_error(L, "This function can only be used in a level!"); + INLEVEL if (lua_gettop(L) < 2) return luaL_error(L, "Don't call sectors.iterate() directly, use it as 'for sector in sectors.iterate do end'."); lua_settop(L, 2); @@ -1270,8 +1270,7 @@ static int lib_iterateSectors(lua_State *L) static int lib_getSector(lua_State *L) { int field; - if (gamestate != GS_LEVEL) - return luaL_error(L, "You cannot access this outside of a level!"); + INLEVEL lua_settop(L, 2); lua_remove(L, 1); // dummy userdata table is unused. if (lua_isnumber(L, 1)) @@ -1305,8 +1304,7 @@ static int lib_numsectors(lua_State *L) static int lib_iterateSubsectors(lua_State *L) { size_t i = 0; - if (gamestate != GS_LEVEL) - return luaL_error(L, "This function can only be used in a level!"); + INLEVEL if (lua_gettop(L) < 2) return luaL_error(L, "Don't call subsectors.iterate() directly, use it as 'for subsector in subsectors.iterate do end'."); lua_settop(L, 2); @@ -1324,8 +1322,7 @@ static int lib_iterateSubsectors(lua_State *L) static int lib_getSubsector(lua_State *L) { int field; - if (gamestate != GS_LEVEL) - return luaL_error(L, "You cannot access this outside of a level!"); + INLEVEL lua_settop(L, 2); lua_remove(L, 1); // dummy userdata table is unused. if (lua_isnumber(L, 1)) @@ -1359,8 +1356,7 @@ static int lib_numsubsectors(lua_State *L) static int lib_iterateLines(lua_State *L) { size_t i = 0; - if (gamestate != GS_LEVEL) - return luaL_error(L, "This function can only be used in a level!"); + INLEVEL if (lua_gettop(L) < 2) return luaL_error(L, "Don't call lines.iterate() directly, use it as 'for line in lines.iterate do end'."); lua_settop(L, 2); @@ -1378,8 +1374,7 @@ static int lib_iterateLines(lua_State *L) static int lib_getLine(lua_State *L) { int field; - if (gamestate != GS_LEVEL) - return luaL_error(L, "You cannot access this outside of a level!"); + INLEVEL lua_settop(L, 2); lua_remove(L, 1); // dummy userdata table is unused. if (lua_isnumber(L, 1)) @@ -1413,8 +1408,7 @@ static int lib_numlines(lua_State *L) static int lib_iterateSides(lua_State *L) { size_t i = 0; - if (gamestate != GS_LEVEL) - return luaL_error(L, "This function can only be used in a level!"); + INLEVEL if (lua_gettop(L) < 2) return luaL_error(L, "Don't call sides.iterate() directly, use it as 'for side in sides.iterate do end'."); lua_settop(L, 2); @@ -1432,8 +1426,7 @@ static int lib_iterateSides(lua_State *L) static int lib_getSide(lua_State *L) { int field; - if (gamestate != GS_LEVEL) - return luaL_error(L, "You cannot access this outside of a level!"); + INLEVEL lua_settop(L, 2); lua_remove(L, 1); // dummy userdata table is unused. if (lua_isnumber(L, 1)) @@ -1467,8 +1460,7 @@ static int lib_numsides(lua_State *L) static int lib_iterateVertexes(lua_State *L) { size_t i = 0; - if (gamestate != GS_LEVEL) - return luaL_error(L, "This function can only be used in a level!"); + INLEVEL if (lua_gettop(L) < 2) return luaL_error(L, "Don't call vertexes.iterate() directly, use it as 'for vertex in vertexes.iterate do end'."); lua_settop(L, 2); @@ -1486,8 +1478,7 @@ static int lib_iterateVertexes(lua_State *L) static int lib_getVertex(lua_State *L) { int field; - if (gamestate != GS_LEVEL) - return luaL_error(L, "You cannot access this outside of a level!"); + INLEVEL lua_settop(L, 2); lua_remove(L, 1); // dummy userdata table is unused. if (lua_isnumber(L, 1)) @@ -1523,8 +1514,7 @@ static int lib_numvertexes(lua_State *L) static int lib_iterateSegs(lua_State *L) { size_t i = 0; - if (gamestate != GS_LEVEL) - return luaL_error(L, "This function can only be used in a level!"); + INLEVEL if (lua_gettop(L) < 2) return luaL_error(L, "Don't call segs.iterate() directly, use it as 'for seg in segs.iterate do end'."); lua_settop(L, 2); @@ -1542,8 +1532,7 @@ static int lib_iterateSegs(lua_State *L) static int lib_getSeg(lua_State *L) { int field; - if (gamestate != GS_LEVEL) - return luaL_error(L, "You cannot access this outside of a level!"); + INLEVEL lua_settop(L, 2); lua_remove(L, 1); // dummy userdata table is unused. if (lua_isnumber(L, 1)) @@ -1577,8 +1566,7 @@ static int lib_numsegs(lua_State *L) static int lib_iterateNodes(lua_State *L) { size_t i = 0; - if (gamestate != GS_LEVEL) - return luaL_error(L, "This function can only be used in a level!"); + INLEVEL if (lua_gettop(L) < 2) return luaL_error(L, "Don't call nodes.iterate() directly, use it as 'for node in nodes.iterate do end'."); lua_settop(L, 2); @@ -1596,8 +1584,7 @@ static int lib_iterateNodes(lua_State *L) static int lib_getNode(lua_State *L) { int field; - if (gamestate != GS_LEVEL) - return luaL_error(L, "You cannot access this outside of a level!"); + INLEVEL lua_settop(L, 2); lua_remove(L, 1); // dummy userdata table is unused. if (lua_isnumber(L, 1)) diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 8bbbebe1d..5ddcb0ca7 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -22,6 +22,9 @@ #include "lua_libs.h" #include "lua_hud.h" // hud_running errors +#define INLEVEL if (gamestate != GS_LEVEL && !titlemapinaction)\ +return luaL_error(L, "This function can only be used in a level!"); + static const char *const array_opt[] ={"iterate",NULL}; enum mobj_e { @@ -816,8 +819,7 @@ static int mapthing_set(lua_State *L) static int lib_iterateMapthings(lua_State *L) { size_t i = 0; - if (gamestate != GS_LEVEL) - return luaL_error(L, "This function can only be used in a level!"); + INLEVEL if (lua_gettop(L) < 2) return luaL_error(L, "Don't call mapthings.iterate() directly, use it as 'for mapthing in mapthings.iterate do end'."); lua_settop(L, 2); @@ -835,8 +837,7 @@ static int lib_iterateMapthings(lua_State *L) static int lib_getMapthing(lua_State *L) { int field; - if (gamestate != GS_LEVEL) - return luaL_error(L, "You cannot access this outside of a level!"); + INLEVEL lua_settop(L, 2); lua_remove(L, 1); // dummy userdata table is unused. if (lua_isnumber(L, 1)) diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 700dab211..c4b092c6f 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -22,11 +22,13 @@ #include "lua_libs.h" #include "lua_hud.h" // hud_running errors +#define INLEVEL if (gamestate != GS_LEVEL && !titlemapinaction)\ +return luaL_error(L, "This function can only be used in a level!"); + static int lib_iteratePlayers(lua_State *L) { INT32 i = -1; - if (gamestate != GS_LEVEL) - return luaL_error(L, "This function can only be used in a level!"); + INLEVEL if (lua_gettop(L) < 2) { //return luaL_error(L, "Don't call players.iterate() directly, use it as 'for player in players.iterate do end'."); @@ -53,8 +55,7 @@ static int lib_getPlayer(lua_State *L) { const char *field; // i -> players[i] - if (gamestate != GS_LEVEL) - return luaL_error(L, "You cannot access this outside of a level!"); + INLEVEL if (lua_type(L, 2) == LUA_TNUMBER) { lua_Integer i = luaL_checkinteger(L, 2); diff --git a/src/lua_thinkerlib.c b/src/lua_thinkerlib.c index 63eb15846..8fa2869c8 100644 --- a/src/lua_thinkerlib.c +++ b/src/lua_thinkerlib.c @@ -16,6 +16,9 @@ #include "lua_script.h" #include "lua_libs.h" +#define INLEVEL if (gamestate != GS_LEVEL && !titlemapinaction)\ +return luaL_error(L, "This function can only be used in a level!"); + #define META_ITERATIONSTATE "iteration state" /*static const char *const iter_opt[] = { @@ -56,8 +59,7 @@ static int lib_iterateThinkers(lua_State *L) thinker_t *th = NULL, *next = NULL; struct iterationState *it; - if (gamestate != GS_LEVEL) - return luaL_error(L, "This function can only be used in a level!"); + INLEVEL it = luaL_checkudata(L, 1, META_ITERATIONSTATE); @@ -112,8 +114,7 @@ static int lib_startIterate(lua_State *L) { struct iterationState *it; - if (gamestate != GS_LEVEL) - return luaL_error(L, "This function can only be used in a level!"); + INLEVEL lua_pushvalue(L, lua_upvalueindex(1)); it = lua_newuserdata(L, sizeof(struct iterationState)); From 7bff3056720c34bd7419ca3ace4903da0951e418 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 30 Jul 2019 17:57:57 +0100 Subject: [PATCH 111/128] * Strip the word "function" from INLEVEL error messages, since they're now shared between access and function cases. * Move it into lua_script.h, so it's available to everything that needs it. --- src/lua_baselib.c | 2 -- src/lua_consolelib.c | 3 --- src/lua_maplib.c | 3 --- src/lua_mobjlib.c | 3 --- src/lua_playerlib.c | 3 --- src/lua_script.h | 4 ++++ src/lua_thinkerlib.c | 3 --- 7 files changed, 4 insertions(+), 17 deletions(-) diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 7592fdf48..3fd58f637 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -33,8 +33,6 @@ #define NOHUD if (hud_running)\ return luaL_error(L, "HUD rendering code should not call this function!"); -#define INLEVEL if (gamestate != GS_LEVEL && !titlemapinaction)\ -return luaL_error(L, "This function can only be used in a level!"); boolean luaL_checkboolean(lua_State *L, int narg) { luaL_checktype(L, narg, LUA_TBOOLEAN); diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index ed0295ca1..c6856b426 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -28,9 +28,6 @@ return luaL_error(L, "HUD rendering code should not call this function!"); // for functions not allowed in hooks or coroutines (supercedes above) #define NOHOOK if (!lua_lumploading)\ return luaL_error(L, "This function cannot be called from within a hook or coroutine!"); -// for functions only allowed within a level -#define INLEVEL if (gamestate != GS_LEVEL && !titlemapinaction)\ -return luaL_error(L, "This function can only be used in a level!"); static const char *cvname = NULL; diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 1ab2828bf..82843db4e 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -29,9 +29,6 @@ #include "fastcmp.h" #include "doomstat.h" -#define INLEVEL if (gamestate != GS_LEVEL && !titlemapinaction)\ -return luaL_error(L, "This function can only be used in a level!"); - enum sector_e { sector_valid = 0, sector_floorheight, diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 5ddcb0ca7..de1b854f6 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -22,9 +22,6 @@ #include "lua_libs.h" #include "lua_hud.h" // hud_running errors -#define INLEVEL if (gamestate != GS_LEVEL && !titlemapinaction)\ -return luaL_error(L, "This function can only be used in a level!"); - static const char *const array_opt[] ={"iterate",NULL}; enum mobj_e { diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index c4b092c6f..b7bdaa1be 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -22,9 +22,6 @@ #include "lua_libs.h" #include "lua_hud.h" // hud_running errors -#define INLEVEL if (gamestate != GS_LEVEL && !titlemapinaction)\ -return luaL_error(L, "This function can only be used in a level!"); - static int lib_iteratePlayers(lua_State *L) { INT32 i = -1; diff --git a/src/lua_script.h b/src/lua_script.h index b690e4fa7..fcbca2937 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -15,6 +15,7 @@ #include "m_fixed.h" #include "doomtype.h" #include "d_player.h" +#include "g_state.h" #include "blua/lua.h" #include "blua/lualib.h" @@ -97,4 +98,7 @@ void COM_Lua_f(void); // uncomment if you want seg_t/node_t in Lua // #define HAVE_LUA_SEGS +#define INLEVEL if (gamestate != GS_LEVEL && !titlemapinaction)\ +return luaL_error(L, "This can only be used in a level!"); + #endif diff --git a/src/lua_thinkerlib.c b/src/lua_thinkerlib.c index 8fa2869c8..877294898 100644 --- a/src/lua_thinkerlib.c +++ b/src/lua_thinkerlib.c @@ -16,9 +16,6 @@ #include "lua_script.h" #include "lua_libs.h" -#define INLEVEL if (gamestate != GS_LEVEL && !titlemapinaction)\ -return luaL_error(L, "This function can only be used in a level!"); - #define META_ITERATIONSTATE "iteration state" /*static const char *const iter_opt[] = { From 7cb02985f4707f95e4eecbb3102a2d8b8f5a261a Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 31 Jul 2019 23:17:17 +0100 Subject: [PATCH 112/128] * Added boss enable linedef (type 449). - Frontside x offset = boss ID (determined via parameter for all bosses) - Noclimb flag = disable mode - Bosses don't do a fuckin' THING - no state updates, no player searches, no sounds, no lua, no nothin' - and it's all totally netsynced. - The only thing they WILL do is flash infinitely if you hurt them, but this is designed for stuff where you're not meant to be in the same room as the boss til it's activated. - All bosses of all IDs are automatically enabled on mapload, then if an enable mode version of this linedef is present in the map for a specific boss id, that boss id is automatically disabled. * Add multi-boss support via parameter for: - All bosses' MT_BOSSFLYPOINT search - Boss 5's waypoint search - Oldbrak's waypoint search (this one's for you, jood) --- src/p_enemy.c | 52 ++++++++++++++++++++++++++++++-------- src/p_mobj.c | 70 +++++++++++++++++++++++++++++---------------------- src/p_mobj.h | 1 + src/p_saveg.c | 2 ++ src/p_setup.c | 1 + src/p_spec.c | 48 ++++++++++++++++++++++++++++++++++- 6 files changed, 132 insertions(+), 42 deletions(-) diff --git a/src/p_enemy.c b/src/p_enemy.c index 88405437c..18d6f20c0 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -3878,6 +3878,8 @@ bossjustdie: } default: //eggmobiles { + UINT8 extrainfo = (mo->spawnpoint ? mo->spawnpoint->extrainfo : 0); + // Stop exploding and prepare to run. P_SetMobjState(mo, mo->info->xdeathstate); if (P_MobjWasRemoved(mo)) @@ -3897,6 +3899,9 @@ bossjustdie: if (mo2->type != MT_BOSSFLYPOINT) continue; + if (mo2->spawnpoint && mo2->spawnpoint->extrainfo != extrainfo) + continue; + // If this one's further then the last one, don't go for it. if (mo->target && P_AproxDistance(P_AproxDistance(mo->x - mo2->x, mo->y - mo2->y), mo->z - mo2->z) > @@ -12303,6 +12308,7 @@ void A_Boss5FindWaypoint(mobj_t *actor) //INT32 locvar2 = var2; boolean avoidcenter; UINT32 i; + UINT8 extrainfo = (actor->spawnpoint ? actor->spawnpoint->extrainfo : 0); #ifdef HAVE_BLUA if (LUA_CallAction("A_Boss5FindWaypoint", actor)) return; @@ -12312,16 +12318,34 @@ void A_Boss5FindWaypoint(mobj_t *actor) if (locvar1 == 2) // look for the boss waypoint { - for (i = 0; i < nummapthings; i++) + thinker_t *th; + mobj_t *mo2; + P_SetTarget(&actor->tracer, NULL); + // Flee! Flee! Find a point to escape to! If none, just shoot upward! + // scan the thinkers to find the runaway point + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (!mapthings[i].mobj) + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; - if (mapthings[i].mobj->type != MT_BOSSFLYPOINT) + + mo2 = (mobj_t *)th; + + if (mo2->type != MT_BOSSFLYPOINT) continue; - P_SetTarget(&actor->tracer, mapthings[i].mobj); - break; + + if (mo2->spawnpoint && mo2->spawnpoint->extrainfo != extrainfo) + continue; + + // If this one's further then the last one, don't go for it. + if (actor->tracer && + P_AproxDistance(P_AproxDistance(actor->x - mo2->x, actor->y - mo2->y), actor->z - mo2->z) > + P_AproxDistance(P_AproxDistance(actor->x - actor->tracer->x, actor->y - actor->tracer->y), actor->z - actor->tracer->z)) + continue; + + // Otherwise... Do! + P_SetTarget(&actor->tracer, mo2); } - if (i == nummapthings) + if (!actor->tracer) return; // no boss flypoints found } else if (locvar1 == 1) // always go to ambush-marked waypoint @@ -12335,11 +12359,13 @@ void A_Boss5FindWaypoint(mobj_t *actor) continue; if (mapthings[i].mobj->type != MT_FANGWAYPOINT) continue; - if (mapthings[i].options & MTF_AMBUSH) - { - P_SetTarget(&actor->tracer, mapthings[i].mobj); - break; - } + if (mapthings[i].extrainfo != extrainfo) + continue; + if (!(mapthings[i].options & MTF_AMBUSH)) + continue; + + P_SetTarget(&actor->tracer, mapthings[i].mobj); + break; } if (i == nummapthings) @@ -12363,6 +12389,8 @@ void A_Boss5FindWaypoint(mobj_t *actor) continue; if (actor->tracer == mapthings[i].mobj) // this was your tracer last time continue; + if (mapthings[i].extrainfo != extrainfo) + continue; if (mapthings[i].options & MTF_AMBUSH) { if (avoidcenter) @@ -12418,6 +12446,8 @@ void A_Boss5FindWaypoint(mobj_t *actor) continue; if (actor->tracer == mapthings[i].mobj) // this was your tracer last time continue; + if (mapthings[i].extrainfo != extrainfo) + continue; if (mapthings[i].options & MTF_AMBUSH) { if (avoidcenter) diff --git a/src/p_mobj.c b/src/p_mobj.c index 1cb7f742d..fe0044634 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5236,6 +5236,7 @@ static void P_Boss7Thinker(mobj_t *mobj) INT32 i; boolean foundgoop = false; INT32 closestNum; + UINT8 extrainfo = (mobj->spawnpoint ? mobj->spawnpoint->extrainfo : 0); // Looks for players in goop. If you find one, try to jump on him. for (i = 0; i < MAXPLAYERS; i++) @@ -5261,17 +5262,23 @@ static void P_Boss7Thinker(mobj_t *mobj) continue; mo2 = (mobj_t *)th; - if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint) - { - dist = P_AproxDistance(players[i].mo->x - mo2->x, players[i].mo->y - mo2->y); + if (mo2->type != MT_BOSS3WAYPOINT) + continue; + if (!mo2->spawnpoint) + continue; + if (mo2->spawnpoint->extrainfo != extrainfo) + continue; + if (mobj->health <= mobj->info->damage && !(mo2->spawnpoint->options & 7)) + continue; // don't jump to center - if (closestNum == -1 || dist < closestdist) - { - closestNum = (mo2->spawnpoint->options & 7); - closestdist = dist; - foundgoop = true; - } - } + dist = P_AproxDistance(players[i].mo->x - mo2->x, players[i].mo->y - mo2->y); + + if (!(closestNum == -1 || dist < closestdist)) + continue; + + closestNum = (mo2->spawnpoint->options & 7); + closestdist = dist; + foundgoop = true; } waypointNum = closestNum; break; @@ -5280,17 +5287,14 @@ static void P_Boss7Thinker(mobj_t *mobj) if (!foundgoop) { - if (mobj->z > 1056*FRACUNIT) - waypointNum = 0; - else + // Don't jump to the center when health is low. + // Force the player to beat you with missiles. + if (mobj->z <= 1056*FRACUNIT || mobj->health <= mobj->info->damage) waypointNum = 1 + P_RandomKey(4); + else + waypointNum = 0; } - // Don't jump to the center when health is low. - // Force the player to beat you with missiles. - if (mobj->health <= mobj->info->damage && waypointNum == 0) - waypointNum = 1 + P_RandomKey(4); - if (mobj->tracer && mobj->tracer->type == MT_BOSS3WAYPOINT && mobj->tracer->spawnpoint && (mobj->tracer->spawnpoint->options & 7) == waypointNum) { @@ -5299,15 +5303,12 @@ static void P_Boss7Thinker(mobj_t *mobj) else waypointNum--; - waypointNum %= 5; - - if (waypointNum < 0) - waypointNum = 0; + if (mobj->health <= mobj->info->damage) + waypointNum = ((waypointNum + 3) % 4) + 1; // plus four to avoid modulo being negative, minus one to avoid waypoint #0 + else + waypointNum = ((waypointNum + 5) % 5); } - if (waypointNum == 0 && mobj->health <= mobj->info->damage) - waypointNum = 1 + (P_RandomFixed() & 1); - // scan the thinkers to find // the waypoint to use for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) @@ -5316,11 +5317,17 @@ static void P_Boss7Thinker(mobj_t *mobj) continue; mo2 = (mobj_t *)th; - if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && (mo2->spawnpoint->options & 7) == waypointNum) - { - hitspot = mo2; - break; - } + if (mo2->type != MT_BOSS3WAYPOINT) + continue; + if (!mo2->spawnpoint) + continue; + if ((mo2->spawnpoint->options & 7) != waypointNum) + continue; + if (mo2->spawnpoint->extrainfo != extrainfo) + continue; + + hitspot = mo2; + break; } if (hitspot == NULL) @@ -7667,6 +7674,9 @@ void P_MobjThinker(mobj_t *mobj) } else if (mobj->flags & MF_BOSS) { + if (mobj->spawnpoint && (mobj->spawnpoint->extrainfo < 16) && (bossdisabled & (1<spawnpoint->extrainfo))) + return; + #ifdef HAVE_BLUA if (LUAh_BossThinker(mobj)) { diff --git a/src/p_mobj.h b/src/p_mobj.h index bfcb09210..77791f928 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -470,4 +470,5 @@ extern INT32 numhuntemeralds; extern boolean runemeraldmanager; extern UINT16 emeraldspawndelay; extern INT32 numstarposts; +extern UINT16 bossdisabled; #endif diff --git a/src/p_saveg.c b/src/p_saveg.c index 09df38eb0..24b68b971 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -3990,6 +3990,7 @@ static void P_NetArchiveMisc(void) WRITEUINT32(save_p, leveltime); WRITEUINT32(save_p, ssspheres); WRITEINT16(save_p, lastmap); + WRITEUINT16(save_p, bossdisabled); WRITEUINT16(save_p, emeralds); WRITEUINT8(save_p, stagefailed); @@ -4067,6 +4068,7 @@ static inline boolean P_NetUnArchiveMisc(void) leveltime = READUINT32(save_p); ssspheres = READUINT32(save_p); lastmap = READINT16(save_p); + bossdisabled = READUINT16(save_p); emeralds = READUINT16(save_p); stagefailed = READUINT8(save_p); diff --git a/src/p_setup.c b/src/p_setup.c index c0aa7ffa3..4d713881d 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -102,6 +102,7 @@ line_t *lines; side_t *sides; mapthing_t *mapthings; INT32 numstarposts; +UINT16 bossdisabled; boolean levelloading; UINT8 levelfadecol; diff --git a/src/p_spec.c b/src/p_spec.c index 3cd0461e2..f1fb5c82f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3554,6 +3554,29 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } break; + case 449: // Enable bosses with parameter + { + INT32 bossid = sides[line->sidenum[0]].textureoffset>>FRACBITS; + if (bossid & ~15) // if any bits other than first 16 are set + { + CONS_Alert(CONS_WARNING, + M_GetText("Boss enable linedef (tag %d) has an invalid texture x offset.\nConsider changing it or removing it entirely.\n"), + line->tag); + break; + } + if (line->flags & ML_NOCLIMB) + { + bossdisabled |= (1<tag, mo, NULL); break; @@ -6399,7 +6422,10 @@ void P_SpawnSpecials(INT32 fromnetsave) // This used to be used, and *should* be used in the future, // but currently isn't. - (void)fromnetsave; + //(void)fromnetsave; -- hooray, it's used! + + if (!fromnetsave) + bossdisabled = 0; // Init special SECTORs. sector = sectors; @@ -7289,6 +7315,26 @@ void P_SpawnSpecials(INT32 fromnetsave) case 431: break; + case 449: // Enable bosses with parameter + { + INT32 bossid = sides[*lines[i].sidenum].textureoffset>>FRACBITS; + if (bossid & ~15) // if any bits other than first 16 are set + { + CONS_Alert(CONS_WARNING, + M_GetText("Boss enable linedef (tag %d) has an invalid texture x offset.\nConsider changing it or removing it entirely.\n"), + lines[i].tag); + break; + } + if (fromnetsave) + break; + if (!(lines[i].flags & ML_NOCLIMB)) + { + bossdisabled |= (1< Date: Thu, 1 Aug 2019 11:35:04 +0100 Subject: [PATCH 113/128] Ok, now the MobjThinker Lua hook is neutralised properly as well. --- src/p_mobj.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index fe0044634..fe45a799a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7011,6 +7011,9 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->flags & MF_NOTHINK) return; + if ((mobj->flags & MF_BOSS) && mobj->spawnpoint && !(mobj->spawnpoint->extrainfo & ~15) && (bossdisabled & (1<spawnpoint->extrainfo))) + return; + // Remove dead target/tracer. if (mobj->target && P_MobjWasRemoved(mobj->target)) P_SetTarget(&mobj->target, NULL); @@ -7674,9 +7677,6 @@ void P_MobjThinker(mobj_t *mobj) } else if (mobj->flags & MF_BOSS) { - if (mobj->spawnpoint && (mobj->spawnpoint->extrainfo < 16) && (bossdisabled & (1<spawnpoint->extrainfo))) - return; - #ifdef HAVE_BLUA if (LUAh_BossThinker(mobj)) { From 39c15e71b061099465938907fe2398102fc5411b Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 1 Aug 2019 08:01:29 -0400 Subject: [PATCH 114/128] Was reviewing old merge requests as a procrastination technique, and discovered that the followmobj's scale was being inaccurately handled for Smiles' tails! Fixed that... --- src/p_user.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/p_user.c b/src/p_user.c index b758cebe4..2ca6c3535 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -11641,7 +11641,6 @@ void P_PlayerAfterThink(player_t *player) player->followmobj->threshold = player->mo->z; player->followmobj->movecount = player->panim; player->followmobj->angle = horizangle; - player->followmobj->scale = player->mo->scale; P_SetScale(player->followmobj, player->mo->scale); player->followmobj->destscale = player->mo->destscale; player->followmobj->radius = player->mo->radius; From 8fa0641e99b47573184238ce03eb563ab3d890f4 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 1 Aug 2019 18:12:12 +0100 Subject: [PATCH 115/128] Instead of checking whether mobj->spawnpoint->extrainfo is in the correct range every tic, have a lua error for trying to set it outside (since there'll no doubt be other consequences to being outside the range too) --- src/lua_mobjlib.c | 7 ++++++- src/p_mobj.c | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 8bbbebe1d..5fc3babd3 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -804,7 +804,12 @@ static int mapthing_set(lua_State *L) else if(fastcmp(field,"z")) mt->z = (INT16)luaL_checkinteger(L, 3); else if(fastcmp(field,"extrainfo")) - mt->extrainfo = (UINT8)luaL_checkinteger(L, 3); + { + INT32 extrainfo = luaL_checkinteger(L, 3); + if (extrainfo & ~15) + return luaL_error(L, "mapthing_t extrainfo set %d out of range (%d - %d)", extrainfo, 0, 15); + mt->extrainfo = (UINT8)extrainfo; + } else if(fastcmp(field,"mobj")) mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); else diff --git a/src/p_mobj.c b/src/p_mobj.c index fe45a799a..5b924c3eb 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7011,7 +7011,7 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->flags & MF_NOTHINK) return; - if ((mobj->flags & MF_BOSS) && mobj->spawnpoint && !(mobj->spawnpoint->extrainfo & ~15) && (bossdisabled & (1<spawnpoint->extrainfo))) + if ((mobj->flags & MF_BOSS) && mobj->spawnpoint && (bossdisabled & (1<spawnpoint->extrainfo))) return; // Remove dead target/tracer. From 0821f7fb2168c6d063b05f7620baf28c35a52524 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 1 Aug 2019 18:56:00 +0100 Subject: [PATCH 116/128] Add openfloorrover and openceilingrover vars so that PIT_CheckLine can update tmfloorrover and tmceilingrover properly via P_LineOpening ...which should hopefully stop that issue where you just teleport back to the ground. Assuming this works as expected. Also this is untested lol. --- src/p_maputl.c | 13 +++++++++++++ src/p_maputl.h | 1 + 2 files changed, 14 insertions(+) diff --git a/src/p_maputl.c b/src/p_maputl.c index 0ca84096a..4dafbcc7f 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -311,6 +311,7 @@ fixed_t opentop, openbottom, openrange, lowfloor, highceiling; #ifdef ESLOPE pslope_t *opentopslope, *openbottomslope; #endif +ffloor_t *openfloorrover, *openceilingrover; // P_CameraLineOpening // P_LineOpening, but for camera @@ -517,6 +518,8 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) I_Assert(front != NULL); I_Assert(back != NULL); + openfloorrover = openceilingrover = NULL; + { // Set open and high/low values here fixed_t frontheight, backheight; @@ -641,6 +644,8 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) pslope_t *ceilingslope = opentopslope; pslope_t *floorslope = openbottomslope; #endif + ffloor_t *floorrover = NULL; + ffloor_t *ceilingrover = NULL; // Check for frontsector's fake floors for (rover = front->ffloors; rover; rover = rover->next) @@ -668,6 +673,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) #ifdef ESLOPE ceilingslope = *rover->b_slope; #endif + ceilingrover = rover; } else if (bottomheight < highestceiling) highestceiling = bottomheight; @@ -680,6 +686,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) #ifdef ESLOPE floorslope = *rover->t_slope; #endif + floorrover = rover; } else if (topheight > lowestfloor) lowestfloor = topheight; @@ -712,6 +719,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) #ifdef ESLOPE ceilingslope = *rover->b_slope; #endif + ceilingrover = rover; } else if (bottomheight < highestceiling) highestceiling = bottomheight; @@ -724,6 +732,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) #ifdef ESLOPE floorslope = *rover->t_slope; #endif + floorrover = rover; } else if (topheight > lowestfloor) lowestfloor = topheight; @@ -743,6 +752,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) #ifdef ESLOPE ceilingslope = NULL; #endif + ceilingrover = NULL; } else if (polysec->floorheight < highestceiling && delta1 >= delta2) highestceiling = polysec->floorheight; @@ -752,6 +762,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) #ifdef ESLOPE floorslope = NULL; #endif + floorrover = NULL; } else if (polysec->ceilingheight > lowestfloor && delta1 < delta2) lowestfloor = polysec->ceilingheight; @@ -765,6 +776,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) #ifdef ESLOPE openbottomslope = floorslope; #endif + openfloorrover = floorrover; } if (lowestceiling < opentop) { @@ -772,6 +784,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) #ifdef ESLOPE opentopslope = ceilingslope; #endif + openceilingrover = floorrover; } if (lowestfloor > lowfloor) diff --git a/src/p_maputl.h b/src/p_maputl.h index 1fcb68d4c..5042817c5 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -58,6 +58,7 @@ extern fixed_t opentop, openbottom, openrange, lowfloor, highceiling; #ifdef ESLOPE extern pslope_t *opentopslope, *openbottomslope; #endif +extern ffloor_t *openfloorrover, *openceilingrover; void P_LineOpening(line_t *plinedef, mobj_t *mobj); From 67f7c9d7d9d0bcdbc7588d464bad57743e5c08b4 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 1 Aug 2019 20:17:15 +0100 Subject: [PATCH 117/128] Whoops, forgot this part --- src/p_map.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index e78dd1e84..f7e1d72c8 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1808,7 +1808,7 @@ static boolean PIT_CheckLine(line_t *ld) { tmceilingz = opentop; ceilingline = ld; - tmceilingrover = NULL; + tmceilingrover = openceilingrover; #ifdef ESLOPE tmceilingslope = opentopslope; #endif @@ -1817,7 +1817,7 @@ static boolean PIT_CheckLine(line_t *ld) if (openbottom > tmfloorz) { tmfloorz = openbottom; - tmfloorrover = NULL; + tmfloorrover = openfloorrover; #ifdef ESLOPE tmfloorslope = openbottomslope; #endif From ac058529c5b2a7287afd479648ec76e6cfe9cbfd Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Thu, 1 Aug 2019 20:48:24 +0100 Subject: [PATCH 118/128] Whoops the second --- src/p_maputl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/p_maputl.c b/src/p_maputl.c index 4dafbcc7f..740797fb0 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -784,7 +784,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) #ifdef ESLOPE opentopslope = ceilingslope; #endif - openceilingrover = floorrover; + openceilingrover = ceilingrover; } if (lowestfloor > lowfloor) From f2349c5ce485ef169fcc9322e790e722cd0744c6 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 2 Aug 2019 13:18:57 +0100 Subject: [PATCH 119/128] fixed sphere's CA2_MELEE stasis issue --- src/p_user.c | 77 +++++++++++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/src/p_user.c b/src/p_user.c index 29e29d7c1..4a804ace8 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2037,47 +2037,50 @@ boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) else player->pflags &= ~PF_GLIDING; } - else if (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2 && player->mo->state-states != S_PLAY_MELEE_LANDING) + else if (player->charability2 == CA2_MELEE && player->panim == PA_ABILITY2) { - mobjtype_t type = player->revitem; - P_SetPlayerMobjState(player->mo, S_PLAY_MELEE_LANDING); - player->mo->tics = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS; - S_StartSound(player->mo, sfx_s3k8b); - player->pflags |= PF_FULLSTASIS; - - // hearticles - if (type) + if (player->mo->state-states != S_PLAY_MELEE_LANDING) { - UINT8 i = 0; - angle_t throwang = -(2*ANG30); - fixed_t xo = P_ReturnThrustX(player->mo, player->drawangle, 16*player->mo->scale); - fixed_t yo = P_ReturnThrustY(player->mo, player->drawangle, 16*player->mo->scale); - fixed_t zo = 6*player->mo->scale; - fixed_t mu = FixedMul(player->maxdash, player->mo->scale); - fixed_t mu2 = FixedHypot(player->mo->momx, player->mo->momy); - fixed_t ev; - mobj_t *missile = NULL; - if (mu2 < mu) - mu2 = mu; - ev = (50*FRACUNIT - (mu/25))/50; - while (i < 5) - { - missile = P_SpawnMobjFromMobj(player->mo, xo, yo, zo, type); - P_SetTarget(&missile->target, player->mo); - missile->angle = throwang + player->drawangle; - P_Thrust(missile, player->drawangle + ANGLE_90, - P_ReturnThrustY(missile, throwang, mu)); // side to side component - P_Thrust(missile, player->drawangle, mu2); // forward component - P_SetObjectMomZ(missile, (4 + ((i&1)<<1))*FRACUNIT, true); - missile->momz += player->mo->pmomz; - missile->fuse = TICRATE/2; - missile->extravalue2 = ev; + mobjtype_t type = player->revitem; + P_SetPlayerMobjState(player->mo, S_PLAY_MELEE_LANDING); + player->mo->tics = (player->mo->movefactor == FRACUNIT) ? TICRATE/2 : (FixedDiv(35<<(FRACBITS-1), FixedSqrt(player->mo->movefactor)))>>FRACBITS; + S_StartSound(player->mo, sfx_s3k8b); + player->pflags |= PF_FULLSTASIS; - i++; - throwang += ANG30; + // hearticles + if (type) + { + UINT8 i = 0; + angle_t throwang = -(2*ANG30); + fixed_t xo = P_ReturnThrustX(player->mo, player->drawangle, 16*player->mo->scale); + fixed_t yo = P_ReturnThrustY(player->mo, player->drawangle, 16*player->mo->scale); + fixed_t zo = 6*player->mo->scale; + fixed_t mu = FixedMul(player->maxdash, player->mo->scale); + fixed_t mu2 = FixedHypot(player->mo->momx, player->mo->momy); + fixed_t ev; + mobj_t *missile = NULL; + if (mu2 < mu) + mu2 = mu; + ev = (50*FRACUNIT - (mu/25))/50; + while (i < 5) + { + missile = P_SpawnMobjFromMobj(player->mo, xo, yo, zo, type); + P_SetTarget(&missile->target, player->mo); + missile->angle = throwang + player->drawangle; + P_Thrust(missile, player->drawangle + ANGLE_90, + P_ReturnThrustY(missile, throwang, mu)); // side to side component + P_Thrust(missile, player->drawangle, mu2); // forward component + P_SetObjectMomZ(missile, (4 + ((i&1)<<1))*FRACUNIT, true); + missile->momz += player->mo->pmomz; + missile->fuse = TICRATE/2; + missile->extravalue2 = ev; + + i++; + throwang += ANG30; + } + if (mobjinfo[type].seesound && missile) + S_StartSound(missile, missile->info->seesound); } - if (mobjinfo[type].seesound && missile) - S_StartSound(missile, missile->info->seesound); } } else if (player->charability2 == CA2_GUNSLINGER && player->panim == PA_ABILITY2) From 42a36de4595fc55fdbba6ffcd61d94690cf174b6 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Fri, 2 Aug 2019 16:51:44 +0100 Subject: [PATCH 120/128] Modify P_CheckSector with a modified version of Sal's attempted proper fix for polyobjects crushing, so that we only need to check the polyobject's control sector directly in the waypoints code. This time I've definitely fixed that teleport to ground issue I'm pretty sure, I don't get it in my tests at least. --- src/p_map.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++- src/p_polyobj.c | 8 ++-- 2 files changed, 101 insertions(+), 6 deletions(-) diff --git a/src/p_map.c b/src/p_map.c index f7e1d72c8..76bb99bff 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2089,6 +2089,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) #ifdef ESLOPE tmfloorslope = NULL; #endif + tmfloorrover = NULL; } if (polybottom < tmceilingz && abs(delta1) >= abs(delta2)) { @@ -2096,6 +2097,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) #ifdef ESLOPE tmceilingslope = NULL; #endif + tmceilingrover = NULL; } } plink = (polymaplink_t *)(plink->link.next); @@ -4079,6 +4081,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush) boolean P_CheckSector(sector_t *sector, boolean crunch) { msecnode_t *n; + size_t i; nofit = false; crushchange = crunch; @@ -4093,9 +4096,57 @@ boolean P_CheckSector(sector_t *sector, boolean crunch) // First, let's see if anything will keep it from crushing. + + // Sal: This stupid function chain is required to fix polyobjects not being able to crush. + // Monster Iestyn: don't use P_CheckSector actually just look for objects in the blockmap instead + validcount++; + + for (i = 0; i < sector->linecount; i++) + { + if (sector->lines[i]->polyobj) + { + polyobj_t *po = sector->lines[i]->polyobj; + if (po->validcount == validcount) + continue; // skip if already checked + if (!(po->flags & POF_SOLID)) + continue; + if (po->lines[0]->backsector == sector) // Make sure you're currently checking the control sector + { + INT32 x, y; + po->validcount = validcount; + + for (y = po->blockbox[BOXBOTTOM]; y <= po->blockbox[BOXTOP]; ++y) + { + for (x = po->blockbox[BOXLEFT]; x <= po->blockbox[BOXRIGHT]; ++x) + { + mobj_t *mo; + + if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) + continue; + + mo = blocklinks[y * bmapwidth + x]; + + for (; mo; mo = mo->bnext) + { + // Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect + + if (!P_MobjTouchingPolyobj(po, mo)) + continue; + + if (!PIT_ChangeSector(mo, false)) + { + nofit = true; + return nofit; + } + } + } + } + } + } + } + if (sector->numattached) { - size_t i; sector_t *sec; for (i = 0; i < sector->numattached; i++) { @@ -4155,9 +4206,53 @@ boolean P_CheckSector(sector_t *sector, boolean crunch) } while (n); // repeat from scratch until all things left are marked valid // Nothing blocked us, so lets crush for real! + + // Sal: This stupid function chain is required to fix polyobjects not being able to crush. + // Monster Iestyn: don't use P_CheckSector actually just look for objects in the blockmap instead + validcount++; + + for (i = 0; i < sector->linecount; i++) + { + if (sector->lines[i]->polyobj) + { + polyobj_t *po = sector->lines[i]->polyobj; + if (po->validcount == validcount) + continue; // skip if already checked + if (!(po->flags & POF_SOLID)) + continue; + if (po->lines[0]->backsector == sector) // Make sure you're currently checking the control sector + { + INT32 x, y; + po->validcount = validcount; + + for (y = po->blockbox[BOXBOTTOM]; y <= po->blockbox[BOXTOP]; ++y) + { + for (x = po->blockbox[BOXLEFT]; x <= po->blockbox[BOXRIGHT]; ++x) + { + mobj_t *mo; + + if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) + continue; + + mo = blocklinks[y * bmapwidth + x]; + + for (; mo; mo = mo->bnext) + { + // Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect + + if (!P_MobjTouchingPolyobj(po, mo)) + continue; + + PIT_ChangeSector(mo, true); + return nofit; + } + } + } + } + } + } if (sector->numattached) { - size_t i; sector_t *sec; for (i = 0; i < sector->numattached; i++) { diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 475fa41b7..857e6f3d1 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1873,7 +1873,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) po->lines[0]->backsector->floorheight = target->z - amtz; po->lines[0]->backsector->ceilingheight = target->z + amtz; // Sal: Remember to check your sectors! - P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage)); + //P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage)); P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); // Apply action to mirroring polyobjects as well start = 0; @@ -1887,7 +1887,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) po->lines[0]->backsector->floorheight += diffz; // move up/down by same amount as the parent did po->lines[0]->backsector->ceilingheight += diffz; // Sal: Remember to check your sectors! - P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage)); + //P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage)); P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); } @@ -2050,7 +2050,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) po->lines[0]->backsector->floorheight += momz; po->lines[0]->backsector->ceilingheight += momz; // Sal: Remember to check your sectors! - P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage)); // frontsector is NEEDED for crushing + //P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage)); // frontsector is NEEDED for crushing P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); // backsector may not be necessary, but just in case // Apply action to mirroring polyobjects as well @@ -2065,7 +2065,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th) po->lines[0]->backsector->floorheight += momz; po->lines[0]->backsector->ceilingheight += momz; // Sal: Remember to check your sectors! - P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage)); + //P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage)); P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); } } From 8d561334256bc6704634004940fd066aed716b5f Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 2 Aug 2019 20:02:55 +0100 Subject: [PATCH 121/128] Fix old Special Stage failure sounds not always playing. --- src/p_spec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/p_spec.c b/src/p_spec.c index 3cd0461e2..7e1230528 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -4601,7 +4601,10 @@ DoneSection2: if (player->bot) break; if (!(maptol & TOL_NIGHTS) && G_IsSpecialStage(gamemap) && player->nightstime > 6) + { player->nightstime = 6; // Just let P_Ticker take care of the rest. + return; + } // Exit (for FOF exits; others are handled in P_PlayerThink in p_user.c) { From c4f0fdb7837d4c4288bf711b5c2be67ee28a0974 Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 2 Aug 2019 22:52:37 +0100 Subject: [PATCH 122/128] Perfect bonus support for non-NiGHTS special stages --- src/y_inter.c | 137 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 87 insertions(+), 50 deletions(-) diff --git a/src/y_inter.c b/src/y_inter.c index 992193964..42aee79de 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -86,8 +86,8 @@ typedef union INT32 passedx3; INT32 passedx4; - y_bonus_t bonus; - patch_t *bonuspatch; + y_bonus_t bonuses[2]; + patch_t *bonuspatches[2]; patch_t *pscore; // SCORE UINT32 score; // fake score @@ -326,34 +326,36 @@ void Y_IntermissionDrawer(void) // draw the header if (intertic <= 2*TICRATE) animatetic = 0; - else if (!animatetic && data.spec.bonus.points == 0 && data.spec.passed3[0] != '\0') + else if (!animatetic && data.spec.bonuses[0].points == 0 && data.spec.bonuses[1].points == 0 && data.spec.passed3[0] != '\0') animatetic = intertic + TICRATE; if (animatetic && (tic_t)intertic >= animatetic) { const INT32 scradjust = (vid.width/vid.dupx)>>3; // 40 for BASEVIDWIDTH INT32 animatetimer = (intertic - animatetic); - if (animatetimer <= 14) + if (animatetimer <= 16) { - xoffset1 = -(animatetimer * scradjust); - xoffset2 = -((animatetimer-2) * scradjust); - xoffset3 = -((animatetimer-4) * scradjust); - xoffset4 = -((animatetimer-6) * scradjust); - xoffset5 = -((animatetimer-8) * scradjust); + xoffset1 = -(animatetimer * scradjust); + xoffset2 = -((animatetimer- 2) * scradjust); + xoffset3 = -((animatetimer- 4) * scradjust); + xoffset4 = -((animatetimer- 6) * scradjust); + xoffset5 = -((animatetimer- 8) * scradjust); + xoffset6 = -((animatetimer-10) * scradjust); if (xoffset2 > 0) xoffset2 = 0; if (xoffset3 > 0) xoffset3 = 0; if (xoffset4 > 0) xoffset4 = 0; if (xoffset5 > 0) xoffset5 = 0; + if (xoffset6 > 0) xoffset6 = 0; } - else if (animatetimer < 32) + else if (animatetimer < 34) { drawsection = 1; - xoffset1 = (22-animatetimer) * scradjust; - xoffset2 = (24-animatetimer) * scradjust; - xoffset3 = (26-animatetimer) * scradjust; - xoffset4 = (28-animatetimer) * scradjust; - xoffset5 = (30-animatetimer) * scradjust; - xoffset6 = (32-animatetimer) * scradjust; + xoffset1 = (24-animatetimer) * scradjust; + xoffset2 = (26-animatetimer) * scradjust; + xoffset3 = (28-animatetimer) * scradjust; + xoffset4 = (30-animatetimer) * scradjust; + xoffset5 = (32-animatetimer) * scradjust; + xoffset6 = (34-animatetimer) * scradjust; if (xoffset1 < 0) xoffset1 = 0; if (xoffset2 < 0) xoffset2 = 0; if (xoffset3 < 0) xoffset3 = 0; @@ -370,9 +372,9 @@ void Y_IntermissionDrawer(void) if (drawsection == 1) { - const char *ringtext = "\x86" "50 RINGS, NO SHIELD"; - const char *tut1text = "\x86" "PRESS " "\x82" "SPIN"; - const char *tut2text = "\x86" "MID-" "\x82" "JUMP"; + const char *ringtext = "\x82" "50 RINGS, NO SHIELD"; + const char *tut1text = "\x82" "PRESS " "\x80" "SPIN"; + const char *tut2text = "\x82" "MID-" "\x80" "JUMP"; ttheight = 16; V_DrawLevelTitle(data.spec.passedx1 + xoffset1, ttheight, 0, data.spec.passed1); ttheight += V_LevelNameHeight(data.spec.passed3) + 2; @@ -389,6 +391,7 @@ void Y_IntermissionDrawer(void) } else { + INT32 yoffset = 0; if (data.spec.passed1[0] != '\0') { ttheight = 24; @@ -402,22 +405,31 @@ void Y_IntermissionDrawer(void) V_DrawLevelTitle(data.spec.passedx2 + xoffset1, ttheight, 0, data.spec.passed2); } - V_DrawScaledPatch(152 + xoffset3, 108, 0, data.spec.bonuspatch); - V_DrawTallNum(BASEVIDWIDTH + xoffset3 - 68, 109, 0, data.spec.bonus.points); - V_DrawScaledPatch(152 + xoffset4, 124, 0, data.spec.pscore); - V_DrawTallNum(BASEVIDWIDTH + xoffset4 - 68, 125, 0, data.spec.score); + V_DrawScaledPatch(152 + xoffset3, 108, 0, data.spec.bonuspatches[0]); + V_DrawTallNum(BASEVIDWIDTH + xoffset3 - 68, 109, 0, data.spec.bonuses[0].points); + if (data.spec.bonuses[1].display) + { + V_DrawScaledPatch(152 + xoffset4, 124, 0, data.spec.bonuspatches[1]); + V_DrawTallNum(BASEVIDWIDTH + xoffset4 - 68, 125, 0, data.spec.bonuses[1].points); + yoffset = 16; + // hack; pass the buck along... + xoffset4 = xoffset5; + xoffset5 = xoffset6; + } + V_DrawScaledPatch(152 + xoffset4, 124+yoffset, 0, data.spec.pscore); + V_DrawTallNum(BASEVIDWIDTH + xoffset4 - 68, 125+yoffset, 0, data.spec.score); // Draw continues! if (!multiplayer /* && (data.spec.continues & 0x80) */) // Always draw outside of netplay { UINT8 continues = data.spec.continues & 0x7F; - V_DrawScaledPatch(152 + xoffset5, 150, 0, data.spec.pcontinues); + V_DrawScaledPatch(152 + xoffset5, 150+yoffset, 0, data.spec.pcontinues); for (i = 0; i < continues; ++i) { if ((data.spec.continues & 0x80) && i == continues-1 && (endtic < 0 || intertic%20 < 10)) break; - V_DrawContinueIcon(246 + xoffset5 - (i*12), 162, 0, *data.spec.playerchar, *data.spec.playercolor); + V_DrawContinueIcon(246 + xoffset5 - (i*12), 162+yoffset, 0, *data.spec.playerchar, *data.spec.playercolor); } } } @@ -904,7 +916,7 @@ void Y_Ticker(void) { INT32 i; UINT32 oldscore = data.spec.score; - boolean skip = false, super = false; + boolean skip = false, super = false, anybonuses = false; if (!intertic) // first time only { @@ -946,16 +958,26 @@ void Y_Ticker(void) return; } - // ring bonus counts down by 222 each tic - data.spec.bonus.points -= 222; - data.spec.score += 222; - if (data.spec.bonus.points < 0 || skip == true) // went too far + // bonuses count down by 222 each tic + for (i = 0; i < 2; ++i) { - data.spec.score += data.spec.bonus.points; - data.spec.bonus.points = 0; + if (!data.spec.bonuses[i].points) + continue; + + data.spec.bonuses[i].points -= 222; + data.spec.score += 222; + if (data.spec.bonuses[i].points < 0 || skip == true) // too far? + { + data.spec.score += data.spec.bonuses[i].points; + data.spec.bonuses[i].points = 0; + } + if (data.spec.score > MAXSCORE) + data.spec.score = MAXSCORE; + if (data.spec.bonuses[i].points > 0) + anybonuses = true; } - if (!data.spec.bonus.points) + if (!anybonuses) { tallydonetic = intertic; if (!((data.spec.continues & 0x80) || (super && ALL7EMERALDS(emeralds)))) // don't set endtic yet! @@ -1301,7 +1323,9 @@ void Y_StartIntermission(void) // give out ring bonuses Y_AwardSpecialStageBonus(); - data.spec.bonuspatch = W_CachePatchName(data.spec.bonus.patch, PU_STATIC); + for (i = 0; i < 2; ++i) + data.spec.bonuspatches[i] = W_CachePatchName(data.spec.bonuses[i].patch, PU_STATIC); + data.spec.pscore = W_CachePatchName("YB_SCORE", PU_STATIC); data.spec.pcontinues = W_CachePatchName("YB_CONTI", PU_STATIC); @@ -1831,7 +1855,7 @@ static void Y_SetPerfectBonus(player_t *player, y_bonus_t *bstruct) memset(bstruct, 0, sizeof(y_bonus_t)); strncpy(bstruct->patch, "YB_PERFE", sizeof(bstruct->patch)); - if (data.coop.gotperfbonus == -1) + if (intertype != int_coop || data.coop.gotperfbonus == -1) { INT32 sharedringtotal = 0; for (i = 0; i < MAXPLAYERS; i++) @@ -1840,15 +1864,17 @@ static void Y_SetPerfectBonus(player_t *player, y_bonus_t *bstruct) sharedringtotal += players[i].rings; } if (!sharedringtotal || nummaprings == -1 || sharedringtotal < nummaprings) - data.coop.gotperfbonus = 0; + bstruct->display = false; else - data.coop.gotperfbonus = 1; + { + bstruct->display = true; + bstruct->points = 50000; + } } - if (!data.coop.gotperfbonus) + if (intertype != int_coop) return; - bstruct->display = true; - bstruct->points = 50000; + data.coop.gotperfbonus = (bstruct->display ? 1 : 0); } // This list can be extended in the future with SOC/Lua, perhaps. @@ -1953,23 +1979,33 @@ static void Y_AwardCoopBonuses(void) static void Y_AwardSpecialStageBonus(void) { INT32 i, oldscore, ptlives; - y_bonus_t localbonus; + y_bonus_t localbonuses[2]; data.spec.score = players[consoleplayer].score; - memset(&data.spec.bonus, 0, sizeof(data.spec.bonus)); - data.spec.bonuspatch = NULL; + memset(data.spec.bonuses, 0, sizeof(data.spec.bonuses)); + memset(data.spec.bonuspatches, 0, sizeof(data.coop.bonuspatches)); for (i = 0; i < MAXPLAYERS; i++) { oldscore = players[i].score; if (!playeringame[i] || players[i].lives < 1) // not active or game over - Y_SetNullBonus(&players[i], &localbonus); - else if (maptol & TOL_NIGHTS) // Mare score instead of Rings - Y_SetNightsBonus(&players[i], &localbonus); + { + Y_SetNullBonus(&players[i], &localbonuses[0]); + Y_SetNullBonus(&players[i], &localbonuses[1]); + } + else if (maptol & TOL_NIGHTS) // NiGHTS bonus score instead of Rings + { + Y_SetNightsBonus(&players[i], &localbonuses[0]); + Y_SetNullBonus(&players[i], &localbonuses[1]); + } else - Y_SetRingBonus(&players[i], &localbonus); - players[i].score += localbonus.points; + { + Y_SetRingBonus(&players[i], &localbonuses[0]); + Y_SetPerfectBonus(&players[i], &localbonuses[1]); + } + players[i].score += localbonuses[0].points; + players[i].score += localbonuses[1].points; if (players[i].score > MAXSCORE) players[i].score = MAXSCORE; @@ -1982,7 +2018,7 @@ static void Y_AwardSpecialStageBonus(void) if (i == consoleplayer) { data.spec.gotlife = (((netgame || multiplayer) && gametype == GT_COOP && cv_cooplives.value == 0) ? 0 : ptlives); - M_Memcpy(&data.spec.bonus, &localbonus, sizeof(data.spec.bonus)); + M_Memcpy(&data.spec.bonuses, &localbonuses, sizeof(data.spec.bonuses)); // Continues related data.spec.continues = min(players[i].continues, 8); @@ -2057,7 +2093,8 @@ static void Y_UnloadData(void) // unload the special stage patches //UNLOAD(data.spec.cemerald); //UNLOAD(data.spec.nowsuper); - UNLOAD(data.spec.bonuspatch); + UNLOAD(data.spec.bonuspatches[1]); + UNLOAD(data.spec.bonuspatches[0]); UNLOAD(data.spec.pscore); UNLOAD(data.spec.pcontinues); break; From 16c541ef1b80b75d1ef41bbb3103307538e9d98f Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 2 Aug 2019 23:51:22 +0100 Subject: [PATCH 123/128] Add rings to old/MP special stage HUD + make both them and spheres (in old special stage only) count down rather than up, to match s3k --- src/st_stuff.c | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index 3b8fc749d..241e35143 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -110,6 +110,7 @@ static patch_t *orngstat; static patch_t *redstat; static patch_t *yelstat; static patch_t *nbracket; +static patch_t *nring; static patch_t *nhud[12]; static patch_t *nsshud; static patch_t *nbon[12]; @@ -311,6 +312,7 @@ void ST_LoadGraphics(void) redstat = W_CachePatchName("REDSTAT", PU_HUDGFX); yelstat = W_CachePatchName("YELSTAT", PU_HUDGFX); nbracket = W_CachePatchName("NBRACKET", PU_HUDGFX); + nring = W_CachePatchName("NRNG1", PU_HUDGFX); for (i = 0; i < 12; ++i) { nhud[i] = W_CachePatchName(va("NHUD%d", i+1), PU_HUDGFX); @@ -1545,7 +1547,7 @@ static void ST_drawNiGHTSLink(void) static void ST_drawNiGHTSHUD(void) { INT32 origamount; - INT32 total_spherecount; + INT32 total_spherecount, total_ringcount; const boolean oldspecialstage = (G_IsSpecialStage(gamemap) && !(maptol & TOL_NIGHTS)); // Drill meter @@ -1625,21 +1627,20 @@ static void ST_drawNiGHTSHUD(void) if (G_IsSpecialStage(gamemap)) { INT32 i; - total_spherecount = 0; + total_spherecount = total_ringcount = 0; for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] /*&& players[i].powers[pw_carry] == CR_NIGHTSMODE*/ && players[i].spheres) - total_spherecount += players[i].spheres; + { + if (!playeringame[i]) + continue; + total_spherecount += players[i].spheres; + total_ringcount += players[i].rings; + } } else - total_spherecount = stplyr->spheres; - - /*if (oldspecialstage) { - if (total_spherecount < ssspheres) - total_spherecount = ssspheres - total_spherecount; - else - total_spherecount = 0; - }*/ + total_spherecount = stplyr->spheres; + total_ringcount = stplyr->spheres; + } if (stplyr->capsule) { @@ -1727,6 +1728,23 @@ static void ST_drawNiGHTSHUD(void) else ST_DrawTopLeftOverlayPatch(40, 8 + 5, narrow[8]); + if (oldspecialstage) + { + // invert for s3k style junk + total_spherecount = ssspheres - total_spherecount; + total_ringcount = nummaprings - total_ringcount; + if (total_spherecount < 0) + total_spherecount = 0; + if (total_ringcount < 0) + total_ringcount = 0; + + // now rings! you know, for that perfect bonus. + V_DrawScaledPatch(272, 8, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTORIGHT|V_HUDTRANS, nbracket); + V_DrawScaledPatch(280, 16+1, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTORIGHT|V_HUDTRANS, nring); + V_DrawScaledPatch(280, 8+5, V_FLIP|V_PERPLAYER|V_SNAPTOTOP|V_SNAPTORIGHT|V_HUDTRANS, narrow[8]); + V_DrawTallNum(272, 8 + 11, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTORIGHT|V_HUDTRANS, total_ringcount); + } + if (total_spherecount >= 100) V_DrawTallNum((total_spherecount >= 1000) ? 76 : 72, 8 + 11, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTOLEFT|V_HUDTRANS, total_spherecount); else From 876f87e793bacaff87c9d260f935f927eabc70fa Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 2 Aug 2019 23:56:25 +0100 Subject: [PATCH 124/128] Have the ring bonus in MP Special Stages be based on the shared sum of all players'. --- src/y_inter.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/y_inter.c b/src/y_inter.c index 42aee79de..975902ab0 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1877,6 +1877,22 @@ static void Y_SetPerfectBonus(player_t *player, y_bonus_t *bstruct) data.coop.gotperfbonus = (bstruct->display ? 1 : 0); } +static void Y_SetSpecialRingBonus(player_t *player, y_bonus_t *bstruct) +{ + INT32 i, sharedringtotal = 0; + + (void)player; + strncpy(bstruct->patch, "YB_RING", sizeof(bstruct->patch)); + bstruct->display = true; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) continue; + sharedringtotal += players[i].rings; + } + bstruct->points = max(0, (sharedringtotal) * 100); +} + // This list can be extended in the future with SOC/Lua, perhaps. typedef void (*bonus_f)(player_t *, y_bonus_t *); bonus_f bonuses_list[6][4] = { @@ -2001,7 +2017,7 @@ static void Y_AwardSpecialStageBonus(void) } else { - Y_SetRingBonus(&players[i], &localbonuses[0]); + Y_SetSpecialRingBonus(&players[i], &localbonuses[0]); Y_SetPerfectBonus(&players[i], &localbonuses[1]); } players[i].score += localbonuses[0].points; From 105df2395d4078bf7c6f318fbf1245cce50ff839 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 3 Aug 2019 12:09:18 +0100 Subject: [PATCH 125/128] MI made a good argument for bossdisabled not being conditional on fromnetsave. --- src/p_spec.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index f1fb5c82f..ce769ac52 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6422,10 +6422,10 @@ void P_SpawnSpecials(INT32 fromnetsave) // This used to be used, and *should* be used in the future, // but currently isn't. - //(void)fromnetsave; -- hooray, it's used! + (void)fromnetsave; - if (!fromnetsave) - bossdisabled = 0; + // yep, we do this here - "bossdisabled" is considered an apparatus of specials. + bossdisabled = 0; // Init special SECTORs. sector = sectors; @@ -7325,8 +7325,6 @@ void P_SpawnSpecials(INT32 fromnetsave) lines[i].tag); break; } - if (fromnetsave) - break; if (!(lines[i].flags & ML_NOCLIMB)) { bossdisabled |= (1< Date: Sat, 3 Aug 2019 12:25:46 +0100 Subject: [PATCH 126/128] Add a condition to bail on the HUD's ring counting down calculation if nummaprings is 0 or -1. --- src/st_stuff.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/st_stuff.c b/src/st_stuff.c index 241e35143..962bdd722 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -1732,11 +1732,15 @@ static void ST_drawNiGHTSHUD(void) { // invert for s3k style junk total_spherecount = ssspheres - total_spherecount; - total_ringcount = nummaprings - total_ringcount; if (total_spherecount < 0) total_spherecount = 0; - if (total_ringcount < 0) - total_ringcount = 0; + + if (nummaprings > 0) // don't count down if there ISN'T a valid maximum number of rings, like sonic 3 + { + total_ringcount = nummaprings - total_ringcount; + if (total_ringcount < 0) + total_ringcount = 0; + } // now rings! you know, for that perfect bonus. V_DrawScaledPatch(272, 8, V_PERPLAYER|V_SNAPTOTOP|V_SNAPTORIGHT|V_HUDTRANS, nbracket); From f3baac85770e26b3b5efd3b3294422c9a250d3cc Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 3 Aug 2019 08:04:02 -0400 Subject: [PATCH 127/128] Fix the minor issues since steel's busy --- src/p_spec.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/p_spec.c b/src/p_spec.c index f712f4b23..f6c0be083 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -3916,13 +3916,15 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) F_StartTextPrompt(promptnum, pagenum, mo, runpostexec ? postexectag : 0, blockcontrols, freezerealtime); } } + break; + case 460: // Award rings { INT16 rings = (sides[line->sidenum[0]].textureoffset>>FRACBITS); - tic_t delay = (sides[line->sidenum[0]].rowoffset>>FRACBITS); + INT32 delay = (sides[line->sidenum[0]].rowoffset>>FRACBITS); if (mo && mo->player) { - if (delay <= 0 || !(leveltime % (delay))) + if (delay <= 0 || !(leveltime % delay)) P_GivePlayerRings(mo->player, rings); } } From f9037509a13758a20410f3463a898e43685b6df9 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sat, 3 Aug 2019 19:06:45 +0100 Subject: [PATCH 128/128] Remove commented out P_CheckSector calls and add extra comments explaining the situation --- src/p_polyobj.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 857e6f3d1..040bdca2a 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1873,7 +1873,8 @@ void T_PolyObjWaypoint(polywaypoint_t *th) po->lines[0]->backsector->floorheight = target->z - amtz; po->lines[0]->backsector->ceilingheight = target->z + amtz; // Sal: Remember to check your sectors! - //P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage)); + // Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap + // updating objects in the front one too just added teleporting to ground bugs P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); // Apply action to mirroring polyobjects as well start = 0; @@ -1887,7 +1888,8 @@ void T_PolyObjWaypoint(polywaypoint_t *th) po->lines[0]->backsector->floorheight += diffz; // move up/down by same amount as the parent did po->lines[0]->backsector->ceilingheight += diffz; // Sal: Remember to check your sectors! - //P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage)); + // Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap + // updating objects in the front one too just added teleporting to ground bugs P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); } @@ -2050,8 +2052,9 @@ void T_PolyObjWaypoint(polywaypoint_t *th) po->lines[0]->backsector->floorheight += momz; po->lines[0]->backsector->ceilingheight += momz; // Sal: Remember to check your sectors! - //P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage)); // frontsector is NEEDED for crushing - P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); // backsector may not be necessary, but just in case + // Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap + // updating objects in the front one too just added teleporting to ground bugs + P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); // Apply action to mirroring polyobjects as well start = 0; @@ -2065,7 +2068,8 @@ void T_PolyObjWaypoint(polywaypoint_t *th) po->lines[0]->backsector->floorheight += momz; po->lines[0]->backsector->ceilingheight += momz; // Sal: Remember to check your sectors! - //P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage)); + // Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap + // updating objects in the front one too just added teleporting to ground bugs P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); } }