From f7d1515888ace7e637635714e6cfa0ccae7a3ca5 Mon Sep 17 00:00:00 2001 From: Nev3r Date: Thu, 18 Apr 2019 14:43:34 +0200 Subject: [PATCH 01/76] 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 02/76] 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 03/76] 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 04/76] 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 05/76] 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 06/76] 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 07/76] 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 08/76] 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 09/76] 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 10/76] 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 11/76] 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 12/76] 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 13/76] 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 14/76] 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 15/76] 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 16/76] 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 17/76] 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 18/76] 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 19/76] 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 20/76] 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 21/76] 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 22/76] 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 23/76] 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 24/76] 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 25/76] "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 26/76] 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 27/76] 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 28/76] 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 29/76] 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 30/76] 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 31/76] 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 32/76] 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 33/76] 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 34/76] 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 35/76] 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 36/76] 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 37/76] 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 38/76] 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 39/76] 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 40/76] 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 41/76] 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 42/76] 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 43/76] 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 44/76] 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 45/76] 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 46/76] 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 47/76] 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 48/76] 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 49/76] 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 50/76] 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 51/76] 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 52/76] 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 53/76] 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 54/76] 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 55/76] 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 56/76] 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 57/76] 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 58/76] 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 59/76] 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 60/76] 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 61/76] 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 62/76] 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 63/76] 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 64/76] 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 65/76] 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 66/76] 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 67/76] 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 68/76] 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 69/76] 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 70/76] 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 71/76] 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 b3e953c8c34689c82d1ea589b1e9c34a2217dce1 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 14 Jul 2019 14:21:32 +0100 Subject: [PATCH 72/76] 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 794235a848aecd2424d30386ab652cb8bfa222d8 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 14 Jul 2019 16:19:48 +0100 Subject: [PATCH 73/76] 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 74/76] 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 fac6de9c2e218593aa1e6686088f5baec2a856a6 Mon Sep 17 00:00:00 2001 From: Monster Iestyn Date: Sun, 14 Jul 2019 18:10:03 +0100 Subject: [PATCH 75/76] 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 76/76] 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);