Merge branch 'custom-weather' into 'master'

Allow freesloting & editing precipprops

See merge request KartKrew/Kart!612
This commit is contained in:
James R 2022-06-11 03:05:37 +00:00
commit 6bc1d65442
18 changed files with 560 additions and 107 deletions

View file

@ -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;
@ -475,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.

View file

@ -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; }

View file

@ -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

View file

@ -6741,6 +6741,11 @@ 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},
{"PRECIPFX_WATERPARTICLES",PRECIPFX_WATERPARTICLES},
{NULL,0}
};

View file

@ -576,6 +576,18 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
readcupheader(f, cup);
}
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
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]))

View file

@ -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,31 +63,44 @@ 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;
typedef enum
{
PRECIPFX_THUNDER = 1,
PRECIPFX_LIGHTNING = 1<<1
PRECIPFX_LIGHTNING = 1<<1,
PRECIPFX_WATERPARTICLES = 1<<2
} precipeffect_t;
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;

View file

@ -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

View file

@ -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

View file

@ -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"},

View file

@ -1758,6 +1758,151 @@ 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
// 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)) {
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 +2006,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 +2117,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");

View file

@ -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"

View file

@ -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);

View file

@ -3760,19 +3760,25 @@ animonly:
P_CyclePlayerMobjState(mobj);
}
static void CalculatePrecipFloor(precipmobj_t *mobj)
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_GetSectorCeilingZAt(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)
{
@ -3780,14 +3786,44 @@ static void 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;
topheight = P_GetFFloorTopZAt(rover, mobj->x, mobj->y);
if (topheight > mobj->floorz)
mobj->floorz = topheight;
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)
@ -3800,7 +3836,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);
}
//
@ -3812,11 +3848,12 @@ void P_NullPrecipThinker(precipmobj_t *mobj)
{
//(void)mobj;
mobj->precipflags &= ~PCF_THUNK;
R_ResetPrecipitationMobjInterpolationState(mobj);
}
void P_PrecipThinker(precipmobj_t *mobj)
{
R_ResetPrecipitationMobjInterpolationState(mobj);
boolean flip = (mobj->precipflags & PCF_FLIP);
P_CycleStateAnimation((mobj_t *)mobj);
@ -3824,9 +3861,10 @@ 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->z = (flip) ? (mobj->floorz) : (mobj->ceilingz);
mobj->momz = -mobj->info->speed;
mobj->precipflags &= ~PCF_SPLASH;
R_ResetPrecipitationMobjInterpolationState(mobj);
}
if (mobj->tics != -1)
@ -3858,18 +3896,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 +10381,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,26 +10404,43 @@ 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;
mobj->z = z;
mobj->momz = info->speed;
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 +10645,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 +10666,87 @@ 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?
if (precipprops[curWeather].effects & PRECIPFX_WATERPARTICLES)
{
UINT16 numparticles = 0;
condition = false;
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?
if (precipsector->sector->ceilingpic != skyflatnum)
continue;
height = precipsector->sector->ceilingheight - precipsector->sector->floorheight;
// Exists, but is too small for reasonable precipitation.
if (height < 64<<FRACBITS)
continue;
// Hack around a quirk of this entire system, where taller sectors look like they get less precipitation.
numparticles = 1 + (height / (MAPBLOCKUNITS<<4<<FRACBITS));
// Don't set z properly yet...
z = precipsector->sector->ceilingheight;
for (j = 0; j < numparticles; j++)
if (precipsector->sector->ffloors)
{
rainmo = P_SpawnPrecipMobj(x, y, z, type);
ffloor_t *rover;
if (randomstates > 0)
for (rover = precipsector->sector->ffloors; rover; rover = rover->next)
{
UINT8 mrand = M_RandomByte();
UINT8 threshold = UINT8_MAX / (randomstates + 1);
statenum_t st = mobjinfo[type].spawnstate;
if (!(rover->flags & FF_EXISTS))
continue;
for (k = 0; k < randomstates; k++)
if (!(rover->flags & FF_SWIMMABLE))
continue;
condition = true;
break;
}
}
}
else
{
condition = (precipsector->sector->ceilingpic == skyflatnum);
}
if (precipsector->sector->flags & SF_INVERTPRECIP)
{
condition = !condition;
}
if (!condition)
{
continue;
}
height = precipsector->sector->ceilingheight - precipsector->sector->floorheight;
// Exists, but is too small for reasonable precipitation.
if (height < 64<<FRACBITS)
continue;
// Hack around a quirk of this entire system, where taller sectors look like they get less precipitation.
numparticles = 1 + (height / (MAPBLOCKUNITS<<4<<FRACBITS));
// Don't set z properly yet...
z = (flip) ? (precipsector->sector->floorheight) : (precipsector->sector->ceilingheight);
for (j = 0; j < numparticles; j++)
{
rainmo = P_SpawnPrecipMobj(x, y, z, type);
if (randomstates > 0)
{
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)<<FRACBITS;
}
// Randomly assign a height, now that floorz is set.
rainmo->z = M_RandomRange(rainmo->floorz >> FRACBITS, rainmo->ceilingz >> FRACBITS) << FRACBITS;
}
}
}

View file

@ -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.
@ -462,6 +461,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 +474,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

View file

@ -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;

View file

@ -1769,10 +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;
INT32 oldEffects = precipprops[curWeather].effects;
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)
{
@ -1790,6 +1798,8 @@ void P_SwitchWeather(UINT8 newWeather)
}
}
curWeather = newWeather;
if (purge == true)
{
thinker_t *think;
@ -1844,14 +1854,22 @@ void P_SwitchWeather(UINT8 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;
}
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();
}

View file

@ -66,7 +66,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);

View file

@ -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; //<<detailshift;
@ -2318,12 +2332,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
// than lumpid for sprites-in-pwad : the graphics are patched
vis->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;