Merge branch 'v2dev3' into udmf-cherrypick-cherrypick

This commit is contained in:
NepDisk 2024-08-21 22:13:53 -04:00
commit ccfa90677c
25 changed files with 309 additions and 83 deletions

View file

@ -31,6 +31,9 @@
static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name);
#ifdef DEVELOP
static const char *getcanonicalfuncname (Closure *f, const char **name);
#endif
static int currentpc (lua_State *L, CallInfo *ci) {
@ -212,7 +215,11 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar,
break;
}
case 'n': {
#ifdef DEVELOP
ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : getcanonicalfuncname(f, &ar->name);
#else
ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL;
#endif
if (ar->namewhat == NULL) {
ar->namewhat = ""; /* not found */
ar->name = NULL;
@ -555,6 +562,19 @@ static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) {
}
#ifdef DEVELOP
static const char *getcanonicalfuncname (Closure *cl, const char **name) {
if (!cl->c.isC && cl->l.p->canonicalname)
{
*name = cl->l.p->canonicalname;
return "global";
}
else
return NULL;
}
#endif
/* only ANSI way to check whether a pointer points to an array */
static int isinstack (CallInfo *ci, const TValue *o) {
StkId p;

View file

@ -134,6 +134,9 @@ Proto *luaF_newproto (lua_State *L) {
f->linedefined = 0;
f->lastlinedefined = 0;
f->source = NULL;
#ifdef DEVELOP
f->canonicalname = NULL;
#endif
return f;
}

View file

@ -237,6 +237,9 @@ typedef struct Proto {
struct LocVar *locvars; /* information about local variables */
TString **upvalues; /* upvalue names */
TString *source;
#ifdef DEVELOP
const char *canonicalname; /* function name, only for globals right now */
#endif
int sizeupvalues;
int sizek; /* size of `k' */
int sizecode;

View file

@ -246,8 +246,7 @@ static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
}
static void singlevar (LexState *ls, expdesc *var) {
TString *varname = str_checkname(ls);
static void singlevar (LexState *ls, expdesc *var, TString *varname) {
FuncState *fs = ls->fs;
if (singlevaraux(fs, varname, var, 1) == VGLOBAL)
var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */
@ -603,11 +602,16 @@ static void body_noparms (LexState *ls, expdesc *e, int line) {
close_func(ls);
pushclosure(ls, &new_fs, e);
}
static void body (LexState *ls, expdesc *e, int needself, int line) {
static void body (LexState *ls, expdesc *e, int needself, int line, const char *name) {
/* body -> `(' parlist `)' chunk END */
FuncState new_fs;
open_func(ls, &new_fs);
new_fs.f->linedefined = line;
#ifdef DEVELOP
new_fs.f->canonicalname = name;
#else
(void)name;
#endif
checknext(ls, '(');
if (needself) {
new_localvarliteral(ls, "self", 0);
@ -706,7 +710,7 @@ static void prefixexp (LexState *ls, expdesc *v) {
return;
}
case TK_NAME: {
singlevar(ls, v);
singlevar(ls, v, str_checkname(ls));
return;
}
case '$': {
@ -826,7 +830,7 @@ static void simpleexp (LexState *ls, expdesc *v) {
}
case TK_FUNCTION: {
luaX_next(ls);
body(ls, v, 0, ls->linenumber);
body(ls, v, 0, ls->linenumber, NULL);
return;
}
default: {
@ -1315,11 +1319,12 @@ static void ifstat (LexState *ls, int line) {
static void localfunc (LexState *ls) {
expdesc v, b;
FuncState *fs = ls->fs;
new_localvar(ls, str_checkname(ls), 0);
TString *name = str_checkname(ls);
new_localvar(ls, name, 0);
init_exp(&v, VLOCAL, fs->freereg);
luaK_reserveregs(fs, 1);
adjustlocalvars(ls, 1);
body(ls, &b, 0, ls->linenumber);
body(ls, &b, 0, ls->linenumber, NULL);
luaK_storevar(fs, &v, &b);
/* debug information will only see the variable after this point! */
getlocvar(fs, fs->nactvar - 1).startpc = fs->pc;
@ -1345,10 +1350,10 @@ static void localstat (LexState *ls) {
}
static int funcname (LexState *ls, expdesc *v) {
static int funcname (LexState *ls, expdesc *v, TString *varname) {
/* funcname -> NAME {field} [`:' NAME] */
int needself = 0;
singlevar(ls, v);
singlevar(ls, v, varname);
while (ls->t.token == '.')
field(ls, v);
if (ls->t.token == ':') {
@ -1363,9 +1368,16 @@ static void funcstat (LexState *ls, int line) {
/* funcstat -> FUNCTION funcname body */
int needself;
expdesc v, b;
TString *name;
luaX_next(ls); /* skip FUNCTION */
needself = funcname(ls, &v);
body(ls, &b, needself, line);
name = str_checkname(ls);
needself = funcname(ls, &v, name);
#ifdef DEVELOP
/* just strdup this because I couldn't figure out gc */
body(ls, &b, needself, line, name ? strdup(getstr(name)) : NULL);
#else
body(ls, &b, needself, line, NULL);
#endif
luaK_storevar(ls->fs, &v, &b);
luaK_fixline(ls->fs, line); /* definition `happens' in the first line */
}

View file

@ -2915,16 +2915,6 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
pnum = READUINT8(*p);
msg = READUINT8(*p);
if (pnum == serverplayer && IsPlayerAdmin(playernum))
{
CONS_Printf(M_GetText("Server is being shut down remotely. Goodbye!\n"));
if (server)
COM_BufAddText("quit\n");
return;
}
// Is playernum authorized to make this kick?
if (playernum != serverplayer && !IsPlayerAdmin(playernum)
/*&& !(playernode[playernum] != UINT8_MAX && playerpernode[playernode[playernum]] == 2
@ -2974,6 +2964,12 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
READSTRINGN(*p, reason, MAX_REASONLENGTH+1);
}
if (playernode[pnum] == servernode)
{
CONS_Printf(M_GetText("Ignoring kick attempt from %s on node %d (it's the server)\n"), player_names[playernum], servernode);
return;
}
//CONS_Printf("\x82%s ", player_names[pnum]);
// Save bans here. Used to be split between here and the actual command, depending on

View file

@ -1661,7 +1661,7 @@ void D_SRB2Main(void)
I_Error("Cannot find a map remotely named '%s'\n", word);
else
{
if (!M_CheckParm("-server"))
if (!M_CheckParm("-server") && !M_CheckParm("-dedicated"))
{
G_SetGameModified(true, true);

View file

@ -5126,7 +5126,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
"MT_SKYBOX",
// Debris
"MT_SPARK", //spark
"MT_SPARK", //spark, only used for debugging, actually
"MT_EXPLODE", // Robot Explosion
"MT_UWEXPLODE", // Underwater Explosion
"MT_DUST",

View file

@ -1113,7 +1113,7 @@ void G_GhostTicker(void)
for(g = ghosts, p = NULL; g; g = g->next)
{
// Skip normal demo data.
UINT8 ziptic = READUINT8(g->p);
UINT16 ziptic = READUINT8(g->p);
UINT8 xziptic = 0;
while (ziptic != DW_END) // Get rid of extradata stuff
@ -1142,12 +1142,16 @@ void G_GhostTicker(void)
ziptic = READUINT8(g->p);
}
ziptic = READUINT8(g->p);
ziptic = READUINT16(g->p);
if (ziptic & ZT_FWD)
g->p++;
if (ziptic & ZT_SIDE)
g->p++;
if (ziptic & ZT_TURNING)
g->p += 2;
if (ziptic & ZT_ANGLE)
g->p += 2;
if (ziptic & ZT_THROWDIR)
g->p += 2;
if (ziptic & ZT_BUTTONS)

View file

@ -6143,7 +6143,7 @@ typedef enum mobj_type
MT_SKYBOX,
// Debris
MT_SPARK, //spark
MT_SPARK, //spark, only used for debugging, actually
MT_EXPLODE, // Robot Explosion
MT_UWEXPLODE, // Underwater Explosion
MT_DUST,

View file

@ -514,10 +514,7 @@ boolean K_DropTargetCollide(mobj_t *t1, mobj_t *t2)
{
mobj_t *draggeddroptarget = (t1->type == MT_DROPTARGET_SHIELD) ? t1->target : NULL;
if ((t1->threshold > 0 && (!draggeddroptarget)) || (t2->threshold > 0))
return true;
if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
if (((t1->target == t2) || (t1->target == t2->target)) && ((t1->threshold > 0 && t2->type == MT_PLAYER) || (t2->type != MT_PLAYER && t2->threshold > 0)))
return true;
if (t1->health <= 0 || t2->health <= 0)

View file

@ -8902,18 +8902,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
{
player->pflags &= ~PF_AIRFAILSAFE;
}
// Play the starting countdown sounds
if (!(gametyperules & GTR_FREEROAM) && player == &players[g_localplayers[0]]) // Don't play louder in splitscreen
{
if ((leveltime == starttime-(3*TICRATE)) || (leveltime == starttime-(2*TICRATE)) || (leveltime == starttime-TICRATE))
S_StartSound(NULL, sfx_s3ka7);
if (leveltime == starttime-(3*TICRATE))
S_FadeOutStopMusic(3500);
else if (leveltime == starttime)
S_StartSound(NULL, sfx_s3kad);
}
}
void K_CheckSpectateStatus(void)

View file

@ -620,6 +620,13 @@ void K_DebugWaypointsVisualise(void)
// Hunt through the waypointcap so we can show all waypoint mobjs and not just ones that were able to be graphed
for (waypointmobj = waypointcap; waypointmobj != NULL; waypointmobj = waypointmobj->tracer)
{
// If this waypoint is outside of draw distance, don't spawn all the debug crap because it is SLOW
if (cv_drawdist.value != 0 &&
R_PointToDist(waypointmobj->x, waypointmobj->y) > cv_drawdist.value * mapobjectscale)
{
continue;
}
waypoint = K_SearchWaypointHeapForMobj(waypointmobj);
debugmobj = P_SpawnMobj(waypointmobj->x, waypointmobj->y, waypointmobj->z, MT_SPARK);

View file

@ -671,6 +671,23 @@ static int lib_pSpawnMobjFromMobj(lua_State *L)
return 1;
}
static int lib_pSpawnMobjFromMobjUnscaled(lua_State *L)
{
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
fixed_t x = luaL_checkfixed(L, 2);
fixed_t y = luaL_checkfixed(L, 3);
fixed_t z = luaL_checkfixed(L, 4);
mobjtype_t type = luaL_checkinteger(L, 5);
NOHUD
INLEVEL
if (!actor)
return LUA_ErrInvalid(L, "mobj_t");
if (type >= NUMMOBJTYPES)
return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1);
LUA_PushUserdata(L, P_SpawnMobjFromMobjUnscaled(actor, x, y, z, type), META_MOBJ);
return 1;
}
static int lib_pRemoveMobj(lua_State *L)
{
mobj_t *th = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
@ -3847,6 +3864,7 @@ static luaL_Reg lib[] = {
// don't add P_SetMobjState or P_SetPlayerMobjState, use "mobj.state = S_NEWSTATE" instead.
{"P_SpawnMobj",lib_pSpawnMobj},
{"P_SpawnMobjFromMobj",lib_pSpawnMobjFromMobj},
{"P_SpawnMobjFromMobjUnscaled",lib_pSpawnMobjFromMobjUnscaled},
{"P_RemoveMobj",lib_pRemoveMobj},
{"P_IsValidSprite2", lib_pIsValidSprite2},
{"P_SpawnLockOn", lib_pSpawnLockOn},

View file

@ -672,7 +672,7 @@ void LUA_HookThinkFrame(void)
{
get_hook(&hook, map->ids, k);
if (cv_perfstats.value == 3)
if (cv_perfstats.value == PS_THINKFRAME)
{
lua_pushvalue(gL, -1);/* need the function again */
time_taken = I_GetPreciseTime();
@ -680,7 +680,7 @@ void LUA_HookThinkFrame(void)
call_single_hook(&hook);
if (cv_perfstats.value == 3)
if (cv_perfstats.value == PS_THINKFRAME)
{
lua_Debug ar;
time_taken = I_GetPreciseTime() - time_taken;

View file

@ -43,7 +43,8 @@ enum sfxinfo_read {
sfxinfor_flags, // "pitch"
sfxinfor_volume,
sfxinfor_caption,
sfxinfor_skinsound
sfxinfor_skinsound,
sfxinfor_string,
};
const char *const sfxinfo_ropt[] = {
"name",
@ -53,6 +54,7 @@ const char *const sfxinfo_ropt[] = {
"volume",
"caption",
"skinsound",
"string",
NULL};
enum sfxinfo_write {
@ -917,12 +919,52 @@ static int state_get(lua_State *L)
// because the metatable will trigger.
lua_getglobal(L, name); // actually gets from LREG_ACTIONS if applicable, and pushes a META_ACTION userdata if not.
return 1; // return just the function
#ifdef DEVELOP
} else if (fastcmp(field,"actionname")) {
if (!st->action.acp1) { // Action is NULL.
lua_pushstring(L, "NULL");
} else if (st->action.acp1 == (actionf_p1)A_Lua) { // This is a Lua function?
lua_Debug ar;
lua_getfield(L, LUA_REGISTRYINDEX, LREG_STATEACTION);
I_Assert(lua_istable(L, -1));
lua_pushlightuserdata(L, st); // Push the state pointer and
lua_rawget(L, -2); // use it to get the actual Lua function.
lua_remove(L, -2); // pop LREG_STATEACTION
// This normally doesn't get a function's name because the same Lua function can have many names.
// It only works because of a hack called 'canonicalname' in blua/lparser.c, which records the
// name a GLOBAL function was defined with. This does not work for local functions! (Lua actions
// are almost always global functions though.)
lua_getinfo(L, ">n", &ar);
lua_pushstring(L, ar.name);
} else {
lua_pushstring(L, LUA_GetActionName(&st->action)); // find a hardcoded function name
}
return 1;
#endif
} else if (fastcmp(field,"var1"))
number = st->var1;
else if (fastcmp(field,"var2"))
number = st->var2;
else if (fastcmp(field,"nextstate"))
number = st->nextstate;
else if (fastcmp(field,"string"))
{
statenum_t id = st-states;
if (id < S_FIRSTFREESLOT)
{
lua_pushstring(L, STATE_LIST[id]+2);
return 1;
}
id -= S_FIRSTFREESLOT;
if (id < NUMSTATEFREESLOTS && FREE_STATES[id])
{
lua_pushstring(L, FREE_STATES[id]);
return 1;
}
return 0;
}
else if (devparm)
return luaL_error(L, LUA_QL("state_t") " has no field named " LUA_QS, field);
else
@ -1188,6 +1230,23 @@ static int mobjinfo_get(lua_State *L)
lua_pushinteger(L, info->flags);
else if (fastcmp(field,"raisestate"))
lua_pushinteger(L, info->raisestate);
else if (fastcmp(field,"string")) {
mobjtype_t id = info-mobjinfo;
if (id < MT_FIRSTFREESLOT)
{
lua_pushstring(L, MOBJTYPE_LIST[id]+3);
return 1;
}
id -= MT_FIRSTFREESLOT;
if (id < NUMMOBJFREESLOTS && FREE_MOBJS[id])
{
lua_pushstring(L, FREE_MOBJS[id]);
return 1;
}
return 0;
}
else {
lua_getfield(L, LUA_REGISTRYINDEX, LREG_EXTVARS);
I_Assert(lua_istable(L, -1));
@ -1411,6 +1470,10 @@ static int sfxinfo_get(lua_State *L)
case sfxinfor_skinsound:
lua_pushinteger(L, sfx->skinsound);
return 1;
case sfxinfor_string: {
lua_pushstring(L, sfx->name);
return 1;
}
default:
return luaL_error(L, "Field does not exist in sfxinfo_t");
}

View file

@ -36,6 +36,7 @@
#include "doomstat.h"
#include "g_state.h"
#include "m_argv.h"
lua_State *gL = NULL;
@ -608,6 +609,12 @@ void LUA_LoadLump(UINT16 wad, UINT16 lump, boolean noresults)
MYFILE f;
char *name;
size_t len;
if (M_CheckParm("-nolua"))
{
return;
}
f.wad = wad;
f.size = W_LumpLengthPwad(wad, lump);
f.data = Z_Malloc(f.size, PU_LUA, NULL);

View file

@ -1870,6 +1870,12 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source,
{
(void)source;
if (player->respawn)
{
K_DoInstashield(player);
return false;
}
if (player->exiting)
{
player->mo->destscale = 1;

View file

@ -46,9 +46,7 @@
#define BMBOUNDFIX(xl, xh, yl, yh) {if (xl > xh) xl = 0; if (yl > yh) yl = 0;}
// MAXRADIUS is for precalculated sector block boxes
// the spider demon is larger,
// but we do not have any moving sectors nearby
#define MAXRADIUS (32*FRACUNIT)
#define MAXRADIUS (MAPBLOCKSIZE >> 1)
// max Z move up or down without jumping
// above this, a height difference is considered as a 'dropoff'
@ -326,6 +324,7 @@ boolean P_CheckDeathPitCollide(mobj_t *mo);
boolean P_CheckSolidLava(ffloor_t *rover);
void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motype);
mobj_t *P_SpawnMobjFromMobjUnscaled(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zofs, mobjtype_t type);
mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zofs, mobjtype_t type);
mobj_t *P_SpawnMissile(mobj_t *source, mobj_t *dest, mobjtype_t type);

View file

@ -12276,7 +12276,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
// Ambush = double size (grounded) / half size (aerial)
if (!(mthing->args[2] & TMICF_INVERTSIZE) == !P_IsObjectOnGround(mobj))
{
mobj->extravalue1 = min(mobj->extravalue1 << 1, FixedDiv(64*FRACUNIT, mobj->info->radius)); // don't make them larger than the blockmap can handle
mobj->extravalue1 = min(mobj->extravalue1 << 1, FixedDiv(MAPBLOCKSIZE, mobj->info->radius)); // don't make them larger than the blockmap can handle
mobj->scalespeed <<= 1;
}
break;
@ -13239,6 +13239,65 @@ fixed_t P_ScaleFromMap(fixed_t n, fixed_t scale)
return FixedMul(n, FixedDiv(scale, mapobjectscale));
}
//
// P_SpawnMobjFromMobjUnscaled
// Spawns an object with offsets relative to the position of another object.
// Scale, gravity flip, etc. is taken into account automatically.
//
mobj_t *P_SpawnMobjFromMobjUnscaled(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zofs, mobjtype_t type)
{
mobj_t *newmobj;
newmobj = P_SpawnMobj(mobj->x + xofs, mobj->y + yofs, mobj->z + zofs, type);
if (!newmobj)
return NULL;
newmobj->destscale = P_ScaleFromMap(mobj->destscale, newmobj->destscale);
P_SetScale(newmobj, P_ScaleFromMap(mobj->scale, newmobj->scale));
if (mobj->eflags & MFE_VERTICALFLIP)
{
newmobj->eflags |= MFE_VERTICALFLIP;
newmobj->flags2 |= MF2_OBJECTFLIP;
newmobj->z = mobj->z + mobj->height - zofs - newmobj->height;
newmobj->old_z = mobj->old_z + mobj->height - zofs - newmobj->height;
newmobj->old_z2 = mobj->old_z2 + mobj->height - zofs - newmobj->height;
}
else
{
newmobj->old_z = mobj->old_z + zofs;
newmobj->old_z2 = mobj->old_z2 + zofs;
}
newmobj->old_x2 = mobj->old_x2 + xofs;
newmobj->old_y2 = mobj->old_y2 + yofs;
newmobj->old_x = mobj->old_x + xofs;
newmobj->old_y = mobj->old_y + yofs;
// This angle hack is needed for Lua scripts that set the angle after
// spawning, to avoid erroneous interpolation.
if (mobj->player)
{
newmobj->old_angle2 = mobj->player->old_drawangle2;
newmobj->old_angle = mobj->player->old_drawangle;
}
else
{
newmobj->old_angle2 = mobj->old_angle2;
newmobj->old_angle = mobj->old_angle;
}
newmobj->old_scale2 = mobj->old_scale2;
newmobj->old_scale = mobj->old_scale;
newmobj->old_spritexscale = mobj->old_spritexscale;
newmobj->old_spriteyscale = mobj->old_spriteyscale;
newmobj->old_spritexoffset = mobj->old_spritexoffset;
newmobj->old_spriteyoffset = mobj->old_spriteyoffset;
return newmobj;
}
//
// P_SpawnMobjFromMobj
// Spawns an object with offsets relative to the position of another object.

View file

@ -1749,6 +1749,10 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
if (mobj->type == MT_HOOPCENTER && mobj->threshold == 4242)
return;
// MT_SPARK: used for debug stuff
if (mobj->type == MT_SPARK)
return;
if (mobj->spawnpoint)
{
// spawnpoint is not modified but we must save it since it is an identifier
@ -4236,7 +4240,9 @@ static void P_RelinkPointers(void)
mobj = (mobj_t *)currentthinker;
if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER)
if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER
// MT_SPARK: used for debug stuff
|| mobj->type == MT_SPARK)
continue;
if (mobj->tracer)
@ -4869,7 +4875,9 @@ void P_SaveNetGame(boolean resending)
continue;
mobj = (mobj_t *)th;
if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER)
if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER
// MT_SPARK: used for debug stuff
|| mobj->type == MT_SPARK)
continue;
mobj->mobjnum = i++;
}

View file

@ -672,7 +672,7 @@ void P_Ticker(boolean run)
// Bosses have a punchy start, so no position.
if (bossinfo.boss == true)
{
if (leveltime == 3)
if (leveltime == 0)
{
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
S_ShowMusicCredit();
@ -681,6 +681,19 @@ void P_Ticker(boolean run)
// Plays the music after the starting countdown.
else
{
if (leveltime == starttime-(3*TICRATE))
{
S_StartSound(NULL, sfx_s3ka7); // 3,
S_FadeOutStopMusic(3500);
}
else if ((leveltime == starttime-(2*TICRATE)) || (leveltime == starttime-TICRATE))
{
S_StartSound(NULL, sfx_s3ka7); // 2, 1,
}
else if (leveltime == starttime)
{
S_StartSound(NULL, sfx_s3kad); // GO!
}
if (leveltime == (starttime + (TICRATE/2)))
{
S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0);
@ -689,7 +702,7 @@ void P_Ticker(boolean run)
}
ps_lua_thinkframe_time = I_GetPreciseTime();
LUA_HOOK(ThinkFrame);
LUA_HookThinkFrame();
ps_lua_thinkframe_time = I_GetPreciseTime() - ps_lua_thinkframe_time;
}

View file

@ -2615,39 +2615,41 @@ static boolean R_SortVisSpriteFunc(vissprite_t *ds, fixed_t bestscale, INT32 bes
//
static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 end)
{
UINT32 i, linkedvissprites = 0;
UINT32 i, count = 0;
vissprite_t *ds, *dsprev, *dsnext, *dsfirst;
vissprite_t *best = NULL;
vissprite_t unsorted;
fixed_t bestscale;
INT32 bestdispoffset;
unsorted.next = unsorted.prev = &unsorted;
dsfirst = &unsorted;
dsprev = dsfirst;
dsnext = dsfirst;
dsfirst = R_GetVisSprite(start);
I_Assert(start <= end);
// The first's prev and last's next will be set to
// nonsense, but are fixed in a moment
for (i = start, dsnext = dsfirst, ds = NULL; i < end; i++)
for (i = start; i < end; ++i)
{
dsprev = ds;
ds = dsnext;
if (i < end - 1) dsnext = R_GetVisSprite(i + 1);
ds = R_GetVisSprite(i);
ds->next = dsnext;
ds->prev = dsprev;
ds->linkdraw = NULL;
// Do not include this sprite, since it is completely obscured
if (ds->cut & SC_CULL)
{
continue;
}
dsnext = ds;
dsnext->linkdraw = NULL;
dsprev->next = dsnext;
dsnext->prev = dsprev;
dsprev = dsnext;
count++;
}
// Fix first and last. ds still points to the last one after the loop
dsfirst->prev = &unsorted;
unsorted.next = dsfirst;
if (ds)
{
ds->next = &unsorted;
ds->linkdraw = NULL;
}
unsorted.prev = ds;
dsnext->next = dsfirst;
dsfirst->prev = dsnext;
// bundle linkdraw
for (ds = unsorted.prev; ds != &unsorted; ds = ds->prev)
@ -2693,7 +2695,7 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e
// remove from chain
ds->next->prev = ds->prev;
ds->prev->next = ds->next;
linkedvissprites++;
count--;
if (dsfirst != &unsorted)
{
@ -2727,7 +2729,7 @@ static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 e
// pull the vissprites out by scale
vsprsortedhead->next = vsprsortedhead->prev = vsprsortedhead;
for (i = start; i < end-linkedvissprites; i++)
for (i = 0; i < count; i++)
{
bestscale = bestdispoffset = INT32_MAX;
for (ds = unsorted.next; ds != &unsorted; ds = ds->next)
@ -3142,6 +3144,7 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* portal)
fixed_t scale;
fixed_t lowscale;
INT32 silhouette;
INT32 xclip;
for (x = x1; x <= x2; x++)
{
@ -3314,7 +3317,7 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* portal)
// all clipping has been performed, so store the values - what, did you think we were drawing them NOW?
// check for unclipped columns
for (x = x1; x <= x2; x++)
for (xclip = x = x1; x <= x2; x++)
{
if (spr->clipbot[x] == CLIP_UNDEF)
spr->clipbot[x] = (INT16)viewheight;
@ -3322,9 +3325,17 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* portal)
if (spr->cliptop[x] == CLIP_UNDEF)
//Fab : 26-04-98: was -1, now clips against console bottom
spr->cliptop[x] = (INT16)con_clipviewtop;
// Sprite is completely above or below clip plane
if (spr->szt >= spr->clipbot[x] || spr->sz <= spr->cliptop[x])
xclip++;
}
if (portal)
if (xclip == x)
{
spr->cut |= SC_CULL; // completely skip this sprite going forward
}
else if (portal)
{
INT32 start_index = max(portal->start, x1);
INT32 end_index = min(portal->start + portal->end - portal->start, x2);

View file

@ -138,6 +138,7 @@ typedef enum
// srb2kart
SC_SEMIBRIGHT = 1<<12,
SC_BBOX = 1<<13,
SC_CULL = 1<<14,
// masks
SC_CUTMASK = SC_TOP|SC_BOTTOM,
SC_FLAGMASK = ~SC_CUTMASK

View file

@ -1960,6 +1960,12 @@ void I_Error(const char *error, ...)
exit(-1); // recursive errors detected
}
}
else
{
// This makes crashes funnier by stimulating the funnicampus of the brain
S_StopSounds();
S_StartSound(NULL, sfx_s3k35);
}
shutdowning = true;
@ -1989,13 +1995,10 @@ void I_Error(const char *error, ...)
D_QuitNetGame();
CL_AbortDownloadResume();
M_FreePlayerSetupColors();
I_ShutdownMusic();
I_ShutdownSound();
// use this for 1.28 19990220 by Kin
I_ShutdownGraphics();
I_ShutdownInput();
I_ShutdownSystem();
SDL_Quit();
// Implement message box with SDL_ShowSimpleMessageBox,
// which should fail gracefully if it can't put a message box up
@ -2005,6 +2008,12 @@ void I_Error(const char *error, ...)
"SRB2Kart "VERSIONSTRING" Error",
buffer, NULL);
// We wait until now to do this so the funny sound can be heard
I_ShutdownSound();
// use this for 1.28 19990220 by Kin
I_ShutdownSystem();
SDL_Quit();
// Note that SDL_ShowSimpleMessageBox does *not* require SDL to be
// initialized at the time, so calling it after SDL_Quit() is
// perfectly okay! In addition, we do this on purpose so the

View file

@ -242,7 +242,9 @@ void ST_Start(void)
ST_Stop();
ST_InitData();
st_stopped = false;
if (!dedicated)
st_stopped = false;
}
//