Merge branch 'master' of https://git.magicalgirl.moe/STJr/SRB2Internal.git into toast_cleanup

# Conflicts:
#	src/p_mobj.c
This commit is contained in:
toaster 2019-07-08 13:53:31 +01:00
commit 98b6280d03
36 changed files with 1385 additions and 1575 deletions

View File

@ -127,8 +127,6 @@ static CV_PossibleValue_t backpic_cons_t[] = {{0, "translucent"}, {1, "picture"}
// whether to use console background picture, or translucent mode
static consvar_t cons_backpic = {"con_backpic", "translucent", CV_SAVE, backpic_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
// \todo SRB2-CHAT 2.1 colors -- pending translation to 2.2 palette indexes
#if 0
static CV_PossibleValue_t backcolor_cons_t[] = {{0, "White"}, {1, "Black"}, {2, "Sepia"},
{3, "Brown"}, {4, "Pink"}, {5, "Raspberry"},
{6, "Red"}, {7, "Creamsicle"}, {8, "Orange"},
@ -137,13 +135,7 @@ static CV_PossibleValue_t backcolor_cons_t[] = {{0, "White"}, {1, "Black"}, {
{15,"Periwinkle"}, {16,"Blue"}, {17,"Purple"},
{18,"Lavender"},
{0, NULL}};
#else
static CV_PossibleValue_t backcolor_cons_t[] = {{0, "White"}, {1, "Gray"}, {2, "Brown"},
{3, "Red"}, {4, "Orange"}, {5, "Yellow"},
{6, "Green"}, {7, "Blue"}, {8, "Purple"},
{9, "Magenta"}, {10, "Aqua"},
{0, NULL}};
#endif
consvar_t cons_backcolor = {"con_backcolor", "Green", CV_CALL|CV_SAVE, backcolor_cons_t, CONS_backcolor_Change, 0, NULL, NULL, 0, 0, NULL};
@ -256,50 +248,30 @@ void CON_SetupBackColormapEx(INT32 color, boolean prompt)
shift = 6; // 12 colors -- shift of 7 means 6 colors
// \todo SRB2-CHAT colors, pending translation to 2.2 palette indexes
#if 0
switch (color)
{
case 0: palindex = 15; break; // White
case 1: palindex = 31; break; // Gray
case 2: palindex = 47; break; // Sepia
case 3: palindex = 63; break; // Brown
case 4: palindex = 150; shift = 7; break; // Pink
case 5: palindex = 127; shift = 7; break; // Raspberry
case 6: palindex = 143; break; // Red
case 7: palindex = 86; shift = 7; break; // Creamsicle
case 8: palindex = 95; break; // Orange
case 9: palindex = 119; shift = 7; break; // Gold
case 10: palindex = 111; break; // Yellow
case 11: palindex = 191; shift = 7; break; // Emerald
case 12: palindex = 175; break; // Green
case 13: palindex = 219; break; // Cyan
case 14: palindex = 207; shift = 7; break; // Steel
case 15: palindex = 230; shift = 7; break; // Periwinkle
case 16: palindex = 239; break; // Blue
case 17: palindex = 199; shift = 7; break; // Purple
case 18: palindex = 255; shift = 7; break; // Lavender
case 1: palindex = 31; break; // Black
case 2: palindex = 251; break; // Sepia
case 3: palindex = 239; break; // Brown
case 4: palindex = 215; shift = 7; break; // Pink
case 5: palindex = 37; shift = 7; break; // Raspberry
case 6: palindex = 47; shift = 7; break; // Red
case 7: palindex = 53; shift = 7; break; // Creamsicle
case 8: palindex = 63; break; // Orange
case 9: palindex = 56; shift = 7; break; // Gold
case 10: palindex = 79; shift = 7; break; // Yellow
case 11: palindex = 119; shift = 7; break; // Emerald
case 12: palindex = 111; break; // Green
case 13: palindex = 136; shift = 7; break; // Cyan
case 14: palindex = 175; shift = 7; break; // Steel
case 15: palindex = 166; shift = 7; break; // Periwinkle
case 16: palindex = 159; break; // Blue
case 17: palindex = 187; shift = 7; break; // Purple
case 18: palindex = 199; shift = 7; break; // Lavender
// Default green
default: palindex = 175; break;
default: palindex = 111; break;
}
#else
switch (color)
{
case 0: palindex = 15; break; // White
case 1: palindex = 31; break; // Gray
case 2: palindex = 239; break; // Brown
case 3: palindex = 47; break; // Red
case 4: palindex = 63; break; // Orange
case 5: palindex = 79; shift = 7; break; // Yellow
case 6: palindex = 111; break; // Green
case 7: palindex = 159; break; // Blue
case 8: palindex = 199; shift = 7; break; // Purple
case 9: palindex = 187; break; // Magenta
case 10: palindex = 139; break; // Aqua
// Default green
default: palindex = 175; color = 11; break;
}
#endif
if (prompt)
{

View File

@ -4270,16 +4270,13 @@ static INT16 Consistancy(void)
ret += P_GetRandSeed();
#ifdef MOBJCONSISTANCY
if (!thinkercap.next)
if (!thlist[THINK_MOBJ].next)
{
DEBFILE(va("Consistancy = %u\n", ret));
return ret;
}
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo = (mobj_t *)th;
if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_MONITOR | MF_FIRE | MF_ENEMY | MF_PAIN | MF_STICKY))

View File

@ -4260,9 +4260,8 @@ static void Command_Archivetest_f(void)
// assign mobjnum
i = 1;
for (th = thinkercap.next; th != &thinkercap; th = th->next)
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
((mobj_t *)th)->mobjnum = i++;
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
((mobj_t *)th)->mobjnum = i++;
// allocate buffer
buf = save_p = ZZ_Alloc(1024);

View File

@ -1793,15 +1793,23 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum)
if (i == 0 || fastcmp(word2, "WHITE")) backcolor = 0;
else if (i == 1 || fastcmp(word2, "GRAY") || fastcmp(word2, "GREY") ||
fastcmp(word2, "BLACK")) backcolor = 1;
else if (i == 2 || fastcmp(word2, "BROWN")) backcolor = 2;
else if (i == 3 || fastcmp(word2, "RED")) backcolor = 3;
else if (i == 4 || fastcmp(word2, "ORANGE")) backcolor = 4;
else if (i == 5 || fastcmp(word2, "YELLOW")) backcolor = 5;
else if (i == 6 || fastcmp(word2, "GREEN")) backcolor = 6;
else if (i == 7 || fastcmp(word2, "BLUE")) backcolor = 7;
else if (i == 8 || fastcmp(word2, "PURPLE")) backcolor = 8;
else if (i == 9 || fastcmp(word2, "MAGENTA")) backcolor = 9;
else if (i == 10 || fastcmp(word2, "AQUA")) backcolor = 10;
else if (i == 2 || fastcmp(word2, "SEPIA")) backcolor = 2;
else if (i == 3 || fastcmp(word2, "BROWN")) backcolor = 3;
else if (i == 4 || fastcmp(word2, "PINK")) backcolor = 4;
else if (i == 5 || fastcmp(word2, "RASPBERRY")) backcolor = 5;
else if (i == 6 || fastcmp(word2, "RED")) backcolor = 6;
else if (i == 7 || fastcmp(word2, "CREAMSICLE")) backcolor = 7;
else if (i == 8 || fastcmp(word2, "ORANGE")) backcolor = 8;
else if (i == 9 || fastcmp(word2, "GOLD")) backcolor = 9;
else if (i == 10 || fastcmp(word2, "YELLOW")) backcolor = 10;
else if (i == 11 || fastcmp(word2, "EMERALD")) backcolor = 11;
else if (i == 12 || fastcmp(word2, "GREEN")) backcolor = 12;
else if (i == 13 || fastcmp(word2, "CYAN") || fastcmp(word2, "AQUA")) backcolor = 13;
else if (i == 14 || fastcmp(word2, "STEEL")) backcolor = 14;
else if (i == 15 || fastcmp(word2, "PERIWINKLE")) backcolor = 15;
else if (i == 16 || fastcmp(word2, "BLUE")) backcolor = 16;
else if (i == 17 || fastcmp(word2, "PURPLE")) backcolor = 17;
else if (i == 18 || fastcmp(word2, "LAVENDER")) backcolor = 18;
else if (i < 0) backcolor = INT32_MAX; // CONS_BACKCOLOR user-configured
else backcolor = 1; // default gray
textprompts[num]->page[pagenum].backcolor = backcolor;
@ -8766,10 +8774,8 @@ struct {
#endif
#ifdef ESLOPE
// Slope flags
{"SL_NOPHYSICS",SL_NOPHYSICS}, // Don't do momentum adjustment with this slope
{"SL_NODYNAMIC",SL_NODYNAMIC}, // Slope will never need to move during the level, so don't fuss with recalculating it
{"SL_ANCHORVERTEX",SL_ANCHORVERTEX},// Slope is using a Slope Vertex Thing to anchor its position
{"SL_VERTEXSLOPE",SL_VERTEXSLOPE}, // Slope is built from three Slope Vertex Things
{"SL_NOPHYSICS",SL_NOPHYSICS},
{"SL_DYNAMIC",SL_DYNAMIC},
#endif
// Angles

View File

@ -146,6 +146,7 @@ extern UINT8 skincolor_redteam, skincolor_blueteam, skincolor_redring, skincolor
extern tic_t countdowntimer;
extern boolean countdowntimeup;
extern boolean exitfadestarted;
typedef struct
{

View File

@ -1421,7 +1421,7 @@ void F_InitMenuPresValues(void)
curbgcolor = -1;
curbgxspeed = titlescrollxspeed;
curbgyspeed = titlescrollyspeed;
curbghide = false;
curbghide = true;
// Find current presentation values
M_SetMenuCurBackground((gamestate == GS_TIMEATTACK) ? "SRB2BACK" : "TITLESKY");
@ -1692,11 +1692,8 @@ void F_TitleScreenTicker(boolean run)
// If there's a Line 422 Switch Cut-Away view, don't force us.
if (!titlemapcameraref || titlemapcameraref->type != MT_ALTVIEWMAN)
{
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
continue;
mo2 = (mobj_t *)th;
if (!mo2)

View File

@ -146,6 +146,7 @@ UINT8 skincolor_bluering = SKINCOLOR_CORNFLOWER;
tic_t countdowntimer = 0;
boolean countdowntimeup = false;
boolean exitfadestarted = false;
cutscene_t *cutscenes[128];
textprompt_t *textprompts[MAX_PROMPTS];
@ -2564,11 +2565,8 @@ void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo)
I_Assert((oldmo != NULL) && (newmo != NULL));
// scan all thinkers
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (!(mo2->flags & MF_MISSILE))
@ -3877,7 +3875,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
{
// Clear a bunch of variables
numgameovers = tokenlist = token = sstimer = redscore = bluescore = lastmap = 0;
countdown = countdown2 = 0;
countdown = countdown2 = exitfadestarted = 0;
for (i = 0; i < MAXPLAYERS; i++)
{
@ -4466,10 +4464,8 @@ void G_ConsGhostTic(void)
demo_p += sizeof(angle_t); // angle, unnecessary for cons.
mobj = NULL;
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mobj = (mobj_t *)th;
if (mobj->type == (mobjtype_t)type && mobj->x == x && mobj->y == y && mobj->z == z)
break;
@ -5862,11 +5858,8 @@ void G_DoPlayMetal(void)
metalbuffer = metal_p = W_CacheLumpNum(l, PU_STATIC);
// find metal sonic
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo = (mobj_t *)th;
if (mo->type != MT_METALSONIC_RACE)
continue;

View File

@ -1362,12 +1362,8 @@ static void HWR_SearchLightsInMobjs(void)
//mobj_t * mobj;
// search in the list of thinkers
for (th = thinkercap.next; th != &thinkercap; th = th->next)
{
// a mobj ?
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
HWR_AddMobjLights((mobj_t *)th);
}
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
HWR_AddMobjLights((mobj_t *)th);
}
#endif

View File

@ -19515,7 +19515,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
100, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_RUNSPAWNFUNC|MF_NOCLIPHEIGHT, // flags
MF_NOBLOCKMAP|MF_NOCLIPTHING|MF_RUNSPAWNFUNC|MF_NOCLIPHEIGHT|MF_SCENERY, // flags
S_NULL // raisestate
},

View File

@ -292,8 +292,6 @@ enum slope_e {
slope_normal,
slope_zangle,
slope_xydirection,
slope_sourceline,
slope_refpos,
slope_flags
};
@ -305,8 +303,6 @@ static const char *const slope_opt[] = {
"normal",
"zangle",
"xydirection",
"sourceline",
"refpos",
"flags",
NULL};
@ -1831,12 +1827,6 @@ static int slope_get(lua_State *L)
case slope_xydirection: // xydirection
lua_pushangle(L, slope->xydirection);
return 1;
case slope_sourceline: // source linedef
LUA_PushUserdata(L, slope->sourceline, META_LINE);
return 1;
case slope_refpos: // refpos
lua_pushinteger(L, slope->refpos);
return 1;
case slope_flags: // flags
lua_pushinteger(L, slope->flags);
return 1;
@ -1858,11 +1848,9 @@ static int slope_set(lua_State *L)
switch(field) // todo: reorganize this shit
{
case slope_valid: // valid
case slope_sourceline: // sourceline
case slope_d: // d
case slope_flags: // flags
case slope_normal: // normal
case slope_refpos: // refpos
default:
return luaL_error(L, "pslope_t field " LUA_QS " cannot be set.", slope_opt[field]);
case slope_o: { // o

View File

@ -420,9 +420,9 @@ void LUA_InvalidateLevel(void)
ffloor_t *rover = NULL;
if (!gL)
return;
for (th = thinkercap.next; th && th != &thinkercap; th = th->next)
LUA_InvalidateUserdata(th);
for (i = 0; i < NUM_THINKERLISTS; i++)
for (th = thlist[i].next; th && th != &thlist[i]; th = th->next)
LUA_InvalidateUserdata(th);
LUA_InvalidateMapthings();
@ -1127,13 +1127,15 @@ void LUA_Archive(void)
ArchiveExtVars(&players[i], "player");
}
for (th = thinkercap.next; th != &thinkercap; th = th->next)
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
{
// archive function will determine when to skip mobjs,
// and write mobjnum in otherwise.
ArchiveExtVars(th, "mobj");
}
for (i = 0; i < NUM_THINKERLISTS; i++)
for (th = thlist[i].next; th != &thlist[i]; th = th->next)
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
{
// archive function will determine when to skip mobjs,
// and write mobjnum in otherwise.
ArchiveExtVars(th, "mobj");
}
WRITEUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum.
LUAh_NetArchiveHook(NetArchive); // call the NetArchive hook in archive mode
@ -1161,9 +1163,10 @@ void LUA_UnArchive(void)
do {
mobjnum = READUINT32(save_p); // read a mobjnum
for (th = thinkercap.next; th != &thinkercap; th = th->next)
if (th->function.acp1 == (actionf_p1)P_MobjThinker
&& ((mobj_t *)th)->mobjnum == mobjnum) // find matching mobj
for (i = 0; i < NUM_THINKERLISTS; i++)
for (th = thlist[i].next; th != &thlist[i]; th = th->next)
if (th->function.acp1 == (actionf_p1)P_MobjThinker
&& ((mobj_t *)th)->mobjnum == mobjnum) // find matching mobj
UnArchiveExtVars(th); // apply variables
} while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker.

View File

@ -18,7 +18,7 @@
#define META_ITERATIONSTATE "iteration state"
static const char *const iter_opt[] = {
/*static const char *const iter_opt[] = {
"all",
"mobj",
NULL};
@ -26,7 +26,7 @@ static const char *const iter_opt[] = {
static const actionf_p1 iter_funcs[] = {
NULL,
(actionf_p1)P_MobjThinker
};
};*/
struct iterationState {
actionf_p1 filter;
@ -64,7 +64,7 @@ static int lib_iterateThinkers(lua_State *L)
lua_settop(L, 2);
if (lua_isnil(L, 2))
th = &thinkercap;
th = &thlist[THINK_MOBJ];
else if (lua_isuserdata(L, 2))
{
if (lua_islightuserdata(L, 2))
@ -94,11 +94,11 @@ static int lib_iterateThinkers(lua_State *L)
if (!next)
return luaL_error(L, "next thinker invalidated during iteration");
for (; next != &thinkercap; next = next->next)
for (; next != &thlist[THINK_MOBJ]; next = next->next)
if (!it->filter || next->function.acp1 == it->filter)
{
push_thinker(next);
if (next->next != &thinkercap)
if (next->next != &thlist[THINK_MOBJ])
{
push_thinker(next->next);
it->next = luaL_ref(L, LUA_REGISTRYINDEX);
@ -120,7 +120,7 @@ static int lib_startIterate(lua_State *L)
luaL_getmetatable(L, META_ITERATIONSTATE);
lua_setmetatable(L, -2);
it->filter = iter_funcs[luaL_checkoption(L, 1, "mobj", iter_opt)];
it->filter = (actionf_p1)P_MobjThinker; //iter_funcs[luaL_checkoption(L, 1, "mobj", iter_opt)];
it->next = LUA_REFNIL;
return 2;
}
@ -138,7 +138,7 @@ int LUA_ThinkerLib(lua_State *L)
lua_pushcfunction(L, lib_iterateThinkers);
lua_pushcclosure(L, lib_startIterate, 1);
lua_setfield(L, -2, "iterate");
lua_setglobal(L, "thinkers");
lua_setglobal(L, "mobjs");
return 0;
}

View File

@ -577,11 +577,8 @@ void Command_Teleport_f(void)
INT32 starpostmax = 0;
intz = starpostpath; // variable reuse - counting down for selection purposes
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type != MT_STARPOST)
@ -600,7 +597,7 @@ void Command_Teleport_f(void)
break;
}
if (th == &thinkercap)
if (th == &thlist[THINK_MOBJ])
{
if (intz == starpostpath)
CONS_Alert(CONS_NOTICE, M_GetText("No starpost of position %d found (%d max).\n"), starpostnum, starpostmax);
@ -1069,11 +1066,8 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c
thinker_t *th;
mobj_t *mo;
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo = (mobj_t *)th;
// get offset from mt, which points to old mapthings, then add new location
if (mo->spawnpoint)

View File

@ -2200,6 +2200,7 @@ void M_InitMenuPresTables(void)
menupres[i].bgcolor = -1;
menupres[i].titlescrollxspeed = INT32_MAX;
menupres[i].titlescrollyspeed = INT32_MAX;
menupres[i].bghide = true;
// default true
menupres[i].enterbubble = true;
menupres[i].exitbubble = true;
@ -2468,7 +2469,7 @@ static void M_HandleMenuPresState(menu_t *newMenu)
curbgcolor = -1;
curbgxspeed = titlescrollxspeed;
curbgyspeed = titlescrollyspeed;
curbghide = false;
curbghide = true;
// don't do the below during the in-game menus
if (gamestate != GS_TITLESCREEN && gamestate != GS_TIMEATTACK)

View File

@ -409,7 +409,7 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type)
// new door thinker
rtn = 1;
ceiling = Z_Calloc(sizeof (*ceiling), PU_LEVSPEC, NULL);
P_AddThinker(&ceiling->thinker);
P_AddThinker(THINK_MAIN, &ceiling->thinker);
sec->ceilingdata = ceiling;
ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling;
ceiling->sector = sec;
@ -629,7 +629,7 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type)
// new door thinker
rtn = 1;
ceiling = Z_Calloc(sizeof (*ceiling), PU_LEVSPEC, NULL);
P_AddThinker(&ceiling->thinker);
P_AddThinker(THINK_MAIN, &ceiling->thinker);
sec->ceilingdata = ceiling;
ceiling->thinker.function.acp1 = (actionf_p1)T_CrushCeiling;
ceiling->sector = sec;

View File

@ -3766,11 +3766,8 @@ void A_BossDeath(mobj_t *mo)
// scan the remaining thinkers to see
// if all bosses are dead
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2 != mo && (mo2->flags & MF_BOSS) && mo2->health > 0)
goto bossjustdie; // other boss not dead - just go straight to dying!
@ -3867,11 +3864,8 @@ bossjustdie:
// Flee! Flee! Find a point to escape to! If none, just shoot upward!
// scan the thinkers to find the runaway point
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type != MT_BOSSFLYPOINT)
@ -6123,11 +6117,8 @@ void A_RingExplode(mobj_t *actor)
S_StartSound(actor, sfx_prloop);
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2 == actor) // Don't explode yourself! Endless loop!
@ -7819,11 +7810,8 @@ void A_Boss3Path(mobj_t *actor)
// scan the thinkers
// to find a point that matches
// the number
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && mo2->spawnpoint->angle == actor->threshold)
{
@ -8212,11 +8200,8 @@ void A_FindTarget(mobj_t *actor)
CONS_Debug(DBG_GAMELOGIC, "A_FindTarget called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2);
// scan the thinkers
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == (mobjtype_t)locvar1)
@ -8277,11 +8262,8 @@ void A_FindTracer(mobj_t *actor)
CONS_Debug(DBG_GAMELOGIC, "A_FindTracer called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2);
// scan the thinkers
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == (mobjtype_t)locvar1)
@ -8840,11 +8822,8 @@ void A_RemoteAction(mobj_t *actor)
fixed_t dist1 = 0, dist2 = 0;
// scan the thinkers
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == (mobjtype_t)locvar1)
@ -9106,11 +9085,8 @@ void A_SetObjectTypeState(mobj_t *actor)
return;
#endif
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == (mobjtype_t)loc2lw)
@ -9744,11 +9720,8 @@ void A_CheckThingCount(mobj_t *actor)
return;
#endif
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == (mobjtype_t)loc1up)
@ -13023,7 +12996,14 @@ static boolean PIT_TNTExplode(mobj_t *nearby)
nearby->momx = FixedMul(FixedDiv(dx, dm), explodethrust);
nearby->momy = FixedMul(FixedDiv(dy, dm), explodethrust);
nearby->momz = FixedMul(FixedDiv(dz, dm), explodethrust);
P_UnsetThingPosition(nearby);
if (sector_list)
{
P_DelSeclist(sector_list);
sector_list = NULL;
}
nearby->flags = MF_NOBLOCKMAP|MF_MISSILE;
P_SetThingPosition(nearby);
P_SetMobjState(nearby, nearby->info->missilestate);
}
}
@ -13067,8 +13047,14 @@ void A_TNTExplode(mobj_t *actor)
if (LUA_CallAction("A_TNTExplode", actor))
return;
#endif
P_UnsetThingPosition(actor);
if (sector_list)
{
P_DelSeclist(sector_list);
sector_list = NULL;
}
actor->flags = MF_NOCLIP|MF_NOGRAVITY|MF_NOBLOCKMAP;
P_SetThingPosition(actor);
actor->flags2 = MF2_EXPLOSION;
if (actor->info->deathsound)
S_StartSound(actor, actor->info->deathsound);

View File

@ -1981,11 +1981,8 @@ void T_ThwompSector(levelspecthink_t *thwomp)
if (!rover || (rover->flags & FF_EXISTS))
{
// scan the thinkers to find players!
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo = (mobj_t *)th;
if (mo->type == MT_PLAYER && mo->health && mo->player && !mo->player->spectator
&& mo->z <= thwomp->sector->ceilingheight
@ -2701,7 +2698,7 @@ INT32 EV_DoFloor(line_t *line, floor_e floortype)
// new floor thinker
rtn = 1;
dofloor = Z_Calloc(sizeof (*dofloor), PU_LEVSPEC, NULL);
P_AddThinker(&dofloor->thinker);
P_AddThinker(THINK_MAIN, &dofloor->thinker);
// make sure another floor thinker won't get started over this one
sec->floordata = dofloor;
@ -2922,7 +2919,7 @@ INT32 EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed)
// create and initialize new elevator thinker
rtn = 1;
elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL);
P_AddThinker(&elevator->thinker);
P_AddThinker(THINK_MAIN, &elevator->thinker);
sec->floordata = elevator;
sec->ceilingdata = elevator;
elevator->thinker.function.acp1 = (actionf_p1)T_MoveElevator;
@ -3149,7 +3146,7 @@ INT32 EV_BounceSector(sector_t *sec, fixed_t momz, line_t *sourceline)
return 0;
bouncer = Z_Calloc(sizeof (*bouncer), PU_LEVSPEC, NULL);
P_AddThinker(&bouncer->thinker);
P_AddThinker(THINK_MAIN, &bouncer->thinker);
sec->ceilingdata = bouncer;
bouncer->thinker.function.acp1 = (actionf_p1)T_BounceCheese;
@ -3183,7 +3180,7 @@ INT32 EV_DoContinuousFall(sector_t *sec, sector_t *backsector, fixed_t spd, bool
// create and initialize new thinker
faller = Z_Calloc(sizeof (*faller), PU_LEVSPEC, NULL);
P_AddThinker(&faller->thinker);
P_AddThinker(THINK_MAIN, &faller->thinker);
faller->thinker.function.acp1 = (actionf_p1)T_ContinuousFalling;
// set up the fields
@ -3232,7 +3229,7 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating,
// create and initialize new elevator thinker
elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL);
P_AddThinker(&elevator->thinker);
P_AddThinker(THINK_MAIN, &elevator->thinker);
elevator->thinker.function.acp1 = (actionf_p1)T_StartCrumble;
// Does this crumbler return?
@ -3311,7 +3308,7 @@ INT32 EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher)
// create and initialize new elevator thinker
block = Z_Calloc(sizeof (*block), PU_LEVSPEC, NULL);
P_AddThinker(&block->thinker);
P_AddThinker(THINK_MAIN, &block->thinker);
roversec->floordata = block;
roversec->ceilingdata = block;
block->thinker.function.acp1 = (actionf_p1)T_MarioBlock;

View File

@ -97,11 +97,8 @@ void P_ClearStarPost(INT32 postnum)
mobj_t *mo2;
// scan the thinkers
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type != MT_STARPOST)
@ -126,11 +123,8 @@ void P_ResetStarposts(void)
thinker_t *th;
mobj_t *post;
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
post = (mobj_t *)th;
if (post->type == MT_STARPOST)
@ -833,11 +827,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// The player might have two Ideyas: toucher->tracer and toucher->tracer->hnext
// so handle their anchorpoints accordingly.
// scan the thinkers to find the corresponding anchorpoint
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_IDEYAANCHOR)
@ -927,11 +918,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
count = 1;
// scan the remaining thinkers
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2 == special)
@ -977,11 +965,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
// Now we RE-scan all the thinkers to find close objects to pull
// in from the paraloop. Isn't this just so efficient?
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (P_AproxDistance(P_AproxDistance(mo2->x - x, mo2->y - y), mo2->z - z) > gatherradius)
@ -1351,11 +1336,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
EV_DoElevator(&junk, bridgeFall, false);
// scan the remaining thinkers to find koopa
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type != MT_KOOPA)
@ -1451,11 +1433,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
thinker_t *th;
mobj_t *mo2;
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type != MT_STARPOST)
@ -1690,6 +1669,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
case MT_CANARIVORE_GAS:
// if player and gas touch, attach gas to player (overriding any gas that already attached) and apply slowdown effect
special->flags |= MF_NOGRAVITY|MF_NOCLIPHEIGHT;
P_UnsetThingPosition(special);
special->x = toucher->x - toucher->momx/2;
special->y = toucher->y - toucher->momy/2;
@ -2555,11 +2535,8 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
// scan the thinkers to make sure all the old pinch dummies are gone on death
// this can happen if the boss was hurt earlier than expected
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo = (mobj_t *)th;
if (mo->type == (mobjtype_t)target->info->mass && mo->tracer == target)
{

View File

@ -76,7 +76,7 @@ fireflicker_t *P_SpawnAdjustableFireFlicker(sector_t *minsector, sector_t *maxse
P_RemoveLighting(maxsector); // out with the old, in with the new
flick = Z_Calloc(sizeof (*flick), PU_LEVSPEC, NULL);
P_AddThinker(&flick->thinker);
P_AddThinker(THINK_MAIN, &flick->thinker);
flick->thinker.function.acp1 = (actionf_p1)T_FireFlicker;
flick->sector = maxsector;
@ -155,7 +155,7 @@ void P_SpawnLightningFlash(sector_t *sector)
flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL);
P_AddThinker(&flash->thinker);
P_AddThinker(THINK_MAIN, &flash->thinker);
flash->thinker.function.acp1 = (actionf_p1)T_LightningFlash;
flash->sector = sector;
@ -214,7 +214,7 @@ strobe_t *P_SpawnAdjustableStrobeFlash(sector_t *minsector, sector_t *maxsector,
P_RemoveLighting(maxsector); // out with the old, in with the new
flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL);
P_AddThinker(&flash->thinker);
P_AddThinker(THINK_MAIN, &flash->thinker);
flash->sector = maxsector;
flash->darktime = darktime;
@ -289,7 +289,7 @@ glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector,
P_RemoveLighting(maxsector); // out with the old, in with the new
g = Z_Calloc(sizeof (*g), PU_LEVSPEC, NULL);
P_AddThinker(&g->thinker);
P_AddThinker(THINK_MAIN, &g->thinker);
g->sector = maxsector;
g->minlight = minsector->lightlevel;
@ -349,7 +349,7 @@ void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean
ll->thinker.function.acp1 = (actionf_p1)T_LightFade;
sector->lightingdata = ll; // set it to the lightlevel_t
P_AddThinker(&ll->thinker); // add thinker
P_AddThinker(THINK_MAIN, &ll->thinker); // add thinker
ll->sector = sector;
ll->sourcelevel = sector->lightlevel;

View File

@ -61,15 +61,21 @@
#define P_GetPlayerHeight(player) FixedMul(player->height, player->mo->scale)
#define P_GetPlayerSpinHeight(player) FixedMul(player->spinheight, player->mo->scale)
//
// P_TICK
//
// both the head and tail of the thinker list
extern thinker_t thinkercap;
typedef enum{
THINK_LIMBO,
THINK_POLYOBJ,
THINK_MAIN,
THINK_MOBJ,
#ifdef ESLOPE
THINK_DYNSLOPE,
#endif
THINK_PRECIP,
NUM_THINKERLISTS
} thinklistnum_t; /**< Thinker lists. */
extern thinker_t thlist[];
void P_InitThinkers(void);
void P_AddThinker(thinker_t *thinker);
void P_AddThinker(const thinklistnum_t n, thinker_t *thinker);
void P_RemoveThinker(thinker_t *thinker);
//

View File

@ -4012,7 +4012,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush)
thinker_t *think;
elevator_t *crumbler;
for (think = thinkercap.next; think != &thinkercap; think = think->next)
for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next)
{
if (think->function.acp1 != (actionf_p1)T_StartCrumble)
continue;

View File

@ -714,11 +714,8 @@ void P_EmeraldManager(void)
spawnpoints[i] = NULL;
}
for (think = thinkercap.next; think != &thinkercap; think = think->next)
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{
if (think->function.acp1 != (actionf_p1)P_MobjThinker)
continue; // not a mobj thinker
mo = (mobj_t *)think;
if (mo->type == MT_EMERALDSPAWN)
@ -3695,11 +3692,8 @@ void P_DestroyRobots(void)
mobj_t *mo;
thinker_t *think;
for (think = thinkercap.next; think != &thinkercap; think = think->next)
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{
if (think->function.acp1 != (actionf_p1)P_MobjThinker)
continue; // not a mobj thinker
mo = (mobj_t *)think;
if (mo->health <= 0 || !(mo->flags & (MF_ENEMY|MF_BOSS)))
continue; // not a valid enemy
@ -4480,11 +4474,8 @@ static void P_Boss3Thinker(mobj_t *mobj)
// scan the thinkers to make sure all the old pinch dummies are gone before making new ones
// this can happen if the boss was hurt earlier than expected
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == (mobjtype_t)mobj->info->mass && mo2->tracer == mobj)
{
@ -4571,11 +4562,8 @@ static void P_Boss3Thinker(mobj_t *mobj)
// scan the thinkers
// to find a point that matches
// the number
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && mo2->spawnpoint->angle == mobj->threshold)
{
@ -5233,11 +5221,8 @@ static void P_Boss7Thinker(mobj_t *mobj)
closestdist = INT32_MAX; // Just in case...
// Find waypoint he is closest to
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint)
{
@ -5288,11 +5273,8 @@ static void P_Boss7Thinker(mobj_t *mobj)
// scan the thinkers to find
// the waypoint to use
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && (mo2->spawnpoint->options & 7) == waypointNum)
{
@ -5420,11 +5402,8 @@ static void P_Boss9Thinker(mobj_t *mobj)
// Run through the thinkers ONCE and find all of the MT_BOSS9GATHERPOINT in the map.
// Build a hoop linked list of 'em!
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_BOSS9GATHERPOINT)
{
@ -5882,11 +5861,8 @@ mobj_t *P_GetClosestAxis(mobj_t *source)
fixed_t dist1, dist2 = 0;
// scan the thinkers to find the closest axis point
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_AXIS)
@ -6583,7 +6559,7 @@ void P_RunOverlays(void)
{
angle_t viewingangle;
if (players[displayplayer].awayviewtics)
if (players[displayplayer].awayviewtics && players[displayplayer].awayviewmobj != NULL && !P_MobjWasRemoved(players[displayplayer].awayviewmobj))
viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayer].awayviewmobj->x, players[displayplayer].awayviewmobj->y);
else if (!camera.chase && players[displayplayer].mo)
viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, players[displayplayer].mo->x, players[displayplayer].mo->y);
@ -7327,6 +7303,7 @@ void P_MobjThinker(mobj_t *mobj)
case MT_ROCKCRUMBLE14:
case MT_ROCKCRUMBLE15:
case MT_ROCKCRUMBLE16:
case MT_WOODDEBRIS:
if (mobj->z <= P_FloorzAtPos(mobj->x, mobj->y, mobj->z, mobj->height)
&& mobj->state != &states[mobj->info->deathstate])
{
@ -8522,7 +8499,6 @@ void P_MobjThinker(mobj_t *mobj)
momz = abs(mobj->momz);
if (R_PointToDist2(0, 0, mobj->momx, mobj->momy) < momz)
P_InstaThrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), momz);
mobj->flags |= MF_NOGRAVITY|MF_NOCLIPHEIGHT;
mobj->flags2 |= MF2_AMBUSH;
break;
}
@ -9382,7 +9358,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
}
if (!(mobj->flags & MF_NOTHINK))
P_AddThinker(&mobj->thinker);
P_AddThinker(THINK_MOBJ, &mobj->thinker);
// Call action functions when the state is set
if (st->action.acp1 && (mobj->flags & MF_RUNSPAWNFUNC))
@ -9457,7 +9433,7 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
mobj->momz = mobjinfo[type].speed;
mobj->thinker.function.acp1 = (actionf_p1)P_NullPrecipThinker;
P_AddThinker(&mobj->thinker);
P_AddThinker(THINK_PRECIP, &mobj->thinker);
CalculatePrecipFloor(mobj);
@ -9581,7 +9557,7 @@ void P_RemoveMobj(mobj_t *mobj)
else
{ // Add thinker just to delay removing it until refrences are gone.
mobj->flags &= ~MF_NOTHINK;
P_AddThinker((thinker_t *)mobj);
P_AddThinker(THINK_MOBJ, (thinker_t *)mobj);
#ifdef SCRAMBLE_REMOVED
// Invalidate mobj_t data to cause crashes if accessed!
memset((UINT8 *)mobj + sizeof(thinker_t), 0xff, sizeof(mobj_t) - sizeof(thinker_t));
@ -9651,7 +9627,7 @@ consvar_t cv_flagtime = {"flagtime", "30", CV_NETVAR|CV_CHEAT, flagtime_cons_t,
void P_SpawnPrecipitation(void)
{
INT32 i, /*j,*/ mrand;
INT32 i /*, j*/, mrand;
fixed_t basex, basey, x, y, height;
subsector_t *precipsector = NULL;
precipmobj_t *rainmo = NULL;
@ -11425,11 +11401,8 @@ ML_EFFECT5 : Don't stop thinking when too far away
mobj->health = (mthing->angle / 360) + 1;
// See if other starposts exist in this level that have the same value.
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2 == mobj)

View File

@ -146,16 +146,6 @@ FUNCINLINE static ATTRINLINE void Polyobj_vecSub2(vertex_t *dst, vertex_t *v1, v
dst->y = v1->y - v2->y;
}
// Add the polyobject's thinker to the thinker list
// Unlike P_AddThinker, this adds it to the front of the list instead of the back, so that carrying physics can work right. -Red
FUNCINLINE static ATTRINLINE void PolyObj_AddThinker(thinker_t *th)
{
thinkercap.next->prev = th;
th->next = thinkercap.next;
th->prev = &thinkercap;
thinkercap.next = th;
}
//
// P_PointInsidePolyobj
//
@ -1518,31 +1508,28 @@ void Polyobj_InitLevel(void)
// run down the thinker list, count the number of spawn points, and save
// the mobj_t pointers on a queue for use below.
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
mobj_t *mo = (mobj_t *)th;
if (mo->info->doomednum == POLYOBJ_SPAWN_DOOMEDNUM ||
mo->info->doomednum == POLYOBJ_SPAWNCRUSH_DOOMEDNUM)
{
mobj_t *mo = (mobj_t *)th;
++numPolyObjects;
if (mo->info->doomednum == POLYOBJ_SPAWN_DOOMEDNUM ||
mo->info->doomednum == POLYOBJ_SPAWNCRUSH_DOOMEDNUM)
{
++numPolyObjects;
qitem = malloc(sizeof(mobjqitem_t));
memset(qitem, 0, sizeof(mobjqitem_t));
qitem->mo = mo;
M_QueueInsert(&(qitem->mqitem), &spawnqueue);
}
else if (mo->info->doomednum == POLYOBJ_ANCHOR_DOOMEDNUM)
{
++numAnchors;
qitem = malloc(sizeof(mobjqitem_t));
memset(qitem, 0, sizeof(mobjqitem_t));
qitem->mo = mo;
M_QueueInsert(&(qitem->mqitem), &spawnqueue);
}
else if (mo->info->doomednum == POLYOBJ_ANCHOR_DOOMEDNUM)
{
++numAnchors;
qitem = malloc(sizeof(mobjqitem_t));
memset(qitem, 0, sizeof(mobjqitem_t));
qitem->mo = mo;
M_QueueInsert(&(qitem->mqitem), &anchorqueue);
}
qitem = malloc(sizeof(mobjqitem_t));
memset(qitem, 0, sizeof(mobjqitem_t));
qitem->mo = mo;
M_QueueInsert(&(qitem->mqitem), &anchorqueue);
}
}
@ -1657,7 +1644,7 @@ void T_PolyObjRotate(polyrotate_t *th)
#else
{
CONS_Debug(DBG_POLYOBJ, "T_PolyObjRotate: thinker with invalid id %d removed.\n", th->polyObjNum);
P_RemoveThinkerDelayed(&th->thinker);
P_RemoveThinker(&th->thinker);
return;
}
#endif
@ -1742,7 +1729,7 @@ void T_PolyObjMove(polymove_t *th)
#else
{
CONS_Debug(DBG_POLYOBJ, "T_PolyObjMove: thinker with invalid id %d removed.\n", th->polyObjNum);
P_RemoveThinkerDelayed(&th->thinker);
P_RemoveThinker(&th->thinker);
return;
}
#endif
@ -1815,7 +1802,7 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
#else
{
CONS_Debug(DBG_POLYOBJ, "T_PolyObjWaypoint: thinker with invalid id %d removed.", th->polyObjNum);
P_RemoveThinkerDelayed(&th->thinker);
P_RemoveThinker(&th->thinker);
return;
}
#endif
@ -1826,11 +1813,8 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
// Find out target first.
// We redo this each tic to make savegame compatibility easier.
for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next)
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
{
if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
continue;
mo2 = (mobj_t *)wp;
if (mo2->type != MT_TUBEWAYPOINT)
@ -1907,11 +1891,8 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
CONS_Debug(DBG_POLYOBJ, "Looking for next waypoint...\n");
// Find next waypoint
for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next)
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
{
if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
continue;
mo2 = (mobj_t *)wp;
if (mo2->type != MT_TUBEWAYPOINT)
@ -1946,11 +1927,8 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
th->stophere = true;
}
for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next)
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
{
if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
continue;
mo2 = (mobj_t *)wp;
if (mo2->type != MT_TUBEWAYPOINT)
@ -1983,11 +1961,8 @@ void T_PolyObjWaypoint(polywaypoint_t *th)
if (!th->continuous)
th->comeback = false;
for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next)
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
{
if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
continue;
mo2 = (mobj_t *)wp;
if (mo2->type != MT_TUBEWAYPOINT)
@ -2089,7 +2064,7 @@ void T_PolyDoorSlide(polyslidedoor_t *th)
#else
{
CONS_Debug(DBG_POLYOBJ, "T_PolyDoorSlide: thinker with invalid id %d removed.\n", th->polyObjNum);
P_RemoveThinkerDelayed(&th->thinker);
P_RemoveThinker(&th->thinker);
return;
}
#endif
@ -2194,7 +2169,7 @@ void T_PolyDoorSwing(polyswingdoor_t *th)
#else
{
CONS_Debug(DBG_POLYOBJ, "T_PolyDoorSwing: thinker with invalid id %d removed.\n", th->polyObjNum);
P_RemoveThinkerDelayed(&th->thinker);
P_RemoveThinker(&th->thinker);
return;
}
#endif
@ -2293,7 +2268,7 @@ void T_PolyObjDisplace(polydisplace_t *th)
#else
{
CONS_Debug(DBG_POLYOBJ, "T_PolyObjDisplace: thinker with invalid id %d removed.\n", th->polyObjNum);
P_RemoveThinkerDelayed(&th->thinker);
P_RemoveThinker(&th->thinker);
return;
}
#endif
@ -2333,7 +2308,7 @@ void T_PolyObjRotDisplace(polyrotdisplace_t *th)
#else
{
CONS_Debug(DBG_POLYOBJ, "T_PolyObjRotDisplace: thinker with invalid id %d removed.\n", th->polyObjNum);
P_RemoveThinkerDelayed(&th->thinker);
P_RemoveThinker(&th->thinker);
return;
}
#endif
@ -2390,7 +2365,7 @@ INT32 EV_DoPolyObjRotate(polyrotdata_t *prdata)
// create a new thinker
th = Z_Malloc(sizeof(polyrotate_t), PU_LEVSPEC, NULL);
th->thinker.function.acp1 = (actionf_p1)T_PolyObjRotate;
PolyObj_AddThinker(&th->thinker);
P_AddThinker(THINK_POLYOBJ, &th->thinker);
po->thinker = &th->thinker;
// set fields
@ -2455,7 +2430,7 @@ INT32 EV_DoPolyObjMove(polymovedata_t *pmdata)
// create a new thinker
th = Z_Malloc(sizeof(polymove_t), PU_LEVSPEC, NULL);
th->thinker.function.acp1 = (actionf_p1)T_PolyObjMove;
PolyObj_AddThinker(&th->thinker);
P_AddThinker(THINK_POLYOBJ, &th->thinker);
po->thinker = &th->thinker;
// set fields
@ -2516,7 +2491,7 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
// create a new thinker
th = Z_Malloc(sizeof(polywaypoint_t), PU_LEVSPEC, NULL);
th->thinker.function.acp1 = (actionf_p1)T_PolyObjWaypoint;
PolyObj_AddThinker(&th->thinker);
P_AddThinker(THINK_POLYOBJ, &th->thinker);
po->thinker = &th->thinker;
// set fields
@ -2534,11 +2509,8 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
th->stophere = false;
// Find the first waypoint we need to use
for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next)
for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
{
if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
continue;
mo2 = (mobj_t *)wp;
if (mo2->type != MT_TUBEWAYPOINT)
@ -2605,11 +2577,8 @@ INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata)
// Find the actual target movement waypoint
target = first;
/*for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next)
/*for (wp = thlist[THINK_MOBJ].next; wp != &thlist[THINK_MOBJ]; wp = wp->next)
{
if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
continue;
mo2 = (mobj_t *)wp;
if (mo2->type != MT_TUBEWAYPOINT)
@ -2662,7 +2631,7 @@ static void Polyobj_doSlideDoor(polyobj_t *po, polydoordata_t *doordata)
// allocate and add a new slide door thinker
th = Z_Malloc(sizeof(polyslidedoor_t), PU_LEVSPEC, NULL);
th->thinker.function.acp1 = (actionf_p1)T_PolyDoorSlide;
PolyObj_AddThinker(&th->thinker);
P_AddThinker(THINK_POLYOBJ, &th->thinker);
// point the polyobject to this thinker
po->thinker = &th->thinker;
@ -2710,7 +2679,7 @@ static void Polyobj_doSwingDoor(polyobj_t *po, polydoordata_t *doordata)
// allocate and add a new swing door thinker
th = Z_Malloc(sizeof(polyswingdoor_t), PU_LEVSPEC, NULL);
th->thinker.function.acp1 = (actionf_p1)T_PolyDoorSwing;
PolyObj_AddThinker(&th->thinker);
P_AddThinker(THINK_POLYOBJ, &th->thinker);
// point the polyobject to this thinker
po->thinker = &th->thinker;
@ -2792,7 +2761,7 @@ INT32 EV_DoPolyObjDisplace(polydisplacedata_t *prdata)
// create a new thinker
th = Z_Malloc(sizeof(polydisplace_t), PU_LEVSPEC, NULL);
th->thinker.function.acp1 = (actionf_p1)T_PolyObjDisplace;
PolyObj_AddThinker(&th->thinker);
P_AddThinker(THINK_POLYOBJ, &th->thinker);
po->thinker = &th->thinker;
// set fields
@ -2838,7 +2807,7 @@ INT32 EV_DoPolyObjRotDisplace(polyrotdisplacedata_t *prdata)
// create a new thinker
th = Z_Malloc(sizeof(polyrotdisplace_t), PU_LEVSPEC, NULL);
th->thinker.function.acp1 = (actionf_p1)T_PolyObjRotDisplace;
PolyObj_AddThinker(&th->thinker);
P_AddThinker(THINK_POLYOBJ, &th->thinker);
po->thinker = &th->thinker;
// set fields
@ -2875,7 +2844,7 @@ void T_PolyObjFlag(polymove_t *th)
#else
{
CONS_Debug(DBG_POLYOBJ, "T_PolyObjFlag: thinker with invalid id %d removed.\n", th->polyObjNum);
P_RemoveThinkerDelayed(&th->thinker);
P_RemoveThinker(&th->thinker);
return;
}
#endif
@ -2939,7 +2908,7 @@ INT32 EV_DoPolyObjFlag(line_t *pfdata)
// create a new thinker
th = Z_Malloc(sizeof(polymove_t), PU_LEVSPEC, NULL);
th->thinker.function.acp1 = (actionf_p1)T_PolyObjFlag;
PolyObj_AddThinker(&th->thinker);
P_AddThinker(THINK_POLYOBJ, &th->thinker);
po->thinker = &th->thinker;
// set fields
@ -2978,7 +2947,7 @@ void T_PolyObjFade(polyfade_t *th)
#else
{
CONS_Debug(DBG_POLYOBJ, "T_PolyObjFade: thinker with invalid id %d removed.\n", th->polyObjNum);
P_RemoveThinkerDelayed(&th->thinker);
P_RemoveThinker(&th->thinker);
return;
}
#endif
@ -3089,7 +3058,7 @@ INT32 EV_DoPolyObjFade(polyfadedata_t *pfdata)
// create a new thinker
th = Z_Malloc(sizeof(polyfade_t), PU_LEVSPEC, NULL);
th->thinker.function.acp1 = (actionf_p1)T_PolyObjFade;
PolyObj_AddThinker(&th->thinker);
P_AddThinker(THINK_POLYOBJ, &th->thinker);
po->thinker = &th->thinker;
// set fields

File diff suppressed because it is too large Load Diff

View File

@ -815,11 +815,8 @@ void P_ReloadRings(void)
mapthing_t *mt = mapthings;
// scan the thinkers to find rings/spheres/hoops to unset
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo = (mobj_t *)th;
if (mo->type == MT_HOOPCENTER)
@ -884,11 +881,8 @@ void P_SwitchSpheresBonusMode(boolean bonustime)
#endif
// scan the thinkers to find spheres to switch
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo = (mobj_t *)th;
if (mo->type != MT_BLUESPHERE && mo->type != MT_NIGHTSCHIP
@ -2228,7 +2222,7 @@ static void P_LevelInitStuff(void)
}
}
countdown = countdown2 = 0;
countdown = countdown2 = exitfadestarted = 0;
for (i = 0; i < MAXPLAYERS; i++)
{
@ -2299,11 +2293,8 @@ void P_LoadThingsOnly(void)
}
for (think = thinkercap.next; think != &thinkercap; think = think->next)
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{
if (think->function.acp1 != (actionf_p1)P_MobjThinker)
continue; // not a mobj thinker
mo = (mobj_t *)think;
if (mo)
@ -2921,7 +2912,7 @@ boolean P_SetupLevel(boolean skipprecip)
P_InitSpecials();
#ifdef ESLOPE
P_ResetDynamicSlopes();
P_ResetDynamicSlopes(fromnetsave);
#endif
P_LoadThings(loademblems);

View File

@ -25,68 +25,66 @@
#ifdef ESLOPE
static pslope_t *slopelist = NULL;
static UINT16 slopecount = 0;
pslope_t *slopelist = NULL;
UINT16 slopecount = 0;
// Calculate line normal
void P_CalculateSlopeNormal(pslope_t *slope) {
slope->normal.z = FINECOSINE(slope->zangle>>ANGLETOFINESHIFT);
slope->normal.x = -FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.x);
slope->normal.y = -FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.y);
slope->normal.x = FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.x);
slope->normal.y = FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.y);
}
// With a vertex slope that has its vertices set, configure relevant slope info
static void P_ReconfigureVertexSlope(pslope_t *slope)
/// Setup slope via 3 vertexes.
static void ReconfigureViaVertexes (pslope_t *slope, const vector3_t v1, const vector3_t v2, const vector3_t v3)
{
vector3_t vec1, vec2;
// Set slope normal
vec1.x = (slope->vertices[1]->x - slope->vertices[0]->x) << FRACBITS;
vec1.y = (slope->vertices[1]->y - slope->vertices[0]->y) << FRACBITS;
vec1.z = (slope->vertices[1]->z - slope->vertices[0]->z) << FRACBITS;
// Set origin.
FV3_Copy(&slope->o, &v1);
vec2.x = (slope->vertices[2]->x - slope->vertices[0]->x) << FRACBITS;
vec2.y = (slope->vertices[2]->y - slope->vertices[0]->y) << FRACBITS;
vec2.z = (slope->vertices[2]->z - slope->vertices[0]->z) << FRACBITS;
// Get slope's normal.
FV3_SubEx(&v2, &v1, &vec1);
FV3_SubEx(&v3, &v1, &vec2);
// ugggggggh fixed-point maaaaaaath
slope->extent = max(
max(max(abs(vec1.x), abs(vec1.y)), abs(vec1.z)),
max(max(abs(vec2.x), abs(vec2.y)), abs(vec2.z))
) >> (FRACBITS+5);
vec1.x /= slope->extent;
vec1.y /= slope->extent;
vec1.z /= slope->extent;
vec2.x /= slope->extent;
vec2.y /= slope->extent;
vec2.z /= slope->extent;
// Set some defaults for a non-sloped "slope"
if (vec1.z == 0 && vec2.z == 0)
{
/// \todo Fix fully flat cases.
FV3_Cross(&vec1, &vec2, &slope->normal);
slope->extent = R_PointToDist2(0, 0, R_PointToDist2(0, 0, slope->normal.x, slope->normal.y), slope->normal.z);
if (slope->normal.z < 0)
slope->extent = -slope->extent;
slope->normal.x = FixedDiv(slope->normal.x, slope->extent);
slope->normal.y = FixedDiv(slope->normal.y, slope->extent);
slope->normal.z = FixedDiv(slope->normal.z, slope->extent);
// Set origin
slope->o.x = slope->vertices[0]->x << FRACBITS;
slope->o.y = slope->vertices[0]->y << FRACBITS;
slope->o.z = slope->vertices[0]->z << FRACBITS;
if (slope->normal.x == 0 && slope->normal.y == 0) { // Set some defaults for a non-sloped "slope"
slope->zangle = slope->xydirection = 0;
slope->zdelta = slope->d.x = slope->d.y = 0;
} else {
}
else
{
/// \note Using fixed point for vectorial products easily leads to overflows so we work around by downscaling them.
fixed_t m = max(
max(max(abs(vec1.x), abs(vec1.y)), abs(vec1.z)),
max(max(abs(vec2.x), abs(vec2.y)), abs(vec2.z))
) >> 5; // shifting right by 5 is good enough.
FV3_Cross(
FV3_Divide(&vec1, m),
FV3_Divide(&vec2, m),
&slope->normal
);
// NOTE: FV3_Magnitude() doesn't work properly in some cases, and chaining FixedHypot() seems to give worse results.
m = R_PointToDist2(0, 0, R_PointToDist2(0, 0, slope->normal.x, slope->normal.y), slope->normal.z);
// Invert normal if it's facing down.
if (slope->normal.z < 0)
m = -m;
FV3_Divide(&slope->normal, m);
// Get direction vector
slope->extent = R_PointToDist2(0, 0, slope->normal.x, slope->normal.y);
slope->d.x = -FixedDiv(slope->normal.x, slope->extent);
slope->d.y = -FixedDiv(slope->normal.y, slope->extent);
m = FixedHypot(slope->normal.x, slope->normal.y);
slope->d.x = -FixedDiv(slope->normal.x, m);
slope->d.y = -FixedDiv(slope->normal.y, m);
// Z delta
slope->zdelta = FixedDiv(slope->extent, slope->normal.z);
slope->zdelta = FixedDiv(m, slope->normal.z);
// Get angles
slope->xydirection = R_PointToAngle2(0, 0, slope->d.x, slope->d.y)+ANGLE_180;
@ -94,88 +92,95 @@ static void P_ReconfigureVertexSlope(pslope_t *slope)
}
}
// Recalculate dynamic slopes
void P_RunDynamicSlopes(void) {
pslope_t *slope;
/// Recalculate dynamic slopes.
void T_DynamicSlopeLine (dynplanethink_t* th)
{
pslope_t* slope = th->slope;
line_t* srcline = th->sourceline;
for (slope = slopelist; slope; slope = slope->next) {
fixed_t zdelta;
fixed_t zdelta;
if (slope->flags & SL_NODYNAMIC)
continue;
switch(th->type) {
case DP_FRONTFLOOR:
zdelta = srcline->backsector->floorheight - srcline->frontsector->floorheight;
slope->o.z = srcline->frontsector->floorheight;
break;
switch(slope->refpos) {
case 1: // front floor
zdelta = slope->sourceline->backsector->floorheight - slope->sourceline->frontsector->floorheight;
slope->o.z = slope->sourceline->frontsector->floorheight;
break;
case 2: // front ceiling
zdelta = slope->sourceline->backsector->ceilingheight - slope->sourceline->frontsector->ceilingheight;
slope->o.z = slope->sourceline->frontsector->ceilingheight;
break;
case 3: // back floor
zdelta = slope->sourceline->frontsector->floorheight - slope->sourceline->backsector->floorheight;
slope->o.z = slope->sourceline->backsector->floorheight;
break;
case 4: // back ceiling
zdelta = slope->sourceline->frontsector->ceilingheight - slope->sourceline->backsector->ceilingheight;
slope->o.z = slope->sourceline->backsector->ceilingheight;
break;
case 5: // vertices
{
mapthing_t *mt;
size_t i;
INT32 l;
line_t *line;
case DP_FRONTCEIL:
zdelta = srcline->backsector->ceilingheight - srcline->frontsector->ceilingheight;
slope->o.z = srcline->frontsector->ceilingheight;
break;
for (i = 0; i < 3; i++) {
mt = slope->vertices[i];
l = P_FindSpecialLineFromTag(799, mt->angle, -1);
if (l != -1) {
line = &lines[l];
mt->z = line->frontsector->floorheight >> FRACBITS;
}
}
case DP_BACKFLOOR:
zdelta = srcline->frontsector->floorheight - srcline->backsector->floorheight;
slope->o.z = srcline->backsector->floorheight;
break;
P_ReconfigureVertexSlope(slope);
}
continue; // TODO
case DP_BACKCEIL:
zdelta = srcline->frontsector->ceilingheight - srcline->backsector->ceilingheight;
slope->o.z = srcline->backsector->ceilingheight;
break;
default:
I_Error("P_RunDynamicSlopes: slope has invalid type!");
}
default:
return;
}
if (slope->zdelta != FixedDiv(zdelta, slope->extent)) {
slope->zdelta = FixedDiv(zdelta, slope->extent);
slope->zangle = R_PointToAngle2(0, 0, slope->extent, -zdelta);
P_CalculateSlopeNormal(slope);
}
if (slope->zdelta != FixedDiv(zdelta, th->extent)) {
slope->zdelta = FixedDiv(zdelta, th->extent);
slope->zangle = R_PointToAngle2(0, 0, th->extent, -zdelta);
P_CalculateSlopeNormal(slope);
}
}
//
// P_MakeSlope
//
// Alocates and fill the contents of a slope structure.
//
static pslope_t *P_MakeSlope(const vector3_t *o, const vector2_t *d,
const fixed_t zdelta, UINT8 flags)
/// Mapthing-defined
void T_DynamicSlopeVert (dynplanethink_t* th)
{
pslope_t *ret = Z_Malloc(sizeof(pslope_t), PU_LEVEL, NULL);
memset(ret, 0, sizeof(*ret));
pslope_t* slope = th->slope;
ret->o.x = o->x;
ret->o.y = o->y;
ret->o.z = o->z;
size_t i;
INT32 l;
ret->d.x = d->x;
ret->d.y = d->y;
for (i = 0; i < 3; i++) {
l = P_FindSpecialLineFromTag(799, th->tags[i], -1);
if (l != -1) {
th->vex[i].z = lines[l].frontsector->floorheight;
}
else
th->vex[i].z = 0;
}
ret->zdelta = zdelta;
ReconfigureViaVertexes(slope, th->vex[0], th->vex[1], th->vex[2]);
}
static inline void P_AddDynSlopeThinker (pslope_t* slope, dynplanetype_t type, line_t* sourceline, fixed_t extent, const INT16 tags[3], const vector3_t vx[3])
{
dynplanethink_t* th = Z_Calloc(sizeof (*th), PU_LEVSPEC, NULL);
switch (type)
{
case DP_VERTEX:
th->thinker.function.acp1 = (actionf_p1)T_DynamicSlopeVert;
memcpy(th->tags, tags, sizeof(th->tags));
memcpy(th->vex, vx, sizeof(th->vex));
break;
default:
th->thinker.function.acp1 = (actionf_p1)T_DynamicSlopeLine;
th->sourceline = sourceline;
th->extent = extent;
}
th->slope = slope;
th->type = type;
P_AddThinker(THINK_DYNSLOPE, &th->thinker);
}
/// Create a new slope and add it to the slope list.
static inline pslope_t* Slope_Add (const UINT8 flags)
{
pslope_t *ret = Z_Calloc(sizeof(pslope_t), PU_LEVEL, NULL);
ret->flags = flags;
// Add to the slope list
ret->next = slopelist;
slopelist = ret;
@ -185,13 +190,24 @@ static pslope_t *P_MakeSlope(const vector3_t *o, const vector2_t *d,
return ret;
}
//
// P_GetExtent
//
// Returns the distance to the first line within the sector that
// is intersected by a line parallel to the plane normal with the point (ox, oy)
//
static fixed_t P_GetExtent(sector_t *sector, line_t *line)
/// Alocates and fill the contents of a slope structure.
static pslope_t *MakeViaVectors(const vector3_t *o, const vector2_t *d,
const fixed_t zdelta, UINT8 flags)
{
pslope_t *ret = Slope_Add(flags);
FV3_Copy(&ret->o, o);
FV2_Copy(&ret->d, d);
ret->zdelta = zdelta;
ret->flags = flags;
return ret;
}
/// Get furthest perpendicular distance from all vertexes in a sector for a given line.
static fixed_t GetExtent(sector_t *sector, line_t *line)
{
// ZDoom code reference: v3float_t = vertex_t
fixed_t fardist = -FRACUNIT;
@ -224,14 +240,8 @@ static fixed_t P_GetExtent(sector_t *sector, line_t *line)
return fardist;
}
//
// P_SpawnSlope_Line
//
// Creates one or more slopes based on the given line type and front/back
// sectors.
//
void P_SpawnSlope_Line(int linenum)
/// Creates one or more slopes based on the given line type and front/back sectors.
static void line_SpawnViaLine(const int linenum, const boolean spawnthinker)
{
// With dynamic slopes, it's fine to just leave this function as normal,
// because checking to see if a slope had changed will waste more memory than
@ -251,10 +261,8 @@ void P_SpawnSlope_Line(int linenum)
UINT8 flags = 0; // Slope flags
if (line->flags & ML_NOSONIC)
flags |= SL_NOPHYSICS;
if (!(line->flags & ML_NOTAILS))
flags |= SL_NODYNAMIC;
if (line->flags & ML_NOKNUX)
flags |= SL_ANCHORVERTEX;
if (line->flags & ML_NOTAILS)
flags |= SL_DYNAMIC;
if(!frontfloor && !backfloor && !frontceil && !backceil)
{
@ -274,6 +282,7 @@ void P_SpawnSlope_Line(int linenum)
ny = -FixedDiv(line->dx, len);
}
// Set origin to line's center.
origin.x = line->v1->x + (line->v2->x - line->v1->x)/2;
origin.y = line->v1->y + (line->v2->y - line->v1->y)/2;
@ -286,7 +295,7 @@ void P_SpawnSlope_Line(int linenum)
direction.x = nx;
direction.y = ny;
extent = P_GetExtent(line->frontsector, line);
extent = GetExtent(line->frontsector, line);
if(extent < 0)
{
@ -304,104 +313,43 @@ void P_SpawnSlope_Line(int linenum)
if(frontfloor)
{
fixed_t highest, lowest;
size_t l;
point.z = line->frontsector->floorheight; // Startz
dz = FixedDiv(origin.z - point.z, extent); // Destinationz
// In P_SpawnSlopeLine the origin is the centerpoint of the sourcelinedef
fslope = line->frontsector->f_slope =
P_MakeSlope(&point, &direction, dz, flags);
// Set up some shit
fslope->extent = extent;
fslope->refpos = 1;
MakeViaVectors(&point, &direction, dz, flags);
// Now remember that f_slope IS a vector
// fslope->o = origin 3D point 1 of the vector
// fslope->d = destination 3D point 2 of the vector
// fslope->normal is a 3D line perpendicular to the 3D vector
// Sync the linedata of the line that started this slope
// TODO: Anything special for control sector based slopes later?
fslope->sourceline = line;
// To find the real highz/lowz of a slope, you need to check all the vertexes
// in the slope's sector with P_GetZAt to get the REAL lowz & highz
// Although these slopes are set by floorheights the ANGLE is what a slope is,
// so technically any slope can extend on forever (they are just bound by sectors)
// *You can use sourceline as a reference to see if two slopes really are the same
// Default points for high and low
highest = point.z > origin.z ? point.z : origin.z;
lowest = point.z < origin.z ? point.z : origin.z;
// Now check to see what the REAL high and low points of the slope inside the sector
// TODO: Is this really needed outside of FOFs? -Red
for (l = 0; l < line->frontsector->linecount; l++)
{
fixed_t height = P_GetZAt(line->frontsector->f_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y);
if (height > highest)
highest = height;
if (height < lowest)
lowest = height;
}
// Sets extra clipping data for the frontsector's slope
fslope->highz = highest;
fslope->lowz = lowest;
fslope->zangle = R_PointToAngle2(0, origin.z, extent, point.z);
fslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y);
P_CalculateSlopeNormal(fslope);
if (spawnthinker && (flags & SL_DYNAMIC))
P_AddDynSlopeThinker(fslope, DP_FRONTFLOOR, line, extent, NULL, NULL);
}
if(frontceil)
{
fixed_t highest, lowest;
size_t l;
origin.z = line->backsector->ceilingheight;
point.z = line->frontsector->ceilingheight;
dz = FixedDiv(origin.z - point.z, extent);
cslope = line->frontsector->c_slope =
P_MakeSlope(&point, &direction, dz, flags);
// Set up some shit
cslope->extent = extent;
cslope->refpos = 2;
// Sync the linedata of the line that started this slope
// TODO: Anything special for control sector based slopes later?
cslope->sourceline = line;
// Remember the way the slope is formed
highest = point.z > origin.z ? point.z : origin.z;
lowest = point.z < origin.z ? point.z : origin.z;
for (l = 0; l < line->frontsector->linecount; l++)
{
fixed_t height = P_GetZAt(line->frontsector->c_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y);
if (height > highest)
highest = height;
if (height < lowest)
lowest = height;
}
// This line special sets extra clipping data for the frontsector's slope
cslope->highz = highest;
cslope->lowz = lowest;
MakeViaVectors(&point, &direction, dz, flags);
cslope->zangle = R_PointToAngle2(0, origin.z, extent, point.z);
cslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y);
P_CalculateSlopeNormal(cslope);
if (spawnthinker && (flags & SL_DYNAMIC))
P_AddDynSlopeThinker(cslope, DP_FRONTCEIL, line, extent, NULL, NULL);
}
}
if(backfloor || backceil)
@ -413,7 +361,7 @@ void P_SpawnSlope_Line(int linenum)
direction.x = -nx;
direction.y = -ny;
extent = P_GetExtent(line->backsector, line);
extent = GetExtent(line->backsector, line);
if(extent < 0)
{
@ -429,88 +377,36 @@ void P_SpawnSlope_Line(int linenum)
if(backfloor)
{
fixed_t highest, lowest;
size_t l;
point.z = line->backsector->floorheight;
dz = FixedDiv(origin.z - point.z, extent);
fslope = line->backsector->f_slope =
P_MakeSlope(&point, &direction, dz, flags);
// Set up some shit
fslope->extent = extent;
fslope->refpos = 3;
// Sync the linedata of the line that started this slope
// TODO: Anything special for control sector based slopes later?
fslope->sourceline = line;
// Remember the way the slope is formed
highest = point.z > origin.z ? point.z : origin.z;
lowest = point.z < origin.z ? point.z : origin.z;
for (l = 0; l < line->backsector->linecount; l++)
{
fixed_t height = P_GetZAt(line->backsector->f_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y);
if (height > highest)
highest = height;
if (height < lowest)
lowest = height;
}
// This line special sets extra clipping data for the frontsector's slope
fslope->highz = highest;
fslope->lowz = lowest;
MakeViaVectors(&point, &direction, dz, flags);
fslope->zangle = R_PointToAngle2(0, origin.z, extent, point.z);
fslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y);
P_CalculateSlopeNormal(fslope);
if (spawnthinker && (flags & SL_DYNAMIC))
P_AddDynSlopeThinker(fslope, DP_BACKFLOOR, line, extent, NULL, NULL);
}
if(backceil)
{
fixed_t highest, lowest;
size_t l;
origin.z = line->frontsector->ceilingheight;
point.z = line->backsector->ceilingheight;
dz = FixedDiv(origin.z - point.z, extent);
cslope = line->backsector->c_slope =
P_MakeSlope(&point, &direction, dz, flags);
// Set up some shit
cslope->extent = extent;
cslope->refpos = 4;
// Sync the linedata of the line that started this slope
// TODO: Anything special for control sector based slopes later?
cslope->sourceline = line;
// Remember the way the slope is formed
highest = point.z > origin.z ? point.z : origin.z;
lowest = point.z < origin.z ? point.z : origin.z;
for (l = 0; l < line->backsector->linecount; l++)
{
fixed_t height = P_GetZAt(line->backsector->c_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y);
if (height > highest)
highest = height;
if (height < lowest)
lowest = height;
}
// This line special sets extra clipping data for the backsector's slope
cslope->highz = highest;
cslope->lowz = lowest;
MakeViaVectors(&point, &direction, dz, flags);
cslope->zangle = R_PointToAngle2(0, origin.z, extent, point.z);
cslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y);
P_CalculateSlopeNormal(cslope);
if (spawnthinker && (flags & SL_DYNAMIC))
P_AddDynSlopeThinker(cslope, DP_BACKCEIL, line, extent, NULL, NULL);
}
}
@ -518,63 +414,99 @@ void P_SpawnSlope_Line(int linenum)
return;
}
//
// P_NewVertexSlope
//
// Creates a new slope from three vertices with the specified IDs
//
static pslope_t *P_NewVertexSlope(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flags)
/// Creates a new slope from three mapthings with the specified IDs
static pslope_t *MakeViaMapthings(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flags, const boolean spawnthinker)
{
size_t i;
mapthing_t *mt = mapthings;
mapthing_t* mt = mapthings;
mapthing_t* vertices[3] = {0};
INT16 tags[3] = {tag1, tag2, tag3};
pslope_t *ret = Z_Malloc(sizeof(pslope_t), PU_LEVEL, NULL);
memset(ret, 0, sizeof(*ret));
// Start by setting flags
ret->flags = flags;
// Now set up the vertex list
ret->vertices = Z_Malloc(3*sizeof(mapthing_t), PU_LEVEL, NULL);
memset(ret->vertices, 0, 3*sizeof(mapthing_t));
vector3_t vx[3];
pslope_t* ret = Slope_Add(flags);
// And... look for the vertices in question.
for (i = 0; i < nummapthings; i++, mt++) {
if (mt->type != 750) // Haha, I'm hijacking the old Chaos Spawn thingtype for something!
continue;
if (!ret->vertices[0] && mt->angle == tag1)
ret->vertices[0] = mt;
else if (!ret->vertices[1] && mt->angle == tag2)
ret->vertices[1] = mt;
else if (!ret->vertices[2] && mt->angle == tag3)
ret->vertices[2] = mt;
if (!vertices[0] && mt->angle == tag1)
vertices[0] = mt;
else if (!vertices[1] && mt->angle == tag2)
vertices[1] = mt;
else if (!vertices[2] && mt->angle == tag3)
vertices[2] = mt;
}
// Now set heights for each vertex, because they haven't been set yet
for (i = 0; i < 3; i++) {
mt = ret->vertices[i];
mt = vertices[i];
if (!mt) // If a vertex wasn't found, it's game over. There's nothing you can do to recover (except maybe try and kill the slope instead - TODO?)
I_Error("P_NewVertexSlope: Slope vertex %s (for linedef tag %d) not found!", sizeu1(i), tag1);
I_Error("MakeViaMapthings: Slope vertex %s (for linedef tag %d) not found!", sizeu1(i), tag1);
vx[i].x = mt->x << FRACBITS;
vx[i].y = mt->y << FRACBITS;
if (mt->extrainfo)
mt->z = mt->options;
vx[i].z = mt->options << FRACBITS;
else
mt->z = (R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)->sector->floorheight >> FRACBITS) + (mt->options >> ZSHIFT);
vx[i].z = (R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)->sector->floorheight) + ((mt->options >> ZSHIFT) << FRACBITS);
}
P_ReconfigureVertexSlope(ret);
ret->refpos = 5;
ReconfigureViaVertexes(ret, vx[0], vx[1], vx[2]);
// Add to the slope list
ret->next = slopelist;
slopelist = ret;
slopecount++;
ret->id = slopecount;
if (spawnthinker && (flags & SL_DYNAMIC))
P_AddDynSlopeThinker(ret, DP_VERTEX, NULL, 0, tags, vx);
return ret;
}
/// Create vertex based slopes.
static void line_SpawnViaVertexes(const int linenum, const boolean spawnthinker)
{
line_t *line = lines + linenum;
side_t *side;
pslope_t **slopetoset;
UINT16 tag1, tag2, tag3;
UINT8 flags = 0;
if (line->flags & ML_NOSONIC)
flags |= SL_NOPHYSICS;
if (line->flags & ML_NOTAILS)
flags |= SL_DYNAMIC;
switch(line->special)
{
case 704:
slopetoset = &line->frontsector->f_slope;
side = &sides[line->sidenum[0]];
break;
case 705:
slopetoset = &line->frontsector->c_slope;
side = &sides[line->sidenum[0]];
break;
case 714:
slopetoset = &line->backsector->f_slope;
side = &sides[line->sidenum[1]];
break;
case 715:
slopetoset = &line->backsector->c_slope;
side = &sides[line->sidenum[1]];
default:
return;
}
if (line->flags & ML_NOKNUX)
{
tag1 = line->tag;
tag2 = side->textureoffset >> FRACBITS;
tag3 = side->rowoffset >> FRACBITS;
}
else
tag1 = tag2 = tag3 = line->tag;
*slopetoset = MakeViaMapthings(tag1, tag2, tag3, flags, spawnthinker);
side->sector->hasslope = true;
}
//
@ -620,56 +552,20 @@ pslope_t *P_SlopeById(UINT16 id)
return ret;
}
// Reset the dynamic slopes pointer, and read all of the fancy schmancy slopes
void P_ResetDynamicSlopes(void) {
/// Reset slopes and read them from special lines.
void P_ResetDynamicSlopes(const UINT32 fromsave) {
size_t i;
#ifdef ESLOPE_TYPESHIM // Rewrite old specials to new ones, and give a console warning
boolean warned = false;
#endif
boolean spawnthinkers = !(boolean)fromsave;
slopelist = NULL;
slopecount = 0;
// We'll handle copy slopes later, after all the tag lists have been made.
// Yes, this means copied slopes won't affect things' spawning heights. Too bad for you.
/// Generates line special-defined slopes.
for (i = 0; i < numlines; i++)
{
switch (lines[i].special)
{
#ifdef ESLOPE_TYPESHIM // Rewrite old specials to new ones, and give a console warning
#define WARNME if (!warned) {warned = true; CONS_Alert(CONS_WARNING, "This level uses old slope specials.\nA conversion will be needed before 2.2's release.\n");}
case 386:
case 387:
case 388:
lines[i].special += 700-386;
WARNME
P_SpawnSlope_Line(i);
break;
case 389:
case 390:
case 391:
case 392:
lines[i].special += 710-389;
WARNME
P_SpawnSlope_Line(i);
break;
case 393:
lines[i].special = 703;
WARNME
P_SpawnSlope_Line(i);
break;
case 394:
case 395:
case 396:
lines[i].special += 720-394;
WARNME
break;
#endif
case 700:
case 701:
case 702:
@ -678,63 +574,35 @@ void P_ResetDynamicSlopes(void) {
case 711:
case 712:
case 713:
P_SpawnSlope_Line(i);
line_SpawnViaLine(i, spawnthinkers);
break;
case 704:
case 705:
case 714:
case 715:
{
pslope_t **slopetoset;
size_t which = lines[i].special;
UINT8 flags = SL_VERTEXSLOPE;
if (lines[i].flags & ML_NOSONIC)
flags |= SL_NOPHYSICS;
if (!(lines[i].flags & ML_NOTAILS))
flags |= SL_NODYNAMIC;
if (which == 704)
{
slopetoset = &lines[i].frontsector->f_slope;
which = 0;
}
else if (which == 705)
{
slopetoset = &lines[i].frontsector->c_slope;
which = 0;
}
else if (which == 714)
{
slopetoset = &lines[i].backsector->f_slope;
which = 1;
}
else // 715
{
slopetoset = &lines[i].backsector->c_slope;
which = 1;
}
if (lines[i].flags & ML_NOKNUX)
*slopetoset = P_NewVertexSlope(lines[i].tag, sides[lines[i].sidenum[which]].textureoffset >> FRACBITS,
sides[lines[i].sidenum[which]].rowoffset >> FRACBITS, flags);
else
*slopetoset = P_NewVertexSlope(lines[i].tag, lines[i].tag, lines[i].tag, flags);
sides[lines[i].sidenum[which]].sector->hasslope = true;
}
line_SpawnViaVertexes(i, spawnthinkers);
break;
default:
break;
}
}
/// Copies slopes from tagged sectors via line specials.
/// \note Doesn't actually copy, but instead they share the same pointers.
for (i = 0; i < numlines; i++)
switch (lines[i].special)
{
case 720:
case 721:
case 722:
P_CopySectorSlope(&lines[i]);
default:
break;
}
}
// ============================================================================
//
// Various utilities related to slopes

View File

@ -13,14 +13,17 @@
#ifndef P_SLOPES_H__
#define P_SLOPES_H__
#include "m_fixed.h" // Vectors
#ifdef ESLOPE
extern pslope_t *slopelist;
extern UINT16 slopecount;
void P_LinkSlopeThinkers (void);
void P_CalculateSlopeNormal(pslope_t *slope);
void P_ResetDynamicSlopes(void);
void P_RunDynamicSlopes(void);
// P_SpawnSlope_Line
// Creates one or more slopes based on the given line type and front/back
// sectors.
void P_SpawnSlope_Line(int linenum);
void P_ResetDynamicSlopes(const UINT32 fromsave);
//
// P_CopySectorSlope
@ -42,7 +45,34 @@ fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope);
void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope);
void P_ButteredSlope(mobj_t *mo);
#endif
// EOF
/// Dynamic plane type enum for the thinker. Will have a different functionality depending on this.
typedef enum {
DP_FRONTFLOOR,
DP_FRONTCEIL,
DP_BACKFLOOR,
DP_BACKCEIL,
DP_VERTEX
} dynplanetype_t;
/// Permit slopes to be dynamically altered through a thinker.
typedef struct
{
thinker_t thinker;
pslope_t* slope;
dynplanetype_t type;
// Used by line slopes.
line_t* sourceline;
fixed_t extent;
// Used by mapthing vertex slopes.
INT16 tags[3];
vector3_t vex[3];
} dynplanethink_t;
void T_DynamicSlopeLine (dynplanethink_t* th);
void T_DynamicSlopeVert (dynplanethink_t* th);
#endif // #ifdef ESLOPE
#endif // #ifndef P_SLOPES_H__

View File

@ -1644,7 +1644,7 @@ static void P_AddExecutorDelay(line_t *line, mobj_t *mobj, sector_t *sector)
e->sector = sector;
e->timer = (line->backsector->ceilingheight>>FRACBITS)+(line->backsector->floorheight>>FRACBITS);
P_SetTarget(&e->caller, mobj); // Use P_SetTarget to make sure the mobj doesn't get freed while we're delaying.
P_AddThinker(&e->thinker);
P_AddThinker(THINK_MAIN, &e->thinker);
}
/** Used by P_RunTriggerLinedef to check a NiGHTS trigger linedef's conditions
@ -2253,7 +2253,7 @@ void P_SwitchWeather(INT32 weathernum)
thinker_t *think;
precipmobj_t *precipmobj;
for (think = thinkercap.next; think != &thinkercap; think = think->next)
for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next)
{
if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker)
continue; // not a precipmobj thinker
@ -2269,7 +2269,7 @@ void P_SwitchWeather(INT32 weathernum)
precipmobj_t *precipmobj;
state_t *st;
for (think = thinkercap.next; think != &thinkercap; think = think->next)
for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next)
{
if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker)
continue; // not a precipmobj thinker
@ -3144,7 +3144,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
scroll_t *scroller;
thinker_t *th;
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)T_Scroll)
continue;
@ -3980,11 +3980,8 @@ void P_SetupSignExit(player_t *player)
// didn't find any signposts in the exit sector.
// spin all signposts in the level then.
for (think = thinkercap.next; think != &thinkercap; think = think->next)
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{
if (think->function.acp1 != (actionf_p1)P_MobjThinker)
continue; // not a mobj thinker
thing = (mobj_t *)think;
if (thing->type != MT_SIGN)
continue;
@ -4012,11 +4009,8 @@ boolean P_IsFlagAtBase(mobjtype_t flag)
mobj_t *mo;
INT32 specialnum = 0;
for (think = thinkercap.next; think != &thinkercap; think = think->next)
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{
if (think->function.acp1 != (actionf_p1)P_MobjThinker)
continue; // not a mobj thinker
mo = (mobj_t *)think;
if (mo->type != flag)
@ -4445,11 +4439,8 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
// Find the center of the Eggtrap and release all the pretty animals!
// The chimps are my friends.. heeheeheheehehee..... - LouisJM
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_EGGTRAP)
P_KillMobj(mo2, NULL, player->mo, 0);
@ -4751,11 +4742,8 @@ DoneSection2:
// scan the thinkers
// to find the first waypoint
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_TUBEWAYPOINT && mo2->threshold == sequence
@ -4830,11 +4818,8 @@ DoneSection2:
// scan the thinkers
// to find the last waypoint
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_TUBEWAYPOINT && mo2->threshold == sequence)
@ -4982,11 +4967,8 @@ DoneSection2:
// scan the thinkers
// to find the first waypoint
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type != MT_TUBEWAYPOINT)
@ -5020,11 +5002,8 @@ DoneSection2:
}
// Find waypoint before this one (waypointlow)
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type != MT_TUBEWAYPOINT)
@ -5047,11 +5026,8 @@ DoneSection2:
}
// Find waypoint after this one (waypointhigh)
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type != MT_TUBEWAYPOINT)
@ -5566,11 +5542,6 @@ void P_UpdateSpecials(void)
// POINT LIMIT
P_CheckPointLimit();
#ifdef ESLOPE
// Dynamic slopeness
P_RunDynamicSlopes();
#endif
// ANIMATE TEXTURES
for (anim = anims; anim < lastanim; anim++)
{
@ -5770,7 +5741,7 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
// Just initialise both of these to placate the compiler.
i = 0;
th = thinkercap.next;
th = thlist[THINK_MAIN].next;
for(;;)
{
@ -5780,7 +5751,7 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f
th = secthinkers[sec2num].thinkers[i];
else break;
}
else if (th == &thinkercap)
else if (th == &thlist[THINK_MAIN])
break;
// Should this FOF have spikeness?
@ -5870,7 +5841,7 @@ static void P_AddSpikeThinker(sector_t *sec, INT32 referrer)
// create and initialize new thinker
spikes = Z_Calloc(sizeof (*spikes), PU_LEVSPEC, NULL);
P_AddThinker(&spikes->thinker);
P_AddThinker(THINK_MAIN, &spikes->thinker);
spikes->thinker.function.acp1 = (actionf_p1)T_SpikeSector;
@ -5892,7 +5863,7 @@ static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline)
// create and initialize new thinker
floater = Z_Calloc(sizeof (*floater), PU_LEVSPEC, NULL);
P_AddThinker(&floater->thinker);
P_AddThinker(THINK_MAIN, &floater->thinker);
floater->thinker.function.acp1 = (actionf_p1)T_FloatSector;
@ -5916,7 +5887,7 @@ static inline void P_AddBridgeThinker(line_t *sourceline, sector_t *sec)
// create an initialize new thinker
bridge = Z_Calloc(sizeof (*bridge), PU_LEVSPEC, NULL);
P_AddThinker(&bridge->thinker);
P_AddThinker(THINK_MAIN, &bridge->thinker);
bridge->thinker.function.acp1 = (actionf_p1)T_BridgeThinker;
@ -5952,7 +5923,7 @@ static void P_AddPlaneDisplaceThinker(INT32 type, fixed_t speed, INT32 control,
// create and initialize new displacement thinker
displace = Z_Calloc(sizeof (*displace), PU_LEVSPEC, NULL);
P_AddThinker(&displace->thinker);
P_AddThinker(THINK_MAIN, &displace->thinker);
displace->thinker.function.acp1 = (actionf_p1)T_PlaneDisplace;
displace->affectee = affectee;
@ -5979,7 +5950,7 @@ static void P_AddBlockThinker(sector_t *sec, line_t *sourceline)
// create and initialize new elevator thinker
block = Z_Calloc(sizeof (*block), PU_LEVSPEC, NULL);
P_AddThinker(&block->thinker);
P_AddThinker(THINK_MAIN, &block->thinker);
block->thinker.function.acp1 = (actionf_p1)T_MarioBlockChecker;
block->sourceline = sourceline;
@ -6008,7 +5979,7 @@ static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline)
levelspecthink_t *raise;
raise = Z_Calloc(sizeof (*raise), PU_LEVSPEC, NULL);
P_AddThinker(&raise->thinker);
P_AddThinker(THINK_MAIN, &raise->thinker);
raise->thinker.function.acp1 = (actionf_p1)T_RaiseSector;
@ -6047,7 +6018,7 @@ static void P_AddOldAirbob(sector_t *sec, line_t *sourceline, boolean noadjust)
levelspecthink_t *airbob;
airbob = Z_Calloc(sizeof (*airbob), PU_LEVSPEC, NULL);
P_AddThinker(&airbob->thinker);
P_AddThinker(THINK_MAIN, &airbob->thinker);
airbob->thinker.function.acp1 = (actionf_p1)T_RaiseSector;
@ -6108,7 +6079,7 @@ static inline void P_AddThwompThinker(sector_t *sec, sector_t *actionsector, lin
// create and initialize new elevator thinker
thwomp = Z_Calloc(sizeof (*thwomp), PU_LEVSPEC, NULL);
P_AddThinker(&thwomp->thinker);
P_AddThinker(THINK_MAIN, &thwomp->thinker);
thwomp->thinker.function.acp1 = (actionf_p1)T_ThwompSector;
@ -6144,7 +6115,7 @@ static inline void P_AddNoEnemiesThinker(sector_t *sec, line_t *sourceline)
// create and initialize new thinker
nobaddies = Z_Calloc(sizeof (*nobaddies), PU_LEVSPEC, NULL);
P_AddThinker(&nobaddies->thinker);
P_AddThinker(THINK_MAIN, &nobaddies->thinker);
nobaddies->thinker.function.acp1 = (actionf_p1)T_NoEnemiesSector;
@ -6166,7 +6137,7 @@ static inline void P_AddEachTimeThinker(sector_t *sec, line_t *sourceline)
// create and initialize new thinker
eachtime = Z_Calloc(sizeof (*eachtime), PU_LEVSPEC, NULL);
P_AddThinker(&eachtime->thinker);
P_AddThinker(THINK_MAIN, &eachtime->thinker);
eachtime->thinker.function.acp1 = (actionf_p1)T_EachTimeThinker;
@ -6188,7 +6159,7 @@ static inline void P_AddCameraScanner(sector_t *sourcesec, sector_t *actionsecto
// create and initialize new elevator thinker
elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL);
P_AddThinker(&elevator->thinker);
P_AddThinker(THINK_MAIN, &elevator->thinker);
elevator->thinker.function.acp1 = (actionf_p1)T_CameraScanner;
elevator->type = elevateBounce;
@ -6284,7 +6255,7 @@ static inline void EV_AddLaserThinker(sector_t *sec, sector_t *sec2, line_t *lin
flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL);
P_AddThinker(&flash->thinker);
P_AddThinker(THINK_MAIN, &flash->thinker);
flash->thinker.function.acp1 = (actionf_p1)T_LaserFlash;
flash->ffloor = ffloor;
@ -6453,7 +6424,7 @@ void P_SpawnSpecials(INT32 fromnetsave)
secthinkers = Z_Calloc(numsectors * sizeof(thinkerlist_t), PU_STATIC, NULL);
// Firstly, find out how many there are in each sector
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next)
{
if (th->function.acp1 == (actionf_p1)T_SpikeSector)
secthinkers[((levelspecthink_t *)th)->sector - sectors].count++;
@ -6473,7 +6444,7 @@ void P_SpawnSpecials(INT32 fromnetsave)
}
// Finally, populate the lists.
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next)
{
size_t secnum = (size_t)-1;
@ -7368,14 +7339,6 @@ void P_SpawnSpecials(INT32 fromnetsave)
sectors[s].extra_colormap = sectors[s].spawn_extra_colormap = sides[lines[i].sidenum[0]].colormap_data;
break;
#ifdef ESLOPE // Slope copy specials. Handled here for sanity.
case 720:
case 721:
case 722:
P_CopySectorSlope(&lines[i]);
break;
#endif
default:
break;
}
@ -7735,7 +7698,7 @@ static void Add_Scroller(INT32 type, fixed_t dx, fixed_t dy, INT32 control, INT3
if ((s->control = control) != -1)
s->last_height = sectors[control].floorheight + sectors[control].ceilingheight;
s->affectee = affectee;
P_AddThinker(&s->thinker);
P_AddThinker(THINK_MAIN, &s->thinker);
}
/** Initializes the scrollers.
@ -7869,7 +7832,7 @@ static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t o
d->exists = true;
d->timer = 1;
P_AddThinker(&d->thinker);
P_AddThinker(THINK_MAIN, &d->thinker);
}
/** Makes a FOF appear/disappear
@ -8358,7 +8321,7 @@ static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloor
FixedFloor(FixedDiv(abs(d->destvalue - d->alpha), d->speed))/FRACUNIT);
}
P_AddThinker(&d->thinker);
P_AddThinker(THINK_MAIN, &d->thinker);
}
/** Makes a FOF fade
@ -8428,7 +8391,7 @@ static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, ext
}
sector->fadecolormapdata = d;
P_AddThinker(&d->thinker); // add thinker
P_AddThinker(THINK_MAIN, &d->thinker);
}
void T_FadeColormap(fadecolormap_t *d)
@ -8547,7 +8510,7 @@ static void Add_Friction(INT32 friction, INT32 movefactor, INT32 affectee, INT32
else
f->roverfriction = false;
P_AddThinker(&f->thinker);
P_AddThinker(THINK_MAIN, &f->thinker);
}
/** Applies friction to all things in a sector.
@ -8713,7 +8676,7 @@ static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *
p->z = p->source->z;
}
p->affectee = affectee;
P_AddThinker(&p->thinker);
P_AddThinker(THINK_MAIN, &p->thinker);
}

View File

@ -35,8 +35,8 @@ tic_t leveltime;
// but the first element must be thinker_t.
//
// Both the head and tail of the thinker list.
thinker_t thinkercap;
// The entries will behave like both the head and tail of the lists.
thinker_t thlist[NUM_THINKERLISTS];
void Command_Numthinkers_f(void)
{
@ -102,7 +102,7 @@ void Command_Numthinkers_f(void)
return;
}
for (think = thinkercap.next; think != &thinkercap; think = think->next)
for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next)
{
if (think->function.acp1 != action)
continue;
@ -139,11 +139,8 @@ void Command_CountMobjs_f(void)
count = 0;
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
if (((mobj_t *)th)->type == i)
count++;
}
@ -159,11 +156,8 @@ void Command_CountMobjs_f(void)
{
count = 0;
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
if (((mobj_t *)th)->type == i)
count++;
}
@ -178,19 +172,18 @@ void Command_CountMobjs_f(void)
//
void P_InitThinkers(void)
{
thinkercap.prev = thinkercap.next = &thinkercap;
UINT8 i;
for (i = 0; i < NUM_THINKERLISTS; i++)
thlist[i].prev = thlist[i].next = &thlist[i];
}
//
// P_AddThinker
// Adds a new thinker at the end of the list.
//
void P_AddThinker(thinker_t *thinker)
void P_AddThinker(const thinklistnum_t n, thinker_t *thinker)
{
thinkercap.prev->next = thinker;
thinker->next = &thinkercap;
thinker->prev = thinkercap.prev;
thinkercap.prev = thinker;
thlist[n].prev->next = thinker;
thinker->next = &thlist[n];
thinker->prev = thlist[n].prev;
thlist[n].prev = thinker;
thinker->references = 0; // killough 11/98: init reference counter to 0
}
@ -245,10 +238,23 @@ void P_RemoveThinkerDelayed(void *pthinker)
//
void P_RemoveThinker(thinker_t *thinker)
{
thinker_t *next = thinker->next;
#ifdef HAVE_BLUA
LUA_InvalidateUserdata(thinker);
#endif
thinker->function.acp1 = P_RemoveThinkerDelayed;
if (currentthinker == thinker)
currentthinker = thinker->prev;
// Remove thinker from its current list.
(next->prev = thinker->prev)->next = next;
// Now add it to the limbo list
thlist[THINK_LIMBO].prev->next = thinker;
thinker->next = &thlist[THINK_LIMBO];
thinker->prev = thlist[THINK_LIMBO].prev;
thlist[THINK_LIMBO].prev = thinker;
}
/*
@ -296,11 +302,16 @@ if ((*mop = targ) != NULL) // Set new target and if non-NULL, increase its count
//
static inline void P_RunThinkers(void)
{
for (currentthinker = thinkercap.next; currentthinker != &thinkercap; currentthinker = currentthinker->next)
size_t i;
for (i = 0; i < NUM_THINKERLISTS; i++)
{
if (currentthinker->function.acp1)
currentthinker->function.acp1(currentthinker);
for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = currentthinker->next)
{
if (currentthinker->function.acp1)
currentthinker->function.acp1(currentthinker);
}
}
}
//

View File

@ -343,11 +343,8 @@ UINT8 P_FindLowestMare(void)
// scan the thinkers
// to find the egg capsule with the lowest mare
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_EGGCAPSULE && mo2->health > 0)
@ -392,11 +389,8 @@ boolean P_TransferToNextMare(player_t *player)
// scan the thinkers
// to find the closest axis point
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_AXIS)
@ -443,11 +437,8 @@ static mobj_t *P_FindAxis(INT32 mare, INT32 axisnum)
// scan the thinkers
// to find the closest axis point
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
// Axis things are only at beginning of list.
@ -476,11 +467,8 @@ static mobj_t *P_FindAxisTransfer(INT32 mare, INT32 axisnum, mobjtype_t type)
// scan the thinkers
// to find the closest axis point
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
// Axis things are only at beginning of list.
@ -515,11 +503,8 @@ void P_TransferToAxis(player_t *player, INT32 axisnum)
// scan the thinkers
// to find the closest axis point
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_AXIS)
@ -615,11 +600,8 @@ static void P_DeNightserizePlayer(player_t *player)
}
// Check to see if the player should be killed.
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (!(mo2->type == MT_NIGHTSDRONE))
continue;
@ -1630,11 +1612,8 @@ void P_SpawnShieldOrb(player_t *player)
}
// blaze through the thinkers to see if an orb already exists!
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
shieldobj = (mobj_t *)th;
if (shieldobj->type == orbtype && shieldobj->target == player->mo)
@ -3168,7 +3147,7 @@ static void P_DoClimbing(player_t *player)
angle_t sideangle;
fixed_t dx, dy;
for (think = thinkercap.next; think != &thinkercap; think = think->next)
for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next)
{
if (think->function.acp1 != (actionf_p1)T_Scroll)
continue;
@ -4604,11 +4583,8 @@ void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range)
if (player->powers[pw_super]) // increase range when super
range *= 2;
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2 == player->mo)
@ -5801,11 +5777,8 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad
fixed_t truexspeed = xspeed*(!(player->pflags & PF_TRANSFERTOCLOSEST) && player->mo->target->flags2 & MF2_AMBUSH ? -1 : 1);
// Find next waypoint
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
continue;
mo2 = (mobj_t *)th;
// Axis things are only at beginning of list.
@ -5837,11 +5810,8 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad
// Look for a wrapper point.
if (!transfer1)
{
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
continue;
mo2 = (mobj_t *)th;
// Axis things are only at beginning of list.
@ -5865,11 +5835,8 @@ static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t rad
}
if (!transfer2)
{
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
continue;
mo2 = (mobj_t *)th;
// Axis things are only at beginning of list.
@ -6572,11 +6539,8 @@ static void P_NiGHTSMovement(player_t *player)
// scan the thinkers
// to find the closest axis point
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_AXIS)
@ -7382,11 +7346,8 @@ static void P_MovePlayer(player_t *player)
thinker_t *th;
mobj_t *mo2;
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_EGGCAPSULE
@ -8291,11 +8252,8 @@ static void P_DoZoomTube(player_t *player)
CONS_Debug(DBG_GAMELOGIC, "Looking for next waypoint...\n");
// Find next waypoint
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
continue;
mo2 = (mobj_t *)th;
if (mo2->type != MT_TUBEWAYPOINT)
@ -8425,11 +8383,8 @@ static void P_DoRopeHang(player_t *player)
CONS_Debug(DBG_GAMELOGIC, "Looking for next waypoint...\n");
// Find next waypoint
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
continue;
mo2 = (mobj_t *)th;
if (mo2->type != MT_TUBEWAYPOINT)
@ -8450,11 +8405,8 @@ static void P_DoRopeHang(player_t *player)
CONS_Debug(DBG_GAMELOGIC, "Next waypoint not found, wrapping to start...\n");
// Wrap around back to first waypoint
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker
continue;
mo2 = (mobj_t *)th;
if (mo2->type != MT_TUBEWAYPOINT)
@ -8516,11 +8468,8 @@ static void P_NukeAllPlayers(player_t *player)
mobj_t *mo;
thinker_t *think;
for (think = thinkercap.next; think != &thinkercap; think = think->next)
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{
if (think->function.acp1 != (actionf_p1)P_MobjThinker)
continue; // not a mobj thinker
mo = (mobj_t *)think;
if (!mo->player)
@ -8564,11 +8513,8 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius)
}
}
for (think = thinkercap.next; think != &thinkercap; think = think->next)
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{
if (think->function.acp1 != (actionf_p1)P_MobjThinker)
continue; // not a mobj thinker
mo = (mobj_t *)think;
if (!(mo->flags & MF_SHOOTABLE) && !(mo->type == MT_EGGGUARD || mo->type == MT_MINUS))
@ -8615,11 +8561,8 @@ mobj_t *P_LookForEnemies(player_t *player, boolean nonenemies, boolean bullet)
const angle_t span = (bullet ? ANG30 : ANGLE_90);
fixed_t dist, closestdist = 0;
for (think = thinkercap.next; think != &thinkercap; think = think->next)
for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next)
{
if (think->function.acp1 != (actionf_p1)P_MobjThinker)
continue; // not a mobj thinker
mo = (mobj_t *)think;
if (!(mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR|MF_SPRING)) == !(mo->flags2 & MF2_INVERTAIMABLE)) // allows if it has the flags desired XOR it has the invert aimable flag
continue; // not a valid target
@ -8754,11 +8697,8 @@ void P_FindEmerald(void)
// scan the remaining thinkers
// to find all emeralds
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_EMERHUNT)
{
@ -9982,11 +9922,8 @@ static mobj_t *P_GetAxis(INT32 num)
thinker_t *th;
mobj_t *mobj;
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mobj = (mobj_t *)th;
// NiGHTS axes spawn before anything else. If this mobj doesn't have MF2_AXIS, it means we reached the axes' end.
@ -10399,14 +10336,8 @@ void P_PlayerThink(player_t *player)
if (player->flashcount)
player->flashcount--;
// Re-fixed by Jimita (11-12-2018)
if (player->awayviewtics)
{
if (player->awayviewtics && player->awayviewtics != -1)
player->awayviewtics--;
if (!player->awayviewtics)
player->awayviewtics = -1;
// The timer might've reached zero, but we'll run the remote view camera anyway by setting it to -1.
}
/// \note do this in the cheat code
if (player->pflags & PF_NOCLIP)
@ -10479,6 +10410,44 @@ void P_PlayerThink(player_t *player)
if (player->exiting && countdown2)
player->exiting = 5;
// Same check as below, just at 1 second before
// so we can fade music
if (!exitfadestarted &&
player->exiting > 0 && player->exiting <= 1*TICRATE &&
(!multiplayer || gametype == GT_COOP ? !mapheaderinfo[gamemap-1]->musinterfadeout : true) &&
// don't fade if we're fading during intermission. follows Y_StartIntermission intertype = int_coop
(gametype == GT_RACE || gametype == GT_COMPETITION ? countdown2 == 0 : true) && // don't fade on timeout
player->lives > 0 && // don't fade on game over (competition)
P_IsLocalPlayer(player))
{
if (cv_playersforexit.value)
{
INT32 i;
for (i = 0; i < MAXPLAYERS; i++)
{
if (!playeringame[i] || players[i].spectator || players[i].bot)
continue;
if (players[i].lives <= 0)
continue;
if (!players[i].exiting || players[i].exiting > 1*TICRATE)
break;
}
if (i == MAXPLAYERS)
{
exitfadestarted = true;
S_FadeOutStopMusic(1*MUSICRATE);
}
}
else
{
exitfadestarted = true;
S_FadeOutStopMusic(1*MUSICRATE);
}
}
if (player->exiting == 2 || countdown2 == 2)
{
if (cv_playersforexit.value) // Count to be sure everyone's exited
@ -10591,11 +10560,8 @@ void P_PlayerThink(player_t *player)
fixed_t y = player->mo->y;
fixed_t z = player->mo->z;
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (!(mo2->type == MT_RING || mo2->type == MT_COIN
@ -11398,9 +11364,6 @@ void P_PlayerAfterThink(player_t *player)
}
}
if (player->awayviewtics < 0)
player->awayviewtics = 0;
// spectator invisibility and nogravity.
if ((netgame || multiplayer) && player->spectator)
{

View File

@ -578,16 +578,7 @@ void R_LoadTextures(void)
// but the alternative is to spend a ton of time checking and re-checking all previous entries just to skip any potentially patched textures.
for (w = 0, numtextures = 0; w < numwadfiles; w++)
{
if (wadfiles[w]->type == RET_PK3)
{
texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0);
texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart);
}
else
{
texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0) + 1;
texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
}
// Count the textures from TEXTURES lumps
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
while (texturesLumpPos != INT16_MAX)
@ -596,18 +587,43 @@ void R_LoadTextures(void)
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1);
}
// Add all the textures between TX_START and TX_END
if (texstart != INT16_MAX && texend != INT16_MAX)
// Count single-patch textures
if (wadfiles[w]->type == RET_PK3)
{
texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0);
texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart);
}
else
{
texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0);
texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
}
if (texstart == INT16_MAX || texend == INT16_MAX)
continue;
texstart++; // Do not count the first marker
// PK3s have subfolders, so we can't just make a simple sum
if (wadfiles[w]->type == RET_PK3)
{
for (j = texstart; j < texend; j++)
{
if (!W_IsLumpFolder((UINT16)w, j)) // Check if lump is a folder; if not, then count it
numtextures++;
}
}
else // Add all the textures between TX_START and TX_END
{
numtextures += (UINT32)(texend - texstart);
}
// If no textures found by this point, bomb out
if (!numtextures && w == (numwadfiles - 1))
{
I_Error("No textures detected in any WADs!\n");
}
}
// If no textures found by this point, bomb out
if (!numtextures)
I_Error("No textures detected in any WADs!\n");
// Allocate memory and initialize to 0 for all the textures we are initialising.
// There are actually 5 buffers allocated in one for convenience.
textures = Z_Calloc((numtextures * sizeof(void *)) * 5, PU_STATIC, NULL);
@ -642,7 +658,7 @@ void R_LoadTextures(void)
}
else
{
texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0) + 1;
texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0);
texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
if (texturesLumpPos != INT16_MAX)
@ -652,9 +668,16 @@ void R_LoadTextures(void)
if (texstart == INT16_MAX || texend == INT16_MAX)
continue;
texstart++; // Do not count the first marker
// Work through each lump between the markers in the WAD.
for (j = 0; j < (texend - texstart); i++, j++)
for (j = 0; j < (texend - texstart); j++)
{
if (wadfiles[w]->type == RET_PK3)
{
if (W_IsLumpFolder((UINT16)w, texstart + j)) // Check if lump is a folder
continue; // If it is then SKIP IT
}
patchlump = W_CacheLumpNumPwad((UINT16)w, texstart + j, PU_CACHE);
//CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height);
@ -684,6 +707,7 @@ void R_LoadTextures(void)
texturewidthmask[i] = k - 1;
textureheight[i] = texture->height << FRACBITS;
i++;
}
}
}
@ -1293,14 +1317,23 @@ void R_ReInitColormaps(UINT16 num)
{
char colormap[9] = "COLORMAP";
lumpnum_t lump;
const lumpnum_t basecolormaplump = W_GetNumForName(colormap);
if (num > 0 && num <= 10000)
snprintf(colormap, 8, "CLM%04u", num-1);
// Load in the light tables, now 64k aligned for smokie...
lump = W_GetNumForName(colormap);
if (lump == LUMPERROR)
lump = W_GetNumForName("COLORMAP");
W_ReadLump(lump, colormaps);
lump = basecolormaplump;
else
{
if (W_LumpLength(lump) != W_LumpLength(basecolormaplump))
{
CONS_Alert(CONS_WARNING, "%s lump size does not match COLORMAP, results may be unexpected.\n", colormap);
}
}
W_ReadLumpHeader(lump, colormaps, W_LumpLength(basecolormaplump), 0U);
// Init Boom colormaps.
R_ClearColormaps();
@ -2242,9 +2275,8 @@ void R_PrecacheLevel(void)
spritepresent = calloc(numsprites, sizeof (*spritepresent));
if (spritepresent == NULL) I_Error("%s: Out of memory looking up sprites", "R_PrecacheLevel");
for (th = thinkercap.next; th != &thinkercap; th = th->next)
if (th->function.acp1 == (actionf_p1)P_MobjThinker)
spritepresent[((mobj_t *)th)->sprite] = 1;
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
spritepresent[((mobj_t *)th)->sprite] = 1;
spritememory = 0;
for (i = 0; i < numsprites; i++)

View File

@ -237,46 +237,27 @@ typedef struct linechain_s
// Slopes
#ifdef ESLOPE
typedef enum {
SL_NOPHYSICS = 1, // Don't do momentum adjustment with this slope
SL_NODYNAMIC = 1<<1, // Slope will never need to move during the level, so don't fuss with recalculating it
SL_ANCHORVERTEX = 1<<2, // Slope is using a Slope Vertex Thing to anchor its position
SL_VERTEXSLOPE = 1<<3, // Slope is built from three Slope Vertex Things
SL_NOPHYSICS = 1, /// This plane will have no physics applied besides the positioning.
SL_DYNAMIC = 1<<1, /// This plane slope will be assigned a thinker to make it dynamic.
} slopeflags_t;
typedef struct pslope_s
{
UINT16 id; // The number of the slope, mostly used for netgame syncing purposes
struct pslope_s *next; // Make a linked list of dynamic slopes, for easy reference later
// --- Information used in clipping/projection ---
// Origin vector for the plane
vector3_t o;
// The plane's definition.
vector3_t o; /// Plane origin.
vector3_t normal; /// Plane normal.
// 2-Dimentional vector (x, y) normalized. Used to determine distance from
// the origin in 2d mapspace. (Basically a thrust of FRACUNIT in xydirection angle)
vector2_t d;
// The rate at which z changes based on distance from the origin plane.
fixed_t zdelta;
// The normal of the slope; will always point upward, and thus be inverted on ceilings. I think it's only needed for physics? -Red
vector3_t normal;
// For comparing when a slope should be rendered
fixed_t lowz;
fixed_t highz;
vector2_t d; /// Precomputed normalized projection of the normal over XY.
fixed_t zdelta; /// Precomputed Z unit increase per XY unit.
// This values only check and must be updated if the slope itself is modified
angle_t zangle; // Angle of the plane going up from the ground (not mesured in degrees)
angle_t xydirection; // The direction the slope is facing (north, west, south, etc.)
struct line_s *sourceline; // The line that generated the slope
fixed_t extent; // Distance value used for recalculating zdelta
UINT8 refpos; // 1=front floor 2=front ceiling 3=back floor 4=back ceiling (used for dynamic sloping)
angle_t zangle; /// Precomputed angle of the plane going up from the ground (not measured in degrees).
angle_t xydirection;/// Precomputed angle of the normal's projection on the XY plane.
UINT8 flags; // Slope options
mapthing_t **vertices; // List should be three long for slopes made by vertex things, or one long for slopes using one vertex thing to anchor
struct pslope_s *next; // Make a linked list of dynamic slopes, for easy reference later
} pslope_t;
#endif

View File

@ -2306,10 +2306,8 @@ static void ST_doItemFinderIconsAndSound(void)
return;
// Scan thinkers to find emblem mobj with these ids
for (th = thinkercap.next; th != &thinkercap; th = th->next)
for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next)
{
if (th->function.acp1 != (actionf_p1)P_MobjThinker)
continue;
mo2 = (mobj_t *)th;
if (mo2->type == MT_EMBLEM)

View File

@ -1322,7 +1322,7 @@ static UINT32 V_GetHWConsBackColor(void)
switch (cons_backcolor.value)
{
case 0: hwcolor = 0xffffff00; break; // White
case 1: hwcolor = 0x80808000; break; // Gray
case 1: hwcolor = 0x80808000; break; // Black
case 2: hwcolor = 0xdeb88700; break; // Sepia
case 3: hwcolor = 0x40201000; break; // Brown
case 4: hwcolor = 0xfa807200; break; // Pink
@ -1633,15 +1633,25 @@ void V_DrawPromptBack(INT32 boxheight, INT32 color)
UINT32 hwcolor;
switch (color)
{
case 0: hwcolor = 0xffffff00; break; // White
case 1: hwcolor = 0x00000000; break; // Gray // Note this is different from V_DrawFadeConsBack
case 2: hwcolor = 0x40201000; break; // Brown
case 3: hwcolor = 0xff000000; break; // Red
case 4: hwcolor = 0xff800000; break; // Orange
case 5: hwcolor = 0x80800000; break; // Yellow
case 6: hwcolor = 0x00800000; break; // Green
case 7: hwcolor = 0x0000ff00; break; // Blue
case 8: hwcolor = 0x4080ff00; break; // Cyan
case 0: hwcolor = 0xffffff00; break; // White
case 1: hwcolor = 0x00000000; break; // Black // Note this is different from V_DrawFadeConsBack
case 2: hwcolor = 0xdeb88700; break; // Sepia
case 3: hwcolor = 0x40201000; break; // Brown
case 4: hwcolor = 0xfa807200; break; // Pink
case 5: hwcolor = 0xff69b400; break; // Raspberry
case 6: hwcolor = 0xff000000; break; // Red
case 7: hwcolor = 0xffd68300; break; // Creamsicle
case 8: hwcolor = 0xff800000; break; // Orange
case 9: hwcolor = 0xdaa52000; break; // Gold
case 10: hwcolor = 0x80800000; break; // Yellow
case 11: hwcolor = 0x00ff0000; break; // Emerald
case 12: hwcolor = 0x00800000; break; // Green
case 13: hwcolor = 0x4080ff00; break; // Cyan
case 14: hwcolor = 0x4682b400; break; // Steel
case 15: hwcolor = 0x1e90ff00; break; // Periwinkle
case 16: hwcolor = 0x0000ff00; break; // Blue
case 17: hwcolor = 0xff00ff00; break; // Purple
case 18: hwcolor = 0xee82ee00; break; // Lavender
// Default green
default: hwcolor = 0x00800000; break;
}

View File

@ -162,9 +162,15 @@ FILE *W_OpenWadFile(const char **filename, boolean useerrors)
{
FILE *handle;
strncpy(filenamebuf, *filename, MAX_WADPATH);
filenamebuf[MAX_WADPATH - 1] = '\0';
*filename = filenamebuf;
// Officially, strncpy should not have overlapping buffers, since W_VerifyNMUSlumps is called after this, and it
// changes filename to point at filenamebuf, it would technically be doing that. I doubt any issue will occur since
// they point to the same location, but it's better to be safe and this is a simple change.
if (filenamebuf != *filename)
{
strncpy(filenamebuf, *filename, MAX_WADPATH);
filenamebuf[MAX_WADPATH - 1] = '\0';
*filename = filenamebuf;
}
// open wad file
if ((handle = fopen(*filename, "rb")) == NULL)
@ -1133,6 +1139,22 @@ boolean W_IsLumpWad(lumpnum_t lumpnum)
return false; // WADs should never be inside non-PK3s as far as SRB2 is concerned
}
//
// W_IsLumpFolder
// Is the lump a folder? (in a PK3 obviously)
//
boolean W_IsLumpFolder(UINT16 wad, UINT16 lump)
{
if (wadfiles[wad]->type == RET_PK3)
{
const char *name = wadfiles[wad]->lumpinfo[lump].name2;
return (name[strlen(name)-1] == '/'); // folders end in '/'
}
return false; // non-PK3s don't have folders
}
#ifdef HAVE_ZLIB
/* report a zlib or i/o error */
void zerr(int ret)

View File

@ -151,6 +151,7 @@ size_t W_LumpLengthPwad(UINT16 wad, UINT16 lump);
size_t W_LumpLength(lumpnum_t lumpnum);
boolean W_IsLumpWad(lumpnum_t lumpnum); // for loading maps from WADs in PK3s
boolean W_IsLumpFolder(UINT16 wad, UINT16 lump); // for detecting folder "lumps"
#ifdef HAVE_ZLIB
void zerr(int ret); // zlib error checking