From 80bb59031c4bbf360fd45b875f5c85728feae466 Mon Sep 17 00:00:00 2001 From: TehRealSalt Date: Thu, 14 Nov 2019 04:26:41 -0500 Subject: [PATCH] Blizzard weather option + much more sane workflow for adding new precipitation options "precipprops" lets you create a new precipitation type by picking a mobj type to use, how many random states it has, and flags for effects such as thunder/lightning. Seesound on the mobj type sets an ambient sound (like rain drops) and mass sets the sound's frequency in tics. This could open up the possibility for SOC/Lua Weather options later. --- src/dehacked.c | 12 ++- src/doomstat.h | 35 +++++-- src/g_game.c | 15 ++- src/hardware/hw_main.c | 5 +- src/info.c | 74 ++++++++++---- src/info.h | 7 ++ src/p_floor.c | 1 + src/p_mobj.c | 224 ++++++++++++++++++++--------------------- src/p_mobj.h | 31 +++--- src/p_spec.c | 221 +++++++++------------------------------- src/p_spec.h | 2 +- src/p_tick.c | 10 -- src/r_things.c | 6 +- 13 files changed, 283 insertions(+), 360 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index 5f9249d89..af1ee934e 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -5690,6 +5690,11 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_SNOW2", "S_SNOW3", + // Blizzard Snowball + "S_BLIZZARDSNOW1", + "S_BLIZZARDSNOW2", + "S_BLIZZARDSNOW3", + // Water Splish "S_SPLISH1", "S_SPLISH2", @@ -7589,6 +7594,7 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s // Environmental Effects "MT_RAIN", // Rain "MT_SNOWFLAKE", // Snowflake + "MT_BLIZZARDSNOW", // Blizzard Snowball "MT_SPLISH", // Water splish! "MT_SMOKE", "MT_SMALLBUBBLE", // small bubble @@ -8700,10 +8706,10 @@ struct { // Precipitation {"PRECIP_NONE",PRECIP_NONE}, - {"PRECIP_STORM",PRECIP_STORM}, - {"PRECIP_SNOW",PRECIP_SNOW}, {"PRECIP_RAIN",PRECIP_RAIN}, - {"PRECIP_BLANK",PRECIP_BLANK}, + {"PRECIP_SNOW",PRECIP_SNOW}, + {"PRECIP_BLIZZARD",PRECIP_BLIZZARD}, + {"PRECIP_STORM",PRECIP_STORM}, {"PRECIP_STORM_NORAIN",PRECIP_STORM_NORAIN}, {"PRECIP_STORM_NOSTRIKES",PRECIP_STORM_NOSTRIKES}, diff --git a/src/doomstat.h b/src/doomstat.h index 59e2bd5c4..cdc09cf86 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -41,18 +41,37 @@ extern UINT32 mapmusposition; extern INT16 maptol; extern UINT8 globalweather; -extern INT32 curWeather; +extern UINT8 curWeather; extern INT32 cursaveslot; extern INT16 lastmapsaved; extern boolean gamecomplete; -#define PRECIP_NONE 0 -#define PRECIP_STORM 1 -#define PRECIP_SNOW 2 -#define PRECIP_RAIN 3 -#define PRECIP_BLANK 4 -#define PRECIP_STORM_NORAIN 5 -#define PRECIP_STORM_NOSTRIKES 6 +typedef enum +{ + PRECIP_NONE = 0, + PRECIP_RAIN, + PRECIP_SNOW, + PRECIP_BLIZZARD, + PRECIP_STORM, + PRECIP_STORM_NORAIN, + PRECIP_STORM_NOSTRIKES, + MAXPRECIP +} preciptype_t; + +typedef enum +{ + PRECIPFX_THUNDER = 1, + PRECIPFX_LIGHTNING = 1<<1 +} precipeffect_t; + +typedef struct +{ + mobjtype_t type; + precipeffect_t effects; + UINT8 randomstates; +} precipprops_t; + +extern precipprops_t precipprops[MAXPRECIP]; // Set if homebrew PWAD stuff has been added. extern boolean modifiedgame; diff --git a/src/g_game.c b/src/g_game.c index d4d48f7c2..e15968b3e 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -83,8 +83,21 @@ UINT32 mapmusposition; // Position to jump to INT16 gamemap = 1; INT16 maptol; + UINT8 globalweather = 0; -INT32 curWeather = PRECIP_NONE; +UINT8 curWeather = PRECIP_NONE; + +precipprops_t precipprops[MAXPRECIP] = +{ + {MT_NULL, 0, 0}, // PRECIP_NONE + {MT_RAIN, 0, 0}, // PRECIP_RAIN + {MT_SNOWFLAKE, 0, 2}, // PRECIP_SNOW + {MT_BLIZZARDSNOW, 0, 2}, // PRECIP_BLIZZARD + {MT_RAIN, PRECIPFX_THUNDER|PRECIPFX_LIGHTNING, 0}, // PRECIP_STORM + {MT_NULL, PRECIPFX_THUNDER|PRECIPFX_LIGHTNING, 0}, // PRECIP_STORM_NORAIN + {MT_RAIN, PRECIPFX_THUNDER, 0} // PRECIP_STORM_NOSTRIKES +}; + INT32 cursaveslot = -1; // Auto-save 1p savegame slot INT16 lastmapsaved = 0; // Last map we auto-saved at boolean gamecomplete = false; diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 659af386d..31461283c 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -5882,10 +5882,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) // 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); + P_PrecipThinker(thing); thing->precipflags |= PCF_THUNK; } diff --git a/src/info.c b/src/info.c index 4f448cc00..4542e6c3a 100644 --- a/src/info.c +++ b/src/info.c @@ -44,17 +44,17 @@ char sprnames[NUMSPRITES + 1][5] = "BSZ7","BSZ8","STLG","DBAL","RCRY","ARMA","ARMF","ARMB","WIND","MAGN", "ELEM","FORC","PITY","IVSP","SSPK","GOAL","BIRD","BUNY","MOUS","CHIC", "COWZ","RBRD","SPVY","SPVR","SPVB","SPVG","SPDY","SPDR","SPDB","SPDG", - "SPHY","SPHR","SPHB","SPHG","RAIN","SNO1","SPLH","SPLA","SMOK","BUBP", - "BUBO","BUBN","BUBM","POPP","TFOG","SEED","PRTL","SCOR","DRWN","TTAG", - "GFLG","RRNG","RNGB","RNGR","RNGI","RNGA","RNGE","RNGS","RNGG","PIKB", - "PIKR","PIKA","PIKE","PIKS","PIKG","TAUT","TGRE","TSCR","COIN","CPRK", - "GOOM","BGOM","FFWR","FBLL","SHLL","PUMA","HAMM","KOOP","BFLM","MAXE", - "MUS1","MUS2","TOAD","NDRN","SUPE","SUPZ","NDRL","NSPK","NBMP","HOOP", - "NSCR","NPRU","CAPS","SUPT","SPRK","BOM1","BOM2","BOM3","BOM4","ROIA", - "ROIB","ROIC","ROID","ROIE","ROIF","ROIG","ROIH","ROII","ROIJ","ROIK", - "ROIL","ROIM","ROIN","ROIO","ROIP","BBAL","GWLG","GWLR","SRBA","SRBB", - "SRBC","SRBD","SRBE","SRBF","SRBG","SRBH","SRBI","SRBJ","SRBK","SRBL", - "SRBM","SRBN","SRBO", + "SPHY","SPHR","SPHB","SPHG","RAIN","SNO1","SNO2","SPLH","SPLA","SMOK", + "BUBP","BUBO","BUBN","BUBM","POPP","TFOG","SEED","PRTL","SCOR","DRWN", + "TTAG","GFLG","RRNG","RNGB","RNGR","RNGI","RNGA","RNGE","RNGS","RNGG", + "PIKB","PIKR","PIKA","PIKE","PIKS","PIKG","TAUT","TGRE","TSCR","COIN", + "CPRK","GOOM","BGOM","FFWR","FBLL","SHLL","PUMA","HAMM","KOOP","BFLM", + "MAXE","MUS1","MUS2","TOAD","NDRN","SUPE","SUPZ","NDRL","NSPK","NBMP", + "HOOP","NSCR","NPRU","CAPS","SUPT","SPRK","BOM1","BOM2","BOM3","BOM4", + "ROIA","ROIB","ROIC","ROID","ROIE","ROIF","ROIG","ROIH","ROII","ROIJ", + "ROIK","ROIL","ROIM","ROIN","ROIO","ROIP","BBAL","GWLG","GWLR","SRBA", + "SRBB","SRBC","SRBD","SRBE","SRBF","SRBG","SRBH","SRBI","SRBJ","SRBK", + "SRBL","SRBM","SRBN","SRBO", //SRB2kart Sprites "RNDM","RPOP","SGNS","FAST","DSHR","BOST","BOSM","KFRE","KINV","KINF", "WIPD","DRIF","BDRF","DUST","RSHE","FITM","BANA","ORBN","JAWZ","SSMN", @@ -1869,13 +1869,18 @@ state_t states[NUMSTATES] = // 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_NULL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_RAINRETURN // Snowflake {SPR_SNO1, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SNOW1 {SPR_SNO1, 1, -1, {NULL}, 0, 0, S_NULL}, // S_SNOW2 {SPR_SNO1, 2, -1, {NULL}, 0, 0, S_NULL}, // S_SNOW3 + // Blizzard Snowball + {SPR_SNO2, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BLIZZARDSNOW1 + {SPR_SNO2, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BLIZZARDSNOW2 + {SPR_SNO2, 2, -1, {NULL}, 0, 0, S_NULL}, // S_BLIZZARDSNOW3 + // Water Splish {SPR_SPLH, FF_TRANS50 , 2, {NULL}, 0, 0, S_SPLISH2}, // S_SPLISH1 {SPR_SPLH, FF_TRANS50|1, 2, {NULL}, 0, 0, S_SPLISH3}, // S_SPLISH2 @@ -1888,9 +1893,9 @@ state_t states[NUMSTATES] = {SPR_SPLH, FF_TRANS50|8, 2, {NULL}, 0, 0, S_NULL}, // S_SPLISH9 // Water Splash - {SPR_SPLA, FF_TRANS50 , 3, {NULL}, 0, 0, S_SPLASH2}, // S_SPLASH1 - {SPR_SPLA, FF_TRANS70|1, 3, {NULL}, 0, 0, S_SPLASH3}, // S_SPLASH2 - {SPR_SPLA, FF_TRANS90|2, 3, {NULL}, 0, 0, S_RAINRETURN}, // S_SPLASH3 + {SPR_SPLA, FF_TRANS50 , 3, {NULL}, 0, 0, S_SPLASH2}, // S_SPLASH1 + {SPR_SPLA, FF_TRANS70|1, 3, {NULL}, 0, 0, S_SPLASH3}, // S_SPLASH2 + {SPR_SPLA, FF_TRANS90|2, 3, {NULL}, 0, 0, S_NULL}, // S_SPLASH3 // Smoke {SPR_SMOK, FF_TRANS50 , 4, {NULL}, 0, 0, S_SMOKE2}, // S_SMOKE1 @@ -11438,22 +11443,22 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_RAIN1, // spawnstate 1000, // spawnhealth S_NULL, // seestate - sfx_None, // seesound - 8, // reactiontime + sfx_rainin, // seesound + 0, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_NULL, // deathstate + S_SPLASH1, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound -72*FRACUNIT, // speed -- -24*FRACUNIT originally, srb2kart x3 (nya) 1*FRACUNIT, // radius 8*FRACUNIT, // height 0, // display offset - 4, // mass + 80, // mass 0, // damage sfx_None, // activesound MF_NOBLOCKMAP, // flags @@ -11466,7 +11471,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound - 8, // reactiontime + 0, // reactiontime sfx_None, // attacksound S_NULL, // painstate 0, // painchance @@ -11480,7 +11485,34 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 4*FRACUNIT, // radius 4*FRACUNIT, // height 0, // display offset - 4, // mass + 0, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP, // flags + S_NULL // raisestate + }, + + { // MT_BLIZZARDSNOW + -1, // doomednum + S_BLIZZARDSNOW1, // 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_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + -24*FRACUNIT, // speed + 4*FRACUNIT, // radius + 4*FRACUNIT, // height + 0, // display offset + 0, // mass 0, // damage sfx_None, // activesound MF_NOBLOCKMAP, // flags diff --git a/src/info.h b/src/info.h index 27488d916..cb520252c 100644 --- a/src/info.h +++ b/src/info.h @@ -475,6 +475,7 @@ typedef enum sprite // Environmental Effects SPR_RAIN, // Rain SPR_SNO1, // Snowflake + SPR_SNO2, // Blizzard Snowball SPR_SPLH, // Water Splish SPR_SPLA, // Water Splash SPR_SMOK, @@ -2579,6 +2580,11 @@ typedef enum state S_SNOW2, S_SNOW3, + // Blizzard Snowball + S_BLIZZARDSNOW1, + S_BLIZZARDSNOW2, + S_BLIZZARDSNOW3, + // Water Splish S_SPLISH1, S_SPLISH2, @@ -4510,6 +4516,7 @@ typedef enum mobj_type // Environmental Effects MT_RAIN, // Rain MT_SNOWFLAKE, // Snowflake + MT_BLIZZARDSNOW, // Blizzard Snowball MT_SPLISH, // Water splish! MT_SMOKE, MT_SMALLBUBBLE, // small bubble diff --git a/src/p_floor.c b/src/p_floor.c index ccbfd6eae..666656958 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -1769,6 +1769,7 @@ static mobj_t *SearchMarioNode(msecnode_t *node) case MT_SUPERSPARK: case MT_RAIN: case MT_SNOWFLAKE: + case MT_BLIZZARDSNOW: case MT_SPLISH: case MT_SMOKE: case MT_SMALLBUBBLE: diff --git a/src/p_mobj.c b/src/p_mobj.c index b220ff4e6..87fb7a186 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3928,51 +3928,60 @@ void P_NullPrecipThinker(precipmobj_t *mobj) mobj->precipflags &= ~PCF_THUNK; } -void P_SnowThinker(precipmobj_t *mobj) +void P_PrecipThinker(precipmobj_t *mobj) { P_CycleStateAnimation((mobj_t *)mobj); - // adjust height - if ((mobj->z += mobj->momz) <= mobj->floorz) - mobj->z = mobj->ceilingz; -} - -void P_RainThinker(precipmobj_t *mobj) -{ - P_CycleStateAnimation((mobj_t *)mobj); - - if (mobj->state != &states[S_RAIN1]) + if (mobj->state == &states[S_RAINRETURN]) { - // cycle through states, - // calling action functions at transitions - if (mobj->tics <= 0) - return; - - if (--mobj->tics) - return; - - if (!P_SetPrecipMobjState(mobj, mobj->state->nextstate)) - return; - - if (mobj->state != &states[S_RAINRETURN]) - return; - + // Reset to ceiling! + P_SetPrecipMobjState(mobj, mobj->info->spawnstate); mobj->z = mobj->ceilingz; - P_SetPrecipMobjState(mobj, S_RAIN1); - - return; + mobj->momz = mobj->info->speed; + mobj->precipflags &= ~PCF_SPLASH; } + if (mobj->tics != -1) + { + if (mobj->tics) + { + mobj->tics--; + } + + if (mobj->tics == 0) + { + if ((mobj->precipflags & PCF_SPLASH) && (mobj->state->nextstate == S_NULL)) + { + // HACK: sprite changes are 1 tic late, so you would see splashes on the ceiling if not for this state. + // We need to use the settings from the previous state, since some of those are NOT 1 tic late. + INT32 frame = (mobj->frame & ~FF_FRAMEMASK); + P_SetPrecipMobjState(mobj, S_RAINRETURN); + mobj->frame = frame; + return; + } + else + { + if (!P_SetPrecipMobjState(mobj, mobj->state->nextstate)) + return; + } + } + } + + if (mobj->precipflags & PCF_SPLASH) + return; + // adjust height if ((mobj->z += mobj->momz) <= mobj->floorz) { - // no splashes on sky or bottomless pits - if (mobj->precipflags & PCF_PIT) + if ((mobj->info->deathstate == S_NULL) || (mobj->precipflags & PCF_PIT)) // no splashes on sky or bottomless pits + { mobj->z = mobj->ceilingz; + } else { + P_SetPrecipMobjState(mobj, mobj->info->deathstate); mobj->z = mobj->floorz; - P_SetPrecipMobjState(mobj, S_SPLASH1); + mobj->precipflags |= PCF_SPLASH; } } } @@ -6354,9 +6363,8 @@ fixed_t P_CalculateShadowFloor(mobj_t *mobj, fixed_t x, fixed_t y, fixed_t z, fi } } -#if 0 mobj->standingslope = slope; -#endif + #ifdef HWRENDER mobj->modeltilt = slope; #endif @@ -10754,17 +10762,21 @@ mobj_t *P_SpawnShadowMobj(mobj_t * caster) static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) { + const mobjinfo_t *info = &mobjinfo[type]; state_t *st; precipmobj_t *mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); fixed_t starting_floorz; + mobj->type = type; + mobj->info = info; + mobj->x = x; mobj->y = y; - mobj->flags = mobjinfo[type].flags; + mobj->flags = info->flags; // do not set the state with P_SetMobjState, // because action routines can not be called yet - st = &states[mobjinfo[type].spawnstate]; + st = &states[info->spawnstate]; mobj->state = st; mobj->tics = st->tics; @@ -10787,7 +10799,7 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype mobj->subsector->sector->ceilingheight; mobj->z = z; - mobj->momz = mobjinfo[type].speed; + mobj->momz = info->speed; mobj->thinker.function.acp1 = (actionf_p1)P_NullPrecipThinker; P_AddThinker(&mobj->thinker); @@ -10804,21 +10816,6 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype return mobj; } -static inline precipmobj_t *P_SpawnRainMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) -{ - precipmobj_t *mo = P_SpawnPrecipMobj(x,y,z,type); - mo->precipflags |= PCF_RAIN; - //mo->thinker.function.acp1 = (actionf_p1)P_RainThinker; - return mo; -} - -static inline precipmobj_t *P_SpawnSnowMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) -{ - precipmobj_t *mo = P_SpawnPrecipMobj(x,y,z,type); - //mo->thinker.function.acp1 = (actionf_p1)P_SnowThinker; - return mo; -} - // // P_RemoveMobj // @@ -11007,8 +11004,8 @@ consvar_t cv_suddendeath = {"suddendeath", "Off", CV_NETVAR|CV_CHEAT|CV_NOSHOWHE void P_SpawnPrecipitation(void) { - INT32 i, mrand; - fixed_t basex, basey, x, y, height; + INT32 i, j, k; + fixed_t basex, basey, x, y, z, height; subsector_t *precipsector = NULL; precipmobj_t *rainmo = NULL; @@ -11021,8 +11018,9 @@ 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 kart always { + UINT16 numparticles = 0; + x = basex + ((M_RandomKey(MAPBLOCKUNITS<<3)<>3); y = basey + ((M_RandomKey(MAPBLOCKUNITS<<3)<>3); @@ -11037,40 +11035,43 @@ void P_SpawnPrecipitation(void) if (precipsector->sector->ceilingpic != skyflatnum) continue; + height = abs(precipsector->sector->ceilingheight - precipsector->sector->floorheight); + // Exists, but is too small for reasonable precipitation. - if (!(precipsector->sector->floorheight <= precipsector->sector->ceilingheight - (32<sector->ceilingheight; + // Hack around a quirk of this entire system, where taller sectors look like they get less precipitation. + numparticles = 1 + (height / (MAPBLOCKUNITS<<4<sector->ceilingheight; + + for (j = 0; j < numparticles; j++) { - 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); + rainmo = P_SpawnPrecipMobj(x, y, z, precipprops[curWeather].type); + + if (precipprops[curWeather].randomstates > 0) + { + UINT8 mrand = M_RandomByte(); + UINT8 threshold = UINT8_MAX / (precipprops[curWeather].randomstates + 1); + statenum_t st = mobjinfo[precipprops[curWeather].type].spawnstate; + + for (k = 0; k < precipprops[curWeather].randomstates; k++) + { + if (mrand < (threshold * (k+1))) + { + 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)< 255) volume = 255; - if (sounds_rain && (!leveltime || leveltime % 80 == 1)) - S_StartSoundAtVolume(players[displayplayers[0]].mo, sfx_rainin, volume); + if (rainsfx != sfx_None && (!leveltime || leveltime % rainfreq == 1)) + S_StartSoundAtVolume(players[displayplayers[0]].mo, rainsfx, volume); if (!sounds_thunder) return; diff --git a/src/p_mobj.h b/src/p_mobj.h index aec2ed951..da3ba88e6 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -253,25 +253,23 @@ typedef enum // PRECIPITATION flags ?! ?! ?! // typedef enum { - // Don't draw. - PCF_INVISIBLE = 1, - // Above pit. - PCF_PIT = 2, - // Above FOF. - PCF_FOF = 4, - // Above MOVING FOF (this means we need to keep floorz up to date...) - PCF_MOVINGFOF = 8, - // Is rain. - PCF_RAIN = 16, - // Ran the thinker this tic. - PCF_THUNK = 32, + 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. } precipflag_t; + // Map Object definition. typedef struct mobj_s { // List: thinker links. thinker_t thinker; + mobjtype_t type; + const mobjinfo_t *info; // &mobjinfo[mobj->type] + // Info for drawing: position. fixed_t x, y, z; @@ -321,9 +319,6 @@ typedef struct mobj_s struct mobj_s *hnext; struct mobj_s *hprev; - mobjtype_t type; - const mobjinfo_t *info; // &mobjinfo[mobj->type] - INT32 health; // for player this is rings + 1 // Movement direction, movement generation (zig-zagging). @@ -392,6 +387,9 @@ typedef struct precipmobj_s // List: thinker links. thinker_t thinker; + mobjtype_t type; + const mobjinfo_t *info; // &mobjinfo[mobj->type] + // Info for drawing: position. fixed_t x, y, z; @@ -459,8 +457,7 @@ void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 numb boolean P_BossTargetPlayer(mobj_t *actor, boolean closest); boolean P_SupermanLook4Players(mobj_t *actor); void P_DestroyRobots(void); -void P_SnowThinker(precipmobj_t *mobj); -void P_RainThinker(precipmobj_t *mobj); +void P_PrecipThinker(precipmobj_t *mobj); void P_NullPrecipThinker(precipmobj_t *mobj); void P_RemovePrecipMobj(precipmobj_t *mobj); void P_SetScale(mobj_t *mobj, fixed_t newscale); diff --git a/src/p_spec.c b/src/p_spec.c index 93e88e2ce..d92fb2f3b 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2003,57 +2003,28 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) // // Switches the weather! // -void P_SwitchWeather(INT32 weathernum) +void P_SwitchWeather(UINT8 newWeather) { boolean purge = false; - INT32 swap = 0; + mobjtype_t swap = MT_NULL; - switch (weathernum) + if (precipprops[newWeather].type == MT_NULL) { - case PRECIP_NONE: // None - if (curWeather == PRECIP_NONE) - return; // Nothing to do. - purge = true; - break; - case PRECIP_STORM: // Storm - case PRECIP_STORM_NOSTRIKES: // Storm w/ no lightning - case PRECIP_RAIN: // Rain - if (curWeather == PRECIP_SNOW || curWeather == PRECIP_BLANK || curWeather == PRECIP_STORM_NORAIN) - swap = PRECIP_RAIN; - break; - case PRECIP_SNOW: // Snow - if (curWeather == PRECIP_SNOW) - return; // Nothing to do. - if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES || curWeather == PRECIP_BLANK || curWeather == PRECIP_STORM_NORAIN) - swap = PRECIP_SNOW; // Need to delete the other precips. - break; - case PRECIP_STORM_NORAIN: // Storm w/o rain - if (curWeather == PRECIP_SNOW - || curWeather == PRECIP_STORM - || curWeather == PRECIP_STORM_NOSTRIKES - || curWeather == PRECIP_RAIN - || curWeather == PRECIP_BLANK) - swap = PRECIP_STORM_NORAIN; - else if (curWeather == PRECIP_STORM_NORAIN) - return; - break; - case PRECIP_BLANK: - if (curWeather == PRECIP_SNOW - || curWeather == PRECIP_STORM - || curWeather == PRECIP_STORM_NOSTRIKES - || curWeather == PRECIP_RAIN) - swap = PRECIP_BLANK; - else if (curWeather == PRECIP_STORM_NORAIN) - swap = PRECIP_BLANK; - else if (curWeather == PRECIP_BLANK) - return; - break; - default: - CONS_Debug(DBG_GAMELOGIC, "P_SwitchWeather: Unknown weather type %d.\n", weathernum); - break; + // New type is null, we want to purge the weather. + if (precipprops[curWeather].type == MT_NULL) + return; // Nothing to do. + purge = true; + } + else + { + if (precipprops[curWeather].type != MT_NULL) + { + // There are already existing weather particles to reuse. + swap = precipprops[newWeather].type; + } } - if (purge) + if (purge == true) { thinker_t *think; precipmobj_t *precipmobj; @@ -2068,136 +2039,53 @@ void P_SwitchWeather(INT32 weathernum) P_RemovePrecipMobj(precipmobj); } } - else if (swap && !((swap == PRECIP_BLANK && curWeather == PRECIP_STORM_NORAIN) || (swap == PRECIP_STORM_NORAIN && curWeather == PRECIP_BLANK))) // Rather than respawn all that crap, reuse it! + else if (swap != MT_NULL) // Rather than respawn all that crap, reuse it! { thinker_t *think; precipmobj_t *precipmobj; - state_t *st; + statenum_t st; for (think = thinkercap.next; think != &thinkercap; think = think->next) { if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker) continue; // not a precipmobj thinker + precipmobj = (precipmobj_t *)think; - if (swap == PRECIP_RAIN) // Snow To Rain + precipmobj->flags = mobjinfo[swap].flags; + + st = mobjinfo[swap].spawnstate; + + if (precipprops[curWeather].randomstates > 0) { - precipmobj->flags = mobjinfo[MT_RAIN].flags; - st = &states[mobjinfo[MT_RAIN].spawnstate]; - precipmobj->state = st; - precipmobj->tics = st->tics; - precipmobj->sprite = st->sprite; - precipmobj->frame = st->frame; - precipmobj->momz = mobjinfo[MT_RAIN].speed; + UINT8 mrand = M_RandomByte(); + UINT8 threshold = UINT8_MAX / (precipprops[curWeather].randomstates + 1); + UINT8 i; - precipmobj->precipflags &= ~PCF_INVISIBLE; - - precipmobj->precipflags |= PCF_RAIN; - //think->function.acp1 = (actionf_p1)P_RainThinker; + for (i = 0; i < precipprops[curWeather].randomstates; i++) + { + if (mrand < (threshold * (i+1))) + { + st += i+1; + break; + } + } } - else if (swap == PRECIP_SNOW) // Rain To Snow - { - INT32 z; - precipmobj->flags = mobjinfo[MT_SNOWFLAKE].flags; - z = M_RandomByte(); + precipmobj->state = &states[st]; + precipmobj->tics = precipmobj->state->tics; + precipmobj->sprite = precipmobj->state->sprite; + precipmobj->frame = precipmobj->state->frame; - if (z < 64) - z = 2; - else if (z < 144) - z = 1; - else - z = 0; - - st = &states[mobjinfo[MT_SNOWFLAKE].spawnstate+z]; - precipmobj->state = st; - precipmobj->tics = st->tics; - precipmobj->sprite = st->sprite; - precipmobj->frame = st->frame; - precipmobj->momz = mobjinfo[MT_SNOWFLAKE].speed; - - precipmobj->precipflags &= ~(PCF_INVISIBLE|PCF_RAIN); - - //think->function.acp1 = (actionf_p1)P_SnowThinker; - } - else if (swap == PRECIP_BLANK || swap == PRECIP_STORM_NORAIN) // Remove precip, but keep it around for reuse. - { - //think->function.acp1 = (actionf_p1)P_NullPrecipThinker; - - precipmobj->precipflags |= PCF_INVISIBLE; - } + precipmobj->momz = mobjinfo[swap].speed; + precipmobj->precipflags &= ~PCF_INVISIBLE; } } - switch (weathernum) - { - case PRECIP_SNOW: // snow - curWeather = PRECIP_SNOW; + curWeather = newWeather; - if (!swap) - P_SpawnPrecipitation(); - - break; - case PRECIP_RAIN: // rain - { - boolean dontspawn = false; - - if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES) - dontspawn = true; - - curWeather = PRECIP_RAIN; - - if (!dontspawn && !swap) - P_SpawnPrecipitation(); - - break; - } - case PRECIP_STORM: // storm - { - boolean dontspawn = false; - - if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES) - dontspawn = true; - - curWeather = PRECIP_STORM; - - if (!dontspawn && !swap) - P_SpawnPrecipitation(); - - break; - } - case PRECIP_STORM_NOSTRIKES: // storm w/o lightning - { - boolean dontspawn = false; - - if (curWeather == PRECIP_RAIN || curWeather == PRECIP_STORM || curWeather == PRECIP_STORM_NOSTRIKES) - dontspawn = true; - - curWeather = PRECIP_STORM_NOSTRIKES; - - if (!dontspawn && !swap) - P_SpawnPrecipitation(); - - break; - } - case PRECIP_STORM_NORAIN: // storm w/o rain - curWeather = PRECIP_STORM_NORAIN; - - if (!swap) - P_SpawnPrecipitation(); - - break; - case PRECIP_BLANK: - curWeather = PRECIP_BLANK; - - if (!swap) - P_SpawnPrecipitation(); - - break; - default: - curWeather = PRECIP_NONE; - break; - } + if (swap == MT_NULL && precipprops[newWeather].type != MT_NULL) + P_SpawnPrecipitation(); } /** Gets an object. @@ -5672,25 +5560,10 @@ void P_InitSpecials(void) CheckForBustableBlocks = CheckForBouncySector = CheckForQuicksand = CheckForMarioBlocks = CheckForFloatBob = CheckForReverseGravity = false; - // Set curWeather - switch (mapheaderinfo[gamemap-1]->weather) - { - case PRECIP_SNOW: // snow - case PRECIP_RAIN: // rain - case PRECIP_STORM: // storm - case PRECIP_STORM_NORAIN: // storm w/o rain - case PRECIP_STORM_NOSTRIKES: // storm w/o lightning - curWeather = mapheaderinfo[gamemap-1]->weather; - break; - default: // blank/none - curWeather = PRECIP_NONE; - break; - } + // Set weather + curWeather = globalweather = mapheaderinfo[gamemap-1]->weather; - // Set globalweather - globalweather = mapheaderinfo[gamemap-1]->weather; - - P_InitTagLists(); // Create xref tables for tags + P_InitTagLists(); // Create xref tables for tags } /** After the map has loaded, scans for specials that spawn 3Dfloors and diff --git a/src/p_spec.h b/src/p_spec.h index b604ac951..1aca41155 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -59,7 +59,7 @@ INT32 P_FindMinSurroundingLight(sector_t *sector, INT32 max); void P_SetupSignExit(player_t *player); boolean P_IsFlagAtBase(mobjtype_t flag); -void P_SwitchWeather(INT32 weathernum); +void P_SwitchWeather(UINT8 newWeather); boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller); void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller); diff --git a/src/p_tick.c b/src/p_tick.c index b285c35d0..9e4de8e33 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -58,8 +58,6 @@ void Command_Numthinkers_f(void) CONS_Printf(M_GetText("numthinkers <#>: Count number of thinkers\n")); CONS_Printf( "\t1: P_MobjThinker\n" - /*"\t2: P_RainThinker\n" - "\t3: P_SnowThinker\n"*/ "\t2: P_NullPrecipThinker\n" "\t3: T_Friction\n" "\t4: T_Pusher\n" @@ -75,14 +73,6 @@ void Command_Numthinkers_f(void) action = (actionf_p1)P_MobjThinker; CONS_Printf(M_GetText("Number of %s: "), "P_MobjThinker"); break; - /*case 2: - action = (actionf_p1)P_RainThinker; - CONS_Printf(M_GetText("Number of %s: "), "P_RainThinker"); - break; - case 3: - action = (actionf_p1)P_SnowThinker; - CONS_Printf(M_GetText("Number of %s: "), "P_SnowThinker"); - break;*/ case 2: action = (actionf_p1)P_NullPrecipThinker; CONS_Printf(M_GetText("Number of %s: "), "P_NullPrecipThinker"); diff --git a/src/r_things.c b/src/r_things.c index 1afbb125c..847f011ec 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1639,14 +1639,10 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) // 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); + P_PrecipThinker(thing); thing->precipflags |= PCF_THUNK; } - //SoM: 3/17/2000: Disregard sprites that are out of view.. gzt = thing->z + spritecachedinfo[lump].topoffset; gz = gzt - spritecachedinfo[lump].height;