2014-03-15 16:59:03 +00:00
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 1993-1996 by id Software, Inc.
// Copyright (C) 1998-2000 by DooM Legacy Team.
2018-11-25 12:35:38 +00:00
// Copyright (C) 1999-2018 by Sonic Team Junior.
2014-03-15 16:59:03 +00:00
//
// 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 p_inter.c
/// \brief Handling interactions (i.e., collisions)
# include "doomdef.h"
# include "i_system.h"
# include "am_map.h"
# include "g_game.h"
# include "m_random.h"
# include "p_local.h"
# include "s_sound.h"
# include "r_main.h"
# include "st_stuff.h"
# include "hu_stuff.h"
# include "lua_hook.h"
# include "m_cond.h" // unlockables, emblems, etc
# include "m_cheat.h" // objectplace
# include "m_misc.h"
# include "v_video.h" // video flags for CEchos
2016-08-15 03:51:08 +00:00
# include "k_kart.h" // SRB2kart
2014-03-15 16:59:03 +00:00
2016-07-06 04:09:17 +00:00
// CTF player names
# define CTFTEAMCODE(pl) pl->ctfteam ? (pl->ctfteam == 1 ? "\x85" : "\x84") : ""
# define CTFTEAMENDCODE(pl) pl->ctfteam ? "\x80" : ""
2016-04-07 02:55:58 +00:00
// CTF player names
# define CTFTEAMCODE(pl) pl->ctfteam ? (pl->ctfteam == 1 ? "\x85" : "\x84") : ""
# define CTFTEAMENDCODE(pl) pl->ctfteam ? "\x80" : ""
2014-03-15 16:59:03 +00:00
void P_ForceFeed ( const player_t * player , INT32 attack , INT32 fade , tic_t duration , INT32 period )
{
BasicFF_t Basicfeed ;
if ( ! player )
return ;
Basicfeed . Duration = ( UINT32 ) ( duration * ( 100L / TICRATE ) ) ;
Basicfeed . ForceX = Basicfeed . ForceY = 1 ;
Basicfeed . Gain = 25000 ;
Basicfeed . Magnitude = period * 10 ;
Basicfeed . player = player ;
/// \todo test FFB
P_RampConstant ( & Basicfeed , attack , fade ) ;
}
void P_ForceConstant ( const BasicFF_t * FFInfo )
{
JoyFF_t ConstantQuake ;
if ( ! FFInfo | | ! FFInfo - > player )
return ;
ConstantQuake . ForceX = FFInfo - > ForceX ;
ConstantQuake . ForceY = FFInfo - > ForceY ;
ConstantQuake . Duration = FFInfo - > Duration ;
ConstantQuake . Gain = FFInfo - > Gain ;
ConstantQuake . Magnitude = FFInfo - > Magnitude ;
if ( FFInfo - > player = = & players [ consoleplayer ] )
I_Tactile ( ConstantForce , & ConstantQuake ) ;
2019-04-18 07:08:11 +00:00
else if ( splitscreen & & FFInfo - > player = = & players [ displayplayers [ 1 ] ] )
2014-03-15 16:59:03 +00:00
I_Tactile2 ( ConstantForce , & ConstantQuake ) ;
2019-04-18 07:08:11 +00:00
else if ( splitscreen > 1 & & FFInfo - > player = = & players [ displayplayers [ 2 ] ] )
2017-12-17 06:21:24 +00:00
I_Tactile3 ( ConstantForce , & ConstantQuake ) ;
2019-04-18 07:08:11 +00:00
else if ( splitscreen > 2 & & FFInfo - > player = = & players [ displayplayers [ 3 ] ] )
2017-12-17 06:21:24 +00:00
I_Tactile4 ( ConstantForce , & ConstantQuake ) ;
2014-03-15 16:59:03 +00:00
}
void P_RampConstant ( const BasicFF_t * FFInfo , INT32 Start , INT32 End )
{
JoyFF_t RampQuake ;
if ( ! FFInfo | | ! FFInfo - > player )
return ;
RampQuake . ForceX = FFInfo - > ForceX ;
RampQuake . ForceY = FFInfo - > ForceY ;
RampQuake . Duration = FFInfo - > Duration ;
RampQuake . Gain = FFInfo - > Gain ;
RampQuake . Magnitude = FFInfo - > Magnitude ;
RampQuake . Start = Start ;
RampQuake . End = End ;
if ( FFInfo - > player = = & players [ consoleplayer ] )
I_Tactile ( ConstantForce , & RampQuake ) ;
2019-04-18 07:08:11 +00:00
else if ( splitscreen & & FFInfo - > player = = & players [ displayplayers [ 1 ] ] )
2014-03-15 16:59:03 +00:00
I_Tactile2 ( ConstantForce , & RampQuake ) ;
2019-04-18 07:08:11 +00:00
else if ( splitscreen > 1 & & FFInfo - > player = = & players [ displayplayers [ 2 ] ] )
2017-12-17 06:21:24 +00:00
I_Tactile3 ( ConstantForce , & RampQuake ) ;
2019-04-18 07:08:11 +00:00
else if ( splitscreen > 2 & & FFInfo - > player = = & players [ displayplayers [ 3 ] ] )
2017-12-17 06:21:24 +00:00
I_Tactile4 ( ConstantForce , & RampQuake ) ;
2014-03-15 16:59:03 +00:00
}
//
// GET STUFF
//
//
// P_CanPickupItem
//
// Returns true if the player is in a state where they can pick up items.
//
2018-08-12 00:19:09 +00:00
boolean P_CanPickupItem ( player_t * player , UINT8 weapon )
2014-03-15 16:59:03 +00:00
{
2018-07-22 04:31:02 +00:00
if ( player - > exiting | | mapreset )
2018-06-08 05:12:07 +00:00
return false ;
2018-08-12 15:17:30 +00:00
/*if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) // No bumpers in Match
return false ; */
2014-03-15 16:59:03 +00:00
2018-03-30 04:53:25 +00:00
if ( weapon )
{
2018-08-12 14:22:28 +00:00
// Item slot already taken up
if ( weapon = = 2 )
{
// Invulnerable
if ( player - > powers [ pw_flashing ] > 0
| | player - > kartstuff [ k_spinouttimer ] > 0
| | player - > kartstuff [ k_squishedtimer ] > 0
| | player - > kartstuff [ k_invincibilitytimer ] > 0
| | player - > kartstuff [ k_growshrinktimer ] > 0
| | player - > kartstuff [ k_hyudorotimer ] > 0 )
return false ;
// Already have fake
if ( player - > kartstuff [ k_roulettetype ] = = 2
| | player - > kartstuff [ k_eggmanexplode ] )
return false ;
}
else
{
// Item-specific timer going off
2018-12-06 04:28:44 +00:00
if ( player - > kartstuff [ k_stealingtimer ] | | player - > kartstuff [ k_stolentimer ]
| | player - > kartstuff [ k_growshrinktimer ] > 0 | | player - > kartstuff [ k_rocketsneakertimer ]
2018-08-12 14:22:28 +00:00
| | player - > kartstuff [ k_eggmanexplode ] )
return false ;
// Item slot already taken up
if ( player - > kartstuff [ k_itemroulette ]
Dropping items!
* Shield Drop...
* Whatever you've got orbiting or trailing you, DROP THEM WHERE THEY STAND. (Except for the ghost sink. That one's OK.)
* Pops your Thunder Shield.
* Happens upon ANY hit, except for deathpits.
* HUD Drop...
* Also does the above, except for the Thunder Shield thing.
* If there's any item left in your item box, pop it out as a little hovering, rotating Minecraft item!
* You can pick up the Minecraft item by driving over it if your item box is sufficiently empty, or the item which is contained within it is of the same type.
* Happens upon Size Down and battle elimination.
* Can also be forced on with `cv_kartdebughuddrop on`!
* Some other random stuff.
* Fix a bunch of `a->scale = b`'s into `P_SetScale(a, b)` form, for maximum validity.
* Make K_CleanHnextList and K_UpdateHnextList one function, since they only differed by one continue clause (and the type of their input parameter).
* Allow shrunken players to pick up item boxes again.
* Fix MF_NOCLIPTHING. (Gonna pass this fix to vanilla when I get the chance, too.)
* Break NiGHTS a little through my machinations.
2018-09-06 21:17:29 +00:00
| | ( weapon ! = 3 & & player - > kartstuff [ k_itemamount ] )
2018-11-14 21:53:57 +00:00
| | player - > kartstuff [ k_itemheld ] )
2018-08-12 14:22:28 +00:00
return false ;
2019-03-09 23:28:05 +00:00
2019-03-10 02:23:49 +00:00
if ( weapon = = 3 & & player - > kartstuff [ k_itemtype ] = = KITEM_THUNDERSHIELD )
2019-03-09 23:28:05 +00:00
return false ; // No stacking thunder shields!
2018-08-12 14:22:28 +00:00
}
2018-03-30 04:53:25 +00:00
}
2017-10-22 21:26:43 +00:00
2014-03-15 16:59:03 +00:00
return true ;
}
//
// P_DoNightsScore
//
// When you pick up some items in nights, it displays
// a score sign, and awards you some drill time.
//
void P_DoNightsScore ( player_t * player )
{
mobj_t * dummymo ;
if ( player - > exiting )
return ; // Don't do any fancy shit for failures.
dummymo = P_SpawnMobj ( player - > mo - > x , player - > mo - > y , player - > mo - > z + player - > mo - > height / 2 , MT_NIGHTSCORE ) ;
if ( player - > bot )
player = & players [ consoleplayer ] ;
if ( G_IsSpecialStage ( gamemap ) ) // Global link count? Maybe not a good idea...
{
INT32 i ;
for ( i = 0 ; i < MAXPLAYERS ; i + + )
if ( playeringame [ i ] )
{
if ( + + players [ i ] . linkcount > players [ i ] . maxlink )
players [ i ] . maxlink = players [ i ] . linkcount ;
players [ i ] . linktimer = 2 * TICRATE ;
}
}
else // Individual link counts
{
if ( + + player - > linkcount > player - > maxlink )
player - > maxlink = player - > linkcount ;
player - > linktimer = 2 * TICRATE ;
}
if ( player - > linkcount < 10 )
{
if ( player - > bonustime )
{
P_AddPlayerScore ( player , player - > linkcount * 20 ) ;
P_SetMobjState ( dummymo , dummymo - > info - > xdeathstate + player - > linkcount - 1 ) ;
}
else
{
P_AddPlayerScore ( player , player - > linkcount * 10 ) ;
P_SetMobjState ( dummymo , dummymo - > info - > spawnstate + player - > linkcount - 1 ) ;
}
}
else
{
if ( player - > bonustime )
{
P_AddPlayerScore ( player , 200 ) ;
P_SetMobjState ( dummymo , dummymo - > info - > xdeathstate + 9 ) ;
}
else
{
P_AddPlayerScore ( player , 100 ) ;
P_SetMobjState ( dummymo , dummymo - > info - > spawnstate + 9 ) ;
}
}
// Hoops are the only things that should add to your drill meter
//player->drillmeter += TICRATE;
dummymo - > momz = FRACUNIT ;
dummymo - > fuse = 3 * TICRATE ;
// What?! NO, don't use the camera! Scale up instead!
2019-04-18 07:08:11 +00:00
//P_InstaThrust(dummymo, R_PointToAngle2(dummymo->x, dummymo->y, camera[0].x, camera[0].y), 3*FRACUNIT);
2014-03-15 16:59:03 +00:00
dummymo - > scalespeed = FRACUNIT / 25 ;
dummymo - > destscale = 2 * FRACUNIT ;
}
/** Takes action based on a ::MF_SPECIAL thing touched by a player.
* Actually , this just checks a few things ( heights , toucher - > player , no
* objectplace , no dead or disappearing things )
*
* The special thing may be collected and disappear , or a sound may play , or
* both .
*
* \ param special The special thing .
* \ param toucher The player ' s mobj .
* \ param heightcheck Whether or not to make sure the player and the object
* are actually touching .
*/
void P_TouchSpecialThing ( mobj_t * special , mobj_t * toucher , boolean heightcheck )
{
player_t * player ;
INT32 i ;
if ( objectplacing )
return ;
I_Assert ( special ! = NULL ) ;
I_Assert ( toucher ! = NULL ) ;
// Dead thing touching.
// Can happen with a sliding player corpse.
if ( toucher - > health < = 0 )
return ;
if ( heightcheck )
{
Nuke a bunch of iteration things that have no purpose in SRB2Kart. A full explanation of my reasoning and what it affects is as follows.
p_inter.c -
Everything to do with setting states for starposts
In SRB2Kart, starposts are invisble. We don't need to loop through all thinkers just to set their states when there's no visible effect of the state-setting. In addition, it has no consequences for gameplay - starposts have long been silent here, and all checking is done regarding their health, not their state.
Remove extremely low-traffic conditionals (MT_FLINGEMERALD collision height extension, for example)
These objects serve no functional purpose during regular SRB2Kart gameplay. Why should every other object have to pay an admittedly minor performance hit just for them?
Disable all mechanisms of damaging bosses or enemies with the player's physical contact
With the exception of Sapphire Coast, no MF_ENEMY objects exist in the entirety of the standard roster. In addition, the conditions for damaging the enemies were impossible to achieve, because they required vanilla SRB2 mechanics such as "jumping", "spindashing", or "super". Therefore, they can be safely commented out.
Disable NiGHTS-related material (excepting bumper, hoop, and wing-emblem objects)
NiGHTS is fundamentally incompatible with regular kart gameplay and I believe was already broken. Therefore, any mechanism which enters, aids, or abets it can be safely disabled.
Comment out Tag mechanisms
Tag is the only vanilla multiplayer gametype which has sufficient gameplay depth and complexity (HEYOOOOOOOOO) to require dedicated thinking in and of itself in order to manage. This thinking is irrelevant to Kart's functioning, and can be neutered easily.
d_clisrv.c
Comment out Tag mechanisms
See p_inter.c
d_netcmd.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
When investigating for references to NiGHTS material, I discovered that these remained untouched. In order to present a more coherent game, I have hidden the ones that serve no purpose for us.
Comment out Tag mechanisms
See p_inter.c
g_game.c
Disable NiGHTS-related material
See p_inter.c
Disable some team-related material
Teams are not present in SRB2Kart at present. Obviously we'd want to reconsider for future, but it doesn't need to be run right now.
Everything to do with setting states for starposts
See p_inter.c
m_cheat.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
See d_netcmd.c
p_map.c
Remove extremely low-traffic conditionals (MT_EGGSHIELD collision, for example)
See p_inter.c
Disable NiGHTS-related material
See p_inter.c
p_mobj.c
Disable P_EmeraldManager
Power stones, despite their relevance in vanilla Match, are not in SRB2Kart's Battle. No management of nonexistent emeralds is required.
p_setup.c
Everything to do with setting states for starposts
See p_inter.c
p_spec.c
Disable NiGHTS-related material
See p_inter.c
Everything to do with setting states for starposts
See p_inter.c
p_telept.c
Everything to do with setting states for starposts
See p_inter.c
p_tick.c
Disable some team-related material
See g_game.c
Disable P_EmeraldManager
See p_mobj.c
Do not run shields
Shield objects are not run under the vanilla system; the Thunder Shield is a domain-specific recreation using a standard mobjthinker.
Do not run special stages
SRB2Kart does not have special stages.
Comment out Tag mechanisms
See p_inter.c
y_inter.c
Disable some team-related material
See g_game.c
p_user.c
Disable NiGHTS-related material
See p_inter.c
Disable 2d movement for players
2D mode? In a kart racer? :nick:
2018-10-03 16:04:41 +00:00
/*if (special->type == MT_FLINGEMERALD) // little hack here...
2014-03-15 16:59:03 +00:00
{ // flingemerald sprites are low to the ground, so extend collision radius down some.
if ( toucher - > z > ( special - > z + special - > height ) )
return ;
if ( special - > z - special - > height > ( toucher - > z + toucher - > height ) )
return ;
}
Nuke a bunch of iteration things that have no purpose in SRB2Kart. A full explanation of my reasoning and what it affects is as follows.
p_inter.c -
Everything to do with setting states for starposts
In SRB2Kart, starposts are invisble. We don't need to loop through all thinkers just to set their states when there's no visible effect of the state-setting. In addition, it has no consequences for gameplay - starposts have long been silent here, and all checking is done regarding their health, not their state.
Remove extremely low-traffic conditionals (MT_FLINGEMERALD collision height extension, for example)
These objects serve no functional purpose during regular SRB2Kart gameplay. Why should every other object have to pay an admittedly minor performance hit just for them?
Disable all mechanisms of damaging bosses or enemies with the player's physical contact
With the exception of Sapphire Coast, no MF_ENEMY objects exist in the entirety of the standard roster. In addition, the conditions for damaging the enemies were impossible to achieve, because they required vanilla SRB2 mechanics such as "jumping", "spindashing", or "super". Therefore, they can be safely commented out.
Disable NiGHTS-related material (excepting bumper, hoop, and wing-emblem objects)
NiGHTS is fundamentally incompatible with regular kart gameplay and I believe was already broken. Therefore, any mechanism which enters, aids, or abets it can be safely disabled.
Comment out Tag mechanisms
Tag is the only vanilla multiplayer gametype which has sufficient gameplay depth and complexity (HEYOOOOOOOOO) to require dedicated thinking in and of itself in order to manage. This thinking is irrelevant to Kart's functioning, and can be neutered easily.
d_clisrv.c
Comment out Tag mechanisms
See p_inter.c
d_netcmd.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
When investigating for references to NiGHTS material, I discovered that these remained untouched. In order to present a more coherent game, I have hidden the ones that serve no purpose for us.
Comment out Tag mechanisms
See p_inter.c
g_game.c
Disable NiGHTS-related material
See p_inter.c
Disable some team-related material
Teams are not present in SRB2Kart at present. Obviously we'd want to reconsider for future, but it doesn't need to be run right now.
Everything to do with setting states for starposts
See p_inter.c
m_cheat.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
See d_netcmd.c
p_map.c
Remove extremely low-traffic conditionals (MT_EGGSHIELD collision, for example)
See p_inter.c
Disable NiGHTS-related material
See p_inter.c
p_mobj.c
Disable P_EmeraldManager
Power stones, despite their relevance in vanilla Match, are not in SRB2Kart's Battle. No management of nonexistent emeralds is required.
p_setup.c
Everything to do with setting states for starposts
See p_inter.c
p_spec.c
Disable NiGHTS-related material
See p_inter.c
Everything to do with setting states for starposts
See p_inter.c
p_telept.c
Everything to do with setting states for starposts
See p_inter.c
p_tick.c
Disable some team-related material
See g_game.c
Disable P_EmeraldManager
See p_mobj.c
Do not run shields
Shield objects are not run under the vanilla system; the Thunder Shield is a domain-specific recreation using a standard mobjthinker.
Do not run special stages
SRB2Kart does not have special stages.
Comment out Tag mechanisms
See p_inter.c
y_inter.c
Disable some team-related material
See g_game.c
p_user.c
Disable NiGHTS-related material
See p_inter.c
Disable 2d movement for players
2D mode? In a kart racer? :nick:
2018-10-03 16:04:41 +00:00
else */
2014-03-15 16:59:03 +00:00
{
if ( toucher - > momz < 0 ) {
if ( toucher - > z + toucher - > momz > special - > z + special - > height )
return ;
} else if ( toucher - > z > special - > z + special - > height )
return ;
if ( toucher - > momz > 0 ) {
if ( toucher - > z + toucher - > height + toucher - > momz < special - > z )
return ;
} else if ( toucher - > z + toucher - > height < special - > z )
return ;
}
}
if ( special - > health < = 0 )
return ;
player = toucher - > player ;
I_Assert ( player ! = NULL ) ; // Only players can touch stuff!
if ( player - > spectator )
return ;
// Ignore eggman in "ouchie" mode
if ( special - > flags & MF_BOSS & & special - > flags2 & MF2_FRET )
return ;
# ifdef HAVE_BLUA
if ( LUAh_TouchSpecial ( special , toucher ) | | P_MobjWasRemoved ( special ) )
return ;
# endif
if ( special - > flags & MF_BOSS )
{
Nuke a bunch of iteration things that have no purpose in SRB2Kart. A full explanation of my reasoning and what it affects is as follows.
p_inter.c -
Everything to do with setting states for starposts
In SRB2Kart, starposts are invisble. We don't need to loop through all thinkers just to set their states when there's no visible effect of the state-setting. In addition, it has no consequences for gameplay - starposts have long been silent here, and all checking is done regarding their health, not their state.
Remove extremely low-traffic conditionals (MT_FLINGEMERALD collision height extension, for example)
These objects serve no functional purpose during regular SRB2Kart gameplay. Why should every other object have to pay an admittedly minor performance hit just for them?
Disable all mechanisms of damaging bosses or enemies with the player's physical contact
With the exception of Sapphire Coast, no MF_ENEMY objects exist in the entirety of the standard roster. In addition, the conditions for damaging the enemies were impossible to achieve, because they required vanilla SRB2 mechanics such as "jumping", "spindashing", or "super". Therefore, they can be safely commented out.
Disable NiGHTS-related material (excepting bumper, hoop, and wing-emblem objects)
NiGHTS is fundamentally incompatible with regular kart gameplay and I believe was already broken. Therefore, any mechanism which enters, aids, or abets it can be safely disabled.
Comment out Tag mechanisms
Tag is the only vanilla multiplayer gametype which has sufficient gameplay depth and complexity (HEYOOOOOOOOO) to require dedicated thinking in and of itself in order to manage. This thinking is irrelevant to Kart's functioning, and can be neutered easily.
d_clisrv.c
Comment out Tag mechanisms
See p_inter.c
d_netcmd.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
When investigating for references to NiGHTS material, I discovered that these remained untouched. In order to present a more coherent game, I have hidden the ones that serve no purpose for us.
Comment out Tag mechanisms
See p_inter.c
g_game.c
Disable NiGHTS-related material
See p_inter.c
Disable some team-related material
Teams are not present in SRB2Kart at present. Obviously we'd want to reconsider for future, but it doesn't need to be run right now.
Everything to do with setting states for starposts
See p_inter.c
m_cheat.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
See d_netcmd.c
p_map.c
Remove extremely low-traffic conditionals (MT_EGGSHIELD collision, for example)
See p_inter.c
Disable NiGHTS-related material
See p_inter.c
p_mobj.c
Disable P_EmeraldManager
Power stones, despite their relevance in vanilla Match, are not in SRB2Kart's Battle. No management of nonexistent emeralds is required.
p_setup.c
Everything to do with setting states for starposts
See p_inter.c
p_spec.c
Disable NiGHTS-related material
See p_inter.c
Everything to do with setting states for starposts
See p_inter.c
p_telept.c
Everything to do with setting states for starposts
See p_inter.c
p_tick.c
Disable some team-related material
See g_game.c
Disable P_EmeraldManager
See p_mobj.c
Do not run shields
Shield objects are not run under the vanilla system; the Thunder Shield is a domain-specific recreation using a standard mobjthinker.
Do not run special stages
SRB2Kart does not have special stages.
Comment out Tag mechanisms
See p_inter.c
y_inter.c
Disable some team-related material
See g_game.c
p_user.c
Disable NiGHTS-related material
See p_inter.c
Disable 2d movement for players
2D mode? In a kart racer? :nick:
2018-10-03 16:04:41 +00:00
/*if (special->type == MT_BLACKEGGMAN)
2014-03-15 16:59:03 +00:00
{
P_DamageMobj ( toucher , special , special , 1 ) ; // ouch
return ;
}
2014-08-04 03:49:33 +00:00
if ( ( ( player - > pflags & PF_NIGHTSMODE ) & & ( player - > pflags & PF_DRILLING ) )
| | ( player - > pflags & ( PF_JUMPED | PF_SPINNING | PF_GLIDING ) )
| | player - > powers [ pw_invulnerability ] | | player - > powers [ pw_super ] ) // Do you possess the ability to subdue the object?
2014-03-15 16:59:03 +00:00
{
if ( P_MobjFlip ( toucher ) * toucher - > momz < 0 )
toucher - > momz = - toucher - > momz ;
toucher - > momx = - toucher - > momx ;
toucher - > momy = - toucher - > momy ;
P_DamageMobj ( special , toucher , toucher , 1 ) ;
}
else if ( ( ( toucher - > z < special - > z & & ! ( toucher - > eflags & MFE_VERTICALFLIP ) )
| | ( toucher - > z + toucher - > height > special - > z + special - > height & & ( toucher - > eflags & MFE_VERTICALFLIP ) ) )
2014-08-04 03:49:33 +00:00
& & player - > charability = = CA_FLY
& & ( player - > powers [ pw_tailsfly ]
2014-03-15 16:59:03 +00:00
| | ( toucher - > state > = & states [ S_PLAY_SPC1 ] & & toucher - > state < = & states [ S_PLAY_SPC4 ] ) ) ) // Tails can shred stuff with his propeller.
{
toucher - > momz = - toucher - > momz / 2 ;
P_DamageMobj ( special , toucher , toucher , 1 ) ;
}
Nuke a bunch of iteration things that have no purpose in SRB2Kart. A full explanation of my reasoning and what it affects is as follows.
p_inter.c -
Everything to do with setting states for starposts
In SRB2Kart, starposts are invisble. We don't need to loop through all thinkers just to set their states when there's no visible effect of the state-setting. In addition, it has no consequences for gameplay - starposts have long been silent here, and all checking is done regarding their health, not their state.
Remove extremely low-traffic conditionals (MT_FLINGEMERALD collision height extension, for example)
These objects serve no functional purpose during regular SRB2Kart gameplay. Why should every other object have to pay an admittedly minor performance hit just for them?
Disable all mechanisms of damaging bosses or enemies with the player's physical contact
With the exception of Sapphire Coast, no MF_ENEMY objects exist in the entirety of the standard roster. In addition, the conditions for damaging the enemies were impossible to achieve, because they required vanilla SRB2 mechanics such as "jumping", "spindashing", or "super". Therefore, they can be safely commented out.
Disable NiGHTS-related material (excepting bumper, hoop, and wing-emblem objects)
NiGHTS is fundamentally incompatible with regular kart gameplay and I believe was already broken. Therefore, any mechanism which enters, aids, or abets it can be safely disabled.
Comment out Tag mechanisms
Tag is the only vanilla multiplayer gametype which has sufficient gameplay depth and complexity (HEYOOOOOOOOO) to require dedicated thinking in and of itself in order to manage. This thinking is irrelevant to Kart's functioning, and can be neutered easily.
d_clisrv.c
Comment out Tag mechanisms
See p_inter.c
d_netcmd.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
When investigating for references to NiGHTS material, I discovered that these remained untouched. In order to present a more coherent game, I have hidden the ones that serve no purpose for us.
Comment out Tag mechanisms
See p_inter.c
g_game.c
Disable NiGHTS-related material
See p_inter.c
Disable some team-related material
Teams are not present in SRB2Kart at present. Obviously we'd want to reconsider for future, but it doesn't need to be run right now.
Everything to do with setting states for starposts
See p_inter.c
m_cheat.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
See d_netcmd.c
p_map.c
Remove extremely low-traffic conditionals (MT_EGGSHIELD collision, for example)
See p_inter.c
Disable NiGHTS-related material
See p_inter.c
p_mobj.c
Disable P_EmeraldManager
Power stones, despite their relevance in vanilla Match, are not in SRB2Kart's Battle. No management of nonexistent emeralds is required.
p_setup.c
Everything to do with setting states for starposts
See p_inter.c
p_spec.c
Disable NiGHTS-related material
See p_inter.c
Everything to do with setting states for starposts
See p_inter.c
p_telept.c
Everything to do with setting states for starposts
See p_inter.c
p_tick.c
Disable some team-related material
See g_game.c
Disable P_EmeraldManager
See p_mobj.c
Do not run shields
Shield objects are not run under the vanilla system; the Thunder Shield is a domain-specific recreation using a standard mobjthinker.
Do not run special stages
SRB2Kart does not have special stages.
Comment out Tag mechanisms
See p_inter.c
y_inter.c
Disable some team-related material
See g_game.c
p_user.c
Disable NiGHTS-related material
See p_inter.c
Disable 2d movement for players
2D mode? In a kart racer? :nick:
2018-10-03 16:04:41 +00:00
// SRB2kart - Removed: No more fly states
else */
2014-03-15 16:59:03 +00:00
P_DamageMobj ( toucher , special , special , 1 ) ;
return ;
}
2018-10-29 09:00:08 +00:00
else if ( ( special - > flags & MF_ENEMY ) & & ! ( special - > flags & MF_MISSILE )
& & ( special - > type ! = MT_SPRINGSHELL ) ) // Kart: prevent random hits from these things
{
P_DamageMobj ( toucher , special , special , 1 ) ;
2014-03-15 16:59:03 +00:00
return ;
}
else if ( special - > flags & MF_FIRE )
{
P_DamageMobj ( toucher , special , special , 1 ) ;
return ;
}
else
{
// We now identify by object type, not sprite! Tails 04-11-2001
switch ( special - > type )
{
2018-10-20 19:17:13 +00:00
case MT_MEMENTOSTP : // Mementos teleport
// Teleport player to the other teleporter (special->target). We'll assume there's always only ever 2.
if ( ! special - > target )
return ; // foolproof crash prevention check!!!!!
2018-11-14 21:53:57 +00:00
Implement Uncapped (squashed)
Co-Authored-By: Sally Coolatta <tehrealsalt@gmail.com>
Co-Authored-By: James R <justsomejames2@gmail.com>
Co-Authored-By: Monster Iestyn <iestynjealous@ntlworld.com>
Co-Authored-By: katsy <katmint@live.com>
Place Frame Interpolation in "Experimental" video options header
This seems like an appropriate way to describe the feature for now.
Add smooth level platter under interpolation, `renderdeltatics`
`renderdeltatics` can be used as a standard delta time in any place,
allowing for smooth menus. It will always be equal to `realtics`
when frame interpolation is turned off, producing consistent
framerate behavior everywhere it is used.
Add smooth rendering to save select screen
Add smooth rendering to Record/NiGHTS Attack, F_SkyScroll
Ensure viewsector is accurate to viewx/viewy
This fixes a potential crash in OpenGL when changing between levels.
Ensure + commands get executed before map start
Always have precise_t defined
Fix misc dropshadow issues
Reset view interpolation on level load
Remove unnecessary precipmobj thinker hack
Add reset interpolation state functions
Reset precip interpolation on snap to ceil
Reset mobj interp state on TeleportMove
Only swap view interp state if a tick is run
Run anti-lag chasecam at tic frequency
Fixes jittery and unstable chasecam in high latency netgames
Homogenize mobj interpolations
Add sector plane level interpolations
Add SectorScroll interpolator
Add SideScroll interpolator
Add Polyobj interpolator
Intialize interpolator list at a better time
Delete interpolators associated with thinkers
Interpolate mobj angles and player drawangle
Interpolate HWR_DrawModel
Add functions to handle interpolation
Much less code duplication
P_InitAngle, to fix angle interpolation on spawning objects
Fully fix drop shadows
It used the thing's floorz / ceilingz directly -- that wouldn't account for interpolated coordinates.
Do not speed up underwater/heatwave effect in OpenGL
Closer OpenGL underwater/heatwave effect to Software
Interpolate from time of previous tic
Previously interpolated from last 35th of a second, which
may be offset from game time due to connection lag.
Consider this the proper fix to 54148a0dd0 too.
Calculate FPS stuff even if frame is skipped
I decided ultimately to actually keep the frame skip optimization disabled, because I think it is actually a little bit helpful that you can still get accurate rendering perfstats while paused, however if we decide otherwise then we can have this optimization back without making the game act like it's lagging.
Keep rect in memory
Feel better about this than creating one all da time
Lots of FPS stuff
- Disabled VSync, due to the numerous problems it has.
- Instead, added an FPS cap.
- Frame interpolation is now tied to fpscap != 35.
- By default, the FPS cap is set to the monitor's refresh rate.
- Rewrote the FPS counter.
(This also consolidates several more commits ahead of this
fixing various issues. -eid)
Misc changes after Kart cherry-picks
Fix renderdeltatics with new timing data
Update mobj oldstates before all thinkers
Allow FPS cap values
Adjust how FPS cap is checked to improve FPS stability
Fix precip crash from missing vars
Improve the framerate limiter's timing for extreme stable FPS
Handle the sleep at the end of D_SRB2Loop instead of the start
Simplifies logic in the other parts of the loop, and fixes problems with it frequently waiting too long.
Reset mobj interp state on add
Add mobj interpolator on load netgame
Move mobj interpolators to r_fps
Dynamic slope interpolators
I_GetFrameTime to try and improve frame pace
(It doesn't feel that much better though.)
Move I_FinishUpdate to D_SRB2Loop to sync screen updates with FPS cap, use timestamps in I_FrameCapSleep to simplify the code
Fix plane interpolation light level flickering
Fix flickering plane interpolation for OpenGL in the exact same way
Funny OpenGL renderer being at least 50% copy-pasted Software code :)
P_SetOrigin & P_MoveOrigin to replace P_TeleportMove
Convert P_TeleportMove use to origin funcs
Revert "P_InitAngle, to fix angle interpolation on spawning objects"
This reverts commit a80c98bd164a2748cbbfad9027b34601185d93f5.
Waypoint polyobjects interpolate z & children
Add interpolation to more moving plane types
Adds interpolation to the following:
- Crumbling platforms
- Mario blocks
- Floatbob platforms (this one works really strangely due to two thinkers, maybe double-check this one?)
Reset overlays interp states each TryRunTics
Interpolate model interpolation (lol)
Use interp tracer pos for GL linkdraw
Papersprite angle interpolation
Makes the ending signpost smooth
Move intermission emerald bounce to ticker
Bring back shadows on polyobjects
Also optimizes the method used so rings can show their shadows too. Using just the subsector is a tad bit imprecise admittedly but any more precise methods get really laggy.
Fix a bunch of ticking in hu_ drawing functions
Revert "Reset overlays interp states each TryRunTics"
This reverts commit a71a216faa20e8751b3bd0157354e8d748940c92.
Move intro ticking out of the drawer
Adjust 1up monitor icon z offsets
Fixes interpolation issues with 1up monitors.
Delta time choose player menu animations
Add drawerlib deltaTime function
Interpolate afterimages further back
Use old sleep in dedicated mode
Clamp cechotimer to 0
Fixes issues with cechos staying on-screen and glitching out
(NiGHTS items for example).
Revert "Remove unnecessary precipmobj thinker hack"
This reverts commit 0e38208620d19ec2ab690740438ac2fc7862a49e.
Fix frame pacing when game lags behind
The frame timestamp should've been made at the start of the frame, not the end.
Fix I_FrameCapSleep not respecting cpusleep
Jonathan Joestar bruh
Allow dedicated to use precise sleep timing again
Instead of only using one old sleep, just enforce framerate cap to match TICRATE.
Make Lua TeleportMove call MoveOrigin
Reset Metal fume interp state on appear
Add interpdebug
Put interpdebug stuff in perfstats instead
Add timescale cvar
Slow the game down to debug animations / interpolation problems! Speed it up if you need to get somewhere quickly while mapping!
Enable timescale outside of DEVELOP builds
It has NETVAR, so it should be fine -- put an end to useful debugging features excluded in multiplayer!
Force interpolation when timescale != 1.0
Reset old_z in MT_LOCKON think
Fixes interpolation artifacting due to spawn pos.
Fix cutscenes in interp
Fix boss1 laser in interp
Interpolate mobj scale
Precalculate refresh rate
Slower PCs can have issue querying mode over and over. This might kinda suck for windowed mode if you have different refresh rate displays but oh well
Fix interp scaling crashing software
Reset interp scale when Lua sets .scale
Disable angle interp on fresh mobjs
Fix interp scale crash for hires sprites
Interp shadow scales
Copy interp state in P_SpawnMobjFromMobj
Fix multiplayer character select
Don't interpolate mobj state if frac = 1.0
Fix Mario block item placement
Interpolate spritescale/offset x/y
Fix offset copies for SpawnMobjFromMobj
THANKS SAL
Add Lua HUD drawlists
Buffers draw calls between tics to ensure hooks
run at the originally intended rate.
Rename drawerlib deltaTime to getDeltaTime
Make renderisnewtic is false between tics
I know what I'm doing! I swear
Completely refactor timing system
Time is now tracked internally in the game using I_GetPreciseTime
and I_UpdateTime. I_Time now pulls from this internal timer. The
system code no longer needs to keep track of time itself.
This significantly improves frame and tic timing in interp mode,
resulting in a much smoother image with essentially no judder at
any framerate.
Ensure mobj interpolators reset on level load
Ensure view is not interpolated on first frame
Disable sprite offset interpolation (for now)
Refactor timing code even more
System layer is greatly simplified and framecap
logic has been moved internally. I_Sleep now
takes a sleep duration and I_SleepDuration
generically implements a precise sleep with spin
loop.
2019-10-06 22:40:52 +00:00
P_SetOrigin ( player - > mo , special - > target - > x , special - > target - > y , special - > target - > z + ( 48 < < FRACBITS ) ) ;
2018-10-20 19:17:13 +00:00
player - > mo - > angle = special - > target - > angle ;
P_SetObjectMomZ ( player - > mo , 12 < < FRACBITS , false ) ;
P_InstaThrust ( player - > mo , player - > mo - > angle , 20 < < FRACBITS ) ;
return ;
Dropping items!
* Shield Drop...
* Whatever you've got orbiting or trailing you, DROP THEM WHERE THEY STAND. (Except for the ghost sink. That one's OK.)
* Pops your Thunder Shield.
* Happens upon ANY hit, except for deathpits.
* HUD Drop...
* Also does the above, except for the Thunder Shield thing.
* If there's any item left in your item box, pop it out as a little hovering, rotating Minecraft item!
* You can pick up the Minecraft item by driving over it if your item box is sufficiently empty, or the item which is contained within it is of the same type.
* Happens upon Size Down and battle elimination.
* Can also be forced on with `cv_kartdebughuddrop on`!
* Some other random stuff.
* Fix a bunch of `a->scale = b`'s into `P_SetScale(a, b)` form, for maximum validity.
* Make K_CleanHnextList and K_UpdateHnextList one function, since they only differed by one continue clause (and the type of their input parameter).
* Allow shrunken players to pick up item boxes again.
* Fix MF_NOCLIPTHING. (Gonna pass this fix to vanilla when I get the chance, too.)
* Break NiGHTS a little through my machinations.
2018-09-06 21:17:29 +00:00
case MT_FLOATINGITEM : // SRB2kart
if ( ! P_CanPickupItem ( player , 3 ) | | ( player - > kartstuff [ k_itemamount ] & & player - > kartstuff [ k_itemtype ] ! = special - > threshold ) )
return ;
if ( G_BattleGametype ( ) & & player - > kartstuff [ k_bumper ] < = 0 )
return ;
player - > kartstuff [ k_itemtype ] = special - > threshold ;
player - > kartstuff [ k_itemamount ] + = special - > movecount ;
if ( player - > kartstuff [ k_itemamount ] > 255 )
player - > kartstuff [ k_itemamount ] = 255 ;
S_StartSound ( special , special - > info - > deathsound ) ;
P_SetTarget ( & special - > tracer , toucher ) ;
special - > flags2 | = MF2_NIGHTSPULL ;
2018-12-13 02:55:59 +00:00
special - > destscale = mapobjectscale > > 4 ;
Dropping items!
* Shield Drop...
* Whatever you've got orbiting or trailing you, DROP THEM WHERE THEY STAND. (Except for the ghost sink. That one's OK.)
* Pops your Thunder Shield.
* Happens upon ANY hit, except for deathpits.
* HUD Drop...
* Also does the above, except for the Thunder Shield thing.
* If there's any item left in your item box, pop it out as a little hovering, rotating Minecraft item!
* You can pick up the Minecraft item by driving over it if your item box is sufficiently empty, or the item which is contained within it is of the same type.
* Happens upon Size Down and battle elimination.
* Can also be forced on with `cv_kartdebughuddrop on`!
* Some other random stuff.
* Fix a bunch of `a->scale = b`'s into `P_SetScale(a, b)` form, for maximum validity.
* Make K_CleanHnextList and K_UpdateHnextList one function, since they only differed by one continue clause (and the type of their input parameter).
* Allow shrunken players to pick up item boxes again.
* Fix MF_NOCLIPTHING. (Gonna pass this fix to vanilla when I get the chance, too.)
* Break NiGHTS a little through my machinations.
2018-09-06 21:17:29 +00:00
special - > scalespeed < < = 1 ;
special - > flags & = ~ MF_SPECIAL ;
return ;
2017-02-18 18:39:25 +00:00
case MT_RANDOMITEM : // SRB2kart
2018-08-12 00:19:09 +00:00
if ( ! P_CanPickupItem ( player , 1 ) )
2016-11-21 04:23:00 +00:00
return ;
2017-11-13 03:48:32 +00:00
2018-07-03 19:14:47 +00:00
if ( G_BattleGametype ( ) & & player - > kartstuff [ k_bumper ] < = 0 )
2017-11-13 03:48:32 +00:00
{
2018-10-07 10:40:06 +00:00
if ( player - > kartstuff [ k_comebackmode ] | | player - > kartstuff [ k_comebacktimer ] )
2018-03-27 00:36:16 +00:00
return ;
2018-10-07 10:40:06 +00:00
player - > kartstuff [ k_comebackmode ] = 1 ;
2017-11-13 03:48:32 +00:00
}
2016-11-21 04:23:00 +00:00
special - > momx = special - > momy = special - > momz = 0 ;
P_SetTarget ( & special - > target , toucher ) ;
2018-03-13 05:20:47 +00:00
P_KillMobj ( special , toucher , toucher ) ;
2016-11-21 04:23:00 +00:00
break ;
2018-10-29 09:00:08 +00:00
case MT_EGGMANITEM_SHIELD : // SRB2kart
case MT_EGGMANITEM :
2018-08-12 15:04:36 +00:00
if ( ( special - > target = = toucher | | special - > target = = toucher - > target ) & & ( special - > threshold > 0 ) )
return ;
if ( special - > health < = 0 | | toucher - > health < = 0 )
return ;
if ( ! P_CanPickupItem ( player , 2 ) )
return ;
2018-08-12 15:12:18 +00:00
if ( G_BattleGametype ( ) & & player - > kartstuff [ k_bumper ] < = 0 )
2018-08-12 15:04:36 +00:00
{
2018-10-07 10:40:06 +00:00
if ( player - > kartstuff [ k_comebackmode ] | | player - > kartstuff [ k_comebacktimer ] )
2018-08-12 15:04:36 +00:00
return ;
2018-10-07 10:40:06 +00:00
player - > kartstuff [ k_comebackmode ] = 2 ;
2018-08-12 15:12:18 +00:00
}
2018-10-07 10:40:06 +00:00
else
2018-08-12 15:04:36 +00:00
{
Dropping items!
* Shield Drop...
* Whatever you've got orbiting or trailing you, DROP THEM WHERE THEY STAND. (Except for the ghost sink. That one's OK.)
* Pops your Thunder Shield.
* Happens upon ANY hit, except for deathpits.
* HUD Drop...
* Also does the above, except for the Thunder Shield thing.
* If there's any item left in your item box, pop it out as a little hovering, rotating Minecraft item!
* You can pick up the Minecraft item by driving over it if your item box is sufficiently empty, or the item which is contained within it is of the same type.
* Happens upon Size Down and battle elimination.
* Can also be forced on with `cv_kartdebughuddrop on`!
* Some other random stuff.
* Fix a bunch of `a->scale = b`'s into `P_SetScale(a, b)` form, for maximum validity.
* Make K_CleanHnextList and K_UpdateHnextList one function, since they only differed by one continue clause (and the type of their input parameter).
* Allow shrunken players to pick up item boxes again.
* Fix MF_NOCLIPTHING. (Gonna pass this fix to vanilla when I get the chance, too.)
* Break NiGHTS a little through my machinations.
2018-09-06 21:17:29 +00:00
K_DropItems ( player ) ; //K_StripItems(player);
2018-11-17 14:41:08 +00:00
//K_StripOther(player);
Dropping items!
* Shield Drop...
* Whatever you've got orbiting or trailing you, DROP THEM WHERE THEY STAND. (Except for the ghost sink. That one's OK.)
* Pops your Thunder Shield.
* Happens upon ANY hit, except for deathpits.
* HUD Drop...
* Also does the above, except for the Thunder Shield thing.
* If there's any item left in your item box, pop it out as a little hovering, rotating Minecraft item!
* You can pick up the Minecraft item by driving over it if your item box is sufficiently empty, or the item which is contained within it is of the same type.
* Happens upon Size Down and battle elimination.
* Can also be forced on with `cv_kartdebughuddrop on`!
* Some other random stuff.
* Fix a bunch of `a->scale = b`'s into `P_SetScale(a, b)` form, for maximum validity.
* Make K_CleanHnextList and K_UpdateHnextList one function, since they only differed by one continue clause (and the type of their input parameter).
* Allow shrunken players to pick up item boxes again.
* Fix MF_NOCLIPTHING. (Gonna pass this fix to vanilla when I get the chance, too.)
* Break NiGHTS a little through my machinations.
2018-09-06 21:17:29 +00:00
player - > kartstuff [ k_itemroulette ] = 1 ;
2018-08-12 15:04:36 +00:00
player - > kartstuff [ k_roulettetype ] = 2 ;
2018-10-07 10:40:06 +00:00
}
2019-03-06 03:06:47 +00:00
#if 0
2019-03-06 03:02:41 +00:00
// Eggbox snipe!
if ( special - > type = = MT_EGGMANITEM & & special - > health > 1 )
S_StartSound ( toucher , sfx_bsnipe ) ;
2019-03-06 03:06:47 +00:00
# endif
2019-03-06 03:02:41 +00:00
2018-10-07 10:40:06 +00:00
{
mobj_t * poof = P_SpawnMobj ( special - > x , special - > y , special - > z , MT_EXPLODE ) ;
S_StartSound ( poof , special - > info - > deathsound ) ;
2018-10-07 14:17:31 +00:00
}
2018-10-07 10:40:06 +00:00
2018-10-07 14:17:31 +00:00
if ( special - > target & & special - > target - > player )
{
if ( G_RaceGametype ( ) | | special - > target - > player - > kartstuff [ k_bumper ] > 0 )
2018-08-12 15:04:36 +00:00
player - > kartstuff [ k_eggmanblame ] = special - > target - > player - players ;
else
player - > kartstuff [ k_eggmanblame ] = player - players ;
2018-10-07 14:17:31 +00:00
if ( special - > target - > hnext = = special )
{
P_SetTarget ( & special - > target - > hnext , NULL ) ;
special - > target - > player - > kartstuff [ k_eggmanheld ] = 0 ;
}
2018-08-12 15:04:36 +00:00
}
2018-10-07 14:17:31 +00:00
P_RemoveMobj ( special ) ;
return ;
2018-06-16 04:00:46 +00:00
case MT_KARMAHITBOX :
if ( ! special - > target - > player )
return ;
if ( player = = special - > target - > player )
return ;
2018-07-03 19:14:47 +00:00
if ( player - > kartstuff [ k_bumper ] < = 0 )
2018-06-16 04:00:46 +00:00
return ;
2018-06-20 00:20:06 +00:00
if ( special - > target - > player - > exiting | | player - > exiting )
return ;
2018-06-16 04:00:46 +00:00
if ( special - > target - > player - > kartstuff [ k_comebacktimer ]
| | special - > target - > player - > kartstuff [ k_spinouttimer ]
| | special - > target - > player - > kartstuff [ k_squishedtimer ] )
return ;
2018-10-07 10:40:06 +00:00
if ( ! special - > target - > player - > kartstuff [ k_comebackmode ] )
2018-06-16 04:00:46 +00:00
{
2018-06-18 04:42:53 +00:00
if ( player - > kartstuff [ k_growshrinktimer ] | | player - > kartstuff [ k_squishedtimer ]
| | player - > kartstuff [ k_hyudorotimer ] | | player - > kartstuff [ k_spinouttimer ]
| | player - > kartstuff [ k_invincibilitytimer ] | | player - > powers [ pw_flashing ] )
return ;
2018-06-16 04:00:46 +00:00
else
2018-06-18 04:42:53 +00:00
{
2018-06-19 01:52:26 +00:00
mobj_t * boom = P_SpawnMobj ( special - > target - > x , special - > target - > y , special - > target - > z , MT_BOOMEXPLODE ) ;
2018-11-01 03:34:13 +00:00
UINT8 ptadd = ( K_IsPlayerWanted ( player ) ? 2 : 1 ) ;
2018-06-18 04:42:53 +00:00
boom - > scale = special - > target - > scale ;
boom - > destscale = special - > target - > scale ;
boom - > momz = 5 * FRACUNIT ;
if ( special - > target - > color )
boom - > color = special - > target - > color ;
else
2018-10-18 08:43:50 +00:00
boom - > color = SKINCOLOR_KETCHUP ;
2018-06-18 04:42:53 +00:00
S_StartSound ( boom , special - > info - > attacksound ) ;
2018-09-05 00:16:42 +00:00
if ( player - > kartstuff [ k_bumper ] = = 1 ) // If you have only one bumper left, and see if it's a 1v1
{
INT32 numingame = 0 ;
for ( i = 0 ; i < MAXPLAYERS ; i + + )
{
if ( ! playeringame [ i ] | | players [ i ] . spectator | | players [ i ] . kartstuff [ k_bumper ] < = 0 )
continue ;
numingame + + ;
}
if ( numingame < = 2 ) // If so, then an extra karma point so they are 100% certain to switch places; it's annoying to end matches with a bomb kill
2018-11-01 03:34:13 +00:00
ptadd + + ;
2018-09-05 00:16:42 +00:00
}
2018-11-01 03:34:13 +00:00
special - > target - > player - > kartstuff [ k_comebackpoints ] + = ptadd ;
if ( ptadd > 1 )
2018-11-01 21:08:30 +00:00
special - > target - > player - > kartstuff [ k_yougotem ] = 2 * TICRATE ;
2018-11-01 03:34:13 +00:00
2018-10-24 21:29:13 +00:00
if ( special - > target - > player - > kartstuff [ k_comebackpoints ] > = 2 )
2018-07-03 19:14:47 +00:00
K_StealBumper ( special - > target - > player , player , true ) ;
2018-11-01 03:34:13 +00:00
2018-06-18 04:42:53 +00:00
special - > target - > player - > kartstuff [ k_comebacktimer ] = comebacktime ;
2018-07-01 03:35:38 +00:00
2018-10-19 00:49:30 +00:00
K_ExplodePlayer ( player , special - > target , special ) ;
2018-06-18 04:42:53 +00:00
}
2018-06-16 04:00:46 +00:00
}
2018-08-12 00:19:09 +00:00
else if ( special - > target - > player - > kartstuff [ k_comebackmode ] = = 1 & & P_CanPickupItem ( player , 1 ) )
2018-06-16 04:00:46 +00:00
{
2018-11-26 07:17:14 +00:00
mobj_t * poof = P_SpawnMobj ( special - > x , special - > y , special - > z , MT_EXPLODE ) ;
2018-06-16 04:00:46 +00:00
S_StartSound ( poof , special - > info - > seesound ) ;
2018-11-26 07:17:14 +00:00
// Karma fireworks
for ( i = 0 ; i < 5 ; i + + )
{
mobj_t * firework = P_SpawnMobj ( special - > x , special - > y , special - > z , MT_KARMAFIREWORK ) ;
2018-12-02 01:48:19 +00:00
firework - > momx = ( special - > target - > momx + toucher - > momx ) / 2 ;
firework - > momy = ( special - > target - > momy + toucher - > momy ) / 2 ;
firework - > momz = ( special - > target - > momz + toucher - > momz ) / 2 ;
2018-11-26 07:17:14 +00:00
P_Thrust ( firework , FixedAngle ( ( 72 * i ) < < FRACBITS ) , P_RandomRange ( 1 , 8 ) * special - > scale ) ;
P_SetObjectMomZ ( firework , P_RandomRange ( 1 , 8 ) * special - > scale , false ) ;
firework - > color = special - > target - > color ;
}
2018-06-16 04:00:46 +00:00
special - > target - > player - > kartstuff [ k_comebackmode ] = 0 ;
special - > target - > player - > kartstuff [ k_comebackpoints ] + + ;
2018-07-01 03:35:38 +00:00
2018-10-24 21:29:13 +00:00
if ( special - > target - > player - > kartstuff [ k_comebackpoints ] > = 2 )
2018-07-03 19:14:47 +00:00
K_StealBumper ( special - > target - > player , player , true ) ;
2018-06-16 04:00:46 +00:00
special - > target - > player - > kartstuff [ k_comebacktimer ] = comebacktime ;
2018-07-01 03:35:38 +00:00
player - > kartstuff [ k_itemroulette ] = 1 ;
player - > kartstuff [ k_roulettetype ] = 1 ;
2018-06-16 04:00:46 +00:00
}
2018-10-07 10:40:06 +00:00
else if ( special - > target - > player - > kartstuff [ k_comebackmode ] = = 2 & & P_CanPickupItem ( player , 2 ) )
{
mobj_t * poof = P_SpawnMobj ( special - > x , special - > y , special - > z , MT_EXPLODE ) ;
2018-11-01 03:34:13 +00:00
UINT8 ptadd = 1 ; // No WANTED bonus for tricking
2018-10-07 10:40:06 +00:00
S_StartSound ( poof , special - > info - > seesound ) ;
2018-10-09 20:09:39 +00:00
if ( player - > kartstuff [ k_bumper ] = = 1 ) // If you have only one bumper left, and see if it's a 1v1
{
INT32 numingame = 0 ;
for ( i = 0 ; i < MAXPLAYERS ; i + + )
{
if ( ! playeringame [ i ] | | players [ i ] . spectator | | players [ i ] . kartstuff [ k_bumper ] < = 0 )
continue ;
numingame + + ;
}
2018-10-24 21:29:13 +00:00
if ( numingame < = 2 ) // If so, then an extra karma point so they are 100% certain to switch places; it's annoying to end matches with a fake kill
2018-11-01 03:34:13 +00:00
ptadd + + ;
2018-10-09 20:09:39 +00:00
}
2018-10-07 10:40:06 +00:00
special - > target - > player - > kartstuff [ k_comebackmode ] = 0 ;
2018-11-01 03:34:13 +00:00
special - > target - > player - > kartstuff [ k_comebackpoints ] + = ptadd ;
if ( ptadd > 1 )
2018-11-01 21:08:30 +00:00
special - > target - > player - > kartstuff [ k_yougotem ] = 2 * TICRATE ;
2018-10-07 10:40:06 +00:00
2018-10-24 21:29:13 +00:00
if ( special - > target - > player - > kartstuff [ k_comebackpoints ] > = 2 )
2018-10-07 10:40:06 +00:00
K_StealBumper ( special - > target - > player , player , true ) ;
2018-11-01 03:34:13 +00:00
2018-10-07 10:40:06 +00:00
special - > target - > player - > kartstuff [ k_comebacktimer ] = comebacktime ;
K_DropItems ( player ) ; //K_StripItems(player);
2018-11-17 14:41:08 +00:00
//K_StripOther(player);
2018-10-07 10:40:06 +00:00
player - > kartstuff [ k_itemroulette ] = 1 ;
player - > kartstuff [ k_roulettetype ] = 2 ;
if ( special - > target - > player - > kartstuff [ k_eggmanblame ] > = 0
& & special - > target - > player - > kartstuff [ k_eggmanblame ] < MAXPLAYERS
& & playeringame [ special - > target - > player - > kartstuff [ k_eggmanblame ] ]
& & ! players [ special - > target - > player - > kartstuff [ k_eggmanblame ] ] . spectator )
player - > kartstuff [ k_eggmanblame ] = special - > target - > player - > kartstuff [ k_eggmanblame ] ;
else
player - > kartstuff [ k_eggmanblame ] = - 1 ;
special - > target - > player - > kartstuff [ k_eggmanblame ] = - 1 ;
}
2018-06-16 04:00:46 +00:00
return ;
2018-10-18 08:43:50 +00:00
case MT_SPB :
if ( ( special - > target = = toucher | | special - > target = = toucher - > target ) & & ( special - > threshold > 0 ) )
return ;
if ( special - > health < = 0 | | toucher - > health < = 0 )
return ;
2019-01-15 02:38:38 +00:00
if ( player - > spectator )
2018-10-18 08:43:50 +00:00
return ;
2019-01-15 02:38:38 +00:00
if ( special - > tracer & & ! P_MobjWasRemoved ( special - > tracer ) & & toucher = = special - > tracer )
2018-10-18 08:43:50 +00:00
{
mobj_t * spbexplode ;
2019-01-15 02:38:38 +00:00
if ( player - > kartstuff [ k_invincibilitytimer ] > 0 | | player - > kartstuff [ k_growshrinktimer ] > 0 | | player - > kartstuff [ k_hyudorotimer ] > 0 )
2018-10-18 08:43:50 +00:00
{
2019-01-15 02:55:10 +00:00
//player->powers[pw_flashing] = 0;
2018-10-18 08:43:50 +00:00
K_DropHnextList ( player ) ;
K_StripItems ( player ) ;
}
2019-01-15 02:38:38 +00:00
S_StopSound ( special ) ; // Don't continue playing the gurgle or the siren
2018-10-18 08:43:50 +00:00
spbexplode = P_SpawnMobj ( toucher - > x , toucher - > y , toucher - > z , MT_SPBEXPLOSION ) ;
2018-10-19 00:49:30 +00:00
spbexplode - > extravalue1 = 1 ; // Tell K_ExplodePlayer to use extra knockback
2019-01-15 02:38:38 +00:00
if ( special - > target & & ! P_MobjWasRemoved ( special - > target ) )
P_SetTarget ( & spbexplode - > target , special - > target ) ;
2018-10-18 08:43:50 +00:00
P_RemoveMobj ( special ) ;
}
else
2019-01-15 02:38:38 +00:00
K_SpinPlayer ( player , special - > target , 0 , special , false ) ;
2018-10-29 09:00:08 +00:00
return ;
/*case MT_EERIEFOG:
special - > frame & = ~ FF_TRANS80 ;
special - > frame | = FF_TRANS90 ;
return ; */
case MT_SMK_MOLE :
if ( special - > target & & ! P_MobjWasRemoved ( special - > target ) )
return ;
2018-10-18 08:43:50 +00:00
2018-10-29 09:00:08 +00:00
if ( special - > health < = 0 | | toucher - > health < = 0 )
return ;
if ( ! player - > mo | | player - > spectator )
return ;
// kill
if ( player - > kartstuff [ k_invincibilitytimer ] > 0 | | player - > kartstuff [ k_growshrinktimer ] > 0 )
{
P_KillMobj ( special , toucher , toucher ) ;
return ;
}
// no interaction
if ( player - > powers [ pw_flashing ] > 0 | | player - > kartstuff [ k_hyudorotimer ] > 0
| | player - > kartstuff [ k_squishedtimer ] > 0 | | player - > kartstuff [ k_spinouttimer ] > 0 )
return ;
// attach to player!
P_SetTarget ( & special - > target , toucher ) ;
S_StartSound ( special , sfx_s1a2 ) ;
2018-06-16 04:00:46 +00:00
return ;
2018-10-22 21:36:04 +00:00
case MT_CDUFO : // SRB2kart
2018-10-21 23:34:47 +00:00
if ( special - > fuse | | ! P_CanPickupItem ( player , 1 ) | | ( G_BattleGametype ( ) & & player - > kartstuff [ k_bumper ] < = 0 ) )
return ;
player - > kartstuff [ k_itemroulette ] = 1 ;
player - > kartstuff [ k_roulettetype ] = 1 ;
2018-12-02 01:48:19 +00:00
// Karma fireworks
for ( i = 0 ; i < 5 ; i + + )
{
mobj_t * firework = P_SpawnMobj ( special - > x , special - > y , special - > z , MT_KARMAFIREWORK ) ;
firework - > momx = toucher - > momx ;
firework - > momy = toucher - > momy ;
firework - > momz = toucher - > momz ;
P_Thrust ( firework , FixedAngle ( ( 72 * i ) < < FRACBITS ) , P_RandomRange ( 1 , 8 ) * special - > scale ) ;
P_SetObjectMomZ ( firework , P_RandomRange ( 1 , 8 ) * special - > scale , false ) ;
2018-12-02 04:08:42 +00:00
firework - > color = toucher - > color ;
2018-12-02 01:48:19 +00:00
}
2018-10-21 23:34:47 +00:00
S_StartSound ( toucher , sfx_cdfm73 ) ; // they don't make this sound in the original game but it's nice to have a "reward" for good play
//special->momx = special->momy = special->momz = 0;
special - > momz = - ( 3 * special - > scale ) / 2 ;
//P_SetTarget(&special->target, toucher);
special - > fuse = 2 * TICRATE ;
break ;
2018-10-22 21:36:04 +00:00
case MT_BALLOON : // SRB2kart
P_SetObjectMomZ ( toucher , 20 < < FRACBITS , false ) ;
break ;
2021-07-24 09:08:04 +00:00
case MT_TUMBLEGEM :
case MT_TUMBLECOIN :
{
SINT8 flip = P_MobjFlip ( special ) ;
if ( ( toucher - > momx | | toucher - > momy ) & & ( flip * special - > momz < = 0 ) )
{
special - > momx = toucher - > momx ;
special - > momy = toucher - > momy ;
special - > momz = flip * max ( P_AproxDistance ( toucher - > momx , toucher - > momy ) / 4 , FixedMul ( special - > info - > speed , special - > scale ) ) ;
if ( flip * toucher - > momz > 0 )
special - > momz + = toucher - > momz / 8 ;
if ( ( statenum_t ) ( special - > state - states ) ! = special - > info - > seestate )
P_SetMobjState ( special , special - > info - > seestate ) ;
S_StartSound ( special , special - > info - > activesound ) ;
}
}
return ;
2018-08-12 15:04:36 +00:00
2014-03-15 16:59:03 +00:00
// ***************************************** //
// Rings, coins, spheres, weapon panels, etc //
// ***************************************** //
case MT_REDTEAMRING :
if ( player - > ctfteam ! = 1 )
return ;
2017-09-28 13:39:47 +00:00
/* FALLTHRU */
2014-03-15 16:59:03 +00:00
case MT_BLUETEAMRING : // Yes, I'm lazy. Oh well, deal with it.
if ( special - > type = = MT_BLUETEAMRING & & player - > ctfteam ! = 2 )
return ;
2017-09-28 13:39:47 +00:00
/* FALLTHRU */
2014-03-15 16:59:03 +00:00
case MT_RING :
case MT_FLINGRING :
2018-08-12 00:19:09 +00:00
if ( ! ( P_CanPickupItem ( player , 0 ) ) )
2014-03-15 16:59:03 +00:00
return ;
special - > momx = special - > momy = special - > momz = 0 ;
P_GivePlayerRings ( player , 1 ) ;
if ( ( maptol & TOL_NIGHTS ) & & special - > type ! = MT_FLINGRING )
P_DoNightsScore ( player ) ;
break ;
case MT_COIN :
case MT_FLINGCOIN :
2018-08-12 00:19:09 +00:00
if ( ! ( P_CanPickupItem ( player , 0 ) ) )
2014-03-15 16:59:03 +00:00
return ;
special - > momx = special - > momy = 0 ;
P_GivePlayerRings ( player , 1 ) ;
if ( ( maptol & TOL_NIGHTS ) & & special - > type ! = MT_FLINGCOIN )
P_DoNightsScore ( player ) ;
break ;
case MT_BLUEBALL :
2018-08-12 00:19:09 +00:00
if ( ! ( P_CanPickupItem ( player , 0 ) ) )
2014-03-15 16:59:03 +00:00
return ;
P_GivePlayerRings ( player , 1 ) ;
special - > momx = special - > momy = special - > momz = 0 ;
special - > destscale = FixedMul ( 8 * FRACUNIT , special - > scale ) ;
if ( states [ special - > info - > deathstate ] . tics > 0 )
special - > scalespeed = FixedDiv ( FixedDiv ( special - > destscale , special - > scale ) , states [ special - > info - > deathstate ] . tics < < FRACBITS ) ;
else
special - > scalespeed = 4 * FRACUNIT / 5 ;
if ( maptol & TOL_NIGHTS )
P_DoNightsScore ( player ) ;
break ;
case MT_AUTOPICKUP :
case MT_BOUNCEPICKUP :
case MT_SCATTERPICKUP :
case MT_GRENADEPICKUP :
case MT_EXPLODEPICKUP :
case MT_RAILPICKUP :
2018-08-12 00:19:09 +00:00
if ( ! ( P_CanPickupItem ( player , 1 ) ) )
2014-03-15 16:59:03 +00:00
return ;
// Give the power and ringweapon
if ( special - > info - > mass > = pw_infinityring & & special - > info - > mass < = pw_railring )
{
INT32 pindex = special - > info - > mass - ( INT32 ) pw_infinityring ;
player - > powers [ special - > info - > mass ] + = ( UINT16 ) special - > info - > reactiontime ;
player - > ringweapons | = 1 < < ( pindex - 1 ) ;
if ( player - > powers [ special - > info - > mass ] > rw_maximums [ pindex ] )
player - > powers [ special - > info - > mass ] = rw_maximums [ pindex ] ;
}
break ;
// Ammo pickups
case MT_INFINITYRING :
case MT_AUTOMATICRING :
case MT_BOUNCERING :
case MT_SCATTERRING :
case MT_GRENADERING :
case MT_EXPLOSIONRING :
case MT_RAILRING :
2018-08-12 00:19:09 +00:00
if ( ! ( P_CanPickupItem ( player , 1 ) ) )
2014-03-15 16:59:03 +00:00
return ;
if ( special - > info - > mass > = pw_infinityring & & special - > info - > mass < = pw_railring )
{
INT32 pindex = special - > info - > mass - ( INT32 ) pw_infinityring ;
player - > powers [ special - > info - > mass ] + = ( UINT16 ) special - > health ;
if ( player - > powers [ special - > info - > mass ] > rw_maximums [ pindex ] )
player - > powers [ special - > info - > mass ] = rw_maximums [ pindex ] ;
}
break ;
// ***************************** //
// Gameplay related collectibles //
// ***************************** //
// Special Stage Token
case MT_EMMY :
if ( player - > bot )
return ;
tokenlist + = special - > health ;
if ( ALL7EMERALDS ( emeralds ) ) // Got all 7
{
P_GivePlayerRings ( player , 50 ) ;
nummaprings + = 50 ; // no cheating towards Perfect!
}
else
token + + ;
if ( special - > tracer ) // token BG
P_RemoveMobj ( special - > tracer ) ;
break ;
// Emerald Hunt
case MT_EMERHUNT :
if ( player - > bot )
return ;
if ( hunt1 = = special )
hunt1 = NULL ;
else if ( hunt2 = = special )
hunt2 = NULL ;
else if ( hunt3 = = special )
hunt3 = NULL ;
if ( ! hunt1 & & ! hunt2 & & ! hunt3 )
{
for ( i = 0 ; i < MAXPLAYERS ; i + + )
{
if ( ! playeringame [ i ] | | players [ i ] . spectator )
continue ;
2018-09-22 22:59:26 +00:00
players [ i ] . exiting = raceexittime + 1 ;
2014-03-15 16:59:03 +00:00
}
S_StartSound ( NULL , sfx_lvpass ) ;
}
break ;
// Collectible emeralds
case MT_EMERALD1 :
case MT_EMERALD2 :
case MT_EMERALD3 :
case MT_EMERALD4 :
case MT_EMERALD5 :
case MT_EMERALD6 :
case MT_EMERALD7 :
if ( player - > bot )
return ;
if ( special - > threshold )
player - > powers [ pw_emeralds ] | = special - > info - > speed ;
else
emeralds | = special - > info - > speed ;
if ( special - > target & & special - > target - > type = = MT_EMERALDSPAWN )
{
if ( special - > target - > target )
P_SetTarget ( & special - > target - > target , NULL ) ;
special - > target - > threshold = 0 ;
P_SetTarget ( & special - > target , NULL ) ;
}
break ;
// Power stones / Match emeralds
case MT_FLINGEMERALD :
2018-08-12 00:19:09 +00:00
if ( ! ( P_CanPickupItem ( player , 1 ) ) | | player - > tossdelay )
2014-03-15 16:59:03 +00:00
return ;
player - > powers [ pw_emeralds ] | = special - > threshold ;
break ;
// Secret emblem thingy
case MT_EMBLEM :
{
2019-03-25 02:32:15 +00:00
if ( demo . playback | | player - > bot )
2014-03-15 16:59:03 +00:00
return ;
emblemlocations [ special - > health - 1 ] . collected = true ;
2018-03-30 16:16:15 +00:00
M_UpdateUnlockablesAndExtraEmblems ( false ) ;
2014-03-15 16:59:03 +00:00
2018-03-30 16:16:15 +00:00
G_SaveGameData ( false ) ;
2014-03-15 16:59:03 +00:00
break ;
}
// CTF Flags
case MT_REDFLAG :
case MT_BLUEFLAG :
if ( player - > bot )
return ;
if ( player - > powers [ pw_flashing ] | | player - > tossdelay )
return ;
if ( ! special - > spawnpoint )
return ;
if ( special - > fuse = = 1 )
return ;
// if (special->momz > 0)
// return;
{
UINT8 flagteam = ( special - > type = = MT_REDFLAG ) ? 1 : 2 ;
const char * flagtext ;
2016-07-06 04:09:17 +00:00
char flagcolor ;
char plname [ MAXPLAYERNAME + 4 ] ;
2014-03-15 16:59:03 +00:00
if ( special - > type = = MT_REDFLAG )
2016-07-06 04:09:17 +00:00
{
flagtext = M_GetText ( " Red flag " ) ;
flagcolor = ' \x85 ' ;
}
2014-03-15 16:59:03 +00:00
else
2016-07-06 04:09:17 +00:00
{
flagtext = M_GetText ( " Blue flag " ) ;
flagcolor = ' \x84 ' ;
}
snprintf ( plname , sizeof ( plname ) , " %s%s%s " ,
CTFTEAMCODE ( player ) ,
player_names [ player - players ] ,
CTFTEAMENDCODE ( player ) ) ;
2014-03-15 16:59:03 +00:00
if ( player - > ctfteam = = flagteam ) // Player is on the same team as the flag
{
// Ignore height, only check x/y for now
// avoids stupid problems with some flags constantly returning
if ( special - > x > > FRACBITS ! = special - > spawnpoint - > x
| | special - > y > > FRACBITS ! = special - > spawnpoint - > y )
{
special - > fuse = 1 ;
special - > flags2 | = MF2_JUSTATTACKED ;
if ( ! P_PlayerTouchingSectorSpecial ( player , 4 , 2 + flagteam ) )
{
2016-07-06 04:09:17 +00:00
CONS_Printf ( M_GetText ( " %s returned the %c%s%c to base. \n " ) , plname , flagcolor , flagtext , 0x80 ) ;
2014-03-15 16:59:03 +00:00
2016-07-06 04:09:17 +00:00
// The fuse code plays this sound effect
//if (players[consoleplayer].ctfteam == player->ctfteam)
// S_StartSound(NULL, sfx_hoop1);
2014-03-15 16:59:03 +00:00
}
}
}
else if ( player - > ctfteam ) // Player is on the other team (and not a spectator)
{
UINT16 flagflag = ( special - > type = = MT_REDFLAG ) ? GF_REDFLAG : GF_BLUEFLAG ;
mobj_t * * flagmobj = ( special - > type = = MT_REDFLAG ) ? & redflag : & blueflag ;
if ( player - > powers [ pw_super ] )
return ;
player - > gotflag | = flagflag ;
2016-07-06 04:09:17 +00:00
CONS_Printf ( M_GetText ( " %s picked up the %c%s%c! \n " ) , plname , flagcolor , flagtext , 0x80 ) ;
2014-03-15 16:59:03 +00:00
( * flagmobj ) = NULL ;
2014-08-04 03:49:33 +00:00
// code for dealing with abilities is handled elsewhere now
2014-03-15 16:59:03 +00:00
break ;
}
}
return ;
// ********************************** //
// NiGHTS gameplay items and powerups //
// ********************************** //
Nuke a bunch of iteration things that have no purpose in SRB2Kart. A full explanation of my reasoning and what it affects is as follows.
p_inter.c -
Everything to do with setting states for starposts
In SRB2Kart, starposts are invisble. We don't need to loop through all thinkers just to set their states when there's no visible effect of the state-setting. In addition, it has no consequences for gameplay - starposts have long been silent here, and all checking is done regarding their health, not their state.
Remove extremely low-traffic conditionals (MT_FLINGEMERALD collision height extension, for example)
These objects serve no functional purpose during regular SRB2Kart gameplay. Why should every other object have to pay an admittedly minor performance hit just for them?
Disable all mechanisms of damaging bosses or enemies with the player's physical contact
With the exception of Sapphire Coast, no MF_ENEMY objects exist in the entirety of the standard roster. In addition, the conditions for damaging the enemies were impossible to achieve, because they required vanilla SRB2 mechanics such as "jumping", "spindashing", or "super". Therefore, they can be safely commented out.
Disable NiGHTS-related material (excepting bumper, hoop, and wing-emblem objects)
NiGHTS is fundamentally incompatible with regular kart gameplay and I believe was already broken. Therefore, any mechanism which enters, aids, or abets it can be safely disabled.
Comment out Tag mechanisms
Tag is the only vanilla multiplayer gametype which has sufficient gameplay depth and complexity (HEYOOOOOOOOO) to require dedicated thinking in and of itself in order to manage. This thinking is irrelevant to Kart's functioning, and can be neutered easily.
d_clisrv.c
Comment out Tag mechanisms
See p_inter.c
d_netcmd.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
When investigating for references to NiGHTS material, I discovered that these remained untouched. In order to present a more coherent game, I have hidden the ones that serve no purpose for us.
Comment out Tag mechanisms
See p_inter.c
g_game.c
Disable NiGHTS-related material
See p_inter.c
Disable some team-related material
Teams are not present in SRB2Kart at present. Obviously we'd want to reconsider for future, but it doesn't need to be run right now.
Everything to do with setting states for starposts
See p_inter.c
m_cheat.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
See d_netcmd.c
p_map.c
Remove extremely low-traffic conditionals (MT_EGGSHIELD collision, for example)
See p_inter.c
Disable NiGHTS-related material
See p_inter.c
p_mobj.c
Disable P_EmeraldManager
Power stones, despite their relevance in vanilla Match, are not in SRB2Kart's Battle. No management of nonexistent emeralds is required.
p_setup.c
Everything to do with setting states for starposts
See p_inter.c
p_spec.c
Disable NiGHTS-related material
See p_inter.c
Everything to do with setting states for starposts
See p_inter.c
p_telept.c
Everything to do with setting states for starposts
See p_inter.c
p_tick.c
Disable some team-related material
See g_game.c
Disable P_EmeraldManager
See p_mobj.c
Do not run shields
Shield objects are not run under the vanilla system; the Thunder Shield is a domain-specific recreation using a standard mobjthinker.
Do not run special stages
SRB2Kart does not have special stages.
Comment out Tag mechanisms
See p_inter.c
y_inter.c
Disable some team-related material
See g_game.c
p_user.c
Disable NiGHTS-related material
See p_inter.c
Disable 2d movement for players
2D mode? In a kart racer? :nick:
2018-10-03 16:04:41 +00:00
/*case MT_NIGHTSDRONE:
2014-03-15 16:59:03 +00:00
if ( player - > bot )
return ;
2014-08-04 03:49:33 +00:00
if ( player - > exiting )
return ;
if ( player - > bonustime )
2014-03-15 16:59:03 +00:00
{
2014-08-04 03:49:33 +00:00
if ( G_IsSpecialStage ( gamemap ) ) //After-mare bonus time/emerald reward in special stages.
2014-03-15 16:59:03 +00:00
{
2014-08-04 03:49:33 +00:00
// only allow the player with the emerald in-hand to leave.
if ( toucher - > tracer & & toucher - > tracer - > target
& & toucher - > tracer - > target - > type = = MT_GOTEMERALD )
{
}
else // Make sure that SOMEONE has the emerald, at least!
{
for ( i = 0 ; i < MAXPLAYERS ; i + + )
if ( playeringame [ i ] & & players [ i ] . playerstate = = PST_LIVE
& & players [ i ] . mo - > tracer & & players [ i ] . mo - > tracer - > target
& & players [ i ] . mo - > tracer - > target - > type = = MT_GOTEMERALD )
return ;
// Well no one has an emerald, so exit anyway!
}
2014-03-15 16:59:03 +00:00
P_GiveEmerald ( false ) ;
// Don't play Ideya sound in special stage mode
}
2014-08-04 03:49:33 +00:00
else
S_StartSound ( toucher , special - > info - > activesound ) ;
2014-03-15 16:59:03 +00:00
}
2014-08-04 03:49:33 +00:00
else //Initial transformation. Don't allow second chances in special stages!
2014-03-15 16:59:03 +00:00
{
2014-08-04 03:49:33 +00:00
if ( player - > pflags & PF_NIGHTSMODE )
return ;
2014-03-15 16:59:03 +00:00
2014-08-04 03:49:33 +00:00
S_StartSound ( toucher , sfx_supert ) ;
2014-03-15 16:59:03 +00:00
}
2014-08-04 03:49:33 +00:00
if ( ! ( netgame | | multiplayer ) & & ! ( player - > pflags & PF_NIGHTSMODE ) )
P_SetTarget ( & special - > tracer , toucher ) ;
P_NightserizePlayer ( player , special - > health ) ; // Transform!
2014-03-15 16:59:03 +00:00
return ;
case MT_NIGHTSLOOPHELPER :
// One second delay
2014-08-04 03:49:33 +00:00
if ( special - > fuse < toucher - > fuse - TICRATE )
2014-03-15 16:59:03 +00:00
{
thinker_t * th ;
mobj_t * mo2 ;
INT32 count ;
fixed_t x , y , z , gatherradius ;
angle_t d ;
statenum_t sparklestate = S_NULL ;
if ( special - > target ! = toucher ) // These ain't your helpers, pal!
return ;
x = special - > x > > FRACBITS ;
y = special - > y > > FRACBITS ;
z = special - > z > > FRACBITS ;
count = 1 ;
// scan the remaining thinkers
for ( th = thinkercap . next ; th ! = & thinkercap ; th = th - > next )
{
if ( th - > function . acp1 ! = ( actionf_p1 ) P_MobjThinker )
continue ;
mo2 = ( mobj_t * ) th ;
if ( mo2 = = special )
continue ;
// Not our stuff!
if ( mo2 - > target ! = toucher )
continue ;
if ( mo2 - > type = = MT_NIGHTSPARKLE )
mo2 - > tics = 1 ;
else if ( mo2 - > type = = MT_NIGHTSLOOPHELPER )
{
if ( mo2 - > fuse > = special - > fuse )
{
count + + ;
x + = mo2 - > x > > FRACBITS ;
y + = mo2 - > y > > FRACBITS ;
z + = mo2 - > z > > FRACBITS ;
}
P_RemoveMobj ( mo2 ) ;
}
}
x = ( x / count ) < < FRACBITS ;
y = ( y / count ) < < FRACBITS ;
z = ( z / count ) < < FRACBITS ;
gatherradius = P_AproxDistance ( P_AproxDistance ( special - > x - x , special - > y - y ) , special - > z - z ) ;
P_RemoveMobj ( special ) ;
if ( player - > powers [ pw_nights_superloop ] )
{
gatherradius * = 2 ;
sparklestate = mobjinfo [ MT_NIGHTSPARKLE ] . seestate ;
}
if ( gatherradius < 30 * FRACUNIT ) // Player is probably just sitting there.
return ;
for ( d = 0 ; d < 16 ; d + + )
P_SpawnParaloop ( x , y , z , gatherradius , 16 , MT_NIGHTSPARKLE , sparklestate , d * ANGLE_22h , false ) ;
S_StartSound ( toucher , sfx_prloop ) ;
// Now we RE-scan all the thinkers to find close objects to pull
// in from the paraloop. Isn't this just so efficient?
for ( th = thinkercap . next ; th ! = & thinkercap ; th = th - > next )
{
if ( th - > function . acp1 ! = ( actionf_p1 ) P_MobjThinker )
continue ;
mo2 = ( mobj_t * ) th ;
if ( P_AproxDistance ( P_AproxDistance ( mo2 - > x - x , mo2 - > y - y ) , mo2 - > z - z ) > gatherradius )
continue ;
if ( mo2 - > flags & MF_SHOOTABLE )
{
P_DamageMobj ( mo2 , toucher , toucher , 1 ) ;
continue ;
}
// Make these APPEAR!
// Tails 12-15-2003
if ( mo2 - > flags & MF_NIGHTSITEM )
{
// Requires Bonus Time
if ( ( mo2 - > flags2 & MF2_STRONGBOX ) & & ! player - > bonustime )
continue ;
if ( ! ( mo2 - > flags & MF_SPECIAL ) & & mo2 - > health )
{
P_SetMobjState ( mo2 , mo2 - > info - > seestate ) ;
mo2 - > flags | = MF_SPECIAL ;
mo2 - > flags & = ~ MF_NIGHTSITEM ;
S_StartSound ( toucher , sfx_hidden ) ;
continue ;
}
}
if ( ! ( mo2 - > type = = MT_NIGHTSWING | | mo2 - > type = = MT_RING | | mo2 - > type = = MT_COIN
2016-07-06 04:09:17 +00:00
| | mo2 - > type = = MT_BLUEBALL ) )
2014-03-15 16:59:03 +00:00
continue ;
// Yay! The thing's in reach! Pull it in!
mo2 - > flags | = MF_NOCLIP | MF_NOCLIPHEIGHT ;
mo2 - > flags2 | = MF2_NIGHTSPULL ;
P_SetTarget ( & mo2 - > tracer , toucher ) ;
}
}
return ;
case MT_EGGCAPSULE :
if ( player - > bot )
return ;
// make sure everything is as it should be, THEN take rings from players in special stages
2014-08-04 03:49:33 +00:00
if ( player - > pflags & PF_NIGHTSMODE & & ! toucher - > target )
return ;
if ( player - > mare ! = special - > threshold ) // wrong mare
2014-03-15 16:59:03 +00:00
return ;
2014-08-04 03:49:33 +00:00
if ( special - > reactiontime > 0 ) // capsule already has a player attacking it, ignore
2014-03-15 16:59:03 +00:00
return ;
if ( G_IsSpecialStage ( gamemap ) & & ! player - > exiting )
{ // In special stages, share rings. Everyone gives up theirs to the player who touched the capsule
for ( i = 0 ; i < MAXPLAYERS ; i + + )
if ( playeringame [ i ] & & ( & players [ i ] ! = player ) & & players [ i ] . mo - > health > 1 )
{
2014-08-04 03:49:33 +00:00
toucher - > health + = players [ i ] . mo - > health - 1 ;
player - > health = toucher - > health ;
2014-03-15 16:59:03 +00:00
players [ i ] . mo - > health = 1 ;
players [ i ] . health = players [ i ] . mo - > health ;
}
}
if ( ! ( player - > health > 1 ) | | player - > exiting )
return ;
// Mark the player as 'pull into the capsule'
P_SetTarget ( & player - > capsule , special ) ;
special - > reactiontime = ( player - players ) + 1 ;
P_SetTarget ( & special - > target , NULL ) ;
// Clear text
player - > texttimer = 0 ;
Nuke a bunch of iteration things that have no purpose in SRB2Kart. A full explanation of my reasoning and what it affects is as follows.
p_inter.c -
Everything to do with setting states for starposts
In SRB2Kart, starposts are invisble. We don't need to loop through all thinkers just to set their states when there's no visible effect of the state-setting. In addition, it has no consequences for gameplay - starposts have long been silent here, and all checking is done regarding their health, not their state.
Remove extremely low-traffic conditionals (MT_FLINGEMERALD collision height extension, for example)
These objects serve no functional purpose during regular SRB2Kart gameplay. Why should every other object have to pay an admittedly minor performance hit just for them?
Disable all mechanisms of damaging bosses or enemies with the player's physical contact
With the exception of Sapphire Coast, no MF_ENEMY objects exist in the entirety of the standard roster. In addition, the conditions for damaging the enemies were impossible to achieve, because they required vanilla SRB2 mechanics such as "jumping", "spindashing", or "super". Therefore, they can be safely commented out.
Disable NiGHTS-related material (excepting bumper, hoop, and wing-emblem objects)
NiGHTS is fundamentally incompatible with regular kart gameplay and I believe was already broken. Therefore, any mechanism which enters, aids, or abets it can be safely disabled.
Comment out Tag mechanisms
Tag is the only vanilla multiplayer gametype which has sufficient gameplay depth and complexity (HEYOOOOOOOOO) to require dedicated thinking in and of itself in order to manage. This thinking is irrelevant to Kart's functioning, and can be neutered easily.
d_clisrv.c
Comment out Tag mechanisms
See p_inter.c
d_netcmd.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
When investigating for references to NiGHTS material, I discovered that these remained untouched. In order to present a more coherent game, I have hidden the ones that serve no purpose for us.
Comment out Tag mechanisms
See p_inter.c
g_game.c
Disable NiGHTS-related material
See p_inter.c
Disable some team-related material
Teams are not present in SRB2Kart at present. Obviously we'd want to reconsider for future, but it doesn't need to be run right now.
Everything to do with setting states for starposts
See p_inter.c
m_cheat.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
See d_netcmd.c
p_map.c
Remove extremely low-traffic conditionals (MT_EGGSHIELD collision, for example)
See p_inter.c
Disable NiGHTS-related material
See p_inter.c
p_mobj.c
Disable P_EmeraldManager
Power stones, despite their relevance in vanilla Match, are not in SRB2Kart's Battle. No management of nonexistent emeralds is required.
p_setup.c
Everything to do with setting states for starposts
See p_inter.c
p_spec.c
Disable NiGHTS-related material
See p_inter.c
Everything to do with setting states for starposts
See p_inter.c
p_telept.c
Everything to do with setting states for starposts
See p_inter.c
p_tick.c
Disable some team-related material
See g_game.c
Disable P_EmeraldManager
See p_mobj.c
Do not run shields
Shield objects are not run under the vanilla system; the Thunder Shield is a domain-specific recreation using a standard mobjthinker.
Do not run special stages
SRB2Kart does not have special stages.
Comment out Tag mechanisms
See p_inter.c
y_inter.c
Disable some team-related material
See g_game.c
p_user.c
Disable NiGHTS-related material
See p_inter.c
Disable 2d movement for players
2D mode? In a kart racer? :nick:
2018-10-03 16:04:41 +00:00
return ; */
2014-03-15 16:59:03 +00:00
case MT_NIGHTSBUMPER :
// Don't trigger if the stage is ended/failed
if ( player - > exiting )
return ;
if ( player - > bumpertime < TICRATE / 4 )
{
2014-08-04 03:49:33 +00:00
S_StartSound ( toucher , special - > info - > seesound ) ;
2014-03-15 16:59:03 +00:00
if ( player - > pflags & PF_NIGHTSMODE )
{
player - > bumpertime = TICRATE / 2 ;
if ( special - > threshold > 0 )
player - > flyangle = ( special - > threshold * 30 ) - 1 ;
else
player - > flyangle = special - > threshold ;
player - > speed = FixedMul ( special - > info - > speed , special - > scale ) ;
// Potentially causes axis transfer failures.
// Also rarely worked properly anyway.
//P_UnsetThingPosition(player->mo);
//player->mo->x = special->x;
//player->mo->y = special->y;
//P_SetThingPosition(player->mo);
2014-08-04 03:49:33 +00:00
toucher - > z = special - > z + ( special - > height / 4 ) ;
2014-03-15 16:59:03 +00:00
}
else // More like a spring
{
angle_t fa ;
fixed_t xspeed , yspeed ;
const fixed_t speed = FixedMul ( FixedDiv ( special - > info - > speed * FRACUNIT , 75 * FRACUNIT ) , FixedSqrt ( FixedMul ( toucher - > scale , special - > scale ) ) ) ;
player - > bumpertime = TICRATE / 2 ;
2014-08-04 03:49:33 +00:00
P_UnsetThingPosition ( toucher ) ;
toucher - > x = special - > x ;
toucher - > y = special - > y ;
P_SetThingPosition ( toucher ) ;
toucher - > z = special - > z + ( special - > height / 4 ) ;
2014-03-15 16:59:03 +00:00
if ( special - > threshold > 0 )
fa = ( FixedAngle ( ( ( special - > threshold * 30 ) - 1 ) * FRACUNIT ) > > ANGLETOFINESHIFT ) & FINEMASK ;
else
fa = 0 ;
xspeed = FixedMul ( FINECOSINE ( fa ) , speed ) ;
yspeed = FixedMul ( FINESINE ( fa ) , speed ) ;
2014-08-04 03:49:33 +00:00
P_InstaThrust ( toucher , special - > angle , xspeed / 10 ) ;
toucher - > momz = yspeed / 11 ;
2014-03-15 16:59:03 +00:00
2014-08-04 03:49:33 +00:00
toucher - > angle = special - > angle ;
2014-03-15 16:59:03 +00:00
if ( player = = & players [ consoleplayer ] )
2019-04-18 07:08:11 +00:00
localangle [ 0 ] = toucher - > angle ;
else if ( player = = & players [ displayplayers [ 1 ] ] )
localangle [ 1 ] = toucher - > angle ;
else if ( player = = & players [ displayplayers [ 2 ] ] )
localangle [ 2 ] = toucher - > angle ;
else if ( player = = & players [ displayplayers [ 3 ] ] )
localangle [ 3 ] = toucher - > angle ;
2014-03-15 16:59:03 +00:00
P_ResetPlayer ( player ) ;
2017-11-04 17:32:47 +00:00
P_SetPlayerMobjState ( toucher , S_KART_STND1 ) ; // SRB2kart - was S_PLAY_FALL1
2014-03-15 16:59:03 +00:00
}
}
return ;
Nuke a bunch of iteration things that have no purpose in SRB2Kart. A full explanation of my reasoning and what it affects is as follows.
p_inter.c -
Everything to do with setting states for starposts
In SRB2Kart, starposts are invisble. We don't need to loop through all thinkers just to set their states when there's no visible effect of the state-setting. In addition, it has no consequences for gameplay - starposts have long been silent here, and all checking is done regarding their health, not their state.
Remove extremely low-traffic conditionals (MT_FLINGEMERALD collision height extension, for example)
These objects serve no functional purpose during regular SRB2Kart gameplay. Why should every other object have to pay an admittedly minor performance hit just for them?
Disable all mechanisms of damaging bosses or enemies with the player's physical contact
With the exception of Sapphire Coast, no MF_ENEMY objects exist in the entirety of the standard roster. In addition, the conditions for damaging the enemies were impossible to achieve, because they required vanilla SRB2 mechanics such as "jumping", "spindashing", or "super". Therefore, they can be safely commented out.
Disable NiGHTS-related material (excepting bumper, hoop, and wing-emblem objects)
NiGHTS is fundamentally incompatible with regular kart gameplay and I believe was already broken. Therefore, any mechanism which enters, aids, or abets it can be safely disabled.
Comment out Tag mechanisms
Tag is the only vanilla multiplayer gametype which has sufficient gameplay depth and complexity (HEYOOOOOOOOO) to require dedicated thinking in and of itself in order to manage. This thinking is irrelevant to Kart's functioning, and can be neutered easily.
d_clisrv.c
Comment out Tag mechanisms
See p_inter.c
d_netcmd.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
When investigating for references to NiGHTS material, I discovered that these remained untouched. In order to present a more coherent game, I have hidden the ones that serve no purpose for us.
Comment out Tag mechanisms
See p_inter.c
g_game.c
Disable NiGHTS-related material
See p_inter.c
Disable some team-related material
Teams are not present in SRB2Kart at present. Obviously we'd want to reconsider for future, but it doesn't need to be run right now.
Everything to do with setting states for starposts
See p_inter.c
m_cheat.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
See d_netcmd.c
p_map.c
Remove extremely low-traffic conditionals (MT_EGGSHIELD collision, for example)
See p_inter.c
Disable NiGHTS-related material
See p_inter.c
p_mobj.c
Disable P_EmeraldManager
Power stones, despite their relevance in vanilla Match, are not in SRB2Kart's Battle. No management of nonexistent emeralds is required.
p_setup.c
Everything to do with setting states for starposts
See p_inter.c
p_spec.c
Disable NiGHTS-related material
See p_inter.c
Everything to do with setting states for starposts
See p_inter.c
p_telept.c
Everything to do with setting states for starposts
See p_inter.c
p_tick.c
Disable some team-related material
See g_game.c
Disable P_EmeraldManager
See p_mobj.c
Do not run shields
Shield objects are not run under the vanilla system; the Thunder Shield is a domain-specific recreation using a standard mobjthinker.
Do not run special stages
SRB2Kart does not have special stages.
Comment out Tag mechanisms
See p_inter.c
y_inter.c
Disable some team-related material
See g_game.c
p_user.c
Disable NiGHTS-related material
See p_inter.c
Disable 2d movement for players
2D mode? In a kart racer? :nick:
2018-10-03 16:04:41 +00:00
/*case MT_NIGHTSSUPERLOOP:
2014-03-15 16:59:03 +00:00
if ( player - > bot | | ! ( player - > pflags & PF_NIGHTSMODE ) )
return ;
if ( ! G_IsSpecialStage ( gamemap ) )
player - > powers [ pw_nights_superloop ] = ( UINT16 ) special - > info - > speed ;
else
{
for ( i = 0 ; i < MAXPLAYERS ; i + + )
if ( playeringame [ i ] & & players [ i ] . pflags & PF_NIGHTSMODE )
players [ i ] . powers [ pw_nights_superloop ] = ( UINT16 ) special - > info - > speed ;
if ( special - > info - > deathsound ! = sfx_None )
S_StartSound ( NULL , special - > info - > deathsound ) ;
}
// CECHO showing you what this item is
2019-04-18 07:08:11 +00:00
if ( player = = & players [ displayplayers [ 0 ] ] | | G_IsSpecialStage ( gamemap ) )
2014-03-15 16:59:03 +00:00
{
HU_SetCEchoFlags ( V_AUTOFADEOUT ) ;
HU_SetCEchoDuration ( 4 ) ;
HU_DoCEcho ( M_GetText ( " \\ \\ \\ \\ \\ \\ \\ \\ Super Paraloop " ) ) ;
}
break ;
case MT_NIGHTSDRILLREFILL :
if ( player - > bot | | ! ( player - > pflags & PF_NIGHTSMODE ) )
return ;
if ( ! G_IsSpecialStage ( gamemap ) )
player - > drillmeter = special - > info - > speed ;
else
{
for ( i = 0 ; i < MAXPLAYERS ; i + + )
if ( playeringame [ i ] & & players [ i ] . pflags & PF_NIGHTSMODE )
players [ i ] . drillmeter = special - > info - > speed ;
if ( special - > info - > deathsound ! = sfx_None )
S_StartSound ( NULL , special - > info - > deathsound ) ;
}
// CECHO showing you what this item is
2019-04-18 07:08:11 +00:00
if ( player = = & players [ displayplayers [ 0 ] ] | | G_IsSpecialStage ( gamemap ) )
2014-03-15 16:59:03 +00:00
{
HU_SetCEchoFlags ( V_AUTOFADEOUT ) ;
HU_SetCEchoDuration ( 4 ) ;
HU_DoCEcho ( M_GetText ( " \\ \\ \\ \\ \\ \\ \\ \\ Drill Refill " ) ) ;
}
break ;
case MT_NIGHTSHELPER :
if ( player - > bot | | ! ( player - > pflags & PF_NIGHTSMODE ) )
return ;
if ( ! G_IsSpecialStage ( gamemap ) )
{
// A flicky orbits us now
mobj_t * flickyobj = P_SpawnMobj ( toucher - > x , toucher - > y , toucher - > z + toucher - > info - > height , MT_NIGHTOPIANHELPER ) ;
P_SetTarget ( & flickyobj - > target , toucher ) ;
player - > powers [ pw_nights_helper ] = ( UINT16 ) special - > info - > speed ;
}
else
{
mobj_t * flickyobj ;
for ( i = 0 ; i < MAXPLAYERS ; i + + )
if ( playeringame [ i ] & & players [ i ] . mo & & players [ i ] . pflags & PF_NIGHTSMODE ) {
players [ i ] . powers [ pw_nights_helper ] = ( UINT16 ) special - > info - > speed ;
flickyobj = P_SpawnMobj ( players [ i ] . mo - > x , players [ i ] . mo - > y , players [ i ] . mo - > z + players [ i ] . mo - > info - > height , MT_NIGHTOPIANHELPER ) ;
P_SetTarget ( & flickyobj - > target , players [ i ] . mo ) ;
}
if ( special - > info - > deathsound ! = sfx_None )
S_StartSound ( NULL , special - > info - > deathsound ) ;
}
// CECHO showing you what this item is
2019-04-18 07:08:11 +00:00
if ( player = = & players [ displayplayers [ 0 ] ] | | G_IsSpecialStage ( gamemap ) )
2014-03-15 16:59:03 +00:00
{
HU_SetCEchoFlags ( V_AUTOFADEOUT ) ;
HU_SetCEchoDuration ( 4 ) ;
HU_DoCEcho ( M_GetText ( " \\ \\ \\ \\ \\ \\ \\ \\ Nightopian Helper " ) ) ;
}
break ;
case MT_NIGHTSEXTRATIME :
if ( player - > bot | | ! ( player - > pflags & PF_NIGHTSMODE ) )
return ;
if ( ! G_IsSpecialStage ( gamemap ) )
{
player - > nightstime + = special - > info - > speed ;
player - > startedtime + = special - > info - > speed ;
P_RestoreMusic ( player ) ;
}
else
{
for ( i = 0 ; i < MAXPLAYERS ; i + + )
if ( playeringame [ i ] & & players [ i ] . pflags & PF_NIGHTSMODE )
{
players [ i ] . nightstime + = special - > info - > speed ;
players [ i ] . startedtime + = special - > info - > speed ;
P_RestoreMusic ( & players [ i ] ) ;
}
if ( special - > info - > deathsound ! = sfx_None )
S_StartSound ( NULL , special - > info - > deathsound ) ;
}
// CECHO showing you what this item is
2019-04-18 07:08:11 +00:00
if ( player = = & players [ displayplayers [ 0 ] ] | | G_IsSpecialStage ( gamemap ) )
2014-03-15 16:59:03 +00:00
{
HU_SetCEchoFlags ( V_AUTOFADEOUT ) ;
HU_SetCEchoDuration ( 4 ) ;
HU_DoCEcho ( M_GetText ( " \\ \\ \\ \\ \\ \\ \\ \\ Extra Time " ) ) ;
}
break ;
case MT_NIGHTSLINKFREEZE :
if ( player - > bot | | ! ( player - > pflags & PF_NIGHTSMODE ) )
return ;
if ( ! G_IsSpecialStage ( gamemap ) )
{
player - > powers [ pw_nights_linkfreeze ] = ( UINT16 ) special - > info - > speed ;
player - > linktimer = 2 * TICRATE ;
}
else
{
for ( i = 0 ; i < MAXPLAYERS ; i + + )
if ( playeringame [ i ] & & players [ i ] . pflags & PF_NIGHTSMODE )
{
players [ i ] . powers [ pw_nights_linkfreeze ] + = ( UINT16 ) special - > info - > speed ;
players [ i ] . linktimer = 2 * TICRATE ;
}
if ( special - > info - > deathsound ! = sfx_None )
S_StartSound ( NULL , special - > info - > deathsound ) ;
}
// CECHO showing you what this item is
2019-04-18 07:08:11 +00:00
if ( player = = & players [ displayplayers [ 0 ] ] | | G_IsSpecialStage ( gamemap ) )
2014-03-15 16:59:03 +00:00
{
HU_SetCEchoFlags ( V_AUTOFADEOUT ) ;
HU_SetCEchoDuration ( 4 ) ;
HU_DoCEcho ( M_GetText ( " \\ \\ \\ \\ \\ \\ \\ \\ Link Freeze " ) ) ;
}
Nuke a bunch of iteration things that have no purpose in SRB2Kart. A full explanation of my reasoning and what it affects is as follows.
p_inter.c -
Everything to do with setting states for starposts
In SRB2Kart, starposts are invisble. We don't need to loop through all thinkers just to set their states when there's no visible effect of the state-setting. In addition, it has no consequences for gameplay - starposts have long been silent here, and all checking is done regarding their health, not their state.
Remove extremely low-traffic conditionals (MT_FLINGEMERALD collision height extension, for example)
These objects serve no functional purpose during regular SRB2Kart gameplay. Why should every other object have to pay an admittedly minor performance hit just for them?
Disable all mechanisms of damaging bosses or enemies with the player's physical contact
With the exception of Sapphire Coast, no MF_ENEMY objects exist in the entirety of the standard roster. In addition, the conditions for damaging the enemies were impossible to achieve, because they required vanilla SRB2 mechanics such as "jumping", "spindashing", or "super". Therefore, they can be safely commented out.
Disable NiGHTS-related material (excepting bumper, hoop, and wing-emblem objects)
NiGHTS is fundamentally incompatible with regular kart gameplay and I believe was already broken. Therefore, any mechanism which enters, aids, or abets it can be safely disabled.
Comment out Tag mechanisms
Tag is the only vanilla multiplayer gametype which has sufficient gameplay depth and complexity (HEYOOOOOOOOO) to require dedicated thinking in and of itself in order to manage. This thinking is irrelevant to Kart's functioning, and can be neutered easily.
d_clisrv.c
Comment out Tag mechanisms
See p_inter.c
d_netcmd.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
When investigating for references to NiGHTS material, I discovered that these remained untouched. In order to present a more coherent game, I have hidden the ones that serve no purpose for us.
Comment out Tag mechanisms
See p_inter.c
g_game.c
Disable NiGHTS-related material
See p_inter.c
Disable some team-related material
Teams are not present in SRB2Kart at present. Obviously we'd want to reconsider for future, but it doesn't need to be run right now.
Everything to do with setting states for starposts
See p_inter.c
m_cheat.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
See d_netcmd.c
p_map.c
Remove extremely low-traffic conditionals (MT_EGGSHIELD collision, for example)
See p_inter.c
Disable NiGHTS-related material
See p_inter.c
p_mobj.c
Disable P_EmeraldManager
Power stones, despite their relevance in vanilla Match, are not in SRB2Kart's Battle. No management of nonexistent emeralds is required.
p_setup.c
Everything to do with setting states for starposts
See p_inter.c
p_spec.c
Disable NiGHTS-related material
See p_inter.c
Everything to do with setting states for starposts
See p_inter.c
p_telept.c
Everything to do with setting states for starposts
See p_inter.c
p_tick.c
Disable some team-related material
See g_game.c
Disable P_EmeraldManager
See p_mobj.c
Do not run shields
Shield objects are not run under the vanilla system; the Thunder Shield is a domain-specific recreation using a standard mobjthinker.
Do not run special stages
SRB2Kart does not have special stages.
Comment out Tag mechanisms
See p_inter.c
y_inter.c
Disable some team-related material
See g_game.c
p_user.c
Disable NiGHTS-related material
See p_inter.c
Disable 2d movement for players
2D mode? In a kart racer? :nick:
2018-10-03 16:04:41 +00:00
break ; */
2014-03-15 16:59:03 +00:00
case MT_NIGHTSWING :
if ( G_IsSpecialStage ( gamemap ) & & useNightsSS )
{ // Pseudo-ring.
S_StartSound ( toucher , special - > info - > painsound ) ;
player - > totalring + + ;
}
else
S_StartSound ( toucher , special - > info - > activesound ) ;
P_DoNightsScore ( player ) ;
break ;
case MT_HOOPCOLLIDE :
// This produces a kind of 'domino effect' with the hoop's pieces.
for ( ; special - > hprev ! = NULL ; special = special - > hprev ) ; // Move to the first sprite in the hoop
i = 0 ;
for ( ; special - > type = = MT_HOOP ; special = special - > hnext )
{
special - > fuse = 11 ;
special - > movedir = i ;
special - > extravalue1 = special - > target - > extravalue1 ;
special - > extravalue2 = special - > target - > extravalue2 ;
special - > target - > threshold = 4242 ;
i + + ;
}
// Make the collision detectors disappear.
{
mobj_t * hnext ;
for ( ; special ! = NULL ; special = hnext )
{
hnext = special - > hnext ;
P_RemoveMobj ( special ) ;
}
}
P_DoNightsScore ( player ) ;
// Hoops are the only things that should add to the drill meter
// Also, one tic's worth of drill is too much.
if ( G_IsSpecialStage ( gamemap ) )
{
for ( i = 0 ; i < MAXPLAYERS ; i + + )
if ( playeringame [ i ] & & players [ i ] . pflags & PF_NIGHTSMODE )
players [ i ] . drillmeter + = TICRATE / 2 ;
}
else if ( player - > bot )
players [ consoleplayer ] . drillmeter + = TICRATE / 2 ;
else
player - > drillmeter + = TICRATE / 2 ;
// Play hoop sound -- pick one depending on the current link.
if ( player - > linkcount < = 5 )
S_StartSound ( toucher , sfx_hoop1 ) ;
else if ( player - > linkcount < = 10 )
S_StartSound ( toucher , sfx_hoop2 ) ;
else
S_StartSound ( toucher , sfx_hoop3 ) ;
return ;
// ***** //
// Mario //
// ***** //
case MT_SHELL :
if ( special - > state = = & states [ S_SHELL ] ) // Resting anim
{
// Kick that sucker around!
special - > angle = toucher - > angle ;
P_InstaThrust ( special , special - > angle , FixedMul ( special - > info - > speed , special - > scale ) ) ;
S_StartSound ( toucher , sfx_mario2 ) ;
P_SetMobjState ( special , S_SHELL1 ) ;
P_SetTarget ( & special - > target , toucher ) ;
special - > threshold = ( 3 * TICRATE ) / 2 ;
}
return ;
case MT_AXE :
{
line_t junk ;
thinker_t * th ;
mobj_t * mo2 ;
if ( player - > bot )
return ;
junk . tag = 649 ;
EV_DoElevator ( & junk , bridgeFall , false ) ;
// scan the remaining thinkers to find koopa
for ( th = thinkercap . next ; th ! = & thinkercap ; th = th - > next )
{
if ( th - > function . acp1 ! = ( actionf_p1 ) P_MobjThinker )
continue ;
mo2 = ( mobj_t * ) th ;
if ( mo2 - > type = = MT_KOOPA )
{
mo2 - > momz = 5 * FRACUNIT ;
break ;
}
}
}
break ;
case MT_FIREFLOWER :
if ( player - > bot )
return ;
2014-08-04 03:49:33 +00:00
player - > powers [ pw_shield ] | = SH_FIREFLOWER ;
2014-03-15 16:59:03 +00:00
toucher - > color = SKINCOLOR_WHITE ;
2019-02-16 18:42:24 +00:00
G_GhostAddColor ( player - players , GHC_FIREFLOWER ) ;
2014-03-15 16:59:03 +00:00
break ;
// *************** //
// Misc touchables //
// *************** //
case MT_STARPOST :
if ( player - > bot )
return ;
2017-02-07 22:19:04 +00:00
// SRB2kart - 150117
if ( player - > exiting ) //STOP MESSING UP MY STATS FASDFASDF
{
player - > kartstuff [ k_starpostwp ] = player - > kartstuff [ k_waypoint ] ;
return ;
}
//
2017-11-20 07:00:19 +00:00
// SRB2kart: make sure the player will have enough checkpoints to touch
2018-12-02 07:29:47 +00:00
if ( circuitmap & & special - > health > = ( ( numstarposts / 2 ) + player - > starpostnum ) )
2014-03-15 16:59:03 +00:00
{
// blatant reuse of a variable that's normally unused in circuit
if ( ! player - > tossdelay )
2020-09-20 21:03:14 +00:00
{
2018-06-03 22:20:21 +00:00
S_StartSound ( toucher , sfx_s26d ) ;
2020-09-20 21:03:14 +00:00
if ( netgame & & cv_antigrief . value )
{
player - > grieftime + = TICRATE ;
}
}
2014-03-15 16:59:03 +00:00
player - > tossdelay = 3 ;
return ;
}
// We could technically have 91.1 Star Posts. 90 is cleaner.
if ( special - > health > 90 )
{
CONS_Debug ( DBG_GAMELOGIC , " Bad Starpost Number! \n " ) ;
return ;
}
if ( player - > starpostnum > = special - > health )
return ; // Already hit this post
2016-07-06 04:09:17 +00:00
// Save the player's time and position.
2017-02-07 22:19:04 +00:00
player - > starposttime = player - > realtime ; //this makes race mode's timers work correctly whilst not affecting sp -x
//player->starposttime = leveltime;
2014-08-04 03:49:33 +00:00
player - > starpostx = toucher - > x > > FRACBITS ;
player - > starposty = toucher - > y > > FRACBITS ;
2014-03-15 16:59:03 +00:00
player - > starpostz = special - > z > > FRACBITS ;
player - > starpostangle = special - > angle ;
player - > starpostnum = special - > health ;
2019-02-18 13:00:36 +00:00
player - > kartstuff [ k_starpostflip ] = special - > spawnpoint - > options & MTF_OBJECTFLIP ; // store flipping
2020-09-20 21:03:14 +00:00
player - > grieftime = 0 ;
2014-03-15 16:59:03 +00:00
Nuke a bunch of iteration things that have no purpose in SRB2Kart. A full explanation of my reasoning and what it affects is as follows.
p_inter.c -
Everything to do with setting states for starposts
In SRB2Kart, starposts are invisble. We don't need to loop through all thinkers just to set their states when there's no visible effect of the state-setting. In addition, it has no consequences for gameplay - starposts have long been silent here, and all checking is done regarding their health, not their state.
Remove extremely low-traffic conditionals (MT_FLINGEMERALD collision height extension, for example)
These objects serve no functional purpose during regular SRB2Kart gameplay. Why should every other object have to pay an admittedly minor performance hit just for them?
Disable all mechanisms of damaging bosses or enemies with the player's physical contact
With the exception of Sapphire Coast, no MF_ENEMY objects exist in the entirety of the standard roster. In addition, the conditions for damaging the enemies were impossible to achieve, because they required vanilla SRB2 mechanics such as "jumping", "spindashing", or "super". Therefore, they can be safely commented out.
Disable NiGHTS-related material (excepting bumper, hoop, and wing-emblem objects)
NiGHTS is fundamentally incompatible with regular kart gameplay and I believe was already broken. Therefore, any mechanism which enters, aids, or abets it can be safely disabled.
Comment out Tag mechanisms
Tag is the only vanilla multiplayer gametype which has sufficient gameplay depth and complexity (HEYOOOOOOOOO) to require dedicated thinking in and of itself in order to manage. This thinking is irrelevant to Kart's functioning, and can be neutered easily.
d_clisrv.c
Comment out Tag mechanisms
See p_inter.c
d_netcmd.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
When investigating for references to NiGHTS material, I discovered that these remained untouched. In order to present a more coherent game, I have hidden the ones that serve no purpose for us.
Comment out Tag mechanisms
See p_inter.c
g_game.c
Disable NiGHTS-related material
See p_inter.c
Disable some team-related material
Teams are not present in SRB2Kart at present. Obviously we'd want to reconsider for future, but it doesn't need to be run right now.
Everything to do with setting states for starposts
See p_inter.c
m_cheat.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
See d_netcmd.c
p_map.c
Remove extremely low-traffic conditionals (MT_EGGSHIELD collision, for example)
See p_inter.c
Disable NiGHTS-related material
See p_inter.c
p_mobj.c
Disable P_EmeraldManager
Power stones, despite their relevance in vanilla Match, are not in SRB2Kart's Battle. No management of nonexistent emeralds is required.
p_setup.c
Everything to do with setting states for starposts
See p_inter.c
p_spec.c
Disable NiGHTS-related material
See p_inter.c
Everything to do with setting states for starposts
See p_inter.c
p_telept.c
Everything to do with setting states for starposts
See p_inter.c
p_tick.c
Disable some team-related material
See g_game.c
Disable P_EmeraldManager
See p_mobj.c
Do not run shields
Shield objects are not run under the vanilla system; the Thunder Shield is a domain-specific recreation using a standard mobjthinker.
Do not run special stages
SRB2Kart does not have special stages.
Comment out Tag mechanisms
See p_inter.c
y_inter.c
Disable some team-related material
See g_game.c
p_user.c
Disable NiGHTS-related material
See p_inter.c
Disable 2d movement for players
2D mode? In a kart racer? :nick:
2018-10-03 16:04:41 +00:00
//S_StartSound(toucher, special->info->painsound);
2014-03-15 16:59:03 +00:00
return ;
case MT_FAKEMOBILE :
{
fixed_t touchx , touchy , touchspeed ;
angle_t angle ;
if ( P_AproxDistance ( toucher - > x - special - > x , toucher - > y - special - > y ) >
P_AproxDistance ( ( toucher - > x - toucher - > momx ) - special - > x , ( toucher - > y - toucher - > momy ) - special - > y ) )
{
touchx = toucher - > x + toucher - > momx ;
touchy = toucher - > y + toucher - > momy ;
}
else
{
touchx = toucher - > x ;
touchy = toucher - > y ;
}
angle = R_PointToAngle2 ( special - > x , special - > y , touchx , touchy ) ;
touchspeed = P_AproxDistance ( toucher - > momx , toucher - > momy ) ;
toucher - > momx = P_ReturnThrustX ( special , angle , touchspeed ) ;
toucher - > momy = P_ReturnThrustY ( special , angle , touchspeed ) ;
toucher - > momz = - toucher - > momz ;
if ( player - > pflags & PF_GLIDING )
{
player - > pflags & = ~ ( PF_GLIDING | PF_JUMPED ) ;
2017-11-04 17:32:47 +00:00
P_SetPlayerMobjState ( toucher , S_KART_STND1 ) ; // SRB2kart - was S_PLAY_FALL1
2014-03-15 16:59:03 +00:00
}
// Play a bounce sound?
S_StartSound ( toucher , special - > info - > painsound ) ;
}
return ;
case MT_BLACKEGGMAN_GOOPFIRE :
2016-08-15 03:51:08 +00:00
if ( ! player - > powers [ pw_flashing ] ) // SRB2kart
2014-03-15 16:59:03 +00:00
{
toucher - > momx = 0 ;
toucher - > momy = 0 ;
if ( toucher - > momz ! = 0 )
special - > momz = toucher - > momz ;
player - > powers [ pw_ingoop ] = 2 ;
if ( player - > pflags & PF_ITEMHANG )
{
2014-08-04 03:49:33 +00:00
P_SetTarget ( & toucher - > tracer , NULL ) ;
2014-03-15 16:59:03 +00:00
player - > pflags & = ~ PF_ITEMHANG ;
}
P_ResetPlayer ( player ) ;
if ( special - > target & & special - > target - > state = = & states [ S_BLACKEGG_SHOOT1 ] )
{
2016-07-06 04:09:17 +00:00
if ( special - > target - > health < = 2 & & P_RandomChance ( FRACUNIT / 2 ) )
2014-03-15 16:59:03 +00:00
P_SetMobjState ( special - > target , special - > target - > info - > missilestate ) ;
else
P_SetMobjState ( special - > target , special - > target - > info - > raisestate ) ;
}
}
else
player - > powers [ pw_ingoop ] = 0 ;
return ;
case MT_EGGSHIELD :
{
fixed_t touchx , touchy , touchspeed ;
angle_t angle ;
if ( P_AproxDistance ( toucher - > x - special - > x , toucher - > y - special - > y ) >
P_AproxDistance ( ( toucher - > x - toucher - > momx ) - special - > x , ( toucher - > y - toucher - > momy ) - special - > y ) )
{
touchx = toucher - > x + toucher - > momx ;
touchy = toucher - > y + toucher - > momy ;
}
else
{
touchx = toucher - > x ;
touchy = toucher - > y ;
}
angle = R_PointToAngle2 ( special - > x , special - > y , touchx , touchy ) - special - > angle ;
touchspeed = P_AproxDistance ( toucher - > momx , toucher - > momy ) ;
// Blocked by the shield?
if ( ! ( angle > ANGLE_90 & & angle < ANGLE_270 ) )
{
toucher - > momx = P_ReturnThrustX ( special , special - > angle , touchspeed ) ;
toucher - > momy = P_ReturnThrustY ( special , special - > angle , touchspeed ) ;
toucher - > momz = - toucher - > momz ;
if ( player - > pflags & PF_GLIDING )
{
player - > pflags & = ~ ( PF_GLIDING | PF_JUMPED ) ;
2017-11-04 17:32:47 +00:00
P_SetPlayerMobjState ( toucher , S_KART_STND1 ) ; // SRB2kart - was S_PLAY_FALL1
2014-03-15 16:59:03 +00:00
}
// Play a bounce sound?
S_StartSound ( toucher , special - > info - > painsound ) ;
return ;
}
2014-08-04 03:49:33 +00:00
else if ( ( ( player - > pflags & PF_NIGHTSMODE ) & & ( player - > pflags & PF_DRILLING ) ) | | ( player - > pflags & ( PF_JUMPED | PF_SPINNING | PF_GLIDING ) )
| | player - > powers [ pw_invulnerability ] | | player - > powers [ pw_super ] ) // Do you possess the ability to subdue the object?
2014-03-15 16:59:03 +00:00
{
// Shatter the shield!
toucher - > momx = - toucher - > momx / 2 ;
toucher - > momy = - toucher - > momy / 2 ;
toucher - > momz = - toucher - > momz ;
break ;
}
}
return ;
case MT_BIGTUMBLEWEED :
case MT_LITTLETUMBLEWEED :
if ( toucher - > momx | | toucher - > momy )
{
special - > momx = toucher - > momx ;
special - > momy = toucher - > momy ;
special - > momz = P_AproxDistance ( toucher - > momx , toucher - > momy ) / 4 ;
if ( toucher - > momz > 0 )
special - > momz + = toucher - > momz / 8 ;
P_SetMobjState ( special , special - > info - > seestate ) ;
}
return ;
case MT_SMALLMACECHAIN :
case MT_BIGMACECHAIN :
// Is this the last link in the chain?
2016-08-22 21:54:30 +00:00
if ( toucher - > momz > 0 | | ! ( special - > flags2 & MF2_AMBUSH )
2014-03-15 16:59:03 +00:00
| | ( player - > pflags & PF_ITEMHANG ) | | ( player - > pflags & PF_MACESPIN ) )
return ;
if ( toucher - > z > special - > z + special - > height / 2 )
return ;
if ( toucher - > z + toucher - > height / 2 < special - > z )
return ;
if ( player - > powers [ pw_flashing ] )
return ;
P_ResetPlayer ( player ) ;
P_SetTarget ( & toucher - > tracer , special ) ;
if ( special - > target & & ( special - > target - > type = = MT_SPINMACEPOINT | | special - > target - > type = = MT_HIDDEN_SLING ) )
{
player - > pflags | = PF_MACESPIN ;
S_StartSound ( toucher , sfx_spin ) ;
2017-11-04 17:32:47 +00:00
P_SetPlayerMobjState ( toucher , S_KART_STND1 ) ; // SRB2kart - was S_PLAY_ATK1
2014-03-15 16:59:03 +00:00
}
else
player - > pflags | = PF_ITEMHANG ;
2016-07-06 04:09:17 +00:00
// Can't jump first frame
player - > pflags | = PF_JUMPSTASIS ;
2014-03-15 16:59:03 +00:00
return ;
case MT_BIGMINE :
case MT_BIGAIRMINE :
// Spawn explosion!
P_SpawnMobj ( special - > x , special - > y , special - > z , special - > info - > mass ) ;
P_RadiusAttack ( special , special , special - > info - > damage ) ;
S_StartSound ( special , special - > info - > deathsound ) ;
P_SetMobjState ( special , special - > info - > deathstate ) ;
return ;
case MT_SPECIALSPIKEBALL :
if ( ! ( ! useNightsSS & & G_IsSpecialStage ( gamemap ) ) ) // Only for old special stages
{
P_DamageMobj ( toucher , special , special , 1 ) ;
return ;
}
if ( player - > powers [ pw_invulnerability ] | | player - > powers [ pw_flashing ]
| | ( player - > powers [ pw_super ] & & ! ( ALL7EMERALDS ( player - > powers [ pw_emeralds ] ) ) ) )
return ;
if ( player - > powers [ pw_shield ] | | player - > bot ) //If One-Hit Shield
{
P_RemoveShield ( player ) ;
2014-08-04 03:49:33 +00:00
S_StartSound ( toucher , sfx_shldls ) ; // Ba-Dum! Shield loss.
2014-03-15 16:59:03 +00:00
}
else
{
P_PlayRinglossSound ( toucher ) ;
if ( toucher - > health > 10 )
toucher - > health - = 10 ;
else
toucher - > health = 1 ;
player - > health = toucher - > health ;
}
P_DoPlayerPain ( player , special , NULL ) ;
return ;
case MT_EGGMOBILE2_POGO :
// sanity checks
if ( ! special - > target | | ! special - > target - > health )
return ;
// Goomba Stomp'd!
if ( special - > target - > momz < 0 )
{
P_DamageMobj ( toucher , special , special - > target , 1 ) ;
//special->target->momz = -special->target->momz;
special - > target - > momx = special - > target - > momy = 0 ;
special - > target - > momz = 0 ;
special - > target - > flags | = MF_NOGRAVITY ;
P_SetMobjState ( special - > target , special - > info - > raisestate ) ;
S_StartSound ( special - > target , special - > info - > activesound ) ;
P_RemoveMobj ( special ) ;
}
return ;
2017-02-18 00:25:16 +00:00
case MT_EXTRALARGEBUBBLE :
2016-08-15 03:51:08 +00:00
return ; // SRB2kart - don't need bubbles mucking with the player
2014-03-15 16:59:03 +00:00
if ( ( player - > powers [ pw_shield ] & SH_NOSTACK ) = = SH_ELEMENTAL )
return ;
if ( maptol & TOL_NIGHTS )
return ;
if ( mariomode )
return ;
2014-08-04 03:49:33 +00:00
else if ( toucher - > eflags & MFE_VERTICALFLIP )
{
if ( special - > z + special - > height < toucher - > z + toucher - > height / 3
| | special - > z + special - > height > toucher - > z + ( toucher - > height * 2 / 3 ) )
return ; // Only go in the mouth
}
else if ( special - > z < toucher - > z + toucher - > height / 3
| | special - > z > toucher - > z + ( toucher - > height * 2 / 3 ) )
2014-03-15 16:59:03 +00:00
return ; // Only go in the mouth
Mammoth commit!
* Deaths in record attack no longer put you into a glitchy singleplayer game-over state that we somehow both kept around and also broke since we branched Kart off of Vanilla..
* Fix non-standard mapscales making the Death Egg respawn octagons dissasemble themselves.
* Allow for MULTIPLE TIME EMBLEMS PER MAP, at least in the emblem UI on the timer. It shows all completed emblems plus the uncompleted emblem up to a total of three.
* Major tweaks to the First Person HUD.
* I know this was your baby, Sal, and some of the changes may prove controversial - so I've put the ones that are likely to cause the most fuss inside an ifndef block, so that you can toggle it as you please with minimal code changes.
* Dontdraw-ness, transparency, and colorization match the player's object!
* Moves around on the screen with respect to the direction of the player object's motion, to make drifting look nicer!
* Flashes the colour of your drift sparks.
* Did a WHOLE bunch of things with respect to music. I'm not sure how to describe this, so I'll go through step-by-step.
* Countdowns now play the drowning music again.
* Removed/disabled extraenous P_RestoreMusics.
* Made map-ending music called by its own function, P_EndingMusic(player_t *player).
* Made the ending music play on the LAST player crossing the finishing line in splitscreen, rather than first.
* Make dead players spinout and clip through the floor, at least until we add the new death anims.
* Fix prior pogo spring usage making dead players fall faster.
* Make the time over countdown use the kart font when not splitscreen with 3 or 4 players.
* Removed a weird bonus HWR_DrawCroppedPatch function signature in the hardware header.
2018-07-16 19:19:30 +00:00
/* // SRB2kart - Can't drown.
2014-03-15 16:59:03 +00:00
// Eaten by player!
if ( player - > powers [ pw_underwater ] & & player - > powers [ pw_underwater ] < = 12 * TICRATE + 1 )
P_RestoreMusic ( player ) ;
if ( player - > powers [ pw_underwater ] < underwatertics + 1 )
player - > powers [ pw_underwater ] = underwatertics + 1 ;
Mammoth commit!
* Deaths in record attack no longer put you into a glitchy singleplayer game-over state that we somehow both kept around and also broke since we branched Kart off of Vanilla..
* Fix non-standard mapscales making the Death Egg respawn octagons dissasemble themselves.
* Allow for MULTIPLE TIME EMBLEMS PER MAP, at least in the emblem UI on the timer. It shows all completed emblems plus the uncompleted emblem up to a total of three.
* Major tweaks to the First Person HUD.
* I know this was your baby, Sal, and some of the changes may prove controversial - so I've put the ones that are likely to cause the most fuss inside an ifndef block, so that you can toggle it as you please with minimal code changes.
* Dontdraw-ness, transparency, and colorization match the player's object!
* Moves around on the screen with respect to the direction of the player object's motion, to make drifting look nicer!
* Flashes the colour of your drift sparks.
* Did a WHOLE bunch of things with respect to music. I'm not sure how to describe this, so I'll go through step-by-step.
* Countdowns now play the drowning music again.
* Removed/disabled extraenous P_RestoreMusics.
* Made map-ending music called by its own function, P_EndingMusic(player_t *player).
* Made the ending music play on the LAST player crossing the finishing line in splitscreen, rather than first.
* Make dead players spinout and clip through the floor, at least until we add the new death anims.
* Fix prior pogo spring usage making dead players fall faster.
* Make the time over countdown use the kart font when not splitscreen with 3 or 4 players.
* Removed a weird bonus HWR_DrawCroppedPatch function signature in the hardware header.
2018-07-16 19:19:30 +00:00
*/
2014-03-15 16:59:03 +00:00
2017-02-18 00:25:16 +00:00
/*
2014-03-15 16:59:03 +00:00
if ( ! player - > climbing )
{
2014-08-04 03:49:33 +00:00
P_SetPlayerMobjState ( toucher , S_PLAY_GASP ) ;
2014-03-15 16:59:03 +00:00
P_ResetPlayer ( player ) ;
}
2016-08-15 03:51:08 +00:00
*/
2014-03-15 16:59:03 +00:00
2014-08-04 03:49:33 +00:00
toucher - > momx = toucher - > momy = toucher - > momz = 0 ;
2014-03-15 16:59:03 +00:00
break ;
case MT_WATERDROP :
if ( special - > state = = & states [ special - > info - > spawnstate ] )
{
special - > z = toucher - > z + toucher - > height - FixedMul ( 8 * FRACUNIT , special - > scale ) ;
special - > momz = 0 ;
special - > flags | = MF_NOGRAVITY ;
P_SetMobjState ( special , special - > info - > deathstate ) ;
S_StartSound ( special , special - > info - > deathsound + ( P_RandomKey ( special - > info - > mass ) ) ) ;
}
return ;
default : // SOC or script pickup
if ( player - > bot )
return ;
P_SetTarget ( & special - > target , toucher ) ;
break ;
}
}
2018-03-13 02:51:14 +00:00
if ( ! P_MobjWasRemoved ( special ) )
{
S_StartSound ( toucher , special - > info - > deathsound ) ; // was NULL, but changed to player so you could hear others pick up rings
P_KillMobj ( special , NULL , toucher ) ;
}
2014-03-15 16:59:03 +00:00
}
2016-07-06 04:09:17 +00:00
/** Checks if the level timer is over the timelimit and the round should end,
* unless you are in overtime . In which case leveltime may stretch out beyond
* timelimitintics and overtime ' s status will be checked here each tick .
* Verify that the value of : : cv_timelimit is greater than zero before
* calling this function .
*
* \ sa cv_timelimit , P_CheckPointLimit , P_UpdateSpecials
*/
void P_CheckTimeLimit ( void )
{
2018-07-18 20:40:04 +00:00
INT32 i , k ;
2016-07-06 04:09:17 +00:00
if ( ! cv_timelimit . value )
return ;
if ( ! ( multiplayer | | netgame ) )
return ;
2018-02-08 22:13:06 +00:00
if ( G_RaceGametype ( ) )
2016-07-06 04:09:17 +00:00
return ;
2018-07-18 20:40:04 +00:00
if ( leveltime < ( timelimitintics + starttime ) )
2016-07-06 04:09:17 +00:00
return ;
if ( gameaction = = ga_completed )
return ;
//Tagmode round end but only on the tic before the
2017-01-13 19:53:52 +00:00
//XD_EXITLEVEL packet is received by all players.
Nuke a bunch of iteration things that have no purpose in SRB2Kart. A full explanation of my reasoning and what it affects is as follows.
p_inter.c -
Everything to do with setting states for starposts
In SRB2Kart, starposts are invisble. We don't need to loop through all thinkers just to set their states when there's no visible effect of the state-setting. In addition, it has no consequences for gameplay - starposts have long been silent here, and all checking is done regarding their health, not their state.
Remove extremely low-traffic conditionals (MT_FLINGEMERALD collision height extension, for example)
These objects serve no functional purpose during regular SRB2Kart gameplay. Why should every other object have to pay an admittedly minor performance hit just for them?
Disable all mechanisms of damaging bosses or enemies with the player's physical contact
With the exception of Sapphire Coast, no MF_ENEMY objects exist in the entirety of the standard roster. In addition, the conditions for damaging the enemies were impossible to achieve, because they required vanilla SRB2 mechanics such as "jumping", "spindashing", or "super". Therefore, they can be safely commented out.
Disable NiGHTS-related material (excepting bumper, hoop, and wing-emblem objects)
NiGHTS is fundamentally incompatible with regular kart gameplay and I believe was already broken. Therefore, any mechanism which enters, aids, or abets it can be safely disabled.
Comment out Tag mechanisms
Tag is the only vanilla multiplayer gametype which has sufficient gameplay depth and complexity (HEYOOOOOOOOO) to require dedicated thinking in and of itself in order to manage. This thinking is irrelevant to Kart's functioning, and can be neutered easily.
d_clisrv.c
Comment out Tag mechanisms
See p_inter.c
d_netcmd.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
When investigating for references to NiGHTS material, I discovered that these remained untouched. In order to present a more coherent game, I have hidden the ones that serve no purpose for us.
Comment out Tag mechanisms
See p_inter.c
g_game.c
Disable NiGHTS-related material
See p_inter.c
Disable some team-related material
Teams are not present in SRB2Kart at present. Obviously we'd want to reconsider for future, but it doesn't need to be run right now.
Everything to do with setting states for starposts
See p_inter.c
m_cheat.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
See d_netcmd.c
p_map.c
Remove extremely low-traffic conditionals (MT_EGGSHIELD collision, for example)
See p_inter.c
Disable NiGHTS-related material
See p_inter.c
p_mobj.c
Disable P_EmeraldManager
Power stones, despite their relevance in vanilla Match, are not in SRB2Kart's Battle. No management of nonexistent emeralds is required.
p_setup.c
Everything to do with setting states for starposts
See p_inter.c
p_spec.c
Disable NiGHTS-related material
See p_inter.c
Everything to do with setting states for starposts
See p_inter.c
p_telept.c
Everything to do with setting states for starposts
See p_inter.c
p_tick.c
Disable some team-related material
See g_game.c
Disable P_EmeraldManager
See p_mobj.c
Do not run shields
Shield objects are not run under the vanilla system; the Thunder Shield is a domain-specific recreation using a standard mobjthinker.
Do not run special stages
SRB2Kart does not have special stages.
Comment out Tag mechanisms
See p_inter.c
y_inter.c
Disable some team-related material
See g_game.c
p_user.c
Disable NiGHTS-related material
See p_inter.c
Disable 2d movement for players
2D mode? In a kart racer? :nick:
2018-10-03 16:04:41 +00:00
/*if (G_TagGametype())
2016-07-06 04:09:17 +00:00
{
if ( leveltime = = ( timelimitintics + 1 ) )
{
for ( i = 0 ; i < MAXPLAYERS ; i + + )
{
if ( ! playeringame [ i ] | | players [ i ] . spectator
| | ( players [ i ] . pflags & PF_TAGGED ) | | ( players [ i ] . pflags & PF_TAGIT ) )
continue ;
2017-01-13 19:53:52 +00:00
CONS_Printf ( M_GetText ( " %s received double points for surviving the round. \n " ) , player_names [ i ] ) ;
2016-07-06 04:09:17 +00:00
P_AddPlayerScore ( & players [ i ] , players [ i ] . score ) ;
}
}
}
//Optional tie-breaker for Match/CTF
Nuke a bunch of iteration things that have no purpose in SRB2Kart. A full explanation of my reasoning and what it affects is as follows.
p_inter.c -
Everything to do with setting states for starposts
In SRB2Kart, starposts are invisble. We don't need to loop through all thinkers just to set their states when there's no visible effect of the state-setting. In addition, it has no consequences for gameplay - starposts have long been silent here, and all checking is done regarding their health, not their state.
Remove extremely low-traffic conditionals (MT_FLINGEMERALD collision height extension, for example)
These objects serve no functional purpose during regular SRB2Kart gameplay. Why should every other object have to pay an admittedly minor performance hit just for them?
Disable all mechanisms of damaging bosses or enemies with the player's physical contact
With the exception of Sapphire Coast, no MF_ENEMY objects exist in the entirety of the standard roster. In addition, the conditions for damaging the enemies were impossible to achieve, because they required vanilla SRB2 mechanics such as "jumping", "spindashing", or "super". Therefore, they can be safely commented out.
Disable NiGHTS-related material (excepting bumper, hoop, and wing-emblem objects)
NiGHTS is fundamentally incompatible with regular kart gameplay and I believe was already broken. Therefore, any mechanism which enters, aids, or abets it can be safely disabled.
Comment out Tag mechanisms
Tag is the only vanilla multiplayer gametype which has sufficient gameplay depth and complexity (HEYOOOOOOOOO) to require dedicated thinking in and of itself in order to manage. This thinking is irrelevant to Kart's functioning, and can be neutered easily.
d_clisrv.c
Comment out Tag mechanisms
See p_inter.c
d_netcmd.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
When investigating for references to NiGHTS material, I discovered that these remained untouched. In order to present a more coherent game, I have hidden the ones that serve no purpose for us.
Comment out Tag mechanisms
See p_inter.c
g_game.c
Disable NiGHTS-related material
See p_inter.c
Disable some team-related material
Teams are not present in SRB2Kart at present. Obviously we'd want to reconsider for future, but it doesn't need to be run right now.
Everything to do with setting states for starposts
See p_inter.c
m_cheat.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
See d_netcmd.c
p_map.c
Remove extremely low-traffic conditionals (MT_EGGSHIELD collision, for example)
See p_inter.c
Disable NiGHTS-related material
See p_inter.c
p_mobj.c
Disable P_EmeraldManager
Power stones, despite their relevance in vanilla Match, are not in SRB2Kart's Battle. No management of nonexistent emeralds is required.
p_setup.c
Everything to do with setting states for starposts
See p_inter.c
p_spec.c
Disable NiGHTS-related material
See p_inter.c
Everything to do with setting states for starposts
See p_inter.c
p_telept.c
Everything to do with setting states for starposts
See p_inter.c
p_tick.c
Disable some team-related material
See g_game.c
Disable P_EmeraldManager
See p_mobj.c
Do not run shields
Shield objects are not run under the vanilla system; the Thunder Shield is a domain-specific recreation using a standard mobjthinker.
Do not run special stages
SRB2Kart does not have special stages.
Comment out Tag mechanisms
See p_inter.c
y_inter.c
Disable some team-related material
See g_game.c
p_user.c
Disable NiGHTS-related material
See p_inter.c
Disable 2d movement for players
2D mode? In a kart racer? :nick:
2018-10-03 16:04:41 +00:00
else */ if ( cv_overtime . value )
2016-07-06 04:09:17 +00:00
{
INT32 playerarray [ MAXPLAYERS ] ;
INT32 tempplayer = 0 ;
INT32 spectators = 0 ;
INT32 playercount = 0 ;
//Figure out if we have enough participating players to care.
for ( i = 0 ; i < MAXPLAYERS ; i + + )
{
2018-07-18 20:40:04 +00:00
if ( players [ i ] . exiting )
return ;
2016-07-06 04:09:17 +00:00
if ( playeringame [ i ] & & players [ i ] . spectator )
spectators + + ;
}
if ( ( D_NumPlayers ( ) - spectators ) > 1 )
{
// Play the starpost sfx after the first second of overtime.
if ( gamestate = = GS_LEVEL & & ( leveltime = = ( timelimitintics + TICRATE ) ) )
S_StartSound ( NULL , sfx_strpst ) ;
// Normal Match
if ( ! G_GametypeHasTeams ( ) )
{
//Store the nodes of participating players in an array.
for ( i = 0 ; i < MAXPLAYERS ; i + + )
{
if ( playeringame [ i ] & & ! players [ i ] . spectator )
{
playerarray [ playercount ] = i ;
playercount + + ;
}
}
2019-05-10 03:10:23 +00:00
if ( playercount > MAXPLAYERS )
playercount = MAXPLAYERS ;
2016-07-06 04:09:17 +00:00
//Sort 'em.
for ( i = 1 ; i < playercount ; i + + )
{
for ( k = i ; k < playercount ; k + + )
{
2018-07-18 20:40:04 +00:00
if ( players [ playerarray [ i - 1 ] ] . marescore < players [ playerarray [ k ] ] . marescore )
2016-07-06 04:09:17 +00:00
{
tempplayer = playerarray [ i - 1 ] ;
playerarray [ i - 1 ] = playerarray [ k ] ;
playerarray [ k ] = tempplayer ;
}
}
}
//End the round if the top players aren't tied.
2018-07-18 20:40:04 +00:00
if ( players [ playerarray [ 0 ] ] . marescore = = players [ playerarray [ 1 ] ] . marescore )
2016-07-06 04:09:17 +00:00
return ;
}
else
{
//In team match and CTF, determining a tie is much simpler. =P
if ( redscore = = bluescore )
return ;
}
}
2018-07-18 20:40:04 +00:00
}
for ( i = 0 ; i < MAXPLAYERS ; i + + )
{
if ( ! playeringame [ i ] | | players [ i ] . spectator )
continue ;
if ( players [ i ] . exiting )
return ;
P_DoPlayerExit ( & players [ i ] ) ;
}
2016-07-06 04:09:17 +00:00
2018-07-18 20:40:04 +00:00
/*if (server)
SendNetXCmd ( XD_EXITLEVEL , NULL , 0 ) ; */
2016-07-06 04:09:17 +00:00
}
2014-03-15 16:59:03 +00:00
/** Checks if a player's score is over the pointlimit and the round should end.
* Verify that the value of : : cv_pointlimit is greater than zero before
* calling this function .
*
2016-07-06 04:09:17 +00:00
* \ sa cv_pointlimit , P_CheckTimeLimit , P_UpdateSpecials
2014-03-15 16:59:03 +00:00
*/
void P_CheckPointLimit ( void )
{
INT32 i ;
if ( ! cv_pointlimit . value )
return ;
if ( ! ( multiplayer | | netgame ) )
return ;
2018-02-08 22:13:06 +00:00
if ( G_RaceGametype ( ) )
2014-03-15 16:59:03 +00:00
return ;
// pointlimit is nonzero, check if it's been reached by this player
2018-07-18 20:40:04 +00:00
/*if (G_GametypeHasTeams())
2014-03-15 16:59:03 +00:00
{
// Just check both teams
if ( ( UINT32 ) cv_pointlimit . value < = redscore | | ( UINT32 ) cv_pointlimit . value < = bluescore )
{
if ( server )
SendNetXCmd ( XD_EXITLEVEL , NULL , 0 ) ;
}
}
2018-07-18 20:40:04 +00:00
else */
2014-03-15 16:59:03 +00:00
{
for ( i = 0 ; i < MAXPLAYERS ; i + + )
{
if ( ! playeringame [ i ] | | players [ i ] . spectator )
continue ;
2018-07-18 20:40:04 +00:00
if ( ( UINT32 ) cv_pointlimit . value < = players [ i ] . marescore )
2014-03-15 16:59:03 +00:00
{
2018-07-18 20:40:04 +00:00
for ( i = 0 ; i < MAXPLAYERS ; i + + ) // AAAAA nested loop using the same iteration variable ;;
{
if ( ! playeringame [ i ] | | players [ i ] . spectator )
continue ;
if ( players [ i ] . exiting )
return ;
P_DoPlayerExit ( & players [ i ] ) ;
}
/*if (server)
SendNetXCmd ( XD_EXITLEVEL , NULL , 0 ) ; */
return ; // good thing we're leaving the function immediately instead of letting the loop get mangled!
2014-03-15 16:59:03 +00:00
}
}
}
}
/*Checks for untagged remaining players in both tag derivitave modes.
* If no untagged players remain , end the round .
* Also serves as error checking if the only IT player leaves . */
Nuke a bunch of iteration things that have no purpose in SRB2Kart. A full explanation of my reasoning and what it affects is as follows.
p_inter.c -
Everything to do with setting states for starposts
In SRB2Kart, starposts are invisble. We don't need to loop through all thinkers just to set their states when there's no visible effect of the state-setting. In addition, it has no consequences for gameplay - starposts have long been silent here, and all checking is done regarding their health, not their state.
Remove extremely low-traffic conditionals (MT_FLINGEMERALD collision height extension, for example)
These objects serve no functional purpose during regular SRB2Kart gameplay. Why should every other object have to pay an admittedly minor performance hit just for them?
Disable all mechanisms of damaging bosses or enemies with the player's physical contact
With the exception of Sapphire Coast, no MF_ENEMY objects exist in the entirety of the standard roster. In addition, the conditions for damaging the enemies were impossible to achieve, because they required vanilla SRB2 mechanics such as "jumping", "spindashing", or "super". Therefore, they can be safely commented out.
Disable NiGHTS-related material (excepting bumper, hoop, and wing-emblem objects)
NiGHTS is fundamentally incompatible with regular kart gameplay and I believe was already broken. Therefore, any mechanism which enters, aids, or abets it can be safely disabled.
Comment out Tag mechanisms
Tag is the only vanilla multiplayer gametype which has sufficient gameplay depth and complexity (HEYOOOOOOOOO) to require dedicated thinking in and of itself in order to manage. This thinking is irrelevant to Kart's functioning, and can be neutered easily.
d_clisrv.c
Comment out Tag mechanisms
See p_inter.c
d_netcmd.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
When investigating for references to NiGHTS material, I discovered that these remained untouched. In order to present a more coherent game, I have hidden the ones that serve no purpose for us.
Comment out Tag mechanisms
See p_inter.c
g_game.c
Disable NiGHTS-related material
See p_inter.c
Disable some team-related material
Teams are not present in SRB2Kart at present. Obviously we'd want to reconsider for future, but it doesn't need to be run right now.
Everything to do with setting states for starposts
See p_inter.c
m_cheat.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
See d_netcmd.c
p_map.c
Remove extremely low-traffic conditionals (MT_EGGSHIELD collision, for example)
See p_inter.c
Disable NiGHTS-related material
See p_inter.c
p_mobj.c
Disable P_EmeraldManager
Power stones, despite their relevance in vanilla Match, are not in SRB2Kart's Battle. No management of nonexistent emeralds is required.
p_setup.c
Everything to do with setting states for starposts
See p_inter.c
p_spec.c
Disable NiGHTS-related material
See p_inter.c
Everything to do with setting states for starposts
See p_inter.c
p_telept.c
Everything to do with setting states for starposts
See p_inter.c
p_tick.c
Disable some team-related material
See g_game.c
Disable P_EmeraldManager
See p_mobj.c
Do not run shields
Shield objects are not run under the vanilla system; the Thunder Shield is a domain-specific recreation using a standard mobjthinker.
Do not run special stages
SRB2Kart does not have special stages.
Comment out Tag mechanisms
See p_inter.c
y_inter.c
Disable some team-related material
See g_game.c
p_user.c
Disable NiGHTS-related material
See p_inter.c
Disable 2d movement for players
2D mode? In a kart racer? :nick:
2018-10-03 16:04:41 +00:00
/*void P_CheckSurvivors(void)
2014-03-15 16:59:03 +00:00
{
INT32 i ;
INT32 survivors = 0 ;
INT32 taggers = 0 ;
INT32 spectators = 0 ;
INT32 survivorarray [ MAXPLAYERS ] ;
if ( ! D_NumPlayers ( ) ) //no players in the game, no check performed.
return ;
for ( i = 0 ; i < MAXPLAYERS ; i + + ) //figure out counts of taggers, survivors and spectators.
{
if ( playeringame [ i ] )
{
if ( players [ i ] . spectator )
spectators + + ;
else if ( players [ i ] . pflags & PF_TAGIT )
taggers + + ;
else if ( ! ( players [ i ] . pflags & PF_TAGGED ) )
{
survivorarray [ survivors ] = i ;
survivors + + ;
}
}
}
if ( ! taggers ) //If there are no taggers, pick a survivor at random to be it.
{
// Exception for hide and seek. If a round has started and the IT player leaves, end the round.
if ( gametype = = GT_HIDEANDSEEK & & ( leveltime > = ( hidetime * TICRATE ) ) )
{
CONS_Printf ( M_GetText ( " The IT player has left the game. \n " ) ) ;
if ( server )
SendNetXCmd ( XD_EXITLEVEL , NULL , 0 ) ;
return ;
}
if ( survivors )
{
INT32 newtagger = survivorarray [ P_RandomKey ( survivors ) ] ;
CONS_Printf ( M_GetText ( " %s is now IT! \n " ) , player_names [ newtagger ] ) ; // Tell everyone who is it!
players [ newtagger ] . pflags | = PF_TAGIT ;
survivors - - ; //Get rid of the guy we just made IT.
//Yeah, we have an eligible tagger, but we may not have anybody for him to tag!
//If there is only one guy waiting on the game to fill or spectators to enter game, don't bother.
if ( ! survivors & & ( D_NumPlayers ( ) - spectators ) > 1 )
{
CONS_Printf ( M_GetText ( " All players have been tagged! \n " ) ) ;
if ( server )
SendNetXCmd ( XD_EXITLEVEL , NULL , 0 ) ;
}
return ;
}
//If we reach this point, no player can replace the one that was IT.
//Unless it is one player waiting on a game, end the round.
if ( ( D_NumPlayers ( ) - spectators ) > 1 )
{
CONS_Printf ( M_GetText ( " There are no players able to become IT. \n " ) ) ;
if ( server )
SendNetXCmd ( XD_EXITLEVEL , NULL , 0 ) ;
}
return ;
}
//If there are taggers, but no survivors, end the round.
//Except when the tagger is by himself and the rest of the game are spectators.
if ( ! survivors & & ( D_NumPlayers ( ) - spectators ) > 1 )
{
CONS_Printf ( M_GetText ( " All players have been tagged! \n " ) ) ;
if ( server )
SendNetXCmd ( XD_EXITLEVEL , NULL , 0 ) ;
}
Nuke a bunch of iteration things that have no purpose in SRB2Kart. A full explanation of my reasoning and what it affects is as follows.
p_inter.c -
Everything to do with setting states for starposts
In SRB2Kart, starposts are invisble. We don't need to loop through all thinkers just to set their states when there's no visible effect of the state-setting. In addition, it has no consequences for gameplay - starposts have long been silent here, and all checking is done regarding their health, not their state.
Remove extremely low-traffic conditionals (MT_FLINGEMERALD collision height extension, for example)
These objects serve no functional purpose during regular SRB2Kart gameplay. Why should every other object have to pay an admittedly minor performance hit just for them?
Disable all mechanisms of damaging bosses or enemies with the player's physical contact
With the exception of Sapphire Coast, no MF_ENEMY objects exist in the entirety of the standard roster. In addition, the conditions for damaging the enemies were impossible to achieve, because they required vanilla SRB2 mechanics such as "jumping", "spindashing", or "super". Therefore, they can be safely commented out.
Disable NiGHTS-related material (excepting bumper, hoop, and wing-emblem objects)
NiGHTS is fundamentally incompatible with regular kart gameplay and I believe was already broken. Therefore, any mechanism which enters, aids, or abets it can be safely disabled.
Comment out Tag mechanisms
Tag is the only vanilla multiplayer gametype which has sufficient gameplay depth and complexity (HEYOOOOOOOOO) to require dedicated thinking in and of itself in order to manage. This thinking is irrelevant to Kart's functioning, and can be neutered easily.
d_clisrv.c
Comment out Tag mechanisms
See p_inter.c
d_netcmd.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
When investigating for references to NiGHTS material, I discovered that these remained untouched. In order to present a more coherent game, I have hidden the ones that serve no purpose for us.
Comment out Tag mechanisms
See p_inter.c
g_game.c
Disable NiGHTS-related material
See p_inter.c
Disable some team-related material
Teams are not present in SRB2Kart at present. Obviously we'd want to reconsider for future, but it doesn't need to be run right now.
Everything to do with setting states for starposts
See p_inter.c
m_cheat.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
See d_netcmd.c
p_map.c
Remove extremely low-traffic conditionals (MT_EGGSHIELD collision, for example)
See p_inter.c
Disable NiGHTS-related material
See p_inter.c
p_mobj.c
Disable P_EmeraldManager
Power stones, despite their relevance in vanilla Match, are not in SRB2Kart's Battle. No management of nonexistent emeralds is required.
p_setup.c
Everything to do with setting states for starposts
See p_inter.c
p_spec.c
Disable NiGHTS-related material
See p_inter.c
Everything to do with setting states for starposts
See p_inter.c
p_telept.c
Everything to do with setting states for starposts
See p_inter.c
p_tick.c
Disable some team-related material
See g_game.c
Disable P_EmeraldManager
See p_mobj.c
Do not run shields
Shield objects are not run under the vanilla system; the Thunder Shield is a domain-specific recreation using a standard mobjthinker.
Do not run special stages
SRB2Kart does not have special stages.
Comment out Tag mechanisms
See p_inter.c
y_inter.c
Disable some team-related material
See g_game.c
p_user.c
Disable NiGHTS-related material
See p_inter.c
Disable 2d movement for players
2D mode? In a kart racer? :nick:
2018-10-03 16:04:41 +00:00
} */
2014-03-15 16:59:03 +00:00
// Checks whether or not to end a race netgame.
boolean P_CheckRacers ( void )
{
2018-07-18 00:21:36 +00:00
INT32 i , j , numplayersingame = 0 ;
2014-03-15 16:59:03 +00:00
// Check if all the players in the race have finished. If so, end the level.
for ( i = 0 ; i < MAXPLAYERS ; i + + )
{
2018-07-18 00:21:36 +00:00
if ( ! playeringame [ i ] | | players [ i ] . spectator | | players [ i ] . exiting | | ! players [ i ] . lives )
continue ;
break ;
2014-03-15 16:59:03 +00:00
}
if ( i = = MAXPLAYERS ) // finished
{
2020-03-11 06:37:33 +00:00
racecountdown = exitcountdown = 0 ;
2014-03-15 16:59:03 +00:00
return true ;
}
2018-07-25 20:33:03 +00:00
if ( cv_karteliminatelast . value )
2018-07-18 00:21:36 +00:00
{
2018-07-25 20:33:03 +00:00
for ( j = 0 ; j < MAXPLAYERS ; j + + )
2018-07-18 00:21:36 +00:00
{
2018-07-25 20:33:03 +00:00
if ( ! playeringame [ j ] | | players [ j ] . spectator )
2018-07-18 00:21:36 +00:00
continue ;
2018-07-25 20:33:03 +00:00
numplayersingame + + ;
2018-07-18 00:21:36 +00:00
}
2018-10-23 21:48:09 +00:00
if ( numplayersingame > 1 & & nospectategrief > 0 & & numplayersingame > = nospectategrief ) // prevent spectate griefing
2018-07-18 00:21:36 +00:00
{
2018-07-25 20:33:03 +00:00
// check if we just got unlucky and there was only one guy who was a problem
for ( j = i + 1 ; j < MAXPLAYERS ; j + + )
{
if ( ! playeringame [ j ] | | players [ j ] . spectator | | players [ j ] . exiting | | ! players [ j ] . lives )
continue ;
break ;
}
if ( j = = MAXPLAYERS ) // finish anyways, force a time over
{
P_DoTimeOver ( & players [ i ] ) ;
2020-03-11 06:37:33 +00:00
racecountdown = exitcountdown = 0 ;
2018-07-25 20:33:03 +00:00
return true ;
}
2018-07-18 00:21:36 +00:00
}
}
2020-03-11 06:37:33 +00:00
if ( ! racecountdown ) // Check to see if the winners have finished, to set countdown.
2018-11-25 01:59:22 +00:00
{
UINT8 numingame = 0 , numexiting = 0 ;
UINT8 winningpos = 1 ;
for ( i = 0 ; i < MAXPLAYERS ; i + + )
{
if ( ! playeringame [ i ] | | players [ i ] . spectator )
continue ;
numingame + + ;
if ( players [ i ] . exiting )
numexiting + + ;
}
winningpos = max ( 1 , numingame / 2 ) ;
if ( numingame % 2 ) // any remainder?
winningpos + + ;
if ( numexiting > = winningpos )
2020-03-11 06:37:33 +00:00
racecountdown = ( ( ( netgame | | multiplayer ) ? cv_countdowntime . value : 30 ) * TICRATE ) + 1 ; // 30 seconds to finish, get going!
2018-11-25 01:59:22 +00:00
}
2014-03-15 16:59:03 +00:00
return false ;
}
/** Kills an object.
*
* \ param target The victim .
* \ param inflictor The attack weapon . May be NULL ( environmental damage ) .
* \ param source The attacker . May be NULL .
* \ todo Cleanup , refactor , split up .
* \ sa P_DamageMobj
*/
void P_KillMobj ( mobj_t * target , mobj_t * inflictor , mobj_t * source )
{
mobjtype_t item ;
mobj_t * mo ;
2017-05-13 15:14:26 +00:00
//if (inflictor && (inflictor->type == MT_SHELL || inflictor->type == MT_FIREBALL))
// P_SetTarget(&target->tracer, inflictor);
2014-03-15 16:59:03 +00:00
if ( ! useNightsSS & & G_IsSpecialStage ( gamemap ) & & target - > player & & sstimer > 6 )
sstimer = 6 ; // Just let P_Ticker take care of the rest.
if ( target - > flags & ( MF_ENEMY | MF_BOSS ) )
target - > momx = target - > momy = target - > momz = 0 ;
2017-02-07 22:19:04 +00:00
// SRB2kart
if ( target - > type ! = MT_PLAYER & & ! ( target - > flags & MF_MONITOR )
2018-07-23 00:55:18 +00:00
& & ! ( target - > type = = MT_ORBINAUT | | target - > type = = MT_ORBINAUT_SHIELD
2018-06-01 00:51:05 +00:00
| | target - > type = = MT_JAWZ | | target - > type = = MT_JAWZ_DUD | | target - > type = = MT_JAWZ_SHIELD
| | target - > type = = MT_BANANA | | target - > type = = MT_BANANA_SHIELD
2018-10-29 09:00:08 +00:00
| | target - > type = = MT_EGGMANITEM | | target - > type = = MT_EGGMANITEM_SHIELD
2018-10-18 08:43:50 +00:00
| | target - > type = = MT_BALLHOG | | target - > type = = MT_SPB ) ) // kart dead items
2017-02-07 22:19:04 +00:00
target - > flags | = MF_NOGRAVITY ; // Don't drop Tails 03-08-2000
else
target - > flags & = ~ MF_NOGRAVITY ; // lose it if you for whatever reason have it, I'm looking at you shields
//
2014-03-15 16:59:03 +00:00
if ( target - > flags2 & MF2_NIGHTSPULL )
P_SetTarget ( & target - > tracer , NULL ) ;
// dead target is no more shootable
target - > flags & = ~ ( MF_SHOOTABLE | MF_FLOAT | MF_SPECIAL ) ;
target - > flags2 & = ~ ( MF2_SKULLFLY | MF2_NIGHTSPULL ) ;
target - > health = 0 ; // This makes it easy to check if something's dead elsewhere.
# ifdef HAVE_BLUA
if ( LUAh_MobjDeath ( target , inflictor , source ) | | P_MobjWasRemoved ( target ) )
return ;
# endif
2018-06-16 21:54:12 +00:00
// SRB2kart
// I wish I knew a better way to do this
if ( target - > target & & target - > target - > player & & target - > target - > player - > mo )
{
2018-10-29 09:00:08 +00:00
if ( target - > target - > player - > kartstuff [ k_eggmanheld ] & & target - > type = = MT_EGGMANITEM_SHIELD )
2018-06-16 21:54:12 +00:00
target - > target - > player - > kartstuff [ k_eggmanheld ] = 0 ;
2018-06-17 00:42:47 +00:00
if ( target - > target - > player - > kartstuff [ k_itemheld ] )
2018-06-16 21:54:12 +00:00
{
2018-06-17 00:42:47 +00:00
if ( ( target - > type = = MT_BANANA_SHIELD & & target - > target - > player - > kartstuff [ k_itemtype ] = = KITEM_BANANA ) // trail items
2018-09-04 23:14:44 +00:00
| | ( target - > type = = MT_SSMINE_SHIELD & & target - > target - > player - > kartstuff [ k_itemtype ] = = KITEM_MINE )
| | ( target - > type = = MT_SINK_SHIELD & & target - > target - > player - > kartstuff [ k_itemtype ] = = KITEM_KITCHENSINK ) )
2018-06-16 21:54:12 +00:00
{
2018-08-24 14:14:18 +00:00
if ( target - > movedir ! = 0 & & target - > movedir < ( UINT16 ) target - > target - > player - > kartstuff [ k_itemamount ] )
2018-06-16 21:54:12 +00:00
{
2018-06-16 23:57:08 +00:00
if ( target - > target - > hnext )
K_KillBananaChain ( target - > target - > hnext , inflictor , source ) ;
2018-06-16 21:54:12 +00:00
target - > target - > player - > kartstuff [ k_itemamount ] = 0 ;
}
else
target - > target - > player - > kartstuff [ k_itemamount ] - - ;
}
2018-07-23 00:55:18 +00:00
else if ( ( target - > type = = MT_ORBINAUT_SHIELD & & target - > target - > player - > kartstuff [ k_itemtype ] = = KITEM_ORBINAUT ) // orbit items
2018-06-17 00:42:47 +00:00
| | ( target - > type = = MT_JAWZ_SHIELD & & target - > target - > player - > kartstuff [ k_itemtype ] = = KITEM_JAWZ ) )
2018-06-27 19:58:43 +00:00
{
2018-06-25 05:36:21 +00:00
target - > target - > player - > kartstuff [ k_itemamount ] - - ;
2018-06-27 19:58:43 +00:00
if ( target - > lastlook ! = 0 )
{
2018-11-14 21:53:57 +00:00
K_RepairOrbitChain ( target ) ;
2018-06-27 19:58:43 +00:00
}
}
2018-06-19 01:52:26 +00:00
if ( target - > target - > player - > kartstuff [ k_itemamount ] < 0 )
target - > target - > player - > kartstuff [ k_itemamount ] = 0 ;
if ( ! target - > target - > player - > kartstuff [ k_itemamount ] )
target - > target - > player - > kartstuff [ k_itemheld ] = 0 ;
2018-08-06 15:19:07 +00:00
if ( target - > target - > hnext = = target )
P_SetTarget ( & target - > target - > hnext , NULL ) ;
2018-06-16 21:54:12 +00:00
}
}
2021-09-13 03:06:18 +00:00
// Above block does not clean up rocket sneakers when a player dies, so we need to do it here target->target is null when using rocket sneakers
if ( target - > player )
K_DropRocketSneaker ( target - > player ) ;
2018-06-16 21:54:12 +00:00
2014-03-15 16:59:03 +00:00
// Let EVERYONE know what happened to a player! 01-29-2002 Tails
if ( target - > player & & ! target - > player - > spectator )
{
if ( metalrecording ) // Ack! Metal Sonic shouldn't die! Cut the tape, end recording!
2014-03-23 16:00:29 +00:00
G_StopMetalRecording ( ) ;
2017-11-29 23:31:17 +00:00
/*if (gametype == GT_MATCH && cv_match_scoring.value == 0 // note, no team match suicide penalty
2014-03-15 16:59:03 +00:00
& & ( ( target = = source ) | | ( source = = NULL & & inflictor = = NULL ) | | ( source & & ! source - > player ) ) )
2017-02-26 15:19:12 +00:00
{ // Suicide penalty - Not in Kart
2017-11-29 23:31:17 +00:00
if ( target - > player - > score > = 50 )
target - > player - > score - = 50 ;
else
target - > player - > score = 0 ;
} */
2014-03-15 16:59:03 +00:00
target - > flags2 & = ~ MF2_DONTDRAW ;
}
// if killed by a player
if ( source & & source - > player )
{
2018-03-13 05:20:47 +00:00
if ( target - > flags & MF_MONITOR | | target - > type = = MT_RANDOMITEM )
2014-03-15 16:59:03 +00:00
{
P_SetTarget ( & target - > target , source ) ;
source - > player - > numboxes + + ;
2018-03-27 00:36:16 +00:00
if ( cv_itemrespawn . value & & ( netgame | | multiplayer ) )
2017-10-24 04:06:13 +00:00
{
2017-10-26 06:31:01 +00:00
target - > fuse = cv_itemrespawntime . value * TICRATE + 2 ; // Random box generation
2017-10-24 04:06:13 +00:00
}
2014-03-15 16:59:03 +00:00
}
// Award Score Tails
2017-11-29 23:31:17 +00:00
/*{ // Enemies shouldn't award points in Kart
2014-03-15 16:59:03 +00:00
INT32 score = 0 ;
if ( maptol & TOL_NIGHTS ) // Enemies always worth 200, bosses don't do anything.
{
if ( ( target - > flags & MF_ENEMY ) & & ! ( target - > flags & ( MF_MISSILE | MF_BOSS ) ) )
{
score = 200 ;
if ( source - > player - > bonustime )
score * = 2 ;
// Also, add to the link.
// I don't know if NiGHTS did this, but
// Sonic Time Attacked did and it seems like a good enough incentive
// to make people want to actually dash towards/paraloop enemies
if ( + + source - > player - > linkcount > source - > player - > maxlink )
source - > player - > maxlink = source - > player - > linkcount ;
source - > player - > linktimer = 2 * TICRATE ;
}
}
else
{
if ( target - > flags & MF_BOSS )
score = 1000 ;
else if ( ( target - > flags & MF_ENEMY ) & & ! ( target - > flags & MF_MISSILE ) )
{
mobj_t * scoremobj ;
UINT32 scorestate = mobjinfo [ MT_SCORE ] . spawnstate ;
scoremobj = P_SpawnMobj ( target - > x , target - > y , target - > z + ( target - > height / 2 ) , MT_SCORE ) ;
// On ground? No chain starts.
if ( ! source - > player - > powers [ pw_invulnerability ] & & P_IsObjectOnGround ( source ) )
{
source - > player - > scoreadd = 0 ;
score = 100 ;
}
// Mario Mode has Mario-like chain point values
else if ( mariomode ) switch ( + + source - > player - > scoreadd )
{
case 1 : score = 100 ; break ;
case 2 : score = 200 ; scorestate + = 1 ; break ;
case 3 : score = 400 ; scorestate + = 5 ; break ;
case 4 : score = 800 ; scorestate + = 6 ; break ;
case 5 : score = 1000 ; scorestate + = 3 ; break ;
case 6 : score = 2000 ; scorestate + = 7 ; break ;
case 7 : score = 4000 ; scorestate + = 8 ; break ;
case 8 : score = 8000 ; scorestate + = 9 ; break ;
default : // 1up for a chain this long
if ( modeattacking ) // but 1ups don't exist in record attack!
{ // So we just go back to 10k points.
score = 10000 ; scorestate + = 4 ; break ;
}
P_GivePlayerLives ( source - > player , 1 ) ;
P_PlayLivesJingle ( source - > player ) ;
scorestate + = 10 ;
break ;
}
// More Sonic-like point system
else switch ( + + source - > player - > scoreadd )
{
case 1 : score = 100 ; break ;
case 2 : score = 200 ; scorestate + = 1 ; break ;
case 3 : score = 500 ; scorestate + = 2 ; break ;
case 4 : case 5 : case 6 : case 7 : case 8 : case 9 :
case 10 : case 11 : case 12 : case 13 : case 14 :
score = 1000 ; scorestate + = 3 ; break ;
default : score = 10000 ; scorestate + = 4 ; break ;
}
P_SetMobjState ( scoremobj , scorestate ) ;
}
}
P_AddPlayerScore ( source - > player , score ) ;
2017-11-29 23:31:17 +00:00
} */
2014-03-15 16:59:03 +00:00
}
// if a player avatar dies...
if ( target - > player )
{
target - > flags & = ~ ( MF_SOLID | MF_SHOOTABLE ) ; // does not block
P_UnsetThingPosition ( target ) ;
Mammoth commit!
* Deaths in record attack no longer put you into a glitchy singleplayer game-over state that we somehow both kept around and also broke since we branched Kart off of Vanilla..
* Fix non-standard mapscales making the Death Egg respawn octagons dissasemble themselves.
* Allow for MULTIPLE TIME EMBLEMS PER MAP, at least in the emblem UI on the timer. It shows all completed emblems plus the uncompleted emblem up to a total of three.
* Major tweaks to the First Person HUD.
* I know this was your baby, Sal, and some of the changes may prove controversial - so I've put the ones that are likely to cause the most fuss inside an ifndef block, so that you can toggle it as you please with minimal code changes.
* Dontdraw-ness, transparency, and colorization match the player's object!
* Moves around on the screen with respect to the direction of the player object's motion, to make drifting look nicer!
* Flashes the colour of your drift sparks.
* Did a WHOLE bunch of things with respect to music. I'm not sure how to describe this, so I'll go through step-by-step.
* Countdowns now play the drowning music again.
* Removed/disabled extraenous P_RestoreMusics.
* Made map-ending music called by its own function, P_EndingMusic(player_t *player).
* Made the ending music play on the LAST player crossing the finishing line in splitscreen, rather than first.
* Make dead players spinout and clip through the floor, at least until we add the new death anims.
* Fix prior pogo spring usage making dead players fall faster.
* Make the time over countdown use the kart font when not splitscreen with 3 or 4 players.
* Removed a weird bonus HWR_DrawCroppedPatch function signature in the hardware header.
2018-07-16 19:19:30 +00:00
target - > flags | = MF_NOBLOCKMAP | MF_NOCLIPHEIGHT ;
2014-03-15 16:59:03 +00:00
P_SetThingPosition ( target ) ;
if ( ! target - > player - > bot & & ! G_IsSpecialStage ( gamemap )
& & G_GametypeUsesLives ( ) )
{
target - > player - > lives - = 1 ; // Lose a life Tails 03-11-2000
if ( target - > player - > lives < = 0 ) // Tails 03-14-2000
{
2016-07-06 04:09:17 +00:00
if ( P_IsLocalPlayer ( target - > player ) /* && target->player == &players[consoleplayer] */ )
2014-03-15 16:59:03 +00:00
{
S_StopMusic ( ) ; // Stop the Music! Tails 03-14-2000
2016-07-06 04:09:17 +00:00
S_ChangeMusicInternal ( " gmover " , false ) ; // Yousa dead now, Okieday? Tails 03-14-2000
2014-03-15 16:59:03 +00:00
}
}
}
target - > player - > playerstate = PST_DEAD ;
if ( target - > player = = & players [ consoleplayer ] )
{
// don't die in auto map,
// switch view prior to dying
if ( automapactive )
AM_Stop ( ) ;
//added : 22-02-98: recenter view for next life...
2019-04-18 07:08:11 +00:00
localaiming [ 0 ] = 0 ;
2014-03-15 16:59:03 +00:00
}
2019-04-18 07:08:11 +00:00
if ( target - > player = = & players [ displayplayers [ 1 ] ] )
2014-03-15 16:59:03 +00:00
{
// added : 22-02-98: recenter view for next life...
2019-04-18 07:08:11 +00:00
localaiming [ 1 ] = 0 ;
2014-03-15 16:59:03 +00:00
}
2019-04-18 07:08:11 +00:00
if ( target - > player = = & players [ displayplayers [ 2 ] ] )
localaiming [ 2 ] = 0 ;
if ( target - > player = = & players [ displayplayers [ 3 ] ] )
localaiming [ 3 ] = 0 ;
2014-03-15 16:59:03 +00:00
//tag deaths handled differently in suicide cases. Don't count spectators!
Nuke a bunch of iteration things that have no purpose in SRB2Kart. A full explanation of my reasoning and what it affects is as follows.
p_inter.c -
Everything to do with setting states for starposts
In SRB2Kart, starposts are invisble. We don't need to loop through all thinkers just to set their states when there's no visible effect of the state-setting. In addition, it has no consequences for gameplay - starposts have long been silent here, and all checking is done regarding their health, not their state.
Remove extremely low-traffic conditionals (MT_FLINGEMERALD collision height extension, for example)
These objects serve no functional purpose during regular SRB2Kart gameplay. Why should every other object have to pay an admittedly minor performance hit just for them?
Disable all mechanisms of damaging bosses or enemies with the player's physical contact
With the exception of Sapphire Coast, no MF_ENEMY objects exist in the entirety of the standard roster. In addition, the conditions for damaging the enemies were impossible to achieve, because they required vanilla SRB2 mechanics such as "jumping", "spindashing", or "super". Therefore, they can be safely commented out.
Disable NiGHTS-related material (excepting bumper, hoop, and wing-emblem objects)
NiGHTS is fundamentally incompatible with regular kart gameplay and I believe was already broken. Therefore, any mechanism which enters, aids, or abets it can be safely disabled.
Comment out Tag mechanisms
Tag is the only vanilla multiplayer gametype which has sufficient gameplay depth and complexity (HEYOOOOOOOOO) to require dedicated thinking in and of itself in order to manage. This thinking is irrelevant to Kart's functioning, and can be neutered easily.
d_clisrv.c
Comment out Tag mechanisms
See p_inter.c
d_netcmd.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
When investigating for references to NiGHTS material, I discovered that these remained untouched. In order to present a more coherent game, I have hidden the ones that serve no purpose for us.
Comment out Tag mechanisms
See p_inter.c
g_game.c
Disable NiGHTS-related material
See p_inter.c
Disable some team-related material
Teams are not present in SRB2Kart at present. Obviously we'd want to reconsider for future, but it doesn't need to be run right now.
Everything to do with setting states for starposts
See p_inter.c
m_cheat.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
See d_netcmd.c
p_map.c
Remove extremely low-traffic conditionals (MT_EGGSHIELD collision, for example)
See p_inter.c
Disable NiGHTS-related material
See p_inter.c
p_mobj.c
Disable P_EmeraldManager
Power stones, despite their relevance in vanilla Match, are not in SRB2Kart's Battle. No management of nonexistent emeralds is required.
p_setup.c
Everything to do with setting states for starposts
See p_inter.c
p_spec.c
Disable NiGHTS-related material
See p_inter.c
Everything to do with setting states for starposts
See p_inter.c
p_telept.c
Everything to do with setting states for starposts
See p_inter.c
p_tick.c
Disable some team-related material
See g_game.c
Disable P_EmeraldManager
See p_mobj.c
Do not run shields
Shield objects are not run under the vanilla system; the Thunder Shield is a domain-specific recreation using a standard mobjthinker.
Do not run special stages
SRB2Kart does not have special stages.
Comment out Tag mechanisms
See p_inter.c
y_inter.c
Disable some team-related material
See g_game.c
p_user.c
Disable NiGHTS-related material
See p_inter.c
Disable 2d movement for players
2D mode? In a kart racer? :nick:
2018-10-03 16:04:41 +00:00
/*if (G_TagGametype()
2014-03-15 16:59:03 +00:00
& & ! ( target - > player - > pflags & PF_TAGIT ) & & ( ! source | | ! source - > player ) & & ! ( target - > player - > spectator ) )
{
// if you accidentally die before you run out of time to hide, ignore it.
// allow them to try again, rather than sitting the whole thing out.
if ( leveltime > = hidetime * TICRATE )
{
2016-07-06 04:09:17 +00:00
if ( gametype = = GT_TAG ) //suiciding in survivor makes you IT.
2014-03-15 16:59:03 +00:00
{
target - > player - > pflags | = PF_TAGIT ;
CONS_Printf ( M_GetText ( " %s is now IT! \n " ) , player_names [ target - > player - players ] ) ; // Tell everyone who is it!
P_CheckSurvivors ( ) ;
}
else
{
if ( ! ( target - > player - > pflags & PF_TAGGED ) )
{
//otherwise, increment the tagger's score.
//in hide and seek, suiciding players are counted as found.
INT32 w ;
for ( w = 0 ; w < MAXPLAYERS ; w + + )
{
if ( players [ w ] . pflags & PF_TAGIT )
2017-10-22 21:26:43 +00:00
P_AddPlayerScore ( & players [ w ] , 1 ) ;
2014-03-15 16:59:03 +00:00
}
target - > player - > pflags | = PF_TAGGED ;
CONS_Printf ( M_GetText ( " %s was found! \n " ) , player_names [ target - > player - players ] ) ;
P_CheckSurvivors ( ) ;
}
}
}
}
Nuke a bunch of iteration things that have no purpose in SRB2Kart. A full explanation of my reasoning and what it affects is as follows.
p_inter.c -
Everything to do with setting states for starposts
In SRB2Kart, starposts are invisble. We don't need to loop through all thinkers just to set their states when there's no visible effect of the state-setting. In addition, it has no consequences for gameplay - starposts have long been silent here, and all checking is done regarding their health, not their state.
Remove extremely low-traffic conditionals (MT_FLINGEMERALD collision height extension, for example)
These objects serve no functional purpose during regular SRB2Kart gameplay. Why should every other object have to pay an admittedly minor performance hit just for them?
Disable all mechanisms of damaging bosses or enemies with the player's physical contact
With the exception of Sapphire Coast, no MF_ENEMY objects exist in the entirety of the standard roster. In addition, the conditions for damaging the enemies were impossible to achieve, because they required vanilla SRB2 mechanics such as "jumping", "spindashing", or "super". Therefore, they can be safely commented out.
Disable NiGHTS-related material (excepting bumper, hoop, and wing-emblem objects)
NiGHTS is fundamentally incompatible with regular kart gameplay and I believe was already broken. Therefore, any mechanism which enters, aids, or abets it can be safely disabled.
Comment out Tag mechanisms
Tag is the only vanilla multiplayer gametype which has sufficient gameplay depth and complexity (HEYOOOOOOOOO) to require dedicated thinking in and of itself in order to manage. This thinking is irrelevant to Kart's functioning, and can be neutered easily.
d_clisrv.c
Comment out Tag mechanisms
See p_inter.c
d_netcmd.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
When investigating for references to NiGHTS material, I discovered that these remained untouched. In order to present a more coherent game, I have hidden the ones that serve no purpose for us.
Comment out Tag mechanisms
See p_inter.c
g_game.c
Disable NiGHTS-related material
See p_inter.c
Disable some team-related material
Teams are not present in SRB2Kart at present. Obviously we'd want to reconsider for future, but it doesn't need to be run right now.
Everything to do with setting states for starposts
See p_inter.c
m_cheat.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
See d_netcmd.c
p_map.c
Remove extremely low-traffic conditionals (MT_EGGSHIELD collision, for example)
See p_inter.c
Disable NiGHTS-related material
See p_inter.c
p_mobj.c
Disable P_EmeraldManager
Power stones, despite their relevance in vanilla Match, are not in SRB2Kart's Battle. No management of nonexistent emeralds is required.
p_setup.c
Everything to do with setting states for starposts
See p_inter.c
p_spec.c
Disable NiGHTS-related material
See p_inter.c
Everything to do with setting states for starposts
See p_inter.c
p_telept.c
Everything to do with setting states for starposts
See p_inter.c
p_tick.c
Disable some team-related material
See g_game.c
Disable P_EmeraldManager
See p_mobj.c
Do not run shields
Shield objects are not run under the vanilla system; the Thunder Shield is a domain-specific recreation using a standard mobjthinker.
Do not run special stages
SRB2Kart does not have special stages.
Comment out Tag mechanisms
See p_inter.c
y_inter.c
Disable some team-related material
See g_game.c
p_user.c
Disable NiGHTS-related material
See p_inter.c
Disable 2d movement for players
2D mode? In a kart racer? :nick:
2018-10-03 16:04:41 +00:00
else */ if ( G_BattleGametype ( ) )
2018-07-03 19:14:47 +00:00
K_CheckBumpers ( ) ;
Mammoth commit!
* Deaths in record attack no longer put you into a glitchy singleplayer game-over state that we somehow both kept around and also broke since we branched Kart off of Vanilla..
* Fix non-standard mapscales making the Death Egg respawn octagons dissasemble themselves.
* Allow for MULTIPLE TIME EMBLEMS PER MAP, at least in the emblem UI on the timer. It shows all completed emblems plus the uncompleted emblem up to a total of three.
* Major tweaks to the First Person HUD.
* I know this was your baby, Sal, and some of the changes may prove controversial - so I've put the ones that are likely to cause the most fuss inside an ifndef block, so that you can toggle it as you please with minimal code changes.
* Dontdraw-ness, transparency, and colorization match the player's object!
* Moves around on the screen with respect to the direction of the player object's motion, to make drifting look nicer!
* Flashes the colour of your drift sparks.
* Did a WHOLE bunch of things with respect to music. I'm not sure how to describe this, so I'll go through step-by-step.
* Countdowns now play the drowning music again.
* Removed/disabled extraenous P_RestoreMusics.
* Made map-ending music called by its own function, P_EndingMusic(player_t *player).
* Made the ending music play on the LAST player crossing the finishing line in splitscreen, rather than first.
* Make dead players spinout and clip through the floor, at least until we add the new death anims.
* Fix prior pogo spring usage making dead players fall faster.
* Make the time over countdown use the kart font when not splitscreen with 3 or 4 players.
* Removed a weird bonus HWR_DrawCroppedPatch function signature in the hardware header.
2018-07-16 19:19:30 +00:00
target - > player - > kartstuff [ k_pogospring ] = 0 ;
2014-03-15 16:59:03 +00:00
}
if ( source & & target & & target - > player & & source - > player )
P_PlayVictorySound ( source ) ; // Killer laughs at you. LAUGHS! BWAHAHAHA!
// Drop stuff.
// This determines the kind of object spawned
// during the death frame of a thing.
if ( ! mariomode // Don't show birds, etc. in Mario Mode Tails 12-23-2001
& & target - > flags & MF_ENEMY )
{
if ( cv_soniccd . value )
item = MT_SEED ;
else
{
INT32 prandom ;
switch ( target - > type )
{
case MT_REDCRAWLA :
case MT_GOLDBUZZ :
case MT_SKIM :
case MT_UNIDUS :
item = MT_BUNNY ;
break ;
case MT_BLUECRAWLA :
case MT_JETTBOMBER :
case MT_GFZFISH :
item = MT_BIRD ;
break ;
case MT_JETTGUNNER :
case MT_CRAWLACOMMANDER :
case MT_REDBUZZ :
2014-08-27 03:56:30 +00:00
case MT_DETON :
2014-03-15 16:59:03 +00:00
item = MT_MOUSE ;
break ;
case MT_GSNAPPER :
case MT_EGGGUARD :
case MT_SPRINGSHELL :
item = MT_COW ;
break ;
case MT_MINUS :
case MT_VULTURE :
case MT_POINTY :
case MT_YELLOWSHELL :
item = MT_CHICKEN ;
break ;
case MT_AQUABUZZ :
item = MT_REDBIRD ;
break ;
default :
if ( target - > info - > doomednum )
2016-07-06 04:09:17 +00:00
prandom = target - > info - > doomednum % 5 ; // "Random" animal for new enemies.
else
prandom = P_RandomKey ( 5 ) ; // No placable object, just use a random number.
switch ( prandom )
2014-03-15 16:59:03 +00:00
{
default : item = MT_BUNNY ; break ;
case 1 : item = MT_BIRD ; break ;
case 2 : item = MT_MOUSE ; break ;
case 3 : item = MT_COW ; break ;
case 4 : item = MT_CHICKEN ; break ;
}
break ;
}
}
mo = P_SpawnMobj ( target - > x , target - > y , target - > z + ( target - > height / 2 ) - FixedMul ( mobjinfo [ item ] . height / 2 , target - > scale ) , item ) ;
mo - > destscale = target - > scale ;
P_SetScale ( mo , mo - > destscale ) ;
}
// Other death animation effects
else switch ( target - > type )
{
case MT_BOUNCEPICKUP :
case MT_RAILPICKUP :
case MT_AUTOPICKUP :
case MT_EXPLODEPICKUP :
case MT_SCATTERPICKUP :
case MT_GRENADEPICKUP :
P_SetObjectMomZ ( target , FRACUNIT , false ) ;
target - > fuse = target - > info - > damage ;
break ;
case MT_EGGTRAP :
// Time for birdies! Yaaaaaaaay!
target - > fuse = TICRATE * 2 ;
break ;
2014-08-04 03:49:33 +00:00
case MT_PLAYER :
target - > momx = target - > momy = target - > momz = 0 ;
2018-10-23 21:48:09 +00:00
if ( target - > player & & target - > player - > pflags & PF_TIMEOVER )
break ;
target - > fuse = TICRATE * 3 ; // timer before mobj disappears from view (even if not an actual player)
2014-08-04 03:49:33 +00:00
if ( ! ( source & & source - > type = = MT_NULL & & source - > threshold = = 42 ) ) // Don't jump up when drowning
P_SetObjectMomZ ( target , 14 * FRACUNIT , false ) ;
if ( source & & source - > type = = MT_NULL & & source - > threshold = = 42 ) // drowned
S_StartSound ( target , sfx_drown ) ;
else if ( source & & ( source - > type = = MT_SPIKE | | ( source - > type = = MT_NULL & & source - > threshold = = 43 ) ) ) // Spikes
S_StartSound ( target , sfx_spkdth ) ;
else
P_PlayDeathSound ( target ) ;
break ;
2018-10-29 09:00:08 +00:00
// SRB2Kart:
case MT_SMK_ICEBLOCK :
{
mobj_t * cur = target - > hnext ;
while ( cur & & ! P_MobjWasRemoved ( cur ) )
{
P_SetMobjState ( cur , S_SMK_ICEBLOCK2 ) ;
cur = cur - > hnext ;
}
target - > fuse = 10 ;
S_StartSound ( target , sfx_s3k80 ) ;
}
break ;
2014-03-15 16:59:03 +00:00
default :
break ;
}
// Enemy drops that ALWAYS occur regardless of mode
if ( target - > type = = MT_AQUABUZZ ) // Additionally spawns breathable bubble for players to get
{
if ( inflictor & & inflictor - > player // did a player kill you? Spawn relative to the player so he's bound to get it
& & P_AproxDistance ( inflictor - > x - target - > x , inflictor - > y - target - > y ) < = inflictor - > radius + target - > radius + FixedMul ( 8 * FRACUNIT , inflictor - > scale ) // close enough?
& & inflictor - > z < = target - > z + target - > height + FixedMul ( 8 * FRACUNIT , inflictor - > scale )
& & inflictor - > z + inflictor - > height > = target - > z - FixedMul ( 8 * FRACUNIT , inflictor - > scale ) )
mo = P_SpawnMobj ( inflictor - > x + inflictor - > momx , inflictor - > y + inflictor - > momy , inflictor - > z + ( inflictor - > height / 2 ) + inflictor - > momz , MT_EXTRALARGEBUBBLE ) ;
else
mo = P_SpawnMobj ( target - > x , target - > y , target - > z , MT_EXTRALARGEBUBBLE ) ;
mo - > destscale = target - > scale ;
P_SetScale ( mo , mo - > destscale ) ;
}
else if ( target - > type = = MT_YELLOWSHELL ) // Spawns a spring that falls to the ground
{
mobjtype_t spawnspring = MT_YELLOWSPRING ;
fixed_t spawnheight = target - > z ;
if ( ! ( target - > eflags & MFE_VERTICALFLIP ) )
spawnheight + = target - > height ;
mo = P_SpawnMobj ( target - > x , target - > y , spawnheight , spawnspring ) ;
mo - > destscale = target - > scale ;
P_SetScale ( mo , mo - > destscale ) ;
if ( target - > flags2 & MF2_OBJECTFLIP )
mo - > flags2 | = MF2_OBJECTFLIP ;
}
2014-08-04 03:49:33 +00:00
if ( target - > type = = MT_EGGMOBILE3 )
{
thinker_t * th ;
UINT32 i = 0 ; // to check how many clones we've removed
// scan the thinkers to make sure all the old pinch dummies are gone on death
// this can happen if the boss was hurt earlier than expected
for ( th = thinkercap . next ; th ! = & thinkercap ; th = th - > next )
{
if ( th - > function . acp1 ! = ( actionf_p1 ) P_MobjThinker )
continue ;
mo = ( mobj_t * ) th ;
if ( mo - > type = = ( mobjtype_t ) target - > info - > mass & & mo - > tracer = = target )
{
P_RemoveMobj ( mo ) ;
i + + ;
}
if ( i = = 2 ) // we've already removed 2 of these, let's stop now
break ;
}
}
Dropping items!
* Shield Drop...
* Whatever you've got orbiting or trailing you, DROP THEM WHERE THEY STAND. (Except for the ghost sink. That one's OK.)
* Pops your Thunder Shield.
* Happens upon ANY hit, except for deathpits.
* HUD Drop...
* Also does the above, except for the Thunder Shield thing.
* If there's any item left in your item box, pop it out as a little hovering, rotating Minecraft item!
* You can pick up the Minecraft item by driving over it if your item box is sufficiently empty, or the item which is contained within it is of the same type.
* Happens upon Size Down and battle elimination.
* Can also be forced on with `cv_kartdebughuddrop on`!
* Some other random stuff.
* Fix a bunch of `a->scale = b`'s into `P_SetScale(a, b)` form, for maximum validity.
* Make K_CleanHnextList and K_UpdateHnextList one function, since they only differed by one continue clause (and the type of their input parameter).
* Allow shrunken players to pick up item boxes again.
* Fix MF_NOCLIPTHING. (Gonna pass this fix to vanilla when I get the chance, too.)
* Break NiGHTS a little through my machinations.
2018-09-06 21:17:29 +00:00
if ( ( target - > type = = MT_JAWZ | | target - > type = = MT_JAWZ_DUD | | target - > type = = MT_JAWZ_SHIELD ) & & ! ( target - > flags2 & MF2_AMBUSH ) )
{
target - > z + = P_MobjFlip ( target ) * 20 * target - > scale ;
}
2018-10-29 09:00:08 +00:00
// kill tracer
if ( target - > type = = MT_FROGGER )
{
if ( target - > tracer & & ! P_MobjWasRemoved ( target - > tracer ) )
P_KillMobj ( target - > tracer , inflictor , source ) ;
}
if ( target - > type = = MT_FROGGER | | target - > type = = MT_ROBRA_HEAD | | target - > type = = MT_BLUEROBRA_HEAD ) // clean hnext list
{
mobj_t * cur = target - > hnext ;
while ( cur & & ! P_MobjWasRemoved ( cur ) )
{
P_KillMobj ( cur , inflictor , source ) ;
cur = cur - > hnext ;
}
}
// Bounce up on death
if ( target - > type = = MT_SMK_PIPE | | target - > type = = MT_SMK_MOLE | | target - > type = = MT_SMK_THWOMP )
{
target - > flags & = ( ~ MF_NOGRAVITY ) ;
if ( target - > eflags & MFE_VERTICALFLIP )
target - > z - = target - > height ;
else
target - > z + = target - > height ;
S_StartSound ( target , target - > info - > deathsound ) ;
P_SetObjectMomZ ( target , 8 < < FRACBITS , false ) ;
if ( inflictor )
P_InstaThrust ( target , R_PointToAngle2 ( inflictor - > x , inflictor - > y , target - > x , target - > y ) + ANGLE_90 , 16 < < FRACBITS ) ;
}
2014-03-15 16:59:03 +00:00
if ( target - > type = = MT_SPIKE & & inflictor & & target - > info - > deathstate ! = S_NULL )
{
const fixed_t x = target - > x , y = target - > y , z = target - > z ;
const fixed_t scale = target - > scale ;
const boolean flip = ( target - > eflags & MFE_VERTICALFLIP ) = = MFE_VERTICALFLIP ;
S_StartSound ( target , target - > info - > deathsound ) ;
P_SetMobjState ( target , target - > info - > deathstate ) ;
target - > health = 0 ;
target - > angle = inflictor - > angle + ANGLE_90 ;
P_UnsetThingPosition ( target ) ;
target - > flags = MF_NOCLIP ;
target - > x + = P_ReturnThrustX ( target , target - > angle , FixedMul ( 8 * FRACUNIT , target - > scale ) ) ;
target - > y + = P_ReturnThrustY ( target , target - > angle , FixedMul ( 8 * FRACUNIT , target - > scale ) ) ;
if ( flip )
target - > z - = FixedMul ( 12 * FRACUNIT , target - > scale ) ;
else
target - > z + = FixedMul ( 12 * FRACUNIT , target - > scale ) ;
P_SetThingPosition ( target ) ;
P_InstaThrust ( target , target - > angle , FixedMul ( 2 * FRACUNIT , target - > scale ) ) ;
target - > momz = FixedMul ( 7 * FRACUNIT , target - > scale ) ;
if ( flip )
target - > momz = - target - > momz ;
if ( flip )
{
target = P_SpawnMobj ( x , y , z - FixedMul ( 12 * FRACUNIT , target - > scale ) , MT_SPIKE ) ;
target - > eflags | = MFE_VERTICALFLIP ;
}
else
target = P_SpawnMobj ( x , y , z + FixedMul ( 12 * FRACUNIT , target - > scale ) , MT_SPIKE ) ;
P_SetMobjState ( target , target - > info - > deathstate ) ;
target - > health = 0 ;
target - > angle = inflictor - > angle - ANGLE_90 ;
target - > destscale = scale ;
P_SetScale ( target , scale ) ;
P_UnsetThingPosition ( target ) ;
target - > flags = MF_NOCLIP ;
target - > x + = P_ReturnThrustX ( target , target - > angle , FixedMul ( 8 * FRACUNIT , target - > scale ) ) ;
target - > y + = P_ReturnThrustY ( target , target - > angle , FixedMul ( 8 * FRACUNIT , target - > scale ) ) ;
P_SetThingPosition ( target ) ;
P_InstaThrust ( target , target - > angle , FixedMul ( 2 * FRACUNIT , target - > scale ) ) ;
target - > momz = FixedMul ( 7 * FRACUNIT , target - > scale ) ;
if ( flip )
target - > momz = - target - > momz ;
if ( target - > info - > xdeathstate ! = S_NULL )
{
target = P_SpawnMobj ( x , y , z , MT_SPIKE ) ;
if ( flip )
target - > eflags | = MFE_VERTICALFLIP ;
P_SetMobjState ( target , target - > info - > xdeathstate ) ;
target - > health = 0 ;
target - > angle = inflictor - > angle + ANGLE_90 ;
target - > destscale = scale ;
P_SetScale ( target , scale ) ;
P_UnsetThingPosition ( target ) ;
target - > flags = MF_NOCLIP ;
target - > x + = P_ReturnThrustX ( target , target - > angle , FixedMul ( 8 * FRACUNIT , target - > scale ) ) ;
target - > y + = P_ReturnThrustY ( target , target - > angle , FixedMul ( 8 * FRACUNIT , target - > scale ) ) ;
P_SetThingPosition ( target ) ;
P_InstaThrust ( target , target - > angle , FixedMul ( 4 * FRACUNIT , target - > scale ) ) ;
target - > momz = FixedMul ( 6 * FRACUNIT , target - > scale ) ;
if ( flip )
target - > momz = - target - > momz ;
target = P_SpawnMobj ( x , y , z , MT_SPIKE ) ;
if ( flip )
target - > eflags | = MFE_VERTICALFLIP ;
P_SetMobjState ( target , target - > info - > xdeathstate ) ;
target - > health = 0 ;
target - > angle = inflictor - > angle - ANGLE_90 ;
target - > destscale = scale ;
P_SetScale ( target , scale ) ;
P_UnsetThingPosition ( target ) ;
target - > flags = MF_NOCLIP ;
target - > x + = P_ReturnThrustX ( target , target - > angle , FixedMul ( 8 * FRACUNIT , target - > scale ) ) ;
target - > y + = P_ReturnThrustY ( target , target - > angle , FixedMul ( 8 * FRACUNIT , target - > scale ) ) ;
P_SetThingPosition ( target ) ;
P_InstaThrust ( target , target - > angle , FixedMul ( 4 * FRACUNIT , target - > scale ) ) ;
target - > momz = FixedMul ( 6 * FRACUNIT , target - > scale ) ;
if ( flip )
target - > momz = - target - > momz ;
}
}
else if ( target - > player )
P_SetPlayerMobjState ( target , target - > info - > deathstate ) ;
else
# ifdef DEBUG_NULL_DEATHSTATE
P_SetMobjState ( target , S_NULL ) ;
# else
P_SetMobjState ( target , target - > info - > deathstate ) ;
# endif
/** \note For player, the above is redundant because of P_SetMobjState (target, S_PLAY_DIE1)
in P_DamageMobj ( )
Graue 12 - 22 - 2003 */
}
static inline void P_NiGHTSDamage ( mobj_t * target , mobj_t * source )
{
player_t * player = target - > player ;
tic_t oldnightstime = player - > nightstime ;
if ( ! player - > powers [ pw_flashing ]
& & ! ( player - > pflags & PF_GODMODE ) )
{
angle_t fa ;
player - > angle_pos = player - > old_angle_pos ;
player - > speed / = 5 ;
player - > flyangle + = 180 ; // Shuffle's BETTERNIGHTSMOVEMENT?
player - > flyangle % = 360 ;
2018-03-04 20:27:52 +00:00
if ( G_RaceGametype ( ) )
2014-03-15 16:59:03 +00:00
player - > drillmeter - = 5 * 20 ;
else
{
if ( source & & source - > player )
{
if ( player - > nightstime > 20 * TICRATE )
player - > nightstime - = 20 * TICRATE ;
else
player - > nightstime = 1 ;
}
else
{
if ( player - > nightstime > 5 * TICRATE )
player - > nightstime - = 5 * TICRATE ;
else
player - > nightstime = 1 ;
}
}
if ( player - > pflags & PF_TRANSFERTOCLOSEST )
{
target - > momx = - target - > momx ;
target - > momy = - target - > momy ;
}
else
{
fa = player - > old_angle_pos > > ANGLETOFINESHIFT ;
target - > momx = FixedMul ( FINECOSINE ( fa ) , target - > target - > radius ) ;
target - > momy = FixedMul ( FINESINE ( fa ) , target - > target - > radius ) ;
}
2018-08-11 04:12:41 +00:00
player - > powers [ pw_flashing ] = K_GetKartFlashing ( player ) ;
2014-03-15 16:59:03 +00:00
P_SetMobjState ( target - > tracer , S_NIGHTSHURT1 ) ;
S_StartSound ( target , sfx_nghurt ) ;
if ( oldnightstime > 10 * TICRATE
& & player - > nightstime < 10 * TICRATE )
{
//S_StartSound(NULL, sfx_timeup); // that creepy "out of time" music from NiGHTS. Dummied out, as some on the dev team thought it wasn't Sonic-y enough (Mystic, notably). Uncomment to restore. -SH
2016-07-06 04:09:17 +00:00
S_ChangeMusicInternal ( " drown " , false ) ;
2014-03-15 16:59:03 +00:00
}
}
}
static inline boolean P_TagDamage ( mobj_t * target , mobj_t * inflictor , mobj_t * source , INT32 damage )
{
player_t * player = target - > player ;
( void ) damage ; //unused parm
// If flashing or invulnerable, ignore the tag,
if ( player - > powers [ pw_flashing ] | | player - > powers [ pw_invulnerability ] )
return false ;
// Ignore IT players shooting each other, unless friendlyfire is on.
if ( ( player - > pflags & PF_TAGIT & & ! ( cv_friendlyfire . value & &
source & & source - > player & & source - > player - > pflags & PF_TAGIT ) ) )
return false ;
// Don't allow any damage before the round starts.
if ( leveltime < = hidetime * TICRATE )
return false ;
// Don't allow players on the same team to hurt one another,
// unless cv_friendlyfire is on.
if ( ! cv_friendlyfire . value & & ( player - > pflags & PF_TAGIT ) = = ( source - > player - > pflags & PF_TAGIT ) )
{
if ( ! ( inflictor - > flags & MF_FIRE ) )
P_GivePlayerRings ( player , 1 ) ;
2014-04-14 05:14:58 +00:00
if ( inflictor - > flags2 & MF2_BOUNCERING )
2016-07-06 04:09:17 +00:00
inflictor - > fuse = 0 ; // bounce ring disappears at -1 not 0
2014-03-15 16:59:03 +00:00
return false ;
}
// The tag occurs so long as you aren't shooting another tagger with friendlyfire on.
Nuke a bunch of iteration things that have no purpose in SRB2Kart. A full explanation of my reasoning and what it affects is as follows.
p_inter.c -
Everything to do with setting states for starposts
In SRB2Kart, starposts are invisble. We don't need to loop through all thinkers just to set their states when there's no visible effect of the state-setting. In addition, it has no consequences for gameplay - starposts have long been silent here, and all checking is done regarding their health, not their state.
Remove extremely low-traffic conditionals (MT_FLINGEMERALD collision height extension, for example)
These objects serve no functional purpose during regular SRB2Kart gameplay. Why should every other object have to pay an admittedly minor performance hit just for them?
Disable all mechanisms of damaging bosses or enemies with the player's physical contact
With the exception of Sapphire Coast, no MF_ENEMY objects exist in the entirety of the standard roster. In addition, the conditions for damaging the enemies were impossible to achieve, because they required vanilla SRB2 mechanics such as "jumping", "spindashing", or "super". Therefore, they can be safely commented out.
Disable NiGHTS-related material (excepting bumper, hoop, and wing-emblem objects)
NiGHTS is fundamentally incompatible with regular kart gameplay and I believe was already broken. Therefore, any mechanism which enters, aids, or abets it can be safely disabled.
Comment out Tag mechanisms
Tag is the only vanilla multiplayer gametype which has sufficient gameplay depth and complexity (HEYOOOOOOOOO) to require dedicated thinking in and of itself in order to manage. This thinking is irrelevant to Kart's functioning, and can be neutered easily.
d_clisrv.c
Comment out Tag mechanisms
See p_inter.c
d_netcmd.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
When investigating for references to NiGHTS material, I discovered that these remained untouched. In order to present a more coherent game, I have hidden the ones that serve no purpose for us.
Comment out Tag mechanisms
See p_inter.c
g_game.c
Disable NiGHTS-related material
See p_inter.c
Disable some team-related material
Teams are not present in SRB2Kart at present. Obviously we'd want to reconsider for future, but it doesn't need to be run right now.
Everything to do with setting states for starposts
See p_inter.c
m_cheat.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
See d_netcmd.c
p_map.c
Remove extremely low-traffic conditionals (MT_EGGSHIELD collision, for example)
See p_inter.c
Disable NiGHTS-related material
See p_inter.c
p_mobj.c
Disable P_EmeraldManager
Power stones, despite their relevance in vanilla Match, are not in SRB2Kart's Battle. No management of nonexistent emeralds is required.
p_setup.c
Everything to do with setting states for starposts
See p_inter.c
p_spec.c
Disable NiGHTS-related material
See p_inter.c
Everything to do with setting states for starposts
See p_inter.c
p_telept.c
Everything to do with setting states for starposts
See p_inter.c
p_tick.c
Disable some team-related material
See g_game.c
Disable P_EmeraldManager
See p_mobj.c
Do not run shields
Shield objects are not run under the vanilla system; the Thunder Shield is a domain-specific recreation using a standard mobjthinker.
Do not run special stages
SRB2Kart does not have special stages.
Comment out Tag mechanisms
See p_inter.c
y_inter.c
Disable some team-related material
See g_game.c
p_user.c
Disable NiGHTS-related material
See p_inter.c
Disable 2d movement for players
2D mode? In a kart racer? :nick:
2018-10-03 16:04:41 +00:00
/*if (source->player->pflags & PF_TAGIT && !(player->pflags & PF_TAGIT))
2014-03-15 16:59:03 +00:00
{
2017-10-22 21:26:43 +00:00
P_AddPlayerScore ( source - > player , 1 ) ; //award points to tagger.
2014-03-15 16:59:03 +00:00
if ( gametype = = GT_TAG ) //survivor
{
player - > pflags | = PF_TAGIT ; //in survivor, the player becomes IT and helps hunt down the survivors.
CONS_Printf ( M_GetText ( " %s is now IT! \n " ) , player_names [ player - players ] ) ; // Tell everyone who is it!
}
else
{
player - > pflags | = PF_TAGGED ; //in hide and seek, the player is tagged and stays stationary.
CONS_Printf ( M_GetText ( " %s was found! \n " ) , player_names [ player - players ] ) ; // Tell everyone who is it!
}
//checks if tagger has tagged all players, if so, end round early.
P_CheckSurvivors ( ) ;
Nuke a bunch of iteration things that have no purpose in SRB2Kart. A full explanation of my reasoning and what it affects is as follows.
p_inter.c -
Everything to do with setting states for starposts
In SRB2Kart, starposts are invisble. We don't need to loop through all thinkers just to set their states when there's no visible effect of the state-setting. In addition, it has no consequences for gameplay - starposts have long been silent here, and all checking is done regarding their health, not their state.
Remove extremely low-traffic conditionals (MT_FLINGEMERALD collision height extension, for example)
These objects serve no functional purpose during regular SRB2Kart gameplay. Why should every other object have to pay an admittedly minor performance hit just for them?
Disable all mechanisms of damaging bosses or enemies with the player's physical contact
With the exception of Sapphire Coast, no MF_ENEMY objects exist in the entirety of the standard roster. In addition, the conditions for damaging the enemies were impossible to achieve, because they required vanilla SRB2 mechanics such as "jumping", "spindashing", or "super". Therefore, they can be safely commented out.
Disable NiGHTS-related material (excepting bumper, hoop, and wing-emblem objects)
NiGHTS is fundamentally incompatible with regular kart gameplay and I believe was already broken. Therefore, any mechanism which enters, aids, or abets it can be safely disabled.
Comment out Tag mechanisms
Tag is the only vanilla multiplayer gametype which has sufficient gameplay depth and complexity (HEYOOOOOOOOO) to require dedicated thinking in and of itself in order to manage. This thinking is irrelevant to Kart's functioning, and can be neutered easily.
d_clisrv.c
Comment out Tag mechanisms
See p_inter.c
d_netcmd.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
When investigating for references to NiGHTS material, I discovered that these remained untouched. In order to present a more coherent game, I have hidden the ones that serve no purpose for us.
Comment out Tag mechanisms
See p_inter.c
g_game.c
Disable NiGHTS-related material
See p_inter.c
Disable some team-related material
Teams are not present in SRB2Kart at present. Obviously we'd want to reconsider for future, but it doesn't need to be run right now.
Everything to do with setting states for starposts
See p_inter.c
m_cheat.c
Disable several devmode commands which are irrelevant to SRB2Kart gameplay
See d_netcmd.c
p_map.c
Remove extremely low-traffic conditionals (MT_EGGSHIELD collision, for example)
See p_inter.c
Disable NiGHTS-related material
See p_inter.c
p_mobj.c
Disable P_EmeraldManager
Power stones, despite their relevance in vanilla Match, are not in SRB2Kart's Battle. No management of nonexistent emeralds is required.
p_setup.c
Everything to do with setting states for starposts
See p_inter.c
p_spec.c
Disable NiGHTS-related material
See p_inter.c
Everything to do with setting states for starposts
See p_inter.c
p_telept.c
Everything to do with setting states for starposts
See p_inter.c
p_tick.c
Disable some team-related material
See g_game.c
Disable P_EmeraldManager
See p_mobj.c
Do not run shields
Shield objects are not run under the vanilla system; the Thunder Shield is a domain-specific recreation using a standard mobjthinker.
Do not run special stages
SRB2Kart does not have special stages.
Comment out Tag mechanisms
See p_inter.c
y_inter.c
Disable some team-related material
See g_game.c
p_user.c
Disable NiGHTS-related material
See p_inter.c
Disable 2d movement for players
2D mode? In a kart racer? :nick:
2018-10-03 16:04:41 +00:00
} */
2014-03-15 16:59:03 +00:00
P_DoPlayerPain ( player , source , inflictor ) ;
// Check for a shield
if ( player - > powers [ pw_shield ] )
{
P_RemoveShield ( player ) ;
S_StartSound ( target , sfx_shldls ) ;
return true ;
}
if ( target - > health < = 1 ) // Death
{
P_PlayDeathSound ( target ) ;
P_PlayVictorySound ( source ) ; // Killer laughs at you! LAUGHS! BWAHAHAHHAHAA!!
}
else if ( target - > health > 1 ) // Ring loss
{
P_PlayRinglossSound ( target ) ;
P_PlayerRingBurst ( player , player - > mo - > health - 1 ) ;
}
if ( inflictor & & ( ( inflictor - > flags & MF_MISSILE ) | | inflictor - > player ) & & player - > powers [ pw_super ] & & ALL7EMERALDS ( player - > powers [ pw_emeralds ] ) )
{
player - > health - = 10 ;
if ( player - > health < 2 )
player - > health = 2 ;
target - > health = player - > health ;
}
else
player - > health = target - > health = 1 ;
return true ;
}
static inline boolean P_PlayerHitsPlayer ( mobj_t * target , mobj_t * inflictor , mobj_t * source , INT32 damage )
{
player_t * player = target - > player ;
2017-02-26 15:19:12 +00:00
// You can't kill yourself, idiot... // Unless it's Mario kart. Which it is. In this mod. All the time.
//if (source == target)
// return false;
2014-03-15 16:59:03 +00:00
// In COOP/RACE/CHAOS, you can't hurt other players unless cv_friendlyfire is on
2017-02-26 15:19:12 +00:00
// ...But in SRB2kart, you can!
2018-02-08 22:13:06 +00:00
//if (!cv_friendlyfire.value && (G_RaceGametype()))
2017-02-26 15:19:12 +00:00
// return false;
2014-03-15 16:59:03 +00:00
// Tag handling
if ( G_TagGametype ( ) )
return P_TagDamage ( target , inflictor , source , damage ) ;
else if ( G_GametypeHasTeams ( ) ) // CTF + Team Match
{
// Don't allow players on the same team to hurt one another,
// unless cv_friendlyfire is on.
if ( ! cv_friendlyfire . value & & target - > player - > ctfteam = = source - > player - > ctfteam )
{
if ( ! ( inflictor - > flags & MF_FIRE ) )
P_GivePlayerRings ( target - > player , 1 ) ;
2014-04-14 05:14:58 +00:00
if ( inflictor - > flags2 & MF2_BOUNCERING )
2016-07-06 04:09:17 +00:00
inflictor - > fuse = 0 ; // bounce ring disappears at -1 not 0
2014-03-15 16:59:03 +00:00
return false ;
}
}
// Add pity.
if ( ! player - > powers [ pw_flashing ] & & ! player - > powers [ pw_invulnerability ] & & ! player - > powers [ pw_super ]
& & source - > player - > score > player - > score )
player - > pity + + ;
return true ;
}
static void P_KillPlayer ( player_t * player , mobj_t * source , INT32 damage )
{
player - > pflags & = ~ ( PF_CARRIED | PF_SLIDING | PF_ITEMHANG | PF_MACESPIN | PF_ROPEHANG | PF_NIGHTSMODE ) ;
// Burst weapons and emeralds in Match/CTF only
2018-03-04 20:27:52 +00:00
if ( source & & ( G_BattleGametype ( ) ) )
2014-03-15 16:59:03 +00:00
{
P_PlayerRingBurst ( player , player - > health - 1 ) ;
P_PlayerEmeraldBurst ( player , false ) ;
}
// Get rid of shield
player - > powers [ pw_shield ] = SH_NONE ;
player - > mo - > color = player - > skincolor ;
2018-10-23 21:48:09 +00:00
player - > mo - > colorized = false ;
2014-03-15 16:59:03 +00:00
// Get rid of emeralds
player - > powers [ pw_emeralds ] = 0 ;
P_ForceFeed ( player , 40 , 10 , TICRATE , 40 + min ( damage , 100 ) * 2 ) ;
P_ResetPlayer ( player ) ;
P_SetPlayerMobjState ( player - > mo , player - > mo - > info - > deathstate ) ;
2018-10-23 21:48:09 +00:00
2017-10-22 21:26:43 +00:00
/*if (gametype == GT_CTF && (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)))
2014-03-15 16:59:03 +00:00
{
P_PlayerFlagBurst ( player , false ) ;
if ( source & & source - > player )
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if ( ! G_GametypeHasTeams ( ) | | ! ( source - > player - > ctfteam = = player - > ctfteam & & source ! = player - > mo ) )
2017-10-22 21:26:43 +00:00
P_AddPlayerScore ( source - > player , 1 ) ;
2014-03-15 16:59:03 +00:00
}
}
if ( source & & source - > player & & ! player - > powers [ pw_super ] ) //don't score points against super players
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if ( ! G_GametypeHasTeams ( ) | | ! ( source - > player - > ctfteam = = player - > ctfteam & & source ! = player - > mo ) )
2017-10-22 21:26:43 +00:00
P_AddPlayerScore ( source - > player , 1 ) ;
2014-03-15 16:59:03 +00:00
}
// If the player was super, tell them he/she ain't so super nomore.
if ( gametype ! = GT_COOP & & player - > powers [ pw_super ] )
{
S_StartSound ( NULL , sfx_s3k66 ) ; //let all players hear it.
HU_SetCEchoFlags ( 0 ) ;
HU_SetCEchoDuration ( 5 ) ;
HU_DoCEcho ( va ( " %s \\ is no longer super. \\ \\ \\ \\ " , player_names [ player - players ] ) ) ;
2017-10-22 21:26:43 +00:00
} */
2018-10-23 21:48:09 +00:00
if ( player - > pflags & PF_TIMEOVER )
{
mobj_t * boom ;
player - > mo - > flags | = ( MF_NOGRAVITY | MF_NOCLIP ) ;
player - > mo - > flags2 | = MF2_DONTDRAW ;
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_SetTarget ( & boom - > target , player - > mo ) ;
}
2018-03-04 20:27:52 +00:00
if ( G_BattleGametype ( ) )
2017-10-22 21:26:43 +00:00
{
2018-07-03 19:14:47 +00:00
if ( player - > kartstuff [ k_bumper ] > 0 )
2017-11-05 06:43:47 +00:00
{
2018-07-03 19:14:47 +00:00
if ( player - > kartstuff [ k_bumper ] = = 1 )
2018-06-16 04:00:46 +00:00
{
mobj_t * karmahitbox = P_SpawnMobj ( player - > mo - > x , player - > mo - > y , player - > mo - > z , MT_KARMAHITBOX ) ; // Player hitbox is too small!!
P_SetTarget ( & karmahitbox - > target , player - > mo ) ;
karmahitbox - > destscale = player - > mo - > scale ;
P_SetScale ( karmahitbox , player - > mo - > scale ) ;
2018-07-03 19:14:47 +00:00
CONS_Printf ( M_GetText ( " %s lost all of their bumpers! \n " ) , player_names [ player - players ] ) ;
2018-06-16 04:00:46 +00:00
}
2018-07-06 18:22:48 +00:00
player - > kartstuff [ k_bumper ] - - ;
2018-07-04 01:12:25 +00:00
if ( K_IsPlayerWanted ( player ) )
K_CalculateBattleWanted ( ) ;
2017-11-05 06:43:47 +00:00
}
2017-11-01 22:46:35 +00:00
2018-07-03 19:14:47 +00:00
K_CheckBumpers ( ) ;
2014-03-15 16:59:03 +00:00
}
}
void P_RemoveShield ( player_t * player )
{
if ( player - > powers [ pw_shield ] & SH_FORCE )
{ // Multi-hit
if ( ( player - > powers [ pw_shield ] & 0xFF ) = = 0 )
player - > powers [ pw_shield ] & = ~ SH_FORCE ;
else
player - > powers [ pw_shield ] - - ;
}
else if ( ( player - > powers [ pw_shield ] & SH_NOSTACK ) = = SH_NONE )
{ // Second layer shields
player - > powers [ pw_shield ] = SH_NONE ;
// Reset fireflower
if ( ! player - > powers [ pw_super ] )
2014-04-14 05:14:58 +00:00
{
2014-03-15 16:59:03 +00:00
player - > mo - > color = player - > skincolor ;
2019-02-16 18:42:24 +00:00
G_GhostAddColor ( ( INT32 ) ( player - players ) , GHC_NORMAL ) ;
2014-04-14 05:14:58 +00:00
}
2014-03-15 16:59:03 +00:00
}
else if ( ( player - > powers [ pw_shield ] & SH_NOSTACK ) = = SH_BOMB ) // Give them what's coming to them!
{
P_BlackOw ( player ) ; // BAM!
player - > pflags | = PF_JUMPDOWN ;
}
else
player - > powers [ pw_shield ] = player - > powers [ pw_shield ] & SH_STACK ;
}
2017-02-18 18:39:25 +00:00
/*
static void P_ShieldDamage ( player_t * player , mobj_t * inflictor , mobj_t * source , INT32 damage ) // SRB2kart - unused.
2014-03-15 16:59:03 +00:00
{
2014-03-25 02:17:59 +00:00
// Must do pain first to set flashing -- P_RemoveShield can cause damage
P_DoPlayerPain ( player , source , inflictor ) ;
2014-03-15 16:59:03 +00:00
P_RemoveShield ( player ) ;
P_ForceFeed ( player , 40 , 10 , TICRATE , 40 + min ( damage , 100 ) * 2 ) ;
if ( source & & ( source - > type = = MT_SPIKE | | ( source - > type = = MT_NULL & & source - > threshold = = 43 ) ) ) // spikes
S_StartSound ( player - > mo , sfx_spkdth ) ;
else
S_StartSound ( player - > mo , sfx_shldls ) ; // Ba-Dum! Shield loss.
if ( gametype = = GT_CTF & & ( player - > gotflag & ( GF_REDFLAG | GF_BLUEFLAG ) ) )
{
P_PlayerFlagBurst ( player , false ) ;
if ( source & & source - > player )
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if ( ! G_GametypeHasTeams ( ) | | ! ( source - > player - > ctfteam = = player - > ctfteam & & source ! = player - > mo ) )
P_AddPlayerScore ( source - > player , 25 ) ;
}
}
if ( source & & source - > player & & ! player - > powers [ pw_super ] ) //don't score points against super players
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if ( ! G_GametypeHasTeams ( ) | | ! ( source - > player - > ctfteam = = player - > ctfteam & & source ! = player - > mo ) )
P_AddPlayerScore ( source - > player , cv_match_scoring . value = = 1 ? 25 : 50 ) ;
}
}
2017-02-18 18:39:25 +00:00
*/
2014-03-15 16:59:03 +00:00
static void P_RingDamage ( player_t * player , mobj_t * inflictor , mobj_t * source , INT32 damage )
{
2018-07-01 08:36:09 +00:00
//const UINT8 scoremultiply = ((K_IsWantedPlayer(player) && !trapitem) : 2 ? 1);
2014-03-15 16:59:03 +00:00
if ( ! ( inflictor & & ( ( inflictor - > flags & MF_MISSILE ) | | inflictor - > player ) & & player - > powers [ pw_super ] & & ALL7EMERALDS ( player - > powers [ pw_emeralds ] ) ) )
{
P_DoPlayerPain ( player , source , inflictor ) ;
P_ForceFeed ( player , 40 , 10 , TICRATE , 40 + min ( damage , 100 ) * 2 ) ;
if ( source & & ( source - > type = = MT_SPIKE | | ( source - > type = = MT_NULL & & source - > threshold = = 43 ) ) ) // spikes
S_StartSound ( player - > mo , sfx_spkdth ) ;
}
2018-07-01 08:36:09 +00:00
/*if (source && source->player && !player->powers[pw_super]) //don't score points against super players
2014-03-15 16:59:03 +00:00
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if ( ! G_GametypeHasTeams ( ) | | ! ( source - > player - > ctfteam = = player - > ctfteam & & source ! = player - > mo ) )
2018-07-01 08:36:09 +00:00
P_AddPlayerScore ( source - > player , scoremultiply ) ;
2014-03-15 16:59:03 +00:00
}
if ( gametype = = GT_CTF & & ( player - > gotflag & ( GF_REDFLAG | GF_BLUEFLAG ) ) )
{
P_PlayerFlagBurst ( player , false ) ;
if ( source & & source - > player )
{
// Award no points when players shoot each other when cv_friendlyfire is on.
if ( ! G_GametypeHasTeams ( ) | | ! ( source - > player - > ctfteam = = player - > ctfteam & & source ! = player - > mo ) )
2018-07-01 08:36:09 +00:00
P_AddPlayerScore ( source - > player , scoremultiply ) ;
2014-03-15 16:59:03 +00:00
}
2018-07-01 08:36:09 +00:00
} */
2014-03-15 16:59:03 +00:00
// Ring loss sound plays despite hitting spikes
P_PlayRinglossSound ( player - > mo ) ; // Ringledingle!
}
/** Damages an object, which may or may not be a player.
* For melee attacks , source and inflictor are the same .
*
* \ param target The object being damaged .
* \ param inflictor The thing that caused the damage : creature , missile ,
* gargoyle , and so forth . Can be NULL in the case of
* environmental damage , such as slime or crushing .
* \ param source The creature or person responsible . For example , if a
* player is hit by a ring , the player who shot it . In some
* cases , the target will go after this object after
* receiving damage . This can be NULL .
* \ param damage Amount of damage to be dealt . 10000 is instant death .
* \ return True if the target sustained damage , otherwise false .
* \ todo Clean up this mess , split into multiple functions .
* \ todo Get rid of the magic number 10000.
* \ sa P_KillMobj
*/
boolean P_DamageMobj ( mobj_t * target , mobj_t * inflictor , mobj_t * source , INT32 damage )
{
player_t * player ;
# ifdef HAVE_BLUA
boolean force = false ;
# else
static const boolean force = false ;
# endif
if ( objectplacing )
return false ;
if ( target - > health < = 0 )
return false ;
// Spectator handling
if ( netgame )
{
if ( damage = = 42000 & & target - > player & & target - > player - > spectator )
damage = 10000 ;
else if ( target - > player & & target - > player - > spectator )
return false ;
if ( source & & source - > player & & source - > player - > spectator )
return false ;
}
# ifdef HAVE_BLUA
// Everything above here can't be forced.
if ( ! metalrecording )
{
UINT8 shouldForce = LUAh_ShouldDamage ( target , inflictor , source , damage ) ;
if ( P_MobjWasRemoved ( target ) )
return ( shouldForce = = 1 ) ; // mobj was removed
if ( shouldForce = = 1 )
force = true ;
else if ( shouldForce = = 2 )
return false ;
}
# endif
if ( ! force )
{
if ( ! ( target - > flags & MF_SHOOTABLE ) )
return false ; // shouldn't happen...
if ( target - > type = = MT_BLACKEGGMAN )
return false ;
// Make sure that boxes cannot be popped by enemies, red rings, etc.
if ( target - > flags & MF_MONITOR & & ( ( ! source | | ! source - > player | | source - > player - > bot ) | | ( inflictor & & ! inflictor - > player ) ) )
return false ;
}
if ( target - > flags2 & MF2_SKULLFLY )
target - > momx = target - > momy = target - > momz = 0 ;
if ( ! force )
{
// Special case for team ring boxes
if ( target - > type = = MT_REDRINGBOX & & ! ( source - > player - > ctfteam = = 1 ) )
return false ;
if ( target - > type = = MT_BLUERINGBOX & & ! ( source - > player - > ctfteam = = 2 ) )
return false ;
}
// Special case for Crawla Commander
if ( target - > type = = MT_CRAWLACOMMANDER )
{
if ( ! force & & target - > fuse ) // Invincible
return false ;
# ifdef HAVE_BLUA
if ( LUAh_MobjDamage ( target , inflictor , source , damage ) | | P_MobjWasRemoved ( target ) )
return true ;
# endif
if ( target - > health > 1 )
{
if ( target - > info - > painsound )
S_StartSound ( target , target - > info - > painsound ) ;
target - > fuse = TICRATE / 2 ;
target - > flags2 | = MF2_FRET ;
}
else
{
target - > flags | = MF_NOGRAVITY ;
target - > fuse = 0 ;
}
target - > momx = target - > momy = target - > momz = 0 ;
P_InstaThrust ( target , target - > angle - ANGLE_180 , FixedMul ( 5 * FRACUNIT , target - > scale ) ) ;
}
else if ( target - > flags & MF_BOSS )
{
if ( ! force & & target - > flags2 & MF2_FRET ) // Currently flashing from being hit
return false ;
# ifdef HAVE_BLUA
if ( LUAh_MobjDamage ( target , inflictor , source , damage ) | | P_MobjWasRemoved ( target ) )
return true ;
# endif
if ( target - > health > 1 )
target - > flags2 | = MF2_FRET ;
}
2014-04-19 17:41:29 +00:00
# ifdef HAVE_BLUA
else if ( target - > flags & MF_ENEMY )
{
if ( LUAh_MobjDamage ( target , inflictor , source , damage ) | | P_MobjWasRemoved ( target ) )
return true ;
}
# endif
2014-03-15 16:59:03 +00:00
player = target - > player ;
if ( player ) // Player is the target
{
if ( ! force )
{
if ( player - > exiting )
return false ;
if ( ! ( target - > player - > pflags & ( PF_NIGHTSMODE | PF_NIGHTSFALL ) ) & & ( maptol & TOL_NIGHTS ) )
return false ;
}
if ( player - > pflags & PF_NIGHTSMODE ) // NiGHTS damage handling
{
if ( ! force )
{
if ( source = = target )
return false ; // Don't hit yourself with your own paraloop, baka
if ( source & & source - > player & & ! cv_friendlyfire . value
& & ( gametype = = GT_COOP
| | ( G_GametypeHasTeams ( ) & & target - > player - > ctfteam = = source - > player - > ctfteam ) ) )
return false ; // Don't run eachother over in special stages and team games and such
}
# ifdef HAVE_BLUA
if ( LUAh_MobjDamage ( target , inflictor , source , damage ) )
return true ;
# endif
P_NiGHTSDamage ( target , source ) ; // -5s :(
return true ;
}
2018-11-26 20:23:41 +00:00
# ifdef HAVE_BLUA // Add this back here for ACTUAL NORMAL DAMAGE. The funny shit is that the player is barely ever "actually" damaged.
if ( LUAh_MobjDamage ( target , inflictor , source , damage ) )
return true ;
# endif
2014-03-15 16:59:03 +00:00
if ( ! force & & inflictor & & ( inflictor - > flags & MF_FIRE ) )
{
if ( ( player - > powers [ pw_shield ] & SH_NOSTACK ) = = SH_ELEMENTAL )
return false ; // Invincible to fire objects
2018-02-08 22:13:06 +00:00
if ( G_RaceGametype ( ) & & source & & source - > player )
2014-03-15 16:59:03 +00:00
return false ; // Don't get hurt by fire generated from friends.
}
// Sudden-Death mode
if ( source & & source - > type = = MT_PLAYER )
{
2018-03-04 20:27:52 +00:00
if ( ( G_BattleGametype ( ) ) & & cv_suddendeath . value
2014-03-15 16:59:03 +00:00
& & ! player - > powers [ pw_flashing ] & & ! player - > powers [ pw_invulnerability ] )
damage = 10000 ;
}
// Player hits another player
if ( ! force & & source & & source - > player )
{
if ( ! P_PlayerHitsPlayer ( target , inflictor , source , damage ) )
return false ;
}
if ( ! force & & player - > pflags & PF_GODMODE )
return false ;
// Instant-Death
if ( damage = = 10000 )
P_KillPlayer ( player , source , damage ) ;
2018-02-05 23:55:52 +00:00
else if ( player - > kartstuff [ k_invincibilitytimer ] > 0 | | player - > kartstuff [ k_growshrinktimer ] > 0 | | player - > powers [ pw_flashing ] )
2018-07-27 00:12:42 +00:00
{
2018-11-26 20:23:41 +00:00
if ( ! force ) // shoulddamage bypasses all of that.
{
K_DoInstashield ( player ) ;
return false ;
}
2018-07-27 00:12:42 +00:00
}
2016-08-15 03:51:08 +00:00
else
{
2018-07-23 00:55:18 +00:00
if ( inflictor & & ( inflictor - > type = = MT_ORBINAUT | | inflictor - > type = = MT_ORBINAUT_SHIELD
2018-06-01 00:51:05 +00:00
| | inflictor - > type = = MT_JAWZ | | inflictor - > type = = MT_JAWZ_SHIELD | | inflictor - > type = = MT_JAWZ_DUD
2018-10-29 09:00:08 +00:00
| | inflictor - > type = = MT_SMK_THWOMP | | inflictor - > player ) )
2017-11-11 02:10:01 +00:00
{
2018-06-20 00:20:06 +00:00
player - > kartstuff [ k_sneakertimer ] = 0 ;
2018-11-28 18:41:01 +00:00
K_SpinPlayer ( player , source , 1 , inflictor , false ) ;
2017-11-11 02:10:01 +00:00
damage = player - > mo - > health - 1 ;
P_RingDamage ( player , inflictor , source , damage ) ;
2017-10-24 12:15:20 +00:00
P_PlayerRingBurst ( player , 5 ) ;
2017-11-11 02:10:01 +00:00
if ( P_IsLocalPlayer ( player ) )
{
quake . intensity = 32 * FRACUNIT ;
quake . time = 5 ;
}
}
else
2017-10-24 21:58:59 +00:00
{
2018-11-28 18:41:01 +00:00
K_SpinPlayer ( player , source , 0 , inflictor , false ) ;
2017-10-24 21:58:59 +00:00
}
2017-02-19 17:18:43 +00:00
return true ;
2016-08-15 03:51:08 +00:00
}
/* // SRB2kart - don't need these
2014-03-15 16:59:03 +00:00
else if ( metalrecording )
{
if ( ! inflictor )
inflictor = source ;
if ( inflictor & & inflictor - > flags & MF_ENEMY )
{ // Metal Sonic destroy enemy !!
P_KillMobj ( inflictor , NULL , target ) ;
return false ;
}
else if ( inflictor & & inflictor - > flags & MF_MISSILE )
return false ; // Metal Sonic walk through flame !!
else
{ // Oh no! Metal Sonic is hit !!
P_ShieldDamage ( player , inflictor , source , damage ) ;
return true ;
}
}
else if ( player - > powers [ pw_invulnerability ] | | player - > powers [ pw_flashing ] // ignore bouncing & such in invulnerability
| | ( player - > powers [ pw_super ] & & ! ( ALL7EMERALDS ( player - > powers [ pw_emeralds ] ) & & inflictor & & ( ( inflictor - > flags & MF_MISSILE ) | | inflictor - > player ) ) ) )
{
if ( force | | ( inflictor & & ( inflictor - > flags & MF_MISSILE )
& & ( inflictor - > flags2 & MF2_SUPERFIRE )
& & player - > powers [ pw_super ] ) )
{
# ifdef HAVE_BLUA
if ( ! LUAh_MobjDamage ( target , inflictor , source , damage ) )
# endif
P_SuperDamage ( player , inflictor , source , damage ) ;
return true ;
}
else
return false ;
}
# ifdef HAVE_BLUA
else if ( LUAh_MobjDamage ( target , inflictor , source , damage ) )
return true ;
# endif
else if ( ! player - > powers [ pw_super ] & & ( player - > powers [ pw_shield ] | | player - > bot ) ) //If One-Hit Shield
{
P_ShieldDamage ( player , inflictor , source , damage ) ;
damage = 0 ;
}
2016-07-06 04:09:17 +00:00
else if ( player - > mo - > health > 1 ) // No shield but have rings.
2014-03-15 16:59:03 +00:00
{
damage = player - > mo - > health - 1 ;
P_RingDamage ( player , inflictor , source , damage ) ;
}
else // No shield, no rings, no invincibility.
{
// To reduce griefing potential, don't allow players to be killed
// by friendly fire. Spilling their rings and other items is enough.
if ( force | | ! ( G_GametypeHasTeams ( )
& & source & & source - > player & & ( source - > player - > ctfteam = = player - > ctfteam )
& & cv_friendlyfire . value ) )
{
damage = 1 ;
P_KillPlayer ( player , source , damage ) ;
}
else
{
damage = 0 ;
P_ShieldDamage ( player , inflictor , source , damage ) ;
}
}
2016-08-15 03:51:08 +00:00
*/
2014-03-15 16:59:03 +00:00
if ( inflictor & & ( ( inflictor - > flags & MF_MISSILE ) | | inflictor - > player ) & & player - > powers [ pw_super ] & & ALL7EMERALDS ( player - > powers [ pw_emeralds ] ) )
{
if ( player - > powers [ pw_shield ] )
{
P_RemoveShield ( player ) ;
return true ;
}
else
{
player - > health - = ( 10 * ( 1 < < ( INT32 ) ( player - > powers [ pw_super ] / 10500 ) ) ) ;
if ( player - > health < 2 )
player - > health = 2 ;
}
if ( gametype = = GT_CTF & & ( player - > gotflag & ( GF_REDFLAG | GF_BLUEFLAG ) ) )
P_PlayerFlagBurst ( player , false ) ;
}
else
{
player - > health - = damage ; // mirror mobj health here
if ( damage < 10000 )
{
2018-08-11 04:12:41 +00:00
target - > player - > powers [ pw_flashing ] = K_GetKartFlashing ( target - > player ) ;
2016-07-06 04:09:17 +00:00
if ( damage > 0 ) // don't spill emeralds/ammo/panels for shield damage
P_PlayerRingBurst ( player , damage ) ;
2014-03-15 16:59:03 +00:00
}
}
if ( player - > health < 0 )
player - > health = 0 ;
P_ForceFeed ( player , 40 , 10 , TICRATE , 40 + min ( damage , 100 ) * 2 ) ;
}
// Killing dead. Just for kicks.
2014-04-19 17:41:29 +00:00
// Require source and inflictor be player. Don't hurt for firing rings.
2016-07-06 04:09:17 +00:00
if ( cv_killingdead . value & & ( source & & source - > player ) & & ( inflictor & & inflictor - > player ) & & P_RandomChance ( 5 * FRACUNIT / 16 ) )
2014-03-15 16:59:03 +00:00
P_DamageMobj ( source , target , target , 1 ) ;
// do the damage
if ( player & & player - > powers [ pw_super ] & & ALL7EMERALDS ( player - > powers [ pw_emeralds ] ) & & inflictor & & ( ( inflictor - > flags & MF_MISSILE ) | | inflictor - > player ) )
{
target - > health - = ( 10 * ( 1 < < ( INT32 ) ( player - > powers [ pw_super ] / 10500 ) ) ) ;
if ( target - > health < 2 )
target - > health = 2 ;
}
else
target - > health - = damage ;
if ( source & & source - > player & & target )
2019-02-16 18:42:24 +00:00
G_GhostAddHit ( ( INT32 ) ( source - > player - players ) , target ) ;
2014-03-15 16:59:03 +00:00
if ( target - > health < = 0 )
{
P_KillMobj ( target , inflictor , source ) ;
return true ;
}
if ( player )
{
if ( ! ( player - > powers [ pw_super ] & & ALL7EMERALDS ( player - > powers [ pw_emeralds ] ) ) )
P_ResetPlayer ( target - > player ) ;
}
else
switch ( target - > type )
{
case MT_EGGMOBILE2 : // egg slimer
if ( target - > health < target - > info - > damage ) // in pinch phase
{
P_SetMobjState ( target , target - > info - > meleestate ) ; // go to pinch pain state
break ;
}
2017-09-28 13:39:47 +00:00
/* FALLTHRU */
2014-03-15 16:59:03 +00:00
default :
P_SetMobjState ( target , target - > info - > painstate ) ;
break ;
}
2018-07-29 22:07:10 +00:00
if ( ! P_MobjWasRemoved ( target ) )
2014-03-15 16:59:03 +00:00
{
2018-07-29 22:07:10 +00:00
target - > reactiontime = 0 ; // we're awake now...
if ( source & & source ! = target )
2014-03-15 16:59:03 +00:00
{
2018-07-29 22:07:10 +00:00
// if not intent on another player,
// chase after this one
P_SetTarget ( & target - > target , source ) ;
if ( target - > state = = & states [ target - > info - > spawnstate ] & & target - > info - > seestate ! = S_NULL )
2014-03-15 16:59:03 +00:00
{
2018-07-29 22:07:10 +00:00
if ( player )
{
if ( ! ( player - > powers [ pw_super ] & & ALL7EMERALDS ( player - > powers [ pw_emeralds ] ) ) )
P_SetPlayerMobjState ( target , target - > info - > seestate ) ;
}
else
P_SetMobjState ( target , target - > info - > seestate ) ;
2014-03-15 16:59:03 +00:00
}
}
}
return true ;
}
/** Spills an injured player's rings.
*
* \ param player The player who is losing rings .
* \ param num_rings Number of rings lost . A maximum of 32 rings will be
* spawned .
* \ sa P_PlayerFlagBurst
*/
void P_PlayerRingBurst ( player_t * player , INT32 num_rings )
{
INT32 i ;
mobj_t * mo ;
angle_t fa ;
fixed_t ns ;
fixed_t z ;
// Better safe than sorry.
if ( ! player )
return ;
2017-10-24 12:15:20 +00:00
// Never have health in kart I think
2014-03-15 16:59:03 +00:00
if ( player - > mo - > health < = 1 )
2017-10-24 12:15:20 +00:00
num_rings = 5 ;
2014-03-15 16:59:03 +00:00
if ( num_rings > 32 & & ! ( player - > pflags & PF_NIGHTSFALL ) )
num_rings = 32 ;
if ( player - > powers [ pw_emeralds ] )
P_PlayerEmeraldBurst ( player , false ) ;
// Spill weapons first
if ( player - > ringweapons )
P_PlayerWeaponPanelBurst ( player ) ;
// Spill the ammo
P_PlayerWeaponAmmoBurst ( player ) ;
2017-10-24 12:15:20 +00:00
// There's no ring spilling in kart, so I'm hijacking this for the same thing as TD
2014-03-15 16:59:03 +00:00
for ( i = 0 ; i < num_rings ; i + + )
{
2017-10-24 12:15:20 +00:00
INT32 objType = mobjinfo [ MT_FLINGENERGY ] . reactiontime ;
2014-03-15 16:59:03 +00:00
z = player - > mo - > z ;
if ( player - > mo - > eflags & MFE_VERTICALFLIP )
z + = player - > mo - > height - mobjinfo [ objType ] . height ;
mo = P_SpawnMobj ( player - > mo - > x , player - > mo - > y , z , objType ) ;
mo - > fuse = 8 * TICRATE ;
P_SetTarget ( & mo - > target , player - > mo ) ;
mo - > destscale = player - > mo - > scale ;
P_SetScale ( mo , player - > mo - > scale ) ;
// Angle offset by player angle, then slightly offset by amount of rings
fa = ( ( i * FINEANGLES / 16 ) + ( player - > mo - > angle > > ANGLETOFINESHIFT ) - ( ( num_rings - 1 ) * FINEANGLES / 32 ) ) & FINEMASK ;
// Make rings spill out around the player in 16 directions like SA, but spill like Sonic 2.
// Technically a non-SA way of spilling rings. They just so happen to be a little similar.
if ( player - > pflags & PF_NIGHTSFALL )
{
ns = FixedMul ( ( ( i * FRACUNIT ) / 16 ) + 2 * FRACUNIT , mo - > scale ) ;
mo - > momx = FixedMul ( FINECOSINE ( fa ) , ns ) ;
if ( ! ( twodlevel | | ( player - > mo - > flags2 & MF2_TWOD ) ) )
mo - > momy = FixedMul ( FINESINE ( fa ) , ns ) ;
P_SetObjectMomZ ( mo , 8 * FRACUNIT , false ) ;
mo - > fuse = 20 * TICRATE ; // Adjust fuse for NiGHTS
}
else
{
fixed_t momxy , momz ; // base horizonal/vertical thrusts
if ( i > 15 )
{
momxy = 3 * FRACUNIT ;
momz = 4 * FRACUNIT ;
}
else
{
2017-10-24 12:15:20 +00:00
momxy = 28 * FRACUNIT ;
2014-03-15 16:59:03 +00:00
momz = 3 * FRACUNIT ;
}
2017-10-24 13:04:54 +00:00
ns = FixedMul ( momxy , mo - > scale ) ;
2014-03-15 16:59:03 +00:00
mo - > momx = FixedMul ( FINECOSINE ( fa ) , ns ) ;
if ( ! ( twodlevel | | ( player - > mo - > flags2 & MF2_TWOD ) ) )
mo - > momy = FixedMul ( FINESINE ( fa ) , ns ) ;
2017-10-24 13:04:54 +00:00
ns = momz ;
2014-03-15 16:59:03 +00:00
P_SetObjectMomZ ( mo , ns , false ) ;
if ( i & 1 )
P_SetObjectMomZ ( mo , ns , true ) ;
}
if ( player - > mo - > eflags & MFE_VERTICALFLIP )
mo - > momz * = - 1 ;
}
player - > losstime + = 10 * TICRATE ;
if ( P_IsObjectOnGround ( player - > mo ) )
player - > pflags & = ~ PF_NIGHTSFALL ;
return ;
}
void P_PlayerWeaponPanelBurst ( player_t * player )
{
mobj_t * mo ;
angle_t fa ;
fixed_t ns ;
INT32 i ;
fixed_t z ;
INT32 num_weapons = M_CountBits ( ( UINT32 ) player - > ringweapons , NUM_WEAPONS - 1 ) ;
UINT16 ammoamt = 0 ;
for ( i = 0 ; i < num_weapons ; i + + )
{
mobjtype_t weptype = 0 ;
powertype_t power = 0 ;
if ( player - > ringweapons & RW_BOUNCE ) // Bounce
{
weptype = MT_BOUNCEPICKUP ;
player - > ringweapons & = ~ RW_BOUNCE ;
power = pw_bouncering ;
}
else if ( player - > ringweapons & RW_RAIL ) // Rail
{
weptype = MT_RAILPICKUP ;
player - > ringweapons & = ~ RW_RAIL ;
power = pw_railring ;
}
else if ( player - > ringweapons & RW_AUTO ) // Auto
{
weptype = MT_AUTOPICKUP ;
player - > ringweapons & = ~ RW_AUTO ;
power = pw_automaticring ;
}
else if ( player - > ringweapons & RW_EXPLODE ) // Explode
{
weptype = MT_EXPLODEPICKUP ;
player - > ringweapons & = ~ RW_EXPLODE ;
power = pw_explosionring ;
}
else if ( player - > ringweapons & RW_SCATTER ) // Scatter
{
weptype = MT_SCATTERPICKUP ;
player - > ringweapons & = ~ RW_SCATTER ;
power = pw_scatterring ;
}
else if ( player - > ringweapons & RW_GRENADE ) // Grenade
{
weptype = MT_GRENADEPICKUP ;
player - > ringweapons & = ~ RW_GRENADE ;
power = pw_grenadering ;
}
if ( ! weptype ) // ???
continue ;
if ( player - > powers [ power ] > = mobjinfo [ weptype ] . reactiontime )
ammoamt = ( UINT16 ) mobjinfo [ weptype ] . reactiontime ;
else
ammoamt = player - > powers [ power ] ;
player - > powers [ power ] - = ammoamt ;
z = player - > mo - > z ;
if ( player - > mo - > eflags & MFE_VERTICALFLIP )
z + = player - > mo - > height - mobjinfo [ weptype ] . height ;
mo = P_SpawnMobj ( player - > mo - > x , player - > mo - > y , z , weptype ) ;
mo - > reactiontime = ammoamt ;
mo - > flags2 | = MF2_DONTRESPAWN ;
mo - > flags & = ~ ( MF_NOGRAVITY | MF_NOCLIPHEIGHT ) ;
P_SetTarget ( & mo - > target , player - > mo ) ;
mo - > fuse = 12 * TICRATE ;
mo - > destscale = player - > mo - > scale ;
P_SetScale ( mo , player - > mo - > scale ) ;
// Angle offset by player angle
fa = ( ( i * FINEANGLES / 16 ) + ( player - > mo - > angle > > ANGLETOFINESHIFT ) ) & FINEMASK ;
// Make rings spill out around the player in 16 directions like SA, but spill like Sonic 2.
// Technically a non-SA way of spilling rings. They just so happen to be a little similar.
// >16 ring type spillout
ns = FixedMul ( 3 * FRACUNIT , mo - > scale ) ;
mo - > momx = FixedMul ( FINECOSINE ( fa ) , ns ) ;
if ( ! ( twodlevel | | ( player - > mo - > flags2 & MF2_TWOD ) ) )
mo - > momy = FixedMul ( FINESINE ( fa ) , ns ) ;
P_SetObjectMomZ ( mo , 4 * FRACUNIT , false ) ;
if ( i & 1 )
P_SetObjectMomZ ( mo , 4 * FRACUNIT , true ) ;
}
}
void P_PlayerWeaponAmmoBurst ( player_t * player )
{
mobj_t * mo ;
angle_t fa ;
fixed_t ns ;
INT32 i = 0 ;
fixed_t z ;
mobjtype_t weptype = 0 ;
powertype_t power = 0 ;
while ( true )
{
if ( player - > powers [ pw_bouncering ] )
{
weptype = MT_BOUNCERING ;
power = pw_bouncering ;
}
else if ( player - > powers [ pw_railring ] )
{
weptype = MT_RAILRING ;
power = pw_railring ;
}
else if ( player - > powers [ pw_infinityring ] )
{
weptype = MT_INFINITYRING ;
power = pw_infinityring ;
}
else if ( player - > powers [ pw_automaticring ] )
{
weptype = MT_AUTOMATICRING ;
power = pw_automaticring ;
}
else if ( player - > powers [ pw_explosionring ] )
{
weptype = MT_EXPLOSIONRING ;
power = pw_explosionring ;
}
else if ( player - > powers [ pw_scatterring ] )
{
weptype = MT_SCATTERRING ;
power = pw_scatterring ;
}
else if ( player - > powers [ pw_grenadering ] )
{
weptype = MT_GRENADERING ;
power = pw_grenadering ;
}
else
break ; // All done!
z = player - > mo - > z ;
if ( player - > mo - > eflags & MFE_VERTICALFLIP )
z + = player - > mo - > height - mobjinfo [ weptype ] . height ;
mo = P_SpawnMobj ( player - > mo - > x , player - > mo - > y , z , weptype ) ;
mo - > health = player - > powers [ power ] ;
mo - > flags2 | = MF2_DONTRESPAWN ;
mo - > flags & = ~ ( MF_NOGRAVITY | MF_NOCLIPHEIGHT ) ;
P_SetTarget ( & mo - > target , player - > mo ) ;
player - > powers [ power ] = 0 ;
mo - > fuse = 12 * TICRATE ;
mo - > destscale = player - > mo - > scale ;
P_SetScale ( mo , player - > mo - > scale ) ;
// Angle offset by player angle
fa = ( ( i * FINEANGLES / 16 ) + ( player - > mo - > angle > > ANGLETOFINESHIFT ) ) & FINEMASK ;
// Spill them!
ns = FixedMul ( 2 * FRACUNIT , mo - > scale ) ;
mo - > momx = FixedMul ( FINECOSINE ( fa ) , ns ) ;
if ( ! ( twodlevel | | ( player - > mo - > flags2 & MF2_TWOD ) ) )
mo - > momy = FixedMul ( FINESINE ( fa ) , ns ) ;
P_SetObjectMomZ ( mo , 3 * FRACUNIT , false ) ;
if ( i & 1 )
P_SetObjectMomZ ( mo , 3 * FRACUNIT , true ) ;
i + + ;
}
}
//
// P_PlayerEmeraldBurst
//
// Spills ONLY emeralds.
//
void P_PlayerEmeraldBurst ( player_t * player , boolean toss )
{
INT32 i ;
angle_t fa ;
fixed_t ns ;
fixed_t z = 0 , momx = 0 , momy = 0 ;
// Better safe than sorry.
if ( ! player )
return ;
// Spill power stones
if ( player - > powers [ pw_emeralds ] )
{
INT32 num_stones = 0 ;
if ( player - > powers [ pw_emeralds ] & EMERALD1 )
num_stones + + ;
if ( player - > powers [ pw_emeralds ] & EMERALD2 )
num_stones + + ;
if ( player - > powers [ pw_emeralds ] & EMERALD3 )
num_stones + + ;
if ( player - > powers [ pw_emeralds ] & EMERALD4 )
num_stones + + ;
if ( player - > powers [ pw_emeralds ] & EMERALD5 )
num_stones + + ;
if ( player - > powers [ pw_emeralds ] & EMERALD6 )
num_stones + + ;
if ( player - > powers [ pw_emeralds ] & EMERALD7 )
num_stones + + ;
for ( i = 0 ; i < num_stones ; i + + )
{
INT32 stoneflag = 0 ;
statenum_t statenum = S_CEMG1 ;
mobj_t * mo ;
if ( player - > powers [ pw_emeralds ] & EMERALD1 )
{
stoneflag = EMERALD1 ;
statenum = S_CEMG1 ;
}
else if ( player - > powers [ pw_emeralds ] & EMERALD2 )
{
stoneflag = EMERALD2 ;
statenum = S_CEMG2 ;
}
else if ( player - > powers [ pw_emeralds ] & EMERALD3 )
{
stoneflag = EMERALD3 ;
statenum = S_CEMG3 ;
}
else if ( player - > powers [ pw_emeralds ] & EMERALD4 )
{
stoneflag = EMERALD4 ;
statenum = S_CEMG4 ;
}
else if ( player - > powers [ pw_emeralds ] & EMERALD5 )
{
stoneflag = EMERALD5 ;
statenum = S_CEMG5 ;
}
else if ( player - > powers [ pw_emeralds ] & EMERALD6 )
{
stoneflag = EMERALD6 ;
statenum = S_CEMG6 ;
}
else if ( player - > powers [ pw_emeralds ] & EMERALD7 )
{
stoneflag = EMERALD7 ;
statenum = S_CEMG7 ;
}
if ( ! stoneflag ) // ???
continue ;
player - > powers [ pw_emeralds ] & = ~ stoneflag ;
if ( toss )
{
fa = player - > mo - > angle > > ANGLETOFINESHIFT ;
z = player - > mo - > z + player - > mo - > height ;
if ( player - > mo - > eflags & MFE_VERTICALFLIP )
z - = mobjinfo [ MT_FLINGEMERALD ] . height + player - > mo - > height ;
ns = FixedMul ( 8 * FRACUNIT , player - > mo - > scale ) ;
}
else
{
fa = ( ( 255 / num_stones ) * i ) * FINEANGLES / 256 ;
z = player - > mo - > z + ( player - > mo - > height / 2 ) ;
if ( player - > mo - > eflags & MFE_VERTICALFLIP )
z - = mobjinfo [ MT_FLINGEMERALD ] . height ;
ns = FixedMul ( 4 * FRACUNIT , player - > mo - > scale ) ;
}
momx = FixedMul ( FINECOSINE ( fa ) , ns ) ;
if ( ! ( twodlevel | | ( player - > mo - > flags2 & MF2_TWOD ) ) )
momy = FixedMul ( FINESINE ( fa ) , ns ) ;
else
momy = 0 ;
mo = P_SpawnMobj ( player - > mo - > x , player - > mo - > y , z , MT_FLINGEMERALD ) ;
mo - > health = 1 ;
mo - > threshold = stoneflag ;
mo - > flags2 | = ( MF2_DONTRESPAWN | MF2_SLIDEPUSH ) ;
mo - > flags & = ~ ( MF_NOGRAVITY | MF_NOCLIPHEIGHT ) ;
P_SetTarget ( & mo - > target , player - > mo ) ;
mo - > fuse = 12 * TICRATE ;
P_SetMobjState ( mo , statenum ) ;
mo - > momx = momx ;
mo - > momy = momy ;
P_SetObjectMomZ ( mo , 3 * FRACUNIT , false ) ;
if ( player - > mo - > eflags & MFE_VERTICALFLIP )
mo - > momz = - mo - > momz ;
if ( toss )
player - > tossdelay = 2 * TICRATE ;
}
}
}
/** Makes an injured or dead player lose possession of the flag.
*
* \ param player The player with the flag , about to lose it .
* \ sa P_PlayerRingBurst
*/
void P_PlayerFlagBurst ( player_t * player , boolean toss )
{
mobj_t * flag ;
mobjtype_t type ;
if ( ! ( player - > gotflag & ( GF_REDFLAG | GF_BLUEFLAG ) ) )
return ;
if ( player - > gotflag & GF_REDFLAG )
type = MT_REDFLAG ;
else
type = MT_BLUEFLAG ;
flag = P_SpawnMobj ( player - > mo - > x , player - > mo - > y , player - > mo - > z , type ) ;
if ( player - > mo - > eflags & MFE_VERTICALFLIP )
flag - > z + = player - > mo - > height - flag - > height ;
if ( toss )
P_InstaThrust ( flag , player - > mo - > angle , FixedMul ( 6 * FRACUNIT , player - > mo - > scale ) ) ;
else
{
2016-07-06 04:09:17 +00:00
angle_t fa = P_RandomByte ( ) * FINEANGLES / 256 ;
2014-03-15 16:59:03 +00:00
flag - > momx = FixedMul ( FINECOSINE ( fa ) , FixedMul ( 6 * FRACUNIT , player - > mo - > scale ) ) ;
if ( ! ( twodlevel | | ( player - > mo - > flags2 & MF2_TWOD ) ) )
flag - > momy = FixedMul ( FINESINE ( fa ) , FixedMul ( 6 * FRACUNIT , player - > mo - > scale ) ) ;
}
flag - > momz = FixedMul ( 8 * FRACUNIT , player - > mo - > scale ) ;
if ( player - > mo - > eflags & MFE_VERTICALFLIP )
flag - > momz = - flag - > momz ;
if ( type = = MT_REDFLAG )
flag - > spawnpoint = rflagpoint ;
else
flag - > spawnpoint = bflagpoint ;
flag - > fuse = cv_flagtime . value * TICRATE ;
P_SetTarget ( & flag - > target , player - > mo ) ;
2016-07-06 04:09:17 +00:00
// Flag text
{
char plname [ MAXPLAYERNAME + 4 ] ;
2016-06-13 15:11:02 +00:00
const char * flagtext ;
2016-07-06 04:09:17 +00:00
char flagcolor ;
snprintf ( plname , sizeof ( plname ) , " %s%s%s " ,
CTFTEAMCODE ( player ) ,
player_names [ player - players ] ,
CTFTEAMENDCODE ( player ) ) ;
if ( type = = MT_REDFLAG )
{
flagtext = M_GetText ( " Red flag " ) ;
flagcolor = ' \x85 ' ;
}
else
{
flagtext = M_GetText ( " Blue flag " ) ;
flagcolor = ' \x84 ' ;
}
if ( toss )
CONS_Printf ( M_GetText ( " %s tossed the %c%s%c. \n " ) , plname , flagcolor , flagtext , 0x80 ) ;
else
CONS_Printf ( M_GetText ( " %s dropped the %c%s%c. \n " ) , plname , flagcolor , flagtext , 0x80 ) ;
}
2014-03-15 16:59:03 +00:00
player - > gotflag = 0 ;
// Pointers set for displaying time value and for consistency restoration.
if ( type = = MT_REDFLAG )
redflag = flag ;
else
blueflag = flag ;
if ( toss )
player - > tossdelay = 2 * TICRATE ;
return ;
}