From 4c3f89cdf7c592176243793c8b8d170dc86d5bc7 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 31 May 2022 09:03:06 -0400 Subject: [PATCH 01/12] Allow freesloting & editing precipprops Allows for custom weather types. In SOC: ```Freeslot PRECIP_GROOVY Weather PRECIP_GROOVY Type = MT_PARTICLE Effects = PRECIPFX_THUNDER|PRECIPFX_LIGHTNING``` In Lua: ```freeslot("PRECIP_GROOVY") precipprops[PRECIP_GROOVY] = { type = MT_PARTICLE, effects = PRECIPFX_THUNDER|PRECIPFX_LIGHTNING }``` Then in level header, simply set `Weather = PRECIP_GROOVY`. Other properties are part of the object itself: - Falling speed is set as the object's speed - Sound ID is set via the object's SeeSound - Sound frequency is set by the object's Mass. --- src/deh_lua.c | 21 ++++++ src/deh_soc.c | 94 ++++++++++++++++++++++++- src/deh_soc.h | 2 + src/deh_tables.c | 4 ++ src/dehacked.c | 12 ++++ src/doomstat.h | 15 +++- src/g_game.c | 20 +++--- src/lua_baselib.c | 1 + src/lua_infolib.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++ src/lua_libs.h | 1 + src/p_setup.c | 2 +- src/p_spec.c | 9 ++- src/p_spec.h | 2 +- 13 files changed, 338 insertions(+), 15 deletions(-) diff --git a/src/deh_lua.c b/src/deh_lua.c index 6e892d5e2..944a8b67a 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -186,6 +186,27 @@ static inline int lib_freeslot(lua_State *L) } } } + else if (fastcmp(type, "PRECIP")) + { + // Search if we already have a PRECIP by that name... + preciptype_t i; + for (i = PRECIP_FIRSTFREESLOT; i < precip_freeslot; i++) + if (fastcmp(word, precipprops[i].name)) + break; + + // We don't, so allocate a new one. + if (i >= precip_freeslot) { + if (precip_freeslot < MAXPRECIP) + { + CONS_Printf("Weather PRECIP_%s allocated.\n",word); + precipprops[i].name = Z_StrDup(word); + lua_pushinteger(L, precip_freeslot); + r++; + precip_freeslot++; + } else + CONS_Alert(CONS_WARNING, "Ran out of free PRECIP slots!\n"); + } + } Z_Free(s); lua_remove(L, 1); continue; diff --git a/src/deh_soc.c b/src/deh_soc.c index 617857609..8617ad3bb 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -481,6 +481,25 @@ void readfreeslots(MYFILE *f) lastcustomtol <<= 1; } } + else if (fastcmp(type, "PRECIP")) + { + // Search if we already have a PRECIP by that name... + for (i = PRECIP_FIRSTFREESLOT; i < (int)precip_freeslot; i++) + if (fastcmp(word, precipprops[i].name)) + break; + + // We found it? Then don't allocate another one. + if (i < (int)precip_freeslot) + continue; + + // We don't, so allocate a new one. + if (precip_freeslot < MAXPRECIP) + { + precipprops[i].name = Z_StrDup(word); + precip_freeslot++; + } else + deh_warning("Ran out of free PRECIP slots!\n"); + } else deh_warning("Freeslots: unknown enum class '%s' for '%s_%s'", type, type, word); } @@ -1528,7 +1547,7 @@ void readlevelheader(MYFILE *f, INT32 num) strlwr(mapheaderinfo[num-1]->forcecharacter); // skin names are lowercase } else if (fastcmp(word, "WEATHER")) - mapheaderinfo[num-1]->weather = (UINT8)get_number(word2); + mapheaderinfo[num-1]->weather = get_precip(word2); else if (fastcmp(word, "SKYTEXTURE")) deh_strlcpy(mapheaderinfo[num-1]->skytexture, word2, sizeof(mapheaderinfo[num-1]->skytexture), va("Level header %d: sky texture", num)); @@ -4086,6 +4105,61 @@ if (!followers[numfollowers].field) \ Z_Free(s); } +void readweather(MYFILE *f, INT32 num) +{ + char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); + char *word; + char *word2; + char *tmp; + + do + { + if (myfgets(s, MAXLINELEN, f)) + { + if (s[0] == '\n') + break; + + // First remove trailing newline, if there is one + tmp = strchr(s, '\n'); + if (tmp) + *tmp = '\0'; + + tmp = strchr(s, '#'); + if (tmp) + *tmp = '\0'; + if (s == tmp) + continue; // Skip comment lines, but don't break. + + // Set / reset word + word = s; + + // Get the part before the " = " + tmp = strchr(s, '='); + if (tmp) + *(tmp-1) = '\0'; + else + break; + strupr(word); + + // Now get the part after + word2 = tmp += 2; + + if (fastcmp(word, "TYPE")) + { + precipprops[num].type = get_mobjtype(word2); + } + else if (fastcmp(word, "EFFECTS")) + { + precipprops[num].effects = get_number(word2); + } + else + deh_warning("Weather %d : unknown word '%s'", num, word); + } + } while (!myfeof(f)); + + Z_Free(s); +} + // // // @@ -4222,6 +4296,24 @@ menutype_t get_menutype(const char *word) return GT_COOP; }*/ +preciptype_t get_precip(const char *word) +{ // Returns the value of PRECIP_ enumerations + preciptype_t i; + if (*word >= '0' && *word <= '9') + return atoi(word); + if (fastncmp("PRECIP_",word,4)) + word += 7; // take off the PRECIP_ + for (i = 0; i < MAXPRECIP; i++) + { + if (precipprops[i].name == NULL) + break; + if (fasticmp(word, precipprops[i].name)) + return i; + } + deh_warning("Couldn't find weather type named 'PRECIP_%s'",word); + return PRECIP_RAIN; +} + /// \todo Make ANY of this completely over-the-top math craziness obey the order of operations. static fixed_t op_mul(fixed_t a, fixed_t b) { return a*b; } static fixed_t op_div(fixed_t a, fixed_t b) { return a/b; } diff --git a/src/deh_soc.h b/src/deh_soc.h index e2319ab14..7381e548c 100644 --- a/src/deh_soc.h +++ b/src/deh_soc.h @@ -85,5 +85,7 @@ void clear_conditionsets(void); void readcupheader(MYFILE *f, cupheader_t *cup); void readfollower(MYFILE *f); +preciptype_t get_precip(const char *word); +void readweather(MYFILE *f, INT32 num); #endif diff --git a/src/deh_tables.c b/src/deh_tables.c index b01e3ff4b..e421d2b4b 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -6741,6 +6741,10 @@ struct int_const_s const INT_CONST[] = { {"SPOT_WEAK",SPOT_WEAK}, {"SPOT_BUMP",SPOT_BUMP}, + // precipeffect_t + {"PRECIPFX_THUNDER",PRECIPFX_THUNDER}, + {"PRECIPFX_LIGHTNING",PRECIPFX_LIGHTNING}, + {NULL,0} }; diff --git a/src/dehacked.c b/src/dehacked.c index 7288ac374..970f84b9a 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -576,6 +576,18 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) readcupheader(f, cup); } + if (fastcmp(word, "WEATHER") || fastcmp(word, "PRECIP") || fastcmp(word, "PRECIPITATION")) + { + if (i == 0 && word2[0] != '0') // If word2 isn't a number + i = get_precip(word2); // find a weather type by name + if (i < MAXPRECIP && i > 0) + readweather(f, i); + else + { + deh_warning("Weather number %d out of range (1 - %d)", i, MAXPRECIP-1); + ignorelines(f); + } + } else if (fastcmp(word, "RINGRACERS")) { if (isdigit(word2[0])) diff --git a/src/doomstat.h b/src/doomstat.h index 4b3f75d13..5a2478b48 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -41,8 +41,7 @@ extern UINT32 mapmusresume; // Use other bits if necessary. extern UINT32 maptol; -extern UINT8 globalweather; -extern UINT8 curWeather; + extern INT32 cursaveslot; //extern INT16 lastmapsaved; extern INT16 lastmaploaded; @@ -64,15 +63,22 @@ extern tic_t marathontime; extern UINT8 numgameovers; extern SINT8 startinglivesbalance[maxgameovers+1]; +#define NUMPRECIPFREESLOTS 64 + typedef enum { PRECIP_NONE = 0, + PRECIP_RAIN, PRECIP_SNOW, PRECIP_BLIZZARD, PRECIP_STORM, PRECIP_STORM_NORAIN, PRECIP_STORM_NOSTRIKES, + + PRECIP_FIRSTFREESLOT, + PRECIP_LASTFREESLOT = PRECIP_FIRSTFREESLOT + NUMPRECIPFREESLOTS - 1, + MAXPRECIP } preciptype_t; @@ -84,11 +90,16 @@ typedef enum typedef struct { + const char *name; mobjtype_t type; precipeffect_t effects; } precipprops_t; extern precipprops_t precipprops[MAXPRECIP]; +extern preciptype_t precip_freeslot; + +extern preciptype_t globalweather; +extern preciptype_t curWeather; // Set if homebrew PWAD stuff has been added. extern boolean modifiedgame; diff --git a/src/g_game.c b/src/g_game.c index 896ea00ea..2939dee2e 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -93,20 +93,22 @@ UINT32 mapmusresume; INT16 gamemap = 1; UINT32 maptol; -UINT8 globalweather = PRECIP_NONE; -UINT8 curWeather = PRECIP_NONE; +preciptype_t globalweather = PRECIP_NONE; +preciptype_t curWeather = PRECIP_NONE; precipprops_t precipprops[MAXPRECIP] = { - {MT_NULL, 0}, // PRECIP_NONE - {MT_RAIN, 0}, // PRECIP_RAIN - {MT_SNOWFLAKE, 0}, // PRECIP_SNOW - {MT_BLIZZARDSNOW, 0}, // PRECIP_BLIZZARD - {MT_RAIN, PRECIPFX_THUNDER|PRECIPFX_LIGHTNING}, // PRECIP_STORM - {MT_NULL, PRECIPFX_THUNDER|PRECIPFX_LIGHTNING}, // PRECIP_STORM_NORAIN - {MT_RAIN, PRECIPFX_THUNDER} // PRECIP_STORM_NOSTRIKES + {"NONE", MT_NULL, 0}, // PRECIP_NONE + {"RAIN", MT_RAIN, 0}, // PRECIP_RAIN + {"SNOW", MT_SNOWFLAKE, 0}, // PRECIP_SNOW + {"BLIZZARD", MT_BLIZZARDSNOW, 0}, // PRECIP_BLIZZARD + {"STORM", MT_RAIN, PRECIPFX_THUNDER|PRECIPFX_LIGHTNING}, // PRECIP_STORM + {"STORM_NORAIN", MT_NULL, PRECIPFX_THUNDER|PRECIPFX_LIGHTNING}, // PRECIP_STORM_NORAIN + {"STORM_NOSTRIKES", MT_RAIN, PRECIPFX_THUNDER} // PRECIP_STORM_NOSTRIKES }; +preciptype_t precip_freeslot = PRECIP_FIRSTFREESLOT; + INT32 cursaveslot = 0; // Auto-save 1p savegame slot //INT16 lastmapsaved = 0; // Last map we auto-saved at INT16 lastmaploaded = 0; // Last map the game loaded diff --git a/src/lua_baselib.c b/src/lua_baselib.c index a461ac80b..301665e45 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -163,6 +163,7 @@ static const struct { {META_SPRITEINFO, "spriteinfo_t"}, {META_PIVOTLIST, "spriteframepivot_t[]"}, {META_FRAMEPIVOT, "spriteframepivot_t"}, + {META_PRECIPPROPS, "precipprops_t"}, {META_TAGLIST, "taglist"}, diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 880496770..88cb32ed9 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -1758,6 +1758,152 @@ static int colorramp_len(lua_State *L) return 1; } +////////////////// +// PRECIP PROPS // +////////////////// + +// Arbitrary precipprops[] table index -> precipprops_t * +static int lib_getPrecipProps(lua_State *L) +{ + INT32 i; + lua_remove(L, 1); + + i = luaL_checkinteger(L, 1); + if (i <= 0 || i >= MAXPRECIP) + return luaL_error(L, "precipprops[] index %d out of range (1 - %d)", i, MAXPRECIP-1); + LUA_PushUserdata(L, &precipprops[i], META_PRECIPPROPS); + return 1; +} + +// Lua table full of data -> precipprops[] +static int lib_setPrecipProps(lua_State *L) +{ + precipprops_t *props; + lua_remove(L, 1); // don't care about precipprops[] userdata. + { + INT32 i = luaL_checkinteger(L, 1); + if (i <= 0 || i >= MAXPRECIP) + return luaL_error(L, "precipprops[] index %d out of range (1 - %d)", i, MAXPRECIP-1); + props = &precipprops[i]; // get the precipprops to assign to. + } + + luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table. + lua_remove(L, 1); // pop preciptype num, don't need it any more. + lua_settop(L, 1); // cut the stack here. the only thing left now is the table of data we're assigning to the precipprops. + + if (hud_running) + return luaL_error(L, "Do not alter precipprops in HUD rendering code!"); + if (hook_cmd_running) + return luaL_error(L, "Do not alter precipprops in CMD building code!"); + + // clear the precipprops to start with, in case of missing table elements + // done manually because we do not want to clear name + props->type = MT_NULL; + props->effects = 0; + + lua_pushnil(L); + while (lua_next(L, 1)) { + lua_Integer i = 0; + const char *str = NULL; + lua_Integer value; + + if (lua_isnumber(L, 2)) + i = lua_tointeger(L, 2); + else + str = luaL_checkstring(L, 2); + + if (i == 1 || (str && fastcmp(str, "type"))) + { + value = luaL_checkinteger(L, 3); + if (value < MT_NULL || value >= NUMMOBJTYPES) + return luaL_error(L, "type number %d is invalid.", value); + props->type = luaL_checkinteger(L, 3); + } + else if (i == 2 || (str && fastcmp(str, "effects"))) + { + props->effects = luaL_checkinteger(L, 3); + } + + lua_pop(L, 1); + } + return 0; +} + +// #precipprops -> MAXPRECIP +static int lib_precippropslen(lua_State *L) +{ + lua_pushinteger(L, MAXPRECIP); + return 1; +} + +// precipprops_t *, field -> number +static int precipprops_get(lua_State *L) +{ + precipprops_t *props = *((precipprops_t **)luaL_checkudata(L, 1, META_PRECIPPROPS)); + const char *field = luaL_checkstring(L, 2); + + I_Assert(props != NULL); + I_Assert(props >= precipprops); + + if (fastcmp(field, "type")) + { + lua_pushinteger(L, props->type); + } + else if (fastcmp(field,"effects")) + { + lua_pushinteger(L, props->effects); + } + else + { + CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "precipprops_t", field); + return 0; + } + + return 1; +} + +// precipprops_t *, field, number -> precipprops[] +static int precipprops_set(lua_State *L) +{ + precipprops_t *props = *((precipprops_t **)luaL_checkudata(L, 1, META_PRECIPPROPS)); + const char *field = luaL_checkstring(L, 2); + + if (hud_running) + return luaL_error(L, "Do not alter precipprops in HUD rendering code!"); + if (hook_cmd_running) + return luaL_error(L, "Do not alter precipprops in CMD building code!"); + + I_Assert(props != NULL); + I_Assert(props >= precipprops); + + if (fastcmp(field, "type")) + { + props->type = luaL_checkinteger(L, 3); + } + else if (fastcmp(field, "effects")) + { + props->effects = luaL_checkinteger(L, 3); + } + else + { + return luaL_error(L, LUA_QL("precipprops_t") " has no field named " LUA_QS, field); + } + + return 0; +} + +// precipprops_t * -> PRECIP_* +static int precipprops_num(lua_State *L) +{ + precipprops_t *props = *((precipprops_t **)luaL_checkudata(L, 1, META_PRECIPPROPS)); + + I_Assert(props != NULL); + I_Assert(props >= precipprops); + + lua_pushinteger(L, props - precipprops); + return 1; +} + ////////////////////////////// // // Now push all these functions into the Lua state! @@ -1861,6 +2007,17 @@ int LUA_InfoLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + luaL_newmetatable(L, META_PRECIPPROPS); + lua_pushcfunction(L, precipprops_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, precipprops_set); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, precipprops_num); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + lua_newuserdata(L, 0); lua_createtable(L, 0, 2); lua_pushcfunction(L, lib_getSprname); @@ -1961,6 +2118,19 @@ int LUA_InfoLib(lua_State *L) lua_setmetatable(L, -2); lua_setglobal(L, "spriteinfo"); + lua_newuserdata(L, 0); + lua_createtable(L, 0, 2); + lua_pushcfunction(L, lib_getPrecipProps); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_setPrecipProps); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, lib_precippropslen); + lua_setfield(L, -2, "__len"); + lua_setmetatable(L, -2); + lua_setglobal(L, "precipprops"); + luaL_newmetatable(L, META_LUABANKS); lua_pushcfunction(L, lib_getluabanks); lua_setfield(L, -2, "__index"); diff --git a/src/lua_libs.h b/src/lua_libs.h index a6580622b..bc8e4141e 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -28,6 +28,7 @@ extern lua_State *gL; #define META_SPRITEINFO "SPRITEINFO_T*" #define META_PIVOTLIST "SPRITEFRAMEPIVOT_T[]" #define META_FRAMEPIVOT "SPRITEFRAMEPIVOT_T*" +#define META_PRECIPPROPS "PRECIPPROPS_T*" #define META_TAGLIST "TAGLIST" diff --git a/src/p_setup.c b/src/p_setup.c index a47077ba5..372cfa91b 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -390,7 +390,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 i) mapheaderinfo[num]->muspostbossfadein = 0; mapheaderinfo[num]->musforcereset = -1; mapheaderinfo[num]->forcecharacter[0] = '\0'; - mapheaderinfo[num]->weather = 0; + mapheaderinfo[num]->weather = PRECIP_NONE; snprintf(mapheaderinfo[num]->skytexture, 5, "SKY1"); mapheaderinfo[num]->skytexture[4] = 0; mapheaderinfo[num]->skybox_scalex = 16; diff --git a/src/p_spec.c b/src/p_spec.c index 53d3b5370..56e1456ea 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1769,11 +1769,18 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) // // Switches the weather! // -void P_SwitchWeather(UINT8 newWeather) +void P_SwitchWeather(preciptype_t newWeather) { boolean purge = false; mobjtype_t swap = MT_NULL; + if (newWeather >= precip_freeslot) + { + // Weather type invalid, set to no weather. + CONS_Debug(DBG_SETUP, "Weather ID %d out of bounds\n", newWeather); + newWeather = PRECIP_NONE; + } + if (precipprops[newWeather].type == MT_NULL) { // New type is null, we want to purge the weather. diff --git a/src/p_spec.h b/src/p_spec.h index cbcbf366d..6f84c3aac 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -67,7 +67,7 @@ void P_CrossSpecialLine(line_t *ld, INT32 side, mobj_t *thing); void P_SetupSignExit(player_t *player); boolean P_IsFlagAtBase(mobjtype_t flag); -void P_SwitchWeather(UINT8 newWeather); +void P_SwitchWeather(preciptype_t newWeather); boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller); void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller); From 087c15c1efd026c534e53b0116337dd2bce0a535 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 31 May 2022 09:08:01 -0400 Subject: [PATCH 02/12] Add PRECIP_ to enum lib --- src/deh_lua.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/deh_lua.c b/src/deh_lua.c index 944a8b67a..f4c3bcf41 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -496,6 +496,21 @@ static inline int lib_getenum(lua_State *L) if (mathlib) return luaL_error(L, "menutype '%s' could not be found.\n", word); return 0; } + else if (fastncmp("PRECIP_",word,7)) { + p = word+7; + for (i = 0; i < MAXPRECIP; i++) + { + if (precipprops[i].name == NULL) + break; + + if (fastcmp(p, precipprops[i].name)) + { + lua_pushinteger(L, PRECIP_NONE + i); + return 1; + } + } + return luaL_error(L, "weather type '%s' does not exist.\n", word); + } else if (!mathlib && fastncmp("A_",word,2)) { char *caps; // Try to get a Lua action first. From 27c9d698bea5747b333c94ad33ecd42bbe9cc3ad Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 31 May 2022 09:14:19 -0400 Subject: [PATCH 03/12] Reverse weather speed Makes more logical sense on the user end for negative to go up, since most weather should be going down. They need to SPAWN with reversed momz too :V --- src/info.c | 6 +++--- src/p_mobj.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/info.c b/src/info.c index 754530837..78181c2e7 100644 --- a/src/info.c +++ b/src/info.c @@ -18246,7 +18246,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_SPLASH1, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound - -72*FRACUNIT, // speed + 72*FRACUNIT, // speed 1*FRACUNIT, // radius 8*FRACUNIT, // height 0, // display offset @@ -18273,7 +18273,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound - -2*FRACUNIT, // speed + 2*FRACUNIT, // speed 4*FRACUNIT, // radius 4*FRACUNIT, // height 0, // display offset @@ -18300,7 +18300,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL, // deathstate S_NULL, // xdeathstate sfx_None, // deathsound - -24*FRACUNIT, // speed + 24*FRACUNIT, // speed 4*FRACUNIT, // radius 4*FRACUNIT, // height 0, // display offset diff --git a/src/p_mobj.c b/src/p_mobj.c index 5219fb707..1fa1e0b92 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3825,7 +3825,7 @@ void P_PrecipThinker(precipmobj_t *mobj) // Reset to ceiling! P_SetPrecipMobjState(mobj, mobj->info->spawnstate); mobj->z = mobj->ceilingz; - mobj->momz = mobj->info->speed; + mobj->momz = -mobj->info->speed; mobj->precipflags &= ~PCF_SPLASH; } @@ -10371,7 +10371,7 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype mobj->ceilingrover = NULL; mobj->z = z; - mobj->momz = info->speed; + mobj->momz = -info->speed; mobj->thinker.function.acp1 = (actionf_p1)P_NullPrecipThinker; P_AddThinker(THINK_PRECIP, &mobj->thinker); From 965558c52fd0ba4ec3fcbeefe6d4b206cac904d6 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 31 May 2022 10:05:41 -0400 Subject: [PATCH 04/12] Fix precip interpolation (If Ediolon reads this, I'm pretty sure this one is Ring Racers only) --- 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 1fa1e0b92..aedf37ad2 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3812,12 +3812,11 @@ void P_NullPrecipThinker(precipmobj_t *mobj) { //(void)mobj; mobj->precipflags &= ~PCF_THUNK; + R_ResetPrecipitationMobjInterpolationState(mobj); } void P_PrecipThinker(precipmobj_t *mobj) { - R_ResetPrecipitationMobjInterpolationState(mobj); - P_CycleStateAnimation((mobj_t *)mobj); if (mobj->state == &states[S_RAINRETURN]) @@ -3827,6 +3826,7 @@ void P_PrecipThinker(precipmobj_t *mobj) mobj->z = mobj->ceilingz; mobj->momz = -mobj->info->speed; mobj->precipflags &= ~PCF_SPLASH; + R_ResetPrecipitationMobjInterpolationState(mobj); } if (mobj->tics != -1) From a33c2743a156927fa325a81a904f2180f3de1958 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Tue, 31 May 2022 19:33:18 -0400 Subject: [PATCH 05/12] Clear precipprops in Lua more automatically --- src/lua_infolib.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 88cb32ed9..1aaa207de 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -1797,9 +1797,8 @@ static int lib_setPrecipProps(lua_State *L) return luaL_error(L, "Do not alter precipprops in CMD building code!"); // clear the precipprops to start with, in case of missing table elements - // done manually because we do not want to clear name - props->type = MT_NULL; - props->effects = 0; + // make sure we do not clear the name + memset(props + sizeof(props->name), 0, sizeof(precipprops_t) - sizeof(props->name)); lua_pushnil(L); while (lua_next(L, 1)) { From 5c35602d7f522e33bc4c72269214d0cd4ece94e9 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 1 Jun 2022 00:36:53 -0400 Subject: [PATCH 06/12] Fix different types from mobj_t --- src/p_mobj.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/p_mobj.h b/src/p_mobj.h index 09f1c9a87..f7fd6d335 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -462,6 +462,8 @@ typedef struct precipmobj_s fixed_t ceilingz; // Nearest ceiling above. struct ffloor_s *floorrover; // FOF referred by floorz struct ffloor_s *ceilingrover; // FOF referred by ceilingz + fixed_t floordrop; + fixed_t ceilingdrop; // For movement checking. fixed_t radius; // Fixed at 2*FRACUNIT @@ -473,7 +475,7 @@ typedef struct precipmobj_s INT32 tics; // state tic counter state_t *state; - INT32 flags; // flags from mobjinfo tables + UINT32 flags; // flags from mobjinfo tables } precipmobj_t; typedef struct actioncache_s From f84baf47d57158ce348becee4d32fc55ff428241 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Wed, 1 Jun 2022 00:40:08 -0400 Subject: [PATCH 07/12] Fix missing else --- src/dehacked.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dehacked.c b/src/dehacked.c index 970f84b9a..b813106c4 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -576,7 +576,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) readcupheader(f, cup); } - if (fastcmp(word, "WEATHER") || fastcmp(word, "PRECIP") || fastcmp(word, "PRECIPITATION")) + else if (fastcmp(word, "WEATHER") || fastcmp(word, "PRECIP") || fastcmp(word, "PRECIPITATION")) { if (i == 0 && word2[0] != '0') // If word2 isn't a number i = get_precip(word2); // find a weather type by name From 35cc746adf7d0bf8d52613d5d49e28dc6ed9f5b3 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Fri, 3 Jun 2022 14:53:56 -0400 Subject: [PATCH 08/12] Blendmode support for weather --- src/r_things.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/r_things.c b/src/r_things.c index 804287fca..05276ea8e 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2188,6 +2188,9 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) //SoM: 3/17/2000 fixed_t gz, gzt; + UINT32 blendmode; + UINT32 trans; + // uncapped/interpolation interpmobjstate_t interp = {0}; @@ -2281,6 +2284,17 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) goto weatherthink; } + // Determine the blendmode and translucency value + { + blendmode = (thing->frame & FF_BLENDMASK) >> FF_BLENDSHIFT; + if (blendmode) + blendmode++; // realign to constants + + trans = (thing->frame & FF_TRANSMASK) >> FF_TRANSSHIFT; + if (trans >= NUMTRANSMAPS) + goto weatherthink; // cap + } + // store information in a vissprite vis = R_NewVisSprite(); vis->scale = vis->sortscale = yscale; //<patch = W_CachePatchNum(sprframe->lumppat[0], PU_SPRITE); - // specific translucency - // (no draw flags) - if (thing->frame & FF_TRANSMASK) - vis->transmap = ((thing->frame & FF_TRANSMASK) - FF_TRANS10) + transtables; - else - vis->transmap = NULL; + vis->transmap = R_GetBlendTable(blendmode, trans); vis->mobj = (mobj_t *)thing; vis->mobjflags = 0; From 6106ce162414acfa29e6175beec88e93dda64c4e Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 5 Jun 2022 05:39:35 -0400 Subject: [PATCH 09/12] 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; + } } } From 0e96aeec84eb3d6a42089300c510f254300345e1 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 5 Jun 2022 06:24:55 -0400 Subject: [PATCH 10/12] Add water particles --- src/deh_tables.c | 1 + src/doomstat.h | 3 ++- src/p_mobj.c | 43 ++++++++++++++++++++++++++++++++++++++----- src/p_spec.c | 12 +++++++++--- 4 files changed, 50 insertions(+), 9 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index e421d2b4b..9a733141f 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -6744,6 +6744,7 @@ struct int_const_s const INT_CONST[] = { // precipeffect_t {"PRECIPFX_THUNDER",PRECIPFX_THUNDER}, {"PRECIPFX_LIGHTNING",PRECIPFX_LIGHTNING}, + {"PRECIPFX_WATERPARTICLES",PRECIPFX_WATERPARTICLES}, {NULL,0} }; diff --git a/src/doomstat.h b/src/doomstat.h index 5a2478b48..4e782e59c 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -85,7 +85,8 @@ typedef enum typedef enum { PRECIPFX_THUNDER = 1, - PRECIPFX_LIGHTNING = 1<<1 + PRECIPFX_LIGHTNING = 1<<1, + PRECIPFX_WATERPARTICLES = 1<<2 } precipeffect_t; typedef struct diff --git a/src/p_mobj.c b/src/p_mobj.c index 1f6dc93e2..f4e863449 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3764,13 +3764,16 @@ void P_CalculatePrecipFloor(precipmobj_t *mobj) { // recalculate floorz each time const sector_t *mobjsecsubsec; + boolean setWater = false; if (mobj && mobj->subsector && mobj->subsector->sector) mobjsecsubsec = mobj->subsector->sector; else return; + mobj->precipflags &= ~PCF_INVISIBLE; mobj->floorz = P_GetSectorFloorZAt(mobjsecsubsec, mobj->x, mobj->y); + mobj->ceilingz = P_GetSectorFloorZAt(mobjsecsubsec, mobj->x, mobj->y); if (mobjsecsubsec->ffloors) { @@ -3783,14 +3786,44 @@ void P_CalculatePrecipFloor(precipmobj_t *mobj) if (!(rover->flags & FF_EXISTS)) continue; - if (!(rover->flags & FF_BLOCKOTHERS) && !(rover->flags & FF_SWIMMABLE)) - continue; + if (precipprops[curWeather].effects & PRECIPFX_WATERPARTICLES) + { + if (!(rover->flags & FF_SWIMMABLE)) + continue; - height = P_GetFFloorTopZAt(rover, mobj->x, mobj->y); - if (height > mobj->floorz) - mobj->floorz = height; + if (setWater == false) + { + mobj->ceilingz = P_GetFFloorTopZAt(rover, mobj->x, mobj->y); + mobj->floorz = P_GetFFloorBottomZAt(rover, mobj->x, mobj->y); + setWater = true; + } + else + { + height = P_GetFFloorTopZAt(rover, mobj->x, mobj->y); + if (height > mobj->ceilingz) + mobj->ceilingz = height; + + height = P_GetFFloorBottomZAt(rover, mobj->x, mobj->y); + if (height < mobj->floorz) + mobj->floorz = height; + } + } + else + { + if (!(rover->flags & FF_BLOCKOTHERS) && !(rover->flags & FF_SWIMMABLE)) + continue; + + height = P_GetFFloorTopZAt(rover, mobj->x, mobj->y); + if (height > mobj->floorz) + mobj->floorz = height; + } } } + + if ((precipprops[curWeather].effects & PRECIPFX_WATERPARTICLES) && setWater == false) + { + mobj->precipflags |= PCF_INVISIBLE; + } } void P_RecalcPrecipInSector(sector_t *sector) diff --git a/src/p_spec.c b/src/p_spec.c index 5d4f456de..8fe886c7d 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -1773,6 +1773,7 @@ void P_SwitchWeather(preciptype_t newWeather) { boolean purge = false; mobjtype_t swap = MT_NULL; + INT32 oldEffects = precipprops[curWeather].effects; if (newWeather >= precip_freeslot) { @@ -1797,6 +1798,8 @@ void P_SwitchWeather(preciptype_t newWeather) } } + curWeather = newWeather; + if (purge == true) { thinker_t *think; @@ -1858,12 +1861,15 @@ void P_SwitchWeather(preciptype_t newWeather) { precipmobj->precipflags |= PCF_FLIP; } + + if ((oldEffects & PRECIPFX_WATERPARTICLES) != (precipprops[curWeather].effects & PRECIPFX_WATERPARTICLES)) + { + P_CalculatePrecipFloor(precipmobj); + } } } - curWeather = newWeather; - - if (swap == MT_NULL && precipprops[newWeather].type != MT_NULL) + if (swap == MT_NULL && precipprops[curWeather].type != MT_NULL) P_SpawnPrecipitation(); } From 353ac60407196aef2615f09ebcdc652da8e3ee9c Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 5 Jun 2022 07:00:34 -0400 Subject: [PATCH 11/12] Proper sector condition for water particles --- src/p_mobj.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index f4e863449..3f58e6c5a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -10677,7 +10677,31 @@ void P_SpawnPrecipitation(void) continue; // Not in a sector with visible sky? - condition = (precipsector->sector->ceilingpic == skyflatnum); + if (precipprops[curWeather].effects & PRECIPFX_WATERPARTICLES) + { + condition = false; + + if (precipsector->sector->ffloors) + { + ffloor_t *rover; + + for (rover = precipsector->sector->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS)) + continue; + + if (!(rover->flags & FF_SWIMMABLE)) + continue; + + condition = true; + break; + } + } + } + else + { + condition = (precipsector->sector->ceilingpic == skyflatnum); + } if (precipsector->sector->flags & SF_INVERTPRECIP) { From f609043b2e621fae1bc0787eaed7cf0a6b876286 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 5 Jun 2022 12:59:24 -0400 Subject: [PATCH 12/12] Fix copy-paste error in P_CalculatePrecipFloor --- 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 3f58e6c5a..ea20da99e 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -3773,7 +3773,7 @@ void P_CalculatePrecipFloor(precipmobj_t *mobj) mobj->precipflags &= ~PCF_INVISIBLE; mobj->floorz = P_GetSectorFloorZAt(mobjsecsubsec, mobj->x, mobj->y); - mobj->ceilingz = P_GetSectorFloorZAt(mobjsecsubsec, mobj->x, mobj->y); + mobj->ceilingz = P_GetSectorCeilingZAt(mobjsecsubsec, mobj->x, mobj->y); if (mobjsecsubsec->ffloors) {