From 6106ce162414acfa29e6175beec88e93dda64c4e Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 5 Jun 2022 05:39:35 -0400 Subject: [PATCH] Add reversed weather - Negative speed weather will spawn from a floor in a sector with a sky ceiling, and go up into the ceiling. - (Not really the same as reverse gravity weather in that aspect, because that would be for sky floors.) - Fixed invert precipitation flag for linedef type 8 being completely unimplemented. (How long has it been like this...?) - Fix swapping weather on the fly having reversed momz --- src/p_local.h | 1 + src/p_mobj.c | 155 +++++++++++++++++++++++++++++++------------------- src/p_mobj.h | 11 ++-- src/p_spec.c | 9 ++- 4 files changed, 108 insertions(+), 68 deletions(-) diff --git a/src/p_local.h b/src/p_local.h index 82b1d445c..bb0d02fb2 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -277,6 +277,7 @@ void P_RespawnSpecials(void); mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type); +void P_CalculatePrecipFloor(precipmobj_t *mobj); void P_RecalcPrecipInSector(sector_t *sector); void P_PrecipitationEffects(void); diff --git a/src/p_mobj.c b/src/p_mobj.c index aedf37ad2..1f6dc93e2 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3760,19 +3760,22 @@ animonly: P_CyclePlayerMobjState(mobj); } -static void CalculatePrecipFloor(precipmobj_t *mobj) +void P_CalculatePrecipFloor(precipmobj_t *mobj) { // recalculate floorz each time const sector_t *mobjsecsubsec; + if (mobj && mobj->subsector && mobj->subsector->sector) mobjsecsubsec = mobj->subsector->sector; else return; + mobj->floorz = P_GetSectorFloorZAt(mobjsecsubsec, mobj->x, mobj->y); + if (mobjsecsubsec->ffloors) { ffloor_t *rover; - fixed_t topheight; + fixed_t height; for (rover = mobjsecsubsec->ffloors; rover; rover = rover->next) { @@ -3783,9 +3786,9 @@ static void CalculatePrecipFloor(precipmobj_t *mobj) if (!(rover->flags & FF_BLOCKOTHERS) && !(rover->flags & FF_SWIMMABLE)) continue; - topheight = P_GetFFloorTopZAt(rover, mobj->x, mobj->y); - if (topheight > mobj->floorz) - mobj->floorz = topheight; + height = P_GetFFloorTopZAt(rover, mobj->x, mobj->y); + if (height > mobj->floorz) + mobj->floorz = height; } } } @@ -3800,7 +3803,7 @@ void P_RecalcPrecipInSector(sector_t *sector) sector->moved = true; // Recalc lighting and things too, maybe for (psecnode = sector->touching_preciplist; psecnode; psecnode = psecnode->m_thinglist_next) - CalculatePrecipFloor(psecnode->m_thing); + P_CalculatePrecipFloor(psecnode->m_thing); } // @@ -3817,13 +3820,15 @@ void P_NullPrecipThinker(precipmobj_t *mobj) void P_PrecipThinker(precipmobj_t *mobj) { + boolean flip = (mobj->precipflags & PCF_FLIP); + P_CycleStateAnimation((mobj_t *)mobj); if (mobj->state == &states[S_RAINRETURN]) { // Reset to ceiling! P_SetPrecipMobjState(mobj, mobj->info->spawnstate); - mobj->z = mobj->ceilingz; + mobj->z = (flip) ? (mobj->floorz) : (mobj->ceilingz); mobj->momz = -mobj->info->speed; mobj->precipflags &= ~PCF_SPLASH; R_ResetPrecipitationMobjInterpolationState(mobj); @@ -3858,18 +3863,20 @@ void P_PrecipThinker(precipmobj_t *mobj) if (mobj->precipflags & PCF_SPLASH) return; + mobj->z += mobj->momz; + // adjust height - if ((mobj->z += mobj->momz) <= mobj->floorz) + if ((flip) ? (mobj->z >= mobj->ceilingz) : (mobj->z <= mobj->floorz)) { if ((mobj->info->deathstate == S_NULL) || (mobj->precipflags & PCF_PIT)) // no splashes on sky or bottomless pits { - mobj->z = mobj->ceilingz; + mobj->z = (flip) ? (mobj->floorz) : (mobj->ceilingz); R_ResetPrecipitationMobjInterpolationState(mobj); } else { P_SetPrecipMobjState(mobj, mobj->info->deathstate); - mobj->z = mobj->floorz; + mobj->z = (flip) ? (mobj->ceilingz) : (mobj->floorz); mobj->precipflags |= PCF_SPLASH; R_ResetPrecipitationMobjInterpolationState(mobj); } @@ -10341,8 +10348,8 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype { const mobjinfo_t *info = &mobjinfo[type]; state_t *st; + fixed_t start_z = INT32_MIN; precipmobj_t *mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); - fixed_t starting_floorz; mobj->type = type; mobj->info = info; @@ -10364,8 +10371,8 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype // set subsector and/or block links P_SetPrecipitationThingPosition(mobj); - mobj->floorz = starting_floorz = P_GetSectorFloorZAt (mobj->subsector->sector, x, y); - mobj->ceilingz = P_GetSectorCeilingZAt(mobj->subsector->sector, x, y); + mobj->floorz = P_GetSectorFloorZAt (mobj->subsector->sector, x, y); + mobj->ceilingz = P_GetSectorCeilingZAt(mobj->subsector->sector, x, y); mobj->floorrover = NULL; mobj->ceilingrover = NULL; @@ -10373,17 +10380,34 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype mobj->z = z; mobj->momz = -info->speed; + if (info->speed < 0) + { + mobj->precipflags |= PCF_FLIP; + } + + start_z = mobj->floorz; + mobj->thinker.function.acp1 = (actionf_p1)P_NullPrecipThinker; P_AddThinker(THINK_PRECIP, &mobj->thinker); - CalculatePrecipFloor(mobj); + P_CalculatePrecipFloor(mobj); - if (mobj->floorz != starting_floorz) - mobj->precipflags |= PCF_FOF; - else if (GETSECSPECIAL(mobj->subsector->sector->special, 1) == 7 - || GETSECSPECIAL(mobj->subsector->sector->special, 1) == 6 - || mobj->subsector->sector->floorpic == skyflatnum) - mobj->precipflags |= PCF_PIT; + if (mobj->floorz != start_z) + { + ; //mobj->precipflags |= PCF_FOF; + } + else + { + INT32 special = GETSECSPECIAL(mobj->subsector->sector->special, 1); + boolean sFlag = (mobj->precipflags & PCF_FLIP) ? (mobj->subsector->sector->flags & SF_FLIPSPECIAL_CEILING) : (mobj->subsector->sector->flags & SF_FLIPSPECIAL_FLOOR); + boolean pitFloor = ((special == 6 || special == 7) && sFlag); + boolean skyFloor = (mobj->precipflags & PCF_FLIP) ? (mobj->subsector->sector->ceilingpic == skyflatnum) : (mobj->subsector->sector->floorpic == skyflatnum); + + if (pitFloor || skyFloor) + { + mobj->precipflags |= PCF_PIT; + } + } R_ResetPrecipitationMobjInterpolationState(mobj); @@ -10588,13 +10612,19 @@ consvar_t cv_itemrespawn = CVAR_INIT ("respawnitem", "On", CV_NETVAR, CV_OnOff, void P_SpawnPrecipitation(void) { INT32 i, j, k; - mobjtype_t type = precipprops[curWeather].type; - UINT8 randomstates = (UINT8)mobjinfo[type].damage; + + const mobjtype_t type = precipprops[curWeather].type; + const UINT8 randomstates = (UINT8)mobjinfo[type].damage; + const boolean flip = (mobjinfo[type].speed < 0); + fixed_t basex, basey, x, y, z, height; + UINT16 numparticles = 0; + boolean condition = false; + subsector_t *precipsector = NULL; precipmobj_t *rainmo = NULL; - if (dedicated || !cv_drawdist_precip.value || curWeather == PRECIP_NONE) // SRB2Kart + if (dedicated || !cv_drawdist_precip.value || type == MT_NULL) return; // Use the blockmap to narrow down our placing patterns @@ -10603,58 +10633,63 @@ void P_SpawnPrecipitation(void) basex = bmaporgx + (i % bmapwidth) * MAPBLOCKSIZE; basey = bmaporgy + (i / bmapwidth) * MAPBLOCKSIZE; + x = basex + ((M_RandomKey(MAPBLOCKUNITS << 3) << FRACBITS) >> 3); + y = basey + ((M_RandomKey(MAPBLOCKUNITS << 3) << FRACBITS) >> 3); + + precipsector = R_PointInSubsectorOrNull(x, y); + + // No sector? Stop wasting time, + // move on to the next entry in the blockmap + if (!precipsector) + continue; + + // Not in a sector with visible sky? + condition = (precipsector->sector->ceilingpic == skyflatnum); + + if (precipsector->sector->flags & SF_INVERTPRECIP) { - UINT16 numparticles = 0; + condition = !condition; + } - x = basex + ((M_RandomKey(MAPBLOCKUNITS<<3)<>3); - y = basey + ((M_RandomKey(MAPBLOCKUNITS<<3)<>3); + if (!condition) + { + continue; + } - precipsector = R_PointInSubsectorOrNull(x, y); + height = precipsector->sector->ceilingheight - precipsector->sector->floorheight; - // 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 (height < 64<sector->ceilingpic != skyflatnum) - continue; + // Hack around a quirk of this entire system, where taller sectors look like they get less precipitation. + numparticles = 1 + (height / (MAPBLOCKUNITS<<4<sector->ceilingheight - precipsector->sector->floorheight; + // Don't set z properly yet... + z = (flip) ? (precipsector->sector->floorheight) : (precipsector->sector->ceilingheight); - // Exists, but is too small for reasonable precipitation. - if (height < 64<sector->ceilingheight; - - for (j = 0; j < numparticles; j++) + if (randomstates > 0) { - rainmo = P_SpawnPrecipMobj(x, y, z, type); + UINT8 mrand = M_RandomByte(); + UINT8 threshold = UINT8_MAX / (randomstates + 1); + statenum_t st = mobjinfo[type].spawnstate; - if (randomstates > 0) + for (k = 0; k < randomstates; k++) { - UINT8 mrand = M_RandomByte(); - UINT8 threshold = UINT8_MAX / (randomstates + 1); - statenum_t st = mobjinfo[type].spawnstate; - - for (k = 0; k < randomstates; k++) + if (mrand < (threshold * (k+1))) { - if (mrand < (threshold * (k+1))) - { - P_SetPrecipMobjState(rainmo, st+k+1); - break; - } + P_SetPrecipMobjState(rainmo, st+k+1); + break; } } - - // Randomly assign a height, now that floorz is set. - rainmo->z = M_RandomRange(rainmo->floorz>>FRACBITS, rainmo->ceilingz>>FRACBITS)<z = M_RandomRange(rainmo->floorz >> FRACBITS, rainmo->ceilingz >> FRACBITS) << FRACBITS; } } } diff --git a/src/p_mobj.h b/src/p_mobj.h index f7fd6d335..0f05d7c90 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -262,12 +262,11 @@ typedef enum // PRECIPITATION flags ?! ?! ?! // typedef enum { - PCF_INVISIBLE = 1, // Don't draw. - PCF_PIT = 1<<1, // Above pit. - PCF_FOF = 1<<2, // Above FOF. - PCF_MOVINGFOF = 1<<3, // Above MOVING FOF (this means we need to keep floorz up to date...) - PCF_SPLASH = 1<<4, // Splashed on the ground, return to the ceiling after the animation's over - PCF_THUNK = 1<<5, // Ran the thinker this tic. + PCF_THUNK = 1, // Ran the thinker this tic. + PCF_SPLASH = 1<<1, // Splashed on the ground, return to the ceiling after the animation's over + PCF_INVISIBLE = 1<<2, // Don't draw. + PCF_PIT = 1<<3, // Above pit. + PCF_FLIP = 1<<4, // Spawning from floor, moving upwards. } precipflag_t; // Map Object definition. diff --git a/src/p_spec.c b/src/p_spec.c index 56e1456ea..5d4f456de 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1851,8 +1851,13 @@ void P_SwitchWeather(preciptype_t newWeather) precipmobj->sprite = precipmobj->state->sprite; precipmobj->frame = precipmobj->state->frame; - precipmobj->momz = mobjinfo[swap].speed; - precipmobj->precipflags &= ~PCF_INVISIBLE; + precipmobj->momz = -mobjinfo[swap].speed; + precipmobj->precipflags &= ~(PCF_INVISIBLE|PCF_FLIP); + + if (precipmobj->momz > 0) + { + precipmobj->precipflags |= PCF_FLIP; + } } }