Merge branch 'master' of https://git.do.srb2.org/KartKrew/Kart.git into new-menus

# Conflicts:
#	src/Sourcefile
#	src/d_main.c
#	src/m_menu.c
#	src/v_video.c
#	src/v_video.h
This commit is contained in:
toaster 2022-02-14 13:10:36 +00:00
commit 87d797a45a
83 changed files with 4401 additions and 982 deletions

View file

@ -6,7 +6,7 @@ passthru_opts+=\
NONET NO_IPV6 NOHW NOMD5 NOPOSTPROCESSING\
MOBJCONSISTANCY PACKETDROP ZDEBUG\
HAVE_MINIUPNPC\
HAVE_DISCORDRPC TESTERS DEVELOP
HAVE_DISCORDRPC TESTERS HOSTTESTERS DEVELOP
# build with debugging information
ifdef DEBUGMODE

View file

@ -8,6 +8,11 @@ else
EXENAME?=srb2kart64.exe
endif
# disable dynamicbase if under msys2
ifdef MSYSTEM
libs+=-Wl,--disable-dynamicbase
endif
sources+=win32/Srb2win.rc
opts+=-DSTDC_HEADERS
libs+=-ladvapi32 -lkernel32 -lmsvcrt -luser32

View file

@ -113,4 +113,6 @@ k_hud.c
k_menudef.c
k_menufunc.c
k_menudraw.c
k_terrain.c
k_brightmap.c
k_director.c

View file

@ -5256,8 +5256,10 @@ static void SV_Maketic(void)
maketic++;
}
void TryRunTics(tic_t realtics)
boolean TryRunTics(tic_t realtics)
{
boolean ticking;
// the machine has lagged but it is not so bad
if (realtics > TICRATE/7) // FIXME: consistency failure!!
{
@ -5301,7 +5303,9 @@ void TryRunTics(tic_t realtics)
}
#endif
if (neededtic > gametic)
ticking = neededtic > gametic;
if (ticking)
{
if (realtics)
hu_stopped = false;
@ -5311,10 +5315,10 @@ void TryRunTics(tic_t realtics)
{
if (realtics)
hu_stopped = true;
return;
return false;
}
if (neededtic > gametic)
if (ticking)
{
if (advancedemo)
{
@ -5351,6 +5355,8 @@ void TryRunTics(tic_t realtics)
if (realtics)
hu_stopped = true;
}
return ticking;
}

View file

@ -488,7 +488,7 @@ boolean Playing(void);
void D_QuitNetGame(void);
//? How many ticks to run?
void TryRunTics(tic_t realtic);
boolean TryRunTics(tic_t realtic);
// extra data for lmps
// these functions scare me. they contain magic.

View file

@ -295,6 +295,8 @@ static void D_Display(void)
{
for (i = 0; i <= r_splitscreen; ++i)
{
R_SetViewContext(VIEWCONTEXT_PLAYER1 + i);
R_InterpolateViewRollAngle(rendertimefrac);
R_CheckViewMorph(i);
}
}
@ -686,6 +688,7 @@ tic_t rendergametic;
void D_SRB2Loop(void)
{
tic_t oldentertics = 0, entertic = 0, realtics = 0, rendertimeout = INFTICS;
boolean ticked;
if (dedicated)
server = true;
@ -773,11 +776,23 @@ void D_SRB2Loop(void)
realtics = 1;
// process tics (but maybe not if realtic == 0)
TryRunTics(realtics);
ticked = TryRunTics(realtics);
if (cv_frameinterpolation.value == 1 && !(paused || P_AutoPause() || hu_stopped))
if (cv_frameinterpolation.value == 1 && !(paused || P_AutoPause()))
{
fixed_t entertimefrac = I_GetTimeFrac();
static float tictime;
float entertime = I_GetTimeFrac();
fixed_t entertimefrac;
if (ticked)
tictime = entertime;
if (aproxfps < 35.0)
entertimefrac = FRACUNIT;
else
entertimefrac = FLOAT_TO_FIXED(entertime - tictime);
// renderdeltatics is a bit awkard to evaluate, since the system time interface is whole tic-based
renderdeltatics = realtics * FRACUNIT;
if (entertimefrac > rendertimefrac)
@ -1065,17 +1080,39 @@ static void IdentifyVersion(void)
// if you change the ordering of this or add/remove a file, be sure to update the md5
// checking in D_SRB2Main
#if defined (TESTERS) || defined (HOSTTESTERS)
////
#define TEXTURESNAME "MISC_TEXTURES.pk3"
#define MAPSNAME "MISC_MAPS.pk3"
#define PATCHNAME "MISC_PATCH.pk3"
#define MUSICNAME "MISC_MUSIC.PK3"
////
#else
////
#define TEXTURESNAME "textures.pk3"
#define MAPSNAME "maps.pk3"
#define PATCHNAME "patch.pk3"
#define MUSICNAME "music.pk3"
////
#endif
////
#if !defined (TESTERS) && !defined (HOSTTESTERS)
D_AddFile(startupiwads, va(pandf,srb2waddir,"gfx.pk3"));
D_AddFile(startupiwads, va(pandf,srb2waddir,"textures.pk3"));
#endif
D_AddFile(startupiwads, va(pandf,srb2waddir,TEXTURESNAME));
D_AddFile(startupiwads, va(pandf,srb2waddir,"chars.pk3"));
D_AddFile(startupiwads, va(pandf,srb2waddir,"maps.pk3"));
D_AddFile(startupiwads, va(pandf,srb2waddir,MAPSNAME));
D_AddFile(startupiwads, va(pandf,srb2waddir,"followers.pk3"));
#ifdef USE_PATCH_FILE
D_AddFile(startupiwads, va(pandf,srb2waddir,"patch.pk3"));
D_AddFile(startupiwads, va(pandf,srb2waddir,PATCHNAME));
// SPECIFIC HACK TO NEW-MENUS SO THAT MY DUMBASS STOPS FORGETTING TO ADD THE FILE (rip :youfuckedup:)
D_AddFile(startupiwads, va(pandf,srb2waddir,"newmenus.pk3"));
#endif
////
#undef TEXTURESNAME
#undef MAPSNAME
#undef PATCHNAME
#if !defined (HAVE_SDL) || defined (HAVE_MIXER)
@ -1090,8 +1127,9 @@ static void IdentifyVersion(void)
}
MUSICTEST("sounds.pk3")
MUSICTEST("music.pk3")
MUSICTEST(MUSICNAME)
#undef MUSICNAME
#undef MUSICTEST
#endif
@ -1264,6 +1302,7 @@ void D_SRB2Main(void)
// Do this up here so that WADs loaded through the command line can use ExecCfg
COM_Init();
#ifndef TESTERS
// add any files specified on the command line with -file wadfile
// to the wad list
if (!((M_GetUrlProtocolArg() || M_CheckParm("-connect")) && !M_CheckParm("-server")))
@ -1281,6 +1320,7 @@ void D_SRB2Main(void)
}
}
}
#endif
// get map from parms
@ -1315,14 +1355,18 @@ void D_SRB2Main(void)
mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_TEXTURES_PK3); // textures.pk3
mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_CHARS_PK3); // chars.pk3
mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_MAPS_PK3); // maps.pk3 -- 4 - If you touch this, make sure to touch up the majormods stuff below.
mainwads++; W_VerifyFileMd5(mainwads, ASSET_HASH_FOLLOWERS_PK3); // followers.pk3
#ifdef USE_PATCH_FILE
mainwads++; W_VerifyFileMD5(mainwads, ASSET_HASH_PATCH_PK3); // patch.pk3
#endif
#else
#if !defined (TESTERS) && !defined (HOSTTESTERS)
mainwads++; // gfx.pk3
#endif
mainwads++; // textures.pk3
mainwads++; // chars.pk3
mainwads++; // maps.pk3
mainwads++; // followers.pk3
#ifdef USE_PATCH_FILE
mainwads++; // patch.pk3
@ -1335,7 +1379,7 @@ void D_SRB2Main(void)
//
// search for maps
//
for (wadnum = 4; wadnum < 6; wadnum++) // fucking arbitrary numbers
for (wadnum = 0; wadnum <= mainwads; wadnum++)
{
lumpinfo = wadfiles[wadnum]->lumpinfo;
for (i = 0; i < wadfiles[wadnum]->numlumps; i++, lumpinfo++)

View file

@ -382,7 +382,7 @@ consvar_t cv_kartencore = CVAR_INIT ("kartencore", "Auto", CV_NETVAR|CV_CALL|CV_
static CV_PossibleValue_t kartvoterulechanges_cons_t[] = {{0, "Never"}, {1, "Sometimes"}, {2, "Frequent"}, {3, "Always"}, {0, NULL}};
consvar_t cv_kartvoterulechanges = CVAR_INIT ("kartvoterulechanges", "Frequent", CV_NETVAR, kartvoterulechanges_cons_t, NULL);
static CV_PossibleValue_t kartspeedometer_cons_t[] = {{0, "Off"}, {1, "Percentage"}, {2, "Kilometers"}, {3, "Miles"}, {4, "Fracunits"}, {0, NULL}};
consvar_t cv_kartspeedometer = CVAR_INIT ("kartdisplayspeed", "Off", CV_SAVE, kartspeedometer_cons_t, NULL); // use tics in display
consvar_t cv_kartspeedometer = CVAR_INIT ("kartdisplayspeed", "Percentage", CV_SAVE, kartspeedometer_cons_t, NULL); // use tics in display
static CV_PossibleValue_t kartvoices_cons_t[] = {{0, "Never"}, {1, "Tasteful"}, {2, "Meme"}, {0, NULL}};
consvar_t cv_kartvoices = CVAR_INIT ("kartvoices", "Tasteful", CV_SAVE, kartvoices_cons_t, NULL);
@ -423,7 +423,7 @@ consvar_t cv_kartallowgiveitem = CVAR_INIT ("kartallowgiveitem",
#endif
CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, CV_YesNo, NULL
);
consvar_t cv_kartdebugshrink = CVAR_INIT ("kartdebugshrink", "Off", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, CV_OnOff, NULL);
consvar_t cv_kartdebugdistribution = CVAR_INIT ("kartdebugdistribution", "Off", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, CV_OnOff, NULL);
consvar_t cv_kartdebughuddrop = CVAR_INIT ("kartdebughuddrop", "Off", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, CV_OnOff, NULL);
static CV_PossibleValue_t kartdebugwaypoint_cons_t[] = {{0, "Off"}, {1, "Forwards"}, {2, "Backwards"}, {0, NULL}};
@ -433,6 +433,7 @@ consvar_t cv_kartdebugbotpredict = CVAR_INIT ("kartdebugbotpredict", "Off", CV_N
consvar_t cv_kartdebugcheckpoint = CVAR_INIT ("kartdebugcheckpoint", "Off", CV_NOSHOWHELP, CV_OnOff, NULL);
consvar_t cv_kartdebugnodes = CVAR_INIT ("kartdebugnodes", "Off", CV_NOSHOWHELP, CV_OnOff, NULL);
consvar_t cv_kartdebugcolorize = CVAR_INIT ("kartdebugcolorize", "Off", CV_NOSHOWHELP, CV_OnOff, NULL);
consvar_t cv_kartdebugdirector = CVAR_INIT ("kartdebugdirector", "Off", CV_NOSHOWHELP, CV_OnOff, NULL);
static CV_PossibleValue_t votetime_cons_t[] = {{10, "MIN"}, {3600, "MAX"}, {0, NULL}};
consvar_t cv_votetime = CVAR_INIT ("votetime", "20", CV_NETVAR, votetime_cons_t, NULL);
@ -509,6 +510,8 @@ static CV_PossibleValue_t perfstats_cons_t[] = {
{0, "Off"}, {1, "Rendering"}, {2, "Logic"}, {3, "ThinkFrame"}, {0, NULL}};
consvar_t cv_perfstats = CVAR_INIT ("perfstats", "Off", 0, perfstats_cons_t, NULL);
consvar_t cv_director = CVAR_INIT ("director", "Off", 0, CV_OnOff, NULL);
char timedemo_name[256];
boolean timedemo_csv;
char timedemo_csv_id[256];
@ -735,6 +738,8 @@ void D_RegisterServerCommands(void)
CV_RegisterVar(&cv_showping);
CV_RegisterVar(&cv_showviewpointtext);
CV_RegisterVar(&cv_director);
CV_RegisterVar(&cv_dummyconsvar);
#ifdef USE_STUN
@ -929,6 +934,7 @@ void D_RegisterClientCommands(void)
for (i = 0; i < MAXSPLITSCREENPLAYERS; i++)
{
CV_RegisterVar(&cv_kickstartaccel[i]);
CV_RegisterVar(&cv_shrinkme[i]);
CV_RegisterVar(&cv_turnaxis[i]);
CV_RegisterVar(&cv_moveaxis[i]);
CV_RegisterVar(&cv_brakeaxis[i]);
@ -1630,10 +1636,13 @@ void SendWeaponPref(UINT8 n)
UINT8 buf[1];
buf[0] = 0;
// Player option cvars that need to be synched go HERE
if (cv_kickstartaccel[n].value)
buf[0] |= 1;
if (cv_shrinkme[n].value)
buf[0] |= 2;
SendNetXCmdForPlayer(n, XD_WEAPONPREF, buf, 1);
}
@ -1641,11 +1650,22 @@ static void Got_WeaponPref(UINT8 **cp,INT32 playernum)
{
UINT8 prefs = READUINT8(*cp);
// Player option cvars that need to be synched go HERE
players[playernum].pflags &= ~(PF_KICKSTARTACCEL);
players[playernum].pflags &= ~(PF_KICKSTARTACCEL|PF_SHRINKME);
if (prefs & 1)
players[playernum].pflags |= PF_KICKSTARTACCEL;
if (prefs & 2)
players[playernum].pflags |= PF_SHRINKME;
if (leveltime < 2)
{
// BAD HACK: No other place I tried to slot this in
// made it work for the host when they initally host,
// so this will have to do.
K_UpdateShrinkCheat(&players[playernum]);
}
// SEE ALSO g_demo.c
demo_extradata[playernum] |= DXD_WEAPONPREF;
}
@ -3558,7 +3578,10 @@ static void Command_Login_f(void)
boolean IsPlayerAdmin(INT32 playernum)
{
#ifdef DEVELOP
#if defined (TESTERS) || defined (HOSTTESTERS)
(void)playernum;
return false;
#elif defined (DEVELOP)
return playernum != serverplayer;
#else
INT32 i;
@ -3862,6 +3885,7 @@ static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum)
*/
static void Command_Addfile(void)
{
#ifndef TESTERS
size_t argc = COM_Argc(); // amount of arguments total
size_t curarg; // current argument index
@ -3991,6 +4015,7 @@ static void Command_Addfile(void)
else
SendNetXCmd(XD_ADDFILE, buf, buf_p - buf);
}
#endif/*TESTERS*/
}
static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)

View file

@ -86,8 +86,8 @@ extern consvar_t cv_kartusepwrlv;
extern consvar_t cv_votetime;
extern consvar_t cv_kartdebugitem, cv_kartdebugamount, cv_kartallowgiveitem, cv_kartdebugshrink, cv_kartdebugdistribution, cv_kartdebughuddrop;
extern consvar_t cv_kartdebugcheckpoint, cv_kartdebugnodes, cv_kartdebugcolorize;
extern consvar_t cv_kartdebugitem, cv_kartdebugamount, cv_kartallowgiveitem, cv_kartdebugdistribution, cv_kartdebughuddrop;
extern consvar_t cv_kartdebugcheckpoint, cv_kartdebugnodes, cv_kartdebugcolorize, cv_kartdebugdirector;
extern consvar_t cv_kartdebugwaypoints, cv_kartdebugbotpredict;
extern consvar_t cv_itemfinder;
@ -113,6 +113,8 @@ extern consvar_t cv_sleep;
extern consvar_t cv_perfstats;
extern consvar_t cv_director;
extern char timedemo_name[256];
extern boolean timedemo_csv;
extern char timedemo_csv_id[256];

View file

@ -459,7 +459,12 @@ INT32 CL_CheckFiles(void)
if (modifiedgame)
{
CONS_Debug(DBG_NETPLAY, "game is modified; only doing basic checks\n");
for (i = 0, j = mainwads+1; i < fileneedednum || j < numwadfiles;)
#ifdef DEVELOP
j = 0;
#else
j = mainwads + 1;
#endif
for (i = 0; i < fileneedednum || j < numwadfiles;)
{
if (j < numwadfiles && !wadfiles[j]->important)
{

View file

@ -59,10 +59,10 @@ typedef enum
typedef enum
{
// True if button down last tic.
PF_ATTACKDOWN = 1,
PF_ACCELDOWN = 1<<1,
PF_BRAKEDOWN = 1<<2,
PF_LOOKDOWN = 1<<3,
PF_ATTACKDOWN = 1,
PF_ACCELDOWN = 1<<1,
PF_BRAKEDOWN = 1<<2,
PF_LOOKDOWN = 1<<3,
// Accessibility and cheats
PF_KICKSTARTACCEL = 1<<4, // Is accelerate in kickstart mode?
@ -99,6 +99,9 @@ typedef enum
PF_HITFINISHLINE = 1<<26, // Already hit the finish line this tic
PF_WRONGWAY = 1<<27, // Moving the wrong way with respect to waypoints?
PF_SHRINKME = 1<<28, // "Shrink me" cheat preference
PF_SHRINKACTIVE = 1<<29, // "Shrink me" cheat is in effect. (Can't be disabled mid-race)
// up to 1<<31 is free
} pflags_t;
@ -260,6 +263,10 @@ typedef enum
// for kickstartaccel
#define ACCEL_KICKSTART 35
#define ITEMSCALE_NORMAL 0
#define ITEMSCALE_GROW 1
#define ITEMSCALE_SHRINK 2
// player_t struct for all respawn variables
typedef struct respawnvars_s
{
@ -290,6 +297,12 @@ typedef struct botvars_s
tic_t spindashconfirm; // When high enough, they will try spindashing
} botvars_t;
// player_t struct for all skybox variables
typedef struct {
mobj_t * viewpoint;
mobj_t * centerpoint;
} skybox_t;
// ========================================================================
// PLAYER STRUCTURE
// ========================================================================
@ -311,6 +324,8 @@ typedef struct player_s
// bounded/scaled total momentum.
fixed_t bob;
skybox_t skybox;
angle_t viewrollangle;
angle_t old_viewrollangle;
// camera tilt
@ -428,6 +443,7 @@ typedef struct player_s
SINT8 itemtype; // KITEM_ constant for item number
UINT8 itemamount; // Amount of said item
SINT8 throwdir; // Held dir of controls; 1 = forward, 0 = none, -1 = backward (was "player->heldDir")
UINT8 itemscale; // Item scale value, from when an item was taken out. (0 for normal, 1 for grow, 2 for shrink.)
UINT8 sadtimer; // How long you've been sad

View file

@ -5466,6 +5466,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
// SRB2kart
"MT_RANDOMITEM",
"MT_SPHEREBOX",
"MT_RANDOMITEMPOP",
"MT_FLOATINGITEM",
"MT_ITEMCAPSULE",
@ -5806,6 +5807,9 @@ const char *const MOBJFLAG_LIST[] = {
"GRENADEBOUNCE",
"RUNSPAWNFUNC",
"DONTENCOREMAP",
"PICKUPFROMBELOW",
"NOSQUISH",
"NOHITLAGFORME",
NULL
};
@ -5909,6 +5913,10 @@ const char *const PLAYERFLAG_LIST[] = {
"HITFINISHLINE", // Already hit the finish line this tic
"WRONGWAY", // Moving the wrong way with respect to waypoints?
"SHRINKME",
"SHRINKACTIVE",
NULL // stop loop here.
};
@ -6457,6 +6465,7 @@ struct int_const_s const INT_CONST[] = {
//// Masks
{"DMG_STEAL",DMG_CANTHURTSELF},
{"DMG_CANTHURTSELF",DMG_CANTHURTSELF},
{"DMG_WOMBO", DMG_WOMBO},
{"DMG_DEATHMASK",DMG_DEATHMASK},
{"DMG_TYPEMASK",DMG_TYPEMASK},

View file

@ -550,6 +550,22 @@ extern boolean capslock;
// i_system.c, replace getchar() once the keyboard has been appropriated
INT32 I_GetKey(void);
/* http://www.cse.yorku.ca/~oz/hash.html */
static inline
UINT32 quickncasehash (const char *p, size_t n)
{
size_t i = 0;
UINT32 x = 5381;
while (i < n && p[i])
{
x = (x * 33) ^ tolower(p[i]);
i++;
}
return x;
}
#ifndef min // Double-Check with WATTCP-32's cdefs.h
#define min(x, y) (((x) < (y)) ? (x) : (y))
#endif

View file

@ -346,16 +346,6 @@ static void F_IntroDrawScene(void)
// DRAW A FULL PIC INSTEAD OF FLAT!
if (intro_scenenum == 0)
{
if (finalecount == 8)
S_StartSound(NULL, sfx_vroom);
else if (finalecount == 47)
{
// Need to use M_Random otherwise it always uses the same sound
INT32 rskin = M_RandomKey(numskins);
UINT8 rtaunt = M_RandomKey(2);
sfxenum_t rsound = skins[rskin].soundsid[SKSKBST1+rtaunt];
S_StartSound(NULL, rsound);
}
background = W_CachePatchName("KARTKREW", PU_CACHE);
highres = true;
}
@ -454,6 +444,20 @@ void F_IntroTicker(void)
timetonext--;
if (intro_scenenum == 0)
{
if (finalecount == 8)
S_StartSound(NULL, sfx_vroom);
else if (finalecount == 47)
{
// Need to use M_Random otherwise it always uses the same sound
INT32 rskin = M_RandomKey(numskins);
UINT8 rtaunt = M_RandomKey(2);
sfxenum_t rsound = skins[rskin].soundsid[SKSKBST1+rtaunt];
S_StartSound(NULL, rsound);
}
}
F_WriteText();
// check for skipping

View file

@ -60,7 +60,7 @@ boolean nodrawers; // for comparative timing purposes
boolean noblit; // for comparative timing purposes
tic_t demostarttime; // for comparative timing purposes
static char demoname[128];
static char demoname[MAX_WADPATH];
static UINT8 *demobuffer = NULL;
static UINT8 *demotime_p, *demoinfo_p;
UINT8 *demo_p;
@ -122,8 +122,9 @@ demoghost *ghosts = NULL;
#define DF_ENCORE 0x40
#define DF_MULTIPLAYER 0x80 // This demo was recorded in multiplayer mode!
#define DEMO_SPECTATOR 0x40
#define DEMO_KICKSTART 0x20
#define DEMO_SPECTATOR 0x01
#define DEMO_KICKSTART 0x02
#define DEMO_SHRINKME 0x04
// For demos
#define ZT_FWD 0x01
@ -351,9 +352,20 @@ void G_ReadDemoExtraData(void)
if (extradata & DXD_WEAPONPREF)
{
i = READUINT8(demo_p);
players[p].pflags &= ~(PF_KICKSTARTACCEL);
players[p].pflags &= ~(PF_KICKSTARTACCEL|PF_SHRINKME);
if (i & 1)
players[p].pflags |= PF_KICKSTARTACCEL;
if (i & 2)
players[p].pflags |= PF_SHRINKME;
if (leveltime < 2)
{
// BAD HACK: No other place I tried to slot this in
// made it work for the host when they initally host,
// so this will have to do.
K_UpdateShrinkCheat(&players[p]);
}
//CONS_Printf("weaponpref is %d for player %d\n", i, p);
}
@ -466,6 +478,8 @@ void G_WriteDemoExtraData(void)
UINT8 prefs = 0;
if (players[i].pflags & PF_KICKSTARTACCEL)
prefs |= 1;
if (players[i].pflags & PF_SHRINKME)
prefs |= 2;
WRITEUINT8(demo_p, prefs);
}
}
@ -2015,12 +2029,15 @@ void G_BeginRecording(void)
for (p = 0; p < MAXPLAYERS; p++) {
if (playeringame[p]) {
player = &players[p];
WRITEUINT8(demo_p, p);
i = p;
if (player->pflags & PF_KICKSTARTACCEL)
i |= DEMO_KICKSTART;
i = 0;
if (player->spectator)
i |= DEMO_SPECTATOR;
if (player->pflags & PF_KICKSTARTACCEL)
i |= DEMO_KICKSTART;
if (player->pflags & PF_SHRINKME)
i |= DEMO_SHRINKME;
WRITEUINT8(demo_p, i);
// Name
@ -2672,7 +2689,7 @@ void G_DoPlayDemo(char *defdemoname)
UINT32 randseed;
char msg[1024];
boolean spectator, kickstart;
boolean spectator;
UINT8 slots[MAXPLAYERS], kartspeed[MAXPLAYERS], kartweight[MAXPLAYERS], numslots = 0;
#if defined(SKIPERRORS) && !defined(DEVELOP)
@ -2943,10 +2960,12 @@ void G_DoPlayDemo(char *defdemoname)
while (p != 0xFF)
{
if ((spectator = !!(p & DEMO_SPECTATOR)))
{
p &= ~DEMO_SPECTATOR;
UINT8 flags = READUINT8(demo_p);
spectator = !!(flags & DEMO_SPECTATOR);
if (spectator == true)
{
if (modeattacking)
{
snprintf(msg, 1024, M_GetText("%s is a Record Attack replay with spectators, and is thus invalid.\n"), pdemoname);
@ -2960,10 +2979,8 @@ void G_DoPlayDemo(char *defdemoname)
}
}
if ((kickstart = (p & DEMO_KICKSTART)))
p &= ~DEMO_KICKSTART;
slots[numslots] = p; numslots++;
slots[numslots] = p;
numslots++;
if (modeattacking && numslots > 1)
{
@ -2982,11 +2999,19 @@ void G_DoPlayDemo(char *defdemoname)
playeringame[p] = true;
players[p].spectator = spectator;
if (kickstart)
if (flags & DEMO_KICKSTART)
players[p].pflags |= PF_KICKSTARTACCEL;
else
players[p].pflags &= ~PF_KICKSTARTACCEL;
if (flags & DEMO_SHRINKME)
players[p].pflags |= PF_SHRINKME;
else
players[p].pflags &= ~PF_SHRINKME;
K_UpdateShrinkCheat(&players[p]);
// Name
M_Memcpy(player_names[p],demo_p,16);
demo_p += 16;
@ -3245,7 +3270,10 @@ void G_AddGhost(char *defdemoname)
return;
}
if ((READUINT8(p) & ~DEMO_KICKSTART) != 0)
p++; // player number - doesn't really need to be checked, TODO maybe support adding multiple players' ghosts at once
// any invalidating flags?
if ((READUINT8(p) & (DEMO_SPECTATOR)) != 0)
{
CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot.\n"), pdemoname);
Z_Free(pdemoname);
@ -3791,7 +3819,7 @@ void G_SaveDemo(void)
demo_slug[strindex] = 0;
if (dash) demo_slug[strindex-1] = 0;
writepoint = strstr(demoname, "-") + 1;
writepoint = strstr(strrchr(demoname, *PATHSEP), "-") + 1;
demo_slug[128 - (writepoint - demoname) - 4] = 0;
sprintf(writepoint, "%s.lmp", demo_slug);
}
@ -3808,7 +3836,7 @@ void G_SaveDemo(void)
md5_buffer((char *)p+16, (demobuffer + length) - (p+16), p);
#endif
if (FIL_WriteFile(va(pandf, srb2home, demoname), demobuffer, demo_p - demobuffer)) // finally output the file.
if (FIL_WriteFile(demoname, demobuffer, demo_p - demobuffer)) // finally output the file.
demo.savemode = DSM_SAVED;
free(demobuffer);
demo.recording = false;

View file

@ -261,7 +261,7 @@ INT32 stealtime = TICRATE/2;
INT32 sneakertime = TICRATE + (TICRATE/3);
INT32 itemtime = 8*TICRATE;
INT32 bubbletime = TICRATE/2;
INT32 comebacktime = 10*TICRATE;
INT32 comebacktime = 3*TICRATE;
INT32 bumptime = 6;
INT32 greasetics = 3*TICRATE;
INT32 wipeoutslowtime = 20;
@ -342,10 +342,10 @@ INT16 prevmap, nextmap;
static UINT8 *savebuffer;
static void kickstartaccel_OnChange(void);
static void kickstartaccel2_OnChange(void);
static void kickstartaccel3_OnChange(void);
static void kickstartaccel4_OnChange(void);
static void weaponPrefChange(void);
static void weaponPrefChange2(void);
static void weaponPrefChange3(void);
static void weaponPrefChange4(void);
static CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"},
{1, "X-Axis"}, {2, "Y-Axis"}, {-1, "X-Axis-"}, {-2, "Y-Axis-"},
@ -406,10 +406,17 @@ consvar_t cv_resetspecialmusic = CVAR_INIT ("resetspecialmusic", "Yes", CV_SAVE,
consvar_t cv_resume = CVAR_INIT ("resume", "Yes", CV_SAVE, CV_YesNo, NULL);
consvar_t cv_kickstartaccel[MAXSPLITSCREENPLAYERS] = {
CVAR_INIT ("kickstartaccel", "Off", CV_SAVE|CV_CALL, CV_OnOff, kickstartaccel_OnChange),
CVAR_INIT ("kickstartaccel2", "Off", CV_SAVE|CV_CALL, CV_OnOff, kickstartaccel2_OnChange),
CVAR_INIT ("kickstartaccel3", "Off", CV_SAVE|CV_CALL, CV_OnOff, kickstartaccel3_OnChange),
CVAR_INIT ("kickstartaccel4", "Off", CV_SAVE|CV_CALL, CV_OnOff, kickstartaccel4_OnChange)
CVAR_INIT ("kickstartaccel", "Off", CV_SAVE|CV_CALL, CV_OnOff, weaponPrefChange),
CVAR_INIT ("kickstartaccel2", "Off", CV_SAVE|CV_CALL, CV_OnOff, weaponPrefChange2),
CVAR_INIT ("kickstartaccel3", "Off", CV_SAVE|CV_CALL, CV_OnOff, weaponPrefChange3),
CVAR_INIT ("kickstartaccel4", "Off", CV_SAVE|CV_CALL, CV_OnOff, weaponPrefChange4)
};
consvar_t cv_shrinkme[MAXSPLITSCREENPLAYERS] = {
CVAR_INIT ("shrinkme", "Off", CV_CALL, CV_OnOff, weaponPrefChange),
CVAR_INIT ("shrinkme2", "Off", CV_CALL, CV_OnOff, weaponPrefChange2),
CVAR_INIT ("shrinkme3", "Off", CV_CALL, CV_OnOff, weaponPrefChange3),
CVAR_INIT ("shrinkme4", "Off", CV_CALL, CV_OnOff, weaponPrefChange4)
};
consvar_t cv_turnaxis[MAXSPLITSCREENPLAYERS] = {
@ -1185,22 +1192,22 @@ ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n)
return dest;
}
static void kickstartaccel_OnChange(void)
static void weaponPrefChange(void)
{
SendWeaponPref(0);
}
static void kickstartaccel2_OnChange(void)
static void weaponPrefChange2(void)
{
SendWeaponPref(1);
}
static void kickstartaccel3_OnChange(void)
static void weaponPrefChange3(void)
{
SendWeaponPref(2);
}
static void kickstartaccel4_OnChange(void)
static void weaponPrefChange4(void)
{
SendWeaponPref(3);
}
@ -2165,7 +2172,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
botdiffincrease = players[player].botvars.diffincrease;
botrival = players[player].botvars.rival;
pflags = (players[player].pflags & (PF_WANTSTOJOIN|PF_KICKSTARTACCEL));
pflags = (players[player].pflags & (PF_WANTSTOJOIN|PF_KICKSTARTACCEL|PF_SHRINKME|PF_SHRINKACTIVE));
// SRB2kart
if (betweenmaps || leveltime < introtime)
@ -2236,7 +2243,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
if (!(netgame || multiplayer))
pflags |= (players[player].pflags & (PF_GODMODE|PF_NOCLIP));
// Obliterate follower from existence
P_SetTarget(&players[player].follower, NULL);

View file

@ -55,6 +55,8 @@ extern consvar_t cv_pauseifunfocused;
extern consvar_t cv_invertmouse;
extern consvar_t cv_kickstartaccel[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_shrinkme[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_turnaxis[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_moveaxis[MAXSPLITSCREENPLAYERS];
extern consvar_t cv_brakeaxis[MAXSPLITSCREENPLAYERS];

View file

@ -40,9 +40,12 @@
#include "../r_things.h" // R_GetShadowZ
#include "../d_main.h"
#include "../p_slopes.h"
#include "../k_kart.h" // HITLAGJITTERS
#include "hw_md2.h"
// SRB2Kart
#include "../k_kart.h" // HITLAGJITTERS
#include "../r_fps.h"
#ifdef NEWCLIP
#include "hw_clip.h"
#endif
@ -178,6 +181,18 @@ boolean gl_shadersavailable = true;
// Lighting
// ==========================================================================
boolean HWR_OverrideObjectLightLevel(mobj_t *thing, INT32 *lightlevel)
{
if (R_ThingIsFullBright(thing))
*lightlevel = 255;
else if (R_ThingIsFullDark(thing))
*lightlevel = 0;
else
return false;
return true;
}
void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap)
{
RGBA_t poly_color, tint_color, fade_color;
@ -3641,17 +3656,9 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
fixed_t slopez;
pslope_t *groundslope;
fixed_t interpx = thing->x;
fixed_t interpy = thing->y;
fixed_t interpz = thing->z;
// do interpolation
if (cv_frameinterpolation.value == 1)
{
interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x);
interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y);
interpz = thing->old_z + FixedMul(rendertimefrac, thing->z - thing->old_z);
}
fixed_t interpx = R_InterpolateFixed(thing->old_x, thing->x);
fixed_t interpy = R_InterpolateFixed(thing->old_y, thing->y);
fixed_t interpz = R_InterpolateFixed(thing->old_z, thing->z);
// hitlag vibrating (todo: interp somehow?)
if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG))
@ -3673,7 +3680,7 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale)
interpy += thing->spryoff;
interpz += thing->sprzoff;
groundz = R_GetShadowZ(thing, &groundslope);
groundz = R_GetShadowZ(thing, &groundslope, interpx, interpy, interpz);
gpatch = (patch_t *)W_CachePatchName("DSHADOW", PU_SPRITE);
if (!(gpatch && ((GLPatch_t *)gpatch->hardware)->mipmap->format)) return;
@ -3800,7 +3807,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
patch_t *gpatch;
FSurfaceInfo Surf;
extracolormap_t *colormap = NULL;
FUINT lightlevel;
INT32 lightlevel;
boolean lightset = true;
FBITFIELD blend = 0;
FBITFIELD occlusion;
@ -3930,18 +3937,13 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
// Start with the lightlevel and colormap from the top of the sprite
lightlevel = *list[sector->numlights - 1].lightlevel;
if (!(spr->mobj->renderflags & RF_NOCOLORMAPS))
if (!R_ThingIsFullBright(spr->mobj) && !(spr->mobj->renderflags & RF_NOCOLORMAPS))
colormap = *list[sector->numlights - 1].extra_colormap;
i = 0;
temp = FLOAT_TO_FIXED(realtop);
if (R_ThingIsFullBright(spr->mobj))
lightlevel = 255;
else if (R_ThingIsFullDark(spr->mobj))
lightlevel = 0;
else
lightset = false;
lightset = HWR_OverrideObjectLightLevel(spr->mobj, &lightlevel);
for (i = 1; i < sector->numlights; i++)
{
@ -3950,7 +3952,7 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
{
if (!lightset)
lightlevel = *list[i-1].lightlevel > 255 ? 255 : *list[i-1].lightlevel;
if (!(spr->mobj->renderflags & RF_NOCOLORMAPS))
if (!R_ThingIsFullBright(spr->mobj) && !(spr->mobj->renderflags & RF_NOCOLORMAPS))
colormap = *list[i-1].extra_colormap;
break;
}
@ -3968,8 +3970,14 @@ static void HWR_SplitSprite(gl_vissprite_t *spr)
if (!(list[i].flags & FF_NOSHADE) && (list[i].flags & FF_CUTSPRITES))
{
if (!lightset)
{
lightlevel = *list[i].lightlevel > 255 ? 255 : *list[i].lightlevel;
if (!(spr->mobj->renderflags & RF_NOCOLORMAPS))
if (R_ThingIsSemiBright(spr->mobj))
lightlevel = 128 + (lightlevel>>1);
}
if (!R_ThingIsFullBright(spr->mobj) && !(spr->mobj->renderflags & RF_NOCOLORMAPS))
colormap = *list[i].extra_colormap;
}
@ -4284,18 +4292,11 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
// colormap test
{
sector_t *sector = spr->mobj->subsector->sector;
UINT8 lightlevel = 0;
boolean lightset = true;
INT32 lightlevel = 0;
boolean lightset = HWR_OverrideObjectLightLevel(spr->mobj, &lightlevel);
extracolormap_t *colormap = NULL;
if (R_ThingIsFullBright(spr->mobj))
lightlevel = 255;
else if (R_ThingIsFullDark(spr->mobj))
lightlevel = 0;
else
lightset = false;
if (!(spr->mobj->renderflags & RF_NOCOLORMAPS))
if (!R_ThingIsFullBright(spr->mobj) && !(spr->mobj->renderflags & RF_NOCOLORMAPS))
colormap = sector->extra_colormap;
if (splat && sector->numlights)
@ -4305,7 +4306,7 @@ static void HWR_DrawSprite(gl_vissprite_t *spr)
if (!lightset)
lightlevel = *sector->lightlist[light].lightlevel > 255 ? 255 : *sector->lightlist[light].lightlevel;
if (*sector->lightlist[light].extra_colormap && !(spr->mobj->renderflags & RF_NOCOLORMAPS))
if (!R_ThingIsFullBright(spr->mobj) && *sector->lightlist[light].extra_colormap && !(spr->mobj->renderflags & RF_NOCOLORMAPS))
colormap = *sector->lightlist[light].extra_colormap;
}
else if (!lightset)
@ -5084,25 +5085,18 @@ static void HWR_ProjectSprite(mobj_t *thing)
dispoffset = thing->info->dispoffset;
interpx = thing->x;
interpy = thing->y;
interpz = thing->z;
interpangle = (thing->player ? thing->player->drawangle : thing->angle);
interpx = R_InterpolateFixed(thing->old_x, thing->x);
interpy = R_InterpolateFixed(thing->old_y, thing->y);
interpz = R_InterpolateFixed(thing->old_z, thing->z);
interpangle = ANGLE_MAX;
if (cv_frameinterpolation.value == 1)
if (thing->player)
{
interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x);
interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y);
interpz = thing->old_z + FixedMul(rendertimefrac, thing->z - thing->old_z);
if (thing->player)
{
interpangle = thing->player->old_drawangle + FixedMul(rendertimefrac, thing->player->drawangle - thing->player->old_drawangle);
}
else
{
interpangle = thing->old_angle + FixedMul(rendertimefrac, thing->angle - thing->old_angle);
}
interpangle = R_InterpolateAngle(thing->player->old_drawangle, thing->player->drawangle);
}
else
{
interpangle = R_InterpolateAngle(thing->old_angle, thing->angle);
}
// hitlag vibrating (todo: interp somehow?)
@ -5307,7 +5301,7 @@ static void HWR_ProjectSprite(mobj_t *thing)
if (caster && !P_MobjWasRemoved(caster))
{
fixed_t groundz = R_GetShadowZ(thing, NULL);
fixed_t groundz = R_GetShadowZ(thing, NULL, interpx, interpy, interpz);
fixed_t floordiff = abs(((thing->eflags & MFE_VERTICALFLIP) ? caster->height : 0) + caster->z - groundz);
shadowheight = FIXED_TO_FLOAT(floordiff);
@ -5526,17 +5520,9 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
if (!thing)
return;
interpx = thing->x;
interpy = thing->y;
interpz = thing->z;
// do interpolation
if (cv_frameinterpolation.value == 1)
{
interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x);
interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y);
interpz = thing->old_z + FixedMul(rendertimefrac, thing->z - thing->old_z);
}
interpx = R_InterpolateFixed(thing->old_x, thing->x);
interpy = R_InterpolateFixed(thing->old_y, thing->y);
interpz = R_InterpolateFixed(thing->old_z, thing->z);
// transform the origin point
tr_x = FIXED_TO_FLOAT(interpx) - gl_viewx;
@ -6241,7 +6227,7 @@ void HWR_RenderPlayerView(void)
const float fpov = FIXED_TO_FLOAT(cv_fov[viewssnum].value+player->fovadd);
postimg_t *type = &postimgtype[viewssnum];
const boolean skybox = (skyboxmo[0] && cv_skybox.value); // True if there's a skybox object and skyboxes are on
const boolean skybox = (player->skybox.viewpoint && cv_skybox.value); // True if there's a skybox object and skyboxes are on
FRGBAFloat ClearColor;
@ -6772,7 +6758,6 @@ void HWR_DoPostProcessor(player_t *player)
// 10 by 10 grid. 2 coordinates (xy)
float v[SCREENVERTS][SCREENVERTS][2];
static double disStart = 0;
static fixed_t last_fractime = 0;
UINT8 x, y;
INT32 WAVELENGTH;
@ -6782,15 +6767,15 @@ void HWR_DoPostProcessor(player_t *player)
// Modifies the wave.
if (*type == postimg_water)
{
WAVELENGTH = 20; // Lower is longer
AMPLITUDE = 20; // Lower is bigger
FREQUENCY = 16; // Lower is faster
WAVELENGTH = 5;
AMPLITUDE = 20;
FREQUENCY = 8;
}
else
{
WAVELENGTH = 10; // Lower is longer
AMPLITUDE = 30; // Lower is bigger
FREQUENCY = 4; // Lower is faster
WAVELENGTH = 10;
AMPLITUDE = 60;
FREQUENCY = 4;
}
for (x = 0; x < SCREENVERTS; x++)
@ -6804,16 +6789,7 @@ void HWR_DoPostProcessor(player_t *player)
}
HWD.pfnPostImgRedraw(v);
if (!(paused || P_AutoPause()))
disStart += 1;
if (renderdeltatics > FRACUNIT)
{
disStart = disStart - FIXED_TO_FLOAT(last_fractime) + 1 + FIXED_TO_FLOAT(rendertimefrac);
}
else
{
disStart = disStart - FIXED_TO_FLOAT(last_fractime) + FIXED_TO_FLOAT(rendertimefrac);
}
last_fractime = rendertimefrac;
disStart += FIXED_TO_FLOAT(renderdeltatics);
// Capture the screen again for screen waving on the intermission
if(gamestate != GS_INTERMISSION)

View file

@ -67,6 +67,7 @@ void HWR_MakeScreenFinalTexture(void);
void HWR_DrawScreenFinalTexture(int width, int height);
// This stuff is put here so models can use them
boolean HWR_OverrideObjectLightLevel(mobj_t *thing, INT32 *lightlevel);
void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap);
UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work

View file

@ -46,6 +46,7 @@
// SRB2Kart
#include "../k_color.h"
#include "../k_kart.h" // HITLAGJITTERS
#include "../r_fps.h"
#ifdef HAVE_PNG
@ -1323,7 +1324,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
if (spr->mobj->subsector)
{
sector_t *sector = spr->mobj->subsector->sector;
UINT8 lightlevel = 255;
INT32 lightlevel = 255;
boolean lightset = HWR_OverrideObjectLightLevel(spr->mobj, &lightlevel);
extracolormap_t *colormap = NULL;
if (sector->numlights)
@ -1332,22 +1334,22 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
light = R_GetPlaneLight(sector, spr->mobj->z + spr->mobj->height, false); // Always use the light at the top instead of whatever I was doing before
if (!R_ThingIsFullBright(spr->mobj))
if (!lightset)
lightlevel = *sector->lightlist[light].lightlevel > 255 ? 255 : *sector->lightlist[light].lightlevel;
if (*sector->lightlist[light].extra_colormap)
if (!R_ThingIsFullBright(spr->mobj) && *sector->lightlist[light].extra_colormap)
colormap = *sector->lightlist[light].extra_colormap;
}
else
else if (!lightset)
{
if (!R_ThingIsFullBright(spr->mobj))
lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel;
lightlevel = sector->lightlevel > 255 ? 255 : sector->lightlevel;
if (sector->extra_colormap)
colormap = sector->extra_colormap;
}
//lightlevel = 128 + (lightlevel>>1);
if (R_ThingIsSemiBright(spr->mobj))
lightlevel = 128 + (lightlevel>>1);
HWR_Lighting(&Surf, lightlevel, colormap);
}
@ -1368,17 +1370,9 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
INT32 mod;
float finalscale;
fixed_t interpx = spr->mobj->x;
fixed_t interpy = spr->mobj->y;
fixed_t interpz = spr->mobj->z;
// do interpolation
if (cv_frameinterpolation.value == 1)
{
interpx = spr->mobj->old_x + FixedMul(rendertimefrac, spr->mobj->x - spr->mobj->old_x);
interpy = spr->mobj->old_y + FixedMul(rendertimefrac, spr->mobj->y - spr->mobj->old_y);
interpz = spr->mobj->old_z + FixedMul(rendertimefrac, spr->mobj->z - spr->mobj->old_z);
}
fixed_t interpx = R_InterpolateFixed(spr->mobj->old_x, spr->mobj->x);
fixed_t interpy = R_InterpolateFixed(spr->mobj->old_y, spr->mobj->y);
fixed_t interpz = R_InterpolateFixed(spr->mobj->old_z, spr->mobj->z);
// hitlag vibrating
if (spr->mobj->hitlag > 0 && (spr->mobj->eflags & MFE_DAMAGEHITLAG))
@ -1636,10 +1630,16 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
if (sprframe->rotate || papersprite)
{
fixed_t anglef = AngleFixed(spr->mobj->angle);
fixed_t anglef = INT32_MAX;
if (spr->mobj->player)
anglef = AngleFixed(spr->mobj->player->drawangle);
{
anglef = AngleFixed(R_InterpolateAngle(spr->mobj->player->old_drawangle, spr->mobj->player->drawangle));
}
else
{
anglef = AngleFixed(R_InterpolateAngle(spr->mobj->old_angle, spr->mobj->angle));
}
p.angley = FIXED_TO_FLOAT(anglef);
}
@ -1671,8 +1671,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
}
}
p.anglez = FIXED_TO_FLOAT(AngleFixed(spr->mobj->pitch));
p.anglex = FIXED_TO_FLOAT(AngleFixed(spr->mobj->roll));
p.anglez = FIXED_TO_FLOAT(AngleFixed(R_InterpolateAngle(spr->mobj->old_pitch, spr->mobj->pitch)));
p.anglex = FIXED_TO_FLOAT(AngleFixed(R_InterpolateAngle(spr->mobj->old_roll, spr->mobj->roll)));
// SRB2CBTODO: MD2 scaling support
finalscale *= FIXED_TO_FLOAT(spr->mobj->scale);

View file

@ -56,6 +56,7 @@
#include "k_kart.h"
#include "k_color.h"
#include "k_hud.h"
#include "r_fps.h"
// coords are scaled
#define HU_INPUTX 0
@ -165,6 +166,8 @@ static tic_t cechotimer = 0;
static tic_t cechoduration = 5*TICRATE;
static INT32 cechoflags = 0;
static tic_t resynch_ticker = 0;
//======================================================================
// HEADS UP INIT
//======================================================================
@ -908,6 +911,60 @@ static inline boolean HU_keyInChatString(char *s, char ch)
//
//
static void HU_TickSongCredits(void)
{
if (cursongcredit.def == NULL) // No def
{
cursongcredit.x = cursongcredit.old_x = 0;
cursongcredit.anim = 0;
cursongcredit.trans = NUMTRANSMAPS;
return;
}
cursongcredit.old_x = cursongcredit.x;
if (cursongcredit.anim > 0)
{
char *str = va("\x1F"" %s", cursongcredit.def->source);
INT32 len = V_ThinStringWidth(str, V_ALLOWLOWERCASE|V_6WIDTHSPACE);
fixed_t destx = (len+7) * FRACUNIT;
if (cursongcredit.trans > 0)
{
cursongcredit.trans--;
}
if (cursongcredit.x < destx)
{
cursongcredit.x += (destx - cursongcredit.x) / 2;
}
if (cursongcredit.x > destx)
{
cursongcredit.x = destx;
}
cursongcredit.anim--;
}
else
{
if (cursongcredit.trans < NUMTRANSMAPS)
{
cursongcredit.trans++;
}
if (cursongcredit.x > 0)
{
cursongcredit.x /= 2;
}
if (cursongcredit.x < 0)
{
cursongcredit.x = 0;
}
}
}
void HU_Ticker(void)
{
if (dedicated)
@ -922,6 +979,49 @@ void HU_Ticker(void)
hu_showscores = false;
hu_keystrokes = false;
if (chat_on)
{
// count down the scroll timer.
if (chat_scrolltime > 0)
chat_scrolltime--;
}
else
{
chat_scrolltime = 0;
}
if (netgame) // would handle that in hu_drawminichat, but it's actually kinda awkward when you're typing a lot of messages. (only handle that in netgames duh)
{
size_t i = 0;
// handle spam while we're at it:
for(; (i<MAXPLAYERS); i++)
{
if (stop_spamming[i] > 0)
stop_spamming[i]--;
}
// handle chat timers
for (i=0; (i<chat_nummsg_min); i++)
{
if (chat_timers[i] > 0)
chat_timers[i]--;
else
HU_removeChatText_Mini();
}
}
cechotimer--;
if (gamestate != GS_LEVEL)
{
return;
}
resynch_ticker++;
HU_TickSongCredits();
}
#ifndef NONET
@ -1903,8 +2003,6 @@ static void HU_DrawCEcho(void)
echoptr = line;
echoptr++;
}
--cechotimer;
}
//
@ -1954,42 +2052,28 @@ static void HU_DrawDemoInfo(void)
void HU_DrawSongCredits(void)
{
char *str;
INT32 len, destx;
INT32 y = (r_splitscreen ? (BASEVIDHEIGHT/2)-4 : 32);
fixed_t x;
fixed_t y = (r_splitscreen ? (BASEVIDHEIGHT/2)-4 : 32) * FRACUNIT;
INT32 bgt;
if (!cursongcredit.def) // No def
{
return;
}
str = va("\x1F"" %s", cursongcredit.def->source);
len = V_ThinStringWidth(str, V_ALLOWLOWERCASE|V_6WIDTHSPACE);
destx = (len+7);
bgt = (NUMTRANSMAPS/2) + (cursongcredit.trans / 2);
x = R_InterpolateFixed(cursongcredit.old_x, cursongcredit.x);
if (cursongcredit.anim)
{
if (cursongcredit.trans > 0)
cursongcredit.trans--;
if (cursongcredit.x < destx)
cursongcredit.x += (destx - cursongcredit.x) / 2;
if (cursongcredit.x > destx)
cursongcredit.x = destx;
cursongcredit.anim--;
}
else
{
if (cursongcredit.trans < NUMTRANSMAPS)
cursongcredit.trans++;
if (cursongcredit.x > 0)
cursongcredit.x /= 2;
if (cursongcredit.x < 0)
cursongcredit.x = 0;
}
bgt = (NUMTRANSMAPS/2)+(cursongcredit.trans/2);
if (bgt < NUMTRANSMAPS)
V_DrawScaledPatch(cursongcredit.x, y-2, V_SNAPTOLEFT|(bgt<<V_ALPHASHIFT), songcreditbg);
{
V_DrawFixedPatch(x, y - (2 * FRACUNIT), FRACUNIT, V_SNAPTOLEFT|(bgt<<V_ALPHASHIFT), songcreditbg, NULL);
}
if (cursongcredit.trans < NUMTRANSMAPS)
V_DrawRightAlignedThinString(cursongcredit.x, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE|V_SNAPTOLEFT|(cursongcredit.trans<<V_ALPHASHIFT), str);
{
V_DrawRightAlignedThinStringAtFixed(x, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE|V_SNAPTOLEFT|(cursongcredit.trans<<V_ALPHASHIFT), str);
}
}
@ -2004,9 +2088,6 @@ void HU_Drawer(void)
// draw chat string plus cursor
if (chat_on)
{
// count down the scroll timer.
if (chat_scrolltime > 0)
chat_scrolltime--;
if (!OLDCHAT)
HU_DrawChat();
else
@ -2015,31 +2096,9 @@ void HU_Drawer(void)
else
{
typelines = 1;
chat_scrolltime = 0;
if (!OLDCHAT && cv_consolechat.value < 2 && netgame) // Don't display minimized chat if you set the mode to Window (Hidden)
HU_drawMiniChat(); // draw messages in a cool fashion.
}
if (netgame) // would handle that in hu_drawminichat, but it's actually kinda awkward when you're typing a lot of messages. (only handle that in netgames duh)
{
size_t i = 0;
// handle spam while we're at it:
for(; (i<MAXPLAYERS); i++)
{
if (stop_spamming[i] > 0)
stop_spamming[i]--;
}
// handle chat timers
for (i=0; (i<chat_nummsg_min); i++)
{
if (chat_timers[i] > 0)
chat_timers[i]--;
else
HU_removeChatText_Mini();
}
}
#endif
if (cechotimer)
@ -2078,12 +2137,10 @@ void HU_Drawer(void)
// draw desynch text
if (hu_redownloadinggamestate)
{
static UINT32 resynch_ticker = 0;
char resynch_text[14];
UINT32 i;
// Animate the dots
resynch_ticker++;
strcpy(resynch_text, "Resynching");
for (i = 0; i < (resynch_ticker / 16) % 4; i++)
strcat(resynch_text, ".");

View file

@ -46,9 +46,9 @@ UINT32 I_GetFreeMem(UINT32 *total);
*/
tic_t I_GetTime(void);
/** \brief Get the current time as a fraction of a tic since the last tic.
/** \brief Get the current time in tics including fractions.
*/
fixed_t I_GetTimeFrac(void);
float I_GetTimeFrac(void);
/** \brief Returns precise time value for performance measurement.
*/

View file

@ -9295,7 +9295,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
4, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_SCENERY|MF_NOCLIPHEIGHT, // flags
MF_NOBLOCKMAP|MF_SCENERY|MF_NOCLIPHEIGHT|MF_NOHITLAGFORME, // flags
S_NULL // raisestate
},
@ -9322,7 +9322,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
4, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SCENERY|MF_NOCLIPHEIGHT|MF_PAPERCOLLISION, // flags
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SCENERY|MF_NOCLIPHEIGHT|MF_PAPERCOLLISION|MF_NOHITLAGFORME, // flags
S_NULL // raisestate
},
@ -9349,7 +9349,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
4, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPTHING, // flags
MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPTHING|MF_NOHITLAGFORME, // flags
S_NULL // raisestate
},

View file

@ -235,7 +235,7 @@ mobj_t *K_SpawnSphereBox(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8 f
(void)amount;
drop->angle = angle;
P_InitAngle(drop, angle);
P_Thrust(drop,
FixedAngle(P_RandomFixed() * 180) + angle,
P_RandomRange(4, 12) * mapobjectscale);
@ -469,16 +469,15 @@ void K_RunPaperItemSpawners(void)
firstUnspawnedEmerald
);
}
else if (P_RandomChance(FRACUNIT/3))
else
{
drop = K_SpawnSphereBox(
spotList[r]->x, spotList[r]->y, spotList[r]->z + (128 * mapobjectscale * flip),
FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip,
10
);
}
else
{
K_FlipFromObject(drop, spotList[r]);
drop = K_CreatePaperItem(
spotList[r]->x, spotList[r]->y, spotList[r]->z + (128 * mapobjectscale * flip),
FixedAngle(P_RandomRange(0, 359) * FRACUNIT), flip,
@ -529,7 +528,7 @@ static void K_SpawnOvertimeLaser(fixed_t x, fixed_t y, fixed_t scale)
mo->eflags |= MFE_VERTICALFLIP;
}
mo->angle = R_PointToAngle2(mo->x, mo->y, battleovertime.x, battleovertime.y) + ANGLE_90;
P_InitAngle(mo, R_PointToAngle2(mo->x, mo->y, battleovertime.x, battleovertime.y) + ANGLE_90);
mo->renderflags |= (RF_DONTDRAW & ~(K_GetPlayerDontDrawFlag(player)));
P_SetScale(mo, scale);

View file

@ -662,7 +662,10 @@ fixed_t K_DistanceOfLineFromPoint(fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t
--------------------------------------------------*/
static botprediction_t *K_CreateBotPrediction(player_t *player)
{
const INT16 handling = K_GetKartTurnValue(player, KART_FULLTURN); // Reduce prediction based on how fast you can turn
// Stair janking makes it harder to steer, so attempt to steer harder.
const UINT8 jankDiv = (player->stairjank > 0 ? 2 : 1);
const INT16 handling = K_GetKartTurnValue(player, KART_FULLTURN) / jankDiv; // Reduce prediction based on how fast you can turn
const INT16 normal = KART_FULLTURN; // "Standard" handling to compare to
const tic_t futuresight = (TICRATE * normal) / max(1, handling); // How far ahead into the future to try and predict

View file

@ -382,6 +382,8 @@ static void K_BotItemGenericTap(player_t *player, ticcmd_t *cmd)
--------------------------------------------------*/
static boolean K_BotRevealsGenericTrap(player_t *player, INT16 turnamt, boolean mine)
{
const fixed_t coneDist = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed));
if (abs(turnamt) >= KART_FULLTURN/2)
{
// DON'T reveal on turns, we can place bananas on turns whenever we have multiple to spare,
@ -404,7 +406,7 @@ static boolean K_BotRevealsGenericTrap(player_t *player, INT16 turnamt, boolean
}
// Check your behind.
if (K_PlayerInCone(player, player->mo->radius * 16, 10, true) != NULL)
if (K_PlayerInCone(player, coneDist, 15, true) != NULL)
{
return true;
}
@ -536,16 +538,19 @@ static void K_BotItemRocketSneaker(player_t *player, ticcmd_t *cmd)
--------------------------------------------------*/
static void K_BotItemBanana(player_t *player, ticcmd_t *cmd, INT16 turnamt)
{
const fixed_t coneDist = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed));
SINT8 throwdir = -1;
boolean tryLookback = false;
player_t *target = NULL;
player->botvars.itemconfirm++;
target = K_PlayerInCone(player, player->mo->radius * 16, 10, true);
target = K_PlayerInCone(player, coneDist, 15, true);
if (target != NULL)
{
K_ItemConfirmForTarget(player, target, player->botvars.difficulty);
throwdir = -1;
tryLookback = true;
}
if (abs(turnamt) >= KART_FULLTURN/2)
@ -564,7 +569,12 @@ static void K_BotItemBanana(player_t *player, ticcmd_t *cmd, INT16 turnamt)
}
}
if (player->botvars.itemconfirm > 2*TICRATE || player->bananadrag >= TICRATE)
if (tryLookback == true && throwdir == -1)
{
cmd->buttons |= BT_LOOKBACK;
}
if (player->botvars.itemconfirm > 10*TICRATE || player->bananadrag >= TICRATE)
{
K_BotGenericPressItem(player, cmd, throwdir);
}
@ -585,12 +595,14 @@ static void K_BotItemBanana(player_t *player, ticcmd_t *cmd, INT16 turnamt)
--------------------------------------------------*/
static void K_BotItemMine(player_t *player, ticcmd_t *cmd, INT16 turnamt)
{
const fixed_t coneDist = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed));
SINT8 throwdir = 0;
boolean tryLookback = false;
player_t *target = NULL;
player->botvars.itemconfirm++;
target = K_PlayerInCone(player, player->mo->radius * 16, 10, true);
target = K_PlayerInCone(player, coneDist, 15, true);
if (target != NULL)
{
K_ItemConfirmForTarget(player, target, player->botvars.difficulty);
@ -601,6 +613,7 @@ static void K_BotItemMine(player_t *player, ticcmd_t *cmd, INT16 turnamt)
{
player->botvars.itemconfirm += player->botvars.difficulty / 2;
throwdir = -1;
tryLookback = true;
}
else
{
@ -619,7 +632,12 @@ static void K_BotItemMine(player_t *player, ticcmd_t *cmd, INT16 turnamt)
}
}
if (player->botvars.itemconfirm > 2*TICRATE || player->bananadrag >= TICRATE)
if (tryLookback == true && throwdir == -1)
{
cmd->buttons |= BT_LOOKBACK;
}
if (player->botvars.itemconfirm > 10*TICRATE || player->bananadrag >= TICRATE)
{
K_BotGenericPressItem(player, cmd, throwdir);
}
@ -640,6 +658,7 @@ static void K_BotItemMine(player_t *player, ticcmd_t *cmd, INT16 turnamt)
--------------------------------------------------*/
static void K_BotItemLandmine(player_t *player, ticcmd_t *cmd, INT16 turnamt)
{
const fixed_t coneDist = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed));
player_t *target = NULL;
player->botvars.itemconfirm++;
@ -649,13 +668,14 @@ static void K_BotItemLandmine(player_t *player, ticcmd_t *cmd, INT16 turnamt)
player->botvars.itemconfirm += player->botvars.difficulty / 2;
}
target = K_PlayerInCone(player, player->mo->radius * 16, 10, true);
target = K_PlayerInCone(player, coneDist, 15, true);
if (target != NULL)
{
K_ItemConfirmForTarget(player, target, player->botvars.difficulty);
cmd->buttons |= BT_LOOKBACK;
}
if (player->botvars.itemconfirm > 2*TICRATE)
if (player->botvars.itemconfirm > 10*TICRATE)
{
K_BotGenericPressItem(player, cmd, -1);
}
@ -675,8 +695,10 @@ static void K_BotItemLandmine(player_t *player, ticcmd_t *cmd, INT16 turnamt)
--------------------------------------------------*/
static void K_BotItemEggman(player_t *player, ticcmd_t *cmd)
{
const fixed_t coneDist = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed));
const UINT8 stealth = K_EggboxStealth(player->mo->x, player->mo->y);
SINT8 throwdir = -1;
boolean tryLookback = false;
player_t *target = NULL;
player->botvars.itemconfirm++;
@ -688,11 +710,12 @@ static void K_BotItemEggman(player_t *player, ticcmd_t *cmd)
throwdir = 1;
}
target = K_PlayerInCone(player, player->mo->radius * 16, 10, true);
target = K_PlayerInCone(player, coneDist, 15, true);
if (target != NULL)
{
K_ItemConfirmForTarget(player, target, player->botvars.difficulty);
throwdir = -1;
tryLookback = true;
}
if (stealth > 1 || player->itemroulette > 0)
@ -701,7 +724,12 @@ static void K_BotItemEggman(player_t *player, ticcmd_t *cmd)
throwdir = -1;
}
if (player->botvars.itemconfirm > 2*TICRATE || player->bananadrag >= TICRATE)
if (tryLookback == true && throwdir == -1)
{
cmd->buttons |= BT_LOOKBACK;
}
if (player->botvars.itemconfirm > 10*TICRATE || player->bananadrag >= TICRATE)
{
K_BotGenericPressItem(player, cmd, throwdir);
}
@ -720,6 +748,7 @@ static void K_BotItemEggman(player_t *player, ticcmd_t *cmd)
--------------------------------------------------*/
static boolean K_BotRevealsEggbox(player_t *player)
{
const fixed_t coneDist = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed));
const UINT8 stealth = K_EggboxStealth(player->mo->x, player->mo->y);
player_t *target = NULL;
@ -737,7 +766,7 @@ static boolean K_BotRevealsEggbox(player_t *player)
}
// Check your behind.
target = K_PlayerInCone(player, player->mo->radius * 16, 10, true);
target = K_PlayerInCone(player, coneDist, 15, true);
if (target != NULL)
{
return true;
@ -810,8 +839,9 @@ static void K_BotItemEggmanExplosion(player_t *player, ticcmd_t *cmd)
static void K_BotItemOrbinaut(player_t *player, ticcmd_t *cmd)
{
const fixed_t topspeed = K_GetKartSpeed(player, false);
fixed_t radius = (player->mo->radius * 32);
fixed_t radius = FixedMul(2560 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed));
SINT8 throwdir = -1;
boolean tryLookback = false;
UINT8 snipeMul = 2;
player_t *target = NULL;
@ -823,24 +853,30 @@ static void K_BotItemOrbinaut(player_t *player, ticcmd_t *cmd)
player->botvars.itemconfirm++;
target = K_PlayerInCone(player, radius, 10, false);
target = K_PlayerInCone(player, radius, 15, false);
if (target != NULL)
{
K_ItemConfirmForTarget(player, target, player->botvars.difficulty * snipeMul);
throwdir = 1;
}
else if (K_PlayerInCone(player, radius, 10, true))
else
{
target = K_PlayerInCone(player, radius, 10, true);
target = K_PlayerInCone(player, radius, 15, true);
if (target != NULL)
{
K_ItemConfirmForTarget(player, target, player->botvars.difficulty);
throwdir = -1;
tryLookback = true;
}
}
if (player->botvars.itemconfirm > 5*TICRATE)
if (tryLookback == true && throwdir == -1)
{
cmd->buttons |= BT_LOOKBACK;
}
if (player->botvars.itemconfirm > 25*TICRATE)
{
K_BotGenericPressItem(player, cmd, throwdir);
}
@ -861,8 +897,9 @@ static void K_BotItemOrbinaut(player_t *player, ticcmd_t *cmd)
static void K_BotItemJawz(player_t *player, ticcmd_t *cmd)
{
const fixed_t topspeed = K_GetKartSpeed(player, false);
fixed_t radius = (player->mo->radius * 32);
fixed_t radius = FixedMul(2560 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed));
SINT8 throwdir = 1;
boolean tryLookback = false;
UINT8 snipeMul = 2;
INT32 lastTarg = player->lastjawztarget;
player_t *target = NULL;
@ -875,11 +912,12 @@ static void K_BotItemJawz(player_t *player, ticcmd_t *cmd)
player->botvars.itemconfirm++;
target = K_PlayerInCone(player, radius, 10, true);
target = K_PlayerInCone(player, radius, 15, true);
if (target != NULL)
{
K_ItemConfirmForTarget(player, target, player->botvars.difficulty);
throwdir = -1;
tryLookback = true;
}
if (lastTarg != -1
@ -913,7 +951,12 @@ static void K_BotItemJawz(player_t *player, ticcmd_t *cmd)
}
}
if (player->botvars.itemconfirm > 5*TICRATE)
if (tryLookback == true && throwdir == -1)
{
cmd->buttons |= BT_LOOKBACK;
}
if (player->botvars.itemconfirm > 25*TICRATE)
{
K_BotGenericPressItem(player, cmd, throwdir);
}
@ -1007,7 +1050,7 @@ static void K_BotItemBubble(player_t *player, ticcmd_t *cmd)
}
else if (player->bubbleblowup >= bubbletime)
{
if (player->botvars.itemconfirm >= 10*TICRATE)
if (player->botvars.itemconfirm > 10*TICRATE)
{
hold = true;
}

View file

@ -619,7 +619,7 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player)
fixed_t avgX = 0, avgY = 0;
fixed_t avgDist = 0;
const fixed_t baseNudge = 128 * mapobjectscale;
const fixed_t baseNudge = predict->radius;
fixed_t maxNudge = distToPredict;
fixed_t nudgeDist = 0;
angle_t nudgeDir = 0;

View file

@ -17,6 +17,9 @@ boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2)
boolean damageitem = false;
boolean sprung = false;
if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0))
return true;
if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
return true;
@ -45,7 +48,7 @@ boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2)
else
{
// Player Damage
P_DamageMobj(t2, t1, t1->target, 1, DMG_WIPEOUT);
P_DamageMobj(t2, t1, t1->target, 1, DMG_WIPEOUT|DMG_WOMBO);
K_KartBouncing(t2, t1);
S_StartSound(t2, sfx_s3k7b);
}
@ -108,6 +111,9 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2)
{
boolean damageitem = false;
if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0))
return true;
if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
return true;
@ -137,7 +143,7 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2)
}
else
{
P_DamageMobj(t2, t1, t1->target, 1, DMG_NORMAL);
P_DamageMobj(t2, t1, t1->target, 1, DMG_NORMAL|DMG_WOMBO);
}
damageitem = true;
@ -186,6 +192,9 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2)
boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2)
{
if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0))
return true;
// Push fakes out of other item boxes
if (t2->type == MT_RANDOMITEM || t2->type == MT_EGGMANITEM)
{
@ -258,6 +267,9 @@ boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2)
boolean K_MineCollide(mobj_t *t1, mobj_t *t2)
{
if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0))
return true;
if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
return true;
@ -331,6 +343,9 @@ boolean K_MineExplosionCollide(mobj_t *t1, mobj_t *t2)
boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2)
{
if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0))
return true;
if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
return true;
@ -398,6 +413,9 @@ boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2)
boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2)
{
if ((t1->threshold > 0 && t2->hitlag > 0) || (t2->threshold > 0 && t1->hitlag > 0))
return true;
if (((t1->target == t2) || (t1->target == t2->target)) && (t1->threshold > 0 || (t2->type != MT_PLAYER && t2->threshold > 0)))
return true;
@ -465,7 +483,8 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2)
{
boolean t1Condition = false;
boolean t2Condition = false;
boolean stung = false;
boolean stungT1 = false;
boolean stungT2 = false;
// Grow damage
t1Condition = (t1->scale > t2->scale + (mapobjectscale/8));
@ -473,12 +492,12 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2)
if (t1Condition == true && t2Condition == false)
{
P_DamageMobj(t2, t1, t1, 1, DMG_TUMBLE);
P_DamageMobj(t2, t1, t1, 1, DMG_TUMBLE|DMG_WOMBO);
return true;
}
else if (t1Condition == false && t2Condition == true)
{
P_DamageMobj(t1, t2, t2, 1, DMG_TUMBLE);
P_DamageMobj(t1, t2, t2, 1, DMG_TUMBLE|DMG_WOMBO);
return true;
}
@ -488,12 +507,12 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2)
if (t1Condition == true && t2Condition == false)
{
P_DamageMobj(t2, t1, t1, 1, DMG_TUMBLE);
P_DamageMobj(t2, t1, t1, 1, DMG_TUMBLE|DMG_WOMBO);
return true;
}
else if (t1Condition == false && t2Condition == true)
{
P_DamageMobj(t1, t2, t2, 1, DMG_TUMBLE);
P_DamageMobj(t1, t2, t2, 1, DMG_TUMBLE|DMG_WOMBO);
return true;
}
@ -503,12 +522,12 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2)
if (t1Condition == true && t2Condition == false)
{
P_DamageMobj(t2, t1, t1, 1, DMG_WIPEOUT);
P_DamageMobj(t2, t1, t1, 1, DMG_WIPEOUT|DMG_WOMBO);
return true;
}
else if (t1Condition == false && t2Condition == true)
{
P_DamageMobj(t1, t2, t2, 1, DMG_WIPEOUT);
P_DamageMobj(t1, t2, t2, 1, DMG_WIPEOUT|DMG_WOMBO);
return true;
}
@ -521,12 +540,12 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2)
if (t1Condition == true && t2Condition == false)
{
P_DamageMobj(t2, t1, t1, 1, DMG_WIPEOUT|DMG_STEAL);
P_DamageMobj(t2, t1, t1, 1, DMG_WIPEOUT|DMG_STEAL|DMG_WOMBO);
return true;
}
else if (t1Condition == false && t2Condition == true)
{
P_DamageMobj(t1, t2, t2, 1, DMG_WIPEOUT|DMG_STEAL);
P_DamageMobj(t1, t2, t2, 1, DMG_WIPEOUT|DMG_STEAL|DMG_WOMBO);
return true;
}
}
@ -537,25 +556,35 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2)
if (t1Condition == true)
{
P_PlayerRingBurst(t2->player, 1);
if (t2->player->rings <= 0)
{
P_DamageMobj(t2, t1, t1, 1, DMG_STING);
stung = true;
P_DamageMobj(t2, t1, t1, 1, DMG_STING|DMG_WOMBO);
stungT2 = true;
}
P_PlayerRingBurst(t2->player, 1);
}
if (t2Condition == true)
{
P_PlayerRingBurst(t1->player, 1);
if (t1->player->rings <= 0)
{
P_DamageMobj(t1, t2, t2, 1, DMG_STING);
stung = true;
P_DamageMobj(t1, t2, t2, 1, DMG_STING|DMG_WOMBO);
stungT1 = true;
}
P_PlayerRingBurst(t1->player, 1);
}
return stung;
// No damage hitlag for stinging.
if (stungT1 == true && stungT2 == false)
{
t2->eflags &= ~MFE_DAMAGEHITLAG;
}
else if (stungT2 == true && stungT1 == false)
{
t1->eflags &= ~MFE_DAMAGEHITLAG;
}
return (stungT1 || stungT2);
}

294
src/k_director.c Normal file
View file

@ -0,0 +1,294 @@
// SONIC ROBO BLAST 2 KART
//-----------------------------------------------------------------------------
/// \file k_director.c
/// \brief SRB2kart automatic spectator camera.
#include "k_kart.h"
#include "k_respawn.h"
#include "doomdef.h"
#include "g_game.h"
#include "v_video.h"
#include "k_director.h"
#include "d_netcmd.h"
#include "p_local.h"
#define SWITCHTIME TICRATE * 5 // cooldown between unforced switches
#define BOREDOMTIME 3 * TICRATE / 2 // how long until players considered far apart?
#define TRANSFERTIME TICRATE // how long to delay reaction shots?
#define BREAKAWAYDIST 4000 // how *far* until players considered far apart?
#define WALKBACKDIST 600 // how close should a trailing player be before we switch?
#define PINCHDIST 30000 // how close should the leader be to be considered "end of race"?
struct directorinfo directorinfo;
void K_InitDirector(void)
{
INT32 playernum;
directorinfo.cooldown = SWITCHTIME;
directorinfo.freeze = 0;
directorinfo.attacker = 0;
directorinfo.maxdist = 0;
for (playernum = 0; playernum < MAXPLAYERS; playernum++)
{
directorinfo.sortedplayers[playernum] = -1;
directorinfo.gap[playernum] = INT32_MAX;
directorinfo.boredom[playernum] = 0;
}
}
static fixed_t K_GetFinishGap(INT32 leader, INT32 follower)
{
fixed_t dista = players[follower].distancetofinish;
fixed_t distb = players[leader].distancetofinish;
if (players[follower].position < players[leader].position)
{
return distb - dista;
}
else
{
return dista - distb;
}
}
static void K_UpdateDirectorPositions(void)
{
INT32 playernum;
INT32 position;
player_t* target;
memset(directorinfo.sortedplayers, -1, sizeof(directorinfo.sortedplayers));
for (playernum = 0; playernum < MAXPLAYERS; playernum++)
{
target = &players[playernum];
if (playeringame[playernum] && !target->spectator && target->position > 0)
{
directorinfo.sortedplayers[target->position - 1] = playernum;
}
}
for (position = 0; position < MAXPLAYERS - 1; position++)
{
directorinfo.gap[position] = INT32_MAX;
if (directorinfo.sortedplayers[position] == -1 || directorinfo.sortedplayers[position + 1] == -1)
{
continue;
}
directorinfo.gap[position] = P_ScaleFromMap(K_GetFinishGap(directorinfo.sortedplayers[position], directorinfo.sortedplayers[position + 1]), FRACUNIT);
if (directorinfo.gap[position] >= BREAKAWAYDIST)
{
directorinfo.boredom[position] = min(BOREDOMTIME * 2, directorinfo.boredom[position] + 1);
}
else if (directorinfo.boredom[position] > 0)
{
directorinfo.boredom[position]--;
}
}
directorinfo.maxdist = P_ScaleFromMap(players[directorinfo.sortedplayers[0]].distancetofinish, FRACUNIT);
}
static boolean K_CanSwitchDirector(void)
{
INT32 *displayplayerp = &displayplayers[0];
if (players[*displayplayerp].trickpanel > 0)
{
return false;
}
if (directorinfo.cooldown > 0)
{
return false;
}
return true;
}
static void K_DirectorSwitch(INT32 player, boolean force)
{
if (P_IsDisplayPlayer(&players[player]))
{
return;
}
if (players[player].exiting)
{
return;
}
if (!force && !K_CanSwitchDirector())
{
return;
}
G_ResetView(1, player, true);
directorinfo.cooldown = SWITCHTIME;
}
static void K_DirectorForceSwitch(INT32 player, INT32 time)
{
if (players[player].exiting)
{
return;
}
directorinfo.attacker = player;
directorinfo.freeze = time;
}
void K_DirectorFollowAttack(player_t *player, mobj_t *inflictor, mobj_t *source)
{
if (!P_IsDisplayPlayer(player))
{
return;
}
if (inflictor && inflictor->player)
{
K_DirectorForceSwitch(inflictor->player - players, TRANSFERTIME);
}
else if (source && source->player)
{
K_DirectorForceSwitch(source->player - players, TRANSFERTIME);
}
}
void K_DrawDirectorDebugger(void)
{
INT32 position;
INT32 leader;
INT32 follower;
INT32 ytxt;
if (!cv_kartdebugdirector.value)
{
return;
}
V_DrawThinString(10, 0, V_70TRANS, va("PLACE"));
V_DrawThinString(40, 0, V_70TRANS, va("CONF?"));
V_DrawThinString(80, 0, V_70TRANS, va("GAP"));
V_DrawThinString(120, 0, V_70TRANS, va("BORED"));
V_DrawThinString(150, 0, V_70TRANS, va("COOLDOWN: %d", directorinfo.cooldown));
V_DrawThinString(230, 0, V_70TRANS, va("MAXDIST: %d", directorinfo.maxdist));
for (position = 0; position < MAXPLAYERS - 1; position++)
{
ytxt = 10 * (position + 1);
leader = directorinfo.sortedplayers[position];
follower = directorinfo.sortedplayers[position + 1];
if (leader == -1 || follower == -1)
break;
V_DrawThinString(10, ytxt, V_70TRANS, va("%d", position));
V_DrawThinString(20, ytxt, V_70TRANS, va("%d", position + 1));
if (players[leader].positiondelay)
{
V_DrawThinString(40, ytxt, V_70TRANS, va("NG"));
}
V_DrawThinString(80, ytxt, V_70TRANS, va("%d", directorinfo.gap[position]));
if (directorinfo.boredom[position] >= BOREDOMTIME)
{
V_DrawThinString(120, ytxt, V_70TRANS, va("BORED"));
}
else
{
V_DrawThinString(120, ytxt, V_70TRANS, va("%d", directorinfo.boredom[position]));
}
V_DrawThinString(150, ytxt, V_70TRANS, va("%s", player_names[leader]));
V_DrawThinString(230, ytxt, V_70TRANS, va("%s", player_names[follower]));
}
}
void K_UpdateDirector(void)
{
INT32 *displayplayerp = &displayplayers[0];
INT32 targetposition;
if (!cv_director.value)
{
return;
}
K_UpdateDirectorPositions();
if (directorinfo.cooldown > 0) {
directorinfo.cooldown--;
}
// handle pending forced switches
if (directorinfo.freeze > 0)
{
if (!(--directorinfo.freeze))
K_DirectorSwitch(directorinfo.attacker, true);
return;
}
// aaight, time to walk through the standings to find the first interesting pair
// NB: targetposition/sortedplayers is 0-indexed, aiming at the "back half" of a given pair by default.
// we adjust for this when comparing to player->position or when looking at the leading player, Don't Freak Out
for (targetposition = 1; targetposition < MAXPLAYERS; targetposition++)
{
INT32 target;
// you are out of players, try again
if (directorinfo.sortedplayers[targetposition] == -1)
{
break;
}
// pair too far apart? try the next one
if (directorinfo.boredom[targetposition - 1] >= BOREDOMTIME)
{
continue;
}
// pair finished? try the next one
if (players[directorinfo.sortedplayers[targetposition]].exiting)
{
continue;
}
// don't risk switching away from forward pairs at race end, might miss something!
if (directorinfo.maxdist > PINCHDIST)
{
// if the "next" player is close enough, they should be able to see everyone fine!
// walk back through the standings to find a vantage that gets everyone in frame.
// (also creates a pretty cool effect w/ overtakes at speed)
while (targetposition < MAXPLAYERS && directorinfo.gap[targetposition] < WALKBACKDIST)
{
targetposition++;
}
}
target = directorinfo.sortedplayers[targetposition];
// if we're certain the back half of the pair is actually in this position, try to switch
if (*displayplayerp != target && !players[target].positiondelay)
{
K_DirectorSwitch(target, false);
}
// even if we're not certain, if we're certain we're watching the WRONG player, try to switch
if (players[*displayplayerp].position != targetposition+1 && !players[target].positiondelay)
{
K_DirectorSwitch(target, false);
}
break;
}
}

21
src/k_director.h Normal file
View file

@ -0,0 +1,21 @@
// SONIC ROBO BLAST 2 KART
//-----------------------------------------------------------------------------
/// \file k_director.h
/// \brief SRB2kart automatic spectator camera.
extern struct directorinfo
{
tic_t cooldown; // how long has it been since we last switched?
tic_t freeze; // when nonzero, fixed switch pending, freeze logic!
INT32 attacker; // who to switch to when freeze delay elapses
INT32 maxdist; // how far is the closest player from finishing?
INT32 sortedplayers[MAXPLAYERS]; // position-1 goes in, player index comes out.
INT32 gap[MAXPLAYERS]; // gap between a given position and their closest pursuer
INT32 boredom[MAXPLAYERS]; // how long has a given position had no credible attackers?
} directorinfo;
void K_InitDirector(void);
void K_UpdateDirector(void);
void K_DrawDirectorDebugger(void);
void K_DirectorFollowAttack(player_t *player, mobj_t *inflictor, mobj_t *source);

View file

@ -13,6 +13,7 @@
#include "k_kart.h"
#include "k_battle.h"
#include "k_color.h"
#include "k_director.h"
#include "screen.h"
#include "doomtype.h"
#include "doomdef.h"
@ -31,6 +32,7 @@
#include "r_main.h"
#include "s_sound.h"
#include "r_things.h"
#include "r_fps.h"
#define NUMPOSNUMS 10
#define NUMPOSFRAMES 7 // White, three blues, three reds
@ -835,48 +837,26 @@ void K_ObjectTracking(trackingResult_t *result, vector3_t *point, UINT8 cameraNu
return;
}
// TODO: needs da interp
// TODO: parts need interp
if (cam->chase == true && !player->spectator)
{
// Use the camera's properties.
viewpointX = cam->x;
viewpointY = cam->y;
viewpointZ = cam->z - point->z;
viewpointAngle = (INT32)cam->angle;
viewpointAiming = (INT32)cam->aiming;
viewpointRoll = (INT32)player->viewrollangle;
if (cv_frameinterpolation.value == 1)
{
viewpointX = cam->old_x + FixedMul(rendertimefrac, cam->x - cam->old_x);
viewpointY = cam->old_y + FixedMul(rendertimefrac, cam->y - cam->old_y);
viewpointZ = (cam->old_z + FixedMul(rendertimefrac, cam->z - cam->old_z)) - point->z;
viewpointAngle = (INT32)(cam->old_angle + FixedMul(rendertimefrac, cam->angle - cam->old_angle));
viewpointAiming = (INT32)(cam->old_aiming + FixedMul(rendertimefrac, cam->aiming - cam->old_aiming));
viewpointRoll = (INT32)(player->old_viewrollangle + FixedMul(rendertimefrac, player->viewrollangle - player->old_viewrollangle));
}
viewpointX = R_InterpolateFixed(cam->old_x, cam->x);
viewpointY = R_InterpolateFixed(cam->old_y, cam->y);
viewpointZ = R_InterpolateFixed(cam->old_z, cam->z) - point->z;
viewpointAngle = (INT32)R_InterpolateAngle(cam->old_angle, cam->angle);
viewpointAiming = (INT32)R_InterpolateAngle(cam->old_aiming, cam->aiming);
viewpointRoll = (INT32)R_InterpolateAngle(player->old_viewrollangle, player->viewrollangle);
}
else
{
// Use player properties.
viewpointX = player->mo->x;
viewpointY = player->mo->y;
viewpointZ = player->viewz - point->z;
viewpointAngle = (INT32)player->mo->angle;
viewpointX = R_InterpolateFixed(player->mo->old_x, player->mo->x);
viewpointY = R_InterpolateFixed(player->mo->old_y, player->mo->y);
viewpointZ = R_InterpolateFixed(player->mo->old_z, player->mo->z) - point->z; //player->old_viewz
viewpointAngle = (INT32)R_InterpolateAngle(player->mo->old_angle, player->mo->angle);
viewpointAiming = (INT32)player->aiming;
viewpointRoll = (INT32)player->viewrollangle;
if (cv_frameinterpolation.value == 1)
{
viewpointX = player->mo->old_x + FixedMul(rendertimefrac, player->mo->x - player->mo->old_x);
viewpointY = player->mo->old_y + FixedMul(rendertimefrac, player->mo->y - player->mo->old_y);
viewpointZ = (player->mo->old_z + FixedMul(rendertimefrac, player->viewz - player->mo->old_z)) - point->z; //player->old_viewz
viewpointAngle = (INT32)(player->mo->old_angle + FixedMul(rendertimefrac, player->mo->angle - player->mo->old_angle));
//viewpointAiming = (INT32)(player->mo->old_aiming + FixedMul(rendertimefrac, player->mo->aiming - player->mo->old_aiming));
viewpointRoll = (INT32)(player->old_viewrollangle + FixedMul(rendertimefrac, player->viewrollangle - player->old_viewrollangle));
}
viewpointRoll = (INT32)R_InterpolateAngle(player->old_viewrollangle, player->viewrollangle);
}
viewpointAngle += (INT32)angleOffset;
@ -2631,24 +2611,13 @@ static void K_drawKartPlayerCheck(void)
continue;
}
v.x = checkplayer->mo->x;
v.y = checkplayer->mo->y;
v.z = checkplayer->mo->z;
v.x = R_InterpolateFixed(checkplayer->mo->old_x, checkplayer->mo->x);
v.y = R_InterpolateFixed(checkplayer->mo->old_y, checkplayer->mo->y);
v.z = R_InterpolateFixed(checkplayer->mo->old_z, checkplayer->mo->z);
pPos.x = stplyr->mo->x;
pPos.y = stplyr->mo->y;
pPos.z = stplyr->mo->z;
if (cv_frameinterpolation.value == 1)
{
v.x = checkplayer->mo->old_x + FixedMul(rendertimefrac, checkplayer->mo->x - checkplayer->mo->old_x);
v.y = checkplayer->mo->old_y + FixedMul(rendertimefrac, checkplayer->mo->y - checkplayer->mo->old_y);
v.z = checkplayer->mo->old_z + FixedMul(rendertimefrac, checkplayer->mo->z - checkplayer->mo->old_z);
pPos.x = stplyr->mo->old_x + FixedMul(rendertimefrac, stplyr->mo->x - stplyr->mo->old_x);
pPos.y = stplyr->mo->old_y + FixedMul(rendertimefrac, stplyr->mo->y - stplyr->mo->old_y);
pPos.z = stplyr->mo->old_z + FixedMul(rendertimefrac, stplyr->mo->z - stplyr->mo->old_z);
}
pPos.x = R_InterpolateFixed(stplyr->mo->old_x, stplyr->mo->x);
pPos.y = R_InterpolateFixed(stplyr->mo->old_y, stplyr->mo->y);
pPos.z = R_InterpolateFixed(stplyr->mo->old_z, stplyr->mo->z);
distance = R_PointToDist2(pPos.x, pPos.y, v.x, v.y);
@ -2834,29 +2803,15 @@ static void K_drawKartNameTags(void)
if (thiscam->chase == true)
{
c.x = thiscam->x;
c.y = thiscam->y;
c.z = thiscam->z;
if (cv_frameinterpolation.value == 1)
{
c.x = thiscam->old_x + FixedMul(rendertimefrac, thiscam->x - thiscam->old_x);
c.y = thiscam->old_y + FixedMul(rendertimefrac, thiscam->y - thiscam->old_y);
c.z = thiscam->old_z + FixedMul(rendertimefrac, thiscam->z - thiscam->old_z);
}
c.x = R_InterpolateFixed(thiscam->old_x, thiscam->x);
c.y = R_InterpolateFixed(thiscam->old_y, thiscam->y);
c.z = R_InterpolateFixed(thiscam->old_z, thiscam->z);
}
else
{
c.x = stplyr->mo->x;
c.y = stplyr->mo->y;
c.z = stplyr->mo->z;
if (cv_frameinterpolation.value == 1)
{
c.x = stplyr->mo->old_x + FixedMul(rendertimefrac, stplyr->mo->x - stplyr->mo->old_x);
c.y = stplyr->mo->old_y + FixedMul(rendertimefrac, stplyr->mo->y - stplyr->mo->old_y);
c.z = stplyr->mo->old_z + FixedMul(rendertimefrac, stplyr->mo->z - stplyr->mo->old_z);
}
c.x = R_InterpolateFixed(stplyr->mo->old_x, stplyr->mo->x);
c.y = R_InterpolateFixed(stplyr->mo->old_y, stplyr->mo->y);
c.z = R_InterpolateFixed(stplyr->mo->old_z, stplyr->mo->z);
}
for (i = 0; i < MAXPLAYERS; i++)
@ -2895,16 +2850,9 @@ static void K_drawKartNameTags(void)
continue;
}
v.x = ntplayer->mo->x;
v.y = ntplayer->mo->y;
v.z = ntplayer->mo->z;
if (cv_frameinterpolation.value == 1)
{
v.x = ntplayer->mo->old_x + FixedMul(rendertimefrac, ntplayer->mo->x - ntplayer->mo->old_x);
v.y = ntplayer->mo->old_y + FixedMul(rendertimefrac, ntplayer->mo->y - ntplayer->mo->old_y);
v.z = ntplayer->mo->old_z + FixedMul(rendertimefrac, ntplayer->mo->z - ntplayer->mo->old_z);
}
v.x = R_InterpolateFixed(ntplayer->mo->old_x, ntplayer->mo->x);
v.y = R_InterpolateFixed(ntplayer->mo->old_y, ntplayer->mo->y);
v.z = R_InterpolateFixed(ntplayer->mo->old_z, ntplayer->mo->z);
if (!(ntplayer->mo->eflags & MFE_VERTICALFLIP))
{
@ -2959,16 +2907,9 @@ static void K_drawKartNameTags(void)
SINT8 localindicator = -1;
vector3_t v;
v.x = ntplayer->mo->x;
v.y = ntplayer->mo->y;
v.z = ntplayer->mo->z;
if (cv_frameinterpolation.value == 1)
{
v.x = ntplayer->mo->old_x + FixedMul(rendertimefrac, ntplayer->mo->x - ntplayer->mo->old_x);
v.y = ntplayer->mo->old_y + FixedMul(rendertimefrac, ntplayer->mo->y - ntplayer->mo->old_y);
v.z = ntplayer->mo->old_z + FixedMul(rendertimefrac, ntplayer->mo->z - ntplayer->mo->old_z);
}
v.x = R_InterpolateFixed(ntplayer->mo->old_x, ntplayer->mo->x);
v.y = R_InterpolateFixed(ntplayer->mo->old_y, ntplayer->mo->y);
v.z = R_InterpolateFixed(ntplayer->mo->old_z, ntplayer->mo->z);
v.z += (ntplayer->mo->height / 2);
@ -3208,14 +3149,8 @@ static void K_drawKartMinimap(void)
else
colormap = NULL;
interpx = g->mo->x;
interpy = g->mo->y;
if (cv_frameinterpolation.value == 1)
{
interpx = g->mo->old_x + FixedMul(rendertimefrac, g->mo->x - g->mo->old_x);
interpy = g->mo->old_y + FixedMul(rendertimefrac, g->mo->y - g->mo->old_y);
}
interpx = R_InterpolateFixed(g->mo->old_x, g->mo->x);
interpy = R_InterpolateFixed(g->mo->old_y, g->mo->y);
K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap, AutomapPic);
g = g->next;
@ -3273,14 +3208,8 @@ static void K_drawKartMinimap(void)
else
colormap = NULL;
interpx = players[i].mo->x;
interpy = players[i].mo->y;
if (cv_frameinterpolation.value == 1)
{
interpx = players[i].mo->old_x + FixedMul(rendertimefrac, players[i].mo->x - players[i].mo->old_x);
interpy = players[i].mo->old_y + FixedMul(rendertimefrac, players[i].mo->y - players[i].mo->old_y);
}
interpx = R_InterpolateFixed(players[i].mo->old_x, players[i].mo->x);
interpy = R_InterpolateFixed(players[i].mo->old_y, players[i].mo->y);
K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap, AutomapPic);
// Target reticule
@ -3308,14 +3237,8 @@ static void K_drawKartMinimap(void)
colormap = R_GetTranslationColormap(TC_RAINBOW, mobj->color, GTC_CACHE);
}
interpx = mobj->x;
interpy = mobj->y;
if (cv_frameinterpolation.value == 1)
{
interpx = mobj->old_x + FixedMul(rendertimefrac, mobj->x - mobj->old_x);
interpy = mobj->old_y + FixedMul(rendertimefrac, mobj->y - mobj->old_y);
}
interpx = R_InterpolateFixed(mobj->old_x, mobj->x);
interpy = R_InterpolateFixed(mobj->old_y, mobj->y);
K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, kp_spbminimap, colormap, AutomapPic);
}
@ -3345,14 +3268,8 @@ static void K_drawKartMinimap(void)
else
colormap = NULL;
interpx = players[localplayers[i]].mo->x;
interpy = players[localplayers[i]].mo->y;
if (cv_frameinterpolation.value == 1)
{
interpx = players[localplayers[i]].mo->old_x + FixedMul(rendertimefrac, players[localplayers[i]].mo->x - players[localplayers[i]].mo->old_x);
interpy = players[localplayers[i]].mo->old_y + FixedMul(rendertimefrac, players[localplayers[i]].mo->y - players[localplayers[i]].mo->old_y);
}
interpx = R_InterpolateFixed(players[localplayers[i]].mo->old_x, players[localplayers[i]].mo->x);
interpy = R_InterpolateFixed(players[localplayers[i]].mo->old_y, players[localplayers[i]].mo->y);
K_drawKartMinimapIcon(interpx, interpy, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap, AutomapPic);
@ -3631,7 +3548,7 @@ static void K_drawKartFinish(void)
x = ((TICRATE - stplyr->karthud[khud_cardanimation])*(xval > x ? xval : x))/TICRATE;
ox = ((TICRATE - (stplyr->karthud[khud_cardanimation] - 1))*(xval > x ? xval : x))/TICRATE;
interpx = ox + FixedMul(rendertimefrac, x - ox);
interpx = R_InterpolateFixed(ox, x);
if (r_splitscreen && stplyr == &players[displayplayers[1]])
interpx = -interpx;
@ -4028,7 +3945,7 @@ static void K_drawLapStartAnim(void)
const UINT8 t = stplyr->karthud[khud_lapanimation];
const UINT8 progress = 80 - t;
const UINT8 tOld = t - 1;
const UINT8 tOld = t + 1;
const UINT8 progressOld = 80 - tOld;
const tic_t leveltimeOld = leveltime - 1;
@ -4039,11 +3956,11 @@ static void K_drawLapStartAnim(void)
newval = (BASEVIDWIDTH/2 + (32 * max(0, t - 76))) * FRACUNIT;
oldval = (BASEVIDWIDTH/2 + (32 * max(0, tOld - 76))) * FRACUNIT;
interpx = oldval + FixedMul(rendertimefrac, newval - oldval);
interpx = R_InterpolateFixed(oldval, newval);
newval = (48 - (32 * max(0, progress - 76))) * FRACUNIT;
oldval = (48 - (32 * max(0, progressOld - 76))) * FRACUNIT;
interpy = oldval + FixedMul(rendertimefrac, newval - oldval);
interpy = R_InterpolateFixed(oldval, newval);
V_DrawFixedPatch(
interpx, interpy,
@ -4054,7 +3971,7 @@ static void K_drawLapStartAnim(void)
{
newval = (4 - abs((signed)((leveltime % 8) - 4))) * FRACUNIT;
oldval = (4 - abs((signed)((leveltimeOld % 8) - 4))) * FRACUNIT;
interpy += oldval + FixedMul(rendertimefrac, newval - oldval);
interpy += R_InterpolateFixed(oldval, newval);
V_DrawFixedPatch(
interpx, interpy,
@ -4066,7 +3983,7 @@ static void K_drawLapStartAnim(void)
{
newval = (62 - (32 * max(0, progress - 76))) * FRACUNIT;
oldval = (62 - (32 * max(0, progressOld - 76))) * FRACUNIT;
interpx = oldval + FixedMul(rendertimefrac, newval - oldval);
interpx = R_InterpolateFixed(oldval, newval);
V_DrawFixedPatch(
interpx, // 27
@ -4078,7 +3995,7 @@ static void K_drawLapStartAnim(void)
{
newval = (188 + (32 * max(0, progress - 76))) * FRACUNIT;
oldval = (188 + (32 * max(0, progressOld - 76))) * FRACUNIT;
interpx = oldval + FixedMul(rendertimefrac, newval - oldval);
interpx = R_InterpolateFixed(oldval, newval);
V_DrawFixedPatch(
interpx, // 194
@ -4091,7 +4008,7 @@ static void K_drawLapStartAnim(void)
{
newval = (82 - (32 * max(0, progress - 76))) * FRACUNIT;
oldval = (82 - (32 * max(0, progressOld - 76))) * FRACUNIT;
interpx = oldval + FixedMul(rendertimefrac, newval - oldval);
interpx = R_InterpolateFixed(oldval, newval);
V_DrawFixedPatch(
interpx, // 61
@ -4103,7 +4020,7 @@ static void K_drawLapStartAnim(void)
{
newval = (188 + (32 * max(0, progress - 76))) * FRACUNIT;
oldval = (188 + (32 * max(0, progressOld - 76))) * FRACUNIT;
interpx = oldval + FixedMul(rendertimefrac, newval - oldval);
interpx = R_InterpolateFixed(oldval, newval);
V_DrawFixedPatch(
interpx, // 194
@ -4115,7 +4032,7 @@ static void K_drawLapStartAnim(void)
{
newval = (208 + (32 * max(0, progress - 76))) * FRACUNIT;
oldval = (208 + (32 * max(0, progressOld - 76))) * FRACUNIT;
interpx = oldval + FixedMul(rendertimefrac, newval - oldval);
interpx = R_InterpolateFixed(oldval, newval);
V_DrawFixedPatch(
interpx, // 221
@ -4588,6 +4505,7 @@ void K_drawKartHUD(void)
}
K_DrawWaypointDebugger();
K_DrawDirectorDebugger();
if (gametype == GT_BATTLE)
{

File diff suppressed because it is too large Load diff

View file

@ -22,6 +22,12 @@ Make sure this matches the actual number of states
#define MAXHITLAGTICS 18 //12
#define HITLAGJITTERS (FRACUNIT / 20)
#define GROW_SCALE (2*FRACUNIT)
#define SHRINK_SCALE (FRACUNIT/2)
#define GROW_PHYSICS_SCALE (3*FRACUNIT/2)
#define SHRINK_PHYSICS_SCALE (3*FRACUNIT/4)
player_t *K_GetItemBoxPlayer(mobj_t *mobj);
angle_t K_ReflectAngle(angle_t angle, angle_t against, fixed_t maxspeed, fixed_t yourspeed);
@ -76,7 +82,7 @@ void K_RunFinishLineBeam(void);
UINT16 K_DriftSparkColor(player_t *player, INT32 charge);
void K_SpawnBoostTrail(player_t *player);
void K_SpawnSparkleTrail(mobj_t *mo);
void K_SpawnWipeoutTrail(mobj_t *mo, boolean offroad);
void K_SpawnWipeoutTrail(mobj_t *mo);
void K_SpawnDraftDust(mobj_t *mo);
void K_DriftDustHandling(mobj_t *spawner);
void K_Squish(mobj_t *mo);
@ -115,10 +121,13 @@ boolean K_WaterRun(player_t *player);
void K_ApplyTripWire(player_t *player, tripwirestate_t state);
INT16 K_GetSpindashChargeTime(player_t *player);
fixed_t K_GetSpindashChargeSpeed(player_t *player);
fixed_t K_GrowShrinkSpeedMul(player_t *player);
fixed_t K_GetKartSpeedFromStat(UINT8 kartspeed);
fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower);
fixed_t K_GetKartAccel(player_t *player);
UINT16 K_GetKartFlashing(player_t *player);
boolean K_PlayerShrinkCheat(player_t *player);
void K_UpdateShrinkCheat(player_t *player);
boolean K_KartKickstart(player_t *player);
UINT16 K_GetKartButtons(player_t *player);
SINT8 K_GetForwardMove(player_t *player);
@ -141,5 +150,9 @@ void K_PlayPainSound(mobj_t *source);
void K_PlayHitEmSound(mobj_t *source);
void K_PlayPowerGloatSound(mobj_t *source);
fixed_t K_ItemScaleForPlayer(player_t *player);
void K_SetItemOut(player_t *player);
void K_UnsetItemOut(player_t *player);
// =========================================================================
#endif // __K_KART__

View file

@ -370,7 +370,7 @@ static void K_DrawFinishLineBeamForLine(fixed_t offset, angle_t aiming, line_t *
P_SetMobjState(end1, S_FINISHBEAMEND1);
end1->renderflags = RF_DONTDRAW & ~K_GetPlayerDontDrawFlag(&players[displayplayers[i]]);
end1->angle = lineangle;
P_InitAngle(end1, lineangle);
end2 = P_SpawnMobj(
v->x + (8*sx),
@ -381,7 +381,7 @@ static void K_DrawFinishLineBeamForLine(fixed_t offset, angle_t aiming, line_t *
P_SetMobjState(end2, S_FINISHBEAMEND2);
end2->renderflags = RF_DONTDRAW & ~K_GetPlayerDontDrawFlag(&players[displayplayers[i]]);
end2->angle = lineangle;
P_InitAngle(end2, lineangle);
P_SetTarget(&end2->tracer, end1);
end2->flags2 |= MF2_LINKDRAW;

View file

@ -582,7 +582,7 @@ static void K_MovePlayerToRespawnPoint(player_t *player)
P_SetTarget(&lasermo->target, player->mo);
lasermo->angle = stepha + ANGLE_90;
P_InitAngle(lasermo, stepha + ANGLE_90);
P_SetScale(lasermo, (lasermo->destscale = player->mo->scale));
}
}
@ -645,7 +645,7 @@ static void K_DropDashWait(player_t *player)
P_SetTarget(&laser->target, player->mo);
laser->angle = newangle + ANGLE_90;
P_InitAngle(laser, newangle + ANGLE_90);
laser->momz = (8 * player->mo->scale) * P_MobjFlip(player->mo);
P_SetScale(laser, (laser->destscale = player->mo->scale));
}
@ -672,11 +672,11 @@ static void K_HandleDropDash(player_t *player)
if (player->growshrinktimer < 0)
{
player->mo->scalespeed = mapobjectscale/TICRATE;
player->mo->destscale = (6*mapobjectscale)/8;
player->mo->destscale = FixedMul(mapobjectscale, SHRINK_SCALE);
if (cv_kartdebugshrink.value && !modeattacking && !player->bot)
if (K_PlayerShrinkCheat(player) == true)
{
player->mo->destscale = (6*player->mo->destscale)/8;
player->mo->destscale = FixedMul(player->mo->destscale, SHRINK_SCALE);
}
}

1532
src/k_terrain.c Normal file

File diff suppressed because it is too large Load diff

459
src/k_terrain.h Normal file
View file

@ -0,0 +1,459 @@
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 1998-2021 by ZDoom + GZDoom teams, and contributors
// Copyright (C) 2021 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2021 by Kart Krew
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file k_terrain.h
/// \brief Implementation of a TERRAIN-style lump for DRRR, ala GZDoom's codebase.
#ifndef __K_TERRAIN_H__
#define __K_TERRAIN_H__
#include "doomdata.h"
#include "doomdef.h"
#include "doomtype.h"
#include "m_fixed.h"
#include "p_mobj.h"
#define TERRAIN_NAME_LEN 32
typedef struct t_splash_s
{
// Splash definition.
// These are particles spawned when hitting the floor.
char name[TERRAIN_NAME_LEN]; // Lookup name.
UINT16 mobjType; // Thing type. MT_NULL to not spawn anything.
UINT16 sfx; // Sound to play.
fixed_t scale; // Thing scale multiplier.
UINT16 color; // Colorize effect. SKINCOLOR_NONE has no colorize.
fixed_t pushH; // Push-out horizontal multiplier.
fixed_t pushV; // Push-out vertical multiplier.
fixed_t spread; // Randomized spread distance.
angle_t cone; // Randomized angle of the push-out.
UINT8 numParticles; // Number of particles to spawn.
} t_splash_t;
typedef struct t_footstep_s
{
// Footstep definition.
// These are particles spawned when moving fast enough on a floor.
char name[TERRAIN_NAME_LEN]; // Lookup name.
UINT16 mobjType; // Thing type. MT_NULL to not spawn anything.
UINT16 sfx; // Sound to play.
fixed_t scale; // Thing scale multiplier.
UINT16 color; // Colorize effect. SKINCOLOR_NONE has no colorize.
fixed_t pushH; // Push-out horizontal multiplier.
fixed_t pushV; // Push-out vertical multiplier.
fixed_t spread; // Randomized spread distance.
angle_t cone; // Randomized angle of the push-out.
tic_t sfxFreq; // How frequently to play the sound.
tic_t frequency; // How frequently to spawn the particles.
fixed_t requiredSpeed; // Speed percentage you need to be at to trigger the particles.
} t_footstep_t;
typedef enum
{
// Terrain flag values.
TRF_LIQUID = 1, // Texture water properties (wavy, slippery, etc)
TRF_SNEAKERPANEL = 1<<1, // Texture is a booster
TRF_STAIRJANK = 1<<2, // Texture is bumpy road
TRF_TRIPWIRE = 1<<3 // Texture is a tripwire when used as a midtexture
} terrain_flags_t;
typedef struct terrain_s
{
// Terrain definition.
// These are all of the properties that the floor gets.
char name[TERRAIN_NAME_LEN]; // Lookup name.
size_t splashID; // Splash defintion ID.
size_t footstepID; // Footstep defintion ID.
fixed_t friction; // The default friction of this texture.
UINT8 offroad; // The default offroad level of this texture.
INT16 damageType; // The default damage type of this texture. (Negative means no damage).
UINT8 trickPanel; // Trick panel strength
UINT32 flags; // Flag values (see: terrain_flags_t)
} terrain_t;
typedef struct t_floor_s
{
// Terrain floor definition.
// Ties texture names to a .
// (Could be optimized by using texture IDs instead of names,
// but was concerned because I recall sooomething about those not being netsafe?
// Someone confirm if I just hallucinated that. :V)
char textureName[9]; // Floor texture name.
size_t terrainID; // Terrain definition ID.
} t_floor_t;
/*--------------------------------------------------
size_t K_GetSplashHeapIndex(t_splash_t *splash);
Returns a splash defintion's index in the
splash definition heap.
Input Arguments:-
splash - The splash definition to return the index of.
Return:-
The splash heap index, SIZE_MAX if the splash was invalid.
--------------------------------------------------*/
size_t K_GetSplashHeapIndex(t_splash_t *splash);
/*--------------------------------------------------
size_t K_GetNumSplashDefs(void);
Returns the number of splash definitions.
Input Arguments:-
None
Return:-
Length of splashDefs.
--------------------------------------------------*/
size_t K_GetNumSplashDefs(void);
/*--------------------------------------------------
t_splash_t *K_GetSplashByIndex(size_t checkIndex);
Retrieves a splash definition by its heap index.
Input Arguments:-
checkIndex - The heap index to retrieve.
Return:-
The splash definition, NULL if it didn't exist.
--------------------------------------------------*/
t_splash_t *K_GetSplashByIndex(size_t checkIndex);
/*--------------------------------------------------
t_splash_t *K_GetSplashByName(const char *checkName);
Retrieves a splash definition by its lookup name.
Input Arguments:-
checkName - The lookup name to retrieve.
Return:-
The splash definition, NULL if it didn't exist.
--------------------------------------------------*/
t_splash_t *K_GetSplashByName(const char *checkName);
/*--------------------------------------------------
size_t K_GetFootstepHeapIndex(t_footstep_t *footstep);
Returns a footstep defintion's index in the
footstep definition heap.
Input Arguments:-
footstep - The footstep definition to return the index of.
Return:-
The footstep heap index, SIZE_MAX if the footstep was invalid.
--------------------------------------------------*/
size_t K_GetFootstepHeapIndex(t_footstep_t *footstep);
/*--------------------------------------------------
size_t K_GetNumFootstepDefs(void);
Returns the number of footstep definitions.
Input Arguments:-
None
Return:-
Length of footstepDefs.
--------------------------------------------------*/
size_t K_GetNumFootstepDefs(void);
/*--------------------------------------------------
t_footstep_t *K_GetFootstepByIndex(size_t checkIndex);
Retrieves a footstep definition by its heap index.
Input Arguments:-
checkIndex - The heap index to retrieve.
Return:-
The footstep definition, NULL if it didn't exist.
--------------------------------------------------*/
t_footstep_t *K_GetFootstepByIndex(size_t checkIndex);
/*--------------------------------------------------
t_footstep_t *K_GetFootstepByName(const char *checkName);
Retrieves a footstep definition by its lookup name.
Input Arguments:-
checkName - The lookup name to retrieve.
Return:-
The footstep definition, NULL if it didn't exist.
--------------------------------------------------*/
t_footstep_t *K_GetFootstepByName(const char *checkName);
/*--------------------------------------------------
size_t K_GetTerrainHeapIndex(terrain_t *terrain);
Returns a terrain defintion's index in the
terrain definition heap.
Input Arguments:-
terrain - The terrain definition to return the index of.
Return:-
The terrain heap index, SIZE_MAX if the terrain was invalid.
--------------------------------------------------*/
size_t K_GetTerrainHeapIndex(terrain_t *terrain);
/*--------------------------------------------------
size_t K_GetNumTerrainDefs(void);
Returns the number of terrain definitions.
Input Arguments:-
None
Return:-
Length of terrainDefs.
--------------------------------------------------*/
size_t K_GetNumTerrainDefs(void);
/*--------------------------------------------------
terrain_t *K_GetTerrainByIndex(size_t checkIndex);
Retrieves a terrain definition by its heap index.
Input Arguments:-
checkIndex - The heap index to retrieve.
Return:-
The terrain definition, NULL if it didn't exist.
--------------------------------------------------*/
terrain_t *K_GetTerrainByIndex(size_t checkIndex);
/*--------------------------------------------------
terrain_t *K_GetTerrainByName(const char *checkName);
Retrieves a terrain definition by its lookup name.
Input Arguments:-
checkName - The lookup name to retrieve.
Return:-
The terrain definition, NULL if it didn't exist.
--------------------------------------------------*/
terrain_t *K_GetTerrainByName(const char *checkName);
/*--------------------------------------------------
terrain_t *K_GetDefaultTerrain(void);
Returns the default terrain definition, used
in cases where terrain is not set for a texture.
Input Arguments:-
None
Return:-
The default terrain definition, NULL if it didn't exist.
--------------------------------------------------*/
terrain_t *K_GetDefaultTerrain(void);
/*--------------------------------------------------
terrain_t *K_GetTerrainForTextureName(const char *checkName);
Returns the terrain definition applied to
the texture name inputted.
Input Arguments:-
checkName - The texture's name.
Return:-
The texture's terrain definition if it exists,
otherwise the default terrain if it exists,
otherwise NULL.
--------------------------------------------------*/
terrain_t *K_GetTerrainForTextureName(const char *checkName);
/*--------------------------------------------------
terrain_t *K_GetTerrainForTextureNum(INT32 textureNum);
Returns the terrain definition applied to
the texture ID inputted.
Input Arguments:-
textureNum - The texture's ID.
Return:-
The texture's terrain definition if it exists,
otherwise the default terrain if it exists,
otherwise NULL.
--------------------------------------------------*/
terrain_t *K_GetTerrainForTextureNum(INT32 textureNum);
/*--------------------------------------------------
terrain_t *K_GetTerrainForFlatNum(INT32 flatID);
Returns the terrain definition applied to
the level flat ID.
Input Arguments:-
flatID - The level flat's ID.
Return:-
The level flat's terrain definition if it exists,
otherwise the default terrain if it exists,
otherwise NULL.
--------------------------------------------------*/
terrain_t *K_GetTerrainForFlatNum(INT32 flatID);
/*--------------------------------------------------
void K_UpdateMobjTerrain(mobj_t *mo, INT32 flatID);
Updates an object's terrain pointer, based on
the level flat ID supplied. Intended to be called
when the object moves to new floors.
Input Arguments:-
mo - The object to update.
flatID - The level flat ID the object is standing on.
Return:-
None
--------------------------------------------------*/
void K_UpdateMobjTerrain(mobj_t *mo, INT32 flatID);
/*--------------------------------------------------
void K_ProcessTerrainEffect(mobj_t *mo);
Handles applying terrain effects to the object,
intended to be called in a thinker.
Currently only intended for players, but
could be modified to be inclusive of all
object types.
Input Arguments:-
mo - The object to apply effects to.
Return:-
None
--------------------------------------------------*/
void K_ProcessTerrainEffect(mobj_t *mo);
/*--------------------------------------------------
void K_SetDefaultFriction(mobj_t *mo);
Resets an object to their default friction values.
If they are on terrain with different friction,
they will update to that value.
Input Arguments:-
mo - The object to reset the friction values of.
Return:-
None
--------------------------------------------------*/
void K_SetDefaultFriction(mobj_t *mo);
/*--------------------------------------------------
void K_SpawnSplashForMobj(mobj_t *mo, fixed_t impact);
Spawns the splash particles for an object's
terrain type. Intended to be called when hitting a floor.
Input Arguments:-
mo - The object to spawn a splash for.
Return:-
None
--------------------------------------------------*/
void K_SpawnSplashForMobj(mobj_t *mo, fixed_t impact);
/*--------------------------------------------------
void K_HandleFootstepParticles(mobj_t *mo);
Spawns the footstep particles for an object's
terrain type. Intended to be called every tic.
Input Arguments:-
mo - The object to spawn footsteps for.
Return:-
None
--------------------------------------------------*/
void K_HandleFootstepParticles(mobj_t *mo);
/*--------------------------------------------------
void K_InitTerrain(UINT16 wadNum);
Finds the TERRAIN lumps in a WAD/PK3, and
processes all of them.
Input Arguments:-
wadNum - WAD file ID to process.
Return:-
None
--------------------------------------------------*/
void K_InitTerrain(UINT16 wadNum);
#endif // __K_TERRAIN_H__

View file

@ -1414,7 +1414,7 @@ static int lib_pTeleportMove(lua_State *L)
INLEVEL
if (!thing)
return LUA_ErrInvalid(L, "mobj_t");
LUA_Deprecated(L, "P_TeleportMove", "P_SetOrigin or P_MoveOrigin");
LUA_Deprecated(L, "P_TeleportMove", "P_SetOrigin\" or \"P_MoveOrigin");
lua_pushboolean(L, P_SetOrigin(thing, x, y, z));
LUA_PushUserdata(L, tmthing, META_MOBJ);
P_SetTarget(&tmthing, ptmthing);
@ -1455,6 +1455,42 @@ static int lib_pMoveOrigin(lua_State *L)
return 2;
}
static int lib_pInitAngle(lua_State *L)
{
mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
angle_t newValue = luaL_checkangle(L, 2);
NOHUD
INLEVEL
if (!thing)
return LUA_ErrInvalid(L, "mobj_t");
P_InitAngle(thing, newValue);
return 0;
}
static int lib_pInitPitch(lua_State *L)
{
mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
angle_t newValue = luaL_checkangle(L, 2);
NOHUD
INLEVEL
if (!thing)
return LUA_ErrInvalid(L, "mobj_t");
P_InitPitch(thing, newValue);
return 0;
}
static int lib_pInitRoll(lua_State *L)
{
mobj_t *thing = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
angle_t newValue = luaL_checkangle(L, 2);
NOHUD
INLEVEL
if (!thing)
return LUA_ErrInvalid(L, "mobj_t");
P_InitRoll(thing, newValue);
return 0;
}
static int lib_pSlideMove(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
@ -1978,8 +2014,12 @@ static int lib_pSetSkyboxMobj(lua_State *L)
if (w > 1 || w < 0)
return luaL_error(L, "skybox mobj index %d is out of range for P_SetSkyboxMobj argument #2 (expected 0 or 1)", w);
#if 0
if (!user || P_IsLocalPlayer(user))
skyboxmo[w] = mo;
#else
CONS_Alert(CONS_WARNING, "TODO: P_SetSkyboxMobj is unimplemented\n");
#endif
return 0;
}
@ -3587,11 +3627,10 @@ static int lib_kSpawnSparkleTrail(lua_State *L)
static int lib_kSpawnWipeoutTrail(lua_State *L)
{
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
boolean offroad = lua_optboolean(L, 2);
NOHUD
if (!mo)
return LUA_ErrInvalid(L, "mobj_t");
K_SpawnWipeoutTrail(mo, offroad);
K_SpawnWipeoutTrail(mo);
return 0;
}
@ -3871,6 +3910,9 @@ static luaL_Reg lib[] = {
{"P_TeleportMove",lib_pTeleportMove},
{"P_SetOrigin",lib_pSetOrigin},
{"P_MoveOrigin",lib_pMoveOrigin},
{"P_InitAngle",lib_pInitAngle},
{"P_InitPitch",lib_pInitPitch},
{"P_InitRoll",lib_pInitRoll},
{"P_SlideMove",lib_pSlideMove},
{"P_BounceMove",lib_pBounceMove},
{"P_CheckSight", lib_pCheckSight},

View file

@ -494,9 +494,6 @@ static int mobj_set(lua_State *L)
if (hook_cmd_running)
return luaL_error(L, "Do not alter mobj_t in CMD building code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter mobj_t in BuildCMD code!");
switch(field)
{
case mobj_valid:

View file

@ -281,7 +281,7 @@ static int player_get(lua_State *L)
else if (fastcmp(field,"handleboost"))
lua_pushinteger(L, plr->handleboost);
else if (fastcmp(field,"boostangle"))
lua_pushinteger(L, plr->boostangle);
lua_pushangle(L, plr->boostangle);
else if (fastcmp(field,"draftpower"))
lua_pushinteger(L, plr->draftpower);
else if (fastcmp(field,"draftleeway"))
@ -499,9 +499,6 @@ static int player_set(lua_State *L)
if (hook_cmd_running)
return luaL_error(L, "Do not alter player_t in CMD building code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter player_t in BuildCMD code!");
if (fastcmp(field,"mo")) {
mobj_t *newmo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
plr->mo->player = NULL; // remove player pointer from old mobj
@ -626,7 +623,7 @@ static int player_set(lua_State *L)
else if (fastcmp(field,"handleboost"))
plr->handleboost = luaL_checkinteger(L, 3);
else if (fastcmp(field,"boostangle"))
plr->boostangle = luaL_checkinteger(L, 3);
plr->boostangle = luaL_checkangle(L, 3);
else if (fastcmp(field,"draftpower"))
plr->draftpower = luaL_checkinteger(L, 3);
else if (fastcmp(field,"draftleeway"))
@ -861,7 +858,7 @@ static int karthud_set(lua_State *L)
if (hud_running)
return luaL_error(L, "Do not alter player_t in HUD rendering code!");
if (hook_cmd_running)
return luaL_error(L, "Do not alter player_t in BuildCMD code!");
return luaL_error(L, "Do not alter player_t in CMD building code!");
karthud[ks] = i;
return 0;
}

View file

@ -2680,26 +2680,25 @@ const char *M_FileError(FILE *fp)
/** Return the number of parts of this path.
*/
int M_PathParts(const char *path)
int M_PathParts(const char *p)
{
int n;
const char *p;
const char *t;
if (path == NULL)
int parts = 0;
if (p == NULL)
return 0;
for (n = 0, p = path ;; ++n)
#ifdef _WIN32
if (!strncmp(&p[1], ":\\", 2))
p += 3;
#endif
while (*(p += strspn(p, PATHSEP)))
{
t = p;
if (( p = strchr(p, PATHSEP[0]) ))
p += strspn(p, PATHSEP);
else
{
if (*t)/* there is something after the final delimiter */
n++;
break;
}
parts++;
p += strcspn(p, PATHSEP);
}
return n;
return parts;
}
/** Check whether a path is an absolute path.
@ -2717,50 +2716,43 @@ boolean M_IsPathAbsolute(const char *path)
*/
void M_MkdirEachUntil(const char *cpath, int start, int end, int mode)
{
char path[MAX_WADPATH];
char path[256];
char *p;
char *t;
int n;
int c;
if (end > 0 && end <= start)
return;
strlcpy(path, cpath, sizeof path);
#ifdef _WIN32
if (strncmp(&path[1], ":\\", 2) == 0)
if (!strncmp(&path[1], ":\\", 2))
p = &path[3];
else
#endif
p = path;
if (end > 0)
end -= start;
for (; start > 0; --start)
while (end != 0 && *(p += strspn(p, PATHSEP)))
{
p += strspn(p, PATHSEP);
if (!( p = strchr(p, PATHSEP[0]) ))
return;
}
p += strspn(p, PATHSEP);
for (;;)
{
if (end > 0 && !--end)
break;
n = strcspn(p, PATHSEP);
t = p;
if (( p = strchr(p, PATHSEP[0]) ))
{
*p = '\0';
I_mkdir(path, mode);
*p = PATHSEP[0];
p += strspn(p, PATHSEP);
}
if (start > 0)
start--;
else
{
if (*t)
I_mkdir(path, mode);
break;
c = p[n];
p[n] = '\0';
I_mkdir(path, mode);
p[n] = c;
}
p += n;
if (end > 0)
end--;
}
}
@ -2822,4 +2814,4 @@ const char * M_Ftrim (double f)
dig[i + 1] = '\0';
return &dig[1];/* skip the 0 */
}
}
}

View file

@ -63,6 +63,8 @@ static void MasterServer_OnChange(void);
static void Advertise_OnChange(void);
static void RendezvousServer_OnChange(void);
static CV_PossibleValue_t masterserver_update_rate_cons_t[] = {
{2, "MIN"},
{60, "MAX"},
@ -70,7 +72,7 @@ static CV_PossibleValue_t masterserver_update_rate_cons_t[] = {
};
consvar_t cv_masterserver = CVAR_INIT ("masterserver", "https://ms.kartkrew.org/ms/api", CV_SAVE|CV_CALL, NULL, MasterServer_OnChange);
consvar_t cv_rendezvousserver = CVAR_INIT ("rendezvousserver", "jart-dev.jameds.org", CV_SAVE, NULL, NULL);
consvar_t cv_rendezvousserver = CVAR_INIT ("rendezvousserver", "relay.kartkrew.org", CV_SAVE|CV_CALL, NULL, RendezvousServer_OnChange);
consvar_t cv_servername = CVAR_INIT ("servername", "SRB2Kart server", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Update_parameters);
consvar_t cv_server_contact = CVAR_INIT ("server_contact", "", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Update_parameters);
@ -517,17 +519,6 @@ static void MasterServer_OnChange(void)
#ifdef MASTERSERVER
UnregisterServer();
/*
TODO: remove this for v2, it's just a hack
for those coming in with an old config.
*/
if (
! cv_masterserver.changed &&
strcmp(cv_masterserver.string, "ms.srb2.org:28900") == 0
){
CV_StealthSet(&cv_masterserver, cv_masterserver.defaultvalue);
}
Set_api(cv_masterserver.string);
if (Online())
@ -565,3 +556,16 @@ Advertise_OnChange(void)
DRPC_UpdatePresence();
#endif
}
#ifdef DEVELOP
static void
RendezvousServer_OnChange (void)
{
consvar_t *cvar = &cv_rendezvousserver;
if (!strcmp(cvar->string, "jart-dev.jameds.org"))
CV_StealthSet(cvar, cvar->defaultvalue);
}
#else
#error "This was an indev thing, remove at release."
#endif

View file

@ -1220,7 +1220,7 @@ void A_StatueBurst(mobj_t *actor)
if (!locvar1 || !(new = P_SpawnMobjFromMobj(actor, 0, 0, 0, locvar1)))
return;
new->angle = actor->angle;
P_InitAngle(new, actor->angle);
P_SetTarget(&new->target, actor->target);
if (locvar2)
P_SetMobjState(new, (statenum_t)locvar2);
@ -2519,8 +2519,8 @@ void A_LobShot(mobj_t *actor)
P_SetTarget(&shot->target, actor); // where it came from
shot->angle = an = actor->angle;
an >>= ANGLETOFINESHIFT;
P_InitAngle(shot, actor->angle);
an = actor->angle >> ANGLETOFINESHIFT;
dist = P_AproxDistance(actor->target->x - shot->x, actor->target->y - shot->y);
@ -2886,7 +2886,7 @@ void A_Boss1Laser(mobj_t *actor)
S_StartSound(actor, mobjinfo[locvar1].seesound);
point = P_SpawnMobj(x + P_ReturnThrustX(actor, actor->angle, actor->radius), y + P_ReturnThrustY(actor, actor->angle, actor->radius), actor->z - actor->height / 2, MT_EGGMOBILE_TARGET);
point->angle = actor->angle;
P_InitAngle(point, actor->angle);
point->fuse = dur+1;
P_SetTarget(&point->target, actor->target);
P_SetTarget(&actor->target, point);
@ -2896,7 +2896,7 @@ void A_Boss1Laser(mobj_t *actor)
point = P_SpawnMobj(x, y, z, locvar1);
P_SetTarget(&point->target, actor);
point->angle = actor->angle;
P_InitAngle(point, actor->angle);
speed = point->radius;
point->momz = FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT), speed);
point->momx = FixedMul(FINESINE(angle>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(point->angle>>ANGLETOFINESHIFT), speed));
@ -2905,7 +2905,7 @@ void A_Boss1Laser(mobj_t *actor)
for (i = 0; i < 256; i++)
{
mobj_t *mo = P_SpawnMobj(point->x, point->y, point->z, point->type);
mo->angle = point->angle;
P_InitAngle(mo, point->angle);
mo->color = LASERCOLORS[((UINT8)(i + 3*dur) >> 2) % sizeof(LASERCOLORS)]; // codeing
P_UnsetThingPosition(mo);
mo->flags = MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY;
@ -2937,7 +2937,7 @@ void A_Boss1Laser(mobj_t *actor)
if (z - floorz < mobjinfo[MT_EGGMOBILE_FIRE].height>>1 && dur & 1)
{
point = P_SpawnMobj(x, y, floorz, MT_EGGMOBILE_FIRE);
point->angle = actor->angle;
P_InitAngle(point, actor->angle);
point->destscale = actor->scale;
P_SetScale(point, point->destscale);
P_SetTarget(&point->target, actor);
@ -3521,7 +3521,7 @@ bossjustdie:
P_ReturnThrustX(mo, mo->angle - ANGLE_90, 32<<FRACBITS),
P_ReturnThrustY(mo, mo->angle - ANGLE_90, 32<<FRACBITS),
32<<FRACBITS, MT_BOSSJUNK);
mo2->angle = mo->angle;
P_InitAngle(mo2, mo->angle);
P_InstaThrust(mo2, mo2->angle - ANGLE_90, 4*mo2->scale);
P_SetObjectMomZ(mo2, 4*FRACUNIT, false);
P_SetMobjState(mo2, S_BOSSEGLZ1);
@ -3530,7 +3530,7 @@ bossjustdie:
P_ReturnThrustX(mo, mo->angle + ANGLE_90, 32<<FRACBITS),
P_ReturnThrustY(mo, mo->angle + ANGLE_90, 32<<FRACBITS),
32<<FRACBITS, MT_BOSSJUNK);
mo2->angle = mo->angle;
P_InitAngle(mo2, mo->angle);
P_InstaThrust(mo2, mo2->angle + ANGLE_90, 4*mo2->scale);
P_SetObjectMomZ(mo2, 4*FRACUNIT, false);
P_SetMobjState(mo2, S_BOSSEGLZ2);
@ -3542,7 +3542,7 @@ bossjustdie:
P_ReturnThrustX(mo, mo->angle - ANGLE_90, 32<<FRACBITS),
P_ReturnThrustY(mo, mo->angle - ANGLE_90, 32<<FRACBITS),
32<<FRACBITS, MT_BOSSJUNK);
mo2->angle = mo->angle;
P_InitAngle(mo2, mo->angle);
P_InstaThrust(mo2, mo2->angle - ANGLE_90, 4*mo2->scale);
P_SetObjectMomZ(mo2, 4*FRACUNIT, false);
P_SetMobjState(mo2, S_BOSSTANK1);
@ -3551,7 +3551,7 @@ bossjustdie:
P_ReturnThrustX(mo, mo->angle + ANGLE_90, 32<<FRACBITS),
P_ReturnThrustY(mo, mo->angle + ANGLE_90, 32<<FRACBITS),
32<<FRACBITS, MT_BOSSJUNK);
mo2->angle = mo->angle;
P_InitAngle(mo2, mo->angle);
P_InstaThrust(mo2, mo2->angle + ANGLE_90, 4*mo2->scale);
P_SetObjectMomZ(mo2, 4*FRACUNIT, false);
P_SetMobjState(mo2, S_BOSSTANK2);
@ -3559,7 +3559,7 @@ bossjustdie:
mo2 = P_SpawnMobjFromMobj(mo, 0, 0,
mobjinfo[MT_EGGMOBILE2].height + (32<<FRACBITS),
MT_BOSSJUNK);
mo2->angle = mo->angle;
P_InitAngle(mo2, mo->angle);
P_SetObjectMomZ(mo2, 4*FRACUNIT, false);
mo2->momz += mo->momz;
P_SetMobjState(mo2, S_BOSSSPIGOT);
@ -3568,7 +3568,7 @@ bossjustdie:
case MT_EGGMOBILE3:
{
mo2 = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_BOSSJUNK);
mo2->angle = mo->angle;
P_InitAngle(mo2, mo->angle);
P_SetMobjState(mo2, S_BOSSSEBH1);
}
break;
@ -3642,7 +3642,8 @@ bossjustdie:
pole->tracer->flags |= MF_NOCLIPTHING;
P_SetScale(pole, (pole->destscale = 2*FRACUNIT));
P_SetScale(pole->tracer, (pole->tracer->destscale = 2*FRACUNIT));
pole->angle = pole->tracer->angle = mo->tracer->angle;
P_InitAngle(pole, mo->tracer->angle);
P_InitAngle(pole->tracer, mo->tracer->angle);
pole->tracer->tracer->angle = pole->angle - ANGLE_90;
pole->momx = P_ReturnThrustX(pole, pole->angle, speed);
pole->momy = P_ReturnThrustY(pole, pole->angle, speed);
@ -4011,7 +4012,7 @@ void A_AttractChase(mobj_t *actor)
sparkle = P_SpawnMobj(actor->target->x, actor->target->y, actor->target->z, MT_RINGSPARKS);
P_SetTarget(&sparkle->target, actor->target);
sparkle->angle = (actor->target->angle + (offset>>1)) + (offset * actor->target->player->sparkleanim);
P_InitAngle(sparkle, (actor->target->angle + (offset>>1)) + (offset * actor->target->player->sparkleanim));
actor->target->player->sparkleanim = (actor->target->player->sparkleanim+1) % 20;
P_KillMobj(actor, actor->target, actor->target, DMG_NORMAL);
@ -5265,7 +5266,7 @@ void A_RockSpawn(mobj_t *actor)
mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_FALLINGROCK);
P_SetMobjState(mo, mobjinfo[type].spawnstate);
mo->angle = R_PointToAngle2(line->v2->x, line->v2->y, line->v1->x, line->v1->y);
P_InitAngle(mo, R_PointToAngle2(line->v2->x, line->v2->y, line->v1->x, line->v1->y));
P_InstaThrust(mo, mo->angle, dist + randomoomph);
mo->momz = dist + randomoomph;
@ -7131,7 +7132,7 @@ void A_Boss3ShockThink(mobj_t *actor)
snew->momx = (actor->momx + snext->momx) >> 1;
snew->momy = (actor->momy + snext->momy) >> 1;
snew->momz = (actor->momz + snext->momz) >> 1; // is this really needed?
snew->angle = (actor->angle + snext->angle) >> 1;
P_InitAngle(snew, (actor->angle + snext->angle) >> 1);
P_SetTarget(&snew->target, actor->target);
snew->fuse = actor->fuse;
@ -7283,7 +7284,7 @@ void A_SpawnObjectAbsolute(mobj_t *actor)
mo = P_SpawnMobj(x<<FRACBITS, y<<FRACBITS, z<<FRACBITS, type);
// Spawn objects with an angle matching the spawner's, rather than spawning Eastwards - Monster Iestyn
mo->angle = actor->angle;
P_InitAngle(mo, actor->angle);
if (actor->eflags & MFE_VERTICALFLIP)
mo->flags2 |= MF2_OBJECTFLIP;
@ -7325,7 +7326,7 @@ void A_SpawnObjectRelative(mobj_t *actor)
(actor->eflags & MFE_VERTICALFLIP) ? ((actor->z + actor->height - mobjinfo[type].height) - FixedMul(z<<FRACBITS, actor->scale)) : (actor->z + FixedMul(z<<FRACBITS, actor->scale)), type);
// Spawn objects with an angle matching the spawner's, rather than spawning Eastwards - Monster Iestyn
mo->angle = actor->angle;
P_InitAngle(mo, actor->angle);
if (actor->eflags & MFE_VERTICALFLIP)
mo->flags2 |= MF2_OBJECTFLIP;
@ -8035,7 +8036,7 @@ void A_BossJetFume(mobj_t *actor)
P_SetScale(filler, filler->destscale);
if (actor->eflags & MFE_VERTICALFLIP)
filler->flags2 |= MF2_OBJECTFLIP;
filler->angle = actor->angle - ANGLE_180;
P_InitAngle(filler, actor->angle - ANGLE_180);
P_SetTarget(&actor->tracer, filler);
}*/
@ -9745,7 +9746,7 @@ void A_TrapShot(mobj_t *actor)
S_StartSound(missile, missile->info->seesound);
P_SetTarget(&missile->target, actor);
missile->angle = actor->angle;
P_InitAngle(missile, actor->angle);
speed = FixedMul(missile->info->speed, missile->scale);
@ -10324,7 +10325,7 @@ void A_BrakLobShot(mobj_t *actor)
S_StartSound(shot, shot->info->seesound);
P_SetTarget(&shot->target, actor); // where it came from
shot->angle = actor->angle;
P_InitAngle(shot, actor->angle);
// Horizontal axes first. First parameter is initial horizontal impulse, second is to correct its angle.
shot->momx = FixedMul(FixedMul(v, FINECOSINE(theta >> ANGLETOFINESHIFT)), FINECOSINE(shot->angle >> ANGLETOFINESHIFT));
@ -10391,7 +10392,7 @@ void A_NapalmScatter(mobj_t *actor)
mo = P_SpawnMobj(actor->x, actor->y, actor->z, typeOfShot);
P_SetTarget(&mo->target, actor->target); // Transfer target so Brak doesn't hit himself like an idiot
mo->angle = fa << ANGLETOFINESHIFT;
P_InitAngle(mo, fa << ANGLETOFINESHIFT);
mo->momx = FixedMul(FINECOSINE(fa),vx);
mo->momy = FixedMul(FINESINE(fa),vx);
mo->momz = vy;
@ -10415,7 +10416,7 @@ void A_SpawnFreshCopy(mobj_t *actor)
newObject = P_SpawnMobjFromMobj(actor, 0, 0, 0, actor->type);
newObject->flags2 = actor->flags2 & MF2_AMBUSH;
newObject->angle = actor->angle;
P_InitAngle(newObject, actor->angle);
newObject->color = actor->color;
P_SetTarget(&newObject->target, actor->target);
P_SetTarget(&newObject->tracer, actor->tracer);
@ -10451,7 +10452,7 @@ mobj_t *P_InternalFlickySpawn(mobj_t *actor, mobjtype_t flickytype, fixed_t momz
}
flicky = P_SpawnMobjFromMobj(actor, offsx, offsy, 0, flickytype);
flicky->angle = actor->angle;
P_InitAngle(flicky, actor->angle);
if (flickytype == MT_SEED)
flicky->z += P_MobjFlip(actor)*(actor->height - flicky->height)/2;
@ -10601,7 +10602,7 @@ void A_FlickyCenter(mobj_t *actor)
else if (actor->flags & MF_SLIDEME) // aimless
{
actor->tracer->fuse = 0; // less than 2*TICRATE means move aimlessly.
actor->tracer->angle = P_RandomKey(180)*ANG2;
P_InitAngle(actor->tracer, P_RandomKey(180)*ANG2);
}
else //orbit
actor->tracer->fuse = FRACUNIT;
@ -11302,7 +11303,7 @@ void A_ConnectToGround(mobj_t *actor)
{
work = P_SpawnMobjFromMobj(actor, 0, 0, workz, locvar1);
if (work)
work->angle = ang;
P_InitAngle(work, ang);
ang += ANGLE_90;
workz += workh;
}
@ -11348,7 +11349,7 @@ void A_SpawnParticleRelative(mobj_t *actor)
(actor->eflags & MFE_VERTICALFLIP) ? ((actor->z + actor->height - mobjinfo[MT_PARTICLE].height) - FixedMul(z<<FRACBITS, actor->scale)) : (actor->z + FixedMul(z<<FRACBITS, actor->scale)), MT_PARTICLE);
// Spawn objects with an angle matching the spawner's, rather than spawning Eastwards - Monster Iestyn
mo->angle = actor->angle;
P_InitAngle(mo, actor->angle);
if (actor->eflags & MFE_VERTICALFLIP)
mo->flags2 |= MF2_OBJECTFLIP;
@ -12095,7 +12096,7 @@ void A_Boss5MakeJunk(mobj_t *actor)
broked->fuse = TICRATE;
else
broked->fuse = (((locvar2 & 1) ? 4 : 2)*TICRATE)/3;
broked->angle = ang;
P_InitAngle(broked, ang);
P_InstaThrust(broked, ang, ((locvar2 & 2) ? 8 : 5)*actor->scale);
P_SetObjectMomZ(broked, (((locvar2) ? 4 : 0) + P_RandomRange(2, 5))<<FRACBITS, false);
if (locvar1 > 0)
@ -12174,7 +12175,7 @@ static void P_DustRing(mobjtype_t mobjtype, UINT32 div, fixed_t x, fixed_t y, fi
mobjtype
);
dust->angle = ang*i + ANGLE_90;
P_InitAngle(dust, ang*i + ANGLE_90);
P_SetScale(dust, FixedMul(initscale, scale));
dust->destscale = FixedMul(4*FRACUNIT + P_RandomFixed(), scale);
dust->scalespeed = scale/24;
@ -12379,7 +12380,7 @@ static mobj_t *P_TrainSeg(mobj_t *src, fixed_t x, fixed_t y, fixed_t z, angle_t
s->fuse = 16*TICRATE;
s->sprite = spr;
s->frame = frame|FF_PAPERSPRITE;
s->angle = ang;
P_InitAngle(s, ang);
P_Thrust(s, src->angle, 7*FRACUNIT);
return s;
}
@ -12751,7 +12752,7 @@ void A_SaloonDoorSpawn(mobj_t *actor)
// One door...
if (!(door = P_SpawnMobjFromMobj(actor, c, s, 0, locvar1))) return;
door->angle = ang + ANGLE_180;
P_InitAngle(door, ang + ANGLE_180);
door->extravalue1 = AngleFixed(door->angle); // Origin angle
door->extravalue2 = 0; // Angular speed
P_SetTarget(&door->tracer, actor); // Origin door
@ -12759,7 +12760,7 @@ void A_SaloonDoorSpawn(mobj_t *actor)
// ...two door!
if (!(door = P_SpawnMobjFromMobj(actor, -c, -s, 0, locvar1))) return;
door->angle = ang;
P_InitAngle(door, ang);
door->extravalue1 = AngleFixed(door->angle); // Origin angle
door->extravalue2 = 0; // Angular speed
P_SetTarget(&door->tracer, actor); // Origin door
@ -12955,7 +12956,7 @@ void A_SpawnPterabytes(mobj_t *actor)
c = FINECOSINE(fa);
s = FINESINE(fa);
waypoint = P_SpawnMobjFromMobj(actor, FixedMul(c, rad), FixedMul(s, rad), 0, MT_PTERABYTEWAYPOINT);
waypoint->angle = ang + ANGLE_90;
P_InitAngle(waypoint, ang + ANGLE_90);
P_SetTarget(&waypoint->tracer, actor);
ptera = P_SpawnMobjFromMobj(waypoint, 0, 0, 0, MT_PTERABYTE);
ptera->angle = waypoint->angle;
@ -13129,7 +13130,7 @@ void A_DragonbomberSpawn(mobj_t *actor)
segment = P_SpawnMobjFromMobj(mo, x, y, 0, MT_DRAGONTAIL);
P_SetTarget(&segment->target, mo);
P_SetTarget(&mo->tracer, segment);
segment->angle = mo->angle;
P_InitAngle(segment, mo->angle);
mo = segment;
}
for (i = 0; i < 2; i++) // spawn wings
@ -13399,6 +13400,9 @@ void A_JawzChase(mobj_t *actor)
}
ret = P_SpawnMobj(actor->tracer->x, actor->tracer->y, actor->tracer->z, MT_PLAYERRETICULE);
ret->old_x = actor->tracer->old_x;
ret->old_y = actor->tracer->old_y;
ret->old_z = actor->tracer->old_z;
P_SetTarget(&ret->target, actor->tracer);
ret->frame |= ((leveltime % 10) / 2) + 5;
ret->color = actor->cvmem;
@ -13531,7 +13535,7 @@ static void SpawnSPBDust(mobj_t *mo)
P_SetScale(dust, mo->scale*2);
dust->colorized = true;
dust->color = SKINCOLOR_RED;
dust->angle = mo->angle - FixedAngle(FRACUNIT*90 - FRACUNIT*180*i); // The first one will spawn to the right of the spb, the second one to the left.
P_InitAngle(dust, mo->angle - FixedAngle(FRACUNIT*90 - FRACUNIT*180*i)); // The first one will spawn to the right of the spb, the second one to the left.
P_Thrust(dust, dust->angle, 6*dust->scale);
K_MatchGenericExtraFlags(dust, mo);
@ -13568,7 +13572,7 @@ static void SpawnSPBAIZDust(mobj_t *mo, INT32 dir)
spark->flags = MF_NOGRAVITY|MF_PAIN;
P_SetTarget(&spark->target, mo);
spark->angle = travelangle+(dir*ANGLE_90);
P_InitAngle(spark, travelangle+(dir*ANGLE_90));
P_SetScale(spark, (spark->destscale = mo->scale*3/2));
spark->momx = (6*mo->momx)/5;
@ -13587,7 +13591,7 @@ static void SpawnSPBSpeedLines(mobj_t *actor)
MT_FASTLINE);
P_SetTarget(&fast->target, actor);
fast->angle = K_MomentumAngle(actor);
P_InitAngle(fast, K_MomentumAngle(actor));
fast->color = SKINCOLOR_RED;
fast->colorized = true;
K_MatchGenericExtraFlags(fast, actor);
@ -14103,7 +14107,7 @@ void A_SSMineExplode(mobj_t *actor)
INT32 d;
INT32 locvar1 = var1;
mobjtype_t type;
explodedist = FixedMul((3*actor->info->painchance)/2, mapobjectscale);
explodedist = FixedMul((3*actor->info->painchance)/2, actor->scale);
if (LUA_CallAction(A_SSMINEEXPLODE, actor))
return;
@ -14289,7 +14293,7 @@ void A_RandomShadowFrame(mobj_t *actor)
P_SetScale(fake, FRACUNIT*3/2);
fake->scale = FRACUNIT*3/2;
fake->destscale = FRACUNIT*3/2;
fake->angle = actor->angle;
P_InitAngle(fake, actor->angle);
fake->tics = -1;
actor->renderflags |= RF_DONTDRAW;
actor->extravalue1 = 1;
@ -14677,6 +14681,8 @@ void A_FlameShieldPaper(mobj_t *actor)
paper->frame |= framea;
}
P_InitAngle(paper, paper->angle);
paper->extravalue1 = i;
}
}

View file

@ -1054,6 +1054,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
target->flags |= MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY;
P_SetThingPosition(target);
target->standingslope = NULL;
target->terrain = NULL;
target->pmomz = 0;
target->player->playerstate = PST_DEAD;
@ -1184,7 +1185,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
mo->angle = FixedAngle((P_RandomKey(36)*10)<<FRACBITS);
mo2 = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_BOSSJUNK);
mo2->angle = mo->angle;
P_InitAngle(mo2, mo->angle);
P_SetMobjState(mo2, S_BOSSSEBH2);
if (++i == 2) // we've already removed 2 of these, let's stop now
@ -1251,6 +1252,12 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
kart->eflags |= MFE_DAMAGEHITLAG;
P_SetObjectMomZ(kart, 6*FRACUNIT, false);
kart->extravalue1 = target->player->kartweight;
// Copy interp data
kart->old_angle = target->old_angle;
kart->old_x = target->old_x;
kart->old_y = target->old_y;
kart->old_z = target->old_z;
}
if (source && !P_MobjWasRemoved(source))
@ -1322,7 +1329,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
for (i = 0; i < 2; i++)
{
mobj_t *blast = P_SpawnMobjFromMobj(target, 0, 0, target->info->height >> 1, MT_BATTLEBUMPER_BLAST);
blast->angle = angle + i*ANGLE_90;
P_InitAngle(blast, angle + i*ANGLE_90);
P_SetScale(blast, 2*blast->scale/3);
blast->destscale = 2*blast->scale;
}
@ -1547,7 +1554,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
chunk = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_SPIKE);\
P_SetMobjState(chunk, target->info->xdeathstate);\
chunk->health = 0;\
chunk->angle = angtweak;\
P_InitAngle(chunk, angtweak);\
P_UnsetThingPosition(chunk);\
chunk->flags = MF_NOCLIP;\
chunk->x += xmov;\
@ -1569,7 +1576,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
chunk = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_SPIKE);
P_SetMobjState(chunk, target->info->deathstate);
chunk->health = 0;
chunk->angle = ang + ANGLE_180;
P_InitAngle(chunk, ang + ANGLE_180);
P_UnsetThingPosition(chunk);
chunk->flags = MF_NOCLIP;
chunk->x -= xoffs;
@ -1615,7 +1622,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
chunk = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_WALLSPIKE);\
P_SetMobjState(chunk, target->info->xdeathstate);\
chunk->health = 0;\
chunk->angle = target->angle;\
P_InitAngle(chunk, target->angle);\
P_UnsetThingPosition(chunk);\
chunk->flags = MF_NOCLIP;\
chunk->x += xmov - forwardxoffs;\
@ -1641,7 +1648,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
P_SetMobjState(chunk, target->info->deathstate);
chunk->health = 0;
chunk->angle = target->angle;
P_InitAngle(chunk, target->angle);
P_UnsetThingPosition(chunk);
chunk->flags = MF_NOCLIP;
chunk->x += forwardxoffs - xoffs;
@ -1766,7 +1773,7 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source,
boom = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_FZEROBOOM);
boom->scale = player->mo->scale;
boom->angle = player->mo->angle;
P_InitAngle(boom, player->mo->angle);
P_SetTarget(&boom->target, player->mo);
}
@ -1838,7 +1845,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (!(target->flags & MF_SHOOTABLE))
return false; // shouldn't happen...
if (!(damagetype & DMG_DEATHMASK) && target->hitlag > 0)
if (!(damagetype & DMG_DEATHMASK) && target->hitlag > 0 && inflictor == NULL)
return false;
}
@ -1922,7 +1929,18 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (combo == false)
{
if (player->flashing > 0)
// Check if we should allow wombo combos (DMG_WOMBO)
boolean allowcombo = false;
// For MISSILE OBJECTS, allow combo BY DEFAULT. If DMG_WOMBO is set, do *NOT* allow it.
if (inflictor && !P_MobjWasRemoved(inflictor) && (inflictor->flags & MF_MISSILE) && !(damagetype & DMG_WOMBO))
allowcombo = true;
// OTHERWISE, only allow combos IF DMG_WOMBO *IS* set.
else if (damagetype & DMG_WOMBO)
allowcombo = true;
if ((player->mo->hitlag == 0 || allowcombo == false) && player->flashing > 0)
{
// Post-hit invincibility
K_DoInstashield(player);

View file

@ -123,7 +123,7 @@ struct demofreecam_s {
camera_t *cam; // this is useful when the game is paused, notably
mobj_t *soundmobj; // mobj to play sound from, used in s_sound
angle_t localangle; // keeps track of the cam angle for cmds
angle_t localaiming; // ditto with aiming
boolean turnheld; // holding turn button for gradual turn speed
@ -168,7 +168,7 @@ boolean P_IsObjectOnGroundIn(mobj_t *mo, sector_t *sec);
boolean P_IsObjectOnRealGround(mobj_t *mo, sector_t *sec); // SRB2Kart
#define P_IsObjectFlipped(o) ((o)->eflags & MFE_VERTICALFLIP)
boolean P_InQuicksand(mobj_t *mo);
boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff);
boolean P_PlayerHitFloor(player_t *player, boolean fromAir);
void P_SetObjectMomZ(mobj_t *mo, fixed_t value, boolean relative);
void P_RestoreMusic(player_t *player);
@ -385,6 +385,7 @@ extern camera_t *mapcampointer;
extern fixed_t tmx;
extern fixed_t tmy;
extern pslope_t *tmfloorslope, *tmceilingslope;
extern INT32 tmfloorpic, tmceilingpic;
/* cphipps 2004/08/30 */
extern void P_MapStart(void);
@ -410,6 +411,9 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff);
boolean P_Move(mobj_t *actor, fixed_t speed);
boolean P_SetOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z);
boolean P_MoveOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z);
void P_InitAngle(mobj_t *thing, angle_t newValue);
void P_InitPitch(mobj_t *thing, angle_t newValue);
void P_InitRoll(mobj_t *thing, angle_t newValue);
void P_SlideMove(mobj_t *mo);
void P_BouncePlayerMove(mobj_t *mo);
void P_BounceMove(mobj_t *mo);
@ -482,6 +486,7 @@ typedef struct BasicFF_s
#define DMG_SPECTATOR 0x83
#define DMG_TIMEOVER 0x84
// Masks
#define DMG_WOMBO 0x10 // Flag - setting this flag allows objects to damage you if you're already in spinout. The effect is reversed on objects with MF_MISSILE (setting it prevents them from comboing in spinout)
#define DMG_STEAL 0x20 // Flag - can steal bumpers, will only deal damage to players, and will not deal damage outside Battle Mode.
#define DMG_CANTHURTSELF 0x40 // Flag - cannot hurt your self or your team
#define DMG_DEATHMASK DMG_INSTAKILL // if bit 7 is set, this is a death type instead of a damage type
@ -530,5 +535,6 @@ fixed_t P_ScaleFromMap(fixed_t n, fixed_t scale);
fixed_t P_GetMobjHead(const mobj_t *);
fixed_t P_GetMobjFeet(const mobj_t *);
fixed_t P_GetMobjGround(const mobj_t *);
fixed_t P_GetMobjZMovement(mobj_t *mo);
#endif // __P_LOCAL__

View file

@ -24,12 +24,13 @@
#include "r_sky.h"
#include "s_sound.h"
#include "w_wad.h"
#include "k_kart.h" // SRB2kart 011617
#include "k_collide.h"
#include "k_respawn.h"
#include "hu_stuff.h" // SRB2kart
#include "i_system.h" // SRB2kart
#include "k_terrain.h"
#include "r_splats.h"
@ -60,6 +61,7 @@ mobj_t *tmfloorthing; // the thing corresponding to tmfloorz or NULL if tmfloorz
mobj_t *tmhitthing; // the solid thing you bumped into (for collisions)
ffloor_t *tmfloorrover, *tmceilingrover;
pslope_t *tmfloorslope, *tmceilingslope;
INT32 tmfloorpic, tmceilingpic;
static fixed_t tmfloorstep;
static fixed_t tmceilingstep;
@ -155,6 +157,30 @@ boolean P_MoveOrigin(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z)
return P_TeleportMove(thing, x, y, z);
}
//
// P_InitAngle - Change an object's angle, including interp values.
//
void P_InitAngle(mobj_t *thing, angle_t newValue)
{
thing->angle = thing->old_angle = newValue;
}
//
// P_InitPitch - Change an object's pitch, including interp values.
//
void P_InitPitch(mobj_t *thing, angle_t newValue)
{
thing->pitch = thing->old_pitch = newValue;
}
//
// P_InitRoll - Change an object's roll, including interp values.
//
void P_InitRoll(mobj_t *thing, angle_t newValue)
{
thing->roll = thing->old_roll = newValue;
}
// =========================================================================
// MOVEMENT ITERATOR FUNCTIONS
// =========================================================================
@ -267,9 +293,7 @@ static boolean P_SpecialIsLinedefCrossType(line_t *ld)
//
boolean P_DoSpring(mobj_t *spring, mobj_t *object)
{
//INT32 pflags;
const fixed_t hscale = mapobjectscale + (mapobjectscale - object->scale);
const fixed_t vscale = mapobjectscale + (object->scale - mapobjectscale);
const fixed_t scaleVal = FixedSqrt(FixedMul(mapobjectscale, spring->scale));
fixed_t vertispeed = spring->info->mass;
fixed_t horizspeed = spring->info->damage;
UINT16 starcolor = (spring->info->painchance % numskincolors);
@ -303,6 +327,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
}
object->standingslope = NULL; // Okay, now we know it's not going to be relevant - no launching off at silly angles for you.
object->terrain = NULL;
object->eflags |= MFE_SPRUNG; // apply this flag asap!
spring->flags &= ~(MF_SOLID|MF_SPECIAL); // De-solidify
@ -346,13 +371,13 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
if (vertispeed)
{
object->momz = FixedMul(vertispeed, FixedSqrt(FixedMul(vscale, spring->scale)));
object->momz = FixedMul(vertispeed, scaleVal);
}
if (horizspeed)
{
angle_t finalAngle = spring->angle;
fixed_t finalSpeed = FixedMul(horizspeed, FixedSqrt(FixedMul(hscale, spring->scale)));
fixed_t finalSpeed = FixedMul(horizspeed, scaleVal);
fixed_t objectSpeed;
if (object->player)
@ -408,7 +433,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
mobj_t *grease;
grease = P_SpawnMobj(object->x, object->y, object->z, MT_TIREGREASE);
P_SetTarget(&grease->target, object);
grease->angle = K_MomentumAngle(object);
P_InitAngle(grease, K_MomentumAngle(object));
grease->extravalue1 = i;
}
@ -444,6 +469,7 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object)
}
object->standingslope = NULL; // No launching off at silly angles for you.
object->terrain = NULL;
switch (spring->type)
{
@ -756,7 +782,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
return true;
// Player Damage
P_DamageMobj(tmthing, ((thing->type == MT_BUBBLESHIELD) ? thing->target : thing), thing, 1, DMG_NORMAL);
P_DamageMobj(tmthing, ((thing->type == MT_BUBBLESHIELD) ? thing->target : thing), thing, 1, DMG_NORMAL|DMG_WOMBO);
S_StartSound(thing, sfx_s3k44);
}
else
@ -1430,6 +1456,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
tmfloorz = thing->z + thing->height;
tmfloorrover = NULL;
tmfloorslope = NULL;
tmfloorpic = -1;
}
return true;
}
@ -1449,6 +1476,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
tmfloorz = tmceilingz = topz; // block while in air
tmceilingrover = NULL;
tmceilingslope = NULL;
tmceilingpic = -1;
tmfloorthing = thing; // needed for side collision
}
else if (topz < tmceilingz && tmthing->z <= thing->z+thing->height)
@ -1456,6 +1484,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
tmceilingz = topz;
tmceilingrover = NULL;
tmceilingslope = NULL;
tmceilingpic = -1;
tmfloorthing = thing; // thing we may stand on
}
}
@ -1471,6 +1500,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
tmceilingz = thing->z;
tmceilingrover = NULL;
tmceilingslope = NULL;
tmceilingpic = -1;
}
return true;
}
@ -1490,6 +1520,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
tmfloorz = tmceilingz = topz; // block while in air
tmfloorrover = NULL;
tmfloorslope = NULL;
tmfloorpic = -1;
tmfloorthing = thing; // needed for side collision
}
else if (topz > tmfloorz && tmthing->z+tmthing->height >= thing->z)
@ -1497,6 +1528,7 @@ static boolean PIT_CheckThing(mobj_t *thing)
tmfloorz = topz;
tmfloorrover = NULL;
tmfloorslope = NULL;
tmfloorpic = -1;
tmfloorthing = thing; // thing we may stand on
}
}
@ -1676,6 +1708,7 @@ static boolean PIT_CheckLine(line_t *ld)
ceilingline = ld;
tmceilingrover = openceilingrover;
tmceilingslope = opentopslope;
tmceilingpic = opentoppic;
tmceilingstep = openceilingstep;
if (thingtop == tmthing->ceilingz)
{
@ -1688,6 +1721,7 @@ static boolean PIT_CheckLine(line_t *ld)
tmfloorz = openbottom;
tmfloorrover = openfloorrover;
tmfloorslope = openbottomslope;
tmfloorpic = openbottompic;
tmfloorstep = openfloorstep;
if (tmthing->z == tmthing->floorz)
{
@ -1784,6 +1818,8 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
tmceilingrover = NULL;
tmfloorslope = newsubsec->sector->f_slope;
tmceilingslope = newsubsec->sector->c_slope;
tmfloorpic = newsubsec->sector->floorpic;
tmceilingpic = newsubsec->sector->ceilingpic;
tmfloorstep = 0;
tmceilingstep = 0;
@ -1837,6 +1873,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
tmfloorz = topheight - sinklevel;
tmfloorrover = rover;
tmfloorslope = *rover->t_slope;
tmfloorpic = *rover->toppic;
}
}
else if (thing->eflags & MFE_VERTICALFLIP && thingtop <= bottomheight + sinklevel && thing->momz >= 0)
@ -1845,6 +1882,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
tmceilingz = bottomheight + sinklevel;
tmceilingrover = rover;
tmceilingslope = *rover->b_slope;
tmceilingpic = *rover->bottompic;
}
}
}
@ -1868,6 +1906,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
tmfloorz = thing->z;
tmfloorrover = rover;
tmfloorslope = NULL;
tmfloorpic = *rover->toppic;
}
}
// Quicksand blocks never change heights otherwise.
@ -1885,6 +1924,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
tmfloorz = tmdropoffz = topheight;
tmfloorrover = rover;
tmfloorslope = *rover->t_slope;
tmfloorpic = *rover->toppic;
}
if (bottomheight < tmceilingz && abs(delta1) >= abs(delta2)
&& !(rover->flags & FF_PLATFORM)
@ -1893,6 +1933,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
tmceilingz = tmdrpoffceilz = bottomheight;
tmceilingrover = rover;
tmceilingslope = *rover->b_slope;
tmceilingpic = *rover->bottompic;
}
}
}
@ -1967,12 +2008,14 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y)
tmfloorz = tmdropoffz = polytop;
tmfloorslope = NULL;
tmfloorrover = NULL;
tmfloorpic = polysec->ceilingpic;
}
if (polybottom < tmceilingz && abs(delta1) >= abs(delta2)) {
tmceilingz = tmdrpoffceilz = polybottom;
tmceilingslope = NULL;
tmceilingrover = NULL;
tmceilingpic = polysec->floorpic;
}
}
plink = (polymaplink_t *)(plink->link.next);
@ -2390,6 +2433,8 @@ boolean PIT_PushableMoved(mobj_t *thing)
ffloor_t *oldceilrover = tmceilingrover;
pslope_t *oldfslope = tmfloorslope;
pslope_t *oldcslope = tmceilingslope;
INT32 oldfpic = tmfloorpic;
INT32 oldcpic = tmceilingpic;
// Move the player
P_TryMove(thing, thing->x+stand->momx, thing->y+stand->momy, true);
@ -2406,6 +2451,8 @@ boolean PIT_PushableMoved(mobj_t *thing)
tmceilingrover = oldceilrover;
tmfloorslope = oldfslope;
tmceilingslope = oldcslope;
tmfloorpic = oldfpic;
tmceilingpic = oldcpic;
thing->momz = stand->momz;
}
else
@ -2655,9 +2702,14 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
if (!(thing->flags & MF_NOCLIPHEIGHT))
{
// Assign thing's standingslope if needed
if (thing->z <= tmfloorz && !(thing->eflags & MFE_VERTICALFLIP)) {
if (thing->z <= tmfloorz && !(thing->eflags & MFE_VERTICALFLIP))
{
K_UpdateMobjTerrain(thing, tmfloorpic);
if (!startingonground && tmfloorslope)
{
P_HandleSlopeLanding(thing, tmfloorslope);
}
if (thing->momz <= 0)
{
@ -2665,12 +2717,19 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
P_SetPitchRollFromSlope(thing, thing->standingslope);
if (thing->momz == 0 && thing->player && !startingonground)
{
P_PlayerHitFloor(thing->player, true);
}
}
}
else if (thing->z+thing->height >= tmceilingz && (thing->eflags & MFE_VERTICALFLIP)) {
else if (thing->z+thing->height >= tmceilingz && (thing->eflags & MFE_VERTICALFLIP))
{
K_UpdateMobjTerrain(thing, tmceilingpic);
if (!startingonground && tmceilingslope)
{
P_HandleSlopeLanding(thing, tmceilingslope);
}
if (thing->momz >= 0)
{
@ -2678,12 +2737,18 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
P_SetPitchRollFromSlope(thing, thing->standingslope);
if (thing->momz == 0 && thing->player && !startingonground)
{
P_PlayerHitFloor(thing->player, true);
}
}
}
}
else // don't set standingslope if you're not going to clip against it
else
{
// don't set standingslope if you're not going to clip against it
thing->standingslope = NULL;
thing->terrain = NULL;
}
/* FIXME: slope step down (even up) has some false
positives, so just ignore them entirely. */
@ -3431,6 +3496,9 @@ void P_SlideMove(mobj_t *mo)
vertex_t v1, v2; // fake vertexes
line_t junk; // fake linedef
if (P_MobjWasRemoved(mo))
return;
if (tmhitthing && mo->z + mo->height > tmhitthing->z && mo->z < tmhitthing->z + tmhitthing->height)
{
// Don't mess with your momentum if it's a pushable object. Pushables do their own crazy things already.
@ -3667,7 +3735,7 @@ stairstep:
tmymove = 0;
}
if (!P_TryMove(mo, newx, newy, true)) {
if (success)
if (success || P_MobjWasRemoved(mo))
return; // Good enough!!
else
goto retry;
@ -3791,6 +3859,9 @@ void P_BounceMove(mobj_t *mo)
INT32 hitcount;
fixed_t mmomx = 0, mmomy = 0;
if (P_MobjWasRemoved(mo))
return;
if (mo->player)
{
P_BouncePlayerMove(mo);
@ -3914,7 +3985,11 @@ bounceback:
mo->momy = tmymove;
if (!P_TryMove(mo, mo->x + tmxmove, mo->y + tmymove, true))
{
if (P_MobjWasRemoved(mo))
return;
goto retry;
}
}
//

View file

@ -342,6 +342,7 @@ fixed_t openceilingstep;
fixed_t openceilingdrop;
fixed_t openfloorstep;
fixed_t openfloordrop;
INT32 opentoppic, openbottompic;
// P_CameraLineOpening
// P_LineOpening, but for camera
@ -537,6 +538,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
highceiling = INT32_MIN;
lowfloor = INT32_MAX;
opentopslope = openbottomslope = NULL;
opentoppic = openbottompic = -1;
openceilingstep = 0;
openceilingdrop = 0;
openfloorstep = 0;
@ -556,6 +558,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
opentop = height[lo];
highceiling = height[hi];
opentopslope = sector[lo]->c_slope;
opentoppic = sector[lo]->ceilingpic;
if (mobj)
{
@ -575,6 +578,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
openbottom = height[hi];
lowfloor = height[lo];
openbottomslope = sector[hi]->f_slope;
openbottompic = sector[hi]->floorpic;
if (mobj)
{
@ -747,6 +751,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
if (bottomheight < open[FRONT].top) {
open[FRONT].top = bottomheight;
opentopslope = *rover->b_slope;
opentoppic = *rover->bottompic;
open[FRONT].ceilingrover = rover;
}
else if (bottomheight < highceiling)
@ -758,6 +763,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
if (topheight > open[FRONT].bottom) {
open[FRONT].bottom = topheight;
openbottomslope = *rover->t_slope;
openbottompic = *rover->toppic;
open[FRONT].floorrover = rover;
}
else if (topheight > lowfloor)
@ -789,6 +795,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
if (bottomheight < open[BACK].top) {
open[BACK].top = bottomheight;
opentopslope = *rover->b_slope;
opentoppic = *rover->bottompic;
open[BACK].ceilingrover = rover;
}
else if (bottomheight < highceiling)
@ -800,6 +807,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
if (topheight > open[BACK].bottom) {
open[BACK].bottom = topheight;
openbottomslope = *rover->t_slope;
openbottompic = *rover->toppic;
open[BACK].floorrover = rover;
}
else if (topheight > lowfloor)

View file

@ -63,6 +63,7 @@ extern fixed_t openceilingstep;
extern fixed_t openceilingdrop;
extern fixed_t openfloorstep;
extern fixed_t openfloordrop;
extern INT32 opentoppic, openbottompic;
void P_LineOpening(line_t *plinedef, mobj_t *mobj);

View file

@ -40,6 +40,7 @@
#include "k_color.h"
#include "k_respawn.h"
#include "k_bot.h"
#include "k_terrain.h"
static CV_PossibleValue_t CV_BobSpeed[] = {{0, "MIN"}, {4*FRACUNIT, "MAX"}, {0, NULL}};
consvar_t cv_movebob = CVAR_INIT ("movebob", "1.0", CV_FLOAT|CV_SAVE, CV_BobSpeed, NULL);
@ -1201,7 +1202,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo)
gravityadd = -((gravityadd/5) + (gravityadd/8));
}
gravityadd = FixedMul(gravityadd, mo->scale);
gravityadd = FixedMul(gravityadd, mapobjectscale);
return gravityadd;
}
@ -1340,7 +1341,7 @@ static void P_XYFriction(mobj_t *mo, fixed_t oldx, fixed_t oldy)
mo->momy = FixedMul(mo->momy, mo->friction);
}
mo->friction = ORIG_FRICTION;
K_SetDefaultFriction(mo);
}
}
else
@ -1505,7 +1506,10 @@ void P_XYMovement(mobj_t *mo)
oldy = mo->y;
if (mo->flags & MF_NOCLIPHEIGHT)
{
mo->standingslope = NULL;
mo->terrain = NULL;
}
// adjust various things based on slope
if (mo->standingslope && abs(mo->standingslope->zdelta) > FRACUNIT>>8) {
@ -1671,6 +1675,7 @@ void P_XYMovement(mobj_t *mo)
{
mo->momz = transfermomz;
mo->standingslope = NULL;
mo->terrain = NULL;
P_SetPitchRoll(mo, ANGLE_90,
transferslope->xydirection
+ (transferslope->zangle
@ -1684,11 +1689,15 @@ void P_XYMovement(mobj_t *mo)
if (mo->flags & MF_SLIDEME)
{
P_SlideMove(mo);
if (P_MobjWasRemoved(mo))
return;
xmove = ymove = 0;
}
else
{
P_BounceMove(mo);
if (P_MobjWasRemoved(mo))
return;
xmove = ymove = 0;
S_StartSound(mo, mo->info->activesound);
@ -1782,6 +1791,7 @@ void P_XYMovement(mobj_t *mo)
mo->momz = P_MobjFlip(mo)*FRACUNIT/2;
mo->z = predictedz + P_MobjFlip(mo);
mo->standingslope = NULL;
mo->terrain = NULL;
//CONS_Printf("Launched off of flat surface running into downward slope\n");
}
}
@ -1837,6 +1847,9 @@ void P_SceneryXYMovement(mobj_t *mo)
if (!P_SceneryTryMove(mo, mo->x + mo->momx, mo->y + mo->momy))
P_BounceMove(mo);
if (P_MobjWasRemoved(mo))
return;
if ((!(mo->eflags & MFE_VERTICALFLIP) && mo->z > mo->floorz) || (mo->eflags & MFE_VERTICALFLIP && mo->z+mo->height < mo->ceilingz))
return; // no friction when airborne
@ -2274,6 +2287,8 @@ boolean P_ZMovement(mobj_t *mo)
}
P_CheckPosition(mo, mo->x, mo->y); // Sets mo->standingslope correctly
K_UpdateMobjTerrain(mo, ((mo->eflags & MFE_VERTICALFLIP) ? tmceilingpic : tmfloorpic));
if (((mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope) && (mo->type != MT_STEAM))
{
mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope;
@ -2383,7 +2398,7 @@ boolean P_ZMovement(mobj_t *mo)
MT_KART_TIRE
);
tire->angle = mo->angle;
P_InitAngle(tire, mo->angle);
tire->fuse = 3*TICRATE;
P_InstaThrust(tire, tireAngle, 4 * mo->scale);
P_SetObjectMomZ(tire, 4*FRACUNIT, false);
@ -2403,7 +2418,7 @@ boolean P_ZMovement(mobj_t *mo)
MT_KART_TIRE
);
tire->angle = mo->angle;
P_InitAngle(tire, mo->angle);
tire->fuse = 3*TICRATE;
P_InstaThrust(tire, tireAngle, 4 * mo->scale);
P_SetObjectMomZ(tire, 4*FRACUNIT, false);
@ -2503,12 +2518,17 @@ boolean P_ZMovement(mobj_t *mo)
if (mo->type == MT_STEAM)
return true;
}
else if (!(mo->flags & MF_NOGRAVITY)) // Gravity here!
else
{
/// \todo may not be needed (done in P_MobjThinker normally)
mo->eflags &= ~MFE_JUSTHITFLOOR;
mo->terrain = NULL;
P_CheckGravity(mo, true);
if (!(mo->flags & MF_NOGRAVITY)) // Gravity here!
{
/// \todo may not be needed (done in P_MobjThinker normally)
mo->eflags &= ~MFE_JUSTHITFLOOR;
P_CheckGravity(mo, true);
}
}
if (((mo->z + mo->height > mo->ceilingz && !(mo->eflags & MFE_VERTICALFLIP))
@ -2712,20 +2732,29 @@ void P_PlayerZMovement(mobj_t *mo)
if (onground && !(mo->flags & MF_NOCLIPHEIGHT))
{
if (mo->eflags & MFE_VERTICALFLIP)
{
mo->z = mo->ceilingz - mo->height;
}
else
{
mo->z = mo->floorz;
}
K_UpdateMobjTerrain(mo, (mo->eflags & MFE_VERTICALFLIP ? tmceilingpic : tmfloorpic));
// Get up if you fell.
if (mo->player->panim == PA_HURT && mo->player->spinouttimer == 0 && mo->player->tumbleBounces == 0)
{
P_SetPlayerMobjState(mo, S_KART_STILL);
}
if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)) {
if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope))
{
// Handle landing on slope during Z movement
P_HandleSlopeLanding(mo, (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope));
}
if (P_MobjFlip(mo)*mo->momz < 0) // falling
if (P_MobjFlip(mo) * mo->momz < 0) // falling
{
boolean clipmomz = !(P_CheckDeathPitCollide(mo));
@ -2736,29 +2765,38 @@ void P_PlayerZMovement(mobj_t *mo)
P_PlayerPolyObjectZMovement(mo);
if (clipmomz)
{
mo->momz = (tmfloorthing ? tmfloorthing->momz : 0);
}
}
else if (tmfloorthing)
mo->momz = tmfloorthing->momz;
}
else if (!(mo->flags & MF_NOGRAVITY)) // Gravity here!
{
if (P_IsObjectInGoop(mo) && !(mo->flags & MF_NOCLIPHEIGHT))
{
if (mo->z < mo->floorz)
{
mo->z = mo->floorz;
mo->momz = 0;
}
else if (mo->z + mo->height > mo->ceilingz)
{
mo->z = mo->ceilingz - mo->height;
mo->momz = 0;
}
mo->momz = tmfloorthing->momz;
}
}
else
{
mo->terrain = NULL;
if (!(mo->flags & MF_NOGRAVITY)) // Gravity here!
{
if (P_IsObjectInGoop(mo) && !(mo->flags & MF_NOCLIPHEIGHT))
{
if (mo->z < mo->floorz)
{
mo->z = mo->floorz;
mo->momz = 0;
}
else if (mo->z + mo->height > mo->ceilingz)
{
mo->z = mo->ceilingz - mo->height;
mo->momz = 0;
}
}
/// \todo may not be needed (done in P_MobjThinker normally)
mo->eflags &= ~MFE_JUSTHITFLOOR;
P_CheckGravity(mo, true);
}
/// \todo may not be needed (done in P_MobjThinker normally)
mo->eflags &= ~MFE_JUSTHITFLOOR;
P_CheckGravity(mo, true);
}
if (((mo->eflags & MFE_VERTICALFLIP && mo->z < mo->floorz) || (!(mo->eflags & MFE_VERTICALFLIP) && mo->z + mo->height > mo->ceilingz))
@ -3048,6 +3086,26 @@ void P_MobjCheckWater(mobj_t *mobj)
}
}
if (mobj->terrain != NULL)
{
if (mobj->terrain->flags & TRF_LIQUID)
{
// This floor is water.
mobj->eflags |= MFE_TOUCHWATER;
if (mobj->eflags & MFE_VERTICALFLIP)
{
mobj->watertop = thingtop + height;
mobj->waterbottom = thingtop;
}
else
{
mobj->watertop = mobj->z;
mobj->waterbottom = mobj->z - height;
}
}
}
if (mobj->watertop > top2)
mobj->watertop = top2;
@ -3056,7 +3114,9 @@ void P_MobjCheckWater(mobj_t *mobj)
// Spectators and dead players don't get to do any of the things after this.
if (p && (p->spectator || p->playerstate != PST_LIVE))
{
return;
}
// The rest of this code only executes on a water state change.
if (!!(mobj->eflags & MFE_UNDERWATER) == wasinwater)
@ -3073,6 +3133,30 @@ void P_MobjCheckWater(mobj_t *mobj)
|| ((mobj->info->flags & MF_PUSHABLE) && mobj->fuse) // Previously pushable, might be moving still
)
{
fixed_t waterZ = INT32_MAX;
fixed_t solidZ = INT32_MAX;
fixed_t diff = INT32_MAX;
fixed_t thingZ = INT32_MAX;
boolean splashValid = false;
if (mobj->eflags & MFE_VERTICALFLIP)
{
waterZ = mobj->waterbottom;
solidZ = mobj->ceilingz;
}
else
{
waterZ = mobj->watertop;
solidZ = mobj->floorz;
}
diff = waterZ - solidZ;
if (mobj->eflags & MFE_VERTICALFLIP)
{
diff = -diff;
}
// Time to spawn the bubbles!
{
INT32 i;
@ -3131,12 +3215,15 @@ void P_MobjCheckWater(mobj_t *mobj)
// Check to make sure you didn't just cross into a sector to jump out of
// that has shallower water than the block you were originally in.
if ((!(mobj->eflags & MFE_VERTICALFLIP) && mobj->watertop-mobj->floorz <= height>>1)
|| ((mobj->eflags & MFE_VERTICALFLIP) && mobj->ceilingz-mobj->waterbottom <= height>>1))
if (diff <= (height >> 1))
{
return;
}
if (mobj->eflags & MFE_GOOWATER || wasingoo) { // Decide what happens to your momentum when you enter/leave goopy water.
if (P_MobjFlip(mobj)*mobj->momz > 0)
if (mobj->eflags & MFE_GOOWATER || wasingoo)
{
// Decide what happens to your momentum when you enter/leave goopy water.
if (P_MobjFlip(mobj) * mobj->momz > 0)
{
mobj->momz -= (mobj->momz/8); // cut momentum a little bit to prevent multiple bobs
//CONS_Printf("leaving\n");
@ -3148,25 +3235,42 @@ void P_MobjCheckWater(mobj_t *mobj)
//CONS_Printf("entering\n");
}
}
else if (wasinwater && P_MobjFlip(mobj)*mobj->momz > 0)
mobj->momz = FixedMul(mobj->momz, FixedDiv(780*FRACUNIT, 457*FRACUNIT)); // Give the mobj a little out-of-water boost.
if (P_MobjFlip(mobj)*mobj->momz < 0)
else if (wasinwater && P_MobjFlip(mobj) * mobj->momz > 0)
{
if ((mobj->eflags & MFE_VERTICALFLIP && thingtop-(height>>1)-mobj->momz <= mobj->waterbottom)
|| (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z+(height>>1)-mobj->momz >= mobj->watertop))
// Give the mobj a little out-of-water boost.
mobj->momz = FixedMul(mobj->momz, FixedDiv(780*FRACUNIT, 457*FRACUNIT));
}
if (mobj->eflags & MFE_VERTICALFLIP)
{
thingZ = thingtop - (height >> 1);
splashValid = (thingZ - mobj->momz <= waterZ);
}
else
{
thingZ = mobj->z + (height >> 1);
splashValid = (thingZ - mobj->momz >= waterZ);
}
if (P_MobjFlip(mobj) * mobj->momz <= 0)
{
if (splashValid == true)
{
// Spawn a splash
mobj_t *splish;
mobjtype_t splishtype = (mobj->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH;
if (mobj->eflags & MFE_VERTICALFLIP)
{
splish = P_SpawnMobj(mobj->x, mobj->y, mobj->waterbottom-FixedMul(mobjinfo[splishtype].height, mobj->scale), splishtype);
splish = P_SpawnMobj(mobj->x, mobj->y, waterZ - FixedMul(mobjinfo[splishtype].height, mobj->scale), splishtype);
splish->flags2 |= MF2_OBJECTFLIP;
splish->eflags |= MFE_VERTICALFLIP;
}
else
splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, splishtype);
{
splish = P_SpawnMobj(mobj->x, mobj->y, waterZ, splishtype);
}
splish->destscale = mobj->scale;
P_SetScale(splish, mobj->scale);
}
@ -3175,40 +3279,37 @@ void P_MobjCheckWater(mobj_t *mobj)
if (p && p->waterskip < 2
&& ((p->speed/3 > abs(mobj->momz)) // Going more forward than horizontal, so you can skip across the water.
|| (p->speed > 20*mapobjectscale && p->waterskip)) // Already skipped once, so you can skip once more!
&& ((!(mobj->eflags & MFE_VERTICALFLIP) && thingtop - mobj->momz > mobj->watertop)
|| ((mobj->eflags & MFE_VERTICALFLIP) && mobj->z - mobj->momz < mobj->waterbottom)))
&& (splashValid == true))
{
const fixed_t hop = 5<<FRACBITS;
const fixed_t hop = 5 * mobj->scale;
mobj->momx = (4*mobj->momx)/5;
mobj->momy = (4*mobj->momy)/5;
if (mobj->eflags & MFE_VERTICALFLIP)
mobj->momz = FixedMul(-hop, mobj->scale);
else
mobj->momz = FixedMul(hop, mobj->scale);
mobj->momz = hop * P_MobjFlip(mobj);
p->waterskip++;
}
}
else if (P_MobjFlip(mobj)*mobj->momz > 0)
else if (P_MobjFlip(mobj) * mobj->momz > 0)
{
if (((mobj->eflags & MFE_VERTICALFLIP && thingtop-(height>>1)-mobj->momz > mobj->waterbottom)
|| (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z+(height>>1)-mobj->momz < mobj->watertop))
&& !(mobj->eflags & MFE_UNDERWATER)) // underwater check to prevent splashes on opposite side
if (splashValid == true && !(mobj->eflags & MFE_UNDERWATER)) // underwater check to prevent splashes on opposite side
{
// Spawn a splash
mobj_t *splish;
mobjtype_t splishtype = (mobj->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH;
if (mobj->eflags & MFE_VERTICALFLIP)
{
splish = P_SpawnMobj(mobj->x, mobj->y, mobj->waterbottom-FixedMul(mobjinfo[splishtype].height, mobj->scale), splishtype);
splish = P_SpawnMobj(mobj->x, mobj->y, waterZ - FixedMul(mobjinfo[splishtype].height, mobj->scale), splishtype);
splish->flags2 |= MF2_OBJECTFLIP;
splish->eflags |= MFE_VERTICALFLIP;
}
else
splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, splishtype);
{
splish = P_SpawnMobj(mobj->x, mobj->y, waterZ, splishtype);
}
splish->destscale = mobj->scale;
P_SetScale(splish, mobj->scale);
}
@ -3574,7 +3675,8 @@ static void P_CheckFloatbobPlatforms(mobj_t *mobj)
static void P_SquishThink(mobj_t *mobj)
{
if (!(mobj->eflags & MFE_SLOPELAUNCHED))
if (!(mobj->flags & MF_NOSQUISH) &&
!(mobj->eflags & MFE_SLOPELAUNCHED))
{
K_Squish(mobj);
}
@ -4049,7 +4151,7 @@ static void P_SpawnItemCapsuleParts(mobj_t *mobj)
part = part->hnext;
P_SetTarget(&part->target, mobj);
P_SetMobjState(part, buttState);
part->angle = i * ANG_CAPSULE;
P_InitAngle(part, i * ANG_CAPSULE);
part->movedir = spin; // rotation speed
part->movefactor = 0; // z offset
part->extravalue1 = buttScale; // relative scale
@ -4060,7 +4162,7 @@ static void P_SpawnItemCapsuleParts(mobj_t *mobj)
part = part->hnext;
P_SetTarget(&part->target, mobj);
P_SetMobjState(part, S_ITEMCAPSULE_TOP_SIDE);
part->angle = i * ANG_CAPSULE;
P_InitAngle(part, i * ANG_CAPSULE);
part->movedir = spin; // rotation speed
part->movefactor = mobj->info->height - part->info->height; // z offset
}
@ -4385,7 +4487,7 @@ void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 numb
mobj->z -= mobj->height>>1;
// change angle
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, x, y);
P_InitAngle(mobj, R_PointToAngle2(mobj->x, mobj->y, x, y));
// change slope
dist = P_AproxDistance(P_AproxDistance(x - mobj->x, y - mobj->y), z - mobj->z);
@ -5068,7 +5170,7 @@ static void P_FlameJetSceneryThink(mobj_t *mobj)
flame = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_FLAMEJETFLAME);
P_SetMobjState(flame, S_FLAMEJETFLAME4);
flame->angle = mobj->angle;
P_InitAngle(flame, mobj->angle);
if (mobj->flags2 & MF2_AMBUSH) // Wave up and down instead of side-to-side
flame->momz = mobj->fuse << (FRACBITS - 2);
@ -5529,7 +5631,7 @@ static void P_MobjSceneryThink(mobj_t *mobj)
{
mobj_t *blast = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_BATTLEBUMPER_BLAST);
blast->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy) + ANGLE_45;
P_InitAngle(blast, R_PointToAngle2(0, 0, mobj->momx, mobj->momy) + ANGLE_45);
blast->destscale *= 4;
if (i & 1)
@ -6814,12 +6916,15 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
if (( mobj->fuse & 1 ))
{
nudge = 4*mobj->target->radius;
/* unrotate interp angle */
mobj->old_angle -= ANGLE_90;
}
else
{
nudge = 2*mobj->target->radius;
/* rotate the papersprite frames to see the flat angle */
mobj->angle += ANGLE_90;
mobj->old_angle += ANGLE_90;
}
P_MoveOrigin(mobj,
@ -7014,6 +7119,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
return false;
}
P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
mobj->old_x = mobj->target->old_x;
mobj->old_y = mobj->target->old_y;
mobj->old_z = mobj->target->old_z;
break;
case MT_INSTASHIELDB:
mobj->renderflags ^= RF_DONTDRAW;
@ -7026,6 +7134,9 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
return false;
}
P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
mobj->old_x = mobj->target->old_x;
mobj->old_y = mobj->target->old_y;
mobj->old_z = mobj->target->old_z;
K_MatchGenericExtraFlags(mobj, mobj->target);
break;
case MT_BATTLEPOINT:
@ -7398,10 +7509,10 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
mobj->z + (mobj->height/2) + (P_RandomRange(-20,20) * mobj->scale),
MT_FASTLINE);
fast->angle = mobj->angle;
P_InitAngle(fast, mobj->angle);
fast->momx = 3*mobj->target->momx/4;
fast->momy = 3*mobj->target->momy/4;
fast->momz = 3*mobj->target->momz/4;
fast->momz = 3*P_GetMobjZMovement(mobj->target)/4;
K_MatchGenericExtraFlags(fast, mobj);
P_SetMobjState(fast, S_FLAMESHIELDLINE1 + i);
@ -7460,7 +7571,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
if (underlayst != S_NULL)
{
mobj_t *underlay = P_SpawnMobj(mobj->target->x, mobj->target->y, mobj->target->z, MT_FLAMESHIELDUNDERLAY);
underlay->angle = mobj->angle;
P_InitAngle(underlay, mobj->angle);
P_SetMobjState(underlay, underlayst);
}
break;
@ -8838,7 +8949,7 @@ static boolean P_FuseThink(mobj_t *mobj)
for (i = 0; i < 5; i++)
{
mobj_t *debris = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_SMK_ICEBLOCK_DEBRIS);
debris->angle = FixedAngle(P_RandomRange(0,360)<<FRACBITS);
P_InitAngle(debris, FixedAngle(P_RandomRange(0,360)<<FRACBITS));
P_InstaThrust(debris, debris->angle, P_RandomRange(3,18)*(FRACUNIT/4));
debris->momz = P_RandomRange(4,8)<<FRACBITS;
if (!i) // kinda hacky :V
@ -9614,7 +9725,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
case MT_CRUSHSTACEAN:
{
mobj_t *bigmeatyclaw = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_CRUSHCLAW);
bigmeatyclaw->angle = mobj->angle + ((mobj->flags2 & MF2_AMBUSH) ? ANGLE_90 : ANGLE_270);;
P_InitAngle(bigmeatyclaw, mobj->angle + ((mobj->flags2 & MF2_AMBUSH) ? ANGLE_90 : ANGLE_270));
P_SetTarget(&mobj->tracer, bigmeatyclaw);
P_SetTarget(&bigmeatyclaw->tracer, mobj);
mobj->reactiontime >>= 1;
@ -9623,7 +9734,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
case MT_BANPYURA:
{
mobj_t *bigmeatyclaw = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_BANPSPRING);
bigmeatyclaw->angle = mobj->angle + ((mobj->flags2 & MF2_AMBUSH) ? ANGLE_90 : ANGLE_270);;
P_InitAngle(bigmeatyclaw, mobj->angle + ((mobj->flags2 & MF2_AMBUSH) ? ANGLE_90 : ANGLE_270));
P_SetTarget(&mobj->tracer, bigmeatyclaw);
P_SetTarget(&bigmeatyclaw->tracer, mobj);
mobj->reactiontime >>= 1;
@ -9756,7 +9867,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
break;
case MT_MINECARTEND:
P_SetTarget(&mobj->tracer, P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_MINECARTENDSOLID));
mobj->tracer->angle = mobj->angle + ANGLE_90;
P_InitAngle(mobj->tracer, mobj->angle + ANGLE_90);
break;
case MT_TORCHFLOWER:
{
@ -9878,7 +9989,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
angle_t ang = i * diff;
mobj_t *side = P_SpawnMobj(mobj->x + FINECOSINE((ang>>ANGLETOFINESHIFT) & FINEMASK),
mobj->y + FINESINE((ang>>ANGLETOFINESHIFT) & FINEMASK), mobj->z, MT_DAYTONAPINETREE_SIDE);
side->angle = ang;
P_InitAngle(side, ang);
side->target = mobj;
side->threshold = i;
}
@ -9895,7 +10006,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
cur = P_SpawnMobj(mobj->x + FINECOSINE(((mobj->angle*8)>>ANGLETOFINESHIFT) & FINEMASK),
mobj->y + FINESINE(((mobj->angle*8)>>ANGLETOFINESHIFT) & FINEMASK), mobj->z, MT_EZZPROPELLER_BLADE);
cur->angle = mobj->angle;
P_InitAngle(cur, mobj->angle);
P_SetTarget(&cur->hprev, prev);
P_SetTarget(&prev->hnext, cur);
@ -9955,7 +10066,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
cur->threshold = i;
P_MoveOrigin(cur, cur->x + ((cur->radius>>FRACBITS) * FINECOSINE((FixedAngle((90*cur->threshold)<<FRACBITS)>>ANGLETOFINESHIFT) & FINEMASK)),
cur->y + ((cur->radius>>FRACBITS) * FINESINE((FixedAngle((90*cur->threshold)<<FRACBITS)>>ANGLETOFINESHIFT) & FINEMASK)), cur->z);
cur->angle = ANGLE_90*(cur->threshold+1);
P_InitAngle(cur, ANGLE_90*(cur->threshold+1));
P_SetTarget(&cur->hprev, prev);
P_SetTarget(&prev->hnext, cur);
@ -10384,6 +10495,8 @@ void P_PrecipitationEffects(void)
boolean effects_lightning = (precipprops[curWeather].effects & PRECIPFX_LIGHTNING);
boolean lightningStrike = false;
boolean sounds_rain = (rainsfx != sfx_None && (!leveltime || leveltime % rainfreq == 1));
// No thunder except every other tic.
if (!(leveltime & 1))
{
@ -10428,29 +10541,48 @@ void P_PrecipitationEffects(void)
if (sound_disabled)
return; // Sound off? D'aw, no fun.
if (!sounds_rain && !sounds_thunder)
return; // no need to calculate volume at ALL
if (players[g_localplayers[0]].mo->subsector->sector->ceilingpic == skyflatnum)
volume = 255; // Sky above? We get it full blast.
else
{
fixed_t x, y, yl, yh, xl, xh;
INT64 x, y, yl, yh, xl, xh;
fixed_t closedist, newdist;
// Essentially check in a 1024 unit radius of the player for an outdoor area.
yl = players[g_localplayers[0]].mo->y - 1024*FRACUNIT;
yh = players[g_localplayers[0]].mo->y + 1024*FRACUNIT;
xl = players[g_localplayers[0]].mo->x - 1024*FRACUNIT;
xh = players[g_localplayers[0]].mo->x + 1024*FRACUNIT;
closedist = 2048*FRACUNIT;
for (y = yl; y <= yh; y += FRACUNIT*64)
for (x = xl; x <= xh; x += FRACUNIT*64)
#define RADIUSSTEP (64*FRACUNIT)
#define SEARCHRADIUS (16*RADIUSSTEP)
yl = yh = players[g_localplayers[0]].mo->y;
yl -= SEARCHRADIUS;
while (yl < INT32_MIN)
yl += RADIUSSTEP;
yh += SEARCHRADIUS;
while (yh > INT32_MAX)
yh -= RADIUSSTEP;
xl = xh = players[g_localplayers[0]].mo->x;
xl -= SEARCHRADIUS;
while (xl < INT32_MIN)
xl += RADIUSSTEP;
xh += SEARCHRADIUS;
while (xh > INT32_MAX)
xh -= RADIUSSTEP;
closedist = SEARCHRADIUS*2;
#undef SEARCHRADIUS
for (y = yl; y <= yh; y += RADIUSSTEP)
for (x = xl; x <= xh; x += RADIUSSTEP)
{
if (R_PointInSubsector(x, y)->sector->ceilingpic == skyflatnum) // Found the outdoors!
if (R_PointInSubsector((fixed_t)x, (fixed_t)y)->sector->ceilingpic == skyflatnum) // Found the outdoors!
{
newdist = S_CalculateSoundDistance(players[g_localplayers[0]].mo->x, players[g_localplayers[0]].mo->y, 0, x, y, 0);
newdist = S_CalculateSoundDistance(players[g_localplayers[0]].mo->x, players[g_localplayers[0]].mo->y, 0, (fixed_t)x, (fixed_t)y, 0);
if (newdist < closedist)
closedist = newdist;
}
}
#undef RADIUSSTEP
volume = 255 - (closedist>>(FRACBITS+2));
}
@ -10460,7 +10592,7 @@ void P_PrecipitationEffects(void)
else if (volume > 255)
volume = 255;
if (rainsfx != sfx_None && (!leveltime || leveltime % rainfreq == 1))
if (sounds_rain)
S_StartSoundAtVolume(players[g_localplayers[0]].mo, rainsfx, volume);
if (!sounds_thunder)
@ -10716,7 +10848,7 @@ void P_SpawnPlayer(INT32 playernum)
mobj = P_SpawnMobj(0, 0, 0, MT_PLAYER);
(mobj->player = p)->mo = mobj;
mobj->angle = 0;
mobj->angle = mobj->old_angle = 0;
// set color translations for player sprites
mobj->color = p->skincolor;
@ -10737,11 +10869,17 @@ void P_SpawnPlayer(INT32 playernum)
p->awayviewmobj = NULL;
p->awayviewtics = 0;
p->skybox.viewpoint = skyboxviewpnts[0];
p->skybox.centerpoint = skyboxcenterpnts[0];
P_SetTarget(&p->follower, NULL); // cleanse follower from existence
if (K_PlayerShrinkCheat(p) == true)
{
mobj->destscale = FixedMul(mobj->destscale, SHRINK_SCALE);
}
// set the scale to the mobj's destscale so settings get correctly set. if we don't, they sometimes don't.
if (cv_kartdebugshrink.value && !modeattacking && !p->bot)
mobj->destscale = 6*mobj->destscale/8;
P_SetScale(mobj, mobj->destscale);
P_FlashPal(p, 0, 0); // Resets
@ -10803,6 +10941,12 @@ void P_AfterPlayerSpawn(INT32 playernum)
mobj_t *mobj = p->mo;
UINT8 i;
// Update interpolation
mobj->old_x = mobj->x;
mobj->old_y = mobj->y;
mobj->old_z = mobj->z;
mobj->old_angle = mobj->angle;
P_SetPlayerAngle(p, mobj->angle);
p->viewheight = P_GetPlayerViewHeight(p);
@ -11397,7 +11541,7 @@ static boolean P_SetupMace(mapthing_t *mthing, mobj_t *mobj, boolean *doangle)
spawnee->friction = mroll;\
spawnee->movefactor = mwidthset;\
spawnee->movecount = dist;\
spawnee->angle = myaw;\
P_InitAngle(spawnee, myaw);\
spawnee->flags |= (MF_NOGRAVITY|mflagsapply);\
spawnee->flags2 |= (mflags2apply|moreflags2);\
spawnee->eflags |= meflagsapply;\
@ -11596,29 +11740,29 @@ static boolean P_SetupBooster(mapthing_t* mthing, mobj_t* mobj, boolean strong)
statenum_t rollerstate = strong ? S_REDBOOSTERROLLER : S_YELLOWBOOSTERROLLER;
mobj_t *seg = P_SpawnMobjFromMobj(mobj, 26*x1, 26*y1, 0, MT_BOOSTERSEG);
seg->angle = angle - ANGLE_90;
P_InitAngle(seg, angle - ANGLE_90);
P_SetMobjState(seg, facestate);
seg = P_SpawnMobjFromMobj(mobj, -26*x1, -26*y1, 0, MT_BOOSTERSEG);
seg->angle = angle + ANGLE_90;
P_InitAngle(seg, angle + ANGLE_90);
P_SetMobjState(seg, facestate);
seg = P_SpawnMobjFromMobj(mobj, 21*x2, 21*y2, 0, MT_BOOSTERSEG);
seg->angle = angle;
P_InitAngle(seg, angle);
P_SetMobjState(seg, leftstate);
seg = P_SpawnMobjFromMobj(mobj, -21*x2, -21*y2, 0, MT_BOOSTERSEG);
seg->angle = angle;
P_InitAngle(seg, angle);
P_SetMobjState(seg, rightstate);
seg = P_SpawnMobjFromMobj(mobj, 13*(x1 + x2), 13*(y1 + y2), 0, MT_BOOSTERROLLER);
seg->angle = angle;
P_InitAngle(seg, angle);
P_SetMobjState(seg, rollerstate);
seg = P_SpawnMobjFromMobj(mobj, 13*(x1 - x2), 13*(y1 - y2), 0, MT_BOOSTERROLLER);
seg->angle = angle;
P_InitAngle(seg, angle);
P_SetMobjState(seg, rollerstate);
seg = P_SpawnMobjFromMobj(mobj, -13*(x1 + x2), -13*(y1 + y2), 0, MT_BOOSTERROLLER);
seg->angle = angle;
P_InitAngle(seg, angle);
P_SetMobjState(seg, rollerstate);
seg = P_SpawnMobjFromMobj(mobj, -13*(x1 - x2), -13*(y1 - y2), 0, MT_BOOSTERROLLER);
seg->angle = angle;
P_InitAngle(seg, angle);
P_SetMobjState(seg, rollerstate);
return true;
@ -11795,19 +11939,19 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
case MT_THZTREE:
{ // Spawn the branches
angle_t mobjangle = FixedAngle((mthing->angle % 113) << FRACBITS);
P_SpawnMobjFromMobj(mobj, FRACUNIT, 0, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_22h;
P_SpawnMobjFromMobj(mobj, 0, FRACUNIT, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_157h;
P_SpawnMobjFromMobj(mobj, -FRACUNIT, 0, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_270;
P_InitAngle(P_SpawnMobjFromMobj(mobj, FRACUNIT, 0, 0, MT_THZTREEBRANCH), mobjangle + ANGLE_22h);
P_InitAngle(P_SpawnMobjFromMobj(mobj, 0, FRACUNIT, 0, MT_THZTREEBRANCH), mobjangle + ANGLE_157h);
P_InitAngle(P_SpawnMobjFromMobj(mobj, -FRACUNIT, 0, 0, MT_THZTREEBRANCH), mobjangle + ANGLE_270);
}
break;
case MT_CEZPOLE1:
case MT_CEZPOLE2:
{ // Spawn the banner
angle_t mobjangle = FixedAngle(mthing->angle << FRACBITS);
P_SpawnMobjFromMobj(mobj,
P_InitAngle(P_SpawnMobjFromMobj(mobj,
P_ReturnThrustX(mobj, mobjangle, 4 << FRACBITS),
P_ReturnThrustY(mobj, mobjangle, 4 << FRACBITS),
0, ((mobj->type == MT_CEZPOLE1) ? MT_CEZBANNER1 : MT_CEZBANNER2))->angle = mobjangle + ANGLE_90;
0, ((mobj->type == MT_CEZPOLE1) ? MT_CEZBANNER1 : MT_CEZBANNER2)), mobjangle + ANGLE_90);
}
break;
case MT_HHZTREE_TOP:
@ -11816,7 +11960,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
mobj_t* leaf;
#define doleaf(x, y) \
leaf = P_SpawnMobjFromMobj(mobj, x, y, 0, MT_HHZTREE_PART);\
leaf->angle = mobjangle;\
P_InitAngle(leaf, mobjangle);\
P_SetMobjState(leaf, leaf->info->seestate);\
mobjangle += ANGLE_90
doleaf(FRACUNIT, 0);
@ -11840,7 +11984,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
fixed_t xoffs = FINECOSINE(fa);
fixed_t yoffs = FINESINE(fa);
mobj_t* leaf = P_SpawnMobjFromMobj(mobj, xoffs, yoffs, 0, MT_BIGFERNLEAF);
leaf->angle = angle;
P_InitAngle(leaf, angle);
angle += ANGLE_45;
}
break;
@ -11950,7 +12094,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
mobj->x - P_ReturnThrustX(mobj, mobjangle, baseradius),
mobj->y - P_ReturnThrustY(mobj, mobjangle, baseradius),
mobj->z, MT_WALLSPIKEBASE);
base->angle = mobjangle + ANGLE_90;
P_InitAngle(base, mobjangle + ANGLE_90);
base->destscale = mobj->destscale;
P_SetScale(base, mobj->scale);
P_SetTarget(&base->target, mobj);
@ -12136,7 +12280,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
leaf = P_SpawnMobj(mobj->x + FINECOSINE((mobj->angle>>ANGLETOFINESHIFT) & FINEMASK),
mobj->y + FINESINE((mobj->angle>>ANGLETOFINESHIFT) & FINEMASK), top, MT_AAZTREE_LEAF);
leaf->angle = mobj->angle;
P_InitAngle(leaf, mobj->angle);
// Small coconut for each leaf
P_SpawnMobj(mobj->x + (32 * FINECOSINE((mobj->angle>>ANGLETOFINESHIFT) & FINEMASK)),
@ -12353,7 +12497,9 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y,
return mobj;
if (doangle)
mobj->angle = FixedAngle(mthing->angle << FRACBITS);
{
P_InitAngle(mobj, FixedAngle(mthing->angle << FRACBITS));
}
if ((mobj->flags & MF_SPRING)
&& mobj->info->damage != 0
@ -12365,8 +12511,8 @@ static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y,
mobj->spryoff = FixedMul(mobj->radius, FINESINE(a >> ANGLETOFINESHIFT));
}
mobj->pitch = FixedAngle(mthing->pitch << FRACBITS);
mobj->roll = FixedAngle(mthing->roll << FRACBITS);
P_InitPitch(mobj, FixedAngle(mthing->pitch << FRACBITS));
P_InitRoll(mobj, FixedAngle(mthing->roll << FRACBITS));
mthing->mobj = mobj;
@ -12773,7 +12919,7 @@ mobj_t *P_SpawnXYZMissile(mobj_t *source, mobj_t *dest, mobjtype_t type,
P_SetTarget(&th->target, source); // where it came from
an = R_PointToAngle2(x, y, dest->x, dest->y);
th->angle = an;
P_InitAngle(th, an);
an >>= ANGLETOFINESHIFT;
th->momx = FixedMul(speed, FINECOSINE(an));
th->momy = FixedMul(speed, FINESINE(an));
@ -12835,7 +12981,7 @@ mobj_t *P_SpawnAlteredDirectionMissile(mobj_t *source, mobjtype_t type, fixed_t
P_SetTarget(&th->target, source->target); // where it came from
an = R_PointToAngle2(0, 0, source->momx, source->momy) + (ANG1*shiftingAngle);
th->angle = an;
P_InitAngle(th, an);
an >>= ANGLETOFINESHIFT;
th->momx = FixedMul(speed, FINECOSINE(an));
th->momy = FixedMul(speed, FINESINE(an));
@ -12900,7 +13046,7 @@ mobj_t *P_SpawnPointMissile(mobj_t *source, fixed_t xa, fixed_t ya, fixed_t za,
P_SetTarget(&th->target, source); // where it came from
an = R_PointToAngle2(x, y, xa, ya);
th->angle = an;
P_InitAngle(th, an);
an >>= ANGLETOFINESHIFT;
th->momx = FixedMul(speed, FINECOSINE(an));
th->momy = FixedMul(speed, FINESINE(an));
@ -12979,7 +13125,7 @@ mobj_t *P_SpawnMissile(mobj_t *source, mobj_t *dest, mobjtype_t type)
else
an = R_PointToAngle2(source->x, source->y, dest->x, dest->y);
th->angle = an;
P_InitAngle(th, an);
an >>= ANGLETOFINESHIFT;
th->momx = FixedMul(speed, FINECOSINE(an));
th->momy = FixedMul(speed, FINESINE(an));
@ -13067,7 +13213,7 @@ mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle, UINT8 allowai
speed = th->info->speed;
th->angle = an;
P_InitAngle(th, an);
th->momx = FixedMul(speed, FINECOSINE(an>>ANGLETOFINESHIFT));
th->momy = FixedMul(speed, FINESINE(an>>ANGLETOFINESHIFT));
@ -13137,6 +13283,17 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo
newmobj->z = mobj->z + mobj->height - zofs - newmobj->height;
}
// EXPERIMENT: Let all objects set their interp values relative to their owner's old values.
// This will hopefully create a lot less mobj-specific spawn cases,
// but if there's any weird scenarios feel free to remove again.
newmobj->old_x = mobj->old_x + xofs;
newmobj->old_y = mobj->old_y + yofs;
newmobj->old_z = mobj->old_z + zofs;
/*
newmobj->angle = mobj->angle;
newmobj->old_angle = mobj->old_angle;
*/
return newmobj;
}
@ -13153,6 +13310,14 @@ fixed_t P_GetMobjHead(const mobj_t *mobj)
fixed_t P_GetMobjFeet(const mobj_t *mobj)
{
/*
| |
| |
/--\------/ |
| |
-----------------
*/
return P_IsObjectFlipped(mobj) ? mobj->z + mobj->height : mobj->z;
}
@ -13164,3 +13329,25 @@ fixed_t P_GetMobjGround(const mobj_t *mobj)
{
return P_IsObjectFlipped(mobj) ? mobj->ceilingz : mobj->floorz;
}
//
// P_GetMobjZMovement
// Returns the Z momentum of the object, accounting for slopes if the object is grounded
//
fixed_t P_GetMobjZMovement(mobj_t *mo)
{
pslope_t *slope = mo->standingslope;
angle_t angDiff;
fixed_t speed;
if (!P_IsObjectOnGround(mo))
return mo->momz;
if (!slope)
return 0;
angDiff = R_PointToAngle2(0, 0, mo->momx, mo->momy) - slope->xydirection;
speed = FixedHypot(mo->momx, mo->momy);
return P_ReturnThrustY(mo, slope->zangle, P_ReturnThrustX(mo, angDiff, speed));
}

View file

@ -159,7 +159,11 @@ typedef enum
MF_DONTENCOREMAP = 1<<28,
// Hitbox extends just as far below as above.
MF_PICKUPFROMBELOW = 1<<29,
// free: to and including 1<<31
// Disable momentum-based squash and stretch.
MF_NOSQUISH = 1<<30,
// Disable hitlag for this object
MF_NOHITLAGFORME = 1<<31,
// no more free slots, next up I suppose we can get rid of shit like MF_BOXICON?
} mobjflag_t;
typedef enum
@ -395,6 +399,7 @@ typedef struct mobj_s
fixed_t sprxoff, spryoff, sprzoff; // Sprite offsets in real space, does NOT affect position or collision
struct terrain_s *terrain; // Terrain definition of the floor this object last hit. NULL when in the air.
INT32 hitlag; // Sal-style hit lag, straight from Captain Fetch's jowls
// WARNING: New fields must be added separately to savegame and Lua.

View file

@ -38,6 +38,7 @@
// SRB2Kart
#include "k_battle.h"
#include "k_pwrlv.h"
#include "k_terrain.h"
savedata_t savedata;
UINT8 *save_p;
@ -59,6 +60,8 @@ typedef enum
AWAYVIEW = 0x01,
FOLLOWITEM = 0x02,
FOLLOWER = 0x04,
SKYBOXVIEW = 0x08,
SKYBOXCENTER = 0x10,
} player_saveflags;
static inline void P_ArchivePlayer(void)
@ -177,6 +180,12 @@ static void P_NetArchivePlayers(void)
if (players[i].follower)
flags |= FOLLOWER;
if (players[i].skybox.viewpoint)
flags |= SKYBOXVIEW;
if (players[i].skybox.centerpoint)
flags |= SKYBOXCENTER;
WRITEINT16(save_p, players[i].lastsidehit);
WRITEINT16(save_p, players[i].lastlinehit);
@ -189,6 +198,12 @@ static void P_NetArchivePlayers(void)
WRITEUINT16(save_p, flags);
if (flags & SKYBOXVIEW)
WRITEUINT32(save_p, players[i].skybox.viewpoint->mobjnum);
if (flags & SKYBOXCENTER)
WRITEUINT32(save_p, players[i].skybox.centerpoint->mobjnum);
if (flags & AWAYVIEW)
WRITEUINT32(save_p, players[i].awayviewmobj->mobjnum);
@ -446,6 +461,12 @@ static void P_NetUnArchivePlayers(void)
flags = READUINT16(save_p);
if (flags & SKYBOXVIEW)
players[i].skybox.viewpoint = (mobj_t *)(size_t)READUINT32(save_p);
if (flags & SKYBOXCENTER)
players[i].skybox.centerpoint = (mobj_t *)(size_t)READUINT32(save_p);
if (flags & AWAYVIEW)
players[i].awayviewmobj = (mobj_t *)(size_t)READUINT32(save_p);
@ -1540,6 +1561,7 @@ typedef enum
MD2_KITEMCAP = 1<<26,
MD2_ITNEXT = 1<<27,
MD2_LASTMOMZ = 1<<28,
MD2_TERRAIN = 1<<29,
} mobj_diff2_t;
typedef enum
@ -1782,6 +1804,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
diff2 |= MD2_ITNEXT;
if (mobj->lastmomz)
diff2 |= MD2_LASTMOMZ;
if (mobj->terrain != NULL)
diff2 |= MD2_TERRAIN;
if (diff2 != 0)
diff |= MD_MORE;
@ -1979,6 +2003,10 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
{
WRITEINT32(save_p, mobj->lastmomz);
}
if (diff2 & MD2_TERRAIN)
{
WRITEUINT32(save_p, K_GetTerrainHeapIndex(mobj->terrain));
}
WRITEUINT32(save_p, mobj->mobjnum);
}
@ -2885,19 +2913,19 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
mobj->info = &mobjinfo[mobj->type];
if (diff & MD_POS)
{
mobj->x = READFIXED(save_p);
mobj->y = READFIXED(save_p);
mobj->angle = READANGLE(save_p);
mobj->pitch = READANGLE(save_p);
mobj->roll = READANGLE(save_p);
mobj->x = mobj->old_x = READFIXED(save_p);
mobj->y = mobj->old_y = READFIXED(save_p);
mobj->angle = mobj->old_angle = READANGLE(save_p);
mobj->pitch = mobj->old_pitch = READANGLE(save_p);
mobj->roll = mobj->old_roll = READANGLE(save_p);
}
else
{
mobj->x = mobj->spawnpoint->x << FRACBITS;
mobj->y = mobj->spawnpoint->y << FRACBITS;
mobj->angle = FixedAngle(mobj->spawnpoint->angle*FRACUNIT);
mobj->pitch = FixedAngle(mobj->spawnpoint->pitch*FRACUNIT);
mobj->roll = FixedAngle(mobj->spawnpoint->roll*FRACUNIT);
mobj->x = mobj->old_x = mobj->spawnpoint->x << FRACBITS;
mobj->y = mobj->old_y = mobj->spawnpoint->y << FRACBITS;
mobj->angle = mobj->old_angle = FixedAngle(mobj->spawnpoint->angle*FRACUNIT);
mobj->pitch = mobj->old_pitch = FixedAngle(mobj->spawnpoint->pitch*FRACUNIT);
mobj->roll = mobj->old_roll = FixedAngle(mobj->spawnpoint->roll*FRACUNIT);
}
if (diff & MD_MOM)
{
@ -3077,6 +3105,14 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
{
mobj->lastmomz = READINT32(save_p);
}
if (diff2 & MD2_TERRAIN)
{
mobj->terrain = (terrain_t *)(size_t)READUINT32(save_p);
}
else
{
mobj->terrain = NULL;
}
if (diff & MD_REDFLAG)
{
@ -4103,8 +4139,31 @@ static void P_RelinkPointers(void)
if (!(mobj->itnext = P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "itnext not found on %d\n", mobj->type);
}
if (mobj->terrain)
{
temp = (UINT32)(size_t)mobj->terrain;
mobj->terrain = K_GetTerrainByIndex(temp);
if (mobj->terrain == NULL)
{
CONS_Debug(DBG_GAMELOGIC, "terrain not found on %d\n", mobj->type);
}
}
if (mobj->player)
{
if ( mobj->player->skybox.viewpoint)
{
temp = (UINT32)(size_t)mobj->player->skybox.viewpoint;
mobj->player->skybox.viewpoint = NULL;
if (!P_SetTarget(&mobj->player->skybox.viewpoint, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "skybox.viewpoint not found on %d\n", mobj->type);
}
if ( mobj->player->skybox.centerpoint)
{
temp = (UINT32)(size_t)mobj->player->skybox.centerpoint;
mobj->player->skybox.centerpoint = NULL;
if (!P_SetTarget(&mobj->player->skybox.centerpoint, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "skybox.centerpoint not found on %d\n", mobj->type);
}
if ( mobj->player->awayviewmobj)
{
temp = (UINT32)(size_t)mobj->player->awayviewmobj;

View file

@ -91,7 +91,9 @@
#include "k_waypoint.h"
#include "k_bot.h"
#include "k_grandprix.h"
#include "k_terrain.h" // TRF_TRIPWIRE
#include "k_brightmap.h"
#include "k_director.h" // K_InitDirector
// Replay names have time
#if !defined (UNDER_CE)
@ -660,6 +662,9 @@ flatfound:
levelflat->u.flat.baselumpnum = LUMPERROR;
}
levelflat->terrain =
K_GetTerrainForTextureName(levelflat->name);
CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name);
return ( numlevelflats++ );
@ -1935,26 +1940,85 @@ static void P_LoadTextmap(void)
}
}
static fixed_t
P_MirrorTextureOffset
( fixed_t offset,
fixed_t source_width,
fixed_t actual_width)
{
/*
Adjusting the horizontal alignment is a bit ASS...
Textures on the opposite side of the line will begin
drawing from the opposite end.
Start with the texture width and subtract the seg
length to account for cropping/wrapping. Subtract the
offset to mirror the alignment.
*/
return source_width - actual_width - offset;
}
static boolean P_CheckLineSideTripWire(line_t *ld, int p)
{
INT32 n;
side_t *sda;
side_t *sdb;
terrain_t *terrain;
boolean tripwire;
n = ld->sidenum[p];
if (n == 0xffff)
return false;
sda = &sides[n];
terrain = K_GetTerrainForTextureNum(sda->midtexture);
tripwire = terrain && (terrain->flags & TRF_TRIPWIRE);
if (tripwire)
{
// copy midtexture to other side
n = ld->sidenum[!p];
if (n != 0xffff)
{
fixed_t linelength = FixedHypot(ld->dx, ld->dy);
texture_t *tex = textures[sda->midtexture];
sdb = &sides[n];
sdb->midtexture = sda->midtexture;
sdb->rowoffset = sda->rowoffset;
// mirror texture alignment
sdb->textureoffset = P_MirrorTextureOffset(
sda->textureoffset, tex->width * FRACUNIT,
linelength);
}
}
return tripwire;
}
static void P_ProcessLinedefsAfterSidedefs(void)
{
size_t i = numlines;
register line_t *ld = lines;
const INT32 TEX_TRIPWIRE = R_TextureNumForName("TRIPWIRE");
const INT32 TEX_4RIPWIRE = R_TextureNumForName("4RIPWIRE");
for (; i--; ld++)
{
INT32 midtexture = sides[ld->sidenum[0]].midtexture;
ld->frontsector = sides[ld->sidenum[0]].sector; //e6y: Can't be -1 here
ld->backsector = ld->sidenum[1] != 0xffff ? sides[ld->sidenum[1]].sector : 0;
if (midtexture == TEX_TRIPWIRE ||
midtexture == TEX_4RIPWIRE)
{
ld->tripwire = true;
}
// Check for tripwire, if either side matches then
// copy that (mid)texture to the other side.
ld->tripwire =
P_CheckLineSideTripWire(ld, 0) ||
P_CheckLineSideTripWire(ld, 1);
switch (ld->special)
{
@ -3464,6 +3528,7 @@ static void P_InitLevelSettings(void)
players[i].lives = 3;
G_PlayerReborn(i, true);
K_UpdateShrinkCheat(&players[i]);
}
racecountdown = exitcountdown = exitfadestarted = 0;
@ -3513,6 +3578,7 @@ static void P_InitLevelSettings(void)
speedscramble = encorescramble = -1;
}
#if 0
// Respawns all the mapthings and mobjs in the map from the already loaded map data.
void P_RespawnThings(void)
{
@ -3547,6 +3613,7 @@ void P_RespawnThings(void)
skyboxmo[0] = skyboxviewpnts[(viewid >= 0) ? viewid : 0];
skyboxmo[1] = skyboxcenterpnts[(centerid >= 0) ? centerid : 0];
}
#endif
static void P_RunLevelScript(const char *scriptname)
{
@ -3621,14 +3688,19 @@ static void P_ResetSpawnpoints(void)
// reset the player starts
for (i = 0; i < MAXPLAYERS; i++)
{
playerstarts[i] = bluectfstarts[i] = redctfstarts[i] = NULL;
if (playeringame[i])
{
players[i].skybox.viewpoint = NULL;
players[i].skybox.centerpoint = NULL;
}
}
for (i = 0; i < MAX_DM_STARTS; i++)
deathmatchstarts[i] = NULL;
for (i = 0; i < 2; i++)
skyboxmo[i] = NULL;
for (i = 0; i < 16; i++)
skyboxviewpnts[i] = skyboxcenterpnts[i] = NULL;
}
@ -3797,12 +3869,20 @@ static void P_InitGametype(void)
//@TODO I'd like to fix dedis crashing when recording replays for the future too...
if (!demo.playback && multiplayer && !dedicated)
{
static char buf[256];
char *path;
sprintf(buf, "media"PATHSEP"replay"PATHSEP"online"PATHSEP"%d-%s", (int) (time(NULL)), G_BuildMapName(gamemap));
char buf[MAX_WADPATH];
char ver[128];
int parts;
path = va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"online", srb2home);
M_MkdirEach(path, M_PathParts(path) - 4, 0755);
#ifdef DEVELOP
sprintf(ver, "%s-%s", compbranch, comprevision);
#else
strcpy(ver, VERSIONSTRING);
#endif
sprintf(buf, "%s"PATHSEP"media"PATHSEP"replay"PATHSEP"online"PATHSEP"%s"PATHSEP"%d-%s",
srb2home, ver, (int) (time(NULL)), G_BuildMapName(gamemap));
parts = M_PathParts(buf);
M_MkdirEachUntil(buf, parts - 5, parts - 1, 0755);
G_RecordDemo(buf);
}
@ -4067,8 +4147,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
P_SpawnSpecialsAfterSlopes();
P_SpawnMapThings(!fromnetsave);
skyboxmo[0] = skyboxviewpnts[0];
skyboxmo[1] = skyboxcenterpnts[0];
for (numcoopstarts = 0; numcoopstarts < MAXPLAYERS; numcoopstarts++)
if (!playerstarts[numcoopstarts])
@ -4128,6 +4206,8 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
memset(localaiming, 0, sizeof(localaiming));
}
K_InitDirector();
wantedcalcdelay = wantedfrequency*2;
indirectitemcooldown = 0;
hyubgone = 0;
@ -4227,7 +4307,9 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
return true;
// If so...
G_PreLevelTitleCard();
// but not if joining because the fade may time us out
if (!fromnetsave)
G_PreLevelTitleCard();
return true;
}

View file

@ -17,6 +17,7 @@
#include "doomdata.h"
#include "doomstat.h"
#include "r_defs.h"
#include "k_terrain.h"
// map md5, sent to players via PT_SERVERINFO
extern unsigned char mapmd5[16];
@ -71,6 +72,8 @@ typedef struct
UINT16 width, height;
terrain_t *terrain;
// for flat animation
INT32 animseq; // start pos. in the anim sequence
INT32 numpics;

View file

@ -850,6 +850,7 @@ void P_SlopeLaunch(mobj_t *mo)
//CONS_Printf("Launched off of slope.\n");
mo->standingslope = NULL;
mo->terrain = NULL;
if (mo->player)
{

View file

@ -43,6 +43,7 @@
#include "k_kart.h"
#include "console.h" // CON_LogMessage
#include "k_respawn.h"
#include "k_terrain.h"
#ifdef HW3SOUND
#include "hardware/hw3sound.h"
@ -51,7 +52,6 @@
// Not sure if this is necessary, but it was in w_wad.c, so I'm putting it here too -Shadow Hog
#include <errno.h>
mobj_t *skyboxmo[2]; // current skybox mobjs: 0 = viewpoint, 1 = centerpoint
mobj_t *skyboxviewpnts[16]; // array of MT_SKYBOX viewpoint mobjs
mobj_t *skyboxcenterpnts[16]; // array of MT_SKYBOX centerpoint mobjs
@ -2089,6 +2089,19 @@ static mobj_t *P_GetObjectTypeInSectorNum(mobjtype_t type, size_t s)
return NULL;
}
static void P_SwitchSkybox(INT32 ldflags, player_t *player, skybox_t *skybox)
{
if (!(ldflags & ML_EFFECT4)) // Solid Midtexture turns off viewpoint setting
{
player->skybox.viewpoint = skybox->viewpoint;
}
if (ldflags & ML_BLOCKPLAYERS) // Block Enemies turns ON centerpoint setting
{
player->skybox.centerpoint = skybox->centerpoint;
}
}
/** Processes the line special triggered by an object.
*
* \param line Line with the special command on it.
@ -3154,7 +3167,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
break;
}
case 448: // Change skybox viewpoint/centerpoint
if ((mo && mo->player && P_IsLocalPlayer(mo->player)) || (line->flags & ML_NOCLIMB))
if ((mo && mo->player) || (line->flags & ML_NOCLIMB))
{
INT32 viewid = sides[line->sidenum[0]].textureoffset>>FRACBITS;
INT32 centerid = sides[line->sidenum[0]].rowoffset>>FRACBITS;
@ -3167,23 +3180,32 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
}
else
{
skybox_t skybox;
// set viewpoint mobj
if (!(line->flags & ML_EFFECT4)) // Solid Midtexture turns off viewpoint setting
{
if (viewid >= 0 && viewid < 16)
skyboxmo[0] = skyboxviewpnts[viewid];
else
skyboxmo[0] = NULL;
}
if (viewid >= 0 && viewid < 16)
skybox.viewpoint = skyboxviewpnts[viewid];
else
skybox.viewpoint = NULL;
// set centerpoint mobj
if (line->flags & ML_BLOCKPLAYERS) // Block Enemies turns ON centerpoint setting
if (centerid >= 0 && centerid < 16)
skybox.centerpoint = skyboxcenterpnts[centerid];
else
skybox.centerpoint = NULL;
if (line->flags & ML_NOCLIMB) // Applies to all players
{
if (centerid >= 0 && centerid < 16)
skyboxmo[1] = skyboxcenterpnts[centerid];
else
skyboxmo[1] = NULL;
INT32 i;
for (i = 0; i < MAXPLAYERS; ++i)
{
if (playeringame[i])
P_SwitchSkybox(line->flags, &players[i], &skybox);
}
}
else
P_SwitchSkybox(line->flags, mo->player, &skybox);
}
CONS_Debug(DBG_GAMELOGIC, "Line type 448 Executor: viewid = %d, centerid = %d, viewpoint? = %s, centerpoint? = %s\n",
@ -3598,6 +3620,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
INT32 delay = (sides[line->sidenum[0]].rowoffset>>FRACBITS);
if (mo && mo->player)
{
// Don't award rings while SPB is targetting you
if (mo->player->pflags & PF_RINGLOCK)
return;
if (delay <= 0 || !(leveltime % delay))
P_GivePlayerRings(mo->player, rings);
}
@ -3633,7 +3659,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
if (mobj)
{
if (line->flags & ML_EFFECT1)
mobj->angle = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y);
P_InitAngle(mobj, R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y));
CONS_Debug(DBG_GAMELOGIC, "Linedef Type %d - Spawn Object: %d spawned at (%d, %d, %d)\n", line->special, mobj->type, mobj->x>>FRACBITS, mobj->y>>FRACBITS, mobj->z>>FRACBITS); //TODO: Convert mobj->type to a string somehow.
}
else
@ -3928,7 +3954,7 @@ void P_SetupSignExit(player_t *player)
if (player->mo && !P_MobjWasRemoved(player->mo))
{
thing = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->floorz, MT_SIGN);
thing->angle = player->mo->angle;
P_InitAngle(thing, player->mo->angle);
P_SetupSignObject(thing, player->mo, true); // Use :youfuckedup: sign face
}
}
@ -4333,7 +4359,9 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers
// Conveyor stuff
if (section3 == 2 || section3 == 4)
{
player->onconveyor = section3;
}
special = section1;
@ -4657,7 +4685,7 @@ DoneSection2:
case 6: // SRB2kart 190117 - Sneaker Panel
if (roversector || P_MobjReadyToTrigger(player->mo, sector))
{
if (!player->floorboost)
if (player->floorboost == 0)
player->floorboost = 3;
else
player->floorboost = 2;
@ -5050,6 +5078,7 @@ void P_PlayerInSpecialSector(player_t *player)
if (!player->mo)
return;
K_ProcessTerrainEffect(player->mo);
originalsector = player->mo->subsector->sector;
P_PlayerOnSpecial3DFloor(player, originalsector); // Handle FOFs first.

View file

@ -17,7 +17,6 @@
#ifndef __P_SPEC__
#define __P_SPEC__
extern mobj_t *skyboxmo[2]; // current skybox mobjs: 0 = viewpoint, 1 = centerpoint
extern mobj_t *skyboxviewpnts[16]; // array of MT_SKYBOX viewpoint mobjs
extern mobj_t *skyboxcenterpnts[16]; // array of MT_SKYBOX centerpoint mobjs

View file

@ -97,7 +97,7 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle,
P_FlashPal(thing->player, PAL_MIXUP, 10);
}
thing->angle = angle;
P_InitAngle(thing, angle);
thing->momx = thing->momy = thing->momz = 0;
@ -171,7 +171,7 @@ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle
P_FlashPal(thing->player, PAL_MIXUP, 10);
}
thing->angle = angle;
P_InitAngle(thing, angle);
return true;
}

View file

@ -34,6 +34,7 @@
#include "k_race.h"
#include "k_battle.h"
#include "k_waypoint.h"
#include "k_director.h"
tic_t leveltime;
@ -706,6 +707,8 @@ void P_Ticker(boolean run)
}
}
K_UpdateDirector();
// Always move the camera.
for (i = 0; i <= r_splitscreen; i++)
{

View file

@ -52,6 +52,7 @@
#include "k_respawn.h"
#include "k_bot.h"
#include "k_grandprix.h"
#include "k_terrain.h" // K_SpawnSplashForMobj
#ifdef HW3SOUND
#include "hardware/hw3sound.h"
@ -379,7 +380,7 @@ void P_GiveFinishFlags(player_t *player)
fixed_t xoffs = FINECOSINE(fa);
fixed_t yoffs = FINESINE(fa);
mobj_t* flag = P_SpawnMobjFromMobj(player->mo, xoffs, yoffs, 0, MT_FINISHFLAG);
flag->angle = angle;
P_InitAngle(flag, angle);
angle += FixedAngle(120*FRACUNIT);
P_SetTarget(&flag->target, player->mo);
@ -1274,17 +1275,18 @@ void P_DoPlayerExit(player_t *player)
//
// Handles player hitting floor surface.
// Returns whether to clip momz.
boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff)
boolean P_PlayerHitFloor(player_t *player, boolean fromAir)
{
boolean clipmomz;
(void)dorollstuff;
I_Assert(player->mo != NULL);
clipmomz = !(P_CheckDeathPitCollide(player->mo));
// SRB2Kart: removed lots of really vanilla-specific code here
if (fromAir == true && clipmomz == true)
{
K_SpawnSplashForMobj(player->mo, abs(player->mo->momz));
}
return clipmomz;
}
@ -2138,8 +2140,6 @@ void P_MovePlayer(player_t *player)
player->mo->rollangle = 0;
}
player->mo->movefactor = FRACUNIT; // We're not going to do any more with this, so let's change it back for the next frame.
//{ SRB2kart
// Drifting sound
@ -2176,7 +2176,7 @@ void P_MovePlayer(player_t *player)
if (trailScale > 0)
{
const angle_t forwardangle = K_MomentumAngle(player->mo);
const fixed_t playerVisualRadius = player->mo->radius + 8*FRACUNIT;
const fixed_t playerVisualRadius = player->mo->radius + (8 * player->mo->scale);
const size_t numFrames = S_WATERTRAIL8 - S_WATERTRAIL1;
const statenum_t curOverlayFrame = S_WATERTRAIL1 + (leveltime % numFrames);
const statenum_t curUnderlayFrame = S_WATERTRAILUNDERLAY1 + (leveltime % numFrames);
@ -2197,7 +2197,7 @@ void P_MovePlayer(player_t *player)
// underlay
water = P_SpawnMobj(x1, y1,
((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_WATERTRAILUNDERLAY].height, player->mo->scale) : player->mo->watertop), MT_WATERTRAILUNDERLAY);
water->angle = forwardangle - ANGLE_180 - ANGLE_22h;
P_InitAngle(water, forwardangle - ANGLE_180 - ANGLE_22h);
water->destscale = trailScale;
water->momx = player->mo->momx;
water->momy = player->mo->momy;
@ -2208,7 +2208,7 @@ void P_MovePlayer(player_t *player)
// overlay
water = P_SpawnMobj(x1, y1,
((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_WATERTRAIL].height, player->mo->scale) : player->mo->watertop), MT_WATERTRAIL);
water->angle = forwardangle - ANGLE_180 - ANGLE_22h;
P_InitAngle(water, forwardangle - ANGLE_180 - ANGLE_22h);
water->destscale = trailScale;
water->momx = player->mo->momx;
water->momy = player->mo->momy;
@ -2220,7 +2220,7 @@ void P_MovePlayer(player_t *player)
// Underlay
water = P_SpawnMobj(x2, y2,
((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_WATERTRAILUNDERLAY].height, player->mo->scale) : player->mo->watertop), MT_WATERTRAILUNDERLAY);
water->angle = forwardangle - ANGLE_180 + ANGLE_22h;
P_InitAngle(water, forwardangle - ANGLE_180 + ANGLE_22h);
water->destscale = trailScale;
water->momx = player->mo->momx;
water->momy = player->mo->momy;
@ -2231,7 +2231,7 @@ void P_MovePlayer(player_t *player)
// Overlay
water = P_SpawnMobj(x2, y2,
((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_WATERTRAIL].height, player->mo->scale) : player->mo->watertop), MT_WATERTRAIL);
water->angle = forwardangle - ANGLE_180 + ANGLE_22h;
P_InitAngle(water, forwardangle - ANGLE_180 + ANGLE_22h);
water->destscale = trailScale;
water->momx = player->mo->momx;
water->momy = player->mo->momy;
@ -2267,7 +2267,7 @@ void P_MovePlayer(player_t *player)
K_SpawnSparkleTrail(player->mo);
if (player->wipeoutslow > 1 && (leveltime & 1))
K_SpawnWipeoutTrail(player->mo, false);
K_SpawnWipeoutTrail(player->mo);
K_DriftDustHandling(player->mo);
@ -2464,8 +2464,10 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius)
indirectitemcooldown = 0;
}
if (mo->flags & MF_BOSS || mo->type == MT_PLAYER) //don't OHKO bosses nor players!
if (mo->flags & MF_BOSS) //don't OHKO bosses nor players!
P_DamageMobj(mo, inflictor, source, 1, DMG_NORMAL|DMG_CANTHURTSELF);
else if (mo->type == MT_PLAYER) // Thunder shield: Combo players.
P_DamageMobj(mo, inflictor, source, 1, DMG_NORMAL|DMG_CANTHURTSELF|DMG_WOMBO);
else
P_DamageMobj(mo, inflictor, source, 1000, DMG_NORMAL|DMG_CANTHURTSELF);
}
@ -3989,7 +3991,7 @@ static void P_HandleFollower(player_t *player)
P_SetTarget(&player->follower, P_SpawnMobj(sx, sy, sz, MT_FOLLOWER));
P_SetFollowerState(player->follower, fl.idlestate);
P_SetTarget(&player->follower->target, player->mo); // we need that to know when we need to disappear
player->follower->angle = player->mo->angle;
P_InitAngle(player->follower, player->mo->angle);
// This is safe to only spawn it here, the follower is removed then respawned when switched.
if (bubble)
@ -4052,10 +4054,8 @@ static void P_HandleFollower(player_t *player)
if (player->pflags & PF_NOCONTEST)
player->follower->renderflags |= RF_DONTDRAW;
if (player->speed && (player->follower->momx || player->follower->momy))
player->follower->angle = K_MomentumAngle(player->follower);
// if we're moving let's make the angle the direction we're moving towards. This is to avoid drifting / reverse looking awkward.
// Make sure the follower itself is also moving however, otherwise we'll be facing angle 0
// if we're moving let's make the angle the direction we're moving towards. This is to avoid drifting / reverse looking awkward.
player->follower->angle = K_MomentumAngle(player->follower);
// Finally, if the follower has bubbles, move them, set their scale, etc....
// This is what I meant earlier by it being easier, now we can just use this weird lil loop to get the job done!
@ -4504,8 +4504,6 @@ void P_PlayerThink(player_t *player)
P_MovePlayer(player);
}
player->mo->movefactor = FRACUNIT; // We're not going to do any more with this, so let's change it back for the next frame.
// Unset statis flag after moving.
// In other words, if you manually set stasis via code,
// it lasts for one tic.
@ -4557,7 +4555,7 @@ void P_PlayerThink(player_t *player)
|| (player->pflags & PF_NOCONTEST) // NO CONTEST explosion
|| ((gametyperules & GTR_BUMPERS) && player->bumpers <= 0 && player->karmadelay)))
{
if (player->flashing > 0 && player->flashing < K_GetKartFlashing(player)
if (player->flashing > 1 && player->flashing < K_GetKartFlashing(player)
&& (leveltime & 1))
player->mo->renderflags |= RF_DONTDRAW;
else

View file

@ -23,6 +23,8 @@
#include "z_zone.h" // Check R_Prep3DFloors
#include "taglist.h"
#include "k_terrain.h"
seg_t *curline;
side_t *sidedef;
line_t *linedef;
@ -67,11 +69,35 @@ boolean R_IsRipplePlane(sector_t *sector, ffloor_t *rover, int ceiling)
static void R_PlaneLightOverride(sector_t *sector, boolean ceiling, INT32 *lightlevel)
{
if (GETSECSPECIAL(sector->special, 4) == 6) // Fullbright sneaker panels
terrain_t *t = NULL;
if (ceiling == true)
{
if ((ceiling && (sector->flags & SF_FLIPSPECIAL_CEILING))
|| (!ceiling && (sector->flags & SF_FLIPSPECIAL_FLOOR)))
t = K_GetTerrainForFlatNum(sector->ceilingpic);
}
else
{
t = K_GetTerrainForFlatNum(sector->floorpic);
}
if (t != NULL)
{
if (t->flags & TRF_SNEAKERPANEL)
{
*lightlevel = 255;
}
}
else
{
// Sector effect sneaker panels (DEPRECATED)
if (GETSECSPECIAL(sector->special, 4) == 6)
{
if ((ceiling && (sector->flags & SF_FLIPSPECIAL_CEILING))
|| (!ceiling && (sector->flags & SF_FLIPSPECIAL_FLOOR)))
{
*lightlevel = 255;
}
}
}
}

View file

@ -180,6 +180,7 @@ void R_DrawViewBorder(void);
void R_DrawColumn_8(void);
void R_DrawShadeColumn_8(void);
void R_DrawTranslucentColumn_8(void);
void R_DrawDropShadowColumn_8(void);
void R_DrawTranslatedColumn_8(void);
void R_DrawTranslatedTranslucentColumn_8(void);
void R_Draw2sMultiPatchColumn_8(void);

View file

@ -566,6 +566,39 @@ void R_DrawTranslucentColumn_8(void)
}
}
// Hack: A cut-down copy of R_DrawTranslucentColumn_8 that does not read texture
// data since something about calculating the texture reading address for drop shadows is broken.
// dc_texturemid and dc_iscale get wrong values for drop shadows, however those are not strictly
// needed for the current design of the shadows, so this function bypasses the issue
// by not using those variables at all.
void R_DrawDropShadowColumn_8(void)
{
register INT32 count;
register UINT8 *dest;
count = dc_yh - dc_yl + 1;
if (count <= 0) // Zero length, column does not exceed a pixel.
return;
dest = &topleft[dc_yl*vid.width + dc_x];
{
#define DSCOLOR 15 // palette index for the color of the shadow
register const UINT8 *transmap_offset = dc_transmap + (dc_colormap[DSCOLOR] << 8);
#undef DSCOLOR
while ((count -= 2) >= 0)
{
*dest = *(transmap_offset + (*dest));
dest += vid.width;
*dest = *(transmap_offset + (*dest));
dest += vid.width;
}
if (count & 1)
*dest = *(transmap_offset + (*dest));
}
}
/** \brief The R_DrawTranslatedTranslucentColumn_8 function
Spiffy function. Not only does it colormap a sprite, but does translucency as well.
Uber-kudos to Cyan Helkaraxe

View file

@ -32,7 +32,6 @@ static viewvars_t skyview_new[MAXSPLITSCREENPLAYERS];
static viewvars_t *oldview = &pview_old[0];
viewvars_t *newview = &pview_new[0];
enum viewcontext_e viewcontext = VIEWCONTEXT_PLAYER1;
static fixed_t R_LerpFixed(fixed_t from, fixed_t to, fixed_t frac)
@ -81,12 +80,19 @@ static void R_SetupFreelook(player_t *player, boolean skybox)
#undef AIMINGTODY
void R_InterpolateViewRollAngle(fixed_t frac)
{
viewroll = oldview->roll + R_LerpAngle(oldview->roll, newview->roll, frac);
}
void R_InterpolateView(fixed_t frac)
{
if (frac < 0)
frac = 0;
#if 0
if (frac > FRACUNIT)
frac = FRACUNIT;
#endif
viewx = oldview->x + R_LerpFixed(oldview->x, newview->x, frac);
viewy = oldview->y + R_LerpFixed(oldview->y, newview->y, frac);
@ -94,7 +100,7 @@ void R_InterpolateView(fixed_t frac)
viewangle = oldview->angle + R_LerpAngle(oldview->angle, newview->angle, frac);
aimingangle = oldview->aim + R_LerpAngle(oldview->aim, newview->aim, frac);
viewroll = oldview->roll + R_LerpAngle(oldview->roll, newview->roll, frac);
R_InterpolateViewRollAngle(frac);
viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT);
viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT);
@ -147,3 +153,23 @@ void R_SetViewContext(enum viewcontext_e _viewcontext)
break;
}
}
fixed_t R_InterpolateFixed(fixed_t from, fixed_t to)
{
if (cv_frameinterpolation.value == 0)
{
return to;
}
return (from + R_LerpFixed(from, to, rendertimefrac));
}
angle_t R_InterpolateAngle(angle_t from, angle_t to)
{
if (cv_frameinterpolation.value == 0)
{
return to;
}
return (from + R_LerpAngle(from, to, rendertimefrac));
}

View file

@ -51,9 +51,14 @@ extern viewvars_t *newview;
// Interpolates the current view variables (r_state.h) against the selected view context in R_SetViewContext
void R_InterpolateView(fixed_t frac);
// Special function just for software
void R_InterpolateViewRollAngle(fixed_t frac);
// Buffer the current new views into the old views. Call once after each real tic.
void R_UpdateViewInterpolation(void);
// Set the current view context (the viewvars pointed to by newview)
void R_SetViewContext(enum viewcontext_e _viewcontext);
fixed_t R_InterpolateFixed(fixed_t from, fixed_t to);
angle_t R_InterpolateAngle(angle_t from, angle_t to);
#endif

View file

@ -28,7 +28,7 @@
#include "am_map.h"
#include "d_main.h"
#include "v_video.h"
#include "p_spec.h" // skyboxmo
//#include "p_spec.h"
#include "p_setup.h"
#include "z_zone.h"
#include "m_random.h" // quake camera shake
@ -1331,7 +1331,7 @@ void R_SkyboxFrame(player_t *player)
// cut-away view stuff
newview->sky = true;
r_viewmobj = skyboxmo[0];
r_viewmobj = player->skybox.viewpoint;
#ifdef PARANOIA
if (!r_viewmobj)
{
@ -1372,6 +1372,7 @@ void R_SkyboxFrame(player_t *player)
{
mapheader_t *mh = mapheaderinfo[gamemap-1];
vector3_t campos = {0,0,0}; // Position of player's actual view point
mobj_t *center = player->skybox.centerpoint;
if (player->awayviewtics) {
campos.x = player->awayviewmobj->x;
@ -1393,18 +1394,18 @@ void R_SkyboxFrame(player_t *player)
campos.y += quake.y;
campos.z += quake.z;
if (skyboxmo[1]) // Is there a viewpoint?
if (center) // Is there a viewpoint?
{
fixed_t x = 0, y = 0;
if (mh->skybox_scalex > 0)
x = (campos.x - skyboxmo[1]->x) / mh->skybox_scalex;
x = (campos.x - center->x) / mh->skybox_scalex;
else if (mh->skybox_scalex < 0)
x = (campos.x - skyboxmo[1]->x) * -mh->skybox_scalex;
x = (campos.x - center->x) * -mh->skybox_scalex;
if (mh->skybox_scaley > 0)
y = (campos.y - skyboxmo[1]->y) / mh->skybox_scaley;
y = (campos.y - center->y) / mh->skybox_scaley;
else if (mh->skybox_scaley < 0)
y = (campos.y - skyboxmo[1]->y) * -mh->skybox_scaley;
y = (campos.y - center->y) * -mh->skybox_scaley;
if (r_viewmobj->angle == 0)
{
@ -1617,8 +1618,8 @@ void R_RenderPlayerView(void)
// Add skybox portals caused by sky visplanes.
if (cv_skybox.value && skyboxmo[0])
Portal_AddSkyboxPortals();
if (cv_skybox.value && player->skybox.viewpoint)
Portal_AddSkyboxPortals(player);
// Portal rendering. Hijacks the BSP traversal.
ps_sw_portaltime = I_GetPreciseTime();

View file

@ -127,6 +127,4 @@ typedef struct planemgr_s
extern visffloor_t ffloor[MAXFFLOORS];
extern INT32 numffloors;
void Portal_AddSkyboxPortals (void);
#endif

View file

@ -256,12 +256,17 @@ static boolean TrimVisplaneBounds (const visplane_t* plane, INT16* start, INT16*
* Applies the necessary offsets and rotation to give
* a depth illusion to the skybox.
*/
void Portal_AddSkybox (const visplane_t* plane)
void Portal_AddSkybox
( const player_t * player,
const visplane_t * plane)
{
INT16 start, end;
mapheader_t *mh;
portal_t* portal;
mobj_t *viewpoint = player->skybox.viewpoint;
mobj_t *center = player->skybox.centerpoint;
if (TrimVisplaneBounds(plane, &start, &end))
return;
@ -269,28 +274,28 @@ void Portal_AddSkybox (const visplane_t* plane)
Portal_ClipVisplane(plane, portal);
portal->viewx = skyboxmo[0]->x;
portal->viewy = skyboxmo[0]->y;
portal->viewz = skyboxmo[0]->z;
portal->viewangle = viewangle + skyboxmo[0]->angle;
portal->viewx = viewpoint->x;
portal->viewy = viewpoint->y;
portal->viewz = viewpoint->z;
portal->viewangle = viewangle + viewpoint->angle;
mh = mapheaderinfo[gamemap-1];
// If a relative viewpoint exists, offset the viewpoint.
if (skyboxmo[1])
if (center)
{
fixed_t x = 0, y = 0;
angle_t ang = skyboxmo[0]->angle>>ANGLETOFINESHIFT;
angle_t ang = viewpoint->angle>>ANGLETOFINESHIFT;
if (mh->skybox_scalex > 0)
x = (viewx - skyboxmo[1]->x) / mh->skybox_scalex;
x = (viewx - center->x) / mh->skybox_scalex;
else if (mh->skybox_scalex < 0)
x = (viewx - skyboxmo[1]->x) * -mh->skybox_scalex;
x = (viewx - center->x) * -mh->skybox_scalex;
if (mh->skybox_scaley > 0)
y = (viewy - skyboxmo[1]->y) / mh->skybox_scaley;
y = (viewy - center->y) / mh->skybox_scaley;
else if (mh->skybox_scaley < 0)
y = (viewy - skyboxmo[1]->y) * -mh->skybox_scaley;
y = (viewy - center->y) * -mh->skybox_scaley;
// Apply transform to account for the skybox viewport angle.
portal->viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang));
@ -308,7 +313,7 @@ void Portal_AddSkybox (const visplane_t* plane)
/** Creates portals for the currently existing sky visplanes.
* The visplanes are also removed and cleared from the list.
*/
void Portal_AddSkyboxPortals (void)
void Portal_AddSkyboxPortals (const player_t *player)
{
visplane_t *pl;
INT32 i;
@ -320,7 +325,7 @@ void Portal_AddSkyboxPortals (void)
{
if (pl->picnum == skyflatnum)
{
Portal_AddSkybox(pl);
Portal_AddSkybox(player, pl);
pl->minx = 0;
pl->maxx = -1;

View file

@ -52,10 +52,10 @@ extern INT32 portalclipstart, portalclipend;
void Portal_InitList (void);
void Portal_Remove (portal_t* portal);
void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2);
void Portal_AddSkybox (const visplane_t* plane);
void Portal_AddSkybox (const player_t* player, const visplane_t* plane);
void Portal_ClipRange (portal_t* portal);
void Portal_ClipApply (const portal_t* portal);
void Portal_AddSkyboxPortals (void);
void Portal_AddSkyboxPortals (const player_t* player);
#endif

View file

@ -60,6 +60,7 @@ INT32 *texturebrightmaps;
// Painfully simple texture id cacheing to make maps load faster. :3
static struct {
char name[9];
UINT32 hash;
INT32 id;
} *tidcache = NULL;
static INT32 tidcachelen = 0;
@ -803,6 +804,7 @@ Rloadflats (INT32 i, INT32 w)
// Set texture properties.
M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name));
texture->hash = quickncasehash(texture->name, 8);
#ifndef NO_PNG_LUMPS
if (Picture_IsLumpPNG(header, lumplength))
@ -901,6 +903,7 @@ Rloadtextures (INT32 i, INT32 w)
// Set texture properties.
M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name));
texture->hash = quickncasehash(texture->name, 8);
#ifndef NO_PNG_LUMPS
if (Picture_IsLumpPNG((UINT8 *)&patchlump, lumplength))
@ -1389,6 +1392,7 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture)
// Allocate memory for a zero-patch texture. Obviously, we'll be adding patches momentarily.
resultTexture = (texture_t *)Z_Calloc(sizeof(texture_t),PU_STATIC,NULL);
M_Memcpy(resultTexture->name, newTextureName, 8);
resultTexture->hash = quickncasehash(newTextureName, 8);
resultTexture->width = newTextureWidth;
resultTexture->height = newTextureHeight;
resultTexture->type = TEXTURETYPE_COMPOSITE;
@ -1614,25 +1618,29 @@ void R_ClearTextureNumCache(boolean btell)
INT32 R_CheckTextureNumForName(const char *name)
{
INT32 i;
UINT32 hash;
// "NoTexture" marker.
if (name[0] == '-')
return 0;
hash = quickncasehash(name, 8);
for (i = 0; i < tidcachelen; i++)
if (!strncasecmp(tidcache[i].name, name, 8))
if (tidcache[i].hash == hash && !strncasecmp(tidcache[i].name, name, 8))
return tidcache[i].id;
// Need to parse the list backwards, so textures loaded more recently are used in lieu of ones loaded earlier
//for (i = 0; i < numtextures; i++) <- old
for (i = (numtextures - 1); i >= 0; i--) // <- new
if (!strncasecmp(textures[i]->name, name, 8))
if (textures[i]->hash == hash && !strncasecmp(textures[i]->name, name, 8))
{
tidcachelen++;
Z_Realloc(tidcache, tidcachelen * sizeof(*tidcache), PU_STATIC, &tidcache);
strncpy(tidcache[tidcachelen-1].name, name, 8);
tidcache[tidcachelen-1].name[8] = '\0';
CONS_Debug(DBG_SETUP, "texture #%s: %s\n", sizeu1(tidcachelen), tidcache[tidcachelen-1].name);
tidcache[tidcachelen-1].hash = hash;
tidcache[tidcachelen-1].id = i;
return i;
}

View file

@ -54,6 +54,7 @@ typedef struct
{
// Keep name for switch changing, etc.
char name[8];
UINT32 hash;
UINT8 type; // TEXTURETYPE_
INT16 width, height;
boolean holes;

View file

@ -46,6 +46,7 @@
// SRB2kart
#include "k_color.h"
#include "k_kart.h" // HITLAGJITTERS
#include "r_fps.h"
#define MINZ (FRACUNIT*4)
#define BASEYCENTER (BASEVIDHEIGHT/2)
@ -284,14 +285,13 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16
// store sprite info in lookup tables
//FIXME : numspritelumps do not duplicate sprite replacements
W_ReadLumpHeaderPwad(wadnum, l, &patch, PNG_HEADER_SIZE, 0);
#ifndef NO_PNG_LUMPS
{
UINT8 header[PNG_HEADER_SIZE];
size_t len = W_LumpLengthPwad(wadnum, l);
W_ReadLumpHeaderPwad(wadnum, l, header, sizeof header, 0);
if (Picture_IsLumpPNG(header, len))
if (Picture_IsLumpPNG((UINT8*)&patch, len))
{
UINT8 *png = W_CacheLumpNumPwad(wadnum, l, PU_STATIC);
Picture_PNGDimensions((UINT8 *)png, &width, &height, &topoffset, &leftoffset, len);
@ -303,7 +303,6 @@ boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16
if (!isPNG)
#endif
{
W_ReadLumpHeaderPwad(wadnum, l, &patch, sizeof(INT16) * 4, 0);
width = (INT32)(SHORT(patch.width));
height = (INT32)(SHORT(patch.height));
topoffset = (INT16)(SHORT(patch.topoffset));
@ -837,7 +836,15 @@ static void R_DrawVisSprite(vissprite_t *vis)
dc_fullbright = colormaps;
dc_translation = R_GetSpriteTranslation(vis);
if (R_SpriteIsFlashing(vis)) // Bosses "flash"
// Hack: Use a special column function for drop shadows that bypasses
// invalid memory access crashes caused by R_ProjectDropShadow putting wrong values
// in dc_texturemid and dc_iscale when the shadow is sloped.
if (vis->cut & SC_SHADOW)
{
R_SetColumnFunc(COLDRAWFUNC_DROPSHADOW, false);
dc_transmap = vis->transmap;
}
else if (R_SpriteIsFlashing(vis)) // Bosses "flash"
R_SetColumnFunc(COLDRAWFUNC_TRANS, false); // translate certain pixels to white
else if (vis->mobj->color && vis->transmap) // Color mapping
{
@ -854,7 +861,7 @@ static void R_DrawVisSprite(vissprite_t *vis)
else if (vis->mobj->sprite == SPR_PLAY) // Looks like a player, but doesn't have a color? Get rid of green sonic syndrome.
R_SetColumnFunc(COLDRAWFUNC_TRANS, false);
if (vis->extra_colormap && !(vis->renderflags & RF_NOCOLORMAPS))
if (vis->extra_colormap && !(vis->cut & SC_FULLBRIGHT) && !(vis->renderflags & RF_NOCOLORMAPS))
{
if (!dc_colormap)
dc_colormap = vis->extra_colormap->colormap;
@ -1149,15 +1156,21 @@ static void R_SplitSprite(vissprite_t *sprite)
// Get the first visible floor below the object for shadows
// shadowslope is filled with the floor's slope, if provided
//
fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope)
fixed_t R_GetShadowZ(
mobj_t *thing, pslope_t **shadowslope,
fixed_t interpx, fixed_t interpy, fixed_t interpz)
{
fixed_t halfHeight = interpz + (thing->height >> 1);
boolean isflipped = thing->eflags & MFE_VERTICALFLIP;
fixed_t floorz = P_GetFloorZ(thing, thing->subsector->sector, interpx, interpy, NULL);
fixed_t ceilingz = P_GetCeilingZ(thing, thing->subsector->sector, interpx, interpy, NULL);
fixed_t z, groundz = isflipped ? INT32_MAX : INT32_MIN;
pslope_t *slope, *groundslope = NULL;
msecnode_t *node;
sector_t *sector;
ffloor_t *rover;
#define CHECKZ (isflipped ? z > thing->z+thing->height/2 && z < groundz : z < thing->z+thing->height/2 && z > groundz)
#define CHECKZ (isflipped ? z > halfHeight && z < groundz : z < halfHeight && z > groundz)
for (node = thing->touching_sectorlist; node; node = node->m_sectorlist_next)
{
@ -1168,7 +1181,7 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope)
if (sector->heightsec != -1)
z = isflipped ? sectors[sector->heightsec].ceilingheight : sectors[sector->heightsec].floorheight;
else
z = isflipped ? P_GetSectorCeilingZAt(sector, thing->x, thing->y) : P_GetSectorFloorZAt(sector, thing->x, thing->y);
z = isflipped ? P_GetSectorCeilingZAt(sector, interpx, interpy) : P_GetSectorFloorZAt(sector, interpx, interpy);
if CHECKZ
{
@ -1182,7 +1195,7 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope)
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES) || (rover->alpha < 90 && !(rover->flags & FF_SWIMMABLE)))
continue;
z = isflipped ? P_GetFFloorBottomZAt(rover, thing->x, thing->y) : P_GetFFloorTopZAt(rover, thing->x, thing->y);
z = isflipped ? P_GetFFloorBottomZAt(rover, interpx, interpy) : P_GetFFloorTopZAt(rover, interpx, interpy);
if CHECKZ
{
@ -1192,10 +1205,10 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope)
}
}
if (isflipped ? (thing->ceilingz < groundz - (!groundslope ? 0 : FixedMul(abs(groundslope->zdelta), thing->radius*3/2)))
: (thing->floorz > groundz + (!groundslope ? 0 : FixedMul(abs(groundslope->zdelta), thing->radius*3/2))))
if (isflipped ? (ceilingz < groundz - (!groundslope ? 0 : FixedMul(abs(groundslope->zdelta), thing->radius*3/2)))
: (floorz > groundz + (!groundslope ? 0 : FixedMul(abs(groundslope->zdelta), thing->radius*3/2))))
{
groundz = isflipped ? thing->ceilingz : thing->floorz;
groundz = isflipped ? ceilingz : floorz;
groundslope = NULL;
}
@ -1206,10 +1219,10 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope)
{
INT32 xl, xh, yl, yh, bx, by;
xl = (unsigned)(thing->x - thing->radius - bmaporgx)>>MAPBLOCKSHIFT;
xh = (unsigned)(thing->x + thing->radius - bmaporgx)>>MAPBLOCKSHIFT;
yl = (unsigned)(thing->y - thing->radius - bmaporgy)>>MAPBLOCKSHIFT;
yh = (unsigned)(thing->y + thing->radius - bmaporgy)>>MAPBLOCKSHIFT;
xl = (unsigned)(interpx - thing->radius - bmaporgx)>>MAPBLOCKSHIFT;
xh = (unsigned)(interpx + thing->radius - bmaporgx)>>MAPBLOCKSHIFT;
yl = (unsigned)(interpy - thing->radius - bmaporgy)>>MAPBLOCKSHIFT;
yh = (unsigned)(interpy + thing->radius - bmaporgy)>>MAPBLOCKSHIFT;
BMBOUNDFIX(xl, xh, yl, yh);
@ -1246,7 +1259,7 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope)
// We're inside it! Yess...
z = po->lines[0]->backsector->ceilingheight;
if (z < thing->z+thing->height/2 && z > groundz)
if (z < halfHeight && z > groundz)
{
groundz = z;
groundslope = NULL;
@ -1269,11 +1282,12 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope)
static void R_SkewShadowSprite(
mobj_t *thing, pslope_t *groundslope,
fixed_t groundz, INT32 spriteheight, fixed_t scalemul,
fixed_t *shadowyscale, fixed_t *shadowskew)
fixed_t *shadowyscale, fixed_t *shadowskew,
fixed_t interpx, fixed_t interpy)
{
// haha let's try some dumb stuff
fixed_t xslope, zslope;
angle_t sloperelang = (R_PointToAngle(thing->x, thing->y) - groundslope->xydirection) >> ANGLETOFINESHIFT;
angle_t sloperelang = (R_PointToAngle(interpx, interpy) - groundslope->xydirection) >> ANGLETOFINESHIFT;
xslope = FixedMul(FINESINE(sloperelang), groundslope->zdelta);
zslope = FixedMul(FINECOSINE(sloperelang), groundslope->zdelta);
@ -1289,7 +1303,10 @@ static void R_SkewShadowSprite(
*shadowskew = xslope;
}
static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, fixed_t tx, fixed_t tz)
static void R_ProjectDropShadow(
mobj_t *thing, vissprite_t *vis,
fixed_t scale, fixed_t tx, fixed_t tz,
fixed_t interpx, fixed_t interpy, fixed_t interpz)
{
vissprite_t *shadow;
patch_t *patch;
@ -1298,7 +1315,7 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
fixed_t groundz;
pslope_t *groundslope;
groundz = R_GetShadowZ(thing, &groundslope);
groundz = R_GetShadowZ(thing, &groundslope, interpx, interpy, interpz);
if (abs(groundz-viewz)/tz > 4) return; // Prevent stretchy shadows and possible crashes
@ -1312,7 +1329,14 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
shadowskew = 0;
if (groundslope)
R_SkewShadowSprite(thing, groundslope, groundz, patch->height, FRACUNIT, &shadowyscale, &shadowskew);
{
R_SkewShadowSprite(
thing,
groundslope, groundz,
patch->height, FRACUNIT,
&shadowyscale, &shadowskew,
interpx, interpy);
}
tx -= patch->width * shadowxscale/2;
x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS;
@ -1331,8 +1355,8 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale,
shadow->mobjflags = 0;
shadow->sortscale = vis->sortscale;
shadow->dispoffset = vis->dispoffset - 5;
shadow->gx = thing->x;
shadow->gy = thing->y;
shadow->gx = interpx;
shadow->gy = interpy;
shadow->gzt = groundz + patch->height * shadowyscale / 2;
shadow->gz = shadow->gzt - patch->height * shadowyscale;
shadow->texturemid = FixedMul(thing->scale, FixedDiv(shadow->gzt - viewz, shadowyscale));
@ -1470,26 +1494,18 @@ static void R_ProjectSprite(mobj_t *thing)
#endif
// uncapped/interpolation
fixed_t interpx = thing->x;
fixed_t interpy = thing->y;
fixed_t interpz = thing->z;
angle_t interpangle = (thing->player ? thing->player->drawangle : thing->angle);
fixed_t interpx = R_InterpolateFixed(thing->old_x, thing->x);
fixed_t interpy = R_InterpolateFixed(thing->old_y, thing->y);
fixed_t interpz = R_InterpolateFixed(thing->old_z, thing->z);
angle_t interpangle = ANGLE_MAX;
// do interpolation
if (cv_frameinterpolation.value == 1)
if (thing->player)
{
interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x);
interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y);
interpz = thing->old_z + FixedMul(rendertimefrac, thing->z - thing->old_z);
if (thing->player)
{
interpangle = thing->player->old_drawangle + FixedMul(rendertimefrac, thing->player->drawangle - thing->player->old_drawangle);
}
else
{
interpangle = thing->old_angle + FixedMul(rendertimefrac, thing->angle - thing->old_angle);
}
interpangle = R_InterpolateAngle(thing->player->old_drawangle, thing->player->drawangle);
}
else
{
interpangle = R_InterpolateAngle(thing->old_angle, thing->angle);
}
// hitlag vibrating (todo: interp somehow?)
@ -1817,11 +1833,10 @@ static void R_ProjectSprite(mobj_t *thing)
fixed_t linkscale;
thing = thing->tracer;
if (cv_frameinterpolation.value == 1)
{
interpx = thing->old_x + FixedMul(thing->x - thing->old_x, rendertimefrac);
interpy = thing->old_y + FixedMul(thing->y - thing->old_y, rendertimefrac);
}
interpx = R_InterpolateFixed(thing->old_x, thing->x);
interpy = R_InterpolateFixed(thing->old_y, thing->y);
interpz = R_InterpolateFixed(thing->old_z, thing->z);
// hitlag vibrating (todo: interp somehow?)
if (thing->hitlag > 0 && (thing->eflags & MFE_DAMAGEHITLAG))
@ -1911,7 +1926,7 @@ static void R_ProjectSprite(mobj_t *thing)
if (shadowdraw || shadoweffects)
{
fixed_t groundz = R_GetShadowZ(thing, NULL);
fixed_t groundz = R_GetShadowZ(thing, NULL, interpx, interpy, interpz);
boolean isflipped = (thing->eflags & MFE_VERTICALFLIP);
if (shadoweffects)
@ -1935,7 +1950,7 @@ static void R_ProjectSprite(mobj_t *thing)
if (shadowskew)
{
R_SkewShadowSprite(thing, thing->standingslope, groundz, patch->height, shadowscale, &spriteyscale, &sheartan);
R_SkewShadowSprite(thing, thing->standingslope, groundz, patch->height, shadowscale, &spriteyscale, &sheartan, interpx, interpy);
gzt = (isflipped ? (thing->z + thing->height) : thing->z) + patch->height * spriteyscale / 2;
gz = gzt - patch->height * spriteyscale;
@ -2100,8 +2115,7 @@ static void R_ProjectSprite(mobj_t *thing)
//
// determine the colormap (lightlevel & special effects)
//
if (vis->cut & SC_FULLBRIGHT
&& (!vis->extra_colormap || !(vis->extra_colormap->flags & CMF_FADEFULLBRIGHTSPRITES)))
if (vis->cut & SC_FULLBRIGHT)
{
// full bright: goggles
vis->colormap = colormaps;
@ -2135,7 +2149,10 @@ static void R_ProjectSprite(mobj_t *thing)
R_SplitSprite(vis);
if (oldthing->shadowscale && cv_shadow.value)
R_ProjectDropShadow(oldthing, vis, oldthing->shadowscale, basetx, basetz);
{
R_ProjectDropShadow(oldthing, vis, oldthing->shadowscale, basetx, basetz,
interpx, interpy, interpz);
}
// Debug
++objectsdrawn;
@ -2161,17 +2178,9 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
fixed_t gz, gzt;
// uncapped/interpolation
fixed_t interpx = thing->x;
fixed_t interpy = thing->y;
fixed_t interpz = thing->z;
// do interpolation
if (cv_frameinterpolation.value == 1)
{
interpx = thing->old_x + FixedMul(rendertimefrac, thing->x - thing->old_x);
interpy = thing->old_y + FixedMul(rendertimefrac, thing->y - thing->old_y);
interpz = thing->old_z + FixedMul(rendertimefrac, thing->z - thing->old_z);
}
fixed_t interpx = R_InterpolateFixed(thing->old_x, thing->x);
fixed_t interpy = R_InterpolateFixed(thing->old_y, thing->y);
fixed_t interpz = R_InterpolateFixed(thing->old_z, thing->z);
// transform the origin point
tr_x = interpx - viewx;

View file

@ -59,7 +59,7 @@ void R_DrawFlippedMaskedColumn(column_t *column, column_t *brightmap);
extern INT16 negonearray[MAXVIDWIDTH];
extern INT16 screenheightarray[MAXVIDWIDTH];
fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope);
fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope, fixed_t interpx, fixed_t interpy, fixed_t interpz);
//SoM: 6/5/2000: Light sprites correctly!
void R_AddSprites(sector_t *sec, INT32 lightlevel);

View file

@ -1580,7 +1580,7 @@ void S_ShowMusicCredit(void)
{
cursongcredit.def = def;
cursongcredit.anim = 5*TICRATE;
cursongcredit.x = 0;
cursongcredit.x = cursongcredit.old_x =0;
cursongcredit.trans = NUMTRANSMAPS;
return;
}

View file

@ -179,8 +179,9 @@ extern struct cursongcredit
{
musicdef_t *def;
UINT16 anim;
INT32 x;
UINT8 trans;
fixed_t x;
fixed_t old_x;
} cursongcredit;
extern musicdef_t *musicdefstart;

View file

@ -133,6 +133,7 @@ void SCR_SetDrawFuncs(void)
colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8;
colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS] = R_Draw2sMultiPatchTranslucentColumn_8;
colfuncs[COLDRAWFUNC_FOG] = R_DrawFogColumn_8;
colfuncs[COLDRAWFUNC_DROPSHADOW] = R_DrawDropShadowColumn_8;
spanfuncs[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_8;
spanfuncs[SPANDRAWFUNC_TILTED] = R_DrawTiltedSpan_8;

View file

@ -131,6 +131,7 @@ enum
COLDRAWFUNC_TWOSMULTIPATCH,
COLDRAWFUNC_TWOSMULTIPATCHTRANS,
COLDRAWFUNC_FOG,
COLDRAWFUNC_DROPSHADOW,
COLDRAWFUNC_MAX
};

View file

@ -1660,11 +1660,10 @@ tic_t I_GetTime(void)
return (tic_t)f;
}
fixed_t I_GetTimeFrac(void)
float I_GetTimeFrac(void)
{
UpdateElapsedTics();
return FLOAT_TO_FIXED((float) (elapsed_tics - floor(elapsed_tics)));
return elapsed_tics;
}
precise_t I_GetPreciseTime(void)

View file

@ -517,7 +517,7 @@ static inline void I_SetChannels(void)
}
}
void I_SetSfxVolume(UINT8 volume)
void I_SetSfxVolume(int volume)
{
INT32 i;
@ -1466,7 +1466,7 @@ void I_ResumeSong(void)
#endif
}
void I_SetMusicVolume(UINT8 volume)
void I_SetMusicVolume(int volume)
{
(void)volume;
}
@ -1477,6 +1477,9 @@ boolean I_SetSongTrack(int track)
return false;
}
void I_UpdateSongLagThreshold(void){}
void I_UpdateSongLagConditions(void){}
/// ------------------------
/// MUSIC FADING
/// ------------------------

View file

@ -185,6 +185,16 @@ INT32 AngleDeltaSigned(angle_t a1, angle_t a2)
return (INT32)(a1) - (INT32)(a2);
}
float AngleToFloat(angle_t x)
{
return x / (float)ANG1;
}
angle_t FloatToAngle(float f)
{
return (angle_t)(f * ANG1);
}
#include "t_ftan.c"
#include "t_fsin.c"

View file

@ -108,6 +108,8 @@ FUNCMATH angle_t FixedAngleC(fixed_t fa, fixed_t factor);
// difference between two angle_t
FUNCMATH INT32 AngleDelta(angle_t a1, angle_t a2);
FUNCMATH INT32 AngleDeltaSigned(angle_t a1, angle_t a2);
FUNCMATH float AngleToFloat(angle_t x);
FUNCMATH angle_t FloatToAngle(float f);
/// The FixedAcos function
FUNCMATH angle_t FixedAcos(fixed_t x);

View file

@ -45,7 +45,7 @@ UINT8 *screens[5];
// screens[3] = fade screen start
// screens[4] = fade screen end, postimage tempoarary buffer
consvar_t cv_ticrate = CVAR_INIT ("showfps", "No", 0, CV_YesNo, NULL);
consvar_t cv_ticrate = CVAR_INIT ("showfps", "No", CV_SAVE, CV_YesNo, NULL);
static void CV_palette_OnChange(void);
@ -2532,6 +2532,18 @@ void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *st
V_DrawThinString(x, y, option, string);
}
void V_DrawCenteredThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
{
x -= (V_ThinStringWidth(string, option) / 2) * FRACUNIT;
V_DrawThinStringAtFixed(x, y, option, string);
}
void V_DrawRightAlignedThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string)
{
x -= V_ThinStringWidth(string, option) * FRACUNIT;
V_DrawThinStringAtFixed(x, y, option, string);
}
void V_DrawCenteredGamemodeString(INT32 x, INT32 y, INT32 option, const UINT8 *colormap, const char *string)
{
x -= V_GamemodeStringWidth(string, option)/2;

View file

@ -292,6 +292,9 @@ void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *st
#define V_DrawThinStringAtFixed( x,y,option,string ) \
V__DrawOneScaleString (x,y,FRACUNIT,option,NULL,TINY_FONT,string)
void V_DrawCenteredThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string);
void V_DrawRightAlignedThinStringAtFixed(fixed_t x, fixed_t y, INT32 option, const char *string);
// Draws a titlecard font string.
// timer: when the letters start appearing (leave to 0 to disable)
// threshold: when the letters start disappearing (leave to 0 to disable) (both are INT32 in case you supply negative values...)

View file

@ -69,6 +69,8 @@
#include "m_misc.h" // M_MapNumber
#include "g_game.h" // G_SetGameModified
#include "k_terrain.h"
#ifdef HWRENDER
#include "hardware/hw_main.h"
#include "hardware/hw_glob.h"
@ -354,6 +356,7 @@ static lumpinfo_t* ResGetLumpsStandalone (FILE* handle, UINT16* numlumps, const
lumpinfo->size = ftell(handle);
fseek(handle, 0, SEEK_SET);
strcpy(lumpinfo->name, lumpname);
lumpinfo->hash = quickncasehash(lumpname, 8);
// Allocate the lump's long name.
lumpinfo->longname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
@ -451,6 +454,7 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen
lump_p->compression = CM_NOCOMPRESSION;
memset(lump_p->name, 0x00, 9);
strncpy(lump_p->name, fileinfo->name, 8);
lump_p->hash = quickncasehash(lump_p->name, 8);
// Allocate the lump's long name.
lump_p->longname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
@ -625,6 +629,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
memset(lump_p->name, '\0', 9); // Making sure they're initialized to 0. Is it necessary?
strncpy(lump_p->name, trimname, min(8, dotpos - trimname));
lump_p->hash = quickncasehash(lump_p->name, 8);
lump_p->longname = Z_Calloc(dotpos - trimname + 1, PU_STATIC, NULL);
strlcpy(lump_p->longname, trimname, dotpos - trimname + 1);
@ -866,6 +871,8 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
break;
}
K_InitTerrain(numwadfiles - 1);
if (refreshdirmenu & REFRESHDIR_GAMEDATA)
G_LoadGameData();
DEH_UpdateMaxFreeslots();
@ -974,12 +981,14 @@ UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump)
{
UINT16 i;
static char uname[8 + 1];
UINT32 hash;
if (!TestValidLump(wad,0))
return INT16_MAX;
strlcpy(uname, name, sizeof uname);
strupr(uname);
hash = quickncasehash(uname, 8);
//
// scan forward
@ -990,7 +999,7 @@ UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump)
{
lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
if (!strncmp(lump_p->name, uname, sizeof(uname) - 1))
if (lump_p->hash == hash && !strncmp(lump_p->name, uname, sizeof(uname) - 1))
return i;
}
@ -1193,15 +1202,20 @@ lumpnum_t W_CheckNumForLongName(const char *name)
// TODO: Make it search through cache first, maybe...?
lumpnum_t W_CheckNumForMap(const char *name)
{
UINT32 hash = quickncasehash(name, 8);
UINT16 lumpNum, end;
UINT32 i;
lumpinfo_t *p;
for (i = numwadfiles - 1; i < numwadfiles; i--)
{
if (wadfiles[i]->type == RET_WAD)
{
for (lumpNum = 0; lumpNum < wadfiles[i]->numlumps; lumpNum++)
if (!strncmp(name, (wadfiles[i]->lumpinfo + lumpNum)->name, 8))
{
p = wadfiles[i]->lumpinfo + lumpNum;
if (p->hash == hash && !strncmp(name, p->name, 8))
return (i<<16) + lumpNum;
}
}
else if (wadfiles[i]->type == RET_PK3)
{
@ -1212,8 +1226,11 @@ lumpnum_t W_CheckNumForMap(const char *name)
continue;
// Now look for the specified map.
for (; lumpNum < end; lumpNum++)
if (!strnicmp(name, (wadfiles[i]->lumpinfo + lumpNum)->name, 8))
{
p = wadfiles[i]->lumpinfo + lumpNum;
if (p->hash == hash && !strnicmp(name, p->name, 8))
return (i<<16) + lumpNum;
}
}
}
return LUMPERROR;

View file

@ -67,6 +67,7 @@ typedef struct
unsigned long position; // filelump_t filepos
unsigned long disksize; // filelump_t size
char name[9]; // filelump_t name[] e.g. "LongEntr"
UINT32 hash;
char *longname; // e.g. "LongEntryName"
char *fullname; // e.g. "Folder/Subfolder/LongEntryName.extension"
size_t size; // real (uncompressed) size