diff --git a/src/p_floor.c b/src/p_floor.c index e46b0b4fb..774606563 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1104,164 +1104,74 @@ void T_MarioBlockChecker(levelspecthink_t *block) } } +static boolean P_IsPlayerValid(size_t playernum) +{ + if (!playeringame[playernum]) + return false; + + if (!players[playernum].mo) + return false; + + if (players[playernum].mo->health <= 0) + return false; + + if (players[playernum].spectator) + return false; + + return true; +} + // This is the Thwomp's 'brain'. It looks around for players nearby, and if // it finds any, **SMASH**!!! Muahahhaa.... -void T_ThwompSector(levelspecthink_t *thwomp) +void T_ThwompSector(thwomp_t *thwomp) { -#define speed vars[1] -#define direction vars[2] -#define distance vars[3] -#define floorwasheight vars[4] -#define ceilingwasheight vars[5] fixed_t thwompx, thwompy; sector_t *actionsector; ffloor_t *rover = NULL; INT32 secnum; + fixed_t speed; // If you just crashed down, wait a second before coming back up. - if (--thwomp->distance > 0) - { - sides[thwomp->sourceline->sidenum[0]].midtexture = sides[thwomp->sourceline->sidenum[0]].bottomtexture; + if (--thwomp->delay > 0) return; - } // Just find the first sector with the tag. // Doesn't work with multiple sectors that have different floor/ceiling heights. - secnum = P_FindSectorFromTag((INT16)thwomp->vars[0], -1); + secnum = P_FindSectorFromTag(thwomp->tag, -1); - if (secnum > 0) - { - actionsector = §ors[secnum]; - - // Look for thwomp FFloor - for (rover = actionsector->ffloors; rover; rover = rover->next) - { - if (rover->master == thwomp->sourceline) - break; - } - } - else + if (secnum <= 0) return; // Bad bad bad! + actionsector = §ors[secnum]; + + // Look for thwomp FOF + for (rover = actionsector->ffloors; rover; rover = rover->next) + { + if (rover->master == thwomp->sourceline) + break; + } + + if (!rover) + return; // Didn't find any FOFs, so bail out + thwompx = actionsector->soundorg.x; thwompy = actionsector->soundorg.y; - if (thwomp->direction > 0) // Moving back up.. + if (thwomp->direction == 0) // Not going anywhere, so look for players. { - result_e res = 0; - - // Set the texture from the lower one (normal) - sides[thwomp->sourceline->sidenum[0]].midtexture = sides[thwomp->sourceline->sidenum[0]].bottomtexture; - /// \note this should only have to be done once, but is already done repeatedly, above - - if (thwomp->sourceline->flags & ML_EFFECT5) - thwomp->speed = thwomp->sourceline->dx/8; - else - thwomp->speed = 2*FRACUNIT; - - res = T_MovePlane - ( - thwomp->sector, // sector - thwomp->speed, // speed - thwomp->floorwasheight, // dest - false, // crush - false, // ceiling? - thwomp->direction // direction - ); - - if (res == ok || res == pastdest) - T_MovePlane - ( - thwomp->sector, // sector - thwomp->speed, // speed - thwomp->ceilingwasheight, // dest - false, // crush - true, // ceiling? - thwomp->direction // direction - ); - - if (res == pastdest) - thwomp->direction = 0; // stop moving - - thwomp->sector->ceilspeed = 42; - thwomp->sector->floorspeed = thwomp->speed*thwomp->direction; - } - else if (thwomp->direction < 0) // Crashing down! - { - result_e res = 0; - - // Set the texture from the upper one (angry) - sides[thwomp->sourceline->sidenum[0]].midtexture = sides[thwomp->sourceline->sidenum[0]].toptexture; - - if (thwomp->sourceline->flags & ML_EFFECT5) - thwomp->speed = thwomp->sourceline->dy/8; - else - thwomp->speed = 10*FRACUNIT; - - res = T_MovePlane - ( - thwomp->sector, // sector - thwomp->speed, // speed - P_FloorzAtPos(thwompx, thwompy, thwomp->sector->floorheight, - thwomp->sector->ceilingheight - thwomp->sector->floorheight), // dest - false, // crush - false, // ceiling? - thwomp->direction // direction - ); - - if (res == ok || res == pastdest) - T_MovePlane - ( - thwomp->sector, // sector - thwomp->speed, // speed - P_FloorzAtPos(thwompx, thwompy, thwomp->sector->floorheight, - thwomp->sector->ceilingheight - - (thwomp->sector->floorheight + thwomp->speed)) - + (thwomp->sector->ceilingheight - - (thwomp->sector->floorheight + thwomp->speed/2)), // dest - false, // crush - true, // ceiling? - thwomp->direction // direction - ); - - if (res == pastdest) - { - mobj_t *mp = (void *)&actionsector->soundorg; - - if (!rover || (rover->flags & FF_EXISTS)) - { - if (thwomp->sourceline->flags & ML_EFFECT4) - S_StartSound(mp, sides[thwomp->sourceline->sidenum[0]].textureoffset>>FRACBITS); - else - S_StartSound(mp, sfx_thwomp); - } - - thwomp->direction = 1; // start heading back up - thwomp->distance = TICRATE; // but only after a small delay - } - - thwomp->sector->ceilspeed = 42; - thwomp->sector->floorspeed = thwomp->speed*thwomp->direction; - } - else // Not going anywhere, so look for players. - { - if (!rover || (rover->flags & FF_EXISTS)) + if (rover->flags & FF_EXISTS) { UINT8 i; // scan the players to find victims! for (i = 0; i < MAXPLAYERS; i++) { - if (!playeringame[i]) - continue; - if (players[i].spectator) - continue; - if (!players[i].mo) - continue; - if (!players[i].mo->health) + if (!P_IsPlayerValid(i)) 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) + + if (P_AproxDistance(thwompx - players[i].mo->x, thwompy - players[i].mo->y) > 96*FRACUNIT) continue; thwomp->direction = -1; @@ -1272,13 +1182,89 @@ void T_ThwompSector(levelspecthink_t *thwomp) thwomp->sector->ceilspeed = 0; thwomp->sector->floorspeed = 0; } + else + { + result_e res = 0; + + if (thwomp->direction > 0) //Moving back up.. + { + // Set the texture from the lower one (normal) + sides[thwomp->sourceline->sidenum[0]].midtexture = sides[thwomp->sourceline->sidenum[0]].bottomtexture; + + speed = thwomp->retractspeed; + + res = T_MovePlane + ( + thwomp->sector, // sector + speed, // speed + thwomp->floorstartheight, // dest + false, // crush + false, // ceiling? + thwomp->direction // direction + ); + + if (res == ok || res == pastdest) + T_MovePlane + ( + thwomp->sector, // sector + speed, // speed + thwomp->ceilingstartheight, // dest + false, // crush + true, // ceiling? + thwomp->direction // direction + ); + + if (res == pastdest) + thwomp->direction = 0; // stop moving + } + else // Crashing down! + { + // Set the texture from the upper one (angry) + sides[thwomp->sourceline->sidenum[0]].midtexture = sides[thwomp->sourceline->sidenum[0]].toptexture; + + speed = thwomp->crushspeed; + + res = T_MovePlane + ( + thwomp->sector, // sector + speed, // speed + P_FloorzAtPos(thwompx, thwompy, thwomp->sector->floorheight, + thwomp->sector->ceilingheight - thwomp->sector->floorheight), // dest + false, // crush + false, // ceiling? + thwomp->direction // direction + ); + + if (res == ok || res == pastdest) + T_MovePlane + ( + thwomp->sector, // sector + speed, // speed + P_FloorzAtPos(thwompx, thwompy, thwomp->sector->floorheight, + thwomp->sector->ceilingheight + - (thwomp->sector->floorheight + speed)) + + (thwomp->sector->ceilingheight + - (thwomp->sector->floorheight + speed/2)), // dest + false, // crush + true, // ceiling? + thwomp->direction // direction + ); + + if (res == pastdest) + { + if (rover->flags & FF_EXISTS) + S_StartSound((void *)&actionsector->soundorg, thwomp->sound); + + thwomp->direction = 1; // start heading back up + thwomp->delay = TICRATE; // but only after a small delay + } + } + + thwomp->sector->ceilspeed = 42; + thwomp->sector->floorspeed = speed*thwomp->direction; + } P_RecalcPrecipInSector(actionsector); -#undef speed -#undef direction -#undef distance -#undef floorwasheight -#undef ceilingwasheight } static boolean T_SectorHasEnemies(sector_t *sec) @@ -1375,23 +1361,6 @@ static boolean P_IsObjectOnRealGround(mobj_t *mo, sector_t *sec) return false; } -static boolean P_IsPlayerValid(size_t playernum) -{ - if (!playeringame[playernum]) - return false; - - if (!players[playernum].mo) - return false; - - if (players[playernum].mo->health <= 0) - return false; - - if (players[playernum].spectator) - return false; - - return true; -} - static boolean P_IsMobjTouchingSector(mobj_t *mo, sector_t *sec) { msecnode_t *node; diff --git a/src/p_saveg.c b/src/p_saveg.c index afcd9867e..888eb96ca 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -1704,6 +1704,27 @@ static void SaveMarioBlockThinker(const thinker_t *th, const UINT8 type) WRITEINT16(save_p, ht->tag); } +// +// SaveThwompThinker +// +// Saves a thwomp_t thinker +// +static void SaveThwompThinker(const thinker_t *th, const UINT8 type) +{ + const thwomp_t *ht = (const void *)th; + WRITEUINT8(save_p, type); + WRITEUINT32(save_p, SaveLine(ht->sourceline)); + WRITEUINT32(save_p, SaveSector(ht->sector)); + WRITEFIXED(save_p, ht->crushspeed); + WRITEFIXED(save_p, ht->retractspeed); + WRITEINT32(save_p, ht->direction); + WRITEFIXED(save_p, ht->floorstartheight); + WRITEFIXED(save_p, ht->ceilingstartheight); + WRITEINT32(save_p, ht->delay); + WRITEINT16(save_p, ht->tag); + WRITEUINT16(save_p, ht->sound); +} + // // SaveFloatThinker // @@ -2317,7 +2338,7 @@ static void P_NetArchiveThinkers(void) } else if (th->function.acp1 == (actionf_p1)T_ThwompSector) { - SaveSpecialLevelThinker(th, tc_thwomp); + SaveThwompThinker(th, tc_thwomp); continue; } else if (th->function.acp1 == (actionf_p1)T_NoEnemiesSector) @@ -2906,6 +2927,27 @@ static thinker_t* LoadMarioBlockThinker(actionf_p1 thinker) return &ht->thinker; } +// LoadThwompThinker +// +// Loads a thwomp_t from a save game +// +static thinker_t* LoadThwompThinker(actionf_p1 thinker) +{ + thwomp_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + ht->sourceline = LoadLine(READUINT32(save_p)); + ht->sector = LoadSector(READUINT32(save_p)); + ht->crushspeed = READFIXED(save_p); + ht->retractspeed = READFIXED(save_p); + ht->direction = READINT32(save_p); + ht->floorstartheight = READFIXED(save_p); + ht->ceilingstartheight = READFIXED(save_p); + ht->delay = READINT32(save_p); + ht->tag = READINT16(save_p); + ht->sound = READUINT16(save_p); + return &ht->thinker; +} + // LoadFloatThinker // // Loads a floatthink_t from a save game @@ -3624,7 +3666,7 @@ static void P_NetUnArchiveThinkers(void) break; case tc_thwomp: - th = LoadSpecialLevelThinker((actionf_p1)T_ThwompSector, 3); + th = LoadThwompThinker((actionf_p1)T_ThwompSector); break; case tc_noenemies: diff --git a/src/p_spec.c b/src/p_spec.c index 6bcac18f9..921bcef26 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -6068,12 +6068,7 @@ static void P_AddAirbob(sector_t *sec, line_t *sourceline, fixed_t dist, boolean */ static inline void P_AddThwompThinker(sector_t *sec, sector_t *actionsector, line_t *sourceline) { -#define speed vars[1] -#define direction vars[2] -#define distance vars[3] -#define floorwasheight vars[4] -#define ceilingwasheight vars[5] - levelspecthink_t *thwomp; + thwomp_t *thwomp; // You *probably* already have a thwomp in this sector. If you've combined it with something // else that uses the floordata/ceilingdata, you must be weird. @@ -6087,21 +6082,21 @@ static inline void P_AddThwompThinker(sector_t *sec, sector_t *actionsector, lin thwomp->thinker.function.acp1 = (actionf_p1)T_ThwompSector; // set up the fields according to the type of elevator action - thwomp->sector = sec; - thwomp->vars[0] = actionsector->tag; - thwomp->floorwasheight = thwomp->sector->floorheight; - thwomp->ceilingwasheight = thwomp->sector->ceilingheight; - thwomp->direction = 0; - thwomp->distance = 1; thwomp->sourceline = sourceline; - thwomp->sector->floordata = thwomp; - thwomp->sector->ceilingdata = thwomp; - return; -#undef speed -#undef direction -#undef distance -#undef floorwasheight -#undef ceilingwasheight + thwomp->sector = sec; + thwomp->crushspeed = (sourceline->flags & ML_EFFECT5) ? sourceline->dy >> 3 : 10*FRACUNIT; + thwomp->retractspeed = (sourceline->flags & ML_EFFECT5) ? sourceline->dx >> 3 : 2*FRACUNIT; + thwomp->direction = 0; + thwomp->floorstartheight = sec->floorheight; + thwomp->ceilingstartheight = sec->ceilingheight; + thwomp->delay = 1; + thwomp->tag = actionsector->tag; + thwomp->sound = (sourceline->flags & ML_EFFECT4) ? sides[sourceline->sidenum[0]].textureoffset >> FRACBITS : sfx_thwomp; + + sec->floordata = thwomp; + sec->ceilingdata = thwomp; + // Start with 'resting' texture + sides[sourceline->sidenum[0]].midtexture = sides[sourceline->sidenum[0]].bottomtexture; } /** Adds a thinker which checks if any MF_ENEMY objects with health are in the defined area. diff --git a/src/p_spec.h b/src/p_spec.h index ef98be5c4..5e54b568f 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -348,6 +348,21 @@ typedef struct INT16 tag; } mariothink_t; +typedef struct +{ + thinker_t thinker; + line_t *sourceline; + sector_t *sector; + fixed_t crushspeed; + fixed_t retractspeed; + INT32 direction; + fixed_t floorstartheight; + fixed_t ceilingstartheight; + INT32 delay; + INT16 tag; + UINT16 sound; +} thwomp_t; + typedef struct { thinker_t thinker; @@ -419,7 +434,7 @@ void T_StartCrumble(elevator_t *elevator); void T_MarioBlock(mariothink_t *block); void T_FloatSector(floatthink_t *floater); void T_MarioBlockChecker(levelspecthink_t *block); -void T_ThwompSector(levelspecthink_t *thwomp); +void T_ThwompSector(thwomp_t *thwomp); void T_NoEnemiesSector(noenemies_t *nobaddies); void T_EachTimeThinker(eachtime_t *eachtime); void T_CameraScanner(elevator_t *elevator);