Merge branch 'master' into slope-lighting

This commit is contained in:
Sally Coolatta 2022-05-25 04:04:38 -04:00
commit bc3a82b610
32 changed files with 1089 additions and 386 deletions

View file

@ -302,6 +302,7 @@ target_compile_definitions(SRB2SDL2 PRIVATE -DCMAKECONFIG)
#)
add_subdirectory(sdl)
add_subdirectory(objects)
if(${CMAKE_SYSTEM} MATCHES Windows)
add_subdirectory(win32)

View file

@ -208,6 +208,7 @@ objdir:=$(makedir)/objs
sources+=\
$(call List,Sourcefile)\
$(call List,blua/Sourcefile)\
$(call List,objects/Sourcefile)\
depends:=$(basename $(filter %.c %.s,$(sources)))
objects:=$(basename $(filter %.c %.s %.nas,$(sources)))

View file

@ -1448,8 +1448,7 @@ static void SendNameAndColor(UINT8 n)
player->skincolor = cv_playercolor[n].value;
if (player->mo && !player->dye)
player->mo->color = player->skincolor;
K_KartResetPlayerColor(player);
// Update follower for local games:
if (cv_follower[n].value >= -1 && cv_follower[n].value != player->followerskin)
@ -4367,7 +4366,11 @@ static void Command_Version_f(void)
#endif
// DEVELOP build
#ifdef DEVELOP
#if defined(TESTERS)
CONS_Printf("\x88" "TESTERS " "\x80");
#elif defined(HOSTTESTERS)
CONS_Printf("\x82" "HOSTTESTERS " "\x80");
#elif defined(DEVELOP)
CONS_Printf("\x87" "DEVELOP " "\x80");
#endif

View file

@ -469,6 +469,7 @@ typedef struct player_s
UINT16 hyudorotimer; // Duration of the Hyudoro offroad effect itself
SINT8 stealingtimer; // if >0 you are stealing, if <0 you are being stolen from
mobj_t *hoverhyudoro; // First hyudoro hovering next to player
UINT16 sneakertimer; // Duration of a Sneaker Boost (from Sneakers or level boosters)
UINT8 numsneakers; // Number of stacked sneaker effects

View file

@ -368,8 +368,8 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
"S_XDEATHSTATE",
"S_RAISESTATE",
// Thok
"S_THOK",
"S_SHADOW",
// SRB2kart Frames
"S_KART_STILL",
@ -3745,6 +3745,9 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
"S_FLAMESHIELDLINE3",
"S_FLAMESHIELDFLASH",
// Caked-Up Booty-Sheet Ghost
"S_HYUDORO",
// The legend
"S_SINK",
"S_SINK_SHIELD",
@ -4493,6 +4496,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
"MT_UNKNOWN",
"MT_THOK", // Thok! mobj
"MT_SHADOW", // Linkdraw Shadow (for invisible objects)
"MT_PLAYER",
"MT_KART_LEFTOVER",
"MT_KART_TIRE",
@ -5315,6 +5319,9 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
"MT_FLAMESHIELDPAPER",
"MT_BUBBLESHIELDTRAP",
"MT_HYUDORO",
"MT_HYUDORO_CENTER",
"MT_SINK", // Kitchen Sink Stuff
"MT_SINK_SHIELD",
"MT_SINKTRAIL",

View file

@ -696,7 +696,6 @@ extern boolean comeback;
extern SINT8 battlewanted[4];
extern tic_t wantedcalcdelay;
extern tic_t indirectitemcooldown;
extern tic_t hyubgone;
extern tic_t mapreset;
extern boolean thwompsactive;
extern UINT8 lastLowestLap;

View file

@ -1998,6 +1998,38 @@ void F_TitleScreenDrawer(void)
V_DrawFixedPatch(0, 0, FRACUNIT, 0, kts_bumper, NULL);
V_DrawFixedPatch(0, 0, FRACUNIT, 0, kts_copyright, NULL);
// An adapted thing from old menus - most games have version info on the title screen now...
{
INT32 texty = vid.height - 10*vid.dupy;
#define addtext(f, str) {\
V_DrawThinString(vid.dupx, texty, V_NOSCALESTART|f, str);\
texty -= 10*vid.dupy;\
}
if (customversionstring[0] != '\0')
{
addtext(V_ALLOWLOWERCASE, customversionstring);
addtext(0, "Mod version:");
}
else
{
// Development -- show revision / branch info
#if defined(TESTERS)
addtext(V_ALLOWLOWERCASE|V_SKYMAP, "Tester client");
addtext(V_ALLOWLOWERCASE|V_TRANSLUCENT, va("%s", compdate));
#elif defined(HOSTTESTERS)
addtext(V_ALLOWLOWERCASE|V_REDMAP, "Netgame host for testers");
addtext(V_ALLOWLOWERCASE|V_TRANSLUCENT, va("%s", compdate));
#elif defined(DEVELOP)
addtext(V_ALLOWLOWERCASE|V_TRANSLUCENT, comprevision);
addtext(V_ALLOWLOWERCASE|V_TRANSLUCENT, compbranch);
#else // Regular build
addtext(V_ALLOWLOWERCASE|V_TRANSLUCENT, va("%s", VERSIONSTRING));
#endif
}
#undef addtext
}
break;
}

View file

@ -316,7 +316,6 @@ SINT8 pickedvote; // What vote the host rolls
SINT8 battlewanted[4]; // WANTED players in battle, worth x2 points
tic_t wantedcalcdelay; // Time before it recalculates WANTED
tic_t indirectitemcooldown; // Cooldown before any more Shrink, SPB, or any other item that works indirectly is awarded
tic_t hyubgone; // Cooldown before hyudoro is allowed to be rerolled
tic_t mapreset; // Map reset delay when enough players have joined an empty game
boolean thwompsactive; // Thwomps activate on lap 2
UINT8 lastLowestLap; // Last lowest lap, for activating race lap executors

View file

@ -29,6 +29,7 @@
char sprnames[NUMSPRITES + 1][5] =
{
"NULL", // invisible object
"NONE", // invisible but still rendered
"UNKN",
"THOK", // Thok! mobj
@ -570,6 +571,7 @@ char sprnames[NUMSPRITES + 1][5] =
"FLMP", // Flame Shield paper sprites
"FLML", // Flame Shield speed lines
"FLMF", // Flame Shield flash
"HYUU", // Hyudoro
"SINK", // Kitchen Sink
"SITR", // Kitchen Sink Trail
"KBLN", // Battle Mode Bumper
@ -856,6 +858,7 @@ state_t states[NUMSTATES] =
{SPR_UNKN, FF_FULLBRIGHT, -1, {A_InfoState}, 6, 0, S_NULL}, // S_RAISESTATE
{SPR_THOK, FF_TRANS50, 8, {NULL}, 0, 0, S_NULL}, // S_THOK
{SPR_NONE, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SHADOW
// Player
{SPR_PLAY, SPR2_STIN, 1, {NULL}, 0, 0, S_KART_STILL}, // S_KART_STILL
@ -4300,6 +4303,8 @@ state_t states[NUMSTATES] =
{SPR_FLML, FF_FULLBRIGHT|FF_PAPERSPRITE|FF_ANIMATE|14, 7, {NULL}, 6, 1, S_NULL}, // S_FLAMESHIELDLINE3
{SPR_FLMF, FF_FULLBRIGHT, 2, {NULL}, 0, 0, S_NULL}, // S_FLAMESHIELDFLASH
{SPR_HYUU, FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_HYUDORO
{SPR_SINK, 0, 1, {A_SmokeTrailer}, MT_SINKTRAIL, 0, S_SINK}, // S_SINK
{SPR_SINK, 0|FF_TRANS80|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_SINK_SHIELD}, // S_SINK_SHIELD
{SPR_SITR, 0, 1, {NULL}, 0, 0, S_SINKTRAIL2}, // S_SINKTRAIL1
@ -5154,6 +5159,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_SHADOW
-1, // doomednum
S_SHADOW, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
8, // speed
32*FRACUNIT, // radius
64*FRACUNIT, // height
-1, // display offset
16, // mass
0, // damage
sfx_None, // activesound
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_PLAYER
-1, // doomednum
S_KART_STILL, // spawnstate
@ -23881,6 +23913,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
S_NULL // raisestate
},
{ // MT_HYUDORO
-1, // doomednum
S_HYUDORO, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
32*FRACUNIT, // radius
24*FRACUNIT, // height
0, // display offset
0, // mass
0, // damage
sfx_None, // activesound
MF_SPECIAL|MF_NOCLIP|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_HYUDORO_CENTER
-1, // doomednum
S_INVISIBLE, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_None, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_NULL, // deathstate
S_NULL, // xdeathstate
sfx_None, // deathsound
0, // speed
64*FRACUNIT, // radius
32*FRACUNIT, // height
0, // display offset
0, // mass
0, // damage
sfx_None, // activesound
MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
S_NULL // raisestate
},
{ // MT_SINK
-1, // doomednum
S_SINK, // spawnstate

View file

@ -575,6 +575,7 @@ extern boolean actionsoverridden[NUMACTIONS];
typedef enum sprite
{
SPR_NULL, // invisible object
SPR_NONE, // invisible but still rendered
SPR_UNKN,
SPR_THOK, // Thok! mobj
@ -1116,6 +1117,7 @@ typedef enum sprite
SPR_FLMP, // Flame Shield paper sprites
SPR_FLML, // Flame Shield speed lines
SPR_FLMF, // Flame Shield flash
SPR_HYUU, // Hyudoro
SPR_SINK, // Kitchen Sink
SPR_SITR, // Kitchen Sink Trail
SPR_KBLN, // Battle Mode Bumper
@ -1355,8 +1357,8 @@ typedef enum state
S_XDEATHSTATE,
S_RAISESTATE,
// Thok
S_THOK,
S_SHADOW,
S_KART_STILL,
S_KART_STILL_L,
@ -4731,6 +4733,9 @@ typedef enum state
S_FLAMESHIELDLINE3,
S_FLAMESHIELDFLASH,
// Caked-Up Booty-Sheet Ghost
S_HYUDORO,
// The legend
S_SINK,
S_SINK_SHIELD,
@ -5516,6 +5521,7 @@ typedef enum mobj_type
MT_UNKNOWN,
MT_THOK, // Thok! mobj
MT_SHADOW, // Linkdraw Shadow (for invisible objects)
MT_PLAYER,
MT_KART_LEFTOVER,
MT_KART_TIRE,
@ -6338,6 +6344,9 @@ typedef enum mobj_type
MT_FLAMESHIELDPAPER,
MT_BUBBLESHIELDTRAP,
MT_HYUDORO,
MT_HYUDORO_CENTER,
MT_SINK, // Kitchen Sink Stuff
MT_SINK_SHIELD,
MT_SINKTRAIL,

View file

@ -51,7 +51,7 @@ struct globalsmuggle
} globalsmuggle;
/*--------------------------------------------------
static boolean K_FindEggboxes(mobj_t *thing)
static BlockItReturn_t K_FindEggboxes(mobj_t *thing)
Blockmap search function.
Increments the random items and egg boxes counters.
@ -60,27 +60,27 @@ struct globalsmuggle
thing - Object passed in from iteration.
Return:-
true continues searching, false ends the search early.
BlockItReturn_t enum, see its definition for more information.
--------------------------------------------------*/
static boolean K_FindEggboxes(mobj_t *thing)
static BlockItReturn_t K_FindEggboxes(mobj_t *thing)
{
fixed_t dist;
if (thing->type != MT_RANDOMITEM && thing->type != MT_EGGMANITEM)
{
return true;
return BMIT_CONTINUE;
}
if (!thing->health)
{
return true;
return BMIT_CONTINUE;
}
dist = P_AproxDistance(thing->x - globalsmuggle.eggboxx, thing->y - globalsmuggle.eggboxy);
if (dist > globalsmuggle.distancetocheck)
{
return true;
return BMIT_CONTINUE;
}
if (thing->type == MT_RANDOMITEM)
@ -92,7 +92,7 @@ static boolean K_FindEggboxes(mobj_t *thing)
globalsmuggle.eggboxes++;
}
return true;
return BMIT_CONTINUE;
}
/*--------------------------------------------------
@ -347,7 +347,7 @@ static boolean K_PlayerAttackSteer(mobj_t *thing, UINT8 side, UINT8 weight, bool
}
/*--------------------------------------------------
static boolean K_FindObjectsForNudging(mobj_t *thing)
static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing)
Blockmap search function.
Finds objects around the bot to steer towards/away from.
@ -356,9 +356,9 @@ static boolean K_PlayerAttackSteer(mobj_t *thing, UINT8 side, UINT8 weight, bool
thing - Object passed in from iteration.
Return:-
true continues searching, false ends the search early.
BlockItReturn_t enum, see its definition for more information.
--------------------------------------------------*/
static boolean K_FindObjectsForNudging(mobj_t *thing)
static BlockItReturn_t K_FindObjectsForNudging(mobj_t *thing)
{
INT16 anglediff;
fixed_t fulldist;
@ -367,29 +367,29 @@ static boolean K_FindObjectsForNudging(mobj_t *thing)
if (!globalsmuggle.botmo || P_MobjWasRemoved(globalsmuggle.botmo) || !globalsmuggle.botmo->player)
{
return false;
return BMIT_ABORT;
}
if (thing->health <= 0)
{
return true;
return BMIT_CONTINUE;
}
if (globalsmuggle.botmo == thing)
{
return true;
return BMIT_CONTINUE;
}
fulldist = R_PointToDist2(globalsmuggle.botmo->x, globalsmuggle.botmo->y, thing->x, thing->y) - thing->radius;
if (fulldist > globalsmuggle.distancetocheck)
{
return true;
return BMIT_CONTINUE;
}
if (P_CheckSight(globalsmuggle.botmo, thing) == false)
{
return true;
return BMIT_CONTINUE;
}
predictangle = R_PointToAngle2(globalsmuggle.botmo->x, globalsmuggle.botmo->y, globalsmuggle.predict->x, globalsmuggle.predict->y);
@ -607,7 +607,7 @@ static boolean K_FindObjectsForNudging(mobj_t *thing)
break;
}
return true;
return BMIT_CONTINUE;
}
/*--------------------------------------------------
@ -776,7 +776,7 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player)
}
/*--------------------------------------------------
static boolean K_FindPlayersToBully(mobj_t *thing)
static BlockItReturn_t K_FindPlayersToBully(mobj_t *thing)
Blockmap search function.
Finds players around the bot to bump.
@ -785,9 +785,9 @@ void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player)
thing - Object passed in from iteration.
Return:-
true continues searching, false ends the search early.
BlockItReturn_t enum, see its definition for more information.
--------------------------------------------------*/
static boolean K_FindPlayersToBully(mobj_t *thing)
static BlockItReturn_t K_FindPlayersToBully(mobj_t *thing)
{
INT16 anglediff;
fixed_t fulldist;
@ -796,34 +796,34 @@ static boolean K_FindPlayersToBully(mobj_t *thing)
if (!globalsmuggle.botmo || P_MobjWasRemoved(globalsmuggle.botmo) || !globalsmuggle.botmo->player)
{
return false;
return BMIT_ABORT;
}
if (thing->health <= 0)
{
return true;
return BMIT_CONTINUE;
}
if (!thing->player)
{
return true;
return BMIT_CONTINUE;
}
if (globalsmuggle.botmo == thing)
{
return true;
return BMIT_CONTINUE;
}
fulldist = R_PointToDist2(globalsmuggle.botmo->x, globalsmuggle.botmo->y, thing->x, thing->y) - thing->radius;
if (fulldist > globalsmuggle.distancetocheck)
{
return true;
return BMIT_CONTINUE;
}
if (P_CheckSight(globalsmuggle.botmo, thing) == false)
{
return true;
return BMIT_CONTINUE;
}
ourangle = globalsmuggle.botmo->angle;
@ -860,7 +860,7 @@ static boolean K_FindPlayersToBully(mobj_t *thing)
globalsmuggle.annoymo = thing;
}
return true;
return BMIT_CONTINUE;
}
/*--------------------------------------------------

View file

@ -323,26 +323,26 @@ static inline boolean PIT_SSMineChecks(mobj_t *thing)
return false;
}
static inline boolean PIT_SSMineSearch(mobj_t *thing)
static inline BlockItReturn_t PIT_SSMineSearch(mobj_t *thing)
{
if (grenade == NULL || P_MobjWasRemoved(grenade))
return false; // There's the possibility these can chain react onto themselves after they've already died if there are enough all in one spot
return BMIT_ABORT; // There's the possibility these can chain react onto themselves after they've already died if there are enough all in one spot
if (grenade->flags2 & MF2_DEBRIS) // don't explode twice
return false;
return BMIT_ABORT;
if (thing->type != MT_PLAYER) // Don't explode for anything but an actual player.
return true;
return BMIT_CONTINUE;
if (thing == grenade->target && grenade->threshold != 0) // Don't blow up at your owner instantly.
return true;
return BMIT_CONTINUE;
if (PIT_SSMineChecks(thing) == true)
return true;
return BMIT_CONTINUE;
// Explode!
P_SetMobjState(grenade, grenade->info->deathstate);
return false;
return BMIT_ABORT;
}
void K_DoMineSearch(mobj_t *actor, fixed_t size)
@ -364,21 +364,21 @@ void K_DoMineSearch(mobj_t *actor, fixed_t size)
P_BlockThingsIterator(bx, by, PIT_SSMineSearch);
}
static inline boolean PIT_SSMineExplode(mobj_t *thing)
static inline BlockItReturn_t PIT_SSMineExplode(mobj_t *thing)
{
if (grenade == NULL || P_MobjWasRemoved(grenade))
return false; // There's the possibility these can chain react onto themselves after they've already died if there are enough all in one spot
return BMIT_ABORT; // There's the possibility these can chain react onto themselves after they've already died if there are enough all in one spot
#if 0
if (grenade->flags2 & MF2_DEBRIS) // don't explode twice
return false;
return BMIT_ABORT;
#endif
if (PIT_SSMineChecks(thing) == true)
return true;
return BMIT_CONTINUE;
P_DamageMobj(thing, grenade, grenade->target, 1, (explodespin ? DMG_NORMAL : DMG_EXPLODE));
return true;
return BMIT_CONTINUE;
}
void K_MineExplodeAttack(mobj_t *actor, fixed_t size, boolean spin)
@ -667,60 +667,54 @@ boolean K_DropTargetCollide(mobj_t *t1, mobj_t *t2)
static mobj_t *lightningSource;
static fixed_t lightningDist;
static inline boolean PIT_LightningShieldAttack(mobj_t *thing)
static inline BlockItReturn_t PIT_LightningShieldAttack(mobj_t *thing)
{
if (lightningSource == NULL || P_MobjWasRemoved(lightningSource))
{
// Invalid?
return false;
return BMIT_ABORT;
}
if (thing == lightningSource)
{
// Don't explode yourself!!
return true;
return BMIT_CONTINUE;
}
if (thing->health <= 0)
{
// Dead
return true;
return BMIT_CONTINUE;
}
if (!(thing->flags & MF_SHOOTABLE) || (thing->flags & MF_SCENERY))
{
// Not shootable
return true;
return BMIT_CONTINUE;
}
if (thing->player && thing->player->spectator)
{
// Spectator
return true;
}
if ((lightningSource->eflags & MFE_VERTICALFLIP)
? (thing->z > lightningSource->z + lightningSource->height)
: (thing->z + thing->height < lightningSource->z))
{
// Underneath
return true;
return BMIT_CONTINUE;
}
if (P_AproxDistance(thing->x - lightningSource->x, thing->y - lightningSource->y) > lightningDist + thing->radius)
{
// Too far away
return true;
return BMIT_CONTINUE;
}
#if 0
if (P_CheckSight(lightningSource, thing) == false)
{
// Not in sight
return true;
return BMIT_CONTINUE;
}
#endif
P_DamageMobj(thing, lightningSource, lightningSource, 1, DMG_NORMAL|DMG_CANTHURTSELF|DMG_WOMBO);
return true;
return BMIT_CONTINUE;
}
void K_LightningShieldAttack(mobj_t *actor, fixed_t size)

View file

@ -38,6 +38,7 @@
#include "k_director.h"
#include "k_collide.h"
#include "k_follower.h"
#include "k_objects.h"
// SOME IMPORTANT VARIABLES DEFINED IN DOOMDEF.H:
// gamespeed is cc (0 for easy, 1 for normal, 2 for hard)
@ -353,25 +354,25 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS-1][8] =
//P-Odds 0 1 2 3 4 5 6 7
/*Sneaker*/ { 0, 0, 2, 4, 6, 0, 0, 0 }, // Sneaker
/*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 2, 4, 6 }, // Rocket Sneaker
/*Invincibility*/ { 0, 0, 0, 0, 2, 4, 6, 9 }, // Invincibility
/*Banana*/ { 4, 3, 1, 0, 0, 0, 0, 0 }, // Banana
/*Invincibility*/ { 0, 0, 0, 0, 3, 4, 6, 9 }, // Invincibility
/*Banana*/ { 2, 3, 1, 0, 0, 0, 0, 0 }, // Banana
/*Eggman Monitor*/ { 1, 2, 0, 0, 0, 0, 0, 0 }, // Eggman Monitor
/*Orbinaut*/ { 5, 4, 2, 2, 0, 0, 0, 0 }, // Orbinaut
/*Jawz*/ { 0, 3, 2, 1, 1, 0, 0, 0 }, // Jawz
/*Mine*/ { 0, 2, 3, 1, 0, 0, 0, 0 }, // Mine
/*Land Mine*/ { 3, 0, 0, 0, 0, 0, 0, 0 }, // Land Mine
/*Ballhog*/ { 0, 0, 2, 1, 0, 0, 0, 0 }, // Ballhog
/*Ballhog*/ { 0, 0, 2, 2, 0, 0, 0, 0 }, // Ballhog
/*Self-Propelled Bomb*/ { 0, 0, 0, 0, 0, 2, 4, 0 }, // Self-Propelled Bomb
/*Grow*/ { 0, 0, 0, 1, 2, 3, 0, 0 }, // Grow
/*Shrink*/ { 0, 0, 0, 0, 0, 0, 2, 0 }, // Shrink
/*Lightning Shield*/ { 1, 2, 0, 0, 0, 0, 0, 0 }, // Lightning Shield
/*Bubble Shield*/ { 0, 1, 2, 1, 0, 0, 0, 0 }, // Bubble Shield
/*Flame Shield*/ { 0, 0, 0, 0, 0, 1, 3, 5 }, // Flame Shield
/*Hyudoro*/ { 0, 0, 0, 1, 1, 0, 0, 0 }, // Hyudoro
/*Hyudoro*/ { 3, 0, 0, 0, 0, 0, 0, 0 }, // Hyudoro
/*Pogo Spring*/ { 0, 0, 0, 0, 0, 0, 0, 0 }, // Pogo Spring
/*Super Ring*/ { 2, 1, 1, 0, 0, 0, 0, 0 }, // Super Ring
/*Kitchen Sink*/ { 0, 0, 0, 0, 0, 0, 0, 0 }, // Kitchen Sink
/*Drop Target*/ { 4, 0, 0, 0, 0, 0, 0, 0 }, // Drop Target
/*Drop Target*/ { 3, 0, 0, 0, 0, 0, 0, 0 }, // Drop Target
/*Sneaker x2*/ { 0, 0, 2, 2, 1, 0, 0, 0 }, // Sneaker x2
/*Sneaker x3*/ { 0, 0, 0, 2, 6,10, 5, 0 }, // Sneaker x3
/*Banana x3*/ { 0, 1, 1, 0, 0, 0, 0, 0 }, // Banana x3
@ -458,9 +459,6 @@ static void K_KartGetItemResult(player_t *player, SINT8 getitem)
if (getitem == KITEM_SPB || getitem == KITEM_SHRINK) // Indirect items
indirectitemcooldown = 20*TICRATE;
if (getitem == KITEM_HYUDORO) // Hyudoro cooldown
hyubgone = 5*TICRATE;
player->botvars.itemdelay = TICRATE;
player->botvars.itemconfirm = 0;
@ -682,6 +680,7 @@ INT32 K_KartGetItemOdds(
case KITEM_LANDMINE:
case KITEM_DROPTARGET:
case KITEM_BALLHOG:
case KITEM_HYUDORO:
case KRITEM_TRIPLESNEAKER:
case KRITEM_TRIPLEORBINAUT:
case KRITEM_QUADORBINAUT:
@ -742,13 +741,6 @@ INT32 K_KartGetItemOdds(
if (spbplace != -1)
newodds = 0;
break;
case KITEM_HYUDORO:
cooldownOnStart = true;
notNearEnd = true;
if (hyubgone > 0)
newodds = 0;
break;
default:
break;
}
@ -2917,6 +2909,7 @@ boolean K_TripwirePassConditions(player_t *player)
player->sneakertimer ||
player->growshrinktimer > 0 ||
player->flamedash ||
player->hyudorotimer ||
player->speed > 2 * K_GetKartSpeed(player, false)
)
return true;
@ -3549,8 +3542,7 @@ static void K_RemoveGrowShrink(player_t *player)
else if (player->growshrinktimer < 0) // Play Grow noise
S_StartSound(player->mo, sfx_kc5a);
if (player->invincibilitytimer == 0)
player->mo->color = player->skincolor;
K_KartResetPlayerColor(player);
player->mo->scalespeed = mapobjectscale/TICRATE;
player->mo->destscale = mapobjectscale;
@ -5394,6 +5386,7 @@ static void K_FlameDashLeftoverSmoke(mobj_t *src)
}
}
#if 0
static void K_DoHyudoroSteal(player_t *player)
{
INT32 i, numplayers = 0;
@ -5471,6 +5464,7 @@ static void K_DoHyudoroSteal(player_t *player)
S_StartSound(NULL, sfx_s3k92);
}
}
#endif
void K_DoSneaker(player_t *player, INT32 type)
{
@ -7061,57 +7055,57 @@ static mobj_t *attractmo;
static fixed_t attractdist;
static fixed_t attractzdist;
static inline boolean PIT_AttractingRings(mobj_t *thing)
static inline BlockItReturn_t PIT_AttractingRings(mobj_t *thing)
{
if (attractmo == NULL || P_MobjWasRemoved(attractmo) || attractmo->player == NULL)
{
return false;
return BMIT_ABORT;
}
if (thing == NULL || P_MobjWasRemoved(thing))
{
return true; // invalid
return BMIT_CONTINUE; // invalid
}
if (thing == attractmo)
{
return true; // invalid
return BMIT_CONTINUE; // invalid
}
if (!(thing->type == MT_RING || thing->type == MT_FLINGRING))
{
return true; // not a ring
return BMIT_CONTINUE; // not a ring
}
if (thing->health <= 0)
{
return true; // dead
return BMIT_CONTINUE; // dead
}
if (thing->extravalue1)
{
return true; // in special ring animation
return BMIT_CONTINUE; // in special ring animation
}
if (thing->tracer != NULL && P_MobjWasRemoved(thing->tracer) == false)
{
return true; // already attracted
return BMIT_CONTINUE; // already attracted
}
// see if it went over / under
if (attractmo->z - attractzdist > thing->z + thing->height)
{
return true; // overhead
return BMIT_CONTINUE; // overhead
}
if (attractmo->z + attractmo->height + attractzdist < thing->z)
{
return true; // underneath
return BMIT_CONTINUE; // underneath
}
if (P_AproxDistance(attractmo->x - thing->x, attractmo->y - thing->y) > attractdist + thing->radius)
{
return true; // Too far away
return BMIT_CONTINUE; // Too far away
}
if (RINGTOTAL(attractmo->player) >= 20 || (attractmo->player->pflags & PF_RINGLOCK))
@ -7138,7 +7132,7 @@ static inline boolean PIT_AttractingRings(mobj_t *thing)
P_SetTarget(&thing->tracer, attractmo);
}
return true; // find other rings
return BMIT_CONTINUE; // find other rings
}
/** Looks for rings near a player in the blockmap.
@ -7579,6 +7573,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
if (player->eggmanexplode <= 0)
{
mobj_t *eggsexplode;
K_KartResetPlayerColor(player);
//player->flashing = 0;
eggsexplode = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_SPBEXPLOSION);
if (player->eggmanblame >= 0
@ -7658,37 +7655,45 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
K_HandleDelayedHitByEm(player);
}
void K_KartPlayerAfterThink(player_t *player)
void K_KartResetPlayerColor(player_t *player)
{
boolean forcereset = false;
boolean fullbright = false;
if (player->playerstate == PST_DEAD || (player->respawn.state == RESPAWNST_MOVE)) // Ensure these are set correctly here
if (!player->mo || P_MobjWasRemoved(player->mo)) // Can't do anything
return;
if (player->mo->health <= 0 || player->playerstate == PST_DEAD || (player->respawn.state == RESPAWNST_MOVE)) // Override everything
{
player->mo->colorized = (player->dye != 0);
player->mo->color = player->dye ? player->dye : player->skincolor;
goto finalise;
}
else if (player->eggmanexplode) // You're gonna diiiiie
if (player->eggmanexplode) // You're gonna diiiiie
{
const INT32 flashtime = 4<<(player->eggmanexplode/TICRATE);
if (player->eggmanexplode == 1 || (player->eggmanexplode % (flashtime/2) != 0))
{
player->mo->colorized = (player->dye != 0);
player->mo->color = player->dye ? player->dye : player->skincolor;
forcereset = true;
}
else if (player->eggmanexplode % flashtime == 0)
{
player->mo->colorized = true;
player->mo->color = SKINCOLOR_BLACK;
fullbright = true;
goto finalise;
}
else
{
player->mo->colorized = true;
player->mo->color = SKINCOLOR_CRIMSON;
fullbright = true;
goto finalise;
}
}
else if (player->invincibilitytimer)
if (player->invincibilitytimer) // You're gonna kiiiiill
{
const tic_t defaultTime = itemtime+(2*TICRATE);
tic_t flicker = 2;
@ -7699,45 +7704,57 @@ void K_KartPlayerAfterThink(player_t *player)
{
player->mo->color = K_RainbowColor(leveltime / 2);
player->mo->colorized = true;
forcereset = false;
}
else
{
player->mo->color = player->skincolor;
player->mo->colorized = false;
flicker += (defaultTime - player->invincibilitytimer) / TICRATE / 2;
forcereset = true;
}
if (leveltime % flicker == 0)
{
player->mo->color = SKINCOLOR_INVINCFLASH;
player->mo->colorized = true;
forcereset = false;
}
if (!forcereset)
{
goto finalise;
}
}
else if (player->growshrinktimer) // Ditto, for grow/shrink
if (player->growshrinktimer) // Ditto, for grow/shrink
{
if (player->growshrinktimer % 5 == 0)
{
player->mo->colorized = true;
player->mo->color = (player->growshrinktimer < 0 ? SKINCOLOR_CREAMSICLE : SKINCOLOR_PERIWINKLE);
fullbright = true;
goto finalise;
}
else
{
player->mo->colorized = (player->dye != 0);
player->mo->color = player->dye ? player->dye : player->skincolor;
}
forcereset = true;
}
else if (player->ringboost && (leveltime & 1)) // ring boosting
if (player->ringboost && (leveltime & 1)) // ring boosting
{
player->mo->colorized = true;
fullbright = true;
goto finalise;
}
else
{
player->mo->colorized = (player->dye != 0);
if (forcereset)
{
player->mo->color = player->dye ? player->dye : player->skincolor;
}
}
finalise:
if (player->curshield)
{
fullbright = true;
@ -7752,6 +7769,11 @@ void K_KartPlayerAfterThink(player_t *player)
if (!(player->mo->state->frame & FF_FULLBRIGHT))
player->mo->frame &= ~FF_FULLBRIGHT;
}
}
void K_KartPlayerAfterThink(player_t *player)
{
K_KartResetPlayerColor(player);
// Move held objects (Bananas, Orbinaut, etc)
K_MoveHeldObjects(player);
@ -8867,6 +8889,8 @@ void K_StripOther(player_t *player)
{
player->eggmanexplode = 0;
player->eggmanblame = -1;
K_KartResetPlayerColor(player);
}
}
@ -10039,7 +10063,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
{
player->itemamount--;
K_DoHyudoroSteal(player); // yes. yes they do.
//K_DoHyudoroSteal(player); // yes. yes they do.
Obj_HyudoroDeploy(player->mo);
K_PlayAttackTaunt(player->mo);
}
break;
case KITEM_POGOSPRING:

View file

@ -61,6 +61,7 @@ void K_SpawnInvincibilitySpeedLines(mobj_t *mo);
void K_SpawnBumpEffect(mobj_t *mo);
void K_KartMoveAnimation(player_t *player);
void K_KartPlayerHUDUpdate(player_t *player);
void K_KartResetPlayerColor(player_t *player);
void K_KartPlayerThink(player_t *player, ticcmd_t *cmd);
void K_KartPlayerAfterThink(player_t *player);
angle_t K_MomentumAngle(mobj_t *mo);

11
src/k_objects.h Normal file
View file

@ -0,0 +1,11 @@
/* object-specific code */
#ifndef k_objects_H
#define k_objects_H
/* Hyudoro */
void Obj_HyudoroDeploy(mobj_t *master);
void Obj_HyudoroThink(mobj_t *actor);
void Obj_HyudoroCenterThink(mobj_t *actor);
void Obj_HyudoroCollide(mobj_t *special, mobj_t *toucher);
#endif/*k_objects_H*/

View file

@ -378,9 +378,6 @@ int LUA_PushGlobals(lua_State *L, const char *word)
} else if (fastcmp(word,"indirectitemcooldown")) {
lua_pushinteger(L, indirectitemcooldown);
return 1;
} else if (fastcmp(word,"hyubgone")) {
lua_pushinteger(L, hyubgone);
return 1;
} else if (fastcmp(word,"thwompsactive")) {
lua_pushboolean(L, thwompsactive);
return 1;
@ -468,8 +465,6 @@ int LUA_WriteGlobals(lua_State *L, const char *word)
exitcountdown = (tic_t)luaL_checkinteger(L, 2);
else if (fastcmp(word,"indirectitemcooldown"))
indirectitemcooldown = (tic_t)luaL_checkinteger(L, 2);
else if (fastcmp(word,"hyubgone"))
hyubgone = (tic_t)luaL_checkinteger(L, 2);
else
return 0;

View file

@ -3119,26 +3119,6 @@ void M_Drawer(void)
M_GetGametypeColor();
currentMenu->drawroutine(); // call current menu Draw routine
}
// Draw version down in corner
// ... but only in the MAIN MENU. I'm a picky bastard.
if (currentMenu == &MainDef)
{
if (customversionstring[0] != '\0')
{
V_DrawThinString(vid.dupx, vid.height - 20*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT, "Mod version:");
V_DrawThinString(vid.dupx, vid.height - 10*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, customversionstring);
}
else
{
#ifdef DEVELOP // Development -- show revision / branch info
V_DrawThinString(vid.dupx, vid.height - 20*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, compbranch);
V_DrawThinString(vid.dupx, vid.height - 10*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, comprevision);
#else // Regular build
V_DrawThinString(vid.dupx, vid.height - 10*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, va("%s", VERSIONSTRING));
#endif
}
}
}
// focus lost notification goes on top of everything, even the former everything

1
src/objects/Sourcefile Normal file
View file

@ -0,0 +1 @@
hyudoro.c

481
src/objects/hyudoro.c Normal file
View file

@ -0,0 +1,481 @@
#include "../doomdef.h"
#include "../doomstat.h"
#include "../info.h"
#include "../k_kart.h"
#include "../k_objects.h"
#include "../m_random.h"
#include "../p_local.h"
#include "../r_main.h"
#include "../s_sound.h"
enum {
HYU_PATROL,
HYU_RETURN,
HYU_HOVER,
};
// TODO: make these general functions
static fixed_t
K_GetSpeed (mobj_t *mobj)
{
return FixedHypot(mobj->momx, mobj->momy);
}
static void
K_ChangePlayerItem
( player_t * player,
INT32 itemtype,
INT32 itemamount)
{
player->itemtype = itemtype;
player->itemamount = itemamount;
K_UnsetItemOut(player);
}
#define hyudoro_mode(o) ((o)->extravalue1)
#define hyudoro_itemtype(o) ((o)->movefactor)
#define hyudoro_itemcount(o) ((o)->movecount)
#define hyudoro_hover_stack(o) ((o)->threshold)
#define hyudoro_next(o) ((o)->tracer)
#define hyudoro_stackpos(o) ((o)->reactiontime)
// cannot be combined
#define hyudoro_center(o) ((o)->target)
#define hyudoro_target(o) ((o)->target)
#define hyudoro_center_max_radius(o) ((o)->threshold)
#define hyudoro_center_master(o) ((o)->target)
static angle_t
trace_angle (mobj_t *hyu)
{
mobj_t *center = hyu->target;
if (hyu->x != center->x || hyu->y != center->y)
{
return R_PointToAngle2(
center->x, center->y, hyu->x, hyu->y);
}
else
return hyu->angle;
}
static angle_t
get_look_angle (mobj_t *thing)
{
player_t *player = thing->player;
return player ? player->angleturn : thing->angle;
}
static boolean
is_hyudoro (mobj_t *thing)
{
return thing && thing->type == MT_HYUDORO;
}
static mobj_t *
get_hyudoro_master (mobj_t *hyu)
{
mobj_t *center = hyudoro_center(hyu);
return center ? hyudoro_center_master(center) : NULL;
}
static player_t *
get_hyudoro_target_player (mobj_t *hyu)
{
mobj_t *target = hyudoro_target(hyu);
return target ? target->player : NULL;
}
static void
sine_bob
( mobj_t * hyu,
angle_t a,
fixed_t sineofs)
{
hyu->sprzoff = FixedMul(hyu->height,
sineofs + FINESINE(a >> ANGLETOFINESHIFT));
}
static void
project_hyudoro (mobj_t *hyu)
{
mobj_t *center = hyudoro_center(hyu);
angle_t angleStep = FixedMul(5 * ANG1,
FixedDiv(hyudoro_center_max_radius(center),
center->radius));
angle_t angle = trace_angle(hyu) + angleStep;
fixed_t d = center->radius;
fixed_t x = P_ReturnThrustX(center, angle, d);
fixed_t y = P_ReturnThrustY(center, angle, d);
hyu->momx = (center->x + x) - hyu->x;
hyu->momy = (center->y + y) - hyu->y;
hyu->angle = angle + ANGLE_90;
sine_bob(hyu, angle, FRACUNIT);
}
static void
project_hyudoro_hover (mobj_t *hyu)
{
const INT32 bob_speed = 64;
mobj_t *target = hyudoro_target(hyu);
// Turns a bit toward its target
angle_t ang = get_look_angle(target) + ANGLE_67h;
fixed_t rad = (target->radius * 2) + hyu->radius;
fixed_t zofs = hyudoro_stackpos(hyu) *
((target->height / 2) + (hyu->height * 2));
P_MoveOrigin(hyu,
target->x - P_ReturnThrustX(hyu, ang, rad),
target->y - P_ReturnThrustY(hyu, ang, rad),
target->z + (zofs * P_MobjFlip(target)));
// Cancel momentum from HYU_RETURN.
// (And anything else! I don't trust this game!!)
hyu->momx = 0;
hyu->momy = 0;
hyu->angle = ang;
// copies sprite tilting
hyu->pitch = target->pitch;
hyu->roll = target->roll;
sine_bob(hyu,
(leveltime & (bob_speed - 1)) *
(ANGLE_MAX / bob_speed), -(3*FRACUNIT/4));
}
static void
spawn_hyudoro_shadow (mobj_t *hyu)
{
mobj_t *shadow = P_SpawnMobjFromMobj(
hyu, 0, 0, 0, MT_SHADOW);
shadow->whiteshadow = true;
shadow->shadowscale = hyu->shadowscale;
hyu->shadowscale = 0;
P_SetTarget(&shadow->tracer, hyu);
}
static void
move_to_player (mobj_t *hyu)
{
mobj_t *target = hyudoro_target(hyu);
angle_t angle;
if (!target)
return;
angle = R_PointToAngle2(
hyu->x, hyu->y, target->x, target->y);
P_InstaThrust(hyu, angle, (hyu->radius / 2) +
max(hyu->radius, K_GetSpeed(target)));
hyu->z = target->z; // stay level with target
hyu->angle = angle;
}
static void
deliver_item (mobj_t *hyu)
{
mobj_t *target = hyudoro_target(hyu);
player_t *player = target->player;
P_SetTarget(&hyudoro_target(hyu), NULL);
if (player)
{
K_ChangePlayerItem(player,
hyudoro_itemtype(hyu),
player->itemamount + hyudoro_itemcount(hyu));
}
S_StartSound(target, sfx_itpick);
// Stop moving here
hyu->momx = 0;
hyu->momy = 0;
hyu->tics = 4;
hyu->destscale = target->scale / 4;
hyu->scalespeed =
abs(hyu->scale - hyu->destscale) / hyu->tics;
}
static void
append_hyudoro
( mobj_t ** head,
mobj_t * hyu)
{
INT32 lastpos = 0;
while (is_hyudoro(*head))
{
lastpos = hyudoro_stackpos(*head);
head = &hyudoro_next(*head);
}
hyudoro_stackpos(hyu) = lastpos + 1;
*head = hyu;
}
static void
pop_hyudoro (mobj_t **head)
{
mobj_t *hyu = *head;
INT32 lastpos;
INT32 thispos;
if (is_hyudoro(hyu))
{
lastpos = hyudoro_stackpos(hyu);
hyu = hyudoro_next(hyu);
while (is_hyudoro(hyu))
{
thispos = hyudoro_stackpos(hyu);
hyudoro_stackpos(hyu) = lastpos;
lastpos = thispos;
hyu = hyudoro_next(hyu);
}
}
*head = hyu;
}
static boolean
hyudoro_patrol_hit_player
( mobj_t * hyu,
mobj_t * toucher)
{
player_t *player = toucher->player;
mobj_t *center = hyudoro_center(hyu);
if (!player)
return false;
// Cannot hit its master
if (toucher == get_hyudoro_master(hyu))
return false;
// Don't punish a punished player
if (player->hyudorotimer)
return false;
// NO ITEM?
if (!player->itemamount)
return false;
K_AddHitLag(toucher, TICRATE/2, true);
hyudoro_mode(hyu) = HYU_RETURN;
hyudoro_itemtype(hyu) = player->itemtype;
hyudoro_itemcount(hyu) = player->itemamount;
K_StripItems(player);
player->hyudorotimer = hyudorotime;
player->stealingtimer = hyudorotime;
P_SetTarget(&hyudoro_target(hyu),
hyudoro_center_master(center));
if (center)
P_RemoveMobj(center);
hyu->renderflags &= ~(RF_DONTDRAW);
return true;
}
static boolean
award_immediately (mobj_t *hyu)
{
player_t *player = get_hyudoro_target_player(hyu);
if (player)
{
if (player->itemamount &&
player->itemtype != hyudoro_itemtype(hyu))
{
return false;
}
// Same as picking up paper items; get stacks
// immediately
if (!P_CanPickupItem(player, 3))
return false;
}
deliver_item(hyu);
return true;
}
static boolean
hyudoro_return_hit_player
( mobj_t * hyu,
mobj_t * toucher)
{
if (toucher != hyudoro_target(hyu))
return false;
// If the player already has an item, just hover beside
// them until they use/lose it.
if (!award_immediately(hyu))
{
hyudoro_mode(hyu) = HYU_HOVER;
append_hyudoro(&toucher->player->hoverhyudoro, hyu);
}
return true;
}
static boolean
hyudoro_hover_await_stack (mobj_t *hyu)
{
player_t *player = get_hyudoro_target_player(hyu);
if (!player)
return false;
// First in stack goes first
if (hyu != player->hoverhyudoro)
return false;
if (!award_immediately(hyu))
return false;
pop_hyudoro(&player->hoverhyudoro);
return true;
}
void
Obj_HyudoroDeploy (mobj_t *master)
{
mobj_t *center = P_SpawnMobjFromMobj(
master, 0, 0, 0, MT_HYUDORO_CENTER);
mobj_t *hyu = P_SpawnMobjFromMobj(
center, 0, 0, 0, MT_HYUDORO);
// This allows a Lua override
if (!hyudoro_center_max_radius(center))
{
hyudoro_center_max_radius(center) =
128 * center->scale;
}
center->radius = hyu->radius;
P_InitAngle(hyu, master->angle);
P_SetTarget(&hyudoro_center(hyu), center);
P_SetTarget(&hyudoro_center_master(center), master);
hyudoro_mode(hyu) = HYU_PATROL;
// Set splitscreen player visibility
if (master->player)
{
hyu->renderflags |= RF_DONTDRAW &
~(K_GetPlayerDontDrawFlag(master->player));
}
spawn_hyudoro_shadow(hyu); // this sucks btw
S_StartSound(master, sfx_s3k92); // scary ghost noise
}
void
Obj_HyudoroThink (mobj_t *hyu)
{
// Might get set from clipping slopes
hyu->momz = 0;
switch (hyudoro_mode(hyu))
{
case HYU_PATROL:
if (hyudoro_center(hyu))
project_hyudoro(hyu);
if (leveltime & 1)
{
mobj_t *ghost = P_SpawnGhostMobj(hyu);
// Flickers every frame
ghost->extravalue1 = 1;
ghost->extravalue2 = 2;
// copy per-splitscreen-player visibility
ghost->renderflags =
(hyu->renderflags & RF_DONTDRAW);
ghost->tics = 8;
P_SetTarget(&ghost->tracer, hyu);
}
break;
case HYU_RETURN:
move_to_player(hyu);
break;
case HYU_HOVER:
if (hyudoro_target(hyu))
{
project_hyudoro_hover(hyu);
hyudoro_hover_await_stack(hyu);
}
break;
}
}
void
Obj_HyudoroCenterThink (mobj_t *center)
{
fixed_t max_radius = hyudoro_center_max_radius(center);
if (center->radius < max_radius)
center->radius += max_radius / 64;
}
void
Obj_HyudoroCollide
( mobj_t * hyu,
mobj_t * toucher)
{
switch (hyudoro_mode(hyu))
{
case HYU_PATROL:
hyudoro_patrol_hit_player(hyu, toucher);
break;
case HYU_RETURN:
hyudoro_return_hit_player(hyu, toucher);
break;
}
}

View file

@ -4573,26 +4573,26 @@ void A_ShootBullet(mobj_t *actor)
static mobj_t *minus;
static boolean PIT_MinusCarry(mobj_t *thing)
static BlockItReturn_t PIT_MinusCarry(mobj_t *thing)
{
if (minus->tracer)
return true;
return BMIT_CONTINUE;
if (minus->type == thing->type)
return true;
return BMIT_CONTINUE;
if (!(thing->flags & (MF_PUSHABLE|MF_ENEMY)))
return true;
return BMIT_CONTINUE;
if (P_AproxDistance(minus->x - thing->x, minus->y - thing->y) >= minus->radius*3)
return true;
return BMIT_CONTINUE;
if (abs(thing->z - minus->z) > minus->height)
return true;
return BMIT_CONTINUE;
P_SetTarget(&minus->tracer, thing);
return true;
return BMIT_CONTINUE;
}
// Function: A_MinusDigging
@ -12145,13 +12145,13 @@ static mobj_t *barrel;
static fixed_t exploderadius;
static fixed_t explodethrust;
static boolean PIT_TNTExplode(mobj_t *nearby)
static BlockItReturn_t PIT_TNTExplode(mobj_t *nearby)
{
fixed_t dx, dy, dz;
fixed_t dm;
if (nearby == barrel)
return true;
return BMIT_CONTINUE;
dx = nearby->x - barrel->x;
dy = nearby->y - barrel->y;
@ -12159,7 +12159,7 @@ static boolean PIT_TNTExplode(mobj_t *nearby)
dm = P_AproxDistance(P_AproxDistance(dx, dy), dz);
if (dm >= exploderadius || !P_CheckSight(barrel, nearby)) // out of range or not visible
return true;
return BMIT_CONTINUE;
if (barrel->type == nearby->type) // nearby is also a barrel
{
@ -12200,7 +12200,7 @@ static boolean PIT_TNTExplode(mobj_t *nearby)
}
}
return true;
return BMIT_CONTINUE;
}
// Function: A_TNTExplode

View file

@ -37,6 +37,7 @@
#include "k_boss.h"
#include "k_respawn.h"
#include "p_spec.h"
#include "k_objects.h"
// CTF player names
#define CTFTEAMCODE(pl) pl->ctfteam ? (pl->ctfteam == 1 ? "\x85" : "\x84") : ""
@ -483,6 +484,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
S_StartSound(toucher, sfx_s1b2);
return;
case MT_HYUDORO:
Obj_HyudoroCollide(special, toucher);
return;
case MT_RING:
case MT_FLINGRING:
if (special->extravalue1)
@ -1767,8 +1772,7 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source,
player->carry = CR_NONE;
player->mo->color = player->skincolor;
player->mo->colorized = false;
K_KartResetPlayerColor(player);
P_ResetPlayer(player);

View file

@ -435,7 +435,7 @@ void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 dama
fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height);
fixed_t P_CeilingzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height);
boolean PIT_PushableMoved(mobj_t *thing);
BlockItReturn_t PIT_PushableMoved(mobj_t *thing);
boolean P_DoSpring(mobj_t *spring, mobj_t *object);

File diff suppressed because it is too large Load diff

View file

@ -1096,7 +1096,7 @@ void P_SetPrecipitationThingPosition(precipmobj_t *thing)
// to P_BlockLinesIterator, then make one or more calls
// to it.
//
boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean (*func)(line_t *))
boolean P_BlockLinesIterator(INT32 x, INT32 y, BlockItReturn_t (*func)(line_t *))
{
INT32 offset;
const INT32 *list; // Big blockmap
@ -1122,11 +1122,22 @@ boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean (*func)(line_t *))
for (i = 0; i < po->numLines; ++i)
{
BlockItReturn_t ret = BMIT_CONTINUE;
if (po->lines[i]->validcount == validcount) // line has been checked
continue;
po->lines[i]->validcount = validcount;
if (!func(po->lines[i]))
ret = func(po->lines[i]);
if (ret == BMIT_ABORT)
{
return false;
}
else if (ret == BMIT_STOP)
{
return true;
}
}
}
plink = (polymaplink_t *)(plink->link.next);
@ -1137,15 +1148,24 @@ boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean (*func)(line_t *))
// First index is really empty, so +1 it.
for (list = blockmaplump + offset + 1; *list != -1; list++)
{
BlockItReturn_t ret = BMIT_CONTINUE;
ld = &lines[*list];
if (ld->validcount == validcount)
continue; // Line has already been checked.
ld->validcount = validcount;
ret = func(ld);
if (!func(ld))
if (ret == BMIT_ABORT)
{
return false;
}
else if (ret == BMIT_STOP)
{
return true;
}
}
return true; // Everything was checked.
}
@ -1154,7 +1174,7 @@ boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean (*func)(line_t *))
//
// P_BlockThingsIterator
//
boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean (*func)(mobj_t *))
boolean P_BlockThingsIterator(INT32 x, INT32 y, BlockItReturn_t (*func)(mobj_t *))
{
mobj_t *mobj, *bnext = NULL;
@ -1164,19 +1184,25 @@ boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean (*func)(mobj_t *))
// Check interaction with the objects in the blockmap.
for (mobj = blocklinks[y*bmapwidth + x]; mobj; mobj = bnext)
{
BlockItReturn_t ret = BMIT_CONTINUE;
P_SetTarget(&bnext, mobj->bnext); // We want to note our reference to bnext here incase it is MF_NOTHINK and gets removed!
if (!func(mobj))
ret = func(mobj);
if (ret == BMIT_ABORT)
{
P_SetTarget(&bnext, NULL);
return false;
return false; // failure
}
if (P_MobjWasRemoved(tmthing) // func just popped our tmthing, cannot continue.
|| (bnext && P_MobjWasRemoved(bnext))) // func just broke blockmap chain, cannot continue.
if ((ret == BMIT_STOP)
|| (bnext && P_MobjWasRemoved(bnext))) // func just broke blockmap chain, cannot continue.
{
P_SetTarget(&bnext, NULL);
return true;
return true; // success
}
}
return true;
}
@ -1220,7 +1246,7 @@ static void P_CheckIntercepts(void)
// are on opposite sides of the trace.
// Returns true if earlyout and a solid line hit.
//
static boolean PIT_AddLineIntercepts(line_t *ld)
static BlockItReturn_t PIT_AddLineIntercepts(line_t *ld)
{
INT32 s1, s2;
fixed_t frac;
@ -1243,18 +1269,18 @@ static boolean PIT_AddLineIntercepts(line_t *ld)
}
if (s1 == s2)
return true; // Line isn't crossed.
return BMIT_CONTINUE; // Line isn't crossed.
// Hit the line.
P_MakeDivline(ld, &dl);
frac = P_InterceptVector(&trace, &dl);
if (frac < 0)
return true; // Behind source.
return BMIT_CONTINUE; // Behind source.
// Try to take an early out of the check.
if (earlyout && frac < FRACUNIT && !ld->backsector)
return false; // stop checking
return BMIT_ABORT; // stop checking
P_CheckIntercepts();
@ -1263,13 +1289,13 @@ static boolean PIT_AddLineIntercepts(line_t *ld)
intercept_p->d.line = ld;
intercept_p++;
return true; // continue
return BMIT_CONTINUE; // continue
}
//
// PIT_AddThingIntercepts
//
static boolean PIT_AddThingIntercepts(mobj_t *thing)
static BlockItReturn_t PIT_AddThingIntercepts(mobj_t *thing)
{
fixed_t px1, py1, px2, py2, frac;
INT32 s1, s2;
@ -1300,7 +1326,7 @@ static boolean PIT_AddThingIntercepts(mobj_t *thing)
s2 = P_PointOnDivlineSide(px2, py2, &trace);
if (s1 == s2)
return true; // Line isn't crossed.
return BMIT_CONTINUE; // Line isn't crossed.
dl.x = px1;
dl.y = py1;
@ -1310,7 +1336,7 @@ static boolean PIT_AddThingIntercepts(mobj_t *thing)
frac = P_InterceptVector(&trace, &dl);
if (frac < 0)
return true; // Behind source.
return BMIT_CONTINUE; // Behind source.
P_CheckIntercepts();
@ -1319,7 +1345,7 @@ static boolean PIT_AddThingIntercepts(mobj_t *thing)
intercept_p->d.thing = thing;
intercept_p++;
return true; // Keep going.
return BMIT_CONTINUE; // Keep going.
}
//

View file

@ -67,8 +67,15 @@ extern INT32 opentoppic, openbottompic;
void P_LineOpening(line_t *plinedef, mobj_t *mobj);
boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean(*func)(line_t *));
boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean(*func)(mobj_t *));
typedef enum
{
BMIT_CONTINUE, // Continue blockmap search
BMIT_STOP, // End blockmap search with success
BMIT_ABORT // End blockmap search with failure
} BlockItReturn_t;
boolean P_BlockLinesIterator(INT32 x, INT32 y, BlockItReturn_t(*func)(line_t *));
boolean P_BlockThingsIterator(INT32 x, INT32 y, BlockItReturn_t(*func)(mobj_t *));
#define PT_ADDLINES 1
#define PT_ADDTHINGS 2

View file

@ -44,6 +44,7 @@
#include "k_bot.h"
#include "k_terrain.h"
#include "k_collide.h"
#include "k_objects.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);
@ -5300,6 +5301,20 @@ static void P_MobjSceneryThink(mobj_t *mobj)
switch (mobj->type)
{
case MT_SHADOW:
if (mobj->tracer)
{
P_MoveOrigin(mobj,
mobj->tracer->x,
mobj->tracer->y,
mobj->tracer->z);
}
else
{
P_RemoveMobj(mobj);
return;
}
break;
case MT_BOSSJUNK:
mobj->renderflags ^= RF_DONTDRAW;
break;
@ -7671,6 +7686,16 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
}
break;
}
case MT_HYUDORO:
{
Obj_HyudoroThink(mobj);
break;
}
case MT_HYUDORO_CENTER:
{
Obj_HyudoroCenterThink(mobj);
break;
}
case MT_ROCKETSNEAKER:
if (!mobj->target || !mobj->target->health)
{
@ -9185,14 +9210,19 @@ void P_MobjThinker(mobj_t *mobj)
{
if (mobj->extravalue2 >= 2)
{
UINT32 dontdraw = RF_DONTDRAW;
if (mobj->tracer)
dontdraw &= ~(mobj->tracer->renderflags);
if (mobj->extravalue2 == 2) // I don't know why the normal logic doesn't work for this.
mobj->renderflags ^= RF_DONTDRAW;
mobj->renderflags ^= dontdraw;
else
{
if (mobj->fuse == mobj->extravalue2)
mobj->renderflags &= ~RF_DONTDRAW;
mobj->renderflags &= ~(dontdraw);
else
mobj->renderflags |= RF_DONTDRAW;
mobj->renderflags |= dontdraw;
}
}
}
@ -9653,6 +9683,7 @@ static void P_DefaultMobjShadowScale(mobj_t *thing)
case MT_SSMINE_SHIELD:
case MT_LANDMINE:
case MT_BALLHOG:
case MT_HYUDORO:
case MT_SINK:
case MT_ROCKETSNEAKER:
case MT_SPB:

View file

@ -63,6 +63,7 @@ typedef enum
FOLLOWER = 0x04,
SKYBOXVIEW = 0x08,
SKYBOXCENTER = 0x10,
HOVERHYUDORO = 0x20,
} player_saveflags;
static inline void P_ArchivePlayer(void)
@ -196,6 +197,9 @@ static void P_NetArchivePlayers(void)
if (players[i].skybox.centerpoint)
flags |= SKYBOXCENTER;
if (players[i].hoverhyudoro)
flags |= HOVERHYUDORO;
WRITEUINT16(save_p, flags);
if (flags & SKYBOXVIEW)
@ -210,6 +214,9 @@ static void P_NetArchivePlayers(void)
if (flags & FOLLOWITEM)
WRITEUINT32(save_p, players[i].followmobj->mobjnum);
if (flags & HOVERHYUDORO)
WRITEUINT32(save_p, players[i].hoverhyudoro->mobjnum);
WRITEUINT32(save_p, (UINT32)players[i].followitem);
WRITEUINT32(save_p, players[i].charflags);
@ -485,6 +492,9 @@ static void P_NetUnArchivePlayers(void)
if (flags & FOLLOWITEM)
players[i].followmobj = (mobj_t *)(size_t)READUINT32(save_p);
if (flags & HOVERHYUDORO)
players[i].hoverhyudoro = (mobj_t *)(size_t)READUINT32(save_p);
players[i].followitem = (mobjtype_t)READUINT32(save_p);
//SetPlayerSkinByNum(i, players[i].skin);
@ -4238,6 +4248,13 @@ static void P_RelinkPointers(void)
CONS_Debug(DBG_GAMELOGIC, "respawn.wp not found on %d\n", mobj->type);
}
}
if (mobj->player->hoverhyudoro)
{
temp = (UINT32)(size_t)mobj->player->hoverhyudoro;
mobj->player->hoverhyudoro = NULL;
if (!P_SetTarget(&mobj->player->hoverhyudoro, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "hoverhyudoro not found on %d\n", mobj->type);
}
}
}
}
@ -4490,7 +4507,6 @@ static void P_NetArchiveMisc(boolean resending)
WRITEUINT32(save_p, wantedcalcdelay);
WRITEUINT32(save_p, indirectitemcooldown);
WRITEUINT32(save_p, hyubgone);
WRITEUINT32(save_p, mapreset);
for (i = 0; i < MAXPLAYERS; i++)
@ -4640,7 +4656,6 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
wantedcalcdelay = READUINT32(save_p);
indirectitemcooldown = READUINT32(save_p);
hyubgone = READUINT32(save_p);
mapreset = READUINT32(save_p);
for (i = 0; i < MAXPLAYERS; i++)

View file

@ -4426,7 +4426,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
wantedcalcdelay = wantedfrequency*2;
indirectitemcooldown = 0;
hyubgone = 0;
mapreset = 0;
for (i = 0; i < MAXPLAYERS; i++)

View file

@ -8395,13 +8395,13 @@ static pusher_t *tmpusher; // pusher structure for blockmap searches
* ::tmpusher won't need to be used.
* \sa T_Pusher
*/
static inline boolean PIT_PushThing(mobj_t *thing)
static inline BlockItReturn_t PIT_PushThing(mobj_t *thing)
{
if (thing->eflags & MFE_PUSHED)
return false;
return BMIT_ABORT;
if (!tmpusher->source)
return false;
return BMIT_ABORT;
// Allow this to affect pushable objects at some point?
if (thing->player && !(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)))
@ -8421,7 +8421,7 @@ static inline boolean PIT_PushThing(mobj_t *thing)
{
// Make sure the Z is in range
if (thing->z < sz - tmpusher->radius || thing->z > sz + tmpusher->radius)
return false;
return BMIT_ABORT;
dist = P_AproxDistance(P_AproxDistance(thing->x - sx, thing->y - sy),
thing->z - sz);
@ -8487,7 +8487,7 @@ static inline boolean PIT_PushThing(mobj_t *thing)
if (tmpusher->exclusive)
thing->eflags |= MFE_PUSHED;
return true;
return BMIT_CONTINUE;
}
/** Applies a pusher to all affected objects.

View file

@ -685,8 +685,6 @@ void P_Ticker(boolean run)
if (indirectitemcooldown > 0)
indirectitemcooldown--;
if (hyubgone > 0)
hyubgone--;
K_BossInfoTicker();

View file

@ -1692,8 +1692,7 @@ static void P_CheckInvincibilityTimer(player_t *player)
// Resume normal music stuff.
if (player->invincibilitytimer == 1)
{
player->mo->color = player->skincolor;
player->mo->colorized = false;
//K_KartResetPlayerColor(player); -- this gets called every tic anyways
G_GhostAddColor((INT32) (player - players), GHC_NORMAL);
P_RestoreMusic(player);
@ -2680,8 +2679,7 @@ static void P_DeathThink(player_t *player)
if (!player->mo)
return;
player->mo->colorized = false;
player->mo->color = player->skincolor;
//K_KartResetPlayerColor(player); -- called at death, don't think we need to re-establish
P_CalcHeight(player);
}

View file

@ -27,6 +27,9 @@
#include "p_local.h"
#include "dehacked.h" // get_number (for thok)
#include "m_cond.h"
#if 0
#include "k_kart.h" // K_KartResetPlayerColor
#endif
#ifdef HWRENDER
#include "hardware/hw_md2.h"
#endif
@ -280,7 +283,7 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
{
player_t *player = &players[playernum];
skin_t *skin = &skins[skinnum];
UINT16 newcolor = 0;
//UINT16 newcolor = 0;
//UINT8 i;
if (skinnum >= 0 && skinnum < numskins && R_SkinUsable(playernum, skinnum)) // Make sure it exists!
@ -306,6 +309,7 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
}
player->skincolor = newcolor = skin->prefcolor;
K_KartResetPlayerColor(player);
}
#endif
@ -318,12 +322,6 @@ void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum)
if (player->mo)
{
player->mo->skin = skin;
if (newcolor)
{
player->mo->color = newcolor;
}
P_SetScale(player->mo, player->mo->scale);
P_SetPlayerMobjState(player->mo, player->mo->state-states); // Prevent visual errors when switching between skins with differing number of frames
}