From 82066e191c9980a4c33276fcf40cdd0f57bd5d57 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Fri, 6 Oct 2023 23:20:49 +0200 Subject: [PATCH 001/374] cgame - game: Implementing Hit stun, fix and improve flying and ki charge animations --- source/cgame/cg_draw.c | 16 ++- source/game/ai_dmq3.c | 3 + source/game/be_ai_move.h | 3 +- source/game/bg_pmove.c | 231 +++++++++++++++++++++------------------ source/game/bg_public.h | 17 ++- source/game/g_active.c | 13 ++- source/game/g_client.c | 2 +- source/game/g_combat.c | 2 +- source/game/g_misc.c | 2 +- 9 files changed, 158 insertions(+), 131 deletions(-) diff --git a/source/cgame/cg_draw.c b/source/cgame/cg_draw.c index 7774b23..4d0e4b5 100644 --- a/source/cgame/cg_draw.c +++ b/source/cgame/cg_draw.c @@ -2066,21 +2066,19 @@ CG_DrawHitStun */ static void CG_DrawHitStun( void ) { // BFP - Hit stun bottom centerprint const char *s; - int w; - playerState_t *ps; - int value; + int w, t; s = ""; // avoid printing when there are no status changes, for dll and shared objects - if ( cg.predictedPlayerState.stats[STAT_KI] <= 0 ) { + // 900 is added to adjust the timer calculated in milliseconds + t = ( 900 + cg.predictedPlayerState.pm_time ) / 1000; + if ( t > 0 && ( cg.predictedPlayerState.pm_flags & PMF_HITSTUN ) ) { s = "Stun"; } w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; - value = 0; // BFP - TODO: hit stun time - UI_DrawProportionalString( 320 - w / 2, SCREEN_HEIGHT - ( BIGCHAR_HEIGHT * 6 ), + UI_DrawProportionalString( 320 - w / 2, SCREEN_HEIGHT - ( BIGCHAR_HEIGHT * 6 ) + 23, s, UI_SMALLFONT, colorWhite ); - // BFP - TODO: Draw the time (seconds) - if ( value > 0 ) { - CG_DrawField ( 320 - w / 2, SCREEN_HEIGHT - ( BIGCHAR_HEIGHT * 4 ), 3, value ); + if ( t > 0 && ( cg.predictedPlayerState.pm_flags & PMF_HITSTUN ) ) { + CG_DrawField ( 320 - w - 16, SCREEN_HEIGHT - ( BIGCHAR_HEIGHT * 4 ) + 13, 3, t ); } } diff --git a/source/game/ai_dmq3.c b/source/game/ai_dmq3.c index 6e1eada..9c89963 100644 --- a/source/game/ai_dmq3.c +++ b/source/game/ai_dmq3.c @@ -912,9 +912,12 @@ void BotSetupForMovement(bot_state_t *bs) { //set the onground flag if (bs->cur_ps.groundEntityNum != ENTITYNUM_NONE) initmove.or_moveflags |= MFL_ONGROUND; //set the teleported flag + // BFP - No handling PMF_TIME_KNOCKBACK +#if 0 if ((bs->cur_ps.pm_flags & PMF_TIME_KNOCKBACK) && (bs->cur_ps.pm_time > 0)) { initmove.or_moveflags |= MFL_TELEPORTED; } +#endif //set the waterjump flag if ((bs->cur_ps.pm_flags & PMF_TIME_WATERJUMP) && (bs->cur_ps.pm_time > 0)) { initmove.or_moveflags |= MFL_WATERJUMP; diff --git a/source/game/be_ai_move.h b/source/game/be_ai_move.h index fb80819..ddf1797 100644 --- a/source/game/be_ai_move.h +++ b/source/game/be_ai_move.h @@ -43,7 +43,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define MFL_SWIMMING 4 //bot is swimming #define MFL_AGAINSTLADDER 8 //bot is against a ladder #define MFL_WATERJUMP 16 //bot is waterjumping -#define MFL_TELEPORTED 32 //bot is being teleported +// BFP - MFL_TELEPORTED is unused +// #define MFL_TELEPORTED 32 //bot is being teleported #define MFL_GRAPPLEPULL 64 //bot is being pulled by the grapple #define MFL_ACTIVEGRAPPLE 128 //bot is using the grapple hook #define MFL_GRAPPLERESET 256 //bot has reset the grapple diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index 655bb35..3ecc1b8 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -195,11 +195,13 @@ static void PM_Friction( void ) { // apply ground friction if ( pm->waterlevel <= 1 ) { if ( pml.walking && !(pml.groundTrace.surfaceFlags & SURF_SLICK) ) { + + // BFP - No handling PMF_TIME_KNOCKBACK // if getting knocked back, no friction - if ( ! (pm->ps->pm_flags & PMF_TIME_KNOCKBACK) ) { + // if ( ! (pm->ps->pm_flags & PMF_TIME_KNOCKBACK) ) { control = speed < pm_stopspeed ? pm_stopspeed : speed; drop += control*pm_friction*pml.frametime; - } + // } } } @@ -384,10 +386,10 @@ static qboolean PM_CheckJump( void ) { if ( pm->cmd.forwardmove >= 0 ) { PM_ForceLegsAnim( LEGS_JUMP ); - pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP; + // pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP; // BFP - No PMF_BACKWARDS_JUMP handling } else { PM_ForceLegsAnim( LEGS_JUMPB ); - pm->ps->pm_flags |= PMF_BACKWARDS_JUMP; + // pm->ps->pm_flags |= PMF_BACKWARDS_JUMP; // BFP - No PMF_BACKWARDS_JUMP handling } return qtrue; @@ -756,7 +758,7 @@ static void PM_WalkMove( void ) { // when a player gets hit, they temporarily lose // full control, which allows them to be moved a bit - if ( ( pml.groundTrace.surfaceFlags & SURF_SLICK ) || pm->ps->pm_flags & PMF_TIME_KNOCKBACK ) { + if ( ( pml.groundTrace.surfaceFlags & SURF_SLICK ) ) { // BFP - No handling PMF_TIME_KNOCKBACK, before: || pm->ps->pm_flags & PMF_TIME_KNOCKBACK ) { accelerate = pm_airaccelerate; } else { accelerate = pm_accelerate; @@ -767,7 +769,7 @@ static void PM_WalkMove( void ) { //Com_Printf("velocity = %1.1f %1.1f %1.1f\n", pm->ps->velocity[0], pm->ps->velocity[1], pm->ps->velocity[2]); //Com_Printf("velocity1 = %1.1f\n", VectorLength(pm->ps->velocity)); - if ( ( pml.groundTrace.surfaceFlags & SURF_SLICK ) || pm->ps->pm_flags & PMF_TIME_KNOCKBACK ) { + if ( ( pml.groundTrace.surfaceFlags & SURF_SLICK ) ) { // BFP - No handling PMF_TIME_KNOCKBACK, before: || pm->ps->pm_flags & PMF_TIME_KNOCKBACK ) { pm->ps->velocity[2] -= pm->ps->gravity * pml.frametime; } else { // don't reset the z velocity for slopes @@ -917,15 +919,16 @@ static void PM_CrashLand( void ) { // decide which landing animation to use // BFP - Non-existant animations - /* +#if 0 if ( pm->ps->pm_flags & PMF_BACKWARDS_JUMP ) { PM_ForceLegsAnim( LEGS_LANDB ); } else { PM_ForceLegsAnim( LEGS_LAND ); } - */ +#endif - pm->ps->legsTimer = TIMER_LAND; + // BFP - No timer land on the legs + // pm->ps->legsTimer = TIMER_LAND; // calculate the exact velocity on landing dist = pm->ps->origin[2] - pml.previous_origin[2]; @@ -1075,14 +1078,15 @@ static void PM_GroundTraceMissed( void ) { if ( trace.fraction == 1.0 ) { if ( pm->cmd.forwardmove >= 0 ) { PM_ForceLegsAnim( LEGS_JUMP ); - pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP; + // pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP; // BFP - No PMF_BACKWARDS_JUMP handling } else { PM_ForceLegsAnim( LEGS_JUMPB ); - pm->ps->pm_flags |= PMF_BACKWARDS_JUMP; + // pm->ps->pm_flags |= PMF_BACKWARDS_JUMP; // BFP - No PMF_BACKWARDS_JUMP handling } } } + pm->ps->pm_flags |= PMF_FALLING; // BFP - Enable PMF_FALLING flag pm->ps->groundEntityNum = ENTITYNUM_NONE; pml.groundPlane = qfalse; pml.walking = qfalse; @@ -1129,13 +1133,17 @@ static void PM_GroundTrace( void ) { if ( pm->debugLevel ) { Com_Printf("%i:kickoff\n", c_pmove); } - // go into jump animation - if ( pm->cmd.forwardmove >= 0 ) { - PM_ForceLegsAnim( LEGS_JUMP ); - pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP; - } else { - PM_ForceLegsAnim( LEGS_JUMPB ); - pm->ps->pm_flags |= PMF_BACKWARDS_JUMP; + // BFP - Check if the player is using PMF_FALLING flag in this status + if ( pm->ps->pm_flags & PMF_FALLING ) { + // go into jump animation + if ( pm->cmd.forwardmove >= 0 ) { + PM_ForceLegsAnim( LEGS_JUMP ); + // pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP; // BFP - No PMF_BACKWARDS_JUMP handling + } else { + PM_ForceLegsAnim( LEGS_JUMPB ); + // pm->ps->pm_flags |= PMF_BACKWARDS_JUMP; // BFP - No PMF_BACKWARDS_JUMP handling + } + pm->ps->pm_flags &= ~PMF_FALLING; } pm->ps->groundEntityNum = ENTITYNUM_NONE; @@ -1163,7 +1171,7 @@ static void PM_GroundTrace( void ) { // hitting solid ground will end a waterjump if (pm->ps->pm_flags & PMF_TIME_WATERJUMP) { - pm->ps->pm_flags &= ~(PMF_TIME_WATERJUMP | PMF_TIME_LAND); + pm->ps->pm_flags &= ~PMF_TIME_WATERJUMP; // BFP: before: ~(PMF_TIME_WATERJUMP | PMF_TIME_LAND); pm->ps->pm_time = 0; } @@ -1176,15 +1184,16 @@ static void PM_GroundTrace( void ) { PM_CrashLand(); // don't do landing time if we were just going down a slope - if ( pml.previous_velocity[2] < -200 ) { + if ( pml.previous_velocity[2] < -200 && !( pm->ps->pm_flags & PMF_HITSTUN ) ) { // don't allow another jump for a little while - pm->ps->pm_flags |= PMF_TIME_LAND; + // BFP - PMF_TIME_LAND doesn't exist and it doesn't have any handle checks + // pm->ps->pm_flags |= PMF_TIME_LAND; + pm->ps->pm_flags |= PMF_FALLING; // BFP - Enable PMF_FALLING flag pm->ps->pm_time = 250; } } - if ( !( pm->ps->pm_flags & PMF_FLYING ) ) // BFP - Flight - pm->ps->groundEntityNum = trace.entityNum; + pm->ps->groundEntityNum = trace.entityNum; // don't reset the z velocity for slopes // pm->ps->velocity[2] = 0; @@ -1320,6 +1329,11 @@ static void PM_Footsteps( void ) { int old; qboolean footstep; + // BFP - Hit stun + if ( pm->ps->pm_flags & PMF_HITSTUN ) { + return; + } + // // calculate speed and cycle to be used for // all cyclic walking effects @@ -1340,12 +1354,13 @@ static void PM_Footsteps( void ) { } // if not trying to move - if ( !pm->cmd.forwardmove && !pm->cmd.rightmove ) { + if ( !pm->cmd.forwardmove && !pm->cmd.rightmove + && !( pm->ps->pm_flags & PMF_HITSTUN ) ) { if ( pm->xyspeed < 5 ) { pm->ps->bobCycle = 0; // start at beginning of cycle again if ( pm->ps->pm_flags & PMF_DUCKED ) { PM_ContinueLegsAnim( LEGS_IDLECR ); - } else { + } else if ( !( pm->ps->pm_flags & PMF_KI_CHARGE ) ) { PM_ContinueLegsAnim( LEGS_IDLE ); } } @@ -1532,10 +1547,11 @@ PM_FlightAnimation ============== */ static void PM_FlightAnimation( void ) { // BFP - Flight - if ( pm->ps->pm_flags & PMF_FLYING ) { - // make sure to handle the PM_flag - pm->ps->pm_flags |= PMF_BACKWARDS_JUMP; + if ( ( pm->ps->pm_flags & PMF_FLYING ) && ( pm->ps->pm_time <= 0 ) ) { + + // make sure to handle the PMF flag + pm->ps->pm_flags |= PMF_FLIGHT_LANDING; if ( pm->cmd.forwardmove > 0 ) { PM_StartTorsoAnim( TORSO_FLYA ); @@ -1553,22 +1569,19 @@ static void PM_FlightAnimation( void ) { // BFP - Flight } // Handle the player movement animation if trying to change quickly the direction of forward or backward - if ( !pm->isFlying && !( pml.groundTrace.contents & CONTENTS_SOLID ) - && ( pm->ps->pm_flags & PMF_BACKWARDS_JUMP ) ) { + if ( !( pml.groundTrace.contents & CONTENTS_SOLID ) && ( pm->ps->pm_flags & PMF_FLIGHT_LANDING ) ) { // stops entering again here and don't change the animation to backwards/forward - pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP; + pm->ps->pm_flags &= ~PMF_FLIGHT_LANDING; - if ( pm->cmd.forwardmove > 0 ) { - PM_ForceLegsAnim( LEGS_JUMP ); - PM_StartLegsAnim( LEGS_JUMP ); - } else if ( pm->cmd.forwardmove < 0 ) { // when failing backwards after flying - PM_ForceLegsAnim( LEGS_JUMPB ); + if ( pm->cmd.forwardmove < 0 ) { // when failing backwards after flying PM_StartLegsAnim( LEGS_JUMPB ); } else { - PM_ForceLegsAnim( LEGS_JUMP ); PM_StartLegsAnim( LEGS_JUMP ); } + + // enable PMF_FALLING flag + pm->ps->pm_flags |= PMF_FALLING; } } @@ -1578,10 +1591,24 @@ PM_KiChargeAnimation ============== */ static void PM_KiChargeAnimation( void ) { // BFP - Ki Charge + + if ( ( pm->ps->pm_flags & PMF_KI_CHARGE ) && !( pm->cmd.buttons & BUTTON_KI_CHARGE ) ) { + pm->ps->pm_flags &= ~PMF_KI_CHARGE; + // If falling, then do jump animation + if ( !( pml.groundTrace.contents & CONTENTS_SOLID ) + && ( pm->ps->pm_flags & PMF_FALLING ) ) { + PM_ForceLegsAnim( LEGS_JUMP ); + } + } + if ( pm->cmd.buttons & BUTTON_KI_CHARGE ) { + // do a smooth ki charge animation and appearing the aura like BFP does + if ( !( pm->ps->pm_flags & PMF_KI_CHARGE ) ) { + pm->ps->pm_time = 300; + } + pm->ps->pm_flags |= PMF_KI_CHARGE; PM_StartTorsoAnim( TORSO_CHARGE ); - //PM_ForceLegsAnim( LEGS_CHARGE ); - PM_StartLegsAnim( LEGS_CHARGE ); + PM_ContinueLegsAnim( LEGS_CHARGE ); } } @@ -1592,12 +1619,26 @@ PM_HitStunAnimation */ static void PM_HitStunAnimation( void ) { // BFP - Hit stun - // When the player doesn't have more ki, play hit stun animation - if ( pm->ps->stats[STAT_KI] <= 0 - && pm->ps->pm_type != PM_DEAD - && pm->ps->pm_type != PM_SPECTATOR ) { + if ( pm->ps->pm_flags & PMF_HITSTUN ) { PM_StartTorsoAnim( TORSO_STUN ); - PM_ForceLegsAnim( LEGS_IDLECR ); + PM_StartLegsAnim( LEGS_IDLECR ); + } + + // When the player doesn't have more ki, play hit stun animation + if ( pm->ps->stats[STAT_KI] <= 0 && !( pm->ps->pm_flags & PMF_HITSTUN ) + || ( ( pm->ps->pm_flags & PMF_FLYING ) && pm->ps->stats[STAT_KI] <= 24 ) // If flying and has less ki, then hit stun (also BFP does that) + || ( ( pm->cmd.buttons & BUTTON_ATTACK ) && ( pm->ps->pm_flags & PMF_HITSTUN ) ) ) { + pm->ps->pm_time = 1000; + pm->ps->pm_flags |= PMF_HITSTUN; + } + + if ( ( pm->ps->pm_flags & PMF_HITSTUN ) && pm->ps->pm_time <= 0 ) { + pm->ps->pm_flags &= ~PMF_HITSTUN; + // If falling, then do jump animation + if ( !( pml.groundTrace.contents & CONTENTS_SOLID ) + && ( pm->ps->pm_flags & PMF_FALLING ) ) { + PM_ForceLegsAnim( LEGS_JUMP ); + } } } @@ -1611,6 +1652,11 @@ Generates weapon events and modifes the weapon counter static void PM_Weapon( void ) { int addTime; + // BFP - Hit stun, avoid shooting if the player is in this status + if ( pm->ps->pm_flags & PMF_HITSTUN ) { + return; + } + // don't allow attack until all buttons are up if ( pm->ps->pm_flags & PMF_RESPAWNED ) { return; @@ -1886,18 +1932,19 @@ Enables/disables flight static qboolean PM_EnableFlight( void ) { // BFP - Flight if ( !( pm->ps->pm_flags & PMF_FLYING ) ) { - if ( pm->isFlying && ( pml.groundTrace.contents & CONTENTS_SOLID ) ) { - pm->isFlying = qfalse; - } return qfalse; } - if ( pm->ps->pm_flags & PMF_FLYING ) { - if ( !pm->isFlying && ( pml.groundTrace.contents & CONTENTS_SOLID ) - && pm->ps->groundEntityNum != ENTITYNUM_NONE ) { + if ( ( pm->ps->pm_flags & PMF_FLYING ) && !( pm->ps->pm_flags & PMF_HITSTUN ) ) { + if ( ( pml.groundTrace.contents & CONTENTS_SOLID ) && pm->ps->groundEntityNum != ENTITYNUM_NONE ) { + // do a smooth jump animation like BFP does + if ( !( pm->cmd.buttons & BUTTON_KI_CHARGE ) ) { + pm->ps->pm_time = 500; + } pm->ps->velocity[2] = JUMP_VELOCITY; + PM_ForceLegsAnim( LEGS_JUMP ); + PM_StartLegsAnim( LEGS_JUMP ); } - pm->isFlying = qtrue; pm->ps->groundEntityNum = ENTITYNUM_NONE; } @@ -1914,10 +1961,17 @@ Charges ki static void PM_KiCharge( pmove_t *pmove ) { // BFP - Ki Charge pm = pmove; + // BFP - Hit stun, avoid charging if the player is in this status + if ( pm->ps->pm_flags & PMF_HITSTUN ) { + return; + } + if ( pmove->cmd.buttons & ( BUTTON_ATTACK | BUTTON_MELEE | BUTTON_KI_USE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ) ) { pmove->cmd.buttons &= ~( BUTTON_ATTACK | BUTTON_MELEE | BUTTON_KI_USE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ); } + pm->ps->pm_flags |= PMF_FALLING; + pmove->cmd.forwardmove = 0; pmove->cmd.rightmove = 0; pmove->cmd.upmove = 0; @@ -1925,7 +1979,9 @@ static void PM_KiCharge( pmove_t *pmove ) { // BFP - Ki Charge pm->ps->velocity[0] = 0; pm->ps->velocity[1] = 0; pm->ps->velocity[2] = 0; - pm->ps->stats[STAT_KI]++; + if ( ( pm->ps->pm_flags & PMF_KI_CHARGE ) && pm->ps->pm_time <= 0 ) { + pm->ps->stats[STAT_KI]++; + } } /* @@ -1938,37 +1994,16 @@ Receives hit stun static void PM_HitStun( pmove_t *pmove ) { // BFP - Hit stun pm = pmove; - if ( pmove->cmd.buttons & ( BUTTON_ATTACK | BUTTON_MELEE | BUTTON_KI_USE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ) ) { - pmove->cmd.buttons &= ~( BUTTON_ATTACK | BUTTON_MELEE | BUTTON_KI_USE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ); + if ( pmove->cmd.buttons & ( BUTTON_MELEE | BUTTON_KI_USE | BUTTON_KI_CHARGE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ) ) { + pmove->cmd.buttons &= ~( BUTTON_MELEE | BUTTON_KI_USE | BUTTON_KI_CHARGE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ); } pm->ps->pm_flags &= ~PMF_FLYING; pm->ps->pm_flags &= ~PMF_KI_BOOST; pm->ps->eFlags &= ~EF_AURA; - pmove->cmd.forwardmove = 0; - pmove->cmd.rightmove = 0; + // BFP - NOTE: BFP doesn't handle nothing the button directions when there's hit stun pmove->cmd.upmove = 0; - -// BFP - TODO: Hit stun time, maybe remove this and find another way? -#if 0 - if ( pm->ps->hitStunTime > 0 ) { - pm->ps->hitStunTime -= pml.msec; - return; - } - - // drop misc timing counter - /* - if ( pm->ps->pm_time ) { - if ( pml.msec >= pm->ps->pm_time ) { - pm->ps->pm_flags &= ~PMF_ALL_TIMES; - pm->ps->pm_time = 0; - } else { - pm->ps->pm_time -= pml.msec; - } - } - */ -#endif } /* @@ -2089,6 +2124,20 @@ void PmoveSingle (pmove_t *pmove) { pm->cmd.upmove = 0; } + // BFP - Ki Charge + if ( ( pmove->cmd.buttons & BUTTON_KI_CHARGE ) + && pm->ps->pm_type != PM_DEAD + && pm->ps->pm_type != PM_SPECTATOR ) { + PM_KiCharge( pmove ); + } + + // BFP - Hit stun + if ( ( pm->ps->pm_flags & PMF_HITSTUN ) + && pm->ps->pm_type != PM_DEAD + && pm->ps->pm_type != PM_SPECTATOR ) { + PM_HitStun( pmove ); + } + if ( pm->ps->pm_type == PM_SPECTATOR ) { PM_CheckDuck (); PM_FlyMove (); @@ -2124,38 +2173,8 @@ void PmoveSingle (pmove_t *pmove) { PM_DeadMove (); } - // BFP - Ki Charge - if ( ( pmove->cmd.buttons & BUTTON_KI_CHARGE ) - && ( pm->ps->pm_type != PM_DEAD ) ) { - PM_KiCharge( pmove ); - } - PM_DropTimers(); - // BFP - Hit stun - if ( pm->ps->stats[STAT_KI] <= 0 - && pm->ps->pm_type != PM_DEAD - && pm->ps->pm_type != PM_SPECTATOR ) { - PM_HitStun( pmove ); -// BFP - TODO: Hit stun time, maybe remove this and find another way? -#if 0 - if ( pm->ps->hitStunTime <= 0 ) { - pm->ps->hitStunTime = pml.msec + 1000; // give 1 second to be stunned - } -#endif - } -// BFP - TODO: Hit stun time, maybe remove this and find another way? -#if 0 - if ( pm->ps->hitStunTime == -3 - && pm->ps->pm_type != PM_DEAD - && pm->ps->pm_type != PM_SPECTATOR ) { // when receives attack from a ki boost melee - pm->ps->hitStunTime = pml.msec + 3000; // give 3 seconds to be stunned - } - if ( pm->ps->hitStunTime > 0 ) { - PM_HitStun( pmove ); - } -#endif - // BFP - Flight if ( PM_EnableFlight() ) { // flight powerup doesn't allow jump and has different friction diff --git a/source/game/bg_public.h b/source/game/bg_public.h index 09988d8..9519d74 100644 --- a/source/game/bg_public.h +++ b/source/game/bg_public.h @@ -143,25 +143,32 @@ typedef enum { #define PMF_DUCKED 1 #define PMF_JUMP_HELD 2 #define PMF_FLYING 4 // BFP - Flight -#define PMF_BACKWARDS_JUMP 8 // go into backwards land +// BFP - PMF_BACKWARDS_JUMP is unused +// #define PMF_BACKWARDS_JUMP 8 // go into backwards land +#define PMF_FLIGHT_LANDING 8 // BFP - Landing after disabling flight #define PMF_BACKWARDS_RUN 16 // coast down to backwards run -#define PMF_TIME_LAND 32 // pm_time is time before rejump -#define PMF_TIME_KNOCKBACK 64 // pm_time is an air-accelerate only time +// BFP - PMF_TIME_LAND is unused +// #define PMF_TIME_LAND 32 // pm_time is time before rejump +#define PMF_FALLING 32 // BFP - Falling status +// BFP - PMF_TIME_KNOCKBACK is unused +// #define PMF_TIME_KNOCKBACK 64 // pm_time is an air-accelerate only time #define PMF_KI_BOOST 128 // BFP - Using Ki #define PMF_TIME_WATERJUMP 256 // pm_time is waterjump #define PMF_RESPAWNED 512 // clear after attack and jump buttons come up #define PMF_USE_ITEM_HELD 1024 // BFP - no hook // #define PMF_GRAPPLE_PULL 2048 // pull towards grapple location +#define PMF_HITSTUN 2048 // BFP - Hit stun #define PMF_FOLLOW 4096 // spectate following another player // BFP - PMF_SCOREBOARD is unused // #define PMF_SCOREBOARD 8192 // spectate as a scoreboard +#define PMF_KI_CHARGE 8192 // BFP - Ki charge // BFP - TODO: Reuse the following flag (used on Team Arena), change name if it'll be used #define PMF_INVULEXPAND 16384 // invulnerability sphere set to full size // BFP - Last pm_flag after 32768. That's the limit of pm_flags, it can't reach more // #define PMF_SOMEFLAG 65536 // some pm_flag -#define PMF_ALL_TIMES (PMF_TIME_WATERJUMP|PMF_TIME_LAND|PMF_TIME_KNOCKBACK) +#define PMF_ALL_TIMES (PMF_TIME_WATERJUMP) // BFP: before: (PMF_TIME_WATERJUMP|PMF_TIME_LAND|PMF_TIME_KNOCKBACK) #define MAXTOUCH 32 typedef struct { @@ -174,8 +181,6 @@ typedef struct { int debugLevel; // if set, diagnostic output will be printed qboolean noFootsteps; // if the game is setup for no footsteps by the server qboolean gauntletHit; // true if a gauntlet attack would actually hit something - qboolean isFlying; // BFP - Flight - //qboolean hitStunReceived; // BFP - TODO: Hit stun int framecount; diff --git a/source/game/g_active.c b/source/game/g_active.c index a5faf7a..ef26caf 100644 --- a/source/game/g_active.c +++ b/source/game/g_active.c @@ -506,7 +506,7 @@ void ClientEvents( gentity_t *ent, int oldEventSequence ) { case EV_FALL_MEDIUM: case EV_FALL_FAR: // BFP - There's no crash land damage when the players fell in the ground - /* +#if 0 if ( ent->s.eType != ET_PLAYER ) { break; // not in the player model } @@ -521,7 +521,7 @@ void ClientEvents( gentity_t *ent, int oldEventSequence ) { VectorSet (dir, 0, 0, 1); ent->pain_debounce_time = level.time + 200; // no normal pain sound G_Damage (ent, NULL, NULL, NULL, NULL, damage, 0, MOD_FALLING); - */ +#endif break; case EV_FIRE_WEAPON: @@ -728,9 +728,10 @@ void ClientThink_real( gentity_t *ent ) { client->ps.speed = g_speed.value; // BFP - Ki use has 2 options: "kiusetoggle" to toggle and "+button8" when key is being hold - // BFP - if BUTTON_KI_USE > speed - if ( ( ucmd->buttons & BUTTON_KI_USE ) // BFP - Using Ki - || ( ent->client->ps.pm_flags & PMF_KI_BOOST ) ) { // BFP - When "kiusetoggle" is binded, enables/disables + // BFP - If BUTTON_KI_USE > speed + if ( !( ent->client->ps.pm_flags & PMF_HITSTUN ) + && ( ( ucmd->buttons & BUTTON_KI_USE ) // BFP - Using Ki + || ( ent->client->ps.pm_flags & PMF_KI_BOOST ) ) ) { // BFP - When "kiusetoggle" is binded, enables/disables ent->client->ps.speed *= 2.5; ent->client->ps.eFlags |= EF_AURA; } else { @@ -738,7 +739,7 @@ void ClientThink_real( gentity_t *ent ) { } // BFP - Ki Charge - if ( ucmd->buttons & BUTTON_KI_CHARGE ) { + if ( ( ucmd->buttons & BUTTON_KI_CHARGE ) && ent->client->ps.pm_time <= 0 ) { client->ps.eFlags |= EF_AURA; } diff --git a/source/game/g_client.c b/source/game/g_client.c index cfd017b..aa2bfb3 100644 --- a/source/game/g_client.c +++ b/source/game/g_client.c @@ -1200,7 +1200,7 @@ void ClientSpawn(gentity_t *ent) { } // don't allow full run speed for a bit - client->ps.pm_flags |= PMF_TIME_KNOCKBACK; + // client->ps.pm_flags |= PMF_TIME_KNOCKBACK; // BFP - No handling PMF_TIME_KNOCKBACK client->ps.pm_time = 100; client->respawnTime = level.time; diff --git a/source/game/g_combat.c b/source/game/g_combat.c index cc999a7..c9cd729 100644 --- a/source/game/g_combat.c +++ b/source/game/g_combat.c @@ -730,7 +730,7 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, t = 200; } targ->client->ps.pm_time = t; - targ->client->ps.pm_flags |= PMF_TIME_KNOCKBACK; + // targ->client->ps.pm_flags |= PMF_TIME_KNOCKBACK; // BFP - No handling PMF_TIME_KNOCKBACK } } diff --git a/source/game/g_misc.c b/source/game/g_misc.c index 4dc79aa..5ff5174 100644 --- a/source/game/g_misc.c +++ b/source/game/g_misc.c @@ -99,7 +99,7 @@ void TeleportPlayer( gentity_t *player, vec3_t origin, vec3_t angles ) { AngleVectors( angles, player->client->ps.velocity, NULL, NULL ); VectorScale( player->client->ps.velocity, 400, player->client->ps.velocity ); player->client->ps.pm_time = 160; // hold time - player->client->ps.pm_flags |= PMF_TIME_KNOCKBACK; + // player->client->ps.pm_flags |= PMF_TIME_KNOCKBACK; // BFP - No handling PMF_TIME_KNOCKBACK // toggle the teleport bit so the client knows to not lerp player->client->ps.eFlags ^= EF_TELEPORT_BIT; From e86dcddc4ba507c09c90d7529161e7c558da09f4 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Wed, 18 Oct 2023 01:35:32 +0100 Subject: [PATCH 002/374] game: Implement correctly the animations to handle while the player is on the ground, water and air, apply the handling for charging status and fix the unintentional jumping when the player touches the ground --- source/game/bg_pmove.c | 312 +++++++++++++++++++++++++++------------- source/game/bg_public.h | 10 +- source/game/g_cmds.c | 3 +- 3 files changed, 216 insertions(+), 109 deletions(-) diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index 3ecc1b8..d766c85 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -48,6 +48,9 @@ float pm_spectatorfriction = 5.0f; int c_pmove = 0; +// BFP - Macro for jump handling, since the code looked repetitive, so this macro makes the code a bit shorter +#define FORCEJUMP_ANIM_HANDLING() ( pm->cmd.forwardmove >= 0 ) ? PM_ForceLegsAnim( LEGS_JUMP ) : PM_ForceLegsAnim( LEGS_JUMPB ) + /* =============== PM_AddEvent @@ -379,18 +382,16 @@ static qboolean PM_CheckJump( void ) { pml.groundPlane = qfalse; // jumping away pml.walking = qfalse; pm->ps->pm_flags |= PMF_JUMP_HELD; + pm->ps->pm_flags |= PMF_NEARGROUND; // BFP - Handle PMF_NEARGROUND, avoid checking if there's ground at that point pm->ps->groundEntityNum = ENTITYNUM_NONE; pm->ps->velocity[2] = JUMP_VELOCITY; PM_AddEvent( EV_JUMP ); - if ( pm->cmd.forwardmove >= 0 ) { - PM_ForceLegsAnim( LEGS_JUMP ); - // pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP; // BFP - No PMF_BACKWARDS_JUMP handling - } else { - PM_ForceLegsAnim( LEGS_JUMPB ); - // pm->ps->pm_flags |= PMF_BACKWARDS_JUMP; // BFP - No PMF_BACKWARDS_JUMP handling - } + // BFP - No PMF_BACKWARDS_JUMP handling (code removed) + FORCEJUMP_ANIM_HANDLING(); + + PM_ContinueTorsoAnim( TORSO_STAND ); return qtrue; } @@ -534,6 +535,18 @@ static void PM_WaterMove( void ) { VectorScale(pm->ps->velocity, vel, pm->ps->velocity); } + // BFP - Water animation handling, uses flying animation in that case + if ( pm->cmd.forwardmove > 0 ) { + PM_ContinueTorsoAnim( TORSO_FLYA ); + PM_ContinueLegsAnim( LEGS_FLYA ); + } else if ( pm->cmd.forwardmove < 0 ) { + PM_ContinueTorsoAnim( TORSO_FLYB ); + PM_ContinueLegsAnim( LEGS_FLYB ); + } else { + PM_ContinueTorsoAnim( TORSO_STAND ); + PM_ContinueLegsAnim( LEGS_FLYIDLE ); + } + PM_SlideMove( qfalse ); } @@ -975,18 +988,27 @@ static void PM_CrashLand( void ) { // SURF_NODAMAGE is used for bounce pads where you don't ever // want to take damage or play a crunch sound if ( !(pml.groundTrace.surfaceFlags & SURF_NODAMAGE) ) { - if ( delta > 180 ) { // BFP - Before Q3 default value (60), so the fall in BFP is further + if ( delta > 180 ) { // BFP - Before Q3 default value (60), the far fall in BFP is deeper PM_AddEvent( EV_FALL_FAR ); - } /* else if ( delta > 40 ) { // BFP - There's no medium fall on BFP + } + // BFP - There's no medium fall on BFP +#if 0 + else if ( delta > 40 ) { // this is a pain grunt, so don't play it if dead if ( pm->ps->stats[STAT_HEALTH] > 0 ) { PM_AddEvent( EV_FALL_MEDIUM ); } - } */ else if ( delta > 7 ) { + } +#endif + else if ( delta > 7 ) { PM_AddEvent( EV_FALL_SHORT ); - } else { + } + // BFP - No footstep sounds +#if 0 + else { PM_AddEvent( PM_FootstepForSurface() ); } +#endif } // start footstep cycle over @@ -1076,20 +1098,12 @@ static void PM_GroundTraceMissed( void ) { pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask); if ( trace.fraction == 1.0 ) { - if ( pm->cmd.forwardmove >= 0 ) { - PM_ForceLegsAnim( LEGS_JUMP ); - // pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP; // BFP - No PMF_BACKWARDS_JUMP handling - } else { - PM_ForceLegsAnim( LEGS_JUMPB ); - // pm->ps->pm_flags |= PMF_BACKWARDS_JUMP; // BFP - No PMF_BACKWARDS_JUMP handling - } + // BFP - No PMF_BACKWARDS_JUMP handling (code removed) + FORCEJUMP_ANIM_HANDLING(); } } - pm->ps->pm_flags |= PMF_FALLING; // BFP - Enable PMF_FALLING flag pm->ps->groundEntityNum = ENTITYNUM_NONE; - pml.groundPlane = qfalse; - pml.walking = qfalse; } @@ -1114,6 +1128,11 @@ static void PM_GroundTrace( void ) { return; } + // BFP - No ground trace handling in the water + if ( pm->waterlevel > 1 ) { + return; + } + // do something corrective if the trace starts in a solid... if ( trace.allsolid ) { if ( !PM_CorrectAllSolid(&trace) ) @@ -1133,18 +1152,6 @@ static void PM_GroundTrace( void ) { if ( pm->debugLevel ) { Com_Printf("%i:kickoff\n", c_pmove); } - // BFP - Check if the player is using PMF_FALLING flag in this status - if ( pm->ps->pm_flags & PMF_FALLING ) { - // go into jump animation - if ( pm->cmd.forwardmove >= 0 ) { - PM_ForceLegsAnim( LEGS_JUMP ); - // pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP; // BFP - No PMF_BACKWARDS_JUMP handling - } else { - PM_ForceLegsAnim( LEGS_JUMPB ); - // pm->ps->pm_flags |= PMF_BACKWARDS_JUMP; // BFP - No PMF_BACKWARDS_JUMP handling - } - pm->ps->pm_flags &= ~PMF_FALLING; - } pm->ps->groundEntityNum = ENTITYNUM_NONE; pml.groundPlane = qfalse; @@ -1175,7 +1182,8 @@ static void PM_GroundTrace( void ) { pm->ps->pm_time = 0; } - if ( pm->ps->groundEntityNum == ENTITYNUM_NONE ) { + // BFP - Handle when the player isn't flying + if ( pm->ps->groundEntityNum == ENTITYNUM_NONE && !( pm->ps->pm_flags & PMF_FLYING ) ) { // just hit the ground if ( pm->debugLevel ) { Com_Printf("%i:Land\n", c_pmove); @@ -1183,20 +1191,24 @@ static void PM_GroundTrace( void ) { PM_CrashLand(); + // BFP - Handling the PM flag when stepping the ground + pm->ps->pm_flags &= ~PMF_NEARGROUND; + + // BFP - PMF_TIME_LAND doesn't exist and it doesn't have any handle checks +#if 0 // don't do landing time if we were just going down a slope - if ( pml.previous_velocity[2] < -200 && !( pm->ps->pm_flags & PMF_HITSTUN ) ) { + if ( pml.previous_velocity[2] < -200 ) { // don't allow another jump for a little while - // BFP - PMF_TIME_LAND doesn't exist and it doesn't have any handle checks - // pm->ps->pm_flags |= PMF_TIME_LAND; - pm->ps->pm_flags |= PMF_FALLING; // BFP - Enable PMF_FALLING flag + pm->ps->pm_flags |= PMF_TIME_LAND; pm->ps->pm_time = 250; } +#endif } pm->ps->groundEntityNum = trace.entityNum; // don't reset the z velocity for slopes -// pm->ps->velocity[2] = 0; + pm->ps->velocity[2] = 0; // BFP - Avoid jumping unintentionally when that happens PM_AddTouchEnt( trace.entityNum ); } @@ -1343,13 +1355,20 @@ static void PM_Footsteps( void ) { if ( pm->ps->groundEntityNum == ENTITYNUM_NONE ) { - // if ( pm->ps->powerups[PW_INVULNERABILITY] ) { - // PM_ContinueLegsAnim( LEGS_IDLECR ); - // } + // BFP - Unused +#if 0 + if ( pm->ps->powerups[PW_INVULNERABILITY] ) { + PM_ContinueLegsAnim( LEGS_IDLECR ); + } +#endif + + // BFP - Unused +#if 0 // airborne leaves position in cycle intact, but doesn't advance if ( pm->waterlevel > 1 ) { PM_ContinueLegsAnim( LEGS_SWIM ); } +#endif return; } @@ -1363,6 +1382,8 @@ static void PM_Footsteps( void ) { } else if ( !( pm->ps->pm_flags & PMF_KI_CHARGE ) ) { PM_ContinueLegsAnim( LEGS_IDLE ); } + } else if ( !( pm->ps->pm_flags & PMF_DUCKED ) ) { // BFP - Handle the legs while it isn't doing nothing + PM_ContinueLegsAnim( LEGS_IDLE ); } return; } @@ -1372,10 +1393,14 @@ static void PM_Footsteps( void ) { if ( pm->ps->pm_flags & PMF_DUCKED ) { bobmove = 0.5; // ducked characters bob much faster - if ( pm->ps->pm_flags & PMF_BACKWARDS_RUN ) { - PM_ContinueLegsAnim( LEGS_WALKCR ); // BFP - before LEGS_BACKCR - } else { - PM_ContinueLegsAnim( LEGS_WALKCR ); + // BFP - Replaced PMF_BACKWARDS_RUN handling + if ( pml.groundTrace.contents & CONTENTS_SOLID ) { + if ( pm->cmd.forwardmove < 0 ) { + PM_ContinueLegsAnim( LEGS_WALKCR ); // BFP - before LEGS_BACKCR + } else if ( pm->cmd.forwardmove > 0 || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { + PM_ContinueLegsAnim( LEGS_WALKCR ); + } + PM_ContinueTorsoAnim( TORSO_STAND ); // BFP - Keep the torso } // ducked characters never play footsteps /* @@ -1389,22 +1414,26 @@ static void PM_Footsteps( void ) { PM_ContinueLegsAnim( LEGS_BACK ); */ } else { - if ( !( pm->cmd.buttons & BUTTON_WALKING ) ) { + if ( !( pm->cmd.buttons & BUTTON_WALKING ) && ( pml.groundTrace.contents & CONTENTS_SOLID ) ) { bobmove = 0.4f; // faster speeds bob faster - if ( pm->ps->pm_flags & PMF_BACKWARDS_RUN ) { + // BFP - Replaced PMF_BACKWARDS_RUN handling + if ( pm->cmd.forwardmove < 0 ) { PM_ContinueLegsAnim( LEGS_BACK ); - } else { + PM_ContinueTorsoAnim( TORSO_STAND ); // BFP - Keep the torso + } else if ( pm->cmd.forwardmove > 0 || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { PM_ContinueLegsAnim( LEGS_RUN ); - PM_ContinueTorsoAnim( TORSO_RUN ); // BFP - Torso run animation + PM_ContinueTorsoAnim( TORSO_RUN ); // BFP - Keep the torso } footstep = qtrue; - } else { + } else if ( pml.groundTrace.contents & CONTENTS_SOLID ) { bobmove = 0.3f; // walking bobs slow - if ( pm->ps->pm_flags & PMF_BACKWARDS_RUN ) { + // BFP - Replaced PMF_BACKWARDS_RUN handling + if ( pm->cmd.forwardmove < 0 ) { PM_ContinueLegsAnim( LEGS_BACK ); - } else { + } else if ( pm->cmd.forwardmove > 0 || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { PM_ContinueLegsAnim( LEGS_WALK ); } + PM_ContinueTorsoAnim( TORSO_STAND ); // BFP - Keep the torso } } @@ -1491,7 +1520,8 @@ static void PM_BeginWeaponChange( int weapon ) { PM_AddEvent( EV_CHANGE_WEAPON ); pm->ps->weaponstate = WEAPON_DROPPING; pm->ps->weaponTime += 200; - PM_StartTorsoAnim( TORSO_ATTACK0_PREPARE ); // BFP - before TORSO_DROP + // BFP - Non-existant animation + // PM_StartTorsoAnim( TORSO_DROP ); } @@ -1515,7 +1545,8 @@ static void PM_FinishWeaponChange( void ) { pm->ps->weapon = weapon; pm->ps->weaponstate = WEAPON_RAISING; pm->ps->weaponTime += 250; - PM_StartTorsoAnim( TORSO_ATTACK0_PREPARE ); // BFP - before TORSO_RAISE + // BFP - Non-existant animation + // PM_StartTorsoAnim( TORSO_RAISE ); } @@ -1526,11 +1557,37 @@ PM_TorsoAnimation ============== */ static void PM_TorsoAnimation( void ) { + // BFP - NOTE: That function could be called as "PM_NearGround", + // here is tracing something similar to PM_GroundTraceMissed + trace_t trace; + vec3_t point; + + // BFP - TODO: Melee, block and ki attack animation handling (these are for torso animations) + + // BFP - No ground trace handling in the water + if ( pm->waterlevel > 1 ) { + return; + } + + VectorCopy( pm->ps->origin, point ); + point[2] -= 64; + + pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask); + pml.groundTrace = trace; - // BFP - TODO: torso animations may not be needed here, - // possibly weaponstates could be replaced/removed - // or this function could be replaced/removed + if ( trace.fraction == 1.0 && !( pm->ps->pm_flags & PMF_NEARGROUND ) ) { + pm->ps->pm_flags |= PMF_NEARGROUND; + pm->ps->pm_flags &= ~PMF_FALLING; + FORCEJUMP_ANIM_HANDLING(); + PM_ContinueTorsoAnim( TORSO_STAND ); + } + + // If idling, keep the torso + if ( !pm->cmd.forwardmove && !pm->cmd.rightmove ) { + PM_ContinueTorsoAnim( TORSO_STAND ); + } +#if 0 if ( pm->ps->weaponstate == WEAPON_READY ) { if ( pm->ps->weapon == WP_GAUNTLET ) { PM_ContinueTorsoAnim( TORSO_STAND ); // BFP - before TORSO_STAND2 @@ -1539,6 +1596,7 @@ static void PM_TorsoAnimation( void ) { } return; } +#endif } /* @@ -1551,37 +1609,33 @@ static void PM_FlightAnimation( void ) { // BFP - Flight if ( ( pm->ps->pm_flags & PMF_FLYING ) && ( pm->ps->pm_time <= 0 ) ) { // make sure to handle the PMF flag - pm->ps->pm_flags |= PMF_FLIGHT_LANDING; + pm->ps->pm_flags &= ~PMF_FALLING; if ( pm->cmd.forwardmove > 0 ) { - PM_StartTorsoAnim( TORSO_FLYA ); - PM_ForceLegsAnim( LEGS_FLYA ); - PM_StartLegsAnim( LEGS_FLYA ); + PM_ContinueTorsoAnim( TORSO_FLYA ); + PM_ContinueLegsAnim( LEGS_FLYA ); } else if ( pm->cmd.forwardmove < 0 ) { - PM_StartTorsoAnim( TORSO_FLYB ); - PM_ForceLegsAnim( LEGS_FLYB ); - PM_StartLegsAnim( LEGS_FLYB ); + PM_ContinueTorsoAnim( TORSO_FLYB ); + PM_ContinueLegsAnim( LEGS_FLYB ); } else { - // PM_ForceLegsAnim( LEGS_FLYIDLE ); + PM_ContinueTorsoAnim( TORSO_STAND ); PM_ContinueLegsAnim( LEGS_FLYIDLE ); } return; } // Handle the player movement animation if trying to change quickly the direction of forward or backward - if ( !( pml.groundTrace.contents & CONTENTS_SOLID ) && ( pm->ps->pm_flags & PMF_FLIGHT_LANDING ) ) { + if ( !( pml.groundTrace.contents & CONTENTS_SOLID ) && !( pm->ps->pm_flags & PMF_FALLING ) ) { // stops entering again here and don't change the animation to backwards/forward - pm->ps->pm_flags &= ~PMF_FLIGHT_LANDING; + pm->ps->pm_flags |= PMF_FALLING; - if ( pm->cmd.forwardmove < 0 ) { // when failing backwards after flying + if ( pm->cmd.forwardmove < 0 && !( pm->ps->pm_flags & PMF_FLYING ) ) { // when failing backwards after flying PM_StartLegsAnim( LEGS_JUMPB ); } else { PM_StartLegsAnim( LEGS_JUMP ); } - - // enable PMF_FALLING flag - pm->ps->pm_flags |= PMF_FALLING; + PM_ContinueTorsoAnim( TORSO_STAND ); } } @@ -1592,22 +1646,43 @@ PM_KiChargeAnimation */ static void PM_KiChargeAnimation( void ) { // BFP - Ki Charge + // stop charging if it's using ki boost + if ( ( pm->cmd.buttons & BUTTON_KI_USE ) && ( pm->cmd.buttons & BUTTON_KI_CHARGE ) ) { + // handle the button to avoid toggling the animations forward and backwards while using ki boost + pm->cmd.buttons &= ~BUTTON_KI_CHARGE; + } + + if ( ( pm->cmd.buttons & BUTTON_KI_USE ) && ( pm->ps->pm_flags & PMF_KI_CHARGE ) ) { + pm->ps->pm_flags &= ~PMF_KI_CHARGE; + pm->ps->pm_time = 0; + // do jump animation if it's falling + if ( !( pml.groundTrace.contents & CONTENTS_SOLID ) + && !( pm->ps->pm_flags & PMF_FLYING ) + && ( pm->ps->pm_flags & PMF_FALLING ) ) { + pm->ps->pm_flags &= ~PMF_FALLING; // Handle PMF_FALLING when falling + FORCEJUMP_ANIM_HANDLING(); + PM_ContinueTorsoAnim( TORSO_STAND ); // Keep the torso + } + return; + } + if ( ( pm->ps->pm_flags & PMF_KI_CHARGE ) && !( pm->cmd.buttons & BUTTON_KI_CHARGE ) ) { pm->ps->pm_flags &= ~PMF_KI_CHARGE; - // If falling, then do jump animation + // do jump animation if it's falling if ( !( pml.groundTrace.contents & CONTENTS_SOLID ) && ( pm->ps->pm_flags & PMF_FALLING ) ) { - PM_ForceLegsAnim( LEGS_JUMP ); + FORCEJUMP_ANIM_HANDLING(); + PM_ContinueTorsoAnim( TORSO_STAND ); // Keep the torso } } - if ( pm->cmd.buttons & BUTTON_KI_CHARGE ) { + if ( ( pm->cmd.buttons & BUTTON_KI_CHARGE ) ) { // do a smooth ki charge animation and appearing the aura like BFP does if ( !( pm->ps->pm_flags & PMF_KI_CHARGE ) ) { pm->ps->pm_time = 300; } pm->ps->pm_flags |= PMF_KI_CHARGE; - PM_StartTorsoAnim( TORSO_CHARGE ); + PM_ContinueTorsoAnim( TORSO_CHARGE ); PM_ContinueLegsAnim( LEGS_CHARGE ); } } @@ -1620,13 +1695,13 @@ PM_HitStunAnimation static void PM_HitStunAnimation( void ) { // BFP - Hit stun if ( pm->ps->pm_flags & PMF_HITSTUN ) { - PM_StartTorsoAnim( TORSO_STUN ); + PM_ContinueTorsoAnim( TORSO_STUN ); PM_StartLegsAnim( LEGS_IDLECR ); } // When the player doesn't have more ki, play hit stun animation if ( pm->ps->stats[STAT_KI] <= 0 && !( pm->ps->pm_flags & PMF_HITSTUN ) - || ( ( pm->ps->pm_flags & PMF_FLYING ) && pm->ps->stats[STAT_KI] <= 24 ) // If flying and has less ki, then hit stun (also BFP does that) + || ( ( pm->ps->pm_flags & PMF_FLYING ) && pm->ps->stats[STAT_KI] <= 24 ) // BFP - TODO: Apply some timer if used any ki, if flying and has less ki, then hit stun (also BFP does that) || ( ( pm->cmd.buttons & BUTTON_ATTACK ) && ( pm->ps->pm_flags & PMF_HITSTUN ) ) ) { pm->ps->pm_time = 1000; pm->ps->pm_flags |= PMF_HITSTUN; @@ -1634,10 +1709,11 @@ static void PM_HitStunAnimation( void ) { // BFP - Hit stun if ( ( pm->ps->pm_flags & PMF_HITSTUN ) && pm->ps->pm_time <= 0 ) { pm->ps->pm_flags &= ~PMF_HITSTUN; - // If falling, then do jump animation + // do jump animation if it's falling if ( !( pml.groundTrace.contents & CONTENTS_SOLID ) && ( pm->ps->pm_flags & PMF_FALLING ) ) { - PM_ForceLegsAnim( LEGS_JUMP ); + FORCEJUMP_ANIM_HANDLING(); + PM_ContinueTorsoAnim( TORSO_STAND ); // Keep the torso } } } @@ -1715,15 +1791,18 @@ static void PM_Weapon( void ) { return; } + // BFP - No weapon raising handling +#if 0 if ( pm->ps->weaponstate == WEAPON_RAISING ) { pm->ps->weaponstate = WEAPON_READY; if ( pm->ps->weapon == WP_GAUNTLET ) { - PM_StartTorsoAnim( TORSO_STAND ); // BFP - before TORSO_STAND2 + PM_StartTorsoAnim( TORSO_STAND2 ); } else { PM_StartTorsoAnim( TORSO_STAND ); } return; } +#endif // check for fire if ( ! (pm->cmd.buttons & BUTTON_ATTACK) ) { @@ -1732,6 +1811,8 @@ static void PM_Weapon( void ) { return; } + // BFP - No weapon gauntlet handling +#if 0 // start the animation even if out of ammo if ( pm->ps->weapon == WP_GAUNTLET ) { // the guantlet only "fires" when it actually hits something @@ -1744,6 +1825,7 @@ static void PM_Weapon( void ) { } else { PM_StartTorsoAnim( TORSO_STAND ); } +#endif pm->ps->weaponstate = WEAPON_FIRING; @@ -1935,6 +2017,12 @@ static qboolean PM_EnableFlight( void ) { // BFP - Flight return qfalse; } + // do not proceed to the jump event while enables the flight in the charging status + if ( ( pm->ps->pm_flags & PMF_KI_CHARGE ) && ( pm->ps->pm_flags & PMF_FLYING ) ) { + pm->ps->groundEntityNum = ENTITYNUM_NONE; + return qfalse; + } + if ( ( pm->ps->pm_flags & PMF_FLYING ) && !( pm->ps->pm_flags & PMF_HITSTUN ) ) { if ( ( pml.groundTrace.contents & CONTENTS_SOLID ) && pm->ps->groundEntityNum != ENTITYNUM_NONE ) { // do a smooth jump animation like BFP does @@ -1943,7 +2031,6 @@ static qboolean PM_EnableFlight( void ) { // BFP - Flight } pm->ps->velocity[2] = JUMP_VELOCITY; PM_ForceLegsAnim( LEGS_JUMP ); - PM_StartLegsAnim( LEGS_JUMP ); } pm->ps->groundEntityNum = ENTITYNUM_NONE; } @@ -1958,27 +2045,34 @@ PM_KiCharge Charges ki ================ */ -static void PM_KiCharge( pmove_t *pmove ) { // BFP - Ki Charge - pm = pmove; +static void PM_KiCharge( void ) { // BFP - Ki Charge // BFP - Hit stun, avoid charging if the player is in this status if ( pm->ps->pm_flags & PMF_HITSTUN ) { return; } - if ( pmove->cmd.buttons & ( BUTTON_ATTACK | BUTTON_MELEE | BUTTON_KI_USE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ) ) { - pmove->cmd.buttons &= ~( BUTTON_ATTACK | BUTTON_MELEE | BUTTON_KI_USE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ); - } + // BFP - TODO: Handle the fall while charging - pm->ps->pm_flags |= PMF_FALLING; + pm->cmd.forwardmove = 0; + pm->cmd.rightmove = 0; + pm->cmd.upmove = 0; - pmove->cmd.forwardmove = 0; - pmove->cmd.rightmove = 0; - pmove->cmd.upmove = 0; + VectorClear( pm->ps->velocity ); + + // stop charging if it's using ki boost + if ( ( pm->cmd.buttons & BUTTON_KI_USE ) && ( pm->cmd.buttons & BUTTON_KI_CHARGE ) ) { + pm->ps->pm_flags &= ~PMF_KI_CHARGE; + pm->cmd.buttons &= ~BUTTON_KI_CHARGE; + pm->ps->pm_time = 0; + return; + } - pm->ps->velocity[0] = 0; - pm->ps->velocity[1] = 0; - pm->ps->velocity[2] = 0; + if ( pm->cmd.buttons & ( BUTTON_ATTACK | BUTTON_KI_USE | BUTTON_MELEE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ) ) { + pm->cmd.buttons &= ~( BUTTON_ATTACK | BUTTON_KI_USE | BUTTON_MELEE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ); + } + + pm->ps->pm_flags |= PMF_FALLING; // Handle PMF_FALLING flag if ( ( pm->ps->pm_flags & PMF_KI_CHARGE ) && pm->ps->pm_time <= 0 ) { pm->ps->stats[STAT_KI]++; } @@ -1991,11 +2085,10 @@ PM_HitStun Receives hit stun ================ */ -static void PM_HitStun( pmove_t *pmove ) { // BFP - Hit stun - pm = pmove; +static void PM_HitStun( void ) { // BFP - Hit stun - if ( pmove->cmd.buttons & ( BUTTON_MELEE | BUTTON_KI_USE | BUTTON_KI_CHARGE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ) ) { - pmove->cmd.buttons &= ~( BUTTON_MELEE | BUTTON_KI_USE | BUTTON_KI_CHARGE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ); + if ( pm->cmd.buttons & ( BUTTON_MELEE | BUTTON_KI_USE | BUTTON_KI_CHARGE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ) ) { + pm->cmd.buttons &= ~( BUTTON_MELEE | BUTTON_KI_USE | BUTTON_KI_CHARGE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ); } pm->ps->pm_flags &= ~PMF_FLYING; @@ -2003,7 +2096,7 @@ static void PM_HitStun( pmove_t *pmove ) { // BFP - Hit stun pm->ps->eFlags &= ~EF_AURA; // BFP - NOTE: BFP doesn't handle nothing the button directions when there's hit stun - pmove->cmd.upmove = 0; + pm->cmd.upmove = 0; } /* @@ -2043,6 +2136,11 @@ void PmoveSingle (pmove_t *pmove) { pm->ps->eFlags &= ~EF_TALK; } + // BFP - Handling the PM flag when stepping the ground + if ( pm->ps->pm_flags & PMF_RESPAWNED ) { + pm->ps->pm_flags |= PMF_FALLING; + } + // set the firing flag for continuous beam weapons if ( !(pm->ps->pm_flags & PMF_RESPAWNED) && pm->ps->pm_type != PM_INTERMISSION && ( pm->cmd.buttons & BUTTON_ATTACK ) && pm->ps->ammo[ pm->ps->weapon ] ) { @@ -2099,12 +2197,15 @@ void PmoveSingle (pmove_t *pmove) { pm->ps->pm_flags &= ~PMF_JUMP_HELD; } + // BFP - No handling PMF_BACKWARDS_RUN +#if 0 // decide if backpedaling animations should be used if ( pm->cmd.forwardmove < 0 ) { pm->ps->pm_flags |= PMF_BACKWARDS_RUN; } else if ( pm->cmd.forwardmove > 0 || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { pm->ps->pm_flags &= ~PMF_BACKWARDS_RUN; } +#endif if ( pm->ps->pm_type >= PM_DEAD ) { @@ -2126,16 +2227,17 @@ void PmoveSingle (pmove_t *pmove) { // BFP - Ki Charge if ( ( pmove->cmd.buttons & BUTTON_KI_CHARGE ) + && !( pmove->cmd.buttons & BUTTON_KI_USE ) && pm->ps->pm_type != PM_DEAD && pm->ps->pm_type != PM_SPECTATOR ) { - PM_KiCharge( pmove ); + PM_KiCharge(); } // BFP - Hit stun if ( ( pm->ps->pm_flags & PMF_HITSTUN ) && pm->ps->pm_type != PM_DEAD && pm->ps->pm_type != PM_SPECTATOR ) { - PM_HitStun( pmove ); + PM_HitStun(); } if ( pm->ps->pm_type == PM_SPECTATOR ) { @@ -2203,9 +2305,10 @@ void PmoveSingle (pmove_t *pmove) { PM_Animate(); + // BFP - No ground trace again // set groundentity, watertype, and waterlevel - PM_GroundTrace(); - PM_SetWaterLevel(); + // PM_GroundTrace(); + // PM_SetWaterLevel(); // weapons PM_Weapon(); @@ -2284,3 +2387,6 @@ void Pmove (pmove_t *pmove) { } +// BFP - Undefine the macro of jump handling +#undef FORCEJUMP_ANIM_HANDLING + diff --git a/source/game/bg_public.h b/source/game/bg_public.h index 9519d74..54abfd8 100644 --- a/source/game/bg_public.h +++ b/source/game/bg_public.h @@ -145,8 +145,9 @@ typedef enum { #define PMF_FLYING 4 // BFP - Flight // BFP - PMF_BACKWARDS_JUMP is unused // #define PMF_BACKWARDS_JUMP 8 // go into backwards land -#define PMF_FLIGHT_LANDING 8 // BFP - Landing after disabling flight -#define PMF_BACKWARDS_RUN 16 // coast down to backwards run +#define PMF_NEARGROUND 8 // BFP - Near ground check +// BFP - PMF_BACKWARDS_RUN is unused +// #define PMF_BACKWARDS_RUN 16 // coast down to backwards run // BFP - PMF_TIME_LAND is unused // #define PMF_TIME_LAND 32 // pm_time is time before rejump #define PMF_FALLING 32 // BFP - Falling status @@ -545,8 +546,7 @@ typedef enum { TORSO_ATTACK4_STRIKE, // BFP // BFP - The following attackset animations are just reminders, these aren't used as variables - - /* +/* // BFP - (point finger right hand) TORSO_ATTACK5_PREPARE, // BFP TORSO_ATTACK5_STRIKE, // BFP @@ -594,7 +594,7 @@ typedef enum { // BFP - (ken and ryu fireball) TORSO_ATTACK16_PREPARE, // BFP TORSO_ATTACK16_STRIKE, // BFP - */ +*/ // BFP - The following animations are useless, // possibly can be removed only if the game works as should diff --git a/source/game/g_cmds.c b/source/game/g_cmds.c index a219664..b46a8ae 100644 --- a/source/game/g_cmds.c +++ b/source/game/g_cmds.c @@ -1598,7 +1598,8 @@ Cmd_BFP_Fly_f void Cmd_BFP_Fly_f( gentity_t* ent ) { // BFP - Flight if ( ent->client->ps.pm_type != PM_DEAD ) { - if ( !( ent->client->ps.pm_flags & PMF_FLYING ) ) { + // do not play the sound in the charging status + if ( !( ent->client->ps.pm_flags & PMF_FLYING ) && !( ent->client->ps.pm_flags & PMF_KI_CHARGE ) ) { G_AddEvent( ent, EV_JUMP, 0 ); // play jump sound } ent->client->ps.pm_flags ^= PMF_FLYING; From 8aaf5d775a4c8fabd2d94c6d714213f315be9a99 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Fri, 20 Oct 2023 00:42:14 +0100 Subject: [PATCH 003/374] cgame: Handle frametime to avoid being timescaled for the traceable crosshair and cg_flytilt --- source/cgame/cg_draw.c | 17 +++++++++++++---- source/cgame/cg_view.c | 32 +++++++++++++++++++++----------- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/source/cgame/cg_draw.c b/source/cgame/cg_draw.c index 4d0e4b5..b546fe4 100644 --- a/source/cgame/cg_draw.c +++ b/source/cgame/cg_draw.c @@ -1711,6 +1711,15 @@ static void CG_DrawCrosshair(void) { #endif static float lastPositionY = 480.0f; // BFP - Last Y position for traceable crosshair to move smoothly like BFP vanilla does + // BFP - Frametime handling + static int previous; + int t, frameTime; + + // BFP - Handle frametime to avoid being timescaled + t = trap_Milliseconds(); + frameTime = t - previous; + previous = t; + // BFP - TODO: BFP doesn't use the crosshair as player view, // e.g. if the camera angle is 90º, the crosshair should look what's in this view, // not what the player sees @@ -1788,12 +1797,12 @@ static void CG_DrawCrosshair(void) { CG_AdjustFrom640( &x, &y, &w, &h ); // BFP - Make the traceable crosshair move smoothly like BFP vanilla does - // LERP( , , (float)(cg.frametime / 1000.00f) * ); + // LERP( , , (float)(frameTime / 1000.00f) * ); #if ESF_STYLE - x = LERP( lastPositionX, x, (float)(cg.frametime / 1000.00f) * 18.0f ); - y = LERP( lastPositionY, y, (float)(cg.frametime / 1000.00f) * 18.0f ); + x = LERP( lastPositionX, x, (float)(frameTime / 1000.00f) * 18.0f ); + y = LERP( lastPositionY, y, (float)(frameTime / 1000.00f) * 18.0f ); #else - y = LERP( lastPositionY, y, (float)(cg.frametime / 1000.00f) * 12.0f ); + y = LERP( lastPositionY, y, (float)(frameTime / 1000.00f) * 12.0f ); #endif trap_R_DrawStretchPic( x - 0.5f * w, // 492.799987 diff --git a/source/cgame/cg_view.c b/source/cgame/cg_view.c index 67cb3f5..81a9b1a 100644 --- a/source/cgame/cg_view.c +++ b/source/cgame/cg_view.c @@ -237,6 +237,14 @@ static void CG_OffsetThirdPersonView( void ) { // BFP - Last angled for fly tilt angle to move smoothly similar to BFP vanilla static float lastAngled = 0.0f, lastRightAngled = 0.0f, lastUpAngled = 0.0f; float rightAngled, upAngled; + // BFP - Frametime handling + static int previous; + int t, frameTime; + + // BFP - Handle frametime to avoid being timescaled + t = trap_Milliseconds(); + frameTime = t - previous; + previous = t; // BFP - Camera setup camAngle = cg_thirdPersonAngle.value; @@ -332,21 +340,23 @@ static void CG_OffsetThirdPersonView( void ) { cmdNum = trap_GetCurrentCmdNumber(); trap_GetUserCmd( cmdNum, &cmd ); - focusAngles[ROLL] = LERP( lastAngled, 0.0f, (float)(cg.frametime / 1000.00f) * 20.0f ); - rightAngled = LERP( lastRightAngled, 0.0f, (float)(cg.frametime / 1000.00f) * 20.0f ); - upAngled = LERP( lastUpAngled, 0.0f, (float)(cg.frametime / 1000.00f) * 20.0f ); + // BFP - TODO: If cg_thirdPersonAngle is changed, the roll rotation should be moved like in 0º (or fixed) + + focusAngles[ROLL] = LERP( lastAngled, 0.0f, (float)(frameTime / 1000.00f) * 20.0f ); + rightAngled = LERP( lastRightAngled, 0.0f, (float)(frameTime / 1000.00f) * 20.0f ); + upAngled = LERP( lastUpAngled, 0.0f, (float)(frameTime / 1000.00f) * 20.0f ); if ( cg_flytilt.integer >= 1 && ( cg.predictedPlayerState.pm_flags & PMF_FLYING ) && ( cg.predictedPlayerState.eFlags & EF_AURA ) && &cmd ) { - if ( cmd.rightmove < 0 ) { // Left - focusAngles[ROLL] = LERP( lastAngled, -20.0f, (float)(cg.frametime / 1000.00f) * 15.0f ); - rightAngled = LERP( lastRightAngled, focusAngles[ROLL] - 0.55f, (float)(cg.frametime / 1000.00f) * 15.0f ); - upAngled = LERP( lastUpAngled, -acos( focusAngles[ROLL] / 180 * M_PI ) - 1.7f, (float)(cg.frametime / 1000.00f) * 15.0f ); - } else if ( cmd.rightmove > 0 ) { // Right - focusAngles[ROLL] = LERP( lastAngled, 20.0f, (float)(cg.frametime / 1000.00f) * 15.0f ); - rightAngled = LERP( lastRightAngled, focusAngles[ROLL] - 0.55f, (float)(cg.frametime / 1000.00f) * 15.0f ); - upAngled = LERP( lastUpAngled, -acos( focusAngles[ROLL] / 180 * M_PI ) - 1.7f, (float)(cg.frametime / 1000.00f) * 15.0f ); + if ( cmd.rightmove < 0 && ( cmd.buttons & BUTTON_KI_USE ) ) { // Left + focusAngles[ROLL] = LERP( lastAngled, -20.0f, (float)(frameTime / 1000.00f) * 15.0f ); + rightAngled = LERP( lastRightAngled, focusAngles[ROLL] - 0.55f, (float)(frameTime / 1000.00f) * 15.0f ); + upAngled = LERP( lastUpAngled, -acos( focusAngles[ROLL] / 180 * M_PI ) - 1.7f, (float)(frameTime / 1000.00f) * 15.0f ); + } else if ( cmd.rightmove > 0 && ( cmd.buttons & BUTTON_KI_USE ) ) { // Right + focusAngles[ROLL] = LERP( lastAngled, 20.0f, (float)(frameTime / 1000.00f) * 15.0f ); + rightAngled = LERP( lastRightAngled, focusAngles[ROLL] - 0.55f, (float)(frameTime / 1000.00f) * 15.0f ); + upAngled = LERP( lastUpAngled, -acos( focusAngles[ROLL] / 180 * M_PI ) - 1.7f, (float)(frameTime / 1000.00f) * 15.0f ); } } // Last roll where it was "lerped" From 0d90fa8f4205d8038d17fc9e0cff3a0b495360dc Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sun, 22 Oct 2023 23:11:42 +0100 Subject: [PATCH 004/374] q3_ui: Add macros to shorten the number of parameters --- source/q3_ui/ui_controls2.c | 106 +++++++++++++++++++----------------- 1 file changed, 56 insertions(+), 50 deletions(-) diff --git a/source/q3_ui/ui_controls2.c b/source/q3_ui/ui_controls2.c index 61dd546..3c66b8d 100644 --- a/source/q3_ui/ui_controls2.c +++ b/source/q3_ui/ui_controls2.c @@ -269,63 +269,69 @@ static controls_t s_controls; static vec4_t controls_binding_color = {0.90f, 0.90f, 1.00f, 1.00f}; // BFP - Changed to light blue gray (before orange: {1.00f, 0.43f, 0.00f, 1.00f}) +// BFP - A macro to shorten the number of parameters of key bindings +#define G_BINDING_KEY(command, label, id, anim, keybind) {command, label, id, anim, keybind, -1, -1, -1}, static bind_t g_bindings[] = { - {"+scores", "show scores", ID_SHOWSCORES, ANIM_IDLE, K_TAB, -1, -1, -1}, - {"+button2", "use item", ID_USEITEM, ANIM_IDLE, K_ENTER, -1, -1, -1}, - {"+speed", "run / walk", ID_SPEED, ANIM_RUN, K_SHIFT, -1, -1, -1}, - {"+forward", "walk forward", ID_FORWARD, ANIM_WALK, K_UPARROW, -1, -1, -1}, - {"+back", "backpedal", ID_BACKPEDAL, ANIM_BACK, K_DOWNARROW, -1, -1, -1}, - {"+moveleft", "step left", ID_MOVELEFT, ANIM_STEPLEFT, ',', -1, -1, -1}, - {"+moveright", "step right", ID_MOVERIGHT, ANIM_STEPRIGHT, '.', -1, -1, -1}, - {"+moveup", "up / jump", ID_MOVEUP, ANIM_JUMP, K_SPACE, -1, -1, -1}, - {"+movedown", "down / crouch", ID_MOVEDOWN, ANIM_CROUCH, 'c', -1, -1, -1}, - {"+left", "turn left", ID_LEFT, ANIM_TURNLEFT, K_LEFTARROW, -1, -1, -1}, - {"+right", "turn right", ID_RIGHT, ANIM_TURNRIGHT, K_RIGHTARROW, -1, -1, -1}, - {"+strafe", "sidestep / turn", ID_STRAFE, ANIM_IDLE, K_ALT, -1, -1, -1}, - {"+button12", "fly", ID_ENABLEFLIGHT,ANIM_FLY, 'f', -1, -1, -1}, // BFP - flight control "fly" bind - {"+lookup", "look up", ID_LOOKUP, ANIM_LOOKUP, K_PGDN, -1, -1, -1}, - {"+lookdown", "look down", ID_LOOKDOWN, ANIM_LOOKDOWN, K_DEL, -1, -1, -1}, - {"+mlook", "mouse look", ID_MOUSELOOK, ANIM_IDLE, '/', -1, -1, -1}, - {"centerview", "center view", ID_CENTERVIEW, ANIM_IDLE, K_END, -1, -1, -1}, - {"+zoom", "zoom view", ID_ZOOMVIEW, ANIM_IDLE, -1, -1, -1, -1}, - {"weapon 1", "ki attack 1", ID_KIATTACK1, ANIM_KIATTACK1, '1', -1, -1, -1}, // BFP - ki attack 1 (before gauntlet) - {"weapon 2", "ki attack 2", ID_KIATTACK2, ANIM_KIATTACK2, '2', -1, -1, -1}, // BFP - ki attack 2 (before machinegun) - {"weapon 3", "ki attack 3", ID_KIATTACK3, ANIM_KIATTACK3, '3', -1, -1, -1}, // BFP - ki attack 3 (before shotgun) - {"weapon 4", "ki attack 4", ID_KIATTACK4, ANIM_KIATTACK4, '4', -1, -1, -1}, // BFP - ki attack 4 (before grenade launcher) - {"weapon 5", "ki attack 5", ID_KIATTACK5, ANIM_KIATTACK5, '5', -1, -1, -1}, // BFP - ki attack 5 (before rocket launcher) - //{"weapon 6", "lightning", ID_WEAPON6, ANIM_WEAPON6, '6', -1, -1, -1}, // BFP - unused - //{"weapon 7", "railgun", ID_WEAPON7, ANIM_WEAPON7, '7', -1, -1, -1}, // BFP - unused - //{"weapon 8", "plasma gun", ID_WEAPON8, ANIM_WEAPON8, '8', -1, -1, -1}, // BFP - unused - //{"weapon 9", "BFG", ID_WEAPON9, ANIM_WEAPON9, '9', -1, -1, -1}, // BFP - unused - {"+attack", "attack", ID_ATTACK, ANIM_KIATTACK1, K_CTRL, -1, -1, -1}, - {"+button7", "Melee Combat", ID_MELEE, ANIM_MELEE, K_ALT, -1, -1, -1}, // BFP - melee - {"+button10", "Block", ID_BLOCK, ANIM_BLOCK, K_CTRL, -1, -1, -1}, // BFP - block - {"weapprev", "prev weapon", ID_WEAPPREV, ANIM_IDLE, '[', -1, -1, -1}, - {"weapnext", "next weapon", ID_WEAPNEXT, ANIM_IDLE, ']', -1, -1, -1}, - {"+button3", "gesture", ID_GESTURE, ANIM_GESTURE, K_MOUSE3, -1, -1, -1}, - {"messagemode", "chat", ID_CHAT, ANIM_CHAT, 't', -1, -1, -1}, - {"messagemode2", "chat - team", ID_CHAT2, ANIM_CHAT, -1, -1, -1, -1}, - {"messagemode3", "chat - target", ID_CHAT3, ANIM_CHAT, -1, -1, -1, -1}, - {"messagemode4", "chat - attacker", ID_CHAT4, ANIM_CHAT, -1, -1, -1, -1}, - {"+button9", "Charge Ki", ID_KICHARGE, ANIM_KICHARGE, K_MOUSE2, -1, -1, -1}, // BFP - charge ki control - {"kiusetoggle", "Use Ki (toggle)", ID_KIUSETOGGLE, ANIM_IDLE, 'e', -1, -1, -1}, // BFP - use ki toggle control - {"+button8", "Use Ki", ID_KIUSE, ANIM_IDLE, K_SHIFT, -1, -1, -1}, // BFP - use ki control - {(char*)NULL, (char*)NULL, 0, 0, -1, -1, -1, -1}, + G_BINDING_KEY( "+scores", "show scores", ID_SHOWSCORES, ANIM_IDLE, K_TAB ) + G_BINDING_KEY( "+button2", "use item", ID_USEITEM, ANIM_IDLE, K_ENTER ) + G_BINDING_KEY( "+speed", "run / walk", ID_SPEED, ANIM_RUN, K_SHIFT ) + G_BINDING_KEY( "+forward", "walk forward", ID_FORWARD, ANIM_WALK, K_UPARROW ) + G_BINDING_KEY( "+back", "backpedal", ID_BACKPEDAL, ANIM_BACK, K_DOWNARROW ) + G_BINDING_KEY( "+moveleft", "step left", ID_MOVELEFT, ANIM_STEPLEFT, ',' ) + G_BINDING_KEY( "+moveright", "step right", ID_MOVERIGHT, ANIM_STEPRIGHT, '.' ) + G_BINDING_KEY( "+moveup", "up / jump", ID_MOVEUP, ANIM_JUMP, K_SPACE ) + G_BINDING_KEY( "+movedown", "down / crouch", ID_MOVEDOWN, ANIM_CROUCH, 'c' ) + G_BINDING_KEY( "+left", "turn left", ID_LEFT, ANIM_TURNLEFT, K_LEFTARROW ) + G_BINDING_KEY( "+right", "turn right", ID_RIGHT, ANIM_TURNRIGHT, K_RIGHTARROW ) + G_BINDING_KEY( "+strafe", "sidestep / turn", ID_STRAFE, ANIM_IDLE, K_ALT ) + G_BINDING_KEY( "+button12", "fly", ID_ENABLEFLIGHT,ANIM_FLY, 'f' ) // BFP - flight control "fly" bind + G_BINDING_KEY( "+lookup", "look up", ID_LOOKUP, ANIM_LOOKUP, K_PGDN ) + G_BINDING_KEY( "+lookdown", "look down", ID_LOOKDOWN, ANIM_LOOKDOWN, K_DEL ) + G_BINDING_KEY( "+mlook", "mouse look", ID_MOUSELOOK, ANIM_IDLE, '/' ) + G_BINDING_KEY( "centerview", "center view", ID_CENTERVIEW, ANIM_IDLE, K_END ) + G_BINDING_KEY( "+zoom", "zoom view", ID_ZOOMVIEW, ANIM_IDLE, -1 ) + G_BINDING_KEY( "weapon 1", "ki attack 1", ID_KIATTACK1, ANIM_KIATTACK1, '1' ) // BFP - ki attack 1 (before gauntlet) + G_BINDING_KEY( "weapon 2", "ki attack 2", ID_KIATTACK2, ANIM_KIATTACK2, '2' ) // BFP - ki attack 2 (before machinegun) + G_BINDING_KEY( "weapon 3", "ki attack 3", ID_KIATTACK3, ANIM_KIATTACK3, '3' ) // BFP - ki attack 3 (before shotgun) + G_BINDING_KEY( "weapon 4", "ki attack 4", ID_KIATTACK4, ANIM_KIATTACK4, '4' ) // BFP - ki attack 4 (before grenade launcher) + G_BINDING_KEY( "weapon 5", "ki attack 5", ID_KIATTACK5, ANIM_KIATTACK5, '5' ) // BFP - ki attack 5 (before rocket launcher) + //G_BINDING_KEY( "weapon 6", "lightning", ID_WEAPON6, ANIM_WEAPON6, '6' ) // BFP - unused + //G_BINDING_KEY( "weapon 7", "railgun", ID_WEAPON7, ANIM_WEAPON7, '7' ) // BFP - unused + //G_BINDING_KEY( "weapon 8", "plasma gun", ID_WEAPON8, ANIM_WEAPON8, '8' ) // BFP - unused + //G_BINDING_KEY( "weapon 9", "BFG", ID_WEAPON9, ANIM_WEAPON9, '9' ) // BFP - unused + G_BINDING_KEY( "+attack", "attack", ID_ATTACK, ANIM_KIATTACK1, K_CTRL ) + G_BINDING_KEY( "+button7", "Melee Combat", ID_MELEE, ANIM_MELEE, K_ALT ) // BFP - melee + G_BINDING_KEY( "+button10", "Block", ID_BLOCK, ANIM_BLOCK, K_CTRL ) // BFP - block + G_BINDING_KEY( "weapprev", "prev weapon", ID_WEAPPREV, ANIM_IDLE, '[' ) + G_BINDING_KEY( "weapnext", "next weapon", ID_WEAPNEXT, ANIM_IDLE, ']' ) + G_BINDING_KEY( "+button3", "gesture", ID_GESTURE, ANIM_GESTURE, K_MOUSE3 ) + G_BINDING_KEY( "messagemode", "chat", ID_CHAT, ANIM_CHAT, 't' ) + G_BINDING_KEY( "messagemode2", "chat - team", ID_CHAT2, ANIM_CHAT, -1 ) + G_BINDING_KEY( "messagemode3", "chat - target", ID_CHAT3, ANIM_CHAT, -1 ) + G_BINDING_KEY( "messagemode4", "chat - attacker", ID_CHAT4, ANIM_CHAT, -1 ) + G_BINDING_KEY( "+button9", "Charge Ki", ID_KICHARGE, ANIM_KICHARGE, K_MOUSE2 ) // BFP - charge ki control + G_BINDING_KEY( "kiusetoggle", "Use Ki (toggle)", ID_KIUSETOGGLE, ANIM_IDLE, 'e' ) // BFP - use ki toggle control + G_BINDING_KEY( "+button8", "Use Ki", ID_KIUSE, ANIM_IDLE, K_SHIFT ) // BFP - use ki control + G_BINDING_KEY( (char*)NULL, (char*)NULL, 0, 0, -1 ) }; +#undef G_BINDING_KEY +// BFP - A macro to shorten the number of parameters of configcvars +#define G_CONFIGCVAR(cvarname) {cvarname, 0, 0}, static configcvar_t g_configcvars[] = { - {"cl_run", 0, 0}, - {"m_pitch", 0, 0}, - {"cg_autoswitch", 0, 0}, - {"sensitivity", 0, 0}, - {"in_joystick", 0, 0}, - {"joy_threshold", 0, 0}, - {"m_filter", 0, 0}, - {"cl_freelook", 0, 0}, - {NULL, 0, 0} + G_CONFIGCVAR( "cl_run" ) + G_CONFIGCVAR( "m_pitch" ) + G_CONFIGCVAR( "cg_autoswitch" ) + G_CONFIGCVAR( "sensitivity" ) + G_CONFIGCVAR( "in_joystick" ) + G_CONFIGCVAR( "joy_threshold" ) + G_CONFIGCVAR( "m_filter" ) + G_CONFIGCVAR( "cl_freelook" ) + G_CONFIGCVAR( NULL ) }; +#undef G_CONFIGCVAR static menucommon_s *g_movement_controls[] = { From 78abcbe54b6915f7a6156208fbdc2a9c76a1f45e Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 23 Oct 2023 00:46:55 +0100 Subject: [PATCH 005/374] cgame: Implement correctly the aura, apply smoke effect when touching the ground but (still not implemented at all yet) and apply swinging angles when the player rotates the torso and legs (still not implemented at all yet) --- docs/bfp_cvars_task.md | 8 +- source/cgame/cg_cvar.h | 5 + source/cgame/cg_local.h | 5 +- source/cgame/cg_main.c | 5 +- source/cgame/cg_players.c | 305 ++++++++++++++++++++++++++------------ 5 files changed, 230 insertions(+), 98 deletions(-) diff --git a/docs/bfp_cvars_task.md b/docs/bfp_cvars_task.md index 3b8ccef..73dc250 100644 --- a/docs/bfp_cvars_task.md +++ b/docs/bfp_cvars_task.md @@ -34,7 +34,6 @@ ## WIP: - g_hitStun [0/1]: turn on or off the melee hit stun. -- cg_drawKiWarning [0/1]: turn on or off the low ki warning. #### Cvar Gametypes: @@ -45,7 +44,6 @@ - cg_stfu [0/1]: disable character voices when firing attacks. - cg_lowpolysphere [0/1]: force the use of a lower polycount sphere. - cg_kitrail [0-99]: set the length of the ki trail. 0 turns it off. -- cg_lightauras [0/1]: turn on or off the aura dynamic lights. - cg_lightexplosions [0/1]: turn on or off the explosion dynamic lights. - cg_chargeupAlert [0/1]: turn on or off the "ready" message when charging attacks. - cg_explosionShell [0/1]: turn on or off the explosion shell. @@ -66,6 +64,12 @@ - [x] ~~cg_crosshairColor~~ - [x] ~~cg_crosshairHealth~~ - [x] ~~cg_flytilt~~ +- [x] ~~cg_drawKiWarning~~ +- [x] ~~cg_lightAuras~~ +- [x] ~~cg_smallOwnAura~~ +- [x] ~~cg_lightweightAuras~~ +- [x] ~~cg_polygonAura~~ +- [x] ~~cg_highPolyAura~~ #### Cvar Gametypes: diff --git a/source/cgame/cg_cvar.h b/source/cgame/cg_cvar.h index 84c902b..e90abac 100644 --- a/source/cgame/cg_cvar.h +++ b/source/cgame/cg_cvar.h @@ -72,6 +72,11 @@ CG_CVAR( cg_fixedThirdPerson, "cg_fixedThirdPerson", "1", CVAR_ARCHIVE ) // BFP CG_CVAR( cg_drawOwnModel, "cg_drawOwnModel", "1", CVAR_ARCHIVE ) // BFP - toggle first person between traditional and vis modes CG_CVAR( cg_drawKiWarning, "cg_drawKiWarning", "1", CVAR_ARCHIVE ) // BFP - Ki warning CG_CVAR( cg_stableCrosshair, "cg_stableCrosshair", "0", CVAR_ARCHIVE ) // BFP - Accurate crosshair +CG_CVAR( cg_lightAuras, "cg_lightAuras", "1", CVAR_ARCHIVE ) // BFP - Light auras +CG_CVAR( cg_smallOwnAura, "cg_smallOwnAura", "0", CVAR_ARCHIVE ) // BFP - Small own aura +CG_CVAR( cg_lightweightAuras, "cg_lightweightAuras", "0", CVAR_ARCHIVE ) // BFP - Lightweight auras +CG_CVAR( cg_polygonAura, "cg_polygonAura", "1", CVAR_ARCHIVE ) // BFP - Polygonal aura +CG_CVAR( cg_highPolyAura, "cg_highPolyAura", "1", CVAR_ARCHIVE ) // BFP - High polycount aura CG_CVAR( cg_thirdPerson, "cg_thirdPerson", "1", 0 ) // BFP CG_CVAR( cg_yrgolroxor, "cg_yrgolroxor", "0", 0 ) // BFP - Yrgol Roxor easter egg CG_CVAR( cg_teamChatTime, "cg_teamChatTime", "3000", CVAR_ARCHIVE ) diff --git a/source/cgame/cg_local.h b/source/cgame/cg_local.h index d46ecab..89d5d9e 100644 --- a/source/cgame/cg_local.h +++ b/source/cgame/cg_local.h @@ -769,7 +769,10 @@ typedef struct { qhandle_t backauraModel; // BFP - Back aura model qhandle_t flyauraModel; // BFP - Fly aura model qhandle_t runauraModel; // BFP - Run aura model - qhandle_t auraEffectShader; // BFP - Aura shader + // BFP - Aura shaders + qhandle_t auraRedShader; + qhandle_t auraBlueShader; + qhandle_t auraYellowShader; // scoreboard headers qhandle_t scoreboardName; diff --git a/source/cgame/cg_main.c b/source/cgame/cg_main.c index 9b13581..1f4e6d7 100644 --- a/source/cgame/cg_main.c +++ b/source/cgame/cg_main.c @@ -622,7 +622,10 @@ static void CG_RegisterGraphics( void ) { cgs.media.backauraModel = trap_R_RegisterModel( "models/effects/backaura.md3" ); // BFP - Back aura model cgs.media.flyauraModel = trap_R_RegisterModel( "models/effects/flyaura.md3" ); // BFP - Fly aura model cgs.media.runauraModel = trap_R_RegisterModel( "models/effects/runaura.md3" ); // BFP - Run aura model - cgs.media.auraEffectShader = trap_R_RegisterShader( "powerups/redtiny" ); // BFP - Aura shader + // BFP - Aura shaders + cgs.media.auraBlueShader = trap_R_RegisterShader( "powerups/bluetiny" ); + cgs.media.auraRedShader = trap_R_RegisterShader( "powerups/redtiny" ); + cgs.media.auraYellowShader = trap_R_RegisterShader( "powerups/yellowtiny" ); memset( cg_items, 0, sizeof( cg_items ) ); memset( cg_weapons, 0, sizeof( cg_weapons ) ); diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index 1fc004c..57012b3 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -252,10 +252,10 @@ static qboolean CG_ParseAnimationFile( const char *filename, clientInfo_t *ci ) // crouch backward animation memcpy(&animations[LEGS_WALKCR], &animations[LEGS_WALKCR], sizeof(animation_t)); // BFP - Crouch backwards animation tweak - animations[LEGS_WALKCR].reversed = qtrue; + animations[LEGS_WALKCR].reversed = qfalse; // BFP - Make the duck walking forward only // walk backward animation memcpy(&animations[LEGS_WALK], &animations[LEGS_WALK], sizeof(animation_t)); // BFP - Walk backwards animation tweak - animations[LEGS_WALK].reversed = qtrue; + animations[LEGS_WALK].reversed = qfalse; // BFP - Make the walk moving forward only // flag moving fast animations[FLAG_RUN].firstFrame = 0; animations[FLAG_RUN].numFrames = 16; @@ -1420,9 +1420,10 @@ static void CG_PlayerAngles( centity_t *cent, vec3_t legs[3], vec3_t torso[3], v legsAngles[YAW] = headAngles[YAW] + movementOffsets[ dir ]; torsoAngles[YAW] = headAngles[YAW] + 0.25 * movementOffsets[ dir ]; + // BFP - Swing the angles to make the movements look smooth // torso - CG_SwingAngles( torsoAngles[YAW], 25, 90, cg_swingSpeed.value, ¢->pe.torso.yawAngle, ¢->pe.torso.yawing ); - CG_SwingAngles( legsAngles[YAW], 40, 90, cg_swingSpeed.value, ¢->pe.legs.yawAngle, ¢->pe.legs.yawing ); + CG_SwingAngles( torsoAngles[YAW], 40, 90, cg_swingSpeed.value, ¢->pe.torso.yawAngle, ¢->pe.torso.yawing ); + CG_SwingAngles( legsAngles[YAW], 90, 90, cg_swingSpeed.value, ¢->pe.legs.yawAngle, ¢->pe.legs.yawing ); torsoAngles[YAW] = cent->pe.torso.yawAngle; legsAngles[YAW] = cent->pe.legs.yawAngle; @@ -1481,9 +1482,21 @@ static void CG_PlayerAngles( centity_t *cent, vec3_t legs[3], vec3_t torso[3], v // BFP - when flying, set correctly into these angles if ( cg.predictedPlayerState.pm_flags & PMF_FLYING ) { - VectorCopy( cent->lerpAngles, headAngles ); - VectorCopy( cent->lerpAngles, torsoAngles ); - VectorCopy( cent->lerpAngles, legsAngles ); + //VectorCopy( cent->lerpAngles, headAngles ); + //VectorCopy( cent->lerpAngles, torsoAngles ); + // only show a fraction of the pitch angle in the torso + VectorCopy( torsoAngles, legsAngles ); + + CG_SwingAngles( torsoAngles[YAW], 40, 90, cg_swingSpeed.value, ¢->pe.torso.yawAngle, ¢->pe.torso.yawing ); + CG_SwingAngles( legsAngles[YAW], 40, 90, cg_swingSpeed.value, ¢->pe.legs.yawAngle, ¢->pe.legs.yawing ); + + torsoAngles[YAW] = cent->pe.torso.yawAngle; + legsAngles[YAW] = cent->pe.torso.yawAngle; + + //legsAngles[YAW] = torsoAngles[YAW]; + //CG_SwingAngles( torsoAngles[YAW], 40, 90, cg_swingSpeed.value, ¢->pe.torso.yawAngle, ¢->pe.torso.yawing ); + //CG_SwingAngles( legsAngles[YAW], 90, 90, cg_swingSpeed.value, ¢->pe.legs.yawAngle, ¢->pe.legs.yawing ); + //VectorCopy( cent->lerpAngles, legsAngles ); } // pain twitch @@ -1513,27 +1526,32 @@ static void CG_HasteTrail( centity_t *cent ) { if ( cent->trailTime > cg.time ) { return; } + // BFP - No handling running and backwards animations +#if 0 anim = cent->pe.legs.animationNumber & ~ANIM_TOGGLEBIT; if ( anim != LEGS_RUN && anim != LEGS_BACK ) { return; } +#endif - cent->trailTime += 100; + cent->trailTime += 50; // BFP - TODO: Just a test (before 100) if ( cent->trailTime < cg.time ) { cent->trailTime = cg.time; } + // BFP - TODO: Make the smoke move up (always) and move a bit on the left or right (randomly) + VectorCopy( cent->lerpOrigin, origin ); origin[2] -= 16; smoke = CG_SmokePuff( origin, vec3_origin, - 8, - 1, 1, 1, 1, - 500, - cg.time, - 0, - 0, - cgs.media.hastePuffShader ); + 70, // BFP - TODO: Before 8, sizes between 50 ~ 70 + 1, 1, 1, 1, + 500, + cg.time, + 0, + 0, + cgs.media.hastePuffShader ); // use the optimized local entity add smoke->leType = LE_SCALE_FADE; @@ -1701,12 +1719,13 @@ static void CG_PlayerPowerups( centity_t *cent, refEntity_t *torso ) { trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&31), 0.2f, 0.2f, 1 ); } + // BFP - No flight powerup +#if 0 // flight plays a looped sound - /* if ( powerups & ( 1 << PW_FLIGHT ) ) { trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, cgs.media.flightSound ); } - */ +#endif ci = &cgs.clientinfo[ cent->currentState.clientNum ]; // redflag @@ -1742,10 +1761,13 @@ static void CG_PlayerPowerups( centity_t *cent, refEntity_t *torso ) { trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&31), 1.0, 1.0, 1.0 ); } + // BFP - No haste powerup handling +#if 0 // haste leaves smoke trails if ( powerups & ( 1 << PW_HASTE ) ) { CG_HasteTrail( cent ); } +#endif } @@ -1797,7 +1819,8 @@ static void CG_PlayerSprites( centity_t *cent ) { return; } - if ( cent->currentState.eFlags & EF_TALK ) { + if ( cent->currentState.eFlags & EF_TALK + && cent->currentState.number != cg.snap->ps.clientNum ) { // BFP - Don't show the chat ballon to the player itself CG_PlayerFloatSprite( cent, cgs.media.balloonShader ); return; } @@ -1857,6 +1880,7 @@ static qboolean CG_PlayerShadow( centity_t *cent, float *shadowPlane ) { vec3_t end, mins = {-15, -15, 0}, maxs = {15, 15, 2}; trace_t trace; float alpha; + int contents; // BFP - To detect if there is water or lava *shadowPlane = 0; @@ -1882,6 +1906,25 @@ static qboolean CG_PlayerShadow( centity_t *cent, float *shadowPlane ) { *shadowPlane = trace.endpos[2] + 1; + // BFP - TODO: Only show smoke where the shadow is and make one smoke of each moving to the air, + // disappearing randomly according to time, making bigger according the size like BFP does + // CG_SmokePuff will help you to find out how to do + + // BFP - Smoke trail when using ki boost on the ground + contents = CG_PointContents( trace.endpos, -1 ); + if ( ( cent->currentState.eFlags & EF_AURA ) + && !( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) + && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_IDLE + && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_IDLECR + && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_JUMP + && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_JUMPB + && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_FLYIDLE + && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_CHARGE + && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_WALK + && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_WALKCR ) { + CG_HasteTrail( cent ); + } + if ( cg_shadows.integer != 1 ) { // no mark for stencil or projection shadows return qtrue; } @@ -2000,6 +2043,7 @@ Also called by CG_Missile for quad rockets, but nobody can tell... */ void CG_AddRefEntityWithPowerups( refEntity_t *ent, entityState_t *state, int team ) { + if ( state->powerups & ( 1 << PW_INVIS ) ) { ent->customShader = cgs.media.invisShader; trap_R_AddRefEntityToScene( ent ); @@ -2016,6 +2060,21 @@ void CG_AddRefEntityWithPowerups( refEntity_t *ent, entityState_t *state, int te trap_R_AddRefEntityToScene( ent ); //} + // BFP - If the player is using lightweight auras or their own small aura + if ( ( state->eFlags & EF_AURA ) + && ( cg_lightweightAuras.integer > 0 + || cg_smallOwnAura.integer > 0 ) ) { + // BFP - TODO: If player is transformed: + // ent->customShader = cgs.media.auraYellowShader; + + if ( team == TEAM_BLUE) { + ent->customShader = cgs.media.auraBlueShader; + } else { + ent->customShader = cgs.media.auraRedShader; + } + trap_R_AddRefEntityToScene( ent ); + } + if ( state->powerups & ( 1 << PW_QUAD ) ) { if (team == TEAM_RED) @@ -2095,14 +2154,13 @@ void CG_Player( centity_t *cent ) { refEntity_t torso; refEntity_t head; refEntity_t aura; // BFP - Aura + refEntity_t aura2; // BFP - Secondary aura int clientNum; int renderfx; qboolean shadow; float shadowPlane; - // BFP - Aura vertical rotation variables - float auraRotation; - float sinAura, cosAura; - float tmp0, tmp1; + int aura_i, aura_j; // BFP - For aura sizes + vec3_t auraInverseRotation; // BFP - For aura inverse rotation // the client number is stored in clientNum. It can't be derived // from the entity number, because a single client may have @@ -2121,7 +2179,8 @@ void CG_Player( centity_t *cent ) { // get the player model information renderfx = 0; - if ( cent->currentState.number == cg.snap->ps.clientNum) { + // BFP - Don't make the players look to the others with the same torso position + // if ( cent->currentState.number == cg.snap->ps.clientNum) { if (!cg.renderingThirdPerson) { renderfx = RF_THIRD_PERSON; // only draw in mirrors } /*else { // BFP - cg_cameraMode cvar doesn't exist @@ -2129,13 +2188,14 @@ void CG_Player( centity_t *cent ) { return; } }*/ - } + // } memset( &legs, 0, sizeof(legs) ); memset( &torso, 0, sizeof(torso) ); memset( &head, 0, sizeof(head) ); memset( &aura, 0, sizeof(aura) ); // BFP - Aura + memset( &aura2, 0, sizeof(aura2) ); // BFP - Secondary aura // get the rotation information CG_PlayerAngles( cent, legs.axis, torso.axis, head.axis ); @@ -2147,72 +2207,6 @@ void CG_Player( centity_t *cent ) { // add the talk baloon or disconnect icon CG_PlayerSprites( cent ); - // BFP - Aura ki using - if ( cent->currentState.eFlags & EF_AURA ) { - aura.reType = RT_MODEL; - aura.customShader = cgs.media.auraEffectShader; - aura.hModel = cgs.media.auraModel; - - // reset axis model postion - AxisClear( aura.axis ); - - // fixes rotation when player rotates down/up/right/left... even while flying - // according legs position - // cent->lerpAngles is according player base entity position - AnglesToAxis( ¢->pe.legs.pitchAngle, aura.axis ); - - // set aura position to the player - VectorCopy( cent->lerpOrigin, aura.origin ); - - // BFP - when flying, set correctly into these angles - if ( cg.predictedPlayerState.pm_flags & PMF_FLYING ) { - AnglesToAxis( cent->lerpAngles, aura.axis ); - } - - // BFP - TODO: Aura vertical rotation, aura rotates vertically, - // but when player is flying, Z-axis isn't respecting player's position and angles - /* - auraRotation = cg.time * 0.15f * ( M_PI / 180.0f ); - sinAura = sin( auraRotation ); - cosAura = cos( auraRotation ); - tmp0 = aura.axis[0][0]; - tmp1 = aura.axis[0][1]; - - aura.axis[0][0] = cosAura * tmp0 - sinAura * aura.axis[1][0]; - aura.axis[0][1] = cosAura * tmp1 - sinAura * aura.axis[1][1]; - aura.axis[1][0] = sinAura * tmp0 + cosAura * aura.axis[1][0]; - aura.axis[1][1] = sinAura * tmp1 + cosAura * aura.axis[1][1]; - */ - - trap_R_AddRefEntityToScene( &aura ); - - aura.renderfx = renderfx; - - // BFP - TODO: Add secondary aura and with little size - // who knows why, BFP does that as well - //VectorScale( aura.axis[0], 0.9, aura.axis[0] ); - //VectorScale( aura.axis[1], 0.9, aura.axis[1] ); - //VectorScale( aura.axis[2], 0.9, aura.axis[2] ); - - // BFP - TODO: rotate secondary aura in the opposite direction - //trap_R_AddRefEntityToScene( &aura ); // add secondary aura, but it doesn't respect the angles to the player model - // or should do that so? - // CG_AddRefEntityWithPowerups( &aura, ¢->currentState, 0 ); - - // light blinking - trap_R_AddLightToScene( aura.origin, 100 + (rand()&32), 1, 0.01f, 0.002f ); - trap_R_AddLightToScene( cent->lerpOrigin, 80 + (rand()&11), 1, 0.15f, 0.001f ); - - // BFP - Ki boost and ki charge sounds - if ( ( cent->currentState.torsoAnim & ~ANIM_TOGGLEBIT ) != TORSO_CHARGE ) { - trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, - vec3_origin, cgs.media.kiUseSound ); - } else if ( ( cent->currentState.torsoAnim & ~ANIM_TOGGLEBIT ) == TORSO_CHARGE ) { - trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, - vec3_origin, cgs.media.kiChargeSound ); - } - } - // add the shadow shadow = CG_PlayerShadow( cent, &shadowPlane ); @@ -2292,6 +2286,130 @@ void CG_Player( centity_t *cent ) { CG_AddRefEntityWithPowerups( &head, ¢->currentState, ci->team ); + // + // BFP - Aura + // + // Macro for the size of the aura model + #define AURA_MODEL_SIZE(aura, aura_size) \ + for ( aura_i = 0; aura_i < 3; aura_i++ ) { \ + for ( aura_j = 0; aura_j < 3; aura_j++ ) { \ + aura.axis[aura_i][aura_j] *= aura_size; \ + } \ + } + + // Macro to handle the aura animations, when idling it sets the aura vertical rotation, so the aura rotates vertically + #define AURA_ANIMS(aura, reversed) \ + if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_RUN \ + || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_JUMP ) { \ + aura.hModel = cgs.media.runauraModel; \ + } else if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_BACK \ + || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_JUMPB \ + || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYB ) { \ + aura.hModel = cgs.media.backauraModel; \ + } else if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYA ) { \ + aura.hModel = cgs.media.flyauraModel; \ + } else { \ + aura.hModel = cgs.media.auraModel; \ + if ( reversed ) { \ + VectorNegate( cg.autoAngles, auraInverseRotation ); \ + AnglesToAxis( auraInverseRotation, aura.axis ); \ + } else { \ + AnglesToAxis( cg.autoAngles, aura.axis ); \ + } \ + } + + // Macro for the dynamic aura light, note: when charging it changes the shinning a bit + #define AURA_LIGHT(r, g, b) \ + if ( cg_lightAuras.integer > 0 ) { \ + if ( cg_smallOwnAura.integer > 0 ) { \ + trap_R_AddLightToScene( torso.origin, 200 + (rand()&255), r, g, b ); \ + trap_R_AddLightToScene( legs.origin, 200 + (rand()&255), r, g, b ); \ + trap_R_AddLightToScene( aura.origin, 200 + (rand()&255), r, g, b ); \ + trap_R_AddLightToScene( aura2.origin, 200 + (rand()&255), r, g, b ); \ + } \ + if ( cg_lightweightAuras.integer > 0 ) { \ + trap_R_AddLightToScene( torso.origin, 80 + (rand()&83), r, g, b ); \ + trap_R_AddLightToScene( legs.origin, 80 + (rand()&63), r, g, b ); \ + trap_R_AddLightToScene( aura.origin, 80 + (rand()&63), r, g, b ); \ + } else { \ + trap_R_AddLightToScene( torso.origin, 80 + (rand()&63), r, g, b ); \ + trap_R_AddLightToScene( legs.origin, 200 + (rand()&63), r, g, b ); \ + trap_R_AddLightToScene( aura.origin, 200 + (rand()&255), r, g, b ); \ + if ( !( cg.predictedPlayerState.pm_flags & PMF_KI_CHARGE ) ) { \ + trap_R_AddLightToScene( aura2.origin, 200 + (rand()&255), r, g, b ); \ + } \ + } \ + } + + if ( cent->currentState.eFlags & EF_AURA ) { + // Apply the render type + aura.reType = aura2.reType = RT_MODEL; + + // Clear the axis to keep the position + AxisClear( aura.axis ); + AxisClear( aura2.axis ); + + // If the player is moving like going forward and backwards, then use other aura model + AURA_ANIMS( aura, 0 ) + AURA_ANIMS( aura2, 1 ) + + // Resize the aura + AURA_MODEL_SIZE( aura, 1.3f ) + AURA_MODEL_SIZE( aura2, 1.49f ) + + // Set aura position to the player + VectorCopy( legs.origin, aura.origin ); + VectorCopy( legs.lightingOrigin, aura.lightingOrigin ); + VectorCopy( legs.origin, aura2.origin ); + VectorCopy( legs.lightingOrigin, aura2.lightingOrigin ); + + // BFP - TODO: Add yellow aura only when the player is transformed, but don't override when playing a team gamemode + // aura.customShader = aura2.customShader = cgs.media.auraYellowShader; + // Don't put this line of code here if transformed, just put outside the check EF_AURA conditional + // trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), 1.0, 1.0, 0 ); + + // Apply light blinking + if ( ci->team == TEAM_BLUE) { + aura.customShader = aura2.customShader = cgs.media.auraBlueShader; + AURA_LIGHT( 0.2f, 0.2f, 1.0 ) + } else { + aura.customShader = aura2.customShader = cgs.media.auraRedShader; + AURA_LIGHT( 1.0, 0.2f, 0.2f ) + } + + aura.renderfx = aura2.renderfx = renderfx; + VectorCopy( aura.origin, aura.oldorigin ); // don't positionally lerp at all + VectorCopy( aura2.origin, aura2.oldorigin ); // don't positionally lerp at all + + // Ki boost and ki charge sounds + if ( ( cent->currentState.torsoAnim & ~ANIM_TOGGLEBIT ) != TORSO_CHARGE ) { + trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, + vec3_origin, cgs.media.kiUseSound ); + } else if ( ( cent->currentState.torsoAnim & ~ANIM_TOGGLEBIT ) == TORSO_CHARGE ) { + trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, + vec3_origin, cgs.media.kiChargeSound ); + } + + // Keep the aura pivot tagged in tag_torso + if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_RUN + || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_BACK + || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_FLYA + || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_FLYB ) { + CG_PositionRotatedEntityOnTag( &aura, &legs, ci->legsModel, "tag_torso" ); + CG_PositionRotatedEntityOnTag( &aura2, &legs, ci->legsModel, "tag_torso" ); + } + + // Add aura + if ( cg_polygonAura.integer > 0 && cg_smallOwnAura.integer <= 0 ) { + trap_R_AddRefEntityToScene( &aura ); + } + + // Add secondary aura to make look cooler, a bit bigger than the other + if ( cg_polygonAura.integer > 0 && cg_highPolyAura.integer > 0 && cg_smallOwnAura.integer <= 0 ) { + trap_R_AddRefEntityToScene( &aura2 ); + } + } + // // add the gun / barrel / flash // @@ -2300,16 +2418,15 @@ void CG_Player( centity_t *cent ) { // add powerups floating behind the player CG_PlayerPowerups( cent, &torso ); - // BFP - Smoke trail when using Ki boost in the ground - if ( cent->currentState.eFlags & EF_AURA ) { - CG_HasteTrail( cent ); - } // BFP - First person camera setup if ( cg_thirdPerson.integer <= 0 && cent->currentState.number == cg.snap->ps.clientNum ) { // BFP - Avoid every time some player/bot enters in the server and changes the view into the other player CG_OffsetFirstPersonView( cent, &torso, ci->torsoModel ); } } +#undef AURA_MODEL_SIZE +#undef AURA_ANIMS +#undef AURA_LIGHT /* =============== From fa59c1569e53f028358b91a90d0d400f79e34834 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Tue, 24 Oct 2023 00:34:42 +0100 Subject: [PATCH 006/374] game: Apply PMF_KI_BOOST handling when it has been used once on 'kiusetoggle' bind and after pressing a binded only-pressing key --- source/game/bg_pmove.c | 8 +++++++- source/game/g_active.c | 4 +++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index d766c85..86a903b 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -1676,15 +1676,21 @@ static void PM_KiChargeAnimation( void ) { // BFP - Ki Charge } } - if ( ( pm->cmd.buttons & BUTTON_KI_CHARGE ) ) { + if ( pm->cmd.buttons & BUTTON_KI_CHARGE ) { // do a smooth ki charge animation and appearing the aura like BFP does if ( !( pm->ps->pm_flags & PMF_KI_CHARGE ) ) { pm->ps->pm_time = 300; } + pm->ps->pm_flags &= ~PMF_KI_BOOST; pm->ps->pm_flags |= PMF_KI_CHARGE; PM_ContinueTorsoAnim( TORSO_CHARGE ); PM_ContinueLegsAnim( LEGS_CHARGE ); } + + // handle the button to avoid toggling ki boost when already used "kiusetoggle" key bind + if ( ( pm->cmd.buttons & BUTTON_KI_USE ) && ( pm->ps->pm_flags & PMF_KI_BOOST ) ) { + pm->ps->pm_flags &= ~PMF_KI_BOOST; + } } /* diff --git a/source/game/g_active.c b/source/game/g_active.c index ef26caf..dbab22d 100644 --- a/source/game/g_active.c +++ b/source/game/g_active.c @@ -735,7 +735,9 @@ void ClientThink_real( gentity_t *ent ) { ent->client->ps.speed *= 2.5; ent->client->ps.eFlags |= EF_AURA; } else { - ent->client->ps.eFlags &= ~EF_AURA; + if ( !( ucmd->buttons & BUTTON_KI_CHARGE ) ) { // BFP - If it's charging while it was using ki boost, don't remove the aura! + ent->client->ps.eFlags &= ~EF_AURA; + } } // BFP - Ki Charge From f267458ccbb8fbe31ccb5c67a9d97c86b998fcea Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Wed, 25 Oct 2023 00:04:35 +0100 Subject: [PATCH 007/374] cgame - game: Set and place the original Q3 first person camera mode correctly --- source/cgame/cg_view.c | 14 +++++++------- source/game/bg_pmove.c | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/source/cgame/cg_view.c b/source/cgame/cg_view.c index 81a9b1a..9f68238 100644 --- a/source/cgame/cg_view.c +++ b/source/cgame/cg_view.c @@ -816,14 +816,13 @@ static int CG_CalcViewValues( void ) { if ( cg.renderingThirdPerson && ps->pm_type != PM_SPECTATOR ) { // back away from character CG_OffsetThirdPersonView(); - } -// BFP - Original Q3 first person view function call, not used here, moved to cg_players.c in CG_Player function -#if 0 - else { + } else { // offset for local bobbing and kicks - CG_OffsetFirstPersonView(); + // BFP - That only handles if cg_drawOwnModel is disabled + if ( cg_thirdPerson.integer <= 0 && cg_drawOwnModel.integer <= 0 ) { + CG_OffsetFirstPersonView( NULL, NULL, 0 ); + } } -#endif // position eye reletive to origin AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis ); @@ -944,7 +943,8 @@ void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demo CG_PredictPlayerState(); // decide on third person view - cg.renderingThirdPerson = cg_drawOwnModel.integer || (cg.snap->ps.stats[STAT_HEALTH] <= 0); //cg_thirdPerson.integer || (cg.snap->ps.stats[STAT_HEALTH] <= 0); + // BFP - Also cg_drawOwnModel handles + cg.renderingThirdPerson = cg_thirdPerson.integer || cg_drawOwnModel.integer || (cg.snap->ps.stats[STAT_HEALTH] <= 0); // build cg.refdef inwater = CG_CalcViewValues(); diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index 86a903b..fa33c88 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -1278,7 +1278,7 @@ static void PM_CheckDuck (void) VectorSet( pm->maxs, 15, 15, 16 ); } pm->ps->pm_flags |= PMF_DUCKED; - // pm->ps->viewheight = CROUCH_VIEWHEIGHT; // BFP - don't look a bit down while pressing down + pm->ps->viewheight = CROUCH_VIEWHEIGHT; return; } pm->ps->pm_flags &= ~PMF_INVULEXPAND; @@ -1317,7 +1317,7 @@ static void PM_CheckDuck (void) if (pm->ps->pm_flags & PMF_DUCKED) { pm->maxs[2] = 16; - // pm->ps->viewheight = CROUCH_VIEWHEIGHT; // BFP - don't look a bit down while pressing down + pm->ps->viewheight = CROUCH_VIEWHEIGHT; } else { From d0906946af59a257a0350340ed6c7f78f0e3f836 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Wed, 25 Oct 2023 01:29:06 +0100 Subject: [PATCH 008/374] q3_ui: Fix the configurations since it was messed up and tidy some code in BFP OPTIONS menu --- source/q3_ui/ui_bfpoptions.c | 250 ++++++++++++++++++++--------------- 1 file changed, 140 insertions(+), 110 deletions(-) diff --git a/source/q3_ui/ui_bfpoptions.c b/source/q3_ui/ui_bfpoptions.c index 5eb3151..88061b0 100644 --- a/source/q3_ui/ui_bfpoptions.c +++ b/source/q3_ui/ui_bfpoptions.c @@ -36,15 +36,26 @@ BFP OPTIONS MENU #define ID_FLIGHTILT 154 #define ID_BIGHEADS 155 #define ID_DEFAULTSKINS 156 -#define ID_DISABLEVOICES 157 +#define ID_STFU 157 #define ID_LOWPOLYSPHERE 158 #define ID_BACK 159 +// Macros to handle the cases in that order +#define SHADER_AURA 0 +#define LIGHTWEIGHT_AURA 1 +#define POLYGON_AURA 2 +#define HIGHPOLYCOUNT_AURA 3 + +#define WIMPY_EXPLO 0 +#define WEAK_EXPLO 1 +#define SO_SO_EXPLO 2 +#define HARDCORE_EXPLO 3 + static const char *auratype_items[] = { - "High Polycount Aura", - "Polygonal Aura", "Shader Aura", "Lightweight Aura", + "Polygonal Aura", + "High Polycount Aura", NULL }; @@ -56,10 +67,10 @@ static const char *viewpoint_items[] = { }; static const char* explotype_items[] = { - "So-So", - "Hardcore", "Wimpy", "Weak", + "So-So", + "Hardcore", NULL }; @@ -89,7 +100,7 @@ typedef struct { menuradiobutton_s flightilt; menuradiobutton_s bigheads; menuradiobutton_s defaultskins; - menuradiobutton_s disablevoices; + menuradiobutton_s stfu; menuradiobutton_s lowpolysphere; menubitmap_s back; @@ -97,106 +108,113 @@ typedef struct { static bfpoptions_t s_bfpoptions; +// A macro to look better the code +#define BFPOPTIONS_MENUITEM( menu_item_curvalue, cvar ) \ + menu_item_curvalue = trap_Cvar_VariableValue( cvar ) != 0; + static void BFPOptions_SetMenuItems( void ) { - s_bfpoptions.fix3person.curvalue = trap_Cvar_VariableValue( "cg_fixedThirdPerson" ) != 0; - s_bfpoptions.particlesfx.curvalue = trap_Cvar_VariableValue( "cg_particles" ) != 0; - s_bfpoptions.dynauralight.curvalue = trap_Cvar_VariableValue( "cg_lightAuras" ) != 0; - s_bfpoptions.dynexplolights.curvalue = trap_Cvar_VariableValue( "cg_lightExplosions" ) != 0; - s_bfpoptions.transaura.curvalue = trap_Cvar_VariableValue( "cg_transformationAura" ) != 0; - s_bfpoptions.smallaura.curvalue = trap_Cvar_VariableValue( "cg_smallOwnAura" ) != 0; - s_bfpoptions.ssjglow.curvalue = trap_Cvar_VariableValue( "cg_permaglowUltimate" ) != 0; - s_bfpoptions.accucrosshair.curvalue = trap_Cvar_VariableValue( "cg_stableCrosshair" ) != 0; - s_bfpoptions.simplehud.curvalue = trap_Cvar_VariableValue( "cg_simpleHUD" ) != 0; - s_bfpoptions.chargealert.curvalue = trap_Cvar_VariableValue( "cg_chargeupAlert" ) != 0; - s_bfpoptions.q3hitsfx.curvalue = trap_Cvar_VariableValue( "cg_playHitSound" ) != 0; - s_bfpoptions.flightilt.curvalue = trap_Cvar_VariableValue( "cg_flytilt" ) != 0; - s_bfpoptions.bigheads.curvalue = trap_Cvar_VariableValue( "cg_superdeformed" ) != 0; - s_bfpoptions.defaultskins.curvalue = trap_Cvar_VariableValue( "cg_forceSkin" ) != 0; - s_bfpoptions.disablevoices.curvalue = trap_Cvar_VariableValue( "cg_stfu" ) != 0; - s_bfpoptions.lowpolysphere.curvalue = trap_Cvar_VariableValue( "cg_lowpolysphere" ) != 0; + BFPOPTIONS_MENUITEM( s_bfpoptions.fix3person.curvalue, "cg_fixedThirdPerson" ) + BFPOPTIONS_MENUITEM( s_bfpoptions.particlesfx.curvalue, "cg_particles" ) + BFPOPTIONS_MENUITEM( s_bfpoptions.dynauralight.curvalue, "cg_lightAuras" ) + BFPOPTIONS_MENUITEM( s_bfpoptions.dynexplolights.curvalue, "cg_lightExplosions" ) + BFPOPTIONS_MENUITEM( s_bfpoptions.transaura.curvalue, "cg_transformationAura" ) + BFPOPTIONS_MENUITEM( s_bfpoptions.smallaura.curvalue, "cg_smallOwnAura" ) + BFPOPTIONS_MENUITEM( s_bfpoptions.ssjglow.curvalue, "cg_permaglowUltimate" ) + BFPOPTIONS_MENUITEM( s_bfpoptions.accucrosshair.curvalue, "cg_stableCrosshair" ) + BFPOPTIONS_MENUITEM( s_bfpoptions.simplehud.curvalue, "cg_simpleHUD" ) + BFPOPTIONS_MENUITEM( s_bfpoptions.chargealert.curvalue, "cg_chargeupAlert" ) + BFPOPTIONS_MENUITEM( s_bfpoptions.q3hitsfx.curvalue, "cg_playHitSound" ) + BFPOPTIONS_MENUITEM( s_bfpoptions.flightilt.curvalue, "cg_flytilt" ) + BFPOPTIONS_MENUITEM( s_bfpoptions.bigheads.curvalue, "cg_superdeformed" ) + BFPOPTIONS_MENUITEM( s_bfpoptions.defaultskins.curvalue, "cg_forceSkin" ) + BFPOPTIONS_MENUITEM( s_bfpoptions.stfu.curvalue, "cg_stfu" ) + BFPOPTIONS_MENUITEM( s_bfpoptions.lowpolysphere.curvalue, "cg_lowpolysphere" ) } +#undef BFPOPTIONS_MENUITEM + +// Macros to look better the code +#define AURATYPE_SETUP(highpoly, poly, light) \ + trap_Cvar_SetValue( "cg_highPolyAura", highpoly ); \ + trap_Cvar_SetValue( "cg_polygonAura", poly ); \ + trap_Cvar_SetValue( "cg_lightweightAuras", light ); + +#define VIEWPOINT_SETUP(tp, ownmodel) \ + trap_Cvar_SetValue( "cg_thirdPerson", tp ); \ + trap_Cvar_SetValue( "cg_drawOwnModel", ownmodel ); +#define EXPLOTYPE_SETUP(expShell, expSmoke, particles, expRing ) \ + trap_Cvar_SetValue( "cg_explosionShell", expShell ); \ + trap_Cvar_SetValue( "cg_explosionSmoke", expSmoke ); \ + trap_Cvar_SetValue( "cg_particles", particles ); \ + trap_Cvar_SetValue( "cg_explosionRing", expRing ); \ + s_bfpoptions.particlesfx.curvalue = particles; static void BFPOptions_Event( void* ptr, int notification ) { - if( notification != QM_ACTIVATED ) { + if ( notification != QM_ACTIVATED ) { return; } - switch( ((menucommon_s*)ptr)->id ) { + switch ( ((menucommon_s*)ptr)->id ) { //-----------------------------Aura list---------------------------------// case ID_AURATYPE: - if( s_bfpoptions.auratype.curvalue == 0 ) { - trap_Cvar_SetValue( "cg_highPolyAura", 1 ); - trap_Cvar_SetValue( "cg_polygonAura", 1 ); - trap_Cvar_SetValue( "cg_lightweightAuras", 0 ); - } - else if( s_bfpoptions.auratype.curvalue == 1 ) { - trap_Cvar_SetValue( "cg_highPolyAura", 0 ); - trap_Cvar_SetValue( "cg_polygonAura", 1 ); - trap_Cvar_SetValue( "cg_lightweightAuras", 0 ); - } - else if( s_bfpoptions.auratype.curvalue == 2 ) { - trap_Cvar_SetValue( "cg_highPolyAura", 0 ); - trap_Cvar_SetValue( "cg_polygonAura", 0 ); - trap_Cvar_SetValue( "cg_lightweightAuras", 0 ); - } - else if( s_bfpoptions.auratype.curvalue == 3 ) { - trap_Cvar_SetValue( "cg_highPolyAura", 0 ); - trap_Cvar_SetValue( "cg_polygonAura", 0 ); - trap_Cvar_SetValue( "cg_lightweightAuras", 1 ); - } - else if( s_bfpoptions.auratype.curvalue == 4 ) { - trap_Cvar_SetValue( "cg_highPolyAura", 0 ); - trap_Cvar_SetValue( "cg_polygonAura", 0 ); - trap_Cvar_SetValue( "cg_lightweightAuras", 0 ); + switch ( s_bfpoptions.auratype.curvalue ) { + case SHADER_AURA: // Shader Aura + AURATYPE_SETUP( 0, 0, 0 ) + break; + + case LIGHTWEIGHT_AURA: // Lightweight Aura + AURATYPE_SETUP( 0, 0, 1 ) + break; + + case POLYGON_AURA: // Polygonal Aura + AURATYPE_SETUP( 0, 1, 0 ) + break; + + case HIGHPOLYCOUNT_AURA: // High Polycount Aura + AURATYPE_SETUP( 1, 1, 0 ) + break; } break; //---------------------------View point List---------------------------------------// case ID_VIEWPOINT: - if( s_bfpoptions.viewpoint.curvalue == 0 ) { + switch ( s_bfpoptions.viewpoint.curvalue ) { + case 0: // Third Person trap_Cvar_SetValue( "cg_thirdPerson", 1 ); - trap_Cvar_SetValue( "cg_drawOwnModel", 1 ); - } - else if( s_bfpoptions.viewpoint.curvalue == 1 ) { - trap_Cvar_SetValue( "cg_thirdPerson", 0 ); - trap_Cvar_SetValue( "cg_drawOwnModel", 0 ); - } - else if( s_bfpoptions.viewpoint.curvalue == 2 ) { - trap_Cvar_SetValue( "cg_thirdPerson", 0 ); - trap_Cvar_SetValue( "cg_drawOwnModel", 1 ); + break; + + case 1: // First Person + VIEWPOINT_SETUP( 0, 0 ) + break; + + case 2: // First Person Vis + VIEWPOINT_SETUP( 0, 1 ) + break; } break; //---------------------------Explosion type list---------------------------------------// case ID_EXPLOTYPE: - if ( s_bfpoptions.explotype.curvalue == 0 ) { - trap_Cvar_SetValue( "cg_explosionShell", 1 ); - trap_Cvar_SetValue( "cg_explosionSmoke", 0 ); - trap_Cvar_SetValue( "cg_particles", 1 ); - trap_Cvar_SetValue( "cg_explosionRing", 1 ); - } - else if ( s_bfpoptions.explotype.curvalue == 1 ) { - trap_Cvar_SetValue( "cg_explosionShell", 1 ); - trap_Cvar_SetValue( "cg_explosionSmoke", 1 ); - trap_Cvar_SetValue( "cg_particles", 1 ); - trap_Cvar_SetValue( "cg_explosionRing", 1 ); - } - else if ( s_bfpoptions.explotype.curvalue == 2 ) { - trap_Cvar_SetValue( "cg_explosionShell", 0 ); - trap_Cvar_SetValue( "cg_explosionSmoke", 0 ); - trap_Cvar_SetValue( "cg_particles", 0 ); - trap_Cvar_SetValue( "cg_explosionRing", 0 ); - } - else if ( s_bfpoptions.explotype.curvalue == 3 ) { - trap_Cvar_SetValue( "cg_explosionShell", 1 ); - trap_Cvar_SetValue( "cg_explosionSmoke", 0 ); - trap_Cvar_SetValue( "cg_particles", 0 ); - trap_Cvar_SetValue( "cg_explosionRing", 1 ); + switch ( s_bfpoptions.explotype.curvalue ) { + case WIMPY_EXPLO: // Wimpy + EXPLOTYPE_SETUP( 0, 0, 0, 0 ) + break; + + case WEAK_EXPLO: // Weak + EXPLOTYPE_SETUP( 1, 0, 0, 1 ) + break; + + case SO_SO_EXPLO: // So-So + EXPLOTYPE_SETUP( 1, 0, 1, 1 ) + break; + + case HARDCORE_EXPLO: // Hardcore + EXPLOTYPE_SETUP( 1, 1, 1, 1 ) + break; } break; @@ -273,8 +291,8 @@ static void BFPOptions_Event( void* ptr, int notification ) { trap_Cvar_SetValue( "cg_forceSkin", s_bfpoptions.defaultskins.curvalue ); break; - case ID_DISABLEVOICES: - trap_Cvar_SetValue( "cg_stfu", s_bfpoptions.disablevoices.curvalue ); + case ID_STFU: + trap_Cvar_SetValue( "cg_stfu", s_bfpoptions.stfu.curvalue ); break; case ID_LOWPOLYSPHERE: @@ -286,6 +304,9 @@ static void BFPOptions_Event( void* ptr, int notification ) { break; } } +#undef AURATYPE_SETUP +#undef VIEWPOINT_SETUP +#undef EXPLOTYPE_SETUP static void BFPOptions_MenuInit( void ) { @@ -506,13 +527,13 @@ static void BFPOptions_MenuInit( void ) { s_bfpoptions.defaultskins.generic.y = y; y += BIGCHAR_HEIGHT + 2; - s_bfpoptions.disablevoices.generic.type = MTYPE_RADIOBUTTON; - s_bfpoptions.disablevoices.generic.name = "Disable Voices:"; - s_bfpoptions.disablevoices.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; - s_bfpoptions.disablevoices.generic.callback = BFPOptions_Event; - s_bfpoptions.disablevoices.generic.id = ID_DISABLEVOICES; - s_bfpoptions.disablevoices.generic.x = BFPOPTIONS_X_POS; - s_bfpoptions.disablevoices.generic.y = y; + s_bfpoptions.stfu.generic.type = MTYPE_RADIOBUTTON; + s_bfpoptions.stfu.generic.name = "Disable Voices:"; + s_bfpoptions.stfu.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; + s_bfpoptions.stfu.generic.callback = BFPOptions_Event; + s_bfpoptions.stfu.generic.id = ID_STFU; + s_bfpoptions.stfu.generic.x = BFPOPTIONS_X_POS; + s_bfpoptions.stfu.generic.y = y; y += BIGCHAR_HEIGHT + 2; s_bfpoptions.lowpolysphere.generic.type = MTYPE_RADIOBUTTON; @@ -557,7 +578,7 @@ static void BFPOptions_MenuInit( void ) { Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.flightilt ); Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.bigheads ); Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.defaultskins ); - Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.disablevoices ); + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.stfu ); Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.lowpolysphere ); //----------------------------Auras-------------------------------------// @@ -566,14 +587,14 @@ static void BFPOptions_MenuInit( void ) { polygonalaura = trap_Cvar_VariableValue( "cg_polygonAura" ); lightweightaura = trap_Cvar_VariableValue( "cg_lightweightAuras" ); - if ( highpolyaura == 1 ) { - s_bfpoptions.auratype.curvalue = 0; - } else if ( polygonalaura == 1 ) { - s_bfpoptions.auratype.curvalue = 1; - } else if ( lightweightaura == 1 ) { - s_bfpoptions.auratype.curvalue = 3; + if ( highpolyaura >= 1 ) { + s_bfpoptions.auratype.curvalue = HIGHPOLYCOUNT_AURA; + } else if ( polygonalaura >= 1 ) { + s_bfpoptions.auratype.curvalue = POLYGON_AURA; + } else if ( lightweightaura >= 1 ) { + s_bfpoptions.auratype.curvalue = LIGHTWEIGHT_AURA; } else { - s_bfpoptions.auratype.curvalue = 2; + s_bfpoptions.auratype.curvalue = SHADER_AURA; } //----------------------------Explosions-------------------------------------// @@ -583,14 +604,16 @@ static void BFPOptions_MenuInit( void ) { particles = trap_Cvar_VariableValue( "cg_particles" ); explosionring = trap_Cvar_VariableValue( "cg_explosionRing" ); - if ( explosionSmoke == 1 ) { - s_bfpoptions.explotype.curvalue = 1; - } else if ( particles == 1 ) { - s_bfpoptions.explotype.curvalue = 0; - } else if ( explosionShell == 1 ) { - s_bfpoptions.explotype.curvalue = 3; - } else if ( explosionring == 0 ) { - s_bfpoptions.explotype.curvalue = 2; + if ( explosionSmoke <= 0 && explosionShell <= 0 && explosionring <= 0 ) { + s_bfpoptions.explotype.curvalue = WIMPY_EXPLO; + } else if ( explosionSmoke >= 1 && explosionring >= 1 ) { + s_bfpoptions.explotype.curvalue = WEAK_EXPLO; + } else if ( explosionSmoke >= 1 && particles >= 1 && explosionring >= 1 ) { + s_bfpoptions.explotype.curvalue = SO_SO_EXPLO; + } else if ( explosionSmoke >= 1 && explosionShell >= 1 && particles >= 1 && explosionring >= 1 ) { + s_bfpoptions.explotype.curvalue = HARDCORE_EXPLO; + } else { + s_bfpoptions.explotype.curvalue = WIMPY_EXPLO; } //----------------------------Camera-------------------------------------// @@ -598,11 +621,11 @@ static void BFPOptions_MenuInit( void ) { thirdperson = trap_Cvar_VariableValue( "cg_thirdPerson" ); firstpersonvis = trap_Cvar_VariableValue( "cg_drawOwnModel" ); - if( thirdperson == 1 ) { + if ( thirdperson == 1 ) { s_bfpoptions.viewpoint.curvalue = 0; - } else if( firstpersonvis == 1 ) { + } else if ( firstpersonvis == 1 ) { s_bfpoptions.viewpoint.curvalue = 2; - } else if( firstpersonvis == 0 ) { + } else if ( firstpersonvis == 0 ) { s_bfpoptions.viewpoint.curvalue = 1; } @@ -610,11 +633,18 @@ static void BFPOptions_MenuInit( void ) { s_bfpoptions.kitrailength.curvalue = trap_Cvar_VariableValue( "cg_kiTrail" ); s_bfpoptions.beamcmpxy.curvalue = trap_Cvar_VariableValue( "cg_beamTrail" ); - Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.back ); BFPOptions_SetMenuItems(); } +#undef SHADER_AURA +#undef LIGHTWEIGHT_AURA +#undef POLYGON_AURA +#undef HIGHPOLYCOUNT_AURA +#undef WIMPY_EXPLO +#undef WEAK_EXPLO +#undef SO_SO_EXPLO +#undef HARDCORE_EXPLO /* From c9600fb0b6719e63cbf98338704f89f8835fde40 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Thu, 26 Oct 2023 00:07:36 +0100 Subject: [PATCH 009/374] game: Don't add EF_AURA too early when it didn't end 3 seconds while the key is being pressed --- source/game/g_active.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/game/g_active.c b/source/game/g_active.c index dbab22d..6246473 100644 --- a/source/game/g_active.c +++ b/source/game/g_active.c @@ -741,7 +741,8 @@ void ClientThink_real( gentity_t *ent ) { } // BFP - Ki Charge - if ( ( ucmd->buttons & BUTTON_KI_CHARGE ) && ent->client->ps.pm_time <= 0 ) { + if ( ( ucmd->buttons & BUTTON_KI_CHARGE ) && ent->client->ps.pm_time <= 0 + && ( ent->client->ps.pm_flags & PMF_KI_CHARGE ) ) { client->ps.eFlags |= EF_AURA; } From 6aa29322200395c86a62756454cc0a66646d4802 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Thu, 26 Oct 2023 01:00:00 +0100 Subject: [PATCH 010/374] cgame: Apply swingangles to the player when moving the torso and legs (smooth flying movements aren't completed yet), apply highpoly and poly aura checks and don't show float sprites to the player itself --- source/cgame/cg_players.c | 129 +++++++++++++++----------------------- 1 file changed, 52 insertions(+), 77 deletions(-) diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index 57012b3..be22394 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -1244,12 +1244,12 @@ static void CG_PlayerAnimation( centity_t *cent, int *legsOld, int *legs, float // if ( cent->currentState.powerups & ( 1 << PW_HASTE ) ) { // BFP - When using ki boost use the following speed as haste powerup - if ( cent->currentState.number == cg.snap->ps.clientNum - && ( cent->currentState.eFlags & EF_AURA ) - && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_IDLE - && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_CHARGE - && ( cent->currentState.torsoAnim & ~ANIM_TOGGLEBIT ) != TORSO_STAND - && ( cent->currentState.torsoAnim & ~ANIM_TOGGLEBIT ) != TORSO_CHARGE ) { + if ( clientNum == cg.snap->ps.clientNum + && ( cent->currentState.eFlags & EF_AURA ) + && ( ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_IDLE + || ( cent->currentState.torsoAnim & ~ANIM_TOGGLEBIT ) != TORSO_STAND ) + && ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_CHARGE + || ( cent->currentState.torsoAnim & ~ANIM_TOGGLEBIT ) != TORSO_CHARGE ) ) ) { speedScale = 1.5; // when using ki boost } else { speedScale = 1; @@ -1398,9 +1398,14 @@ static void CG_PlayerAngles( centity_t *cent, vec3_t legs[3], vec3_t torso[3], v // --------- yaw ------------- + // BFP - Allow yaw while flying too // allow yaw to drift a bit - if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_IDLE - || ( cent->currentState.torsoAnim & ~ANIM_TOGGLEBIT ) != TORSO_STAND ) { + if ( ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_IDLE + || ( cent->currentState.torsoAnim & ~ANIM_TOGGLEBIT ) != TORSO_STAND ) + && ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_FLYIDLE + || ( cent->currentState.torsoAnim & ~ANIM_TOGGLEBIT ) != TORSO_STAND ) + && ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_CHARGE + || ( cent->currentState.torsoAnim & ~ANIM_TOGGLEBIT ) != TORSO_CHARGE ) ) { // if not standing still, always point all in the same direction cent->pe.torso.yawing = qtrue; // always center cent->pe.torso.pitching = qtrue; // always center @@ -1422,8 +1427,8 @@ static void CG_PlayerAngles( centity_t *cent, vec3_t legs[3], vec3_t torso[3], v // BFP - Swing the angles to make the movements look smooth // torso - CG_SwingAngles( torsoAngles[YAW], 40, 90, cg_swingSpeed.value, ¢->pe.torso.yawAngle, ¢->pe.torso.yawing ); - CG_SwingAngles( legsAngles[YAW], 90, 90, cg_swingSpeed.value, ¢->pe.legs.yawAngle, ¢->pe.legs.yawing ); + CG_SwingAngles( torsoAngles[YAW], 40, 90, cg_swingSpeed.value, ¢->pe.torso.yawAngle, ¢->pe.torso.yawing ); // BFP - Before: 25, 90 + CG_SwingAngles( legsAngles[YAW], 90, 90, cg_swingSpeed.value, ¢->pe.legs.yawAngle, ¢->pe.legs.yawing ); // BFP - Before: 40, 90 torsoAngles[YAW] = cent->pe.torso.yawAngle; legsAngles[YAW] = cent->pe.legs.yawAngle; @@ -1437,7 +1442,15 @@ static void CG_PlayerAngles( centity_t *cent, vec3_t legs[3], vec3_t torso[3], v } else { dest = headAngles[PITCH] * 0.75f; } - CG_SwingAngles( dest, 15, 30, 0.1f, ¢->pe.torso.pitchAngle, ¢->pe.torso.pitching ); + // BFP - When flying, set the legs in the first case + if ( cent->currentState.clientNum == cg.snap->ps.clientNum + && ( cg.predictedPlayerState.pm_flags & PMF_FLYING ) ) { + CG_SwingAngles( dest, 15, 30, 0.1f, ¢->pe.legs.pitchAngle, ¢->pe.legs.pitching ); + legsAngles[PITCH] = cent->pe.legs.pitchAngle; + } + + // BFP - When flying, set the torso correctly into these angles + CG_SwingAngles( dest, 30, 30, 0.1f, ¢->pe.torso.pitchAngle, ¢->pe.torso.pitching ); torsoAngles[PITCH] = cent->pe.torso.pitchAngle; // @@ -1451,6 +1464,7 @@ static void CG_PlayerAngles( centity_t *cent, vec3_t legs[3], vec3_t torso[3], v // --------- roll ------------- + // BFP - TODO: Make the forward and backwards movements smooth // lean towards the direction of travel VectorCopy( cent->currentState.pos.trDelta, velocity ); @@ -1459,7 +1473,7 @@ static void CG_PlayerAngles( centity_t *cent, vec3_t legs[3], vec3_t torso[3], v vec3_t axis[3]; float side; - speed *= 0.01f; // BFP - adjust legs speed, before 0.05f + speed *= 0.025f; // BFP - adjust legs speed, before 0.05f AnglesToAxis( legsAngles, axis ); side = speed * DotProduct( velocity, axis[1] ); @@ -1480,25 +1494,6 @@ static void CG_PlayerAngles( centity_t *cent, vec3_t legs[3], vec3_t torso[3], v } } - // BFP - when flying, set correctly into these angles - if ( cg.predictedPlayerState.pm_flags & PMF_FLYING ) { - //VectorCopy( cent->lerpAngles, headAngles ); - //VectorCopy( cent->lerpAngles, torsoAngles ); - // only show a fraction of the pitch angle in the torso - VectorCopy( torsoAngles, legsAngles ); - - CG_SwingAngles( torsoAngles[YAW], 40, 90, cg_swingSpeed.value, ¢->pe.torso.yawAngle, ¢->pe.torso.yawing ); - CG_SwingAngles( legsAngles[YAW], 40, 90, cg_swingSpeed.value, ¢->pe.legs.yawAngle, ¢->pe.legs.yawing ); - - torsoAngles[YAW] = cent->pe.torso.yawAngle; - legsAngles[YAW] = cent->pe.torso.yawAngle; - - //legsAngles[YAW] = torsoAngles[YAW]; - //CG_SwingAngles( torsoAngles[YAW], 40, 90, cg_swingSpeed.value, ¢->pe.torso.yawAngle, ¢->pe.torso.yawing ); - //CG_SwingAngles( legsAngles[YAW], 90, 90, cg_swingSpeed.value, ¢->pe.legs.yawAngle, ¢->pe.legs.yawing ); - //VectorCopy( cent->lerpAngles, legsAngles ); - } - // pain twitch CG_AddPainTwitch( cent, torsoAngles ); @@ -1814,49 +1809,25 @@ Float sprites over the player's head static void CG_PlayerSprites( centity_t *cent ) { int team; - if ( cent->currentState.eFlags & EF_CONNECTION ) { - CG_PlayerFloatSprite( cent, cgs.media.connectionShader ); - return; - } - - if ( cent->currentState.eFlags & EF_TALK - && cent->currentState.number != cg.snap->ps.clientNum ) { // BFP - Don't show the chat ballon to the player itself - CG_PlayerFloatSprite( cent, cgs.media.balloonShader ); - return; - } - - if ( cent->currentState.eFlags & EF_AWARD_IMPRESSIVE ) { - CG_PlayerFloatSprite( cent, cgs.media.medalImpressive ); - return; - } - - if ( cent->currentState.eFlags & EF_AWARD_EXCELLENT ) { - CG_PlayerFloatSprite( cent, cgs.media.medalExcellent ); - return; - } - - if ( cent->currentState.eFlags & EF_AWARD_GAUNTLET ) { - CG_PlayerFloatSprite( cent, cgs.media.medalGauntlet ); - return; - } - - if ( cent->currentState.eFlags & EF_AWARD_DEFEND ) { - CG_PlayerFloatSprite( cent, cgs.media.medalDefend ); - return; - } - - if ( cent->currentState.eFlags & EF_AWARD_ASSIST ) { - CG_PlayerFloatSprite( cent, cgs.media.medalAssist ); - return; - } + // BFP - A macro to check if there's some eflag enabled, also don't show the float sprite to the player itself + #define FLOATSPRITE_CHECK(eflag, flspriteshader) \ + if ( ( cent->currentState.eFlags & eflag ) && cent->currentState.number != cg.snap->ps.clientNum ) { \ + CG_PlayerFloatSprite( cent, flspriteshader ); \ + return; \ + } - if ( cent->currentState.eFlags & EF_AWARD_CAP ) { - CG_PlayerFloatSprite( cent, cgs.media.medalCapture ); - return; - } + FLOATSPRITE_CHECK( EF_CONNECTION, cgs.media.connectionShader ) + FLOATSPRITE_CHECK( EF_TALK, cgs.media.balloonShader ) + FLOATSPRITE_CHECK( EF_AWARD_IMPRESSIVE, cgs.media.medalImpressive ) + FLOATSPRITE_CHECK( EF_AWARD_EXCELLENT, cgs.media.medalExcellent ) + FLOATSPRITE_CHECK( EF_AWARD_GAUNTLET, cgs.media.medalGauntlet ) + FLOATSPRITE_CHECK( EF_AWARD_DEFEND, cgs.media.medalDefend ) + FLOATSPRITE_CHECK( EF_AWARD_ASSIST, cgs.media.medalAssist ) + FLOATSPRITE_CHECK( EF_AWARD_CAP, cgs.media.medalCapture ) team = cgs.clientinfo[ cent->currentState.clientNum ].team; if ( !(cent->currentState.eFlags & EF_DEAD) && + cent->currentState.number != cg.snap->ps.clientNum && // BFP - Don't show the friend team shader to the player itself cg.snap->ps.persistant[PERS_TEAM] == team && cgs.gametype >= GT_TEAM) { if (cg_drawFriend.integer) { @@ -1865,6 +1836,7 @@ static void CG_PlayerSprites( centity_t *cent ) { return; } } +#undef FLOATSPRITE_CHECK /* =============== @@ -2179,8 +2151,7 @@ void CG_Player( centity_t *cent ) { // get the player model information renderfx = 0; - // BFP - Don't make the players look to the others with the same torso position - // if ( cent->currentState.number == cg.snap->ps.clientNum) { + if ( cent->currentState.number == cg.snap->ps.clientNum ) { if (!cg.renderingThirdPerson) { renderfx = RF_THIRD_PERSON; // only draw in mirrors } /*else { // BFP - cg_cameraMode cvar doesn't exist @@ -2188,7 +2159,7 @@ void CG_Player( centity_t *cent ) { return; } }*/ - // } + } memset( &legs, 0, sizeof(legs) ); @@ -2271,8 +2242,8 @@ void CG_Player( centity_t *cent ) { // BFP - First person vis mode doesn't have head model to be displayed if ( cg_drawOwnModel.integer >= 1 && cg_thirdPerson.integer <= 0 - && cent->currentState.number == cg.snap->ps.clientNum - && !( cent->currentState.eFlags & EF_DEAD ) ) { + && clientNum == cg.snap->ps.clientNum + && !( cent->currentState.eFlags & EF_DEAD ) ) { head.hModel = 2; // 2: no head model display and no pivot display } head.customSkin = ci->headSkin; @@ -2319,6 +2290,10 @@ void CG_Player( centity_t *cent ) { } // Macro for the dynamic aura light, note: when charging it changes the shinning a bit + + // BFP - TODO: Make the light of aura of highpolycount look less bright + // because bfp looks only the lightweight ones (but blinking correctly is a must) + #define AURA_LIGHT(r, g, b) \ if ( cg_lightAuras.integer > 0 ) { \ if ( cg_smallOwnAura.integer > 0 ) { \ @@ -2327,7 +2302,7 @@ void CG_Player( centity_t *cent ) { trap_R_AddLightToScene( aura.origin, 200 + (rand()&255), r, g, b ); \ trap_R_AddLightToScene( aura2.origin, 200 + (rand()&255), r, g, b ); \ } \ - if ( cg_lightweightAuras.integer > 0 ) { \ + if ( cg_lightweightAuras.integer > 0 || cg_polygonAura.integer > 0 || cg_highPolyAura.integer > 0 ) { \ trap_R_AddLightToScene( torso.origin, 80 + (rand()&83), r, g, b ); \ trap_R_AddLightToScene( legs.origin, 80 + (rand()&63), r, g, b ); \ trap_R_AddLightToScene( aura.origin, 80 + (rand()&63), r, g, b ); \ @@ -2420,7 +2395,7 @@ void CG_Player( centity_t *cent ) { // BFP - First person camera setup if ( cg_thirdPerson.integer <= 0 - && cent->currentState.number == cg.snap->ps.clientNum ) { // BFP - Avoid every time some player/bot enters in the server and changes the view into the other player + && clientNum == cg.snap->ps.clientNum ) { // BFP - Avoid every time some player/bot enters in the server and changes the view into the other player CG_OffsetFirstPersonView( cent, &torso, ci->torsoModel ); } } From 97211f56da009ed95f5b44043891bee25c1600a3 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Fri, 27 Oct 2023 00:56:50 +0100 Subject: [PATCH 011/374] cgame: Apply changes to the aura light blinking to be almost the same as original BFP and refactor the variables for the model size --- source/cgame/cg_players.c | 53 ++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index be22394..c28ffe0 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -2131,9 +2131,17 @@ void CG_Player( centity_t *cent ) { int renderfx; qboolean shadow; float shadowPlane; - int aura_i, aura_j; // BFP - For aura sizes + int model_i, model_j; // BFP - For model sizes vec3_t auraInverseRotation; // BFP - For aura inverse rotation + // BFP - Macro for the size of a model + #define MODEL_SIZE(model, model_size) \ + for ( model_i = 0; model_i < 3; model_i++ ) { \ + for ( model_j = 0; model_j < 3; model_j++ ) { \ + model.axis[model_i][model_j] *= model_size; \ + } \ + } + // the client number is stored in clientNum. It can't be derived // from the entity number, because a single client may have // multiple corpses on the level using the same clientinfo @@ -2260,14 +2268,6 @@ void CG_Player( centity_t *cent ) { // // BFP - Aura // - // Macro for the size of the aura model - #define AURA_MODEL_SIZE(aura, aura_size) \ - for ( aura_i = 0; aura_i < 3; aura_i++ ) { \ - for ( aura_j = 0; aura_j < 3; aura_j++ ) { \ - aura.axis[aura_i][aura_j] *= aura_size; \ - } \ - } - // Macro to handle the aura animations, when idling it sets the aura vertical rotation, so the aura rotates vertically #define AURA_ANIMS(aura, reversed) \ if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_RUN \ @@ -2290,24 +2290,21 @@ void CG_Player( centity_t *cent ) { } // Macro for the dynamic aura light, note: when charging it changes the shinning a bit - - // BFP - TODO: Make the light of aura of highpolycount look less bright - // because bfp looks only the lightweight ones (but blinking correctly is a must) - #define AURA_LIGHT(r, g, b) \ if ( cg_lightAuras.integer > 0 ) { \ if ( cg_smallOwnAura.integer > 0 ) { \ - trap_R_AddLightToScene( torso.origin, 200 + (rand()&255), r, g, b ); \ - trap_R_AddLightToScene( legs.origin, 200 + (rand()&255), r, g, b ); \ - trap_R_AddLightToScene( aura.origin, 200 + (rand()&255), r, g, b ); \ - trap_R_AddLightToScene( aura2.origin, 200 + (rand()&255), r, g, b ); \ - } \ - if ( cg_lightweightAuras.integer > 0 || cg_polygonAura.integer > 0 || cg_highPolyAura.integer > 0 ) { \ - trap_R_AddLightToScene( torso.origin, 80 + (rand()&83), r, g, b ); \ - trap_R_AddLightToScene( legs.origin, 80 + (rand()&63), r, g, b ); \ - trap_R_AddLightToScene( aura.origin, 80 + (rand()&63), r, g, b ); \ + trap_R_AddLightToScene( torso.origin, 100 + (rand()&150), r, g, b ); \ + trap_R_AddLightToScene( legs.origin, 100 + (rand()&255), r, g, b ); \ + trap_R_AddLightToScene( aura.origin, 150 + (rand()&255), r, g, b ); \ + if ( !( cg.predictedPlayerState.pm_flags & PMF_KI_CHARGE ) ) { \ + trap_R_AddLightToScene( aura2.origin, 200 + (rand()&255), r, g, b ); \ + } \ + } else if ( cg_lightweightAuras.integer > 0 || cg_polygonAura.integer > 0 || cg_highPolyAura.integer > 0 ) { \ + trap_R_AddLightToScene( torso.origin, 50 + (rand()&100), r, g, b ); \ + trap_R_AddLightToScene( legs.origin, 50 + (rand()&100), r, g, b ); \ + trap_R_AddLightToScene( aura.origin, 50 + (rand()&100), r, g, b ); \ } else { \ - trap_R_AddLightToScene( torso.origin, 80 + (rand()&63), r, g, b ); \ + trap_R_AddLightToScene( torso.origin, 150 + (rand()&100), r, g, b ); \ trap_R_AddLightToScene( legs.origin, 200 + (rand()&63), r, g, b ); \ trap_R_AddLightToScene( aura.origin, 200 + (rand()&255), r, g, b ); \ if ( !( cg.predictedPlayerState.pm_flags & PMF_KI_CHARGE ) ) { \ @@ -2329,8 +2326,8 @@ void CG_Player( centity_t *cent ) { AURA_ANIMS( aura2, 1 ) // Resize the aura - AURA_MODEL_SIZE( aura, 1.3f ) - AURA_MODEL_SIZE( aura2, 1.49f ) + MODEL_SIZE( aura, 1.3f ) + MODEL_SIZE( aura2, 1.49f ) // Set aura position to the player VectorCopy( legs.origin, aura.origin ); @@ -2375,12 +2372,12 @@ void CG_Player( centity_t *cent ) { } // Add aura - if ( cg_polygonAura.integer > 0 && cg_smallOwnAura.integer <= 0 ) { + if ( cg_polygonAura.integer > 0 && cg_lightweightAuras.integer <= 0 && cg_smallOwnAura.integer <= 0 ) { trap_R_AddRefEntityToScene( &aura ); } // Add secondary aura to make look cooler, a bit bigger than the other - if ( cg_polygonAura.integer > 0 && cg_highPolyAura.integer > 0 && cg_smallOwnAura.integer <= 0 ) { + if ( cg_polygonAura.integer > 0 && cg_highPolyAura.integer > 0 && cg_lightweightAuras.integer <= 0 && cg_smallOwnAura.integer <= 0 ) { trap_R_AddRefEntityToScene( &aura2 ); } } @@ -2399,7 +2396,7 @@ void CG_Player( centity_t *cent ) { CG_OffsetFirstPersonView( cent, &torso, ci->torsoModel ); } } -#undef AURA_MODEL_SIZE +#undef MODEL_SIZE #undef AURA_ANIMS #undef AURA_LIGHT From 26fbd56e83728e1a179d483d7cfb331ee4aab19e Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Fri, 27 Oct 2023 01:26:17 +0100 Subject: [PATCH 012/374] cgame: Implement Super Deformed (Chibi style) easter egg --- source/cgame/cg_cvar.h | 1 + source/cgame/cg_players.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/source/cgame/cg_cvar.h b/source/cgame/cg_cvar.h index e90abac..40da24e 100644 --- a/source/cgame/cg_cvar.h +++ b/source/cgame/cg_cvar.h @@ -78,6 +78,7 @@ CG_CVAR( cg_lightweightAuras, "cg_lightweightAuras", "0", CVAR_ARCHIVE ) // BFP CG_CVAR( cg_polygonAura, "cg_polygonAura", "1", CVAR_ARCHIVE ) // BFP - Polygonal aura CG_CVAR( cg_highPolyAura, "cg_highPolyAura", "1", CVAR_ARCHIVE ) // BFP - High polycount aura CG_CVAR( cg_thirdPerson, "cg_thirdPerson", "1", 0 ) // BFP +CG_CVAR( cg_superdeformed, "cg_superdeformed", "0", CVAR_ARCHIVE ) // BFP - Super Deformed (Chibi style) easter egg CG_CVAR( cg_yrgolroxor, "cg_yrgolroxor", "0", 0 ) // BFP - Yrgol Roxor easter egg CG_CVAR( cg_teamChatTime, "cg_teamChatTime", "3000", CVAR_ARCHIVE ) CG_CVAR( cg_teamChatHeight, "cg_teamChatHeight", "0", CVAR_ARCHIVE ) diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index c28ffe0..a0c041c 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -2203,6 +2203,11 @@ void CG_Player( centity_t *cent ) { legs.hModel = ci->legsModel; legs.customSkin = ci->legsSkin; + // BFP - Super Deformed (Chibi style) easter egg for the base model (the legs apply all parts of the body) + if ( cg_superdeformed.integer > 0 ) { + MODEL_SIZE( legs, 0.8f ) + } + VectorCopy( cent->lerpOrigin, legs.origin ); VectorCopy( cent->lerpOrigin, legs.lightingOrigin ); @@ -2256,6 +2261,11 @@ void CG_Player( centity_t *cent ) { } head.customSkin = ci->headSkin; + // BFP - Super Deformed (Chibi style) easter egg for the head model + if ( cg_superdeformed.integer > 0 ) { + MODEL_SIZE( head, 3.0f ) + } + VectorCopy( cent->lerpOrigin, head.lightingOrigin ); CG_PositionRotatedEntityOnTag( &head, &torso, ci->torsoModel, "tag_head"); From 855cc0905e3e9617110e0e1161ac8ee9564fe5f0 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Fri, 3 Nov 2023 00:54:26 +0000 Subject: [PATCH 013/374] game: Add handling macro of flying animation in order to reduce the amount of code and fix various stuff made during the implementation for ki charge and the handling of near to the ground --- source/game/bg_local.h | 1 - source/game/bg_pmove.c | 76 +++++++++++++++--------------------------- 2 files changed, 26 insertions(+), 51 deletions(-) diff --git a/source/game/bg_local.h b/source/game/bg_local.h index 389683d..1142535 100644 --- a/source/game/bg_local.h +++ b/source/game/bg_local.h @@ -60,7 +60,6 @@ extern pml_t pml; extern float pm_stopspeed; extern float pm_duckScale; extern float pm_swimScale; -extern float pm_wadeScale; extern float pm_accelerate; extern float pm_airaccelerate; diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index fa33c88..054d80e 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -34,7 +34,6 @@ pml_t pml; float pm_stopspeed = 100.0f; float pm_duckScale = 0.25f; float pm_swimScale = 0.50f; -float pm_wadeScale = 0.70f; float pm_accelerate = 10.0f; float pm_airaccelerate = 1.0f; @@ -51,6 +50,12 @@ int c_pmove = 0; // BFP - Macro for jump handling, since the code looked repetitive, so this macro makes the code a bit shorter #define FORCEJUMP_ANIM_HANDLING() ( pm->cmd.forwardmove >= 0 ) ? PM_ForceLegsAnim( LEGS_JUMP ) : PM_ForceLegsAnim( LEGS_JUMPB ) +// BFP - Macro for fly handling, since the code looked repetitive, so this macro makes the code a bit shorter +#define CONTINUEFLY_ANIM_HANDLING() \ + if ( pm->cmd.forwardmove > 0 ) { PM_ContinueTorsoAnim( TORSO_FLYA ); PM_ContinueLegsAnim( LEGS_FLYA ); } \ + else if ( pm->cmd.forwardmove < 0 ) { PM_ContinueTorsoAnim( TORSO_FLYB ); PM_ContinueLegsAnim( LEGS_FLYB ); } \ + else { PM_ContinueTorsoAnim( TORSO_STAND ); PM_ContinueLegsAnim( LEGS_FLYIDLE ); } + /* =============== PM_AddEvent @@ -186,7 +191,6 @@ static void PM_Friction( void ) { speed = VectorLength(vec); if (speed < 1) { - drop = 0; vel[0] = 0; vel[1] = 0; // allow sinking underwater // FIXME: still have z friction underwater? @@ -536,16 +540,7 @@ static void PM_WaterMove( void ) { } // BFP - Water animation handling, uses flying animation in that case - if ( pm->cmd.forwardmove > 0 ) { - PM_ContinueTorsoAnim( TORSO_FLYA ); - PM_ContinueLegsAnim( LEGS_FLYA ); - } else if ( pm->cmd.forwardmove < 0 ) { - PM_ContinueTorsoAnim( TORSO_FLYB ); - PM_ContinueLegsAnim( LEGS_FLYB ); - } else { - PM_ContinueTorsoAnim( TORSO_STAND ); - PM_ContinueLegsAnim( LEGS_FLYIDLE ); - } + CONTINUEFLY_ANIM_HANDLING() PM_SlideMove( qfalse ); } @@ -572,12 +567,11 @@ static void PM_FlyMove( void ) { // user intentions // if ( !scale ) { - wishvel[0] = 0; - wishvel[1] = 0; - wishvel[2] = 0; + VectorClear( wishvel ); } else { for ( i = 0; i < 3; i++ ) { - wishvel[i] = scale * pml.forward[i] * pm->cmd.forwardmove + scale * pml.right[i] * pm->cmd.rightmove + scale * pml.up[i] * pm->cmd.upmove; // BFP - (+ scale * pml.up[i] * pm->cmd.upmove) used when flying and moving upside/downside instead according the ground + // BFP - Before: (+ scale * pml.up[i] * pm->cmd.upmove) used when flying and moving upside/downside instead according the ground + wishvel[i] = scale * pml.forward[i] * pm->cmd.forwardmove + scale * pml.right[i] * pm->cmd.rightmove + scale * pml.up[i] * pm->cmd.upmove; } // wishvel[2] += scale * pm->cmd.upmove; // BFP - disabled to work the wished velocity } @@ -606,6 +600,13 @@ static void PM_AirMove( void ) { float scale; usercmd_t cmd; + // BFP - Avoid adding friction in the air while charging and flying + if ( ( ( pm->ps->pm_flags & PMF_KI_CHARGE ) + || ( pm->cmd.buttons & BUTTON_KI_CHARGE ) ) + && ( pm->ps->pm_flags & PMF_FLYING ) ) { + return; + } + PM_Friction(); fmove = pm->cmd.forwardmove; @@ -982,7 +983,6 @@ static void PM_CrashLand( void ) { if ( delta < 1 ) { return; } - // create a local entity event to play the sound // SURF_NODAMAGE is used for bounce pads where you don't ever @@ -1002,13 +1002,9 @@ static void PM_CrashLand( void ) { #endif else if ( delta > 7 ) { PM_AddEvent( EV_FALL_SHORT ); - } - // BFP - No footstep sounds -#if 0 - else { + } else { PM_AddEvent( PM_FootstepForSurface() ); } -#endif } // start footstep cycle over @@ -1606,21 +1602,12 @@ PM_FlightAnimation */ static void PM_FlightAnimation( void ) { // BFP - Flight - if ( ( pm->ps->pm_flags & PMF_FLYING ) && ( pm->ps->pm_time <= 0 ) ) { + if ( ( pm->ps->pm_flags & PMF_FLYING ) && pm->ps->pm_time <= 0 ) { // make sure to handle the PMF flag pm->ps->pm_flags &= ~PMF_FALLING; - if ( pm->cmd.forwardmove > 0 ) { - PM_ContinueTorsoAnim( TORSO_FLYA ); - PM_ContinueLegsAnim( LEGS_FLYA ); - } else if ( pm->cmd.forwardmove < 0 ) { - PM_ContinueTorsoAnim( TORSO_FLYB ); - PM_ContinueLegsAnim( LEGS_FLYB ); - } else { - PM_ContinueTorsoAnim( TORSO_STAND ); - PM_ContinueLegsAnim( LEGS_FLYIDLE ); - } + CONTINUEFLY_ANIM_HANDLING() return; } @@ -1668,6 +1655,7 @@ static void PM_KiChargeAnimation( void ) { // BFP - Ki Charge if ( ( pm->ps->pm_flags & PMF_KI_CHARGE ) && !( pm->cmd.buttons & BUTTON_KI_CHARGE ) ) { pm->ps->pm_flags &= ~PMF_KI_CHARGE; + PM_ContinueLegsAnim( LEGS_IDLE ); // Keep the legs when being near to the ground at that height // do jump animation if it's falling if ( !( pml.groundTrace.contents & CONTENTS_SOLID ) && ( pm->ps->pm_flags & PMF_FALLING ) ) { @@ -2058,22 +2046,10 @@ static void PM_KiCharge( void ) { // BFP - Ki Charge return; } - // BFP - TODO: Handle the fall while charging - - pm->cmd.forwardmove = 0; - pm->cmd.rightmove = 0; - pm->cmd.upmove = 0; + pm->cmd.forwardmove = pm->cmd.rightmove = pm->cmd.upmove = 0; VectorClear( pm->ps->velocity ); - // stop charging if it's using ki boost - if ( ( pm->cmd.buttons & BUTTON_KI_USE ) && ( pm->cmd.buttons & BUTTON_KI_CHARGE ) ) { - pm->ps->pm_flags &= ~PMF_KI_CHARGE; - pm->cmd.buttons &= ~BUTTON_KI_CHARGE; - pm->ps->pm_time = 0; - return; - } - if ( pm->cmd.buttons & ( BUTTON_ATTACK | BUTTON_KI_USE | BUTTON_MELEE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ) ) { pm->cmd.buttons &= ~( BUTTON_ATTACK | BUTTON_KI_USE | BUTTON_MELEE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ); } @@ -2311,10 +2287,9 @@ void PmoveSingle (pmove_t *pmove) { PM_Animate(); - // BFP - No ground trace again // set groundentity, watertype, and waterlevel - // PM_GroundTrace(); - // PM_SetWaterLevel(); + PM_GroundTrace(); + PM_SetWaterLevel(); // weapons PM_Weapon(); @@ -2393,6 +2368,7 @@ void Pmove (pmove_t *pmove) { } -// BFP - Undefine the macro of jump handling +// BFP - Undefine the macros #undef FORCEJUMP_ANIM_HANDLING +#undef CONTINUEFLY_ANIM_HANDLING From 16bc030214e64fb33750fb82998260580b38b45c Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sat, 4 Nov 2023 01:39:17 +0000 Subject: [PATCH 014/374] game: Remove a variable in gentity_s that mustn't be added, so do not modify anything inside gentity_s struct, it may can break something --- source/game/g_client.c | 2 -- source/game/g_local.h | 1 - 2 files changed, 3 deletions(-) diff --git a/source/game/g_client.c b/source/game/g_client.c index aa2bfb3..22b18f4 100644 --- a/source/game/g_client.c +++ b/source/game/g_client.c @@ -1176,8 +1176,6 @@ void ClientSpawn(gentity_t *ent) { // health will count down towards max_health ent->health = client->ps.stats[STAT_HEALTH] = client->ps.stats[STAT_MAX_HEALTH] + 25; - ent->kiamount = client->ps.stats[STAT_KI]; - G_SetOrigin( ent, spawn_origin ); VectorCopy( spawn_origin, client->ps.origin ); diff --git a/source/game/g_local.h b/source/game/g_local.h index 35da2d0..040e1dc 100644 --- a/source/game/g_local.h +++ b/source/game/g_local.h @@ -143,7 +143,6 @@ struct gentity_s { int last_move_time; int health; - int kiamount; // BFP - ki amount qboolean takedamage; From c76ea8fe216978b785f6671f916a3eae72a0d3eb Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sat, 4 Nov 2023 01:51:46 +0000 Subject: [PATCH 015/374] cgame: Add second jump sound when using ki boost and apply EV_FALL_MEDIUM for normal land sound --- source/cgame/cg_event.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/source/cgame/cg_event.c b/source/cgame/cg_event.c index dc3c179..d9d8718 100644 --- a/source/cgame/cg_event.c +++ b/source/cgame/cg_event.c @@ -481,8 +481,10 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { break; case EV_FALL_MEDIUM: DEBUGNAME("EV_FALL_MEDIUM"); + // BFP - Use normal land sound instead + trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.landSound ); // use normal pain sound - trap_S_StartSound( NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*pain100_1.wav" ) ); + // trap_S_StartSound( NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "*pain100_1.wav" ) ); if ( clientNum == cg.predictedPlayerState.clientNum ) { // smooth landing z changes cg.landChange = -16; @@ -560,7 +562,12 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { case EV_JUMP: DEBUGNAME("EV_JUMP"); - trap_S_StartSound (NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "sound/bfp/jump1.wav" ) ); // BFP - Normal jump sound + // BFP - Use the second jump sound when using ki boost + if ( es->eFlags & EF_AURA ) { + trap_S_StartSound (NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "sound/bfp/jump2.wav" ) ); // BFP - Ki boost jump sound + } else { + trap_S_StartSound (NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "sound/bfp/jump1.wav" ) ); // BFP - Normal jump sound + } break; case EV_TAUNT: DEBUGNAME("EV_TAUNT"); From d1092b522afb1a5cb3bf6b591bcda13366a998f8 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sat, 4 Nov 2023 01:54:07 +0000 Subject: [PATCH 016/374] game: Add accerelation handling when moving during the flight and revert the sound changes on PM_CrashLand --- source/game/bg_pmove.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index 054d80e..63aad52 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -558,6 +558,8 @@ static void PM_FlyMove( void ) { float wishspeed; vec3_t wishdir; float scale; + // BFP - Flight acceleration + float flyacc; // normal slowdown PM_Friction (); @@ -579,7 +581,10 @@ static void PM_FlyMove( void ) { VectorCopy (wishvel, wishdir); wishspeed = VectorNormalize(wishdir); - PM_Accelerate (wishdir, wishspeed, pm_flyaccelerate); + // BFP - When moving during the flight, start with half acceleration + flyacc = (scale > pm_stopspeed) ? pm_flyaccelerate : pm_flyaccelerate/2; + + PM_Accelerate (wishdir, wishspeed, flyacc); PM_StepSlideMove( qfalse ); } @@ -990,17 +995,12 @@ static void PM_CrashLand( void ) { if ( !(pml.groundTrace.surfaceFlags & SURF_NODAMAGE) ) { if ( delta > 180 ) { // BFP - Before Q3 default value (60), the far fall in BFP is deeper PM_AddEvent( EV_FALL_FAR ); - } - // BFP - There's no medium fall on BFP -#if 0 - else if ( delta > 40 ) { + } else if ( delta > 40 ) { // this is a pain grunt, so don't play it if dead if ( pm->ps->stats[STAT_HEALTH] > 0 ) { PM_AddEvent( EV_FALL_MEDIUM ); } - } -#endif - else if ( delta > 7 ) { + } else if ( delta > 7 ) { PM_AddEvent( EV_FALL_SHORT ); } else { PM_AddEvent( PM_FootstepForSurface() ); From f05f4f91f832eab806c6a0e9eff5bf99d0847c27 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sat, 4 Nov 2023 23:35:47 +0000 Subject: [PATCH 017/374] cgame: Add non-flight condition in the jump sound when using ki boost --- source/cgame/cg_event.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/cgame/cg_event.c b/source/cgame/cg_event.c index d9d8718..82821d4 100644 --- a/source/cgame/cg_event.c +++ b/source/cgame/cg_event.c @@ -562,8 +562,8 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { case EV_JUMP: DEBUGNAME("EV_JUMP"); - // BFP - Use the second jump sound when using ki boost - if ( es->eFlags & EF_AURA ) { + // BFP - Use the second jump sound when using ki boost only when it isn't flying + if ( ( es->eFlags & EF_AURA ) && !( cg.predictedPlayerState.pm_flags & PMF_FLYING ) ) { trap_S_StartSound (NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "sound/bfp/jump2.wav" ) ); // BFP - Ki boost jump sound } else { trap_S_StartSound (NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "sound/bfp/jump1.wav" ) ); // BFP - Normal jump sound From 3c2f1e5a13c8bf9a244aaef8366f21a6eab7c7dc Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Tue, 7 Nov 2023 00:49:49 +0000 Subject: [PATCH 018/374] cgame: Handle the speed and some tweaks from PlayerAngles, apply the animations correctly when running using ki boost (for speed movement and haste trail) and tweak the aura blinking light trying to be exact --- source/cgame/cg_players.c | 50 +++++++++++++++------------------------ 1 file changed, 19 insertions(+), 31 deletions(-) diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index a0c041c..0e72f91 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -1246,10 +1246,8 @@ static void CG_PlayerAnimation( centity_t *cent, int *legsOld, int *legs, float // BFP - When using ki boost use the following speed as haste powerup if ( clientNum == cg.snap->ps.clientNum && ( cent->currentState.eFlags & EF_AURA ) - && ( ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_IDLE - || ( cent->currentState.torsoAnim & ~ANIM_TOGGLEBIT ) != TORSO_STAND ) - && ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_CHARGE - || ( cent->currentState.torsoAnim & ~ANIM_TOGGLEBIT ) != TORSO_CHARGE ) ) ) { + && ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_RUN + || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_BACK ) ) { speedScale = 1.5; // when using ki boost } else { speedScale = 1; @@ -1443,8 +1441,7 @@ static void CG_PlayerAngles( centity_t *cent, vec3_t legs[3], vec3_t torso[3], v dest = headAngles[PITCH] * 0.75f; } // BFP - When flying, set the legs in the first case - if ( cent->currentState.clientNum == cg.snap->ps.clientNum - && ( cg.predictedPlayerState.pm_flags & PMF_FLYING ) ) { + if ( cg.predictedPlayerState.pm_flags & PMF_FLYING ) { CG_SwingAngles( dest, 15, 30, 0.1f, ¢->pe.legs.pitchAngle, ¢->pe.legs.pitching ); legsAngles[PITCH] = cent->pe.legs.pitchAngle; } @@ -1473,7 +1470,7 @@ static void CG_PlayerAngles( centity_t *cent, vec3_t legs[3], vec3_t torso[3], v vec3_t axis[3]; float side; - speed *= 0.025f; // BFP - adjust legs speed, before 0.05f + speed *= 0.03f; // BFP - adjust legs speed, before 0.05f AnglesToAxis( legsAngles, axis ); side = speed * DotProduct( velocity, axis[1] ); @@ -1886,14 +1883,10 @@ static qboolean CG_PlayerShadow( centity_t *cent, float *shadowPlane ) { contents = CG_PointContents( trace.endpos, -1 ); if ( ( cent->currentState.eFlags & EF_AURA ) && !( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) - && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_IDLE - && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_IDLECR - && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_JUMP - && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_JUMPB - && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_FLYIDLE - && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_CHARGE - && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_WALK - && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_WALKCR ) { + && ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_RUN + || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_BACK + || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYA + || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYB ) ) { CG_HasteTrail( cent ); } @@ -2303,22 +2296,22 @@ void CG_Player( centity_t *cent ) { #define AURA_LIGHT(r, g, b) \ if ( cg_lightAuras.integer > 0 ) { \ if ( cg_smallOwnAura.integer > 0 ) { \ - trap_R_AddLightToScene( torso.origin, 100 + (rand()&150), r, g, b ); \ trap_R_AddLightToScene( legs.origin, 100 + (rand()&255), r, g, b ); \ trap_R_AddLightToScene( aura.origin, 150 + (rand()&255), r, g, b ); \ + trap_R_AddLightToScene( aura2.origin, 200 + (rand()&255), r, g, b ); \ if ( !( cg.predictedPlayerState.pm_flags & PMF_KI_CHARGE ) ) { \ - trap_R_AddLightToScene( aura2.origin, 200 + (rand()&255), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 100 + (rand()&150), r, g, b ); \ } \ } else if ( cg_lightweightAuras.integer > 0 || cg_polygonAura.integer > 0 || cg_highPolyAura.integer > 0 ) { \ - trap_R_AddLightToScene( torso.origin, 50 + (rand()&100), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 50 + (rand()&100), r, g, b ); \ trap_R_AddLightToScene( legs.origin, 50 + (rand()&100), r, g, b ); \ trap_R_AddLightToScene( aura.origin, 50 + (rand()&100), r, g, b ); \ } else { \ - trap_R_AddLightToScene( torso.origin, 150 + (rand()&100), r, g, b ); \ trap_R_AddLightToScene( legs.origin, 200 + (rand()&63), r, g, b ); \ trap_R_AddLightToScene( aura.origin, 200 + (rand()&255), r, g, b ); \ + trap_R_AddLightToScene( aura2.origin, 200 + (rand()&255), r, g, b ); \ if ( !( cg.predictedPlayerState.pm_flags & PMF_KI_CHARGE ) ) { \ - trap_R_AddLightToScene( aura2.origin, 200 + (rand()&255), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 100 + (rand()&150), r, g, b ); \ } \ } \ } @@ -2364,22 +2357,17 @@ void CG_Player( centity_t *cent ) { VectorCopy( aura2.origin, aura2.oldorigin ); // don't positionally lerp at all // Ki boost and ki charge sounds - if ( ( cent->currentState.torsoAnim & ~ANIM_TOGGLEBIT ) != TORSO_CHARGE ) { - trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, - vec3_origin, cgs.media.kiUseSound ); - } else if ( ( cent->currentState.torsoAnim & ~ANIM_TOGGLEBIT ) == TORSO_CHARGE ) { + if ( ( cent->currentState.torsoAnim & ~ANIM_TOGGLEBIT ) == TORSO_CHARGE ) { trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, cgs.media.kiChargeSound ); + } else { + trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, + vec3_origin, cgs.media.kiUseSound ); } // Keep the aura pivot tagged in tag_torso - if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_RUN - || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_BACK - || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_FLYA - || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_FLYB ) { - CG_PositionRotatedEntityOnTag( &aura, &legs, ci->legsModel, "tag_torso" ); - CG_PositionRotatedEntityOnTag( &aura2, &legs, ci->legsModel, "tag_torso" ); - } + CG_PositionRotatedEntityOnTag( &aura, &legs, ci->legsModel, "tag_torso" ); + CG_PositionRotatedEntityOnTag( &aura2, &legs, ci->legsModel, "tag_torso" ); // Add aura if ( cg_polygonAura.integer > 0 && cg_lightweightAuras.integer <= 0 && cg_smallOwnAura.integer <= 0 ) { From 282b2041b0b7623b0fdada18a6dda66e3ff3e8ec Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Tue, 7 Nov 2023 00:55:52 +0000 Subject: [PATCH 019/374] Replace License to Legal in the part 7, add a section for the use of Bid For Power name there and add the finished Super Deformed (Chibi style) easter egg feature in the cvars task list --- README.md | 12 +++++++++--- docs/bfp_cvars_task.md | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7ae2b4e..a0b7e9f 100644 --- a/README.md +++ b/README.md @@ -30,13 +30,13 @@ A legendary 90s era Quake 3 Arena mod. > > > > > > 5.4. [Optional](#optional) > > 6. [Notes](#notes) -> > 7. [License](#license) +> > 7. [Legal](#legal) > > 8. [Credits](#credits) # TODO list: - [x] ~~Toggeable flight (bind key). Hint: FLIGHT POWERUP~~ -- [ ] Gauntlet logic must be replaced as a bind key, it will use fight animation (using kicks and fists) +- [ ] Melee feature - [x] ~~Remove weapon visuals (models and stuff)~~ - [x] ~~Animations as listed on the old docs~~ - [x] ~~Bind key to recover ki energy~~ @@ -396,7 +396,7 @@ The information in the map file can be useful for debugging and performance anal - ui_specifyleague.c - ui_spreset.c -### License +### Legal The mod source code is GPLv3 licensed, the source code contents are based on Quake III Arena which is GPLv2 licensed. @@ -406,6 +406,12 @@ The ancient abandoned MP3 decoder (`ui_mem.c`, `ui_mem.h`, `ui_mp3decoder.c` and - Copyright (C) 1999 Aaron Holtzman - Copyright (C) 2000-2001 Tim Angus +#### Bid For Power name + +Nobody owns the "Bid For Power" name. Bid For Power was founded by Chris James and likely ended up in the palm of Yrgol's hand (although Yrgol doesn't own the assets). The owner, the maintainer and the contributors of the repository don't own this name.
+This does not give any single person or a group of people to sell the name, basically it belongs to the original community.
+The Bid For Power team may provide sufficient security against any claims or improper use of the name. + ## Credits Bid For Power is made by these staff members. We don't own materials such as art designs, maps and character models from their assets. diff --git a/docs/bfp_cvars_task.md b/docs/bfp_cvars_task.md index 73dc250..6cab102 100644 --- a/docs/bfp_cvars_task.md +++ b/docs/bfp_cvars_task.md @@ -55,6 +55,7 @@ ## COMPLETED: +- [x] ~~cg_superdeformed~~ - [x] ~~cg_yrgolroxor~~ - [x] ~~cg_thirdPersonHeight~~ - [x] ~~cg_fixedThirdPerson~~ From 09e8a8dc76e7b24401a3c1478cd93cdb23565cca Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Wed, 29 Nov 2023 02:47:18 +0000 Subject: [PATCH 020/374] game: No drowning underwater --- source/game/g_active.c | 6 +++++- source/game/g_client.c | 3 ++- source/game/g_local.h | 3 ++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/source/game/g_active.c b/source/game/g_active.c index 6246473..1c02367 100644 --- a/source/game/g_active.c +++ b/source/game/g_active.c @@ -100,6 +100,10 @@ void P_WorldEffects( gentity_t *ent ) { qboolean envirosuit; int waterlevel; + envirosuit = ent->client->ps.powerups[PW_BATTLESUIT] > level.time; + + // BFP - No drowning +#if 0 if ( ent->client->noclip ) { ent->client->airOutTime = level.time + 12000; // don't need air return; @@ -107,7 +111,6 @@ void P_WorldEffects( gentity_t *ent ) { waterlevel = ent->waterlevel; - envirosuit = ent->client->ps.powerups[PW_BATTLESUIT] > level.time; // // check for drowning @@ -148,6 +151,7 @@ void P_WorldEffects( gentity_t *ent ) { ent->client->airOutTime = level.time + 12000; ent->damage = 2; } +#endif // // check for sizzle damage (move to pmove?) diff --git a/source/game/g_client.c b/source/game/g_client.c index 22b18f4..59284a1 100644 --- a/source/game/g_client.c +++ b/source/game/g_client.c @@ -1118,7 +1118,8 @@ void ClientSpawn(gentity_t *ent) { client->ps.persistant[PERS_SPAWN_COUNT]++; client->ps.persistant[PERS_TEAM] = client->sess.sessionTeam; - client->airOutTime = level.time + 12000; + // BFP - No drowning + // client->airOutTime = level.time + 12000; trap_GetUserinfo( index, userinfo, sizeof(userinfo) ); // set max health diff --git a/source/game/g_local.h b/source/game/g_local.h index 040e1dc..a4af6f6 100644 --- a/source/game/g_local.h +++ b/source/game/g_local.h @@ -300,7 +300,8 @@ struct gclient_s { qboolean inactivityWarning; // qtrue if the five seoond warning has been given int rewardTime; // clear the EF_AWARD_IMPRESSIVE, etc when time > this - int airOutTime; + // BFP - No drowning + // int airOutTime; int lastKillTime; // for multiple kill rewards // BFP - no hook From 91a72deb333fd9de05efc03de86d70e95273be88 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sat, 20 Jan 2024 18:23:53 +0100 Subject: [PATCH 021/374] game: When using ki charge and going backwards, don't force to change the jump animation under water --- source/game/bg_pmove.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index 63aad52..3156015 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -1645,7 +1645,8 @@ static void PM_KiChargeAnimation( void ) { // BFP - Ki Charge // do jump animation if it's falling if ( !( pml.groundTrace.contents & CONTENTS_SOLID ) && !( pm->ps->pm_flags & PMF_FLYING ) - && ( pm->ps->pm_flags & PMF_FALLING ) ) { + && ( pm->ps->pm_flags & PMF_FALLING ) + && pm->waterlevel <= 1 ) { // Don't force inside the water pm->ps->pm_flags &= ~PMF_FALLING; // Handle PMF_FALLING when falling FORCEJUMP_ANIM_HANDLING(); PM_ContinueTorsoAnim( TORSO_STAND ); // Keep the torso @@ -1658,7 +1659,8 @@ static void PM_KiChargeAnimation( void ) { // BFP - Ki Charge PM_ContinueLegsAnim( LEGS_IDLE ); // Keep the legs when being near to the ground at that height // do jump animation if it's falling if ( !( pml.groundTrace.contents & CONTENTS_SOLID ) - && ( pm->ps->pm_flags & PMF_FALLING ) ) { + && ( pm->ps->pm_flags & PMF_FALLING ) + && pm->waterlevel <= 1 ) { // Don't force inside the water FORCEJUMP_ANIM_HANDLING(); PM_ContinueTorsoAnim( TORSO_STAND ); // Keep the torso } From 52a38c22bf3f32dda376de29aca9270b85fc0a5c Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sat, 20 Jan 2024 19:14:53 +0100 Subject: [PATCH 022/374] cgame: Apply particles. Implement bubble and dash smoke particles. Clean up cg_marks and cg_particles source code --- Makefile | 2 +- MakefileQVM | 2 +- source/cgame/cg_local.h | 4 + source/cgame/cg_marks.c | 1977 +---------------------------------- source/cgame/cg_particles.c | 221 ++-- source/cgame/cgame.bat | 2 + source/cgame/cgame.q3asm | 1 + 7 files changed, 137 insertions(+), 2072 deletions(-) diff --git a/Makefile b/Makefile index a65e177..8a8df47 100644 --- a/Makefile +++ b/Makefile @@ -372,7 +372,6 @@ makedirs: ############################################################################# ## BASEQ3 CGAME ############################################################################# -# $(B)/cgame/cg_particles.o \ CGOBJ_ = \ $(B)/cgame/cg_main.o \ @@ -389,6 +388,7 @@ CGOBJ_ = \ $(B)/cgame/cg_info.o \ $(B)/cgame/cg_localents.o \ $(B)/cgame/cg_marks.o \ + $(B)/cgame/cg_particles.o \ $(B)/cgame/cg_players.o \ $(B)/cgame/cg_playerstate.o \ $(B)/cgame/cg_predict.o \ diff --git a/MakefileQVM b/MakefileQVM index 4599ad2..a140d4d 100644 --- a/MakefileQVM +++ b/MakefileQVM @@ -88,7 +88,7 @@ QA_SRC = \ CG_SRC = \ cg_main $(CGDIR)/cg_syscalls.asm \ cg_consolecmds cg_draw cg_drawtools cg_effects cg_ents cg_event cg_info \ - cg_localents cg_marks cg_players cg_playerstate cg_predict cg_scoreboard \ + cg_localents cg_marks cg_particles cg_players cg_playerstate cg_predict cg_scoreboard \ cg_servercmds cg_snapshot cg_view cg_weapons \ bg_slidemove bg_pmove bg_lib bg_misc \ q_math q_shared \ diff --git a/source/cgame/cg_local.h b/source/cgame/cg_local.h index 89d5d9e..6214d46 100644 --- a/source/cgame/cg_local.h +++ b/source/cgame/cg_local.h @@ -1488,6 +1488,10 @@ void CG_ParticleSparks (vec3_t org, vec3_t vel, int duration, float x, float y, void CG_ParticleDust (centity_t *cent, vec3_t origin, vec3_t dir); void CG_ParticleMisc (qhandle_t pshader, vec3_t origin, int size, int duration, float alpha); void CG_ParticleExplosion (char *animStr, vec3_t origin, vec3_t vel, int duration, int sizeStart, int sizeEnd); +// BFP - Bubble particle +void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb, float range, int snum); +// BFP - Dash smoke particle for ki boost when moving in the ground +void CG_ParticleDashSmoke (centity_t *cent, qhandle_t pshader, vec3_t origin); extern qboolean initparticles; int CG_NewParticleArea ( int num ); diff --git a/source/cgame/cg_marks.c b/source/cgame/cg_marks.c index 7717308..1f8b8f5 100644 --- a/source/cgame/cg_marks.c +++ b/source/cgame/cg_marks.c @@ -65,7 +65,7 @@ CG_FreeMarkPoly ================== */ void CG_FreeMarkPoly( markPoly_t *le ) { - if ( !le->prevMark ) { + if ( !le->prevMark || !le->nextMark ) { CG_Error( "CG_FreeLocalEntity: not active" ); } @@ -291,1978 +291,3 @@ void CG_AddMarks( void ) { trap_R_AddPolyToScene( mp->markShader, mp->poly.numVerts, mp->verts ); } } - -// cg_particles.c - -#define BLOODRED 2 -#define EMISIVEFADE 3 -#define GREY75 4 - -typedef struct particle_s -{ - struct particle_s *next; - - float time; - float endtime; - - vec3_t org; - vec3_t vel; - vec3_t accel; - int color; - float colorvel; - float alpha; - float alphavel; - int type; - qhandle_t pshader; - - float height; - float width; - - float endheight; - float endwidth; - - float start; - float end; - - float startfade; - qboolean rotate; - int snum; - - qboolean link; - - // Ridah - int shaderAnim; - int roll; - - int accumroll; - -} cparticle_t; - -typedef enum -{ - P_NONE, - P_WEATHER, - P_FLAT, - P_SMOKE, - P_ROTATE, - P_WEATHER_TURBULENT, - P_ANIM, // Ridah - P_BAT, - P_BLEED, - P_FLAT_SCALEUP, - P_FLAT_SCALEUP_FADE, - P_WEATHER_FLURRY, - P_SMOKE_IMPACT, - P_BUBBLE, - P_BUBBLE_TURBULENT, - P_SPRITE -} particle_type_t; - -#define MAX_SHADER_ANIMS 32 -#define MAX_SHADER_ANIM_FRAMES 64 - -static char *shaderAnimNames[MAX_SHADER_ANIMS] = { - "explode1", - NULL -}; -static qhandle_t shaderAnims[MAX_SHADER_ANIMS][MAX_SHADER_ANIM_FRAMES]; -static int shaderAnimCounts[MAX_SHADER_ANIMS] = { - 23 -}; -static float shaderAnimSTRatio[MAX_SHADER_ANIMS] = { - 1.0f -}; -static int numShaderAnims; -// done. - -#define PARTICLE_GRAVITY 40 -#define MAX_PARTICLES 1024 - -cparticle_t *active_particles, *free_particles; -cparticle_t particles[MAX_PARTICLES]; -int cl_numparticles = MAX_PARTICLES; - -qboolean initparticles = qfalse; -vec3_t pvforward, pvright, pvup; -vec3_t rforward, rright, rup; - -float oldtime; - -/* -=============== -CL_ClearParticles -=============== -*/ -void CG_ClearParticles (void) -{ - int i; - - memset( particles, 0, sizeof(particles) ); - - free_particles = &particles[0]; - active_particles = NULL; - - for (i=0 ;itype == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY - || p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) - {// create a front facing polygon - - if (p->type != P_WEATHER_FLURRY) - { - if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) - { - if (org[2] > p->end) - { - p->time = cg.time; - VectorCopy (org, p->org); // Ridah, fixes rare snow flakes that flicker on the ground - - p->org[2] = ( p->start + crandom () * 4 ); - - - if (p->type == P_BUBBLE_TURBULENT) - { - p->vel[0] = crandom() * 4; - p->vel[1] = crandom() * 4; - } - - } - } - else - { - if (org[2] < p->end) - { - p->time = cg.time; - VectorCopy (org, p->org); // Ridah, fixes rare snow flakes that flicker on the ground - - while (p->org[2] < p->end) - { - p->org[2] += (p->start - p->end); - } - - - if (p->type == P_WEATHER_TURBULENT) - { - p->vel[0] = crandom() * 16; - p->vel[1] = crandom() * 16; - } - - } - } - - - // Rafael snow pvs check - if (!p->link) - return; - - p->alpha = 1; - } - - // Ridah, had to do this or MAX_POLYS is being exceeded in village1.bsp - if (Distance( cg.snap->ps.origin, org ) > 1024) { - return; - } - // done. - - if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) - { - VectorMA (org, -p->height, pvup, point); - VectorMA (point, -p->width, pvright, point); - VectorCopy (point, verts[0].xyz); - verts[0].st[0] = 0; - verts[0].st[1] = 0; - verts[0].modulate[0] = 255; - verts[0].modulate[1] = 255; - verts[0].modulate[2] = 255; - verts[0].modulate[3] = 255 * p->alpha; - - VectorMA (org, -p->height, pvup, point); - VectorMA (point, p->width, pvright, point); - VectorCopy (point, verts[1].xyz); - verts[1].st[0] = 0; - verts[1].st[1] = 1; - verts[1].modulate[0] = 255; - verts[1].modulate[1] = 255; - verts[1].modulate[2] = 255; - verts[1].modulate[3] = 255 * p->alpha; - - VectorMA (org, p->height, pvup, point); - VectorMA (point, p->width, pvright, point); - VectorCopy (point, verts[2].xyz); - verts[2].st[0] = 1; - verts[2].st[1] = 1; - verts[2].modulate[0] = 255; - verts[2].modulate[1] = 255; - verts[2].modulate[2] = 255; - verts[2].modulate[3] = 255 * p->alpha; - - VectorMA (org, p->height, pvup, point); - VectorMA (point, -p->width, pvright, point); - VectorCopy (point, verts[3].xyz); - verts[3].st[0] = 1; - verts[3].st[1] = 0; - verts[3].modulate[0] = 255; - verts[3].modulate[1] = 255; - verts[3].modulate[2] = 255; - verts[3].modulate[3] = 255 * p->alpha; - } - else - { - VectorMA (org, -p->height, pvup, point); - VectorMA (point, -p->width, pvright, point); - VectorCopy( point, TRIverts[0].xyz ); - TRIverts[0].st[0] = 1; - TRIverts[0].st[1] = 0; - TRIverts[0].modulate[0] = 255; - TRIverts[0].modulate[1] = 255; - TRIverts[0].modulate[2] = 255; - TRIverts[0].modulate[3] = 255 * p->alpha; - - VectorMA (org, p->height, pvup, point); - VectorMA (point, -p->width, pvright, point); - VectorCopy (point, TRIverts[1].xyz); - TRIverts[1].st[0] = 0; - TRIverts[1].st[1] = 0; - TRIverts[1].modulate[0] = 255; - TRIverts[1].modulate[1] = 255; - TRIverts[1].modulate[2] = 255; - TRIverts[1].modulate[3] = 255 * p->alpha; - - VectorMA (org, p->height, pvup, point); - VectorMA (point, p->width, pvright, point); - VectorCopy (point, TRIverts[2].xyz); - TRIverts[2].st[0] = 0; - TRIverts[2].st[1] = 1; - TRIverts[2].modulate[0] = 255; - TRIverts[2].modulate[1] = 255; - TRIverts[2].modulate[2] = 255; - TRIverts[2].modulate[3] = 255 * p->alpha; - } - - } - else if (p->type == P_SPRITE) - { - vec3_t rr, ru; - vec3_t rotate_ang; - - VectorSet (color, 1.0, 1.0, 0.5); - time = cg.time - p->time; - time2 = p->endtime - p->time; - ratio = time / time2; - - width = p->width + ( ratio * ( p->endwidth - p->width) ); - height = p->height + ( ratio * ( p->endheight - p->height) ); - - if (p->roll) { - vectoangles( cg.refdef.viewaxis[0], rotate_ang ); - rotate_ang[ROLL] += p->roll; - AngleVectors ( rotate_ang, NULL, rr, ru); - } - - if (p->roll) { - VectorMA (org, -height, ru, point); - VectorMA (point, -width, rr, point); - } else { - VectorMA (org, -height, pvup, point); - VectorMA (point, -width, pvright, point); - } - VectorCopy (point, verts[0].xyz); - verts[0].st[0] = 0; - verts[0].st[1] = 0; - verts[0].modulate[0] = 255; - verts[0].modulate[1] = 255; - verts[0].modulate[2] = 255; - verts[0].modulate[3] = 255; - - if (p->roll) { - VectorMA (point, 2*height, ru, point); - } else { - VectorMA (point, 2*height, pvup, point); - } - VectorCopy (point, verts[1].xyz); - verts[1].st[0] = 0; - verts[1].st[1] = 1; - verts[1].modulate[0] = 255; - verts[1].modulate[1] = 255; - verts[1].modulate[2] = 255; - verts[1].modulate[3] = 255; - - if (p->roll) { - VectorMA (point, 2*width, rr, point); - } else { - VectorMA (point, 2*width, pvright, point); - } - VectorCopy (point, verts[2].xyz); - verts[2].st[0] = 1; - verts[2].st[1] = 1; - verts[2].modulate[0] = 255; - verts[2].modulate[1] = 255; - verts[2].modulate[2] = 255; - verts[2].modulate[3] = 255; - - if (p->roll) { - VectorMA (point, -2*height, ru, point); - } else { - VectorMA (point, -2*height, pvup, point); - } - VectorCopy (point, verts[3].xyz); - verts[3].st[0] = 1; - verts[3].st[1] = 0; - verts[3].modulate[0] = 255; - verts[3].modulate[1] = 255; - verts[3].modulate[2] = 255; - verts[3].modulate[3] = 255; - } - else if (p->type == P_SMOKE || p->type == P_SMOKE_IMPACT) - {// create a front rotating facing polygon - - if ( p->type == P_SMOKE_IMPACT && Distance( cg.snap->ps.origin, org ) > 1024) { - return; - } - - if (p->color == BLOODRED) - VectorSet (color, 0.22f, 0.0f, 0.0f); - else if (p->color == GREY75) - { - float len; - float greyit; - float val; - len = Distance (cg.snap->ps.origin, org); - if (!len) - len = 1; - - val = 4096/len; - greyit = 0.25 * val; - if (greyit > 0.5) - greyit = 0.5; - - VectorSet (color, greyit, greyit, greyit); - } - else - VectorSet (color, 1.0, 1.0, 1.0); - - time = cg.time - p->time; - time2 = p->endtime - p->time; - ratio = time / time2; - - if (cg.time > p->startfade) - { - invratio = 1 - ( (cg.time - p->startfade) / (p->endtime - p->startfade) ); - - if (p->color == EMISIVEFADE) - { - float fval; - fval = (invratio * invratio); - if (fval < 0) - fval = 0; - VectorSet (color, fval , fval , fval ); - } - invratio *= p->alpha; - } - else - invratio = 1 * p->alpha; - - if (invratio > 1) - invratio = 1; - - width = p->width + ( ratio * ( p->endwidth - p->width) ); - height = p->height + ( ratio * ( p->endheight - p->height) ); - - if (p->type != P_SMOKE_IMPACT) - { - vec3_t temp; - - vectoangles (rforward, temp); - p->accumroll += p->roll; - temp[ROLL] += p->accumroll * 0.1; - AngleVectors ( temp, NULL, rright2, rup2); - } - else - { - VectorCopy (rright, rright2); - VectorCopy (rup, rup2); - } - - if (p->rotate) - { - VectorMA (org, -height, rup2, point); - VectorMA (point, -width, rright2, point); - } - else - { - VectorMA (org, -p->height, pvup, point); - VectorMA (point, -p->width, pvright, point); - } - VectorCopy (point, verts[0].xyz); - verts[0].st[0] = 0; - verts[0].st[1] = 0; - verts[0].modulate[0] = 255 * color[0]; - verts[0].modulate[1] = 255 * color[1]; - verts[0].modulate[2] = 255 * color[2]; - verts[0].modulate[3] = 255 * invratio; - - if (p->rotate) - { - VectorMA (org, -height, rup2, point); - VectorMA (point, width, rright2, point); - } - else - { - VectorMA (org, -p->height, pvup, point); - VectorMA (point, p->width, pvright, point); - } - VectorCopy (point, verts[1].xyz); - verts[1].st[0] = 0; - verts[1].st[1] = 1; - verts[1].modulate[0] = 255 * color[0]; - verts[1].modulate[1] = 255 * color[1]; - verts[1].modulate[2] = 255 * color[2]; - verts[1].modulate[3] = 255 * invratio; - - if (p->rotate) - { - VectorMA (org, height, rup2, point); - VectorMA (point, width, rright2, point); - } - else - { - VectorMA (org, p->height, pvup, point); - VectorMA (point, p->width, pvright, point); - } - VectorCopy (point, verts[2].xyz); - verts[2].st[0] = 1; - verts[2].st[1] = 1; - verts[2].modulate[0] = 255 * color[0]; - verts[2].modulate[1] = 255 * color[1]; - verts[2].modulate[2] = 255 * color[2]; - verts[2].modulate[3] = 255 * invratio; - - if (p->rotate) - { - VectorMA (org, height, rup2, point); - VectorMA (point, -width, rright2, point); - } - else - { - VectorMA (org, p->height, pvup, point); - VectorMA (point, -p->width, pvright, point); - } - VectorCopy (point, verts[3].xyz); - verts[3].st[0] = 1; - verts[3].st[1] = 0; - verts[3].modulate[0] = 255 * color[0]; - verts[3].modulate[1] = 255 * color[1]; - verts[3].modulate[2] = 255 * color[2]; - verts[3].modulate[3] = 255 * invratio; - - } - else if (p->type == P_BLEED) - { - vec3_t rr, ru; - vec3_t rotate_ang; - float alpha; - - alpha = p->alpha; - - if (p->roll) - { - vectoangles( cg.refdef.viewaxis[0], rotate_ang ); - rotate_ang[ROLL] += p->roll; - AngleVectors ( rotate_ang, NULL, rr, ru); - } - else - { - VectorCopy (pvup, ru); - VectorCopy (pvright, rr); - } - - VectorMA (org, -p->height, ru, point); - VectorMA (point, -p->width, rr, point); - VectorCopy (point, verts[0].xyz); - verts[0].st[0] = 0; - verts[0].st[1] = 0; - verts[0].modulate[0] = 111; - verts[0].modulate[1] = 19; - verts[0].modulate[2] = 9; - verts[0].modulate[3] = 255 * alpha; - - VectorMA (org, -p->height, ru, point); - VectorMA (point, p->width, rr, point); - VectorCopy (point, verts[1].xyz); - verts[1].st[0] = 0; - verts[1].st[1] = 1; - verts[1].modulate[0] = 111; - verts[1].modulate[1] = 19; - verts[1].modulate[2] = 9; - verts[1].modulate[3] = 255 * alpha; - - VectorMA (org, p->height, ru, point); - VectorMA (point, p->width, rr, point); - VectorCopy (point, verts[2].xyz); - verts[2].st[0] = 1; - verts[2].st[1] = 1; - verts[2].modulate[0] = 111; - verts[2].modulate[1] = 19; - verts[2].modulate[2] = 9; - verts[2].modulate[3] = 255 * alpha; - - VectorMA (org, p->height, ru, point); - VectorMA (point, -p->width, rr, point); - VectorCopy (point, verts[3].xyz); - verts[3].st[0] = 1; - verts[3].st[1] = 0; - verts[3].modulate[0] = 111; - verts[3].modulate[1] = 19; - verts[3].modulate[2] = 9; - verts[3].modulate[3] = 255 * alpha; - - } - else if (p->type == P_FLAT_SCALEUP) - { - float width, height; - float sinR, cosR; - - if (p->color == BLOODRED) - VectorSet (color, 1, 1, 1); - else - VectorSet (color, 0.5, 0.5, 0.5); - - time = cg.time - p->time; - time2 = p->endtime - p->time; - ratio = time / time2; - - width = p->width + ( ratio * ( p->endwidth - p->width) ); - height = p->height + ( ratio * ( p->endheight - p->height) ); - - if (width > p->endwidth) - width = p->endwidth; - - if (height > p->endheight) - height = p->endheight; - - sinR = height * sin(DEG2RAD(p->roll)) * sqrt(2); - cosR = width * cos(DEG2RAD(p->roll)) * sqrt(2); - - VectorCopy (org, verts[0].xyz); - verts[0].xyz[0] -= sinR; - verts[0].xyz[1] -= cosR; - verts[0].st[0] = 0; - verts[0].st[1] = 0; - verts[0].modulate[0] = 255 * color[0]; - verts[0].modulate[1] = 255 * color[1]; - verts[0].modulate[2] = 255 * color[2]; - verts[0].modulate[3] = 255; - - VectorCopy (org, verts[1].xyz); - verts[1].xyz[0] -= cosR; - verts[1].xyz[1] += sinR; - verts[1].st[0] = 0; - verts[1].st[1] = 1; - verts[1].modulate[0] = 255 * color[0]; - verts[1].modulate[1] = 255 * color[1]; - verts[1].modulate[2] = 255 * color[2]; - verts[1].modulate[3] = 255; - - VectorCopy (org, verts[2].xyz); - verts[2].xyz[0] += sinR; - verts[2].xyz[1] += cosR; - verts[2].st[0] = 1; - verts[2].st[1] = 1; - verts[2].modulate[0] = 255 * color[0]; - verts[2].modulate[1] = 255 * color[1]; - verts[2].modulate[2] = 255 * color[2]; - verts[2].modulate[3] = 255; - - VectorCopy (org, verts[3].xyz); - verts[3].xyz[0] += cosR; - verts[3].xyz[1] -= sinR; - verts[3].st[0] = 1; - verts[3].st[1] = 0; - verts[3].modulate[0] = 255 * color[0]; - verts[3].modulate[1] = 255 * color[1]; - verts[3].modulate[2] = 255 * color[2]; - verts[3].modulate[3] = 255; - } - else if (p->type == P_FLAT) - { - - VectorCopy (org, verts[0].xyz); - verts[0].xyz[0] -= p->height; - verts[0].xyz[1] -= p->width; - verts[0].st[0] = 0; - verts[0].st[1] = 0; - verts[0].modulate[0] = 255; - verts[0].modulate[1] = 255; - verts[0].modulate[2] = 255; - verts[0].modulate[3] = 255; - - VectorCopy (org, verts[1].xyz); - verts[1].xyz[0] -= p->height; - verts[1].xyz[1] += p->width; - verts[1].st[0] = 0; - verts[1].st[1] = 1; - verts[1].modulate[0] = 255; - verts[1].modulate[1] = 255; - verts[1].modulate[2] = 255; - verts[1].modulate[3] = 255; - - VectorCopy (org, verts[2].xyz); - verts[2].xyz[0] += p->height; - verts[2].xyz[1] += p->width; - verts[2].st[0] = 1; - verts[2].st[1] = 1; - verts[2].modulate[0] = 255; - verts[2].modulate[1] = 255; - verts[2].modulate[2] = 255; - verts[2].modulate[3] = 255; - - VectorCopy (org, verts[3].xyz); - verts[3].xyz[0] += p->height; - verts[3].xyz[1] -= p->width; - verts[3].st[0] = 1; - verts[3].st[1] = 0; - verts[3].modulate[0] = 255; - verts[3].modulate[1] = 255; - verts[3].modulate[2] = 255; - verts[3].modulate[3] = 255; - - } - // Ridah - else if (p->type == P_ANIM) { - vec3_t rr, ru; - vec3_t rotate_ang; - int i, j; - - time = cg.time - p->time; - time2 = p->endtime - p->time; - ratio = time / time2; - if (ratio >= 1.0f) { - ratio = 0.9999f; - } - - width = p->width + ( ratio * ( p->endwidth - p->width) ); - height = p->height + ( ratio * ( p->endheight - p->height) ); - - // if we are "inside" this sprite, don't draw - if (Distance( cg.snap->ps.origin, org ) < width/1.5) { - return; - } - - i = p->shaderAnim; - j = (int)floor(ratio * shaderAnimCounts[p->shaderAnim]); - p->pshader = shaderAnims[i][j]; - - if (p->roll) { - vectoangles( cg.refdef.viewaxis[0], rotate_ang ); - rotate_ang[ROLL] += p->roll; - AngleVectors ( rotate_ang, NULL, rr, ru); - } - - if (p->roll) { - VectorMA (org, -height, ru, point); - VectorMA (point, -width, rr, point); - } else { - VectorMA (org, -height, pvup, point); - VectorMA (point, -width, pvright, point); - } - VectorCopy (point, verts[0].xyz); - verts[0].st[0] = 0; - verts[0].st[1] = 0; - verts[0].modulate[0] = 255; - verts[0].modulate[1] = 255; - verts[0].modulate[2] = 255; - verts[0].modulate[3] = 255; - - if (p->roll) { - VectorMA (point, 2*height, ru, point); - } else { - VectorMA (point, 2*height, pvup, point); - } - VectorCopy (point, verts[1].xyz); - verts[1].st[0] = 0; - verts[1].st[1] = 1; - verts[1].modulate[0] = 255; - verts[1].modulate[1] = 255; - verts[1].modulate[2] = 255; - verts[1].modulate[3] = 255; - - if (p->roll) { - VectorMA (point, 2*width, rr, point); - } else { - VectorMA (point, 2*width, pvright, point); - } - VectorCopy (point, verts[2].xyz); - verts[2].st[0] = 1; - verts[2].st[1] = 1; - verts[2].modulate[0] = 255; - verts[2].modulate[1] = 255; - verts[2].modulate[2] = 255; - verts[2].modulate[3] = 255; - - if (p->roll) { - VectorMA (point, -2*height, ru, point); - } else { - VectorMA (point, -2*height, pvup, point); - } - VectorCopy (point, verts[3].xyz); - verts[3].st[0] = 1; - verts[3].st[1] = 0; - verts[3].modulate[0] = 255; - verts[3].modulate[1] = 255; - verts[3].modulate[2] = 255; - verts[3].modulate[3] = 255; - } - // done. - - if (!p->pshader) { -// (SA) temp commented out for DM -// CG_Printf ("CG_AddParticleToScene type %d p->pshader == ZERO\n", p->type); - return; - } - - if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY) - trap_R_AddPolyToScene( p->pshader, 3, TRIverts ); - else - trap_R_AddPolyToScene( p->pshader, 4, verts ); - -} - -// Ridah, made this static so it doesn't interfere with other files -static float roll = 0.0; - -/* -=============== -CG_AddParticles -=============== -*/ -void CG_AddParticles (void) -{ - cparticle_t *p, *next; - float alpha; - float time, time2; - vec3_t org; - int color; - cparticle_t *active, *tail; - int type; - vec3_t rotate_ang; - - if (!initparticles) - CG_ClearParticles (); - - VectorCopy( cg.refdef.viewaxis[0], pvforward ); - VectorCopy( cg.refdef.viewaxis[1], pvright ); - VectorCopy( cg.refdef.viewaxis[2], pvup ); - - vectoangles( cg.refdef.viewaxis[0], rotate_ang ); - roll += ((cg.time - oldtime) * 0.1) ; - rotate_ang[ROLL] += (roll*0.9); - AngleVectors ( rotate_ang, rforward, rright, rup); - - oldtime = cg.time; - - active = NULL; - tail = NULL; - - for (p=active_particles ; p ; p=next) - { - - next = p->next; - - time = (cg.time - p->time)*0.001; - - alpha = p->alpha + time*p->alphavel; - if (alpha <= 0) - { // faded out - p->next = free_particles; - free_particles = p; - p->type = 0; - p->color = 0; - p->alpha = 0; - continue; - } - - if (p->type == P_SMOKE || p->type == P_ANIM || p->type == P_BLEED || p->type == P_SMOKE_IMPACT) - { - if (cg.time > p->endtime) - { - p->next = free_particles; - free_particles = p; - p->type = 0; - p->color = 0; - p->alpha = 0; - - continue; - } - - } - - if (p->type == P_WEATHER_FLURRY) - { - if (cg.time > p->endtime) - { - p->next = free_particles; - free_particles = p; - p->type = 0; - p->color = 0; - p->alpha = 0; - - continue; - } - } - - - if (p->type == P_FLAT_SCALEUP_FADE) - { - if (cg.time > p->endtime) - { - p->next = free_particles; - free_particles = p; - p->type = 0; - p->color = 0; - p->alpha = 0; - continue; - } - - } - - if ((p->type == P_BAT || p->type == P_SPRITE) && p->endtime < 0) { - // temporary sprite - CG_AddParticleToScene (p, p->org, alpha); - p->next = free_particles; - free_particles = p; - p->type = 0; - p->color = 0; - p->alpha = 0; - continue; - } - - p->next = NULL; - if (!tail) - active = tail = p; - else - { - tail->next = p; - tail = p; - } - - if (alpha > 1.0) - alpha = 1; - - color = p->color; - - time2 = time*time; - - org[0] = p->org[0] + p->vel[0]*time + p->accel[0]*time2; - org[1] = p->org[1] + p->vel[1]*time + p->accel[1]*time2; - org[2] = p->org[2] + p->vel[2]*time + p->accel[2]*time2; - - type = p->type; - - CG_AddParticleToScene (p, org, alpha); - } - - active_particles = active; -} - -/* -====================== -CG_AddParticles -====================== -*/ -void CG_ParticleSnowFlurry (qhandle_t pshader, centity_t *cent) -{ - cparticle_t *p; - qboolean turb = qtrue; - - if (!pshader) - CG_Printf ("CG_ParticleSnowFlurry pshader == ZERO!\n"); - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - p->time = cg.time; - p->color = 0; - p->alpha = 0.90f; - p->alphavel = 0; - - p->start = cent->currentState.origin2[0]; - p->end = cent->currentState.origin2[1]; - - p->endtime = cg.time + cent->currentState.time; - p->startfade = cg.time + cent->currentState.time2; - - p->pshader = pshader; - - if (rand()%100 > 90) - { - p->height = 32; - p->width = 32; - p->alpha = 0.10f; - } - else - { - p->height = 1; - p->width = 1; - } - - p->vel[2] = -20; - - p->type = P_WEATHER_FLURRY; - - if (turb) - p->vel[2] = -10; - - VectorCopy(cent->currentState.origin, p->org); - - p->org[0] = p->org[0]; - p->org[1] = p->org[1]; - p->org[2] = p->org[2]; - - p->vel[0] = p->vel[1] = 0; - - p->accel[0] = p->accel[1] = p->accel[2] = 0; - - p->vel[0] += cent->currentState.angles[0] * 32 + (crandom() * 16); - p->vel[1] += cent->currentState.angles[1] * 32 + (crandom() * 16); - p->vel[2] += cent->currentState.angles[2]; - - if (turb) - { - p->accel[0] = crandom () * 16; - p->accel[1] = crandom () * 16; - } - -} - -void CG_ParticleSnow (qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb, float range, int snum) -{ - cparticle_t *p; - - if (!pshader) - CG_Printf ("CG_ParticleSnow pshader == ZERO!\n"); - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - p->time = cg.time; - p->color = 0; - p->alpha = 0.40f; - p->alphavel = 0; - p->start = origin[2]; - p->end = origin2[2]; - p->pshader = pshader; - p->height = 1; - p->width = 1; - - p->vel[2] = -50; - - if (turb) - { - p->type = P_WEATHER_TURBULENT; - p->vel[2] = -50 * 1.3; - } - else - { - p->type = P_WEATHER; - } - - VectorCopy(origin, p->org); - - p->org[0] = p->org[0] + ( crandom() * range); - p->org[1] = p->org[1] + ( crandom() * range); - p->org[2] = p->org[2] + ( crandom() * (p->start - p->end)); - - p->vel[0] = p->vel[1] = 0; - - p->accel[0] = p->accel[1] = p->accel[2] = 0; - - if (turb) - { - p->vel[0] = crandom() * 16; - p->vel[1] = crandom() * 16; - } - - // Rafael snow pvs check - p->snum = snum; - p->link = qtrue; - -} - -void CG_ParticleBubble (qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb, float range, int snum) -{ - cparticle_t *p; - float randsize; - - if (!pshader) - CG_Printf ("CG_ParticleSnow pshader == ZERO!\n"); - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - p->time = cg.time; - p->color = 0; - p->alpha = 0.40f; - p->alphavel = 0; - p->start = origin[2]; - p->end = origin2[2]; - p->pshader = pshader; - - randsize = 1 + (crandom() * 0.5); - - p->height = randsize; - p->width = randsize; - - p->vel[2] = 50 + ( crandom() * 10 ); - - if (turb) - { - p->type = P_BUBBLE_TURBULENT; - p->vel[2] = 50 * 1.3; - } - else - { - p->type = P_BUBBLE; - } - - VectorCopy(origin, p->org); - - p->org[0] = p->org[0] + ( crandom() * range); - p->org[1] = p->org[1] + ( crandom() * range); - p->org[2] = p->org[2] + ( crandom() * (p->start - p->end)); - - p->vel[0] = p->vel[1] = 0; - - p->accel[0] = p->accel[1] = p->accel[2] = 0; - - if (turb) - { - p->vel[0] = crandom() * 4; - p->vel[1] = crandom() * 4; - } - - // Rafael snow pvs check - p->snum = snum; - p->link = qtrue; - -} - -void CG_ParticleSmoke (qhandle_t pshader, centity_t *cent) -{ - - // using cent->density = enttime - // cent->frame = startfade - cparticle_t *p; - - if (!pshader) - CG_Printf ("CG_ParticleSmoke == ZERO!\n"); - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - p->time = cg.time; - - p->endtime = cg.time + cent->currentState.time; - p->startfade = cg.time + cent->currentState.time2; - - p->color = 0; - p->alpha = 1.0; - p->alphavel = 0; - p->start = cent->currentState.origin[2]; - p->end = cent->currentState.origin2[2]; - p->pshader = pshader; - p->rotate = qfalse; - p->height = 8; - p->width = 8; - p->endheight = 32; - p->endwidth = 32; - p->type = P_SMOKE; - - VectorCopy(cent->currentState.origin, p->org); - - p->vel[0] = p->vel[1] = 0; - p->accel[0] = p->accel[1] = p->accel[2] = 0; - - p->vel[2] = 5; - - if (cent->currentState.frame == 1)// reverse gravity - p->vel[2] *= -1; - - p->roll = 8 + (crandom() * 4); -} - - -void CG_ParticleBulletDebris (vec3_t org, vec3_t vel, int duration) -{ - - cparticle_t *p; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - p->time = cg.time; - - p->endtime = cg.time + duration; - p->startfade = cg.time + duration/2; - - p->color = EMISIVEFADE; - p->alpha = 1.0; - p->alphavel = 0; - - p->height = 0.5; - p->width = 0.5; - p->endheight = 0.5; - p->endwidth = 0.5; - - p->pshader = cgs.media.tracerShader; - - p->type = P_SMOKE; - - VectorCopy(org, p->org); - - p->vel[0] = vel[0]; - p->vel[1] = vel[1]; - p->vel[2] = vel[2]; - p->accel[0] = p->accel[1] = p->accel[2] = 0; - - p->accel[2] = -60; - p->vel[2] += -20; - -} - -/* -====================== -CG_ParticleExplosion -====================== -*/ - -void CG_ParticleExplosion (char *animStr, vec3_t origin, vec3_t vel, int duration, int sizeStart, int sizeEnd) -{ - cparticle_t *p; - int anim; - - if (animStr < (char *)10) - CG_Error( "CG_ParticleExplosion: animStr is probably an index rather than a string" ); - - // find the animation string - for (anim=0; shaderAnimNames[anim]; anim++) { - if (!Q_stricmp( animStr, shaderAnimNames[anim] )) - break; - } - if (!shaderAnimNames[anim]) { - CG_Error("CG_ParticleExplosion: unknown animation string: %s\n", animStr); - return; - } - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - p->time = cg.time; - p->alpha = 0.5; - p->alphavel = 0; - - if (duration < 0) { - duration *= -1; - p->roll = 0; - } else { - p->roll = crandom()*179; - } - - p->shaderAnim = anim; - - p->width = sizeStart; - p->height = sizeStart*shaderAnimSTRatio[anim]; // for sprites that are stretch in either direction - - p->endheight = sizeEnd; - p->endwidth = sizeEnd*shaderAnimSTRatio[anim]; - - p->endtime = cg.time + duration; - - p->type = P_ANIM; - - VectorCopy( origin, p->org ); - VectorCopy( vel, p->vel ); - VectorClear( p->accel ); - -} - -// Rafael Shrapnel -void CG_AddParticleShrapnel (localEntity_t *le) -{ - return; -} -// done. - -int CG_NewParticleArea (int num) -{ - // const char *str; - char *str; - char *token; - int type; - vec3_t origin, origin2; - int i; - float range = 0; - int turb; - int numparticles; - int snum; - - str = (char *) CG_ConfigString (num); - if (!str[0]) - return (0); - - // returns type 128 64 or 32 - token = COM_Parse (&str); - type = atoi (token); - - if (type == 1) - range = 128; - else if (type == 2) - range = 64; - else if (type == 3) - range = 32; - else if (type == 0) - range = 256; - else if (type == 4) - range = 8; - else if (type == 5) - range = 16; - else if (type == 6) - range = 32; - else if (type == 7) - range = 64; - - - for (i=0; i<3; i++) - { - token = COM_Parse (&str); - origin[i] = atof (token); - } - - for (i=0; i<3; i++) - { - token = COM_Parse (&str); - origin2[i] = atof (token); - } - - token = COM_Parse (&str); - numparticles = atoi (token); - - token = COM_Parse (&str); - turb = atoi (token); - - token = COM_Parse (&str); - snum = atoi (token); - - for (i=0; i= 4) - CG_ParticleBubble (cgs.media.waterBubbleShader, origin, origin2, turb, range, snum); - else - CG_ParticleSnow (cgs.media.waterBubbleShader, origin, origin2, turb, range, snum); - } - - return (1); -} - -void CG_SnowLink (centity_t *cent, qboolean particleOn) -{ - cparticle_t *p, *next; - int id; - - id = cent->currentState.frame; - - for (p=active_particles ; p ; p=next) - { - next = p->next; - - if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT) - { - if (p->snum == id) - { - if (particleOn) - p->link = qtrue; - else - p->link = qfalse; - } - } - - } -} - -void CG_ParticleImpactSmokePuff (qhandle_t pshader, vec3_t origin) -{ - cparticle_t *p; - - if (!pshader) - CG_Printf ("CG_ParticleImpactSmokePuff pshader == ZERO!\n"); - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - p->time = cg.time; - p->alpha = 0.25; - p->alphavel = 0; - p->roll = crandom()*179; - - p->pshader = pshader; - - p->endtime = cg.time + 1000; - p->startfade = cg.time + 100; - - p->width = rand()%4 + 8; - p->height = rand()%4 + 8; - - p->endheight = p->height *2; - p->endwidth = p->width * 2; - - p->endtime = cg.time + 500; - - p->type = P_SMOKE_IMPACT; - - VectorCopy( origin, p->org ); - VectorSet(p->vel, 0, 0, 20); - VectorSet(p->accel, 0, 0, 20); - - p->rotate = qtrue; -} - -void CG_Particle_Bleed (qhandle_t pshader, vec3_t start, vec3_t dir, int fleshEntityNum, int duration) -{ - cparticle_t *p; - - if (!pshader) - CG_Printf ("CG_Particle_Bleed pshader == ZERO!\n"); - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - p->time = cg.time; - p->alpha = 1.0; - p->alphavel = 0; - p->roll = 0; - - p->pshader = pshader; - - p->endtime = cg.time + duration; - - if (fleshEntityNum) - p->startfade = cg.time; - else - p->startfade = cg.time + 100; - - p->width = 4; - p->height = 4; - - p->endheight = 4+rand()%3; - p->endwidth = p->endheight; - - p->type = P_SMOKE; - - VectorCopy( start, p->org ); - p->vel[0] = 0; - p->vel[1] = 0; - p->vel[2] = -20; - VectorClear( p->accel ); - - p->rotate = qfalse; - - p->roll = rand()%179; - - p->color = BLOODRED; - p->alpha = 0.75; - -} - -void CG_Particle_OilParticle (qhandle_t pshader, centity_t *cent) -{ - cparticle_t *p; - - int time; - int time2; - float ratio; - - float duration = 1500; - - time = cg.time; - time2 = cg.time + cent->currentState.time; - - ratio =(float)1 - ((float)time / (float)time2); - - if (!pshader) - CG_Printf ("CG_Particle_OilParticle == ZERO!\n"); - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - p->time = cg.time; - p->alpha = 1.0; - p->alphavel = 0; - p->roll = 0; - - p->pshader = pshader; - - p->endtime = cg.time + duration; - - p->startfade = p->endtime; - - p->width = 1; - p->height = 3; - - p->endheight = 3; - p->endwidth = 1; - - p->type = P_SMOKE; - - VectorCopy(cent->currentState.origin, p->org ); - - p->vel[0] = (cent->currentState.origin2[0] * (16 * ratio)); - p->vel[1] = (cent->currentState.origin2[1] * (16 * ratio)); - p->vel[2] = (cent->currentState.origin2[2]); - - p->snum = 1.0f; - - VectorClear( p->accel ); - - p->accel[2] = -20; - - p->rotate = qfalse; - - p->roll = rand()%179; - - p->alpha = 0.75; - -} - - -void CG_Particle_OilSlick (qhandle_t pshader, centity_t *cent) -{ - cparticle_t *p; - - if (!pshader) - CG_Printf ("CG_Particle_OilSlick == ZERO!\n"); - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - p->time = cg.time; - - if (cent->currentState.angles2[2]) - p->endtime = cg.time + cent->currentState.angles2[2]; - else - p->endtime = cg.time + 60000; - - p->startfade = p->endtime; - - p->alpha = 1.0; - p->alphavel = 0; - p->roll = 0; - - p->pshader = pshader; - - if (cent->currentState.angles2[0] || cent->currentState.angles2[1]) - { - p->width = cent->currentState.angles2[0]; - p->height = cent->currentState.angles2[0]; - - p->endheight = cent->currentState.angles2[1]; - p->endwidth = cent->currentState.angles2[1]; - } - else - { - p->width = 8; - p->height = 8; - - p->endheight = 16; - p->endwidth = 16; - } - - p->type = P_FLAT_SCALEUP; - - p->snum = 1.0; - - VectorCopy(cent->currentState.origin, p->org ); - - p->org[2]+= 0.55 + (crandom() * 0.5); - - p->vel[0] = 0; - p->vel[1] = 0; - p->vel[2] = 0; - VectorClear( p->accel ); - - p->rotate = qfalse; - - p->roll = rand()%179; - - p->alpha = 0.75; - -} - -void CG_OilSlickRemove (centity_t *cent) -{ - cparticle_t *p, *next; - int id; - - id = 1.0f; - - if (!id) - CG_Printf ("CG_OilSlickRevove NULL id\n"); - - for (p=active_particles ; p ; p=next) - { - next = p->next; - - if (p->type == P_FLAT_SCALEUP) - { - if (p->snum == id) - { - p->endtime = cg.time + 100; - p->startfade = p->endtime; - p->type = P_FLAT_SCALEUP_FADE; - - } - } - - } -} - -qboolean ValidBloodPool (vec3_t start) -{ -#define EXTRUDE_DIST 0.5 - - vec3_t angles; - vec3_t right, up; - vec3_t this_pos, x_pos, center_pos, end_pos; - float x, y; - float fwidth, fheight; - trace_t trace; - vec3_t normal; - - fwidth = 16; - fheight = 16; - - VectorSet (normal, 0, 0, 1); - - vectoangles (normal, angles); - AngleVectors (angles, NULL, right, up); - - VectorMA (start, EXTRUDE_DIST, normal, center_pos); - - for (x= -fwidth/2; xendpos, start); - legit = ValidBloodPool (start); - - if (!legit) - return; - - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - p->time = cg.time; - - p->endtime = cg.time + 3000; - p->startfade = p->endtime; - - p->alpha = 1.0; - p->alphavel = 0; - p->roll = 0; - - p->pshader = pshader; - - rndSize = 0.4 + random()*0.6; - - p->width = 8*rndSize; - p->height = 8*rndSize; - - p->endheight = 16*rndSize; - p->endwidth = 16*rndSize; - - p->type = P_FLAT_SCALEUP; - - VectorCopy(start, p->org ); - - p->vel[0] = 0; - p->vel[1] = 0; - p->vel[2] = 0; - VectorClear( p->accel ); - - p->rotate = qfalse; - - p->roll = rand()%179; - - p->alpha = 0.75; - - p->color = BLOODRED; -} - -#define NORMALSIZE 16 -#define LARGESIZE 32 - -void CG_ParticleBloodCloud (centity_t *cent, vec3_t origin, vec3_t dir) -{ - float length; - float dist; - float crittersize; - vec3_t angles, forward; - vec3_t point; - cparticle_t *p; - int i; - - dist = 0; - - length = VectorLength (dir); - vectoangles (dir, angles); - AngleVectors (angles, forward, NULL, NULL); - - crittersize = LARGESIZE; - - if (length) - dist = length / crittersize; - - if (dist < 1) - dist = 1; - - VectorCopy (origin, point); - - for (i=0; inext; - p->next = active_particles; - active_particles = p; - - p->time = cg.time; - p->alpha = 1.0; - p->alphavel = 0; - p->roll = 0; - - p->pshader = cgs.media.smokePuffShader; - - p->endtime = cg.time + 350 + (crandom() * 100); - - p->startfade = cg.time; - - p->width = LARGESIZE; - p->height = LARGESIZE; - p->endheight = LARGESIZE; - p->endwidth = LARGESIZE; - - p->type = P_SMOKE; - - VectorCopy( origin, p->org ); - - p->vel[0] = 0; - p->vel[1] = 0; - p->vel[2] = -1; - - VectorClear( p->accel ); - - p->rotate = qfalse; - - p->roll = rand()%179; - - p->color = BLOODRED; - - p->alpha = 0.75; - - } - - -} - -void CG_ParticleSparks (vec3_t org, vec3_t vel, int duration, float x, float y, float speed) -{ - cparticle_t *p; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - p->time = cg.time; - - p->endtime = cg.time + duration; - p->startfade = cg.time + duration/2; - - p->color = EMISIVEFADE; - p->alpha = 0.4f; - p->alphavel = 0; - - p->height = 0.5; - p->width = 0.5; - p->endheight = 0.5; - p->endwidth = 0.5; - - p->pshader = cgs.media.tracerShader; - - p->type = P_SMOKE; - - VectorCopy(org, p->org); - - p->org[0] += (crandom() * x); - p->org[1] += (crandom() * y); - - p->vel[0] = vel[0]; - p->vel[1] = vel[1]; - p->vel[2] = vel[2]; - - p->accel[0] = p->accel[1] = p->accel[2] = 0; - - p->vel[0] += (crandom() * 4); - p->vel[1] += (crandom() * 4); - p->vel[2] += (20 + (crandom() * 10)) * speed; - - p->accel[0] = crandom () * 4; - p->accel[1] = crandom () * 4; - -} - -void CG_ParticleDust (centity_t *cent, vec3_t origin, vec3_t dir) -{ - float length; - float dist; - float crittersize; - vec3_t angles, forward; - vec3_t point; - cparticle_t *p; - int i; - - dist = 0; - - VectorNegate (dir, dir); - length = VectorLength (dir); - vectoangles (dir, angles); - AngleVectors (angles, forward, NULL, NULL); - - crittersize = LARGESIZE; - - if (length) - dist = length / crittersize; - - if (dist < 1) - dist = 1; - - VectorCopy (origin, point); - - for (i=0; inext; - p->next = active_particles; - active_particles = p; - - p->time = cg.time; - p->alpha = 5.0; - p->alphavel = 0; - p->roll = 0; - - p->pshader = cgs.media.smokePuffShader; - - // RF, stay around for long enough to expand and dissipate naturally - if (length) - p->endtime = cg.time + 4500 + (crandom() * 3500); - else - p->endtime = cg.time + 750 + (crandom() * 500); - - p->startfade = cg.time; - - p->width = LARGESIZE; - p->height = LARGESIZE; - - // RF, expand while falling - p->endheight = LARGESIZE*3.0; - p->endwidth = LARGESIZE*3.0; - - if (!length) - { - p->width *= 0.2f; - p->height *= 0.2f; - - p->endheight = NORMALSIZE; - p->endwidth = NORMALSIZE; - } - - p->type = P_SMOKE; - - VectorCopy( point, p->org ); - - p->vel[0] = crandom()*6; - p->vel[1] = crandom()*6; - p->vel[2] = random()*20; - - // RF, add some gravity/randomness - p->accel[0] = crandom()*3; - p->accel[1] = crandom()*3; - p->accel[2] = -PARTICLE_GRAVITY*0.4; - - VectorClear( p->accel ); - - p->rotate = qfalse; - - p->roll = rand()%179; - - p->alpha = 0.75; - - } - - -} - -void CG_ParticleMisc (qhandle_t pshader, vec3_t origin, int size, int duration, float alpha) -{ - cparticle_t *p; - - if (!pshader) - CG_Printf ("CG_ParticleImpactSmokePuff pshader == ZERO!\n"); - - if (!free_particles) - return; - - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - p->time = cg.time; - p->alpha = 1.0; - p->alphavel = 0; - p->roll = rand()%179; - - p->pshader = pshader; - - if (duration > 0) - p->endtime = cg.time + duration; - else - p->endtime = duration; - - p->startfade = cg.time; - - p->width = size; - p->height = size; - - p->endheight = size; - p->endwidth = size; - - p->type = P_SPRITE; - - VectorCopy( origin, p->org ); - - p->rotate = qfalse; -} - diff --git a/source/cgame/cg_particles.c b/source/cgame/cg_particles.c index d9c3e7e..5aa6b4b 100644 --- a/source/cgame/cg_particles.c +++ b/source/cgame/cg_particles.c @@ -133,6 +133,10 @@ vec3_t rforward, rright, rup; float oldtime; +#define NORMALSIZE 16 +#define LARGESIZE 32 + + /* =============== CL_ClearParticles @@ -202,9 +206,13 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) { p->time = cg.time; VectorCopy (org, p->org); // Ridah, fixes rare snow flakes that flicker on the ground - - p->org[2] = ( p->start + crandom () * 4 ); + // BFP - Stop flickering, before: ( p->start + crandom () * 4 ) + p->org[2] = ( p->start ); + + // BFP - Make move less + p->vel[0] *= 0.9; + p->vel[1] *= 0.9; if (p->type == P_BUBBLE_TURBULENT) { @@ -448,9 +456,6 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) else invratio = 1 * p->alpha; - if ( cgs.glconfig.hardwareType == GLHW_RAGEPRO ) - invratio = 1; - if (invratio > 1) invratio = 1; @@ -553,9 +558,6 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) alpha = p->alpha; - if ( cgs.glconfig.hardwareType == GLHW_RAGEPRO ) - alpha = 1; - if (p->roll) { vectoangles( cg.refdef.viewaxis[0], rotate_ang ); @@ -873,7 +875,9 @@ void CG_AddParticles (void) continue; } - if (p->type == P_SMOKE || p->type == P_ANIM || p->type == P_BLEED || p->type == P_SMOKE_IMPACT) + if (p->type == P_SMOKE || p->type == P_ANIM || p->type == P_BLEED || p->type == P_SMOKE_IMPACT + || p->type == P_WEATHER_FLURRY || p->type == P_FLAT_SCALEUP_FADE + || p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) // BFP - Add P_BUBBLE types to remove particles { if (cg.time > p->endtime) { @@ -882,39 +886,8 @@ void CG_AddParticles (void) p->type = 0; p->color = 0; p->alpha = 0; - continue; } - - } - - if (p->type == P_WEATHER_FLURRY) - { - if (cg.time > p->endtime) - { - p->next = free_particles; - free_particles = p; - p->type = 0; - p->color = 0; - p->alpha = 0; - - continue; - } - } - - - if (p->type == P_FLAT_SCALEUP_FADE) - { - if (cg.time > p->endtime) - { - p->next = free_particles; - free_particles = p; - p->type = 0; - p->color = 0; - p->alpha = 0; - continue; - } - } if ((p->type == P_BAT || p->type == P_SPRITE) && p->endtime < 0) { @@ -956,11 +929,6 @@ void CG_AddParticles (void) active_particles = active; } -/* -====================== -CG_AddParticles -====================== -*/ void CG_ParticleSnowFlurry (qhandle_t pshader, centity_t *cent) { cparticle_t *p; @@ -1086,13 +1054,14 @@ void CG_ParticleSnow (qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb } -void CG_ParticleBubble (qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb, float range, int snum) +void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb, float range, int snum) { cparticle_t *p; float randsize; - if (!pshader) - CG_Printf ("CG_ParticleSnow pshader == ZERO!\n"); + // if (!pshader) CG_Printf ("CG_ParticleSnow pshader == ZERO!\n"); + + // BFP - TODO: Make bubbles appear by moving one at a time without being timescaled if (!free_particles) return; @@ -1101,19 +1070,22 @@ void CG_ParticleBubble (qhandle_t pshader, vec3_t origin, vec3_t origin2, int tu p->next = active_particles; active_particles = p; p->time = cg.time; + + // BFP - Add end time to remove particles, if there's no end time the particles will remain there + p->endtime = cg.time + 1000; + p->startfade = cg.time + 200; + p->color = 0; p->alpha = 0.40f; p->alphavel = 0; - p->start = origin[2]; - p->end = origin2[2]; + // BFP - Apply to player's origin + p->start = cent->currentState.origin[2]; + p->end = cent->currentState.origin2[2]; p->pshader = pshader; - randsize = 1 + (crandom() * 0.5); - - p->height = randsize; - p->width = randsize; + randsize = 2 + (crandom() * 0.5); - p->vel[2] = 50 + ( crandom() * 10 ); + p->height = p->width = randsize; if (turb) { @@ -1124,16 +1096,41 @@ void CG_ParticleBubble (qhandle_t pshader, vec3_t origin, vec3_t origin2, int tu { p->type = P_BUBBLE; } - - VectorCopy(origin, p->org); - p->org[0] = p->org[0] + ( crandom() * range); - p->org[1] = p->org[1] + ( crandom() * range); - p->org[2] = p->org[2] + ( crandom() * (p->start - p->end)); + VectorCopy(origin, p->org); - p->vel[0] = p->vel[1] = 0; - - p->accel[0] = p->accel[1] = p->accel[2] = 0; + p->org[0] += (crandom() * range); + p->org[1] += (crandom() * range); + p->org[2] += (crandom() * (p->start - p->end)); + + if ( ( cent->currentState.eFlags & EF_AURA ) + && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE ) { + VectorSet( p->vel, + (rand() % 801) - 400, + (rand() % 801) - 400, + 20 ); + + // dispersion + VectorSet( p->accel, + crandom() * 20, + crandom() * 20, + 1400 ); + } else { + // BFP - Apply end time to remove particles in that case, if there's no end time the particles will remain there + p->endtime = cg.time + 700; + p->startfade = cg.time + 200; + + VectorSet( p->vel, + (rand() % 401) - 200, + (rand() % 401) - 200, + 20 ); + + // dispersion + VectorSet( p->accel, + crandom() * 20, + crandom() * 20, + 300 ); + } if (turb) { @@ -1144,7 +1141,6 @@ void CG_ParticleBubble (qhandle_t pshader, vec3_t origin, vec3_t origin2, int tu // Rafael snow pvs check p->snum = snum; p->link = qtrue; - } void CG_ParticleSmoke (qhandle_t pshader, centity_t *cent) @@ -1252,7 +1248,7 @@ void CG_ParticleExplosion (char *animStr, vec3_t origin, vec3_t vel, int duratio // find the animation string for (anim=0; shaderAnimNames[anim]; anim++) { - if (!stricmp( animStr, shaderAnimNames[anim] )) + if (!Q_stricmp( animStr, shaderAnimNames[anim] )) break; } if (!shaderAnimNames[anim]) { @@ -1305,15 +1301,12 @@ void CG_AddParticleShrapnel (localEntity_t *le) int CG_NewParticleArea (int num) { // const char *str; - char *str; - char *token; + char *str, *token; int type; vec3_t origin, origin2; int i; float range = 0; - int turb; - int numparticles; - int snum; + int turb, numparticles, snum; str = (char *) CG_ConfigString (num); if (!str[0]) @@ -1323,23 +1316,16 @@ int CG_NewParticleArea (int num) token = COM_Parse (&str); type = atoi (token); - if (type == 1) - range = 128; - else if (type == 2) - range = 64; - else if (type == 3) - range = 32; - else if (type == 0) - range = 256; - else if (type == 4) - range = 8; - else if (type == 5) - range = 16; - else if (type == 6) - range = 32; - else if (type == 7) - range = 64; - + switch( type ) { + case 4: range = 8; break; + case 5: range = 16; break; + case 3: + case 6: range = 32; break; + case 2: + case 7: range = 64; break; + case 1: range = 128; break; + case 0: range = 256; break; + } for (i=0; i<3; i++) { @@ -1364,9 +1350,9 @@ int CG_NewParticleArea (int num) for (i=0; i= 4) + /*if (type >= 4) CG_ParticleBubble (cgs.media.waterBubbleShader, origin, origin2, turb, range, snum); - else + else*/ CG_ParticleSnow (cgs.media.waterBubbleShader, origin, origin2, turb, range, snum); } @@ -1398,6 +1384,56 @@ void CG_SnowLink (centity_t *cent, qboolean particleOn) } } +// BFP - Particle for dash smoke when using ki boost and moving in the ground +void CG_ParticleDashSmoke (centity_t *cent, qhandle_t pshader, vec3_t origin) +{ + cparticle_t *p; + + // if (!pshader) CG_Printf ("CG_ParticleDashSmoke pshader == ZERO!\n"); + + if (!free_particles) + return; + + // BFP - TODO: Make smoke appear by moving one at a time without being timescaled + + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->time = cg.time; + + p->alpha = 0.4; + p->alphavel = 0; + + p->pshader = pshader; + p->start = cent->currentState.origin[2]; + p->end = cent->currentState.origin2[2]; + + p->endtime = cg.time + 250; + p->startfade = cg.time + 100; + + p->height = p->width = 25; + + p->endheight = p->height * 2; + p->endwidth = p->width * 2; + + p->type = P_SMOKE; + + VectorCopy( origin, p->org ); + VectorSet( p->vel, + (rand() % 401) - 200, + (rand() % 401) - 200, + 20 ); + + // dispersion + VectorSet( p->accel, + crandom() * 20, + crandom() * 20, + 1400 ); +} + +#if 0 void CG_ParticleImpactSmokePuff (qhandle_t pshader, vec3_t origin) { cparticle_t *p; @@ -1752,9 +1788,6 @@ void CG_BloodPool (localEntity_t *le, qhandle_t pshader, trace_t *tr) p->color = BLOODRED; } -#define NORMALSIZE 16 -#define LARGESIZE 32 - void CG_ParticleBloodCloud (centity_t *cent, vec3_t origin, vec3_t dir) { float length; @@ -1831,6 +1864,7 @@ void CG_ParticleBloodCloud (centity_t *cent, vec3_t origin, vec3_t dir) } +#endif void CG_ParticleSparks (vec3_t org, vec3_t vel, int duration, float x, float y, float speed) { @@ -1980,8 +2014,7 @@ void CG_ParticleMisc (qhandle_t pshader, vec3_t origin, int size, int duration, { cparticle_t *p; - if (!pshader) - CG_Printf ("CG_ParticleImpactSmokePuff pshader == ZERO!\n"); + // if (!pshader) CG_Printf ("CG_ParticleImpactSmokePuff pshader == ZERO!\n"); if (!free_particles) return; diff --git a/source/cgame/cgame.bat b/source/cgame/cgame.bat index 18a79ba..343f717 100644 --- a/source/cgame/cgame.bat +++ b/source/cgame/cgame.bat @@ -40,6 +40,8 @@ set cc=..\..\..\tools\bin\lcc.exe -DQ3_VM -S -Wf-target=bytecode -Wf-g -I%src%\c @if errorlevel 1 goto quit %cc% %src%/cgame/cg_marks.c @if errorlevel 1 goto quit +%cc% %src%/cgame/cg_particles.c +@if errorlevel 1 goto quit %cc% %src%/cgame/cg_players.c @if errorlevel 1 goto quit %cc% %src%/cgame/cg_playerstate.c diff --git a/source/cgame/cgame.q3asm b/source/cgame/cgame.q3asm index c44b804..8e69ed5 100644 --- a/source/cgame/cgame.q3asm +++ b/source/cgame/cgame.q3asm @@ -10,6 +10,7 @@ cg_event cg_info cg_localents cg_marks +cg_particles cg_players cg_playerstate cg_predict From 09b4161495c4b7188b5b19ce0d30f18548018583 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sat, 20 Jan 2024 19:22:16 +0100 Subject: [PATCH 023/374] Remove cg_particles.c from unused source files list, improve About the repository section and center BFP team staff credits --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a0b7e9f..cff493d 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ Click here to see the [Old PyroFragger dev journal (Markdown edition)](docs/pyro ### About the repository We're making a replica of the lost source code.
-The highest priority goal is copying and recreating completely BFP game logical structure.
+The highest priority goal is to copy and recreate the complete logical structure of the BFP game. It would be a game SDK that'll provide a structured and standardized way to modify the mod.
Any fixes, improvements and contributions are welcome. But we can't accept secondary things and other stuff that don't reach the goals. ### References and clues to know how should be the game @@ -372,8 +372,8 @@ The information in the map file can be useful for debugging and performance anal - cg_cvar.h - g_cvar.h -- ui_cvar.h - ui_bfpoptions.c +- ui_cvar.h - ui_mem.c - ui_mp3decoder.c - ui_mp3decoder.h @@ -389,7 +389,6 @@ The information in the map file can be useful for debugging and performance anal #### Unused source code files and unavailable in the build tools: -- cg_particles.c - ui_rankings.c - ui_rankstatus.c - ui_signup.c @@ -416,6 +415,8 @@ The Bid For Power team may provide sufficient security against any claims or imp Bid For Power is made by these staff members. We don't own materials such as art designs, maps and character models from their assets. +
+ #### Bid For Power Staff Members Ansel
@@ -462,3 +463,4 @@ Project Lead, Lead Programmer
::Additional Assistance::
Mooky, Perfect Chaos, Dakota, Bardock, DethAyngel, Ebola, Badhead, $onik, Gigatron, Timex & Nat. +
From c461dfdbd9a6134a2d0befca657d62acc1e65ea8 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sat, 20 Jan 2024 23:55:15 +0100 Subject: [PATCH 024/374] cgame: Apply smooth movements on torso angles, don't force visually the legs of the other players, implement correctly small own aura and disable drown sound name so there's no drowning in BFP --- source/cgame/cg_players.c | 41 ++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index 0e72f91..a456cca 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -34,7 +34,7 @@ char *cg_customSoundNames[MAX_CUSTOM_SOUNDS] = { "*pain100_1.wav", "*falling1.wav", "*gasp.wav", - "*drown.wav", + // "*drown.wav", // BFP - No drowning "*fall1.wav", "*taunt.wav" }; @@ -1244,8 +1244,7 @@ static void CG_PlayerAnimation( centity_t *cent, int *legsOld, int *legs, float // if ( cent->currentState.powerups & ( 1 << PW_HASTE ) ) { // BFP - When using ki boost use the following speed as haste powerup - if ( clientNum == cg.snap->ps.clientNum - && ( cent->currentState.eFlags & EF_AURA ) + if ( ( cent->currentState.eFlags & EF_AURA ) && ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_RUN || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_BACK ) ) { speedScale = 1.5; // when using ki boost @@ -1461,7 +1460,7 @@ static void CG_PlayerAngles( centity_t *cent, vec3_t legs[3], vec3_t torso[3], v // --------- roll ------------- - // BFP - TODO: Make the forward and backwards movements smooth + // BFP - TODO: Make forward and backwards movements smooth when starting to move // lean towards the direction of travel VectorCopy( cent->currentState.pos.trDelta, velocity ); @@ -1470,7 +1469,11 @@ static void CG_PlayerAngles( centity_t *cent, vec3_t legs[3], vec3_t torso[3], v vec3_t axis[3]; float side; - speed *= 0.03f; // BFP - adjust legs speed, before 0.05f + // BFP - Speed handling when moving too much the angles + if ( speed <= -480.0f ) speed = -480.0f; + if ( speed >= 480.0f ) speed = 480.0f; + + speed *= 0.03f; // BFP - Adjust speed when rotate the angles (not a starting velocity), before: 0.05f AnglesToAxis( legsAngles, axis ); side = speed * DotProduct( velocity, axis[1] ); @@ -1478,8 +1481,15 @@ static void CG_PlayerAngles( centity_t *cent, vec3_t legs[3], vec3_t torso[3], v side = speed * DotProduct( velocity, axis[0] ); legsAngles[PITCH] += side; + + // BFP - Make the torso move the pitch angle a bit + AnglesToAxis( torsoAngles, axis ); + side = speed * DotProduct( velocity, axis[0] ); + torsoAngles[PITCH] += side; } + // BFP - Don't make every player forced to see this way with their legs to the others +#if 0 // clientNum = cent->currentState.clientNum; if ( clientNum >= 0 && clientNum < MAX_CLIENTS ) { @@ -1490,6 +1500,7 @@ static void CG_PlayerAngles( centity_t *cent, vec3_t legs[3], vec3_t torso[3], v legsAngles[ROLL] = 0.0f; } } +#endif // pain twitch CG_AddPainTwitch( cent, torsoAngles ); @@ -1537,7 +1548,7 @@ static void CG_HasteTrail( centity_t *cent ) { origin[2] -= 16; smoke = CG_SmokePuff( origin, vec3_origin, - 70, // BFP - TODO: Before 8, sizes between 50 ~ 70 + 8, 1, 1, 1, 1, 500, cg.time, @@ -2008,7 +2019,6 @@ Also called by CG_Missile for quad rockets, but nobody can tell... */ void CG_AddRefEntityWithPowerups( refEntity_t *ent, entityState_t *state, int team ) { - if ( state->powerups & ( 1 << PW_INVIS ) ) { ent->customShader = cgs.media.invisShader; trap_R_AddRefEntityToScene( ent ); @@ -2369,14 +2379,17 @@ void CG_Player( centity_t *cent ) { CG_PositionRotatedEntityOnTag( &aura, &legs, ci->legsModel, "tag_torso" ); CG_PositionRotatedEntityOnTag( &aura2, &legs, ci->legsModel, "tag_torso" ); - // Add aura - if ( cg_polygonAura.integer > 0 && cg_lightweightAuras.integer <= 0 && cg_smallOwnAura.integer <= 0 ) { - trap_R_AddRefEntityToScene( &aura ); - } + // BFP - Small own aura only can be shown to the one who enables it for themself, not everyone + if ( clientNum != cg.snap->ps.clientNum || cg_smallOwnAura.integer <= 0 ) { + // Add aura + if ( cg_polygonAura.integer > 0 && cg_lightweightAuras.integer <= 0 ) { + trap_R_AddRefEntityToScene( &aura ); + } - // Add secondary aura to make look cooler, a bit bigger than the other - if ( cg_polygonAura.integer > 0 && cg_highPolyAura.integer > 0 && cg_lightweightAuras.integer <= 0 && cg_smallOwnAura.integer <= 0 ) { - trap_R_AddRefEntityToScene( &aura2 ); + // Add secondary aura to make look cooler, a bit bigger than the other + if ( cg_polygonAura.integer > 0 && cg_highPolyAura.integer > 0 && cg_lightweightAuras.integer <= 0 ) { + trap_R_AddRefEntityToScene( &aura2 ); + } } } From 2b48d91bf2dda45eaf29f5ef7d93615fc29cc66d Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sat, 20 Jan 2024 23:58:59 +0100 Subject: [PATCH 025/374] cgame: Apply bubble and dash smoke particles when entering under water, using ki boost or ki charge statuses and for projectile type weapons --- source/cgame/cg_event.c | 12 ++++++++ source/cgame/cg_players.c | 65 +++++++++++++++++++++++++++++++-------- source/cgame/cg_weapons.c | 9 +++++- 3 files changed, 73 insertions(+), 13 deletions(-) diff --git a/source/cgame/cg_event.c b/source/cgame/cg_event.c index 82821d4..b43b07c 100644 --- a/source/cgame/cg_event.c +++ b/source/cgame/cg_event.c @@ -584,6 +584,18 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { case EV_WATER_UNDER: DEBUGNAME("EV_WATER_UNDER"); trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.watrUnSound ); + // BFP - Bubble and splash particles when entering under water + { + // BFP - TODO: Splash particles (that appears bubbles outside water but bouncing once) + vec3_t end = {0, 0, 1}; + + // Blub, blub, blub... + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 0, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 0, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 0, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 0, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 0, 20, 0 ); + } break; case EV_WATER_CLEAR: DEBUGNAME("EV_WATER_CLEAR"); diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index a456cca..56636c1 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -1521,10 +1521,13 @@ static void CG_PlayerAngles( centity_t *cent, vec3_t legs[3], vec3_t torso[3], v CG_HasteTrail =============== */ -static void CG_HasteTrail( centity_t *cent ) { +static void CG_HasteTrail( centity_t *cent, vec3_t endPos ) { // BFP - Second parameter added for smoke particles + // BFP - No smoke puff effect +#if 0 localEntity_t *smoke; vec3_t origin; int anim; +#endif if ( cent->trailTime > cg.time ) { return; @@ -1537,13 +1540,18 @@ static void CG_HasteTrail( centity_t *cent ) { } #endif - cent->trailTime += 50; // BFP - TODO: Just a test (before 100) + cent->trailTime += 100; if ( cent->trailTime < cg.time ) { cent->trailTime = cg.time; } - // BFP - TODO: Make the smoke move up (always) and move a bit on the left or right (randomly) + // BFP - Apply dash smoke particle for the trail, if the function were used directly, it would generate too many particles than we expected + CG_ParticleDashSmoke( cent, cgs.media.hastePuffShader, endPos ); + CG_ParticleDashSmoke( cent, cgs.media.hastePuffShader, endPos ); + CG_ParticleDashSmoke( cent, cgs.media.hastePuffShader, endPos ); + // BFP - No smoke puff effect +#if 0 VectorCopy( cent->lerpOrigin, origin ); origin[2] -= 16; @@ -1558,6 +1566,7 @@ static void CG_HasteTrail( centity_t *cent ) { // use the optimized local entity add smoke->leType = LE_SCALE_FADE; +#endif } /* @@ -1886,19 +1895,16 @@ static qboolean CG_PlayerShadow( centity_t *cent, float *shadowPlane ) { *shadowPlane = trace.endpos[2] + 1; - // BFP - TODO: Only show smoke where the shadow is and make one smoke of each moving to the air, - // disappearing randomly according to time, making bigger according the size like BFP does - // CG_SmokePuff will help you to find out how to do - - // BFP - Smoke trail when using ki boost on the ground + // BFP - Dash smoke particles when using ki boost on the ground contents = CG_PointContents( trace.endpos, -1 ); if ( ( cent->currentState.eFlags & EF_AURA ) - && !( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) - && ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_RUN + && !( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) + && ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_RUN || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_BACK || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYA - || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYB ) ) { - CG_HasteTrail( cent ); + || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYB ) + && trace.fraction <= 0.70f ) { + CG_HasteTrail( cent, trace.endpos ); } if ( cg_shadows.integer != 1 ) { // no mark for stencil or projection shadows @@ -2327,6 +2333,41 @@ void CG_Player( centity_t *cent ) { } if ( cent->currentState.eFlags & EF_AURA ) { + // BFP - TODO: Create a new function "CG_KiTrail" only when moving to draw ki trail and add the cvar for the length + + // BFP - Traces for bubble particles only when moving in the water and charging + int sourceContentType, destContentType; + vec3_t start; + + sourceContentType = trap_CM_PointContents( start, 0 ); + destContentType = trap_CM_PointContents( cent->lerpOrigin, 0 ); + + // spawning bubble particles + if ( destContentType & CONTENTS_WATER ) { + trace_t trace; + vec3_t bubbleOrigin; + + VectorCopy( legs.origin, bubbleOrigin ); + trap_CM_BoxTrace( &trace, start, bubbleOrigin, NULL, NULL, 0, CONTENTS_WATER ); + + bubbleOrigin[2] += -15; // put the origin below the character's feet + + if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYA + || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYB ) { + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); + } else if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE ) { + bubbleOrigin[2] += -10; // put the origin a little below + + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); + } + } + // Apply the render type aura.reType = aura2.reType = RT_MODEL; diff --git a/source/cgame/cg_weapons.c b/source/cgame/cg_weapons.c index 60986b9..c40b9b3 100644 --- a/source/cgame/cg_weapons.c +++ b/source/cgame/cg_weapons.c @@ -327,7 +327,11 @@ static void CG_RocketTrail( centity_t *ent, const weaponInfo_t *wi ) { if ( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) { if ( contents & lastContents & CONTENTS_WATER ) { - CG_BubbleTrail( lastPos, origin, 8 ); + // BFP - Apply particle bubble effect in that case + CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 0, 20, 0 ); + CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 0, 20, 0 ); + CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 0, 20, 0 ); + // CG_BubbleTrail( lastPos, origin, 8 ); } return; } @@ -2033,6 +2037,8 @@ Renders bullet effects. ====================== */ void CG_Bullet( vec3_t end, int sourceEntityNum, vec3_t normal, qboolean flesh, int fleshEntityNum ) { + // BFP - No water particles in BFP by firing a kind of ki-type bullet +#if 0 trace_t trace; int sourceContentType, destContentType; vec3_t start; @@ -2065,6 +2071,7 @@ void CG_Bullet( vec3_t end, int sourceEntityNum, vec3_t normal, qboolean flesh, } } } +#endif // impact splash and mark if ( flesh ) { From 7b3ada83646fa023bcca5994c068649e55756cf9 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 22 Jan 2024 23:53:12 +0100 Subject: [PATCH 026/374] cgame: Make particles non-timescaled and adjusted to be similar to BFP, plus some particles code tweaks --- source/cgame/cg_particles.c | 186 ++++++++++++++++-------------------- 1 file changed, 84 insertions(+), 102 deletions(-) diff --git a/source/cgame/cg_particles.c b/source/cgame/cg_particles.c index 5aa6b4b..1a25155 100644 --- a/source/cgame/cg_particles.c +++ b/source/cgame/cg_particles.c @@ -133,6 +133,9 @@ vec3_t rforward, rright, rup; float oldtime; +// BFP - NOTE: Particles use non-timescaled, before it was timescaled by game using cg.time +int timenonscaled; + #define NORMALSIZE 16 #define LARGESIZE 32 @@ -204,29 +207,28 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) { if (org[2] > p->end) { - p->time = cg.time; + p->time = timenonscaled; VectorCopy (org, p->org); // Ridah, fixes rare snow flakes that flicker on the ground - // BFP - Stop flickering, before: ( p->start + crandom () * 4 ) + // BFP - Stop shivering, before: ( p->start + crandom () * 4 ) p->org[2] = ( p->start ); // BFP - Make move less - p->vel[0] *= 0.9; - p->vel[1] *= 0.9; - - if (p->type == P_BUBBLE_TURBULENT) - { - p->vel[0] = crandom() * 4; - p->vel[1] = crandom() * 4; + if (p->type == P_BUBBLE_TURBULENT) { + p->vel[0] *= 0.95; + p->vel[1] *= 0.95; + } + else { + p->vel[0] *= 0.9; + p->vel[1] *= 0.9; } - } } else { if (org[2] < p->end) { - p->time = cg.time; + p->time = timenonscaled; VectorCopy (org, p->org); // Ridah, fixes rare snow flakes that flicker on the ground while (p->org[2] < p->end) @@ -840,6 +842,8 @@ void CG_AddParticles (void) int type; vec3_t rotate_ang; + timenonscaled = trap_Milliseconds(); // BFP - That's what the variable makes non-timescaled + if (!initparticles) CG_ClearParticles (); @@ -854,24 +858,22 @@ void CG_AddParticles (void) oldtime = cg.time; - active = NULL; - tail = NULL; + active = tail = NULL; for (p=active_particles ; p ; p=next) { - next = p->next; - time = (cg.time - p->time)*0.001; + time = (timenonscaled - p->time)*0.001; - alpha = p->alpha + time*p->alphavel; - if (alpha <= 0) + // BFP - Make alpha timescaled for smoke-like particles + alpha = p->alpha + time*p->alphavel*(cg_timescale.value <= 0.1 ? 0.1 : cg_timescale.value); + if (p->alphavel < 0.0f) p->alpha = alpha; // BFP - Alpha fading out + if (p->alpha <= 0 && cg.frametime > 0.0f) // BFP - If paused, don't fade out { // faded out p->next = free_particles; free_particles = p; - p->type = 0; - p->color = 0; - p->alpha = 0; + p->type = p->color = p->alpha = 0; continue; } @@ -879,13 +881,11 @@ void CG_AddParticles (void) || p->type == P_WEATHER_FLURRY || p->type == P_FLAT_SCALEUP_FADE || p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) // BFP - Add P_BUBBLE types to remove particles { - if (cg.time > p->endtime) + if (timenonscaled > p->endtime) { p->next = free_particles; free_particles = p; - p->type = 0; - p->color = 0; - p->alpha = 0; + p->type = p->color = p->alpha = 0; continue; } } @@ -895,9 +895,7 @@ void CG_AddParticles (void) CG_AddParticleToScene (p, p->org, alpha); p->next = free_particles; free_particles = p; - p->type = 0; - p->color = 0; - p->alpha = 0; + p->type = p->color = p->alpha = 0; continue; } @@ -943,7 +941,7 @@ void CG_ParticleSnowFlurry (qhandle_t pshader, centity_t *cent) free_particles = p->next; p->next = active_particles; active_particles = p; - p->time = cg.time; + p->time = timenonscaled; p->color = 0; p->alpha = 0.90f; p->alphavel = 0; @@ -951,7 +949,7 @@ void CG_ParticleSnowFlurry (qhandle_t pshader, centity_t *cent) p->start = cent->currentState.origin2[0]; p->end = cent->currentState.origin2[1]; - p->endtime = cg.time + cent->currentState.time; + p->endtime = timenonscaled + cent->currentState.time; p->startfade = cg.time + cent->currentState.time2; p->pshader = pshader; @@ -1010,7 +1008,7 @@ void CG_ParticleSnow (qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb free_particles = p->next; p->next = active_particles; active_particles = p; - p->time = cg.time; + p->time = timenonscaled; p->color = 0; p->alpha = 0.40f; p->alphavel = 0; @@ -1061,18 +1059,16 @@ void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_ // if (!pshader) CG_Printf ("CG_ParticleSnow pshader == ZERO!\n"); - // BFP - TODO: Make bubbles appear by moving one at a time without being timescaled - if (!free_particles) return; p = free_particles; free_particles = p->next; p->next = active_particles; active_particles = p; - p->time = cg.time; + p->time = timenonscaled; // BFP - Add end time to remove particles, if there's no end time the particles will remain there - p->endtime = cg.time + 1000; + p->endtime = timenonscaled + 1000; p->startfade = cg.time + 200; p->color = 0; @@ -1083,60 +1079,48 @@ void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_ p->end = cent->currentState.origin2[2]; p->pshader = pshader; - randsize = 2 + (crandom() * 0.5); + randsize = 3 + (crandom() * 0.5); p->height = p->width = randsize; if (turb) { p->type = P_BUBBLE_TURBULENT; - p->vel[2] = 50 * 1.3; - } - else - { - p->type = P_BUBBLE; - } - - VectorCopy(origin, p->org); - - p->org[0] += (crandom() * range); - p->org[1] += (crandom() * range); - p->org[2] += (crandom() * (p->start - p->end)); + // BFP - Apply end time to remove particles in that case, if there's no end time the particles will remain there + p->endtime = timenonscaled + 700; + p->startfade = cg.time + 200; - if ( ( cent->currentState.eFlags & EF_AURA ) - && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE ) { VectorSet( p->vel, - (rand() % 801) - 400, - (rand() % 801) - 400, + (rand() % 401) - 200, + (rand() % 401) - 200, 20 ); // dispersion VectorSet( p->accel, crandom() * 20, crandom() * 20, - 1400 ); - } else { - // BFP - Apply end time to remove particles in that case, if there's no end time the particles will remain there - p->endtime = cg.time + 700; - p->startfade = cg.time + 200; - + 300 ); + } + else + { + p->type = P_BUBBLE; VectorSet( p->vel, - (rand() % 401) - 200, - (rand() % 401) - 200, + (rand() % 801) - 400, + (rand() % 801) - 400, 20 ); // dispersion VectorSet( p->accel, crandom() * 20, crandom() * 20, - 300 ); + 1400 ); } - if (turb) - { - p->vel[0] = crandom() * 4; - p->vel[1] = crandom() * 4; - } + VectorCopy(origin, p->org); + + p->org[0] += (crandom() * range); + p->org[1] += (crandom() * range); + p->org[2] += (crandom() * (p->start - p->end)); // Rafael snow pvs check p->snum = snum; @@ -1159,9 +1143,9 @@ void CG_ParticleSmoke (qhandle_t pshader, centity_t *cent) free_particles = p->next; p->next = active_particles; active_particles = p; - p->time = cg.time; + p->time = timenonscaled; - p->endtime = cg.time + cent->currentState.time; + p->endtime = timenonscaled + cent->currentState.time; p->startfade = cg.time + cent->currentState.time2; p->color = 0; @@ -1202,9 +1186,9 @@ void CG_ParticleBulletDebris (vec3_t org, vec3_t vel, int duration) free_particles = p->next; p->next = active_particles; active_particles = p; - p->time = cg.time; + p->time = timenonscaled; - p->endtime = cg.time + duration; + p->endtime = timenonscaled + duration; p->startfade = cg.time + duration/2; p->color = EMISIVEFADE; @@ -1262,7 +1246,7 @@ void CG_ParticleExplosion (char *animStr, vec3_t origin, vec3_t vel, int duratio free_particles = p->next; p->next = active_particles; active_particles = p; - p->time = cg.time; + p->time = timenonscaled; p->alpha = 1.0; p->alphavel = 0; @@ -1281,7 +1265,7 @@ void CG_ParticleExplosion (char *animStr, vec3_t origin, vec3_t vel, int duratio p->endheight = sizeEnd; p->endwidth = sizeEnd*shaderAnimSTRatio[anim]; - p->endtime = cg.time + duration; + p->endtime = timenonscaled + duration; p->type = P_ANIM; @@ -1394,23 +1378,21 @@ void CG_ParticleDashSmoke (centity_t *cent, qhandle_t pshader, vec3_t origin) if (!free_particles) return; - // BFP - TODO: Make smoke appear by moving one at a time without being timescaled - p = free_particles; free_particles = p->next; p->next = active_particles; active_particles = p; - p->time = cg.time; + p->time = timenonscaled; - p->alpha = 0.4; - p->alphavel = 0; + p->alpha = 0.45; + p->alphavel = -0.1; p->pshader = pshader; p->start = cent->currentState.origin[2]; p->end = cent->currentState.origin2[2]; - p->endtime = cg.time + 250; + p->endtime = timenonscaled + 2000; p->startfade = cg.time + 100; p->height = p->width = 25; @@ -1418,7 +1400,7 @@ void CG_ParticleDashSmoke (centity_t *cent, qhandle_t pshader, vec3_t origin) p->endheight = p->height * 2; p->endwidth = p->width * 2; - p->type = P_SMOKE; + p->type = P_SMOKE_IMPACT; VectorCopy( origin, p->org ); VectorSet( p->vel, @@ -1428,8 +1410,8 @@ void CG_ParticleDashSmoke (centity_t *cent, qhandle_t pshader, vec3_t origin) // dispersion VectorSet( p->accel, - crandom() * 20, - crandom() * 20, + crandom() * 10, + crandom() * 10, 1400 ); } @@ -1447,14 +1429,14 @@ void CG_ParticleImpactSmokePuff (qhandle_t pshader, vec3_t origin) free_particles = p->next; p->next = active_particles; active_particles = p; - p->time = cg.time; + p->time = timenonscaled; p->alpha = 0.25; p->alphavel = 0; p->roll = crandom()*179; p->pshader = pshader; - p->endtime = cg.time + 1000; + p->endtime = timenonscaled + 1000; p->startfade = cg.time + 100; p->width = rand()%4 + 8; @@ -1463,7 +1445,7 @@ void CG_ParticleImpactSmokePuff (qhandle_t pshader, vec3_t origin) p->endheight = p->height *2; p->endwidth = p->width * 2; - p->endtime = cg.time + 500; + p->endtime = timenonscaled + 500; p->type = P_SMOKE_IMPACT; @@ -1487,14 +1469,14 @@ void CG_Particle_Bleed (qhandle_t pshader, vec3_t start, vec3_t dir, int fleshEn free_particles = p->next; p->next = active_particles; active_particles = p; - p->time = cg.time; + p->time = timenonscaled; p->alpha = 1.0; p->alphavel = 0; p->roll = 0; p->pshader = pshader; - p->endtime = cg.time + duration; + p->endtime = timenonscaled + duration; if (fleshEntityNum) p->startfade = cg.time; @@ -1548,14 +1530,14 @@ void CG_Particle_OilParticle (qhandle_t pshader, centity_t *cent) free_particles = p->next; p->next = active_particles; active_particles = p; - p->time = cg.time; + p->time = timenonscaled; p->alpha = 1.0; p->alphavel = 0; p->roll = 0; p->pshader = pshader; - p->endtime = cg.time + duration; + p->endtime = timenonscaled + duration; p->startfade = p->endtime; @@ -1601,12 +1583,12 @@ void CG_Particle_OilSlick (qhandle_t pshader, centity_t *cent) free_particles = p->next; p->next = active_particles; active_particles = p; - p->time = cg.time; + p->time = timenonscaled; if (cent->currentState.angles2[2]) - p->endtime = cg.time + cent->currentState.angles2[2]; + p->endtime = timenonscaled + cent->currentState.angles2[2]; else - p->endtime = cg.time + 60000; + p->endtime = timenonscaled + 60000; p->startfade = p->endtime; @@ -1672,7 +1654,7 @@ void CG_OilSlickRemove (centity_t *cent) { if (p->snum == id) { - p->endtime = cg.time + 100; + p->endtime = timenonscaled + 100; p->startfade = p->endtime; p->type = P_FLAT_SCALEUP_FADE; @@ -1751,9 +1733,9 @@ void CG_BloodPool (localEntity_t *le, qhandle_t pshader, trace_t *tr) free_particles = p->next; p->next = active_particles; active_particles = p; - p->time = cg.time; + p->time = timenonscaled; - p->endtime = cg.time + 3000; + p->endtime = timenonscaled + 3000; p->startfade = p->endtime; p->alpha = 1.0; @@ -1826,14 +1808,14 @@ void CG_ParticleBloodCloud (centity_t *cent, vec3_t origin, vec3_t dir) p->next = active_particles; active_particles = p; - p->time = cg.time; + p->time = timenonscaled; p->alpha = 1.0; p->alphavel = 0; p->roll = 0; p->pshader = cgs.media.smokePuffShader; - p->endtime = cg.time + 350 + (crandom() * 100); + p->endtime = timenonscaled + 350 + (crandom() * 100); p->startfade = cg.time; @@ -1876,9 +1858,9 @@ void CG_ParticleSparks (vec3_t org, vec3_t vel, int duration, float x, float y, free_particles = p->next; p->next = active_particles; active_particles = p; - p->time = cg.time; + p->time = timenonscaled; - p->endtime = cg.time + duration; + p->endtime = timenonscaled + duration; p->startfade = cg.time + duration/2; p->color = EMISIVEFADE; @@ -1953,7 +1935,7 @@ void CG_ParticleDust (centity_t *cent, vec3_t origin, vec3_t dir) p->next = active_particles; active_particles = p; - p->time = cg.time; + p->time = timenonscaled; p->alpha = 5.0; p->alphavel = 0; p->roll = 0; @@ -1962,9 +1944,9 @@ void CG_ParticleDust (centity_t *cent, vec3_t origin, vec3_t dir) // RF, stay around for long enough to expand and dissipate naturally if (length) - p->endtime = cg.time + 4500 + (crandom() * 3500); + p->endtime = timenonscaled + 4500 + (crandom() * 3500); else - p->endtime = cg.time + 750 + (crandom() * 500); + p->endtime = timenonscaled + 750 + (crandom() * 500); p->startfade = cg.time; @@ -2023,7 +2005,7 @@ void CG_ParticleMisc (qhandle_t pshader, vec3_t origin, int size, int duration, free_particles = p->next; p->next = active_particles; active_particles = p; - p->time = cg.time; + p->time = timenonscaled; p->alpha = 1.0; p->alphavel = 0; p->roll = rand()%179; @@ -2031,7 +2013,7 @@ void CG_ParticleMisc (qhandle_t pshader, vec3_t origin, int size, int duration, p->pshader = pshader; if (duration > 0) - p->endtime = cg.time + duration; + p->endtime = timenonscaled + duration; else p->endtime = duration; From 0f843308e9e9a1b1cba656c34975cd165041a52b Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Tue, 23 Jan 2024 00:15:39 +0100 Subject: [PATCH 027/374] cgame: Apply and adjust correctly bubble and dash smoke particles to ki boost and ki charge status, events and projectile type weapons to be similar to BFP --- source/cgame/cg_event.c | 10 +++++----- source/cgame/cg_players.c | 37 ++++++++++++++++++++----------------- source/cgame/cg_weapons.c | 9 +++++---- 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/source/cgame/cg_event.c b/source/cgame/cg_event.c index b43b07c..bcad970 100644 --- a/source/cgame/cg_event.c +++ b/source/cgame/cg_event.c @@ -590,11 +590,11 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { vec3_t end = {0, 0, 1}; // Blub, blub, blub... - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 0, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 0, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 0, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 0, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 0, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 1, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 1, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 1, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 1, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 1, 20, 0 ); } break; case EV_WATER_CLEAR: diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index 56636c1..ba849a0 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -1540,15 +1540,13 @@ static void CG_HasteTrail( centity_t *cent, vec3_t endPos ) { // BFP - Second pa } #endif - cent->trailTime += 100; + cent->trailTime += 50; // BFP - Before: += 100 if ( cent->trailTime < cg.time ) { cent->trailTime = cg.time; } // BFP - Apply dash smoke particle for the trail, if the function were used directly, it would generate too many particles than we expected CG_ParticleDashSmoke( cent, cgs.media.hastePuffShader, endPos ); - CG_ParticleDashSmoke( cent, cgs.media.hastePuffShader, endPos ); - CG_ParticleDashSmoke( cent, cgs.media.hastePuffShader, endPos ); // BFP - No smoke puff effect #if 0 @@ -1888,25 +1886,30 @@ static qboolean CG_PlayerShadow( centity_t *cent, float *shadowPlane ) { trap_CM_BoxTrace( &trace, cent->lerpOrigin, end, mins, maxs, 0, MASK_PLAYERSOLID ); - // no shadow if too high - if ( trace.fraction == 1.0 || trace.startsolid || trace.allsolid ) { - return qfalse; - } - - *shadowPlane = trace.endpos[2] + 1; - - // BFP - Dash smoke particles when using ki boost on the ground + // BFP - Dash smoke and bubble particles when using ki boost on the ground or above the water contents = CG_PointContents( trace.endpos, -1 ); if ( ( cent->currentState.eFlags & EF_AURA ) - && !( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) && ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_RUN || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_BACK || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYA - || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYB ) + || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYB ) ) { + if ( !( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) && trace.fraction <= 0.70f ) { - CG_HasteTrail( cent, trace.endpos ); + CG_HasteTrail( cent, trace.endpos ); + } else if ( contents & CONTENTS_WATER ) { + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, end, trace.endpos, 1, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, end, trace.endpos, 1, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, end, trace.endpos, 1, 20, 0 ); + } } + // no shadow if too high + if ( trace.fraction == 1.0 || trace.startsolid || trace.allsolid ) { + return qfalse; + } + + *shadowPlane = trace.endpos[2] + 1; + if ( cg_shadows.integer != 1 ) { // no mark for stencil or projection shadows return qtrue; } @@ -2354,9 +2357,9 @@ void CG_Player( centity_t *cent ) { if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYA || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYB ) { - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 1, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 1, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 1, 20, 0 ); } else if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE ) { bubbleOrigin[2] += -10; // put the origin a little below diff --git a/source/cgame/cg_weapons.c b/source/cgame/cg_weapons.c index c40b9b3..e4d6916 100644 --- a/source/cgame/cg_weapons.c +++ b/source/cgame/cg_weapons.c @@ -326,11 +326,12 @@ static void CG_RocketTrail( centity_t *ent, const weaponInfo_t *wi ) { ent->trailTime = cg.time; if ( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) { - if ( contents & lastContents & CONTENTS_WATER ) { + if ( ( contents & lastContents & CONTENTS_WATER ) + && cg.frametime > 0.0f ) { // BFP - If paused, don't spawn bubble particles (cg_paused.integer < 1 is another solution, but not good enough for server responses) // BFP - Apply particle bubble effect in that case - CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 0, 20, 0 ); - CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 0, 20, 0 ); - CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 0, 20, 0 ); + CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 1, 20, 0 ); + CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 1, 20, 0 ); + CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 1, 20, 0 ); // CG_BubbleTrail( lastPos, origin, 8 ); } return; From 74b0df551a638f7b45a553062a7e1c7cc28007d1 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sat, 3 Feb 2024 00:07:40 +0100 Subject: [PATCH 028/374] cgame: Add antigrav rock particles, make some adjustments to the other particles and add rock and smoke particle shaders --- source/cgame/cg_local.h | 11 +- source/cgame/cg_main.c | 10 +- source/cgame/cg_particles.c | 331 +++++++++++++++++++----------------- 3 files changed, 196 insertions(+), 156 deletions(-) diff --git a/source/cgame/cg_local.h b/source/cgame/cg_local.h index 6214d46..92ebf7e 100644 --- a/source/cgame/cg_local.h +++ b/source/cgame/cg_local.h @@ -765,7 +765,14 @@ typedef struct { qhandle_t invulnerabilityPowerupModel; - qhandle_t auraModel; // BFP - Aura model + // BFP - Particle shaders + qhandle_t pebbleShader1; + qhandle_t pebbleShader2; + qhandle_t pebbleShader3; + qhandle_t particleSmokeShader; + + // BFP - Aura models + qhandle_t auraModel; // BFP - Normal aura model qhandle_t backauraModel; // BFP - Back aura model qhandle_t flyauraModel; // BFP - Fly aura model qhandle_t runauraModel; // BFP - Run aura model @@ -1492,6 +1499,8 @@ void CG_ParticleExplosion (char *animStr, vec3_t origin, vec3_t vel, int duratio void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb, float range, int snum); // BFP - Dash smoke particle for ki boost when moving in the ground void CG_ParticleDashSmoke (centity_t *cent, qhandle_t pshader, vec3_t origin); +// BFP - Antigrav rock particles for charging +void CG_ParticleAntigravRock (qhandle_t pshader, centity_t *cent, vec3_t origin); extern qboolean initparticles; int CG_NewParticleArea ( int num ); diff --git a/source/cgame/cg_main.c b/source/cgame/cg_main.c index 1f4e6d7..e1f50c2 100644 --- a/source/cgame/cg_main.c +++ b/source/cgame/cg_main.c @@ -618,10 +618,12 @@ static void CG_RegisterGraphics( void ) { cgs.media.medalAssist = trap_R_RegisterShaderNoMip( "medal_assist" ); cgs.media.medalCapture = trap_R_RegisterShaderNoMip( "medal_capture" ); - cgs.media.auraModel = trap_R_RegisterModel( "models/effects/aura.md3" ); // BFP - Aura model + // BFP - Aura models + cgs.media.auraModel = trap_R_RegisterModel( "models/effects/aura.md3" ); // BFP - Normal aura model cgs.media.backauraModel = trap_R_RegisterModel( "models/effects/backaura.md3" ); // BFP - Back aura model cgs.media.flyauraModel = trap_R_RegisterModel( "models/effects/flyaura.md3" ); // BFP - Fly aura model cgs.media.runauraModel = trap_R_RegisterModel( "models/effects/runaura.md3" ); // BFP - Run aura model + // BFP - Aura shaders cgs.media.auraBlueShader = trap_R_RegisterShader( "powerups/bluetiny" ); cgs.media.auraRedShader = trap_R_RegisterShader( "powerups/redtiny" ); @@ -649,6 +651,12 @@ static void CG_RegisterGraphics( void ) { cgs.media.wakeMarkShader = trap_R_RegisterShader( "wake" ); cgs.media.bloodMarkShader = trap_R_RegisterShader( "bloodMark" ); + // BFP - Particle shaders + cgs.media.pebbleShader1 = trap_R_RegisterShader( "pebbleShader1" ); // BFP - Rock particles for charging and explosion + cgs.media.pebbleShader2 = trap_R_RegisterShader( "pebbleShader2" ); // BFP - Rock particles for charging and explosion + cgs.media.pebbleShader3 = trap_R_RegisterShader( "pebbleShader3" ); // BFP - Rock particles for charging and explosion + cgs.media.particleSmokeShader = trap_R_RegisterShader( "particleSmokeShader" ); // BFP - Smoke particle when using ki boost in the ground and for the explosion + // register the inline models cgs.numInlineModels = trap_CM_NumInlineModels(); for ( i = 1 ; i < cgs.numInlineModels ; i++ ) { diff --git a/source/cgame/cg_particles.c b/source/cgame/cg_particles.c index 1a25155..13f732e 100644 --- a/source/cgame/cg_particles.c +++ b/source/cgame/cg_particles.c @@ -71,6 +71,7 @@ typedef struct particle_s typedef enum { P_NONE, + P_ANTIGRAV_ROCK, // BFP - Antigrav rock particles P_WEATHER, P_FLAT, P_SMOKE, @@ -161,7 +162,7 @@ void CG_ClearParticles (void) } particles[cl_numparticles-1].next = NULL; - oldtime = cg.time; + oldtime = timenonscaled; // Ridah, init the shaderAnims for (i=0; shaderAnimNames[i]; i++) { @@ -185,7 +186,6 @@ CG_AddParticleToScene */ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) { - vec3_t point; polyVert_t verts[4]; float width; @@ -197,55 +197,29 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) polyVert_t TRIverts[3]; vec3_t rright2, rup2; - if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY - || p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) + if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY) {// create a front facing polygon if (p->type != P_WEATHER_FLURRY) { - if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) - { - if (org[2] > p->end) - { - p->time = timenonscaled; - VectorCopy (org, p->org); // Ridah, fixes rare snow flakes that flicker on the ground - - // BFP - Stop shivering, before: ( p->start + crandom () * 4 ) - p->org[2] = ( p->start ); - - // BFP - Make move less - if (p->type == P_BUBBLE_TURBULENT) { - p->vel[0] *= 0.95; - p->vel[1] *= 0.95; - } - else { - p->vel[0] *= 0.9; - p->vel[1] *= 0.9; - } + if (org[2] < p->end) + { + p->time = timenonscaled; + VectorCopy (org, p->org); // Ridah, fixes rare snow flakes that flicker on the ground + + while (p->org[2] < p->end) + { + p->org[2] += (p->start - p->end); } - } - else - { - if (org[2] < p->end) - { - p->time = timenonscaled; - VectorCopy (org, p->org); // Ridah, fixes rare snow flakes that flicker on the ground - - while (p->org[2] < p->end) - { - p->org[2] += (p->start - p->end); - } - - - if (p->type == P_WEATHER_TURBULENT) - { - p->vel[0] = crandom() * 16; - p->vel[1] = crandom() * 16; - } + + if (p->type == P_WEATHER_TURBULENT) + { + p->vel[0] = crandom() * 16; + p->vel[1] = crandom() * 16; } - } + } // Rafael snow pvs check if (!p->link) @@ -259,82 +233,36 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) return; } // done. - - if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) - { - VectorMA (org, -p->height, vup, point); - VectorMA (point, -p->width, vright, point); - VectorCopy (point, verts[0].xyz); - verts[0].st[0] = 0; - verts[0].st[1] = 0; - verts[0].modulate[0] = 255; - verts[0].modulate[1] = 255; - verts[0].modulate[2] = 255; - verts[0].modulate[3] = 255 * p->alpha; - - VectorMA (org, -p->height, vup, point); - VectorMA (point, p->width, vright, point); - VectorCopy (point, verts[1].xyz); - verts[1].st[0] = 0; - verts[1].st[1] = 1; - verts[1].modulate[0] = 255; - verts[1].modulate[1] = 255; - verts[1].modulate[2] = 255; - verts[1].modulate[3] = 255 * p->alpha; - - VectorMA (org, p->height, vup, point); - VectorMA (point, p->width, vright, point); - VectorCopy (point, verts[2].xyz); - verts[2].st[0] = 1; - verts[2].st[1] = 1; - verts[2].modulate[0] = 255; - verts[2].modulate[1] = 255; - verts[2].modulate[2] = 255; - verts[2].modulate[3] = 255 * p->alpha; - VectorMA (org, p->height, vup, point); - VectorMA (point, -p->width, vright, point); - VectorCopy (point, verts[3].xyz); - verts[3].st[0] = 1; - verts[3].st[1] = 0; - verts[3].modulate[0] = 255; - verts[3].modulate[1] = 255; - verts[3].modulate[2] = 255; - verts[3].modulate[3] = 255 * p->alpha; - } - else - { - VectorMA (org, -p->height, vup, point); - VectorMA (point, -p->width, vright, point); - VectorCopy( point, TRIverts[0].xyz ); - TRIverts[0].st[0] = 1; - TRIverts[0].st[1] = 0; - TRIverts[0].modulate[0] = 255; - TRIverts[0].modulate[1] = 255; - TRIverts[0].modulate[2] = 255; - TRIverts[0].modulate[3] = 255 * p->alpha; - - VectorMA (org, p->height, vup, point); - VectorMA (point, -p->width, vright, point); - VectorCopy (point, TRIverts[1].xyz); - TRIverts[1].st[0] = 0; - TRIverts[1].st[1] = 0; - TRIverts[1].modulate[0] = 255; - TRIverts[1].modulate[1] = 255; - TRIverts[1].modulate[2] = 255; - TRIverts[1].modulate[3] = 255 * p->alpha; - - VectorMA (org, p->height, vup, point); - VectorMA (point, p->width, vright, point); - VectorCopy (point, TRIverts[2].xyz); - TRIverts[2].st[0] = 0; - TRIverts[2].st[1] = 1; - TRIverts[2].modulate[0] = 255; - TRIverts[2].modulate[1] = 255; - TRIverts[2].modulate[2] = 255; - TRIverts[2].modulate[3] = 255 * p->alpha; - } - + VectorMA (org, -p->height, vup, point); + VectorMA (point, -p->width, vright, point); + VectorCopy( point, TRIverts[0].xyz ); + TRIverts[0].st[0] = 1; + TRIverts[0].st[1] = 0; + TRIverts[0].modulate[0] = 255; + TRIverts[0].modulate[1] = 255; + TRIverts[0].modulate[2] = 255; + TRIverts[0].modulate[3] = 255 * p->alpha; + + VectorMA (org, p->height, vup, point); + VectorMA (point, -p->width, vright, point); + VectorCopy (point, TRIverts[1].xyz); + TRIverts[1].st[0] = 0; + TRIverts[1].st[1] = 0; + TRIverts[1].modulate[0] = 255; + TRIverts[1].modulate[1] = 255; + TRIverts[1].modulate[2] = 255; + TRIverts[1].modulate[3] = 255 * p->alpha; + + VectorMA (org, p->height, vup, point); + VectorMA (point, p->width, vright, point); + VectorCopy (point, TRIverts[2].xyz); + TRIverts[2].st[0] = 0; + TRIverts[2].st[1] = 1; + TRIverts[2].modulate[0] = 255; + TRIverts[2].modulate[1] = 255; + TRIverts[2].modulate[2] = 255; + TRIverts[2].modulate[3] = 255 * p->alpha; } else if (p->type == P_SPRITE) { @@ -342,7 +270,7 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) vec3_t rotate_ang; VectorSet (color, 1.0, 1.0, 1.0); - time = cg.time - p->time; + time = timenonscaled - p->time; time2 = p->endtime - p->time; ratio = time / time2; @@ -409,7 +337,9 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) verts[3].modulate[2] = 255; verts[3].modulate[3] = 255; } - else if (p->type == P_SMOKE || p->type == P_SMOKE_IMPACT) + else if (p->type == P_SMOKE || p->type == P_SMOKE_IMPACT + || p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT // BFP - Bubble types moved here for better management + || p->type == P_ANTIGRAV_ROCK) // BFP - Added antigrav rock type {// create a front rotating facing polygon if ( p->type == P_SMOKE_IMPACT && Distance( cg.snap->ps.origin, org ) > 1024) { @@ -437,13 +367,13 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) else VectorSet (color, 1.0, 1.0, 1.0); - time = cg.time - p->time; + time = timenonscaled - p->time; time2 = p->endtime - p->time; ratio = time / time2; - if (cg.time > p->startfade) + if (timenonscaled > p->startfade) { - invratio = 1 - ( (cg.time - p->startfade) / (p->endtime - p->startfade) ); + invratio = 1 - ( (timenonscaled - p->startfade) / (p->endtime - p->startfade) ); if (p->color == EMISIVEFADE) { @@ -458,7 +388,7 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) else invratio = 1 * p->alpha; - if (invratio > 1) + if (invratio > 1 || p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) // BFP - Don't disappear opaquely the bubbles invratio = 1; width = p->width + ( ratio * ( p->endwidth - p->width) ); @@ -478,7 +408,64 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) VectorCopy (rright, rright2); VectorCopy (rup, rup2); } - + + // BFP - Bubble types here + if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) + { + if (org[2] > p->end) + { + p->time = timenonscaled; + VectorCopy (org, p->org); // Ridah, fixes rare snow flakes that flicker on the ground + + // BFP - Stop shivering, before: ( p->start + crandom () * 4 ) + p->org[2] = ( p->start ); + + // BFP - Make move less + if (p->type == P_BUBBLE_TURBULENT) { + p->vel[0] *= 0.95; + p->vel[1] *= 0.95; + } else { + p->vel[0] *= 0.9; + p->vel[1] *= 0.9; + } + } + } + + // BFP - Antigrav rock type + if (p->type == P_ANTIGRAV_ROCK) + { + // BFP - To detect if there is something solid + trace_t trace; + CG_Trace( &trace, p->org, vec3_origin, vec3_origin, org, -1, CONTENTS_SOLID ); + + // BFP - Make each particle fall when they aren't on ki charging status + if ( !( cg.snap->ps.pm_flags & PMF_KI_CHARGE ) && !p->link ) { + p->endtime = timenonscaled + 2000; + p->link = qtrue; + } + + // BFP - When the particle, checked to be fallen, won't be reactivated when entering ki charging status again + if (p->link) { + p->time = timenonscaled; + // not hit anything or not a collider + if ( trace.fraction == 1.0f && p->roll > 0 ) + { + VectorCopy (org, p->org); + p->vel[2] -= 30; + p->accel[2] -= 200; + } + else + { + // bouncing + p->roll--; + p->vel[2] = (p->roll > 0) ? 100 * p->roll : 1; + if (p->roll <= 0) { // stop moving + p->vel[2] = p->accel[2] = 0; + } + } + } + } + if (p->rotate) { VectorMA (org, -height, rup2, point); @@ -550,7 +537,6 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) verts[3].modulate[1] = 255 * color[1]; verts[3].modulate[2] = 255 * color[2]; verts[3].modulate[3] = 255 * invratio; - } else if (p->type == P_BLEED) { @@ -623,7 +609,7 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) else VectorSet (color, 0.5, 0.5, 0.5); - time = cg.time - p->time; + time = timenonscaled - p->time; time2 = p->endtime - p->time; ratio = time / time2; @@ -729,7 +715,7 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) vec3_t rotate_ang; int i, j; - time = cg.time - p->time; + time = timenonscaled - p->time; time2 = p->endtime - p->time; ratio = time / time2; if (ratio >= 1.0f) { @@ -852,11 +838,11 @@ void CG_AddParticles (void) VectorCopy( cg.refdef.viewaxis[2], vup ); vectoangles( cg.refdef.viewaxis[0], rotate_ang ); - roll += ((cg.time - oldtime) * 0.1) ; + roll += ((timenonscaled - oldtime) * 0.1) ; rotate_ang[ROLL] += (roll*0.9); AngleVectors ( rotate_ang, rforward, rright, rup); - oldtime = cg.time; + oldtime = timenonscaled; active = tail = NULL; @@ -879,7 +865,8 @@ void CG_AddParticles (void) if (p->type == P_SMOKE || p->type == P_ANIM || p->type == P_BLEED || p->type == P_SMOKE_IMPACT || p->type == P_WEATHER_FLURRY || p->type == P_FLAT_SCALEUP_FADE - || p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) // BFP - Add P_BUBBLE types to remove particles + || p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT // BFP - Add P_BUBBLE types to remove particles + || p->type == P_ANTIGRAV_ROCK) // BFP - Add P_ANTIGRAV_ROCK to remove particles { if (timenonscaled > p->endtime) { @@ -950,7 +937,7 @@ void CG_ParticleSnowFlurry (qhandle_t pshader, centity_t *cent) p->end = cent->currentState.origin2[1]; p->endtime = timenonscaled + cent->currentState.time; - p->startfade = cg.time + cent->currentState.time2; + p->startfade = timenonscaled + cent->currentState.time2; p->pshader = pshader; @@ -1055,7 +1042,6 @@ void CG_ParticleSnow (qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb, float range, int snum) { cparticle_t *p; - float randsize; // if (!pshader) CG_Printf ("CG_ParticleSnow pshader == ZERO!\n"); @@ -1068,27 +1054,23 @@ void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_ p->time = timenonscaled; // BFP - Add end time to remove particles, if there's no end time the particles will remain there - p->endtime = timenonscaled + 1000; - p->startfade = cg.time + 200; + p->endtime = timenonscaled + 1250 + (crandom() * 20); + p->startfade = timenonscaled + 200; p->color = 0; - p->alpha = 0.40f; + p->alpha = 1; p->alphavel = 0; // BFP - Apply to player's origin p->start = cent->currentState.origin[2]; p->end = cent->currentState.origin2[2]; p->pshader = pshader; - - randsize = 3 + (crandom() * 0.5); - - p->height = p->width = randsize; + p->height = p->width = 2 + (crandom() * 0.5); if (turb) { p->type = P_BUBBLE_TURBULENT; // BFP - Apply end time to remove particles in that case, if there's no end time the particles will remain there p->endtime = timenonscaled + 700; - p->startfade = cg.time + 200; VectorSet( p->vel, (rand() % 401) - 200, @@ -1113,7 +1095,7 @@ void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_ VectorSet( p->accel, crandom() * 20, crandom() * 20, - 1400 ); + 2000 ); } VectorCopy(origin, p->org); @@ -1146,7 +1128,7 @@ void CG_ParticleSmoke (qhandle_t pshader, centity_t *cent) p->time = timenonscaled; p->endtime = timenonscaled + cent->currentState.time; - p->startfade = cg.time + cent->currentState.time2; + p->startfade = timenonscaled + cent->currentState.time2; p->color = 0; p->alpha = 1.0; @@ -1189,7 +1171,7 @@ void CG_ParticleBulletDebris (vec3_t org, vec3_t vel, int duration) p->time = timenonscaled; p->endtime = timenonscaled + duration; - p->startfade = cg.time + duration/2; + p->startfade = timenonscaled + duration/2; p->color = EMISIVEFADE; p->alpha = 1.0; @@ -1393,7 +1375,7 @@ void CG_ParticleDashSmoke (centity_t *cent, qhandle_t pshader, vec3_t origin) p->end = cent->currentState.origin2[2]; p->endtime = timenonscaled + 2000; - p->startfade = cg.time + 100; + p->startfade = timenonscaled + 100; p->height = p->width = 25; @@ -1415,6 +1397,47 @@ void CG_ParticleDashSmoke (centity_t *cent, qhandle_t pshader, vec3_t origin) 1400 ); } +// BFP - Antigrav rock particles for ki charging status +void CG_ParticleAntigravRock (qhandle_t pshader, centity_t *cent, vec3_t origin) +{ + cparticle_t *p; + + // if (!pshader) CG_Printf ("CG_ParticleAntigravRock == ZERO!\n"); + + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + p->time = timenonscaled; + + p->endtime = timenonscaled + 450 + (crandom() * 20); + p->startfade = timenonscaled + 200; + p->roll = 5; // used as bounce counter + p->link = qfalse; // to handle the ki charging status + + p->color = 0; + p->alpha = 1; + p->alphavel = 0; + p->start = cent->currentState.origin[2]; + p->end = cent->currentState.origin2[2]; + p->pshader = pshader; + p->height = p->width = 2 + (crandom() * 0.5); + p->type = P_ANTIGRAV_ROCK; + + VectorCopy( origin, p->org ); + + p->org[0] += (crandom() * 40); + p->org[1] += (crandom() * 40); + + p->vel[0] = p->vel[1] = 0; + p->accel[0] = p->accel[1] = 0; + + p->vel[2] = 20; + p->accel[2] = 1000; +} + #if 0 void CG_ParticleImpactSmokePuff (qhandle_t pshader, vec3_t origin) { @@ -1437,7 +1460,7 @@ void CG_ParticleImpactSmokePuff (qhandle_t pshader, vec3_t origin) p->pshader = pshader; p->endtime = timenonscaled + 1000; - p->startfade = cg.time + 100; + p->startfade = timenonscaled + 100; p->width = rand()%4 + 8; p->height = rand()%4 + 8; @@ -1479,9 +1502,9 @@ void CG_Particle_Bleed (qhandle_t pshader, vec3_t start, vec3_t dir, int fleshEn p->endtime = timenonscaled + duration; if (fleshEntityNum) - p->startfade = cg.time; + p->startfade = timenonscaled; else - p->startfade = cg.time + 100; + p->startfade = timenonscaled + 100; p->width = 4; p->height = 4; @@ -1516,8 +1539,8 @@ void CG_Particle_OilParticle (qhandle_t pshader, centity_t *cent) float duration = 1500; - time = cg.time; - time2 = cg.time + cent->currentState.time; + time = timenonscaled; + time2 = timenonscaled + cent->currentState.time; ratio =(float)1 - ((float)time / (float)time2); @@ -1817,7 +1840,7 @@ void CG_ParticleBloodCloud (centity_t *cent, vec3_t origin, vec3_t dir) p->endtime = timenonscaled + 350 + (crandom() * 100); - p->startfade = cg.time; + p->startfade = timenonscaled; p->width = LARGESIZE; p->height = LARGESIZE; @@ -1861,7 +1884,7 @@ void CG_ParticleSparks (vec3_t org, vec3_t vel, int duration, float x, float y, p->time = timenonscaled; p->endtime = timenonscaled + duration; - p->startfade = cg.time + duration/2; + p->startfade = timenonscaled + duration/2; p->color = EMISIVEFADE; p->alpha = 0.4f; @@ -1948,7 +1971,7 @@ void CG_ParticleDust (centity_t *cent, vec3_t origin, vec3_t dir) else p->endtime = timenonscaled + 750 + (crandom() * 500); - p->startfade = cg.time; + p->startfade = timenonscaled; p->width = LARGESIZE; p->height = LARGESIZE; @@ -2017,7 +2040,7 @@ void CG_ParticleMisc (qhandle_t pshader, vec3_t origin, int size, int duration, else p->endtime = duration; - p->startfade = cg.time; + p->startfade = timenonscaled; p->width = size; p->height = size; From 4ccee2b157301851faf93ce3263a9ac413585ec2 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sat, 3 Feb 2024 00:20:43 +0100 Subject: [PATCH 029/374] cgame: Apply antigrav rock particles on ki charging status and adjust again correctly bubble and dash smoke particles --- source/cgame/cg_players.c | 60 ++++++++++++++++++++++++++------------- source/cgame/cg_weapons.c | 6 ++-- 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index ba849a0..fe3de9f 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -1546,7 +1546,7 @@ static void CG_HasteTrail( centity_t *cent, vec3_t endPos ) { // BFP - Second pa } // BFP - Apply dash smoke particle for the trail, if the function were used directly, it would generate too many particles than we expected - CG_ParticleDashSmoke( cent, cgs.media.hastePuffShader, endPos ); + CG_ParticleDashSmoke( cent, cgs.media.particleSmokeShader, endPos ); // BFP - No smoke puff effect #if 0 @@ -1865,7 +1865,7 @@ Returns the Z component of the surface being shadowed #define SHADOW_DISTANCE 128 static qboolean CG_PlayerShadow( centity_t *cent, float *shadowPlane ) { vec3_t end, mins = {-15, -15, 0}, maxs = {15, 15, 2}; - trace_t trace; + trace_t trace, waterTrace; // BFP - Trace for the water float alpha; int contents; // BFP - To detect if there is water or lava @@ -1885,21 +1885,43 @@ static qboolean CG_PlayerShadow( centity_t *cent, float *shadowPlane ) { end[2] -= SHADOW_DISTANCE; trap_CM_BoxTrace( &trace, cent->lerpOrigin, end, mins, maxs, 0, MASK_PLAYERSOLID ); + // BFP - Tracing the water surface + trap_CM_BoxTrace( &waterTrace, cent->lerpOrigin, end, mins, maxs, 0, CONTENTS_WATER ); // BFP - Dash smoke and bubble particles when using ki boost on the ground or above the water contents = CG_PointContents( trace.endpos, -1 ); - if ( ( cent->currentState.eFlags & EF_AURA ) - && ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_RUN + if ( cent->currentState.eFlags & EF_AURA ) { + if ( !( cg.snap->ps.pm_flags & PMF_KI_CHARGE ) && + ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_RUN || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_BACK || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYA || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYB ) ) { - if ( !( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) - && trace.fraction <= 0.70f ) { - CG_HasteTrail( cent, trace.endpos ); - } else if ( contents & CONTENTS_WATER ) { - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, end, trace.endpos, 1, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, end, trace.endpos, 1, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, end, trace.endpos, 1, 20, 0 ); + if ( !( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) + && trace.fraction <= 0.70f ) { + CG_HasteTrail( cent, trace.endpos ); + } else if ( waterTrace.fraction >= 0.10f && waterTrace.fraction <= 0.70f ) { + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, waterTrace.endpos, end, 1, 0, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, waterTrace.endpos, end, 1, 0, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, waterTrace.endpos, end, 1, 0, 0 ); + } + } else if ( ( cg.snap->ps.pm_flags & PMF_KI_CHARGE ) // BFP - Antigrav rock particles on ki charging status + && !( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) + && trace.fraction <= 0.50f ) { + // BFP - Spawn randomly the antigrav rock shaders with the particles + int shaderIndex = rand() % 3; + switch ( shaderIndex ) { + case 0: { + CG_ParticleAntigravRock( cgs.media.pebbleShader1, cent, trace.endpos ); + break; + } + case 1: { + CG_ParticleAntigravRock( cgs.media.pebbleShader2, cent, trace.endpos ); + break; + } + default: { + CG_ParticleAntigravRock( cgs.media.pebbleShader3, cent, trace.endpos ); + } + } } } @@ -2357,17 +2379,17 @@ void CG_Player( centity_t *cent ) { if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYA || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYB ) { - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 1, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 1, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 1, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 1, 0, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 1, 0, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 1, 0, 0 ); } else if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE ) { bubbleOrigin[2] += -10; // put the origin a little below - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 0, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 0, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 0, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 0, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 0, 0 ); } } diff --git a/source/cgame/cg_weapons.c b/source/cgame/cg_weapons.c index e4d6916..260389d 100644 --- a/source/cgame/cg_weapons.c +++ b/source/cgame/cg_weapons.c @@ -329,9 +329,9 @@ static void CG_RocketTrail( centity_t *ent, const weaponInfo_t *wi ) { if ( ( contents & lastContents & CONTENTS_WATER ) && cg.frametime > 0.0f ) { // BFP - If paused, don't spawn bubble particles (cg_paused.integer < 1 is another solution, but not good enough for server responses) // BFP - Apply particle bubble effect in that case - CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 1, 20, 0 ); - CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 1, 20, 0 ); - CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 1, 20, 0 ); + CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 1, 0, 0 ); + CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 1, 0, 0 ); + CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 1, 0, 0 ); // CG_BubbleTrail( lastPos, origin, 8 ); } return; From 93b69d92b416efc79766c17d0d28dd282b772880 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sun, 4 Feb 2024 01:31:33 +0100 Subject: [PATCH 030/374] cgame: Add more tweaks for antigrav rock particles when there's a mover (temporary solution), even for dash smoke particles and clean up some unused code in aura status --- source/cgame/cg_particles.c | 18 ++++++++++-------- source/cgame/cg_players.c | 19 +++++++++++-------- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/source/cgame/cg_particles.c b/source/cgame/cg_particles.c index 13f732e..9676abd 100644 --- a/source/cgame/cg_particles.c +++ b/source/cgame/cg_particles.c @@ -436,11 +436,11 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) { // BFP - To detect if there is something solid trace_t trace; - CG_Trace( &trace, p->org, vec3_origin, vec3_origin, org, -1, CONTENTS_SOLID ); + CG_Trace( &trace, p->org, vec3_origin, vec3_origin, org, -1, MASK_PLAYERSOLID ); // BFP - Make each particle fall when they aren't on ki charging status if ( !( cg.snap->ps.pm_flags & PMF_KI_CHARGE ) && !p->link ) { - p->endtime = timenonscaled + 2000; + p->endtime = timenonscaled + 1650; p->link = qtrue; } @@ -454,13 +454,15 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) p->vel[2] -= 30; p->accel[2] -= 200; } - else + else // bouncing { - // bouncing - p->roll--; - p->vel[2] = (p->roll > 0) ? 100 * p->roll : 1; - if (p->roll <= 0) { // stop moving - p->vel[2] = p->accel[2] = 0; + // BFP - TODO: Temporary solution... Make bouncing more interactive when there's a mover moving + if ( trace.fraction <= 0 // if the particle is touching a mover and moves down, so keep bouncing + && cg.snap->ps.groundEntityNum != ENTITYNUM_NONE ) { + p->roll = 10; + } else { + p->vel[2] = p->accel[2] = (p->roll > 0) ? 50 * p->roll : 0; + p->roll--; // that decreases bounces } } } diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index fe3de9f..d3a1045 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -1896,8 +1896,10 @@ static qboolean CG_PlayerShadow( centity_t *cent, float *shadowPlane ) { || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_BACK || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYA || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYB ) ) { - if ( !( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) - && trace.fraction <= 0.70f ) { + if ( ( !( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) + && trace.fraction <= 0.70f ) + // If the player is stepping a mover: + || cg.snap->ps.groundEntityNum != ENTITYNUM_NONE ) { CG_HasteTrail( cent, trace.endpos ); } else if ( waterTrace.fraction >= 0.10f && waterTrace.fraction <= 0.70f ) { CG_ParticleBubble( cent, cgs.media.waterBubbleShader, waterTrace.endpos, end, 1, 0, 0 ); @@ -1905,8 +1907,10 @@ static qboolean CG_PlayerShadow( centity_t *cent, float *shadowPlane ) { CG_ParticleBubble( cent, cgs.media.waterBubbleShader, waterTrace.endpos, end, 1, 0, 0 ); } } else if ( ( cg.snap->ps.pm_flags & PMF_KI_CHARGE ) // BFP - Antigrav rock particles on ki charging status - && !( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) - && trace.fraction <= 0.50f ) { + && ( ( !( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) + && trace.fraction <= 0.50f ) + // If the player is stepping a mover: + || cg.snap->ps.groundEntityNum != ENTITYNUM_NONE ) ) { // BFP - Spawn randomly the antigrav rock shaders with the particles int shaderIndex = rand() % 3; switch ( shaderIndex ) { @@ -2360,12 +2364,11 @@ void CG_Player( centity_t *cent ) { if ( cent->currentState.eFlags & EF_AURA ) { // BFP - TODO: Create a new function "CG_KiTrail" only when moving to draw ki trail and add the cvar for the length - // BFP - Traces for bubble particles only when moving in the water and charging - int sourceContentType, destContentType; + // BFP - Trace for bubble particles only when moving in the water and charging + int destContentType; vec3_t start; - sourceContentType = trap_CM_PointContents( start, 0 ); - destContentType = trap_CM_PointContents( cent->lerpOrigin, 0 ); + destContentType = CG_PointContents( cent->lerpOrigin, -1 ); // spawning bubble particles if ( destContentType & CONTENTS_WATER ) { From b2fb6b329020e09f7de0d3f0eeb67e7a8f3b76b4 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sun, 4 Feb 2024 16:48:57 +0100 Subject: [PATCH 031/374] cgame: Correct mouse yaw direction when player is flying and looking vertically --- source/cgame/cg_snapshot.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source/cgame/cg_snapshot.c b/source/cgame/cg_snapshot.c index f337e08..d0b7e5e 100644 --- a/source/cgame/cg_snapshot.c +++ b/source/cgame/cg_snapshot.c @@ -186,6 +186,14 @@ static void CG_TransitionSnapshot( void ) { } } + // BFP - When the player is flying and looking vertically, + // adjust the mouse's yaw direction to prevent the player from + // looking in the incorrect horizontal direction + if ( cg.refdefViewAngles[PITCH] <= -100 || cg.refdefViewAngles[PITCH] >= 100 ) { + trap_SendConsoleCommand( "seta m_yaw -0.022" ); + } else { + trap_SendConsoleCommand( "seta m_yaw 0.022" ); + } } From 0a2e1bac5887f06d661a149b1e6fbbd9c94ef240 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 5 Feb 2024 00:14:46 +0100 Subject: [PATCH 032/374] cgame: Adjust correctly fly tilt feature when the player is flying and using ki boost moving right/left, and remove unnecessary non-timescaled handling --- source/cgame/cg_view.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/source/cgame/cg_view.c b/source/cgame/cg_view.c index 9f68238..e620fc8 100644 --- a/source/cgame/cg_view.c +++ b/source/cgame/cg_view.c @@ -237,14 +237,6 @@ static void CG_OffsetThirdPersonView( void ) { // BFP - Last angled for fly tilt angle to move smoothly similar to BFP vanilla static float lastAngled = 0.0f, lastRightAngled = 0.0f, lastUpAngled = 0.0f; float rightAngled, upAngled; - // BFP - Frametime handling - static int previous; - int t, frameTime; - - // BFP - Handle frametime to avoid being timescaled - t = trap_Milliseconds(); - frameTime = t - previous; - previous = t; // BFP - Camera setup camAngle = cg_thirdPersonAngle.value; @@ -302,6 +294,7 @@ static void CG_OffsetThirdPersonView( void ) { // in a solid block. Use an 8 by 8 block to prevent the view from near clipping anything // BFP - cg_cameraMode cvar to detect if it's disabled doesn't exist + // BFP - NOTE: Originally, BFP uses MASK_SOLID for tracing and it might not be a good solution, so use MASK_PLAYERSOLID for all traces here instead in the future // That traces the camera pivot CG_Trace( &trace, cg.refdef.vieworg, mins, maxs, view, cg.predictedPlayerState.clientNum, MASK_SOLID ); if ( trace.fraction != 1.0 ) { @@ -342,21 +335,22 @@ static void CG_OffsetThirdPersonView( void ) { // BFP - TODO: If cg_thirdPersonAngle is changed, the roll rotation should be moved like in 0º (or fixed) - focusAngles[ROLL] = LERP( lastAngled, 0.0f, (float)(frameTime / 1000.00f) * 20.0f ); - rightAngled = LERP( lastRightAngled, 0.0f, (float)(frameTime / 1000.00f) * 20.0f ); - upAngled = LERP( lastUpAngled, 0.0f, (float)(frameTime / 1000.00f) * 20.0f ); + focusAngles[ROLL] = LERP( lastAngled, 0.0f, (float)(cg.frametime / 1000.00f) * 20.0f ); + rightAngled = LERP( lastRightAngled, 0.0f, (float)(cg.frametime / 1000.00f) * 20.0f ); + upAngled = LERP( lastUpAngled, 0.0f, (float)(cg.frametime / 1000.00f) * 20.0f ); if ( cg_flytilt.integer >= 1 + && ( cg.predictedPlayerState.eFlags & EF_AURA ) && ( cg.predictedPlayerState.pm_flags & PMF_FLYING ) - && ( cg.predictedPlayerState.eFlags & EF_AURA ) && &cmd ) { - if ( cmd.rightmove < 0 && ( cmd.buttons & BUTTON_KI_USE ) ) { // Left - focusAngles[ROLL] = LERP( lastAngled, -20.0f, (float)(frameTime / 1000.00f) * 15.0f ); - rightAngled = LERP( lastRightAngled, focusAngles[ROLL] - 0.55f, (float)(frameTime / 1000.00f) * 15.0f ); - upAngled = LERP( lastUpAngled, -acos( focusAngles[ROLL] / 180 * M_PI ) - 1.7f, (float)(frameTime / 1000.00f) * 15.0f ); - } else if ( cmd.rightmove > 0 && ( cmd.buttons & BUTTON_KI_USE ) ) { // Right - focusAngles[ROLL] = LERP( lastAngled, 20.0f, (float)(frameTime / 1000.00f) * 15.0f ); - rightAngled = LERP( lastRightAngled, focusAngles[ROLL] - 0.55f, (float)(frameTime / 1000.00f) * 15.0f ); - upAngled = LERP( lastUpAngled, -acos( focusAngles[ROLL] / 180 * M_PI ) - 1.7f, (float)(frameTime / 1000.00f) * 15.0f ); + && !( cg.predictedPlayerState.pm_flags & PMF_KI_CHARGE ) ) { + if ( cmd.rightmove < 0 ) { // Left + focusAngles[ROLL] = LERP( lastAngled, -20.0f, (float)(cg.frametime / 1000.00f) * 15.0f ); + rightAngled = LERP( lastRightAngled, focusAngles[ROLL] - 0.55f, (float)(cg.frametime / 1000.00f) * 15.0f ); + upAngled = LERP( lastUpAngled, -acos( focusAngles[ROLL] / 180 * M_PI ) - 1.7f, (float)(cg.frametime / 1000.00f) * 15.0f ); + } else if ( cmd.rightmove > 0 ) { // Right + focusAngles[ROLL] = LERP( lastAngled, 20.0f, (float)(cg.frametime / 1000.00f) * 15.0f ); + rightAngled = LERP( lastRightAngled, focusAngles[ROLL] - 0.55f, (float)(cg.frametime / 1000.00f) * 15.0f ); + upAngled = LERP( lastUpAngled, -acos( focusAngles[ROLL] / 180 * M_PI ) - 1.7f, (float)(cg.frametime / 1000.00f) * 15.0f ); } } // Last roll where it was "lerped" From 57c93c34e325ba0464b8650a23a490873aa404da Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 5 Feb 2024 20:36:42 +0100 Subject: [PATCH 033/374] cgame: Tweak the shine of light auras a bit --- source/cgame/cg_players.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index d3a1045..520e995 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -2341,20 +2341,29 @@ void CG_Player( centity_t *cent ) { #define AURA_LIGHT(r, g, b) \ if ( cg_lightAuras.integer > 0 ) { \ if ( cg_smallOwnAura.integer > 0 ) { \ - trap_R_AddLightToScene( legs.origin, 100 + (rand()&255), r, g, b ); \ - trap_R_AddLightToScene( aura.origin, 150 + (rand()&255), r, g, b ); \ - trap_R_AddLightToScene( aura2.origin, 200 + (rand()&255), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 200, r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 200, r, g, b ); \ if ( !( cg.predictedPlayerState.pm_flags & PMF_KI_CHARGE ) ) { \ - trap_R_AddLightToScene( cent->lerpOrigin, 100 + (rand()&150), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), r, g, b ); \ + } else { \ + trap_R_AddLightToScene( cent->lerpOrigin, 100 + (rand()&100), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 100 + (rand()&100), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 100 + (rand()&100), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 100 + (rand()&100), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 100 + (rand()&100), r, g, b ); \ } \ } else if ( cg_lightweightAuras.integer > 0 || cg_polygonAura.integer > 0 || cg_highPolyAura.integer > 0 ) { \ trap_R_AddLightToScene( cent->lerpOrigin, 50 + (rand()&100), r, g, b ); \ - trap_R_AddLightToScene( legs.origin, 50 + (rand()&100), r, g, b ); \ - trap_R_AddLightToScene( aura.origin, 50 + (rand()&100), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 50 + (rand()&100), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 50 + (rand()&100), r, g, b ); \ } else { \ - trap_R_AddLightToScene( legs.origin, 200 + (rand()&63), r, g, b ); \ - trap_R_AddLightToScene( aura.origin, 200 + (rand()&255), r, g, b ); \ - trap_R_AddLightToScene( aura2.origin, 200 + (rand()&255), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&63), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), r, g, b ); \ if ( !( cg.predictedPlayerState.pm_flags & PMF_KI_CHARGE ) ) { \ trap_R_AddLightToScene( cent->lerpOrigin, 100 + (rand()&150), r, g, b ); \ } \ From ef01d5ac2416820179a1c3864215671291953b02 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 5 Feb 2024 20:43:20 +0100 Subject: [PATCH 034/374] game: Apply movements when interacting the steep slopes, apply jump animations when getting out of the water, apply MASK_PLAYERSOLID to ground traces for anything solid where the players step and apply sticky while flying and grazing the steep slopes; that's what originally BFP did --- source/game/bg_pmove.c | 92 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 79 insertions(+), 13 deletions(-) diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index 3156015..fd53e51 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -468,6 +468,13 @@ static void PM_WaterJumpMove( void ) { pm->ps->pm_flags &= ~PMF_ALL_TIMES; pm->ps->pm_time = 0; } + + // BFP - Handle jumping animation when getting out of the water + if ( !( pm->ps->pm_flags & PMF_FLYING ) + && ( pm->ps->pm_flags & PMF_FALLING ) ) { + pm->ps->pm_flags &= ~PMF_FALLING; + FORCEJUMP_ANIM_HANDLING(); + } } /* @@ -1119,10 +1126,13 @@ static void PM_GroundTrace( void ) { pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask); pml.groundTrace = trace; - // BFP - Flight, if flying, do nothing when touching the ground + // BFP - NOTE: Originally, BFP doesn't stop "groundtracing" when the player is flying +#if 0 + // BFP - If flying, do nothing when touching the ground if ( pm->ps->pm_flags & PMF_FLYING ) { return; } +#endif // BFP - No ground trace handling in the water if ( pm->waterlevel > 1 ) { @@ -1165,6 +1175,54 @@ static void PM_GroundTrace( void ) { pm->ps->groundEntityNum = ENTITYNUM_NONE; pml.groundPlane = qtrue; pml.walking = qfalse; + + // BFP - Handle if the player is trying to jump and/or do another movements + // when stepping the steep slopes + if ( PM_CheckJump () ) { + // jumped away + if ( pm->waterlevel > 1 ) { + PM_WaterMove(); + } else { + PM_AirMove(); + } + return; + } + + // BFP - Handling the PMF flag when that happens + pm->ps->pm_flags &= ~PMF_NEARGROUND; + + if ( pm->ps->pm_flags & PMF_DUCKED ) { + PM_ContinueLegsAnim( LEGS_IDLECR ); + if ( pm->cmd.forwardmove < 0 + || ( pm->cmd.forwardmove > 0 + || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) ) { + PM_ContinueLegsAnim( LEGS_WALKCR ); + } + PM_ContinueTorsoAnim( TORSO_STAND ); // BFP - Keep the torso + return; + } + + if ( !pm->cmd.forwardmove && !pm->cmd.rightmove ) { + PM_ContinueLegsAnim( LEGS_IDLE ); + return; + } + + if ( !( pm->cmd.buttons & BUTTON_WALKING ) ) { + if ( pm->cmd.forwardmove < 0 ) { + PM_ContinueLegsAnim( LEGS_BACK ); + PM_ContinueTorsoAnim( TORSO_STAND ); // BFP - Keep the torso + } else if ( pm->cmd.forwardmove > 0 || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { + PM_ContinueLegsAnim( LEGS_RUN ); + PM_ContinueTorsoAnim( TORSO_RUN ); // BFP - Keep the torso + } + } else { + if ( pm->cmd.forwardmove < 0 ) { + PM_ContinueLegsAnim( LEGS_BACK ); + } else if ( pm->cmd.forwardmove > 0 || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { + PM_ContinueLegsAnim( LEGS_WALK ); + } + PM_ContinueTorsoAnim( TORSO_STAND ); // BFP - Keep the torso + } return; } @@ -1179,7 +1237,8 @@ static void PM_GroundTrace( void ) { } // BFP - Handle when the player isn't flying - if ( pm->ps->groundEntityNum == ENTITYNUM_NONE && !( pm->ps->pm_flags & PMF_FLYING ) ) { + if ( pm->ps->groundEntityNum == ENTITYNUM_NONE && !( pm->ps->pm_flags & PMF_FLYING ) + && ( pm->ps->pm_flags & PMF_NEARGROUND ) ) { // just hit the ground if ( pm->debugLevel ) { Com_Printf("%i:Land\n", c_pmove); @@ -1390,7 +1449,7 @@ static void PM_Footsteps( void ) { if ( pm->ps->pm_flags & PMF_DUCKED ) { bobmove = 0.5; // ducked characters bob much faster // BFP - Replaced PMF_BACKWARDS_RUN handling - if ( pml.groundTrace.contents & CONTENTS_SOLID ) { + if ( pml.groundTrace.contents & MASK_PLAYERSOLID ) { if ( pm->cmd.forwardmove < 0 ) { PM_ContinueLegsAnim( LEGS_WALKCR ); // BFP - before LEGS_BACKCR } else if ( pm->cmd.forwardmove > 0 || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { @@ -1410,7 +1469,7 @@ static void PM_Footsteps( void ) { PM_ContinueLegsAnim( LEGS_BACK ); */ } else { - if ( !( pm->cmd.buttons & BUTTON_WALKING ) && ( pml.groundTrace.contents & CONTENTS_SOLID ) ) { + if ( !( pm->cmd.buttons & BUTTON_WALKING ) && ( pml.groundTrace.contents & MASK_PLAYERSOLID ) ) { bobmove = 0.4f; // faster speeds bob faster // BFP - Replaced PMF_BACKWARDS_RUN handling if ( pm->cmd.forwardmove < 0 ) { @@ -1421,7 +1480,7 @@ static void PM_Footsteps( void ) { PM_ContinueTorsoAnim( TORSO_RUN ); // BFP - Keep the torso } footstep = qtrue; - } else if ( pml.groundTrace.contents & CONTENTS_SOLID ) { + } else if ( pml.groundTrace.contents & MASK_PLAYERSOLID ) { bobmove = 0.3f; // walking bobs slow // BFP - Replaced PMF_BACKWARDS_RUN handling if ( pm->cmd.forwardmove < 0 ) { @@ -1477,6 +1536,12 @@ static void PM_WaterEvents( void ) { // FIXME? // if (pml.previous_waterlevel && !pm->waterlevel) { PM_AddEvent( EV_WATER_LEAVE ); + // BFP - Handle jumping animation when getting out of the water + if ( !( pm->ps->pm_flags & PMF_FLYING ) + && ( pm->ps->pm_flags & PMF_FALLING ) ) { + pm->ps->pm_flags &= ~PMF_FALLING; + FORCEJUMP_ANIM_HANDLING(); + } } // @@ -1559,6 +1624,9 @@ static void PM_TorsoAnimation( void ) { vec3_t point; // BFP - TODO: Melee, block and ki attack animation handling (these are for torso animations) + // Keep in mind about the implementations of the steep slopes, + // PM_ContinueTorsoAnim( TORSO_STAND ) and + // !pm->cmd.forwardmove && !pm->cmd.rightmove && !pm->cmd.buttons thingies // BFP - No ground trace handling in the water if ( pm->waterlevel > 1 ) { @@ -1612,7 +1680,7 @@ static void PM_FlightAnimation( void ) { // BFP - Flight } // Handle the player movement animation if trying to change quickly the direction of forward or backward - if ( !( pml.groundTrace.contents & CONTENTS_SOLID ) && !( pm->ps->pm_flags & PMF_FALLING ) ) { + if ( !( pml.groundTrace.contents & MASK_PLAYERSOLID ) && !( pm->ps->pm_flags & PMF_FALLING ) ) { // stops entering again here and don't change the animation to backwards/forward pm->ps->pm_flags |= PMF_FALLING; @@ -1643,7 +1711,7 @@ static void PM_KiChargeAnimation( void ) { // BFP - Ki Charge pm->ps->pm_flags &= ~PMF_KI_CHARGE; pm->ps->pm_time = 0; // do jump animation if it's falling - if ( !( pml.groundTrace.contents & CONTENTS_SOLID ) + if ( !( pml.groundTrace.contents & MASK_PLAYERSOLID ) && !( pm->ps->pm_flags & PMF_FLYING ) && ( pm->ps->pm_flags & PMF_FALLING ) && pm->waterlevel <= 1 ) { // Don't force inside the water @@ -1658,7 +1726,7 @@ static void PM_KiChargeAnimation( void ) { // BFP - Ki Charge pm->ps->pm_flags &= ~PMF_KI_CHARGE; PM_ContinueLegsAnim( LEGS_IDLE ); // Keep the legs when being near to the ground at that height // do jump animation if it's falling - if ( !( pml.groundTrace.contents & CONTENTS_SOLID ) + if ( !( pml.groundTrace.contents & MASK_PLAYERSOLID ) && ( pm->ps->pm_flags & PMF_FALLING ) && pm->waterlevel <= 1 ) { // Don't force inside the water FORCEJUMP_ANIM_HANDLING(); @@ -1706,7 +1774,7 @@ static void PM_HitStunAnimation( void ) { // BFP - Hit stun if ( ( pm->ps->pm_flags & PMF_HITSTUN ) && pm->ps->pm_time <= 0 ) { pm->ps->pm_flags &= ~PMF_HITSTUN; // do jump animation if it's falling - if ( !( pml.groundTrace.contents & CONTENTS_SOLID ) + if ( !( pml.groundTrace.contents & MASK_PLAYERSOLID ) && ( pm->ps->pm_flags & PMF_FALLING ) ) { FORCEJUMP_ANIM_HANDLING(); PM_ContinueTorsoAnim( TORSO_STAND ); // Keep the torso @@ -1981,8 +2049,6 @@ void PM_UpdateViewAngles( playerState_t *ps, const usercmd_t *cmd ) { return; // no view changes at all } - // Com_Printf( "pml.groundPlane == qtrue: %d\n", pml.groundPlane == qtrue ? "true" : "false" ); - // circularly clamp the angles with deltas for (i=0 ; i<3 ; i++) { temp = cmd->angles[i] + ps->delta_angles[i]; @@ -2020,7 +2086,7 @@ static qboolean PM_EnableFlight( void ) { // BFP - Flight } if ( ( pm->ps->pm_flags & PMF_FLYING ) && !( pm->ps->pm_flags & PMF_HITSTUN ) ) { - if ( ( pml.groundTrace.contents & CONTENTS_SOLID ) && pm->ps->groundEntityNum != ENTITYNUM_NONE ) { + if ( ( pml.groundTrace.contents & MASK_PLAYERSOLID ) && pm->ps->groundEntityNum != ENTITYNUM_NONE ) { // do a smooth jump animation like BFP does if ( !( pm->cmd.buttons & BUTTON_KI_CHARGE ) ) { pm->ps->pm_time = 500; @@ -2120,7 +2186,7 @@ void PmoveSingle (pmove_t *pmove) { pm->ps->eFlags &= ~EF_TALK; } - // BFP - Handling the PM flag when stepping the ground + // BFP - Handling the PMF flag when stepping the ground if ( pm->ps->pm_flags & PMF_RESPAWNED ) { pm->ps->pm_flags |= PMF_FALLING; } From 7cfb3afd649346e5ed21782a0bc040054ec9d500 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 5 Feb 2024 21:23:20 +0100 Subject: [PATCH 035/374] game: Implement g_noFlight cvar. An option to disable/enable flight in the server --- docs/bfp_cvars_task.md | 1 + source/game/g_cmds.c | 5 +++++ source/game/g_cvar.h | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/bfp_cvars_task.md b/docs/bfp_cvars_task.md index 6cab102..8d4d955 100644 --- a/docs/bfp_cvars_task.md +++ b/docs/bfp_cvars_task.md @@ -71,6 +71,7 @@ - [x] ~~cg_lightweightAuras~~ - [x] ~~cg_polygonAura~~ - [x] ~~cg_highPolyAura~~ +- [x] ~~g_noFlight (disables "fly" bind too, original BFP has a leak though)~~ #### Cvar Gametypes: diff --git a/source/game/g_cmds.c b/source/game/g_cmds.c index b46a8ae..8fdab05 100644 --- a/source/game/g_cmds.c +++ b/source/game/g_cmds.c @@ -1597,6 +1597,11 @@ Cmd_BFP_Fly_f */ void Cmd_BFP_Fly_f( gentity_t* ent ) { // BFP - Flight + // BFP - No flight + if ( g_noFlight.integer > 0 ) { + return; + } + if ( ent->client->ps.pm_type != PM_DEAD ) { // do not play the sound in the charging status if ( !( ent->client->ps.pm_flags & PMF_FLYING ) && !( ent->client->ps.pm_flags & PMF_KI_CHARGE ) ) { diff --git a/source/game/g_cvar.h b/source/game/g_cvar.h index fad0c45..941c391 100644 --- a/source/game/g_cvar.h +++ b/source/game/g_cvar.h @@ -70,7 +70,7 @@ G_CVAR( g_meleeRange, "g_meleeRange", "32", 0, 0, qtrue ) // BFP - Melee range G_CVAR( g_chargeDelay, "g_chargeDelay", "750", 0, 0, qtrue ) // BFP - Charge delay G_CVAR( g_hitStun, "g_hitStun", "", 0, 0, qtrue ) // BFP - Hit stun G_CVAR( g_meleeOnly, "g_meleeOnly", "", 0, 0, qtrue ) // BFP - Melee only -G_CVAR( g_noFlight, "g_noFlight", "", 0, 0, qtrue ) // BFP - No flight +G_CVAR( g_noFlight, "g_noFlight", "0", CVAR_SERVERINFO | CVAR_USERINFO | CVAR_LATCH, 0, qtrue ) // BFP - No flight G_CVAR( g_plKillBonusPct, "g_plKillBonusPct", ".1", 0, 0, qtrue ) // BFP - Kill bonus percentage G_CVAR( g_maxSpawnPL, "g_maxSpawnPL", "999", 0, 0, qtrue ) // BFP - Max spawn powerlevel G_CVAR( g_flightCost, "g_flightCost", "50", 0, 0, qtrue ) // BFP - Flight cost From a264ff9e4dc0188d22a89c18f027458ac8a5e6ea Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 5 Feb 2024 23:24:14 +0100 Subject: [PATCH 036/374] game: Prevent from doing a jumping action on flat ground when flying --- source/game/bg_pmove.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index fd53e51..93f8666 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -1126,14 +1126,6 @@ static void PM_GroundTrace( void ) { pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask); pml.groundTrace = trace; - // BFP - NOTE: Originally, BFP doesn't stop "groundtracing" when the player is flying -#if 0 - // BFP - If flying, do nothing when touching the ground - if ( pm->ps->pm_flags & PMF_FLYING ) { - return; - } -#endif - // BFP - No ground trace handling in the water if ( pm->waterlevel > 1 ) { return; @@ -1226,6 +1218,12 @@ static void PM_GroundTrace( void ) { return; } + // BFP - NOTE: Originally, BFP doesn't stop "groundtracing" until here when the player is flying + // BFP - If flying, prevent from doing a jumping action on flat ground + if ( pm->ps->pm_flags & PMF_FLYING ) { + return; + } + pml.groundPlane = qtrue; pml.walking = qtrue; From 12012b0070e3b99a9a7e39ac51147f6e39315da7 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Tue, 6 Feb 2024 23:59:43 +0100 Subject: [PATCH 037/374] game: Add unfinished command 'selectcharacter [name/model]'. Original BFP didn't complete that implementation --- source/game/g_cmds.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/source/game/g_cmds.c b/source/game/g_cmds.c index 8fdab05..c9937b8 100644 --- a/source/game/g_cmds.c +++ b/source/game/g_cmds.c @@ -1627,8 +1627,24 @@ void Cmd_BFP_SetKiIdle_f( gentity_t* ent ) { // BFP - TODO: Set Ki idle Com_Printf( "Cmd_BFP_SetKiIdle_f\n" ); } -void Cmd_BFP_SelectCharacter_f( gentity_t* ent ) { // BFP - TODO: Select character - Com_Printf( "Cmd_BFP_SelectCharacter_f\n" ); +/* +===================== +Cmd_BFP_SelectCharacter_f +===================== +*/ +void Cmd_BFP_SelectCharacter_f( gentity_t* ent ) { // BFP - Select character + char characterselected[MAX_TOKEN_CHARS]; + + // BFP - NOTE: That command was left without finishing the implementation to change the character of this way + // What could it be? + + if ( trap_Argc() != 2 ) { + return; + } + trap_Argv( 1, characterselected, sizeof( characterselected ) ); + + // that prints the info in the server + G_Printf( "Character: %s\n", characterselected ); } void Cmd_BFP_StartBlock_f( gentity_t* ent ) { // BFP - TODO: Start block @@ -1761,7 +1777,7 @@ void ClientCommand( int clientNum ) { Cmd_BFP_KiUseToggle_f( ent ); else if (Q_stricmp (cmd, "set_ki_idle") == 0) // BFP - TODO: Set Ki idle Cmd_BFP_SetKiIdle_f( ent ); - else if (Q_stricmp (cmd, "selectcharacter") == 0) // BFP - TODO: Select character + else if (Q_stricmp (cmd, "selectcharacter") == 0) // BFP - Select character Cmd_BFP_SelectCharacter_f( ent ); else if (Q_stricmp (cmd, "start_block") == 0) // BFP - TODO: Start Block Cmd_BFP_StartBlock_f( ent ); From 6e1577856b908aa8325f8cf8eda4ccfecd8c9eac Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Wed, 7 Feb 2024 01:25:20 +0100 Subject: [PATCH 038/374] game: Add unfinished command 'set_ki_use', researching that, it doesn't do anything on original BFP, and add another semi-complete command 'set_ki_charge', neither does this one... What were they thinking? --- source/game/g_cmds.c | 53 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/source/game/g_cmds.c b/source/game/g_cmds.c index c9937b8..4cf81a9 100644 --- a/source/game/g_cmds.c +++ b/source/game/g_cmds.c @@ -1611,6 +1611,40 @@ void Cmd_BFP_Fly_f( gentity_t* ent ) { // BFP - Flight } } +/* +===================== +Cmd_BFP_SetKiCharge_f +===================== +*/ +void Cmd_BFP_SetKiCharge_f( gentity_t* ent ) { // BFP - Set Ki charge + // BFP - NOTE: Charging only when ki use has been toggled, + // but it's a charging pose animation only, + // what were they (original BFP devs) thinking? + + // Nah, that implementation doesn't make sense, + // if you want silly and useless stuff like that, play it in original BFP + if ( ent->client->ps.pm_type != PM_DEAD + && ( ent->client->ps.eFlags & EF_AURA ) ) { + ent->client->ps.torsoTimer = ent->client->ps.legsTimer = 0; + ent->client->ps.legsAnim = LEGS_CHARGE; + ent->client->ps.torsoAnim = TORSO_CHARGE; + } +} + +/* +===================== +Cmd_BFP_SetKiUse_f +===================== +*/ +void Cmd_BFP_SetKiUse_f( gentity_t* ent ) { // BFP - Set Ki use + // BFP - NOTE: Originally, an unfinished command... +#if 0 + if ( ent->client->ps.pm_type != PM_DEAD ) { + ent->client->ps.pm_flags |= PMF_KI_BOOST; + } +#endif +} + /* ===================== Cmd_BFP_KiUseToggle_f @@ -1623,8 +1657,17 @@ void Cmd_BFP_KiUseToggle_f( gentity_t* ent ) { // BFP - Ki use toggle } } -void Cmd_BFP_SetKiIdle_f( gentity_t* ent ) { // BFP - TODO: Set Ki idle - Com_Printf( "Cmd_BFP_SetKiIdle_f\n" ); +/* +===================== +Cmd_BFP_SetKiIdle_f +===================== +*/ +void Cmd_BFP_SetKiIdle_f( gentity_t* ent ) { // BFP - Set Ki idle + + // BFP - NOTE: originally... Ki idling means disabling the ki? Sounds like it isn't operating... + if ( ent->client->ps.pm_type != PM_DEAD ) { + ent->client->ps.pm_flags &= ~PMF_KI_BOOST; + } } /* @@ -1773,9 +1816,13 @@ void ClientCommand( int clientNum ) { Cmd_Stats_f( ent ); else if (Q_stricmp (cmd, "fly") == 0) // BFP - Flight Cmd_BFP_Fly_f( ent ); + else if (Q_stricmp (cmd, "set_ki_charge") == 0) // BFP - Set Ki charge + Cmd_BFP_SetKiCharge_f( ent ); + else if (Q_stricmp (cmd, "set_ki_use") == 0) // BFP - Set Ki use + Cmd_BFP_SetKiUse_f( ent ); else if (Q_stricmp (cmd, "kiusetoggle") == 0) // BFP - Ki use toggle Cmd_BFP_KiUseToggle_f( ent ); - else if (Q_stricmp (cmd, "set_ki_idle") == 0) // BFP - TODO: Set Ki idle + else if (Q_stricmp (cmd, "set_ki_idle") == 0) // BFP - Set Ki idle Cmd_BFP_SetKiIdle_f( ent ); else if (Q_stricmp (cmd, "selectcharacter") == 0) // BFP - Select character Cmd_BFP_SelectCharacter_f( ent ); From 377db590e11fe8772ed1a1be6a10b2a6a8e899db Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Thu, 8 Feb 2024 14:02:21 +0100 Subject: [PATCH 039/374] cgame: Fix the implementation of mouse's yaw direction, without '\n' in the commands borks the user interaction keys when playing in the game (that issue can be played on ioQuake3 and Quake3 vanilla engines) --- source/cgame/cg_snapshot.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/cgame/cg_snapshot.c b/source/cgame/cg_snapshot.c index d0b7e5e..f066af1 100644 --- a/source/cgame/cg_snapshot.c +++ b/source/cgame/cg_snapshot.c @@ -190,9 +190,9 @@ static void CG_TransitionSnapshot( void ) { // adjust the mouse's yaw direction to prevent the player from // looking in the incorrect horizontal direction if ( cg.refdefViewAngles[PITCH] <= -100 || cg.refdefViewAngles[PITCH] >= 100 ) { - trap_SendConsoleCommand( "seta m_yaw -0.022" ); + trap_SendConsoleCommand( "seta m_yaw -0.022\n" ); } else { - trap_SendConsoleCommand( "seta m_yaw 0.022" ); + trap_SendConsoleCommand( "seta m_yaw 0.022\n" ); } } From 4c5e8ce0645793dc9b8b38b478ffe15a2c24fe78 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Thu, 8 Feb 2024 14:16:49 +0100 Subject: [PATCH 040/374] game: Add less flight friction and prevent from doing a jumping action on slopes when flying --- source/game/bg_pmove.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index 93f8666..06e30cd 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -42,7 +42,7 @@ float pm_flyaccelerate = 8.0f; float pm_friction = 6.0f; float pm_waterfriction = 1.0f; -float pm_flightfriction = 3.0f; +float pm_flightfriction = 2.0f; // BFP - Add less flight friction, before 3.0f float pm_spectatorfriction = 5.0f; int c_pmove = 0; @@ -1168,6 +1168,11 @@ static void PM_GroundTrace( void ) { pml.groundPlane = qtrue; pml.walking = qfalse; + // BFP - If flying, prevent from doing a jumping action on slopes + if ( pm->ps->pm_flags & PMF_FLYING ) { + return; + } + // BFP - Handle if the player is trying to jump and/or do another movements // when stepping the steep slopes if ( PM_CheckJump () ) { From 8e7cfe38269bce0756965de780b1531f8f0c2cea Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Fri, 9 Feb 2024 00:59:01 +0100 Subject: [PATCH 041/374] game: Disable PMF_TIME_WATERJUMP flag and PMF_ALL_TIMES macro, these will be reused. Handle charging status when being under water, handle PMF flags in the slopes, water and falling near the ground, make sure the aura is off when charging status isn't being active and change the velocity of water jump when getting out of the water touching the shore --- source/game/ai_dmq3.c | 3 ++ source/game/be_ai_move.h | 3 +- source/game/bg_pmove.c | 104 +++++++++++++++++++++++++++++++++------ source/game/bg_public.h | 6 ++- 4 files changed, 97 insertions(+), 19 deletions(-) diff --git a/source/game/ai_dmq3.c b/source/game/ai_dmq3.c index 9c89963..d05ee68 100644 --- a/source/game/ai_dmq3.c +++ b/source/game/ai_dmq3.c @@ -919,9 +919,12 @@ void BotSetupForMovement(bot_state_t *bs) { } #endif //set the waterjump flag + // BFP - No handling PMF_TIME_WATERJUMP +#if 0 if ((bs->cur_ps.pm_flags & PMF_TIME_WATERJUMP) && (bs->cur_ps.pm_time > 0)) { initmove.or_moveflags |= MFL_WATERJUMP; } +#endif //set presence type if (bs->cur_ps.pm_flags & PMF_DUCKED) initmove.presencetype = PRESENCE_CROUCH; else initmove.presencetype = PRESENCE_NORMAL; diff --git a/source/game/be_ai_move.h b/source/game/be_ai_move.h index ddf1797..40826d7 100644 --- a/source/game/be_ai_move.h +++ b/source/game/be_ai_move.h @@ -42,7 +42,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define MFL_ONGROUND 2 //bot is in the ground #define MFL_SWIMMING 4 //bot is swimming #define MFL_AGAINSTLADDER 8 //bot is against a ladder -#define MFL_WATERJUMP 16 //bot is waterjumping +// BFP - MFL_WATERJUMP is unused +// #define MFL_WATERJUMP 16 //bot is waterjumping // BFP - MFL_TELEPORTED is unused // #define MFL_TELEPORTED 32 //bot is being teleported #define MFL_GRAPPLEPULL 64 //bot is being pulled by the grapple diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index 06e30cd..0e89826 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -56,6 +56,20 @@ int c_pmove = 0; else if ( pm->cmd.forwardmove < 0 ) { PM_ContinueTorsoAnim( TORSO_FLYB ); PM_ContinueLegsAnim( LEGS_FLYB ); } \ else { PM_ContinueTorsoAnim( TORSO_STAND ); PM_ContinueLegsAnim( LEGS_FLYIDLE ); } +// BFP - TODO: For future clean code... Macro for movement handling in the slopes, since the code looked repetitive, so this macro makes the code a bit shorter +#define SLOPES_NEARGROUND_ANIM_HANDLING() \ + if ( !pm->cmd.forwardmove && !pm->cmd.rightmove ) { PM_ContinueLegsAnim( LEGS_IDLE ); return; } \ + if ( !( pm->cmd.buttons & BUTTON_WALKING ) ) { \ + if ( pm->cmd.forwardmove < 0 ) { PM_ContinueLegsAnim( LEGS_BACK ); PM_ContinueTorsoAnim( TORSO_STAND ); } \ + else if ( pm->cmd.forwardmove > 0 \ + || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { PM_ContinueLegsAnim( LEGS_RUN ); PM_ContinueTorsoAnim( TORSO_RUN ); } \ + } else { \ + if ( pm->cmd.forwardmove < 0 ) { PM_ContinueLegsAnim( LEGS_BACK ); } \ + else if ( pm->cmd.forwardmove > 0 \ + || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { PM_ContinueLegsAnim( LEGS_WALK ); } \ + PM_ContinueTorsoAnim( TORSO_STAND ); \ + } + /* =============== PM_AddEvent @@ -439,10 +453,13 @@ static qboolean PM_CheckWaterJump( void ) { // jump out of water VectorScale (pml.forward, 200, pm->ps->velocity); - pm->ps->velocity[2] = 350; + pm->ps->velocity[2] = 250; // BFP - before 350 + // BFP - No handling PMF_TIME_WATERJUMP +#if 0 pm->ps->pm_flags |= PMF_TIME_WATERJUMP; pm->ps->pm_time = 2000; +#endif return qtrue; } @@ -463,18 +480,14 @@ static void PM_WaterJumpMove( void ) { PM_StepSlideMove( qtrue ); pm->ps->velocity[2] -= pm->ps->gravity * pml.frametime; + // BFP - No handling PMF_ALL_TIMES +#if 0 if (pm->ps->velocity[2] < 0) { // cancel as soon as we are falling down again pm->ps->pm_flags &= ~PMF_ALL_TIMES; pm->ps->pm_time = 0; } - - // BFP - Handle jumping animation when getting out of the water - if ( !( pm->ps->pm_flags & PMF_FLYING ) - && ( pm->ps->pm_flags & PMF_FALLING ) ) { - pm->ps->pm_flags &= ~PMF_FALLING; - FORCEJUMP_ANIM_HANDLING(); - } +#endif } /* @@ -491,6 +504,13 @@ static void PM_WaterMove( void ) { float scale; float vel; + // BFP - Avoid adding friction in the water while charging and flying + if ( ( ( pm->ps->pm_flags & PMF_KI_CHARGE ) + || ( pm->cmd.buttons & BUTTON_KI_CHARGE ) ) + && ( pm->ps->pm_flags & PMF_FLYING ) ) { + return; + } + if ( PM_CheckWaterJump() ) { PM_WaterJumpMove(); return; @@ -1185,7 +1205,7 @@ static void PM_GroundTrace( void ) { return; } - // BFP - Handling the PMF flag when that happens + // BFP - Handling the PMF flags when that happens pm->ps->pm_flags &= ~PMF_NEARGROUND; if ( pm->ps->pm_flags & PMF_DUCKED ) { @@ -1232,12 +1252,15 @@ static void PM_GroundTrace( void ) { pml.groundPlane = qtrue; pml.walking = qtrue; + // BFP - No handling PMF_TIME_WATERJUMP +#if 0 // hitting solid ground will end a waterjump if (pm->ps->pm_flags & PMF_TIME_WATERJUMP) { pm->ps->pm_flags &= ~PMF_TIME_WATERJUMP; // BFP: before: ~(PMF_TIME_WATERJUMP | PMF_TIME_LAND); pm->ps->pm_time = 0; } +#endif // BFP - Handle when the player isn't flying if ( pm->ps->groundEntityNum == ENTITYNUM_NONE && !( pm->ps->pm_flags & PMF_FLYING ) @@ -1642,9 +1665,10 @@ static void PM_TorsoAnimation( void ) { pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask); pml.groundTrace = trace; - if ( trace.fraction == 1.0 && !( pm->ps->pm_flags & PMF_NEARGROUND ) ) { + // BFP - Falling distantly from the ground + if ( trace.fraction == 1.0 && !( pm->ps->pm_flags & PMF_NEARGROUND ) + && !( pm->ps->pm_flags & PMF_FLYING ) ) { pm->ps->pm_flags |= PMF_NEARGROUND; - pm->ps->pm_flags &= ~PMF_FALLING; FORCEJUMP_ANIM_HANDLING(); PM_ContinueTorsoAnim( TORSO_STAND ); } @@ -1654,6 +1678,41 @@ static void PM_TorsoAnimation( void ) { PM_ContinueTorsoAnim( TORSO_STAND ); } + // BFP - That happens when the player is landing nearly + if ( !( pm->ps->pm_flags & PMF_NEARGROUND ) + && !( pm->ps->pm_flags & PMF_FLYING ) + && ( pml.groundTrace.contents & MASK_PLAYERSOLID ) ) { + + // If it's trying to crouch, then play the jump animation + if ( pm->ps->pm_flags & PMF_DUCKED ) { + pm->ps->pm_flags |= PMF_NEARGROUND; // stop here, don't change any animation + FORCEJUMP_ANIM_HANDLING(); + return; + } + + if ( !pm->cmd.forwardmove && !pm->cmd.rightmove ) { + PM_ContinueLegsAnim( LEGS_IDLE ); + return; + } + + if ( !( pm->cmd.buttons & BUTTON_WALKING ) ) { + if ( pm->cmd.forwardmove < 0 ) { + PM_ContinueLegsAnim( LEGS_BACK ); + PM_ContinueTorsoAnim( TORSO_STAND ); // BFP - Keep the torso + } else if ( pm->cmd.forwardmove > 0 || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { + PM_ContinueLegsAnim( LEGS_RUN ); + PM_ContinueTorsoAnim( TORSO_RUN ); // BFP - Keep the torso + } + } else { + if ( pm->cmd.forwardmove < 0 ) { + PM_ContinueLegsAnim( LEGS_BACK ); + } else if ( pm->cmd.forwardmove > 0 || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { + PM_ContinueLegsAnim( LEGS_WALK ); + } + PM_ContinueTorsoAnim( TORSO_STAND ); // BFP - Keep the torso + } + } + #if 0 if ( pm->ps->weaponstate == WEAPON_READY ) { if ( pm->ps->weapon == WP_GAUNTLET ) { @@ -1675,20 +1734,23 @@ static void PM_FlightAnimation( void ) { // BFP - Flight if ( ( pm->ps->pm_flags & PMF_FLYING ) && pm->ps->pm_time <= 0 ) { - // make sure to handle the PMF flag + // make sure to handle the PMF flags pm->ps->pm_flags &= ~PMF_FALLING; + pm->ps->pm_flags &= ~PMF_NEARGROUND; CONTINUEFLY_ANIM_HANDLING() return; } // Handle the player movement animation if trying to change quickly the direction of forward or backward - if ( !( pml.groundTrace.contents & MASK_PLAYERSOLID ) && !( pm->ps->pm_flags & PMF_FALLING ) ) { + if ( !( pml.groundTrace.contents & MASK_PLAYERSOLID ) + && !( pm->ps->pm_flags & PMF_FALLING ) + && !( pm->ps->pm_flags & PMF_FLYING ) ) { // stops entering again here and don't change the animation to backwards/forward pm->ps->pm_flags |= PMF_FALLING; - if ( pm->cmd.forwardmove < 0 && !( pm->ps->pm_flags & PMF_FLYING ) ) { // when failing backwards after flying + if ( pm->cmd.forwardmove < 0 ) { // when failing backwards after flying PM_StartLegsAnim( LEGS_JUMPB ); } else { PM_StartLegsAnim( LEGS_JUMP ); @@ -1726,6 +1788,7 @@ static void PM_KiChargeAnimation( void ) { // BFP - Ki Charge } if ( ( pm->ps->pm_flags & PMF_KI_CHARGE ) && !( pm->cmd.buttons & BUTTON_KI_CHARGE ) ) { + pm->ps->eFlags &= ~EF_AURA; // Make sure the aura is off, otherwise the ki use proceeds pm->ps->pm_flags &= ~PMF_KI_CHARGE; PM_ContinueLegsAnim( LEGS_IDLE ); // Keep the legs when being near to the ground at that height // do jump animation if it's falling @@ -2008,10 +2071,14 @@ PM_DropTimers static void PM_DropTimers( void ) { // drop misc timing counter if ( pm->ps->pm_time ) { + // BFP - No handling PMF_ALL_TIMES +#if 0 if ( pml.msec >= pm->ps->pm_time ) { pm->ps->pm_flags &= ~PMF_ALL_TIMES; pm->ps->pm_time = 0; - } else { + } else +#endif + { pm->ps->pm_time -= pml.msec; } } @@ -2343,9 +2410,13 @@ void PmoveSingle (pmove_t *pmove) { PM_AirMove(); } #endif + // BFP - No handling PMF_TIME_WATERJUMP +#if 0 else if (pm->ps->pm_flags & PMF_TIME_WATERJUMP) { PM_WaterJumpMove(); - } else if ( pm->waterlevel > 1 ) { + } +#endif + else if ( pm->waterlevel > 1 ) { // swimming PM_WaterMove(); } else if ( pml.walking ) { @@ -2442,4 +2513,5 @@ void Pmove (pmove_t *pmove) { // BFP - Undefine the macros #undef FORCEJUMP_ANIM_HANDLING #undef CONTINUEFLY_ANIM_HANDLING +#undef SLOPES_NEARGROUND_ANIM_HANDLING diff --git a/source/game/bg_public.h b/source/game/bg_public.h index 54abfd8..0dedc07 100644 --- a/source/game/bg_public.h +++ b/source/game/bg_public.h @@ -154,7 +154,8 @@ typedef enum { // BFP - PMF_TIME_KNOCKBACK is unused // #define PMF_TIME_KNOCKBACK 64 // pm_time is an air-accelerate only time #define PMF_KI_BOOST 128 // BFP - Using Ki -#define PMF_TIME_WATERJUMP 256 // pm_time is waterjump +// BFP - PMF_TIME_WATERJUMP is unused +// #define PMF_TIME_WATERJUMP 256 // pm_time is waterjump #define PMF_RESPAWNED 512 // clear after attack and jump buttons come up #define PMF_USE_ITEM_HELD 1024 // BFP - no hook @@ -169,7 +170,8 @@ typedef enum { // BFP - Last pm_flag after 32768. That's the limit of pm_flags, it can't reach more // #define PMF_SOMEFLAG 65536 // some pm_flag -#define PMF_ALL_TIMES (PMF_TIME_WATERJUMP) // BFP: before: (PMF_TIME_WATERJUMP|PMF_TIME_LAND|PMF_TIME_KNOCKBACK) +// BFP - That combination of PMF_TIME_* flags is unused +// #define PMF_ALL_TIMES (PMF_TIME_WATERJUMP|PMF_TIME_LAND|PMF_TIME_KNOCKBACK) #define MAXTOUCH 32 typedef struct { From fdeb290fc54d3d46bf30f1b303f89e284f7637be Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sat, 10 Feb 2024 22:59:01 +0100 Subject: [PATCH 042/374] game: Make player, when flying, stick to the movers while being close to them --- source/game/bg_pmove.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index 0e89826..c3d20d7 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -1246,6 +1246,9 @@ static void PM_GroundTrace( void ) { // BFP - NOTE: Originally, BFP doesn't stop "groundtracing" until here when the player is flying // BFP - If flying, prevent from doing a jumping action on flat ground if ( pm->ps->pm_flags & PMF_FLYING ) { + // BFP - To stick to the movers if the player is near to them + pm->ps->groundEntityNum = trace.entityNum; + PM_AddTouchEnt( trace.entityNum ); return; } @@ -1427,6 +1430,11 @@ static void PM_Footsteps( void ) { return; } + // BFP - Hit stun + if ( pm->ps->pm_flags & PMF_FLYING ) { + return; + } + // // calculate speed and cycle to be used for // all cyclic walking effects @@ -2145,17 +2153,27 @@ Enables/disables flight */ static qboolean PM_EnableFlight( void ) { // BFP - Flight + // BFP - Hit stun, avoid enabling flight if the player is in this status + if ( pm->ps->pm_flags & PMF_HITSTUN ) { + return qfalse; + } + if ( !( pm->ps->pm_flags & PMF_FLYING ) ) { return qfalse; } + // Handle the PMF flag if it's already flying + if ( ( pm->ps->pm_flags & PMF_FLYING ) && !( pm->ps->pm_flags & PMF_FALLING ) ) { + return qtrue; + } + // do not proceed to the jump event while enables the flight in the charging status if ( ( pm->ps->pm_flags & PMF_KI_CHARGE ) && ( pm->ps->pm_flags & PMF_FLYING ) ) { pm->ps->groundEntityNum = ENTITYNUM_NONE; return qfalse; } - if ( ( pm->ps->pm_flags & PMF_FLYING ) && !( pm->ps->pm_flags & PMF_HITSTUN ) ) { + if ( pm->ps->pm_flags & PMF_FLYING ) { if ( ( pml.groundTrace.contents & MASK_PLAYERSOLID ) && pm->ps->groundEntityNum != ENTITYNUM_NONE ) { // do a smooth jump animation like BFP does if ( !( pm->cmd.buttons & BUTTON_KI_CHARGE ) ) { @@ -2192,7 +2210,10 @@ static void PM_KiCharge( void ) { // BFP - Ki Charge pm->cmd.buttons &= ~( BUTTON_ATTACK | BUTTON_KI_USE | BUTTON_MELEE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ); } - pm->ps->pm_flags |= PMF_FALLING; // Handle PMF_FALLING flag + if ( !( pm->ps->pm_flags & PMF_FLYING ) ) { + pm->ps->pm_flags |= PMF_FALLING; // Handle PMF_FALLING flag + } + if ( ( pm->ps->pm_flags & PMF_KI_CHARGE ) && pm->ps->pm_time <= 0 ) { pm->ps->stats[STAT_KI]++; } From aa619e98e2f1f60880a451880b5918a4685d7837 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sun, 11 Feb 2024 01:17:13 +0100 Subject: [PATCH 043/374] game: When stopping to charge and falling near to the ground, handle the PMF flag to play the jump animation when touching a jump pad --- source/game/bg_pmove.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index c3d20d7..bb4ff1e 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -632,13 +632,6 @@ static void PM_AirMove( void ) { float scale; usercmd_t cmd; - // BFP - Avoid adding friction in the air while charging and flying - if ( ( ( pm->ps->pm_flags & PMF_KI_CHARGE ) - || ( pm->cmd.buttons & BUTTON_KI_CHARGE ) ) - && ( pm->ps->pm_flags & PMF_FLYING ) ) { - return; - } - PM_Friction(); fmove = pm->cmd.forwardmove; @@ -1430,7 +1423,7 @@ static void PM_Footsteps( void ) { return; } - // BFP - Hit stun + // BFP - Avoid when flying if ( pm->ps->pm_flags & PMF_FLYING ) { return; } @@ -1798,6 +1791,7 @@ static void PM_KiChargeAnimation( void ) { // BFP - Ki Charge if ( ( pm->ps->pm_flags & PMF_KI_CHARGE ) && !( pm->cmd.buttons & BUTTON_KI_CHARGE ) ) { pm->ps->eFlags &= ~EF_AURA; // Make sure the aura is off, otherwise the ki use proceeds pm->ps->pm_flags &= ~PMF_KI_CHARGE; + pm->ps->pm_flags &= ~PMF_NEARGROUND; // Make sure to handle the PMF flag PM_ContinueLegsAnim( LEGS_IDLE ); // Keep the legs when being near to the ground at that height // do jump animation if it's falling if ( !( pml.groundTrace.contents & MASK_PLAYERSOLID ) From 7baa1676b78387c0aa30a6840683cdbfaec8c348 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 12 Feb 2024 10:30:42 +0100 Subject: [PATCH 044/374] game: In g_active.c, shorten ent->client->ps into client->ps and replace the commented PMF_SCOREBOARD with #if 0 --- source/game/g_active.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/source/game/g_active.c b/source/game/g_active.c index 1c02367..2935917 100644 --- a/source/game/g_active.c +++ b/source/game/g_active.c @@ -732,21 +732,22 @@ void ClientThink_real( gentity_t *ent ) { client->ps.speed = g_speed.value; // BFP - Ki use has 2 options: "kiusetoggle" to toggle and "+button8" when key is being hold - // BFP - If BUTTON_KI_USE > speed - if ( !( ent->client->ps.pm_flags & PMF_HITSTUN ) + if ( !( client->ps.pm_flags & PMF_HITSTUN ) && ( ( ucmd->buttons & BUTTON_KI_USE ) // BFP - Using Ki - || ( ent->client->ps.pm_flags & PMF_KI_BOOST ) ) ) { // BFP - When "kiusetoggle" is binded, enables/disables - ent->client->ps.speed *= 2.5; - ent->client->ps.eFlags |= EF_AURA; + || ( client->ps.pm_flags & PMF_KI_BOOST ) ) ) { // BFP - When "kiusetoggle" is binded, enables/disables + if ( !( client->ps.pm_flags & PMF_FLYING ) ) { + client->ps.speed *= 2.5; + } + client->ps.eFlags |= EF_AURA; } else { if ( !( ucmd->buttons & BUTTON_KI_CHARGE ) ) { // BFP - If it's charging while it was using ki boost, don't remove the aura! - ent->client->ps.eFlags &= ~EF_AURA; + client->ps.eFlags &= ~EF_AURA; } } // BFP - Ki Charge - if ( ( ucmd->buttons & BUTTON_KI_CHARGE ) && ent->client->ps.pm_time <= 0 - && ( ent->client->ps.pm_flags & PMF_KI_CHARGE ) ) { + if ( ( ucmd->buttons & BUTTON_KI_CHARGE ) && client->ps.pm_time <= 0 + && ( client->ps.pm_flags & PMF_KI_CHARGE ) ) { client->ps.eFlags |= EF_AURA; } @@ -755,7 +756,7 @@ void ClientThink_real( gentity_t *ent ) { } // BFP - TODO: When charging a ki attack like beam wave, consult FlyingThink and SpectatorThink if that's the case - // BFP - if BUTTON_ENABLEFLIGHT enable flight + // BFP - Enable flight FlyingThink( ent, ucmd ); // prevents client-server side issues when there's other client in-game // BFP - no hook @@ -958,13 +959,13 @@ void SpectatorClientEndFrame( gentity_t *ent ) { } // BFP - PMF_SCOREBOARD is unused - /* +#if 0 if ( ent->client->sess.spectatorState == SPECTATOR_SCOREBOARD ) { ent->client->ps.pm_flags |= PMF_SCOREBOARD; } else { ent->client->ps.pm_flags &= ~PMF_SCOREBOARD; } - */ +#endif } /* From 6f7fa09c96913c7d668e93172fc0a1f78365f03f Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Wed, 14 Feb 2024 20:16:03 +0100 Subject: [PATCH 045/374] game: Add less flight acceleration, add macros for torso handling, slopes and when being near to the ground, adjust FlyMove speed and fix flying to handle correctly when being near to the ground, plus shorten the code, thanks to the macros, about the movements when the player is in the slopes and near to the ground --- source/game/bg_pmove.c | 200 +++++++++++++++++++---------------------- 1 file changed, 94 insertions(+), 106 deletions(-) diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index bb4ff1e..196a170 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -38,7 +38,7 @@ float pm_swimScale = 0.50f; float pm_accelerate = 10.0f; float pm_airaccelerate = 1.0f; float pm_wateraccelerate = 4.0f; -float pm_flyaccelerate = 8.0f; +float pm_flyaccelerate = 2.0f; // BFP - Add less flight acceleration, before 8.0f float pm_friction = 6.0f; float pm_waterfriction = 1.0f; @@ -47,27 +47,46 @@ float pm_spectatorfriction = 5.0f; int c_pmove = 0; +// BFP - TODO: Macro for torso handling, since the code looked repetitive, so this macro makes the code a bit shorter +#define TORSOSTATUS_ANIM_HANDLING(other_torsostatus) ( pm->ps->pm_flags & PMF_INVULEXPAND ) ? PM_ContinueTorsoAnim( TORSO_BLOCK ) : PM_ContinueTorsoAnim( other_torsostatus ) + // BFP - Macro for jump handling, since the code looked repetitive, so this macro makes the code a bit shorter #define FORCEJUMP_ANIM_HANDLING() ( pm->cmd.forwardmove >= 0 ) ? PM_ForceLegsAnim( LEGS_JUMP ) : PM_ForceLegsAnim( LEGS_JUMPB ) // BFP - Macro for fly handling, since the code looked repetitive, so this macro makes the code a bit shorter #define CONTINUEFLY_ANIM_HANDLING() \ - if ( pm->cmd.forwardmove > 0 ) { PM_ContinueTorsoAnim( TORSO_FLYA ); PM_ContinueLegsAnim( LEGS_FLYA ); } \ - else if ( pm->cmd.forwardmove < 0 ) { PM_ContinueTorsoAnim( TORSO_FLYB ); PM_ContinueLegsAnim( LEGS_FLYB ); } \ - else { PM_ContinueTorsoAnim( TORSO_STAND ); PM_ContinueLegsAnim( LEGS_FLYIDLE ); } - -// BFP - TODO: For future clean code... Macro for movement handling in the slopes, since the code looked repetitive, so this macro makes the code a bit shorter -#define SLOPES_NEARGROUND_ANIM_HANDLING() \ + if ( pm->cmd.forwardmove > 0 ) { TORSOSTATUS_ANIM_HANDLING( TORSO_FLYA ); PM_ContinueLegsAnim( LEGS_FLYA ); } \ + else if ( pm->cmd.forwardmove < 0 ) { TORSOSTATUS_ANIM_HANDLING( TORSO_FLYB ); PM_ContinueLegsAnim( LEGS_FLYB ); } \ + else { TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ); PM_ContinueLegsAnim( LEGS_FLYIDLE ); } + +// BFP - Macro for movement handling in the slopes and when being near to the ground, since the code looked repetitive, so this macro makes the code a bit shorter +#define SLOPES_NEARGROUND_ANIM_HANDLING(is_slope) \ + if (is_slope) { \ + if ( pm->ps->pm_flags & PMF_DUCKED ) { \ + PM_ContinueLegsAnim( LEGS_IDLECR ); \ + if ( pm->cmd.forwardmove < 0 \ + || ( pm->cmd.forwardmove > 0 \ + || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) ) { PM_ContinueLegsAnim( LEGS_WALKCR ); } \ + TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ); \ + return; \ + } \ + } else { \ + if ( pm->ps->pm_flags & PMF_DUCKED ) { \ + pm->ps->pm_flags |= PMF_NEARGROUND; \ + FORCEJUMP_ANIM_HANDLING(); \ + return; \ + } \ + } \ if ( !pm->cmd.forwardmove && !pm->cmd.rightmove ) { PM_ContinueLegsAnim( LEGS_IDLE ); return; } \ if ( !( pm->cmd.buttons & BUTTON_WALKING ) ) { \ - if ( pm->cmd.forwardmove < 0 ) { PM_ContinueLegsAnim( LEGS_BACK ); PM_ContinueTorsoAnim( TORSO_STAND ); } \ + if ( pm->cmd.forwardmove < 0 ) { PM_ContinueLegsAnim( LEGS_BACK ); TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ); } \ else if ( pm->cmd.forwardmove > 0 \ - || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { PM_ContinueLegsAnim( LEGS_RUN ); PM_ContinueTorsoAnim( TORSO_RUN ); } \ + || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { PM_ContinueLegsAnim( LEGS_RUN ); TORSOSTATUS_ANIM_HANDLING( TORSO_RUN ); } \ } else { \ if ( pm->cmd.forwardmove < 0 ) { PM_ContinueLegsAnim( LEGS_BACK ); } \ else if ( pm->cmd.forwardmove > 0 \ || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { PM_ContinueLegsAnim( LEGS_WALK ); } \ - PM_ContinueTorsoAnim( TORSO_STAND ); \ + TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ); \ } /* @@ -409,7 +428,7 @@ static qboolean PM_CheckJump( void ) { // BFP - No PMF_BACKWARDS_JUMP handling (code removed) FORCEJUMP_ANIM_HANDLING(); - PM_ContinueTorsoAnim( TORSO_STAND ); + TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ); return qtrue; } @@ -585,8 +604,6 @@ static void PM_FlyMove( void ) { float wishspeed; vec3_t wishdir; float scale; - // BFP - Flight acceleration - float flyacc; // normal slowdown PM_Friction (); @@ -599,19 +616,19 @@ static void PM_FlyMove( void ) { VectorClear( wishvel ); } else { for ( i = 0; i < 3; i++ ) { - // BFP - Before: (+ scale * pml.up[i] * pm->cmd.upmove) used when flying and moving upside/downside instead according the ground - wishvel[i] = scale * pml.forward[i] * pm->cmd.forwardmove + scale * pml.right[i] * pm->cmd.rightmove + scale * pml.up[i] * pm->cmd.upmove; + wishvel[i] = scale * pml.forward[i]*pm->cmd.forwardmove + scale * pml.right[i]*pm->cmd.rightmove; } - // wishvel[2] += scale * pm->cmd.upmove; // BFP - disabled to work the wished velocity + wishvel[2] += scale * pm->cmd.upmove; } VectorCopy (wishvel, wishdir); wishspeed = VectorNormalize(wishdir); + if ( !( pm->ps->pm_flags & PMF_INVULEXPAND ) // BFP - Don't increase the speed when blocking + && ( ( pm->ps->pm_flags & PMF_KI_BOOST ) || ( pm->cmd.buttons & BUTTON_KI_USE ) ) ) { + wishspeed *= scale; + } - // BFP - When moving during the flight, start with half acceleration - flyacc = (scale > pm_stopspeed) ? pm_flyaccelerate : pm_flyaccelerate/2; - - PM_Accelerate (wishdir, wishspeed, flyacc); + PM_Accelerate (wishdir, wishspeed, pm_flyaccelerate); PM_StepSlideMove( qfalse ); } @@ -678,6 +695,7 @@ static void PM_AirMove( void ) { else PM_SlideMove ( qtrue ); #endif + TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ); PM_StepSlideMove ( qtrue ); } @@ -1170,6 +1188,32 @@ static void PM_GroundTrace( void ) { return; } + // BFP - Make sure to handle the PMF flags when the player isn't flying + if ( !( pm->ps->pm_flags & PMF_FLYING ) ) { + pm->ps->pm_flags |= PMF_FALLING; + pm->ps->pm_flags &= ~PMF_NEARGROUND; + } + + // BFP - If the player is in the ground, then jump! + // And make sure to handle the PMF flag when the player isn't flying and falling + if ( ( pm->ps->pm_flags & PMF_FLYING ) + && ( pm->ps->pm_flags & PMF_FALLING ) + && !( pm->ps->pm_flags & PMF_NEARGROUND ) ) { + if ( pml.groundTrace.contents & MASK_PLAYERSOLID ) { + // do a smooth jump animation like BFP does + if ( !( pm->cmd.buttons & BUTTON_KI_CHARGE ) ) { + pm->ps->pm_time = 500; + } + pml.groundPlane = qfalse; // jumping away + pml.walking = qfalse; + pm->ps->velocity[2] = JUMP_VELOCITY; + PM_ForceLegsAnim( LEGS_JUMP ); + } + pm->ps->pm_flags &= ~PMF_FALLING; + pm->ps->groundEntityNum = ENTITYNUM_NONE; + return; + } + // slopes that are too steep will not be considered onground if ( trace.plane.normal[2] < MIN_WALK_NORMAL ) { if ( pm->debugLevel ) { @@ -1201,38 +1245,7 @@ static void PM_GroundTrace( void ) { // BFP - Handling the PMF flags when that happens pm->ps->pm_flags &= ~PMF_NEARGROUND; - if ( pm->ps->pm_flags & PMF_DUCKED ) { - PM_ContinueLegsAnim( LEGS_IDLECR ); - if ( pm->cmd.forwardmove < 0 - || ( pm->cmd.forwardmove > 0 - || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) ) { - PM_ContinueLegsAnim( LEGS_WALKCR ); - } - PM_ContinueTorsoAnim( TORSO_STAND ); // BFP - Keep the torso - return; - } - - if ( !pm->cmd.forwardmove && !pm->cmd.rightmove ) { - PM_ContinueLegsAnim( LEGS_IDLE ); - return; - } - - if ( !( pm->cmd.buttons & BUTTON_WALKING ) ) { - if ( pm->cmd.forwardmove < 0 ) { - PM_ContinueLegsAnim( LEGS_BACK ); - PM_ContinueTorsoAnim( TORSO_STAND ); // BFP - Keep the torso - } else if ( pm->cmd.forwardmove > 0 || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { - PM_ContinueLegsAnim( LEGS_RUN ); - PM_ContinueTorsoAnim( TORSO_RUN ); // BFP - Keep the torso - } - } else { - if ( pm->cmd.forwardmove < 0 ) { - PM_ContinueLegsAnim( LEGS_BACK ); - } else if ( pm->cmd.forwardmove > 0 || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { - PM_ContinueLegsAnim( LEGS_WALK ); - } - PM_ContinueTorsoAnim( TORSO_STAND ); // BFP - Keep the torso - } + SLOPES_NEARGROUND_ANIM_HANDLING( 1 ) return; } @@ -1242,6 +1255,7 @@ static void PM_GroundTrace( void ) { // BFP - To stick to the movers if the player is near to them pm->ps->groundEntityNum = trace.entityNum; PM_AddTouchEnt( trace.entityNum ); + pm->ps->pm_flags |= PMF_NEARGROUND; return; } @@ -1259,8 +1273,8 @@ static void PM_GroundTrace( void ) { #endif // BFP - Handle when the player isn't flying - if ( pm->ps->groundEntityNum == ENTITYNUM_NONE && !( pm->ps->pm_flags & PMF_FLYING ) - && ( pm->ps->pm_flags & PMF_NEARGROUND ) ) { + if ( pm->ps->groundEntityNum == ENTITYNUM_NONE + && !( pm->ps->pm_flags & PMF_FLYING ) ) { // just hit the ground if ( pm->debugLevel ) { Com_Printf("%i:Land\n", c_pmove); @@ -1482,7 +1496,7 @@ static void PM_Footsteps( void ) { } else if ( pm->cmd.forwardmove > 0 || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { PM_ContinueLegsAnim( LEGS_WALKCR ); } - PM_ContinueTorsoAnim( TORSO_STAND ); // BFP - Keep the torso + TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ); // BFP - Keep the torso } // ducked characters never play footsteps /* @@ -1501,10 +1515,10 @@ static void PM_Footsteps( void ) { // BFP - Replaced PMF_BACKWARDS_RUN handling if ( pm->cmd.forwardmove < 0 ) { PM_ContinueLegsAnim( LEGS_BACK ); - PM_ContinueTorsoAnim( TORSO_STAND ); // BFP - Keep the torso + TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ); // BFP - Keep the torso } else if ( pm->cmd.forwardmove > 0 || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { PM_ContinueLegsAnim( LEGS_RUN ); - PM_ContinueTorsoAnim( TORSO_RUN ); // BFP - Keep the torso + TORSOSTATUS_ANIM_HANDLING( TORSO_RUN ); // BFP - Keep the torso } footstep = qtrue; } else if ( pml.groundTrace.contents & MASK_PLAYERSOLID ) { @@ -1515,7 +1529,7 @@ static void PM_Footsteps( void ) { } else if ( pm->cmd.forwardmove > 0 || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { PM_ContinueLegsAnim( LEGS_WALK ); } - PM_ContinueTorsoAnim( TORSO_STAND ); // BFP - Keep the torso + TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ); // BFP - Keep the torso } } @@ -1650,9 +1664,9 @@ static void PM_TorsoAnimation( void ) { trace_t trace; vec3_t point; - // BFP - TODO: Melee, block and ki attack animation handling (these are for torso animations) + // BFP - TODO: Melee and ki attack animation handling (these are for torso animations) // Keep in mind about the implementations of the steep slopes, - // PM_ContinueTorsoAnim( TORSO_STAND ) and + // TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ) and // !pm->cmd.forwardmove && !pm->cmd.rightmove && !pm->cmd.buttons thingies // BFP - No ground trace handling in the water @@ -1671,47 +1685,32 @@ static void PM_TorsoAnimation( void ) { && !( pm->ps->pm_flags & PMF_FLYING ) ) { pm->ps->pm_flags |= PMF_NEARGROUND; FORCEJUMP_ANIM_HANDLING(); - PM_ContinueTorsoAnim( TORSO_STAND ); + TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ); } // If idling, keep the torso if ( !pm->cmd.forwardmove && !pm->cmd.rightmove ) { - PM_ContinueTorsoAnim( TORSO_STAND ); + TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ); + } + + // Handle the player movement animation when stopping to fly and falling near to the ground + // that happens when PMF_FALLING flag isn't handled correctly + if ( ( pml.groundTrace.contents & MASK_PLAYERSOLID ) + && !( pm->ps->pm_flags & PMF_FLYING ) + && !( pm->ps->pm_flags & PMF_FALLING ) + && ( pm->ps->pm_flags & PMF_NEARGROUND ) ) { + pm->ps->pm_flags |= PMF_FALLING; + pm->ps->pm_flags &= ~PMF_NEARGROUND; } // BFP - That happens when the player is landing nearly if ( !( pm->ps->pm_flags & PMF_NEARGROUND ) && !( pm->ps->pm_flags & PMF_FLYING ) + && pm->ps->groundEntityNum == ENTITYNUM_NONE // hasn't touched the ground yet && ( pml.groundTrace.contents & MASK_PLAYERSOLID ) ) { - // If it's trying to crouch, then play the jump animation - if ( pm->ps->pm_flags & PMF_DUCKED ) { - pm->ps->pm_flags |= PMF_NEARGROUND; // stop here, don't change any animation - FORCEJUMP_ANIM_HANDLING(); - return; - } - - if ( !pm->cmd.forwardmove && !pm->cmd.rightmove ) { - PM_ContinueLegsAnim( LEGS_IDLE ); - return; - } - - if ( !( pm->cmd.buttons & BUTTON_WALKING ) ) { - if ( pm->cmd.forwardmove < 0 ) { - PM_ContinueLegsAnim( LEGS_BACK ); - PM_ContinueTorsoAnim( TORSO_STAND ); // BFP - Keep the torso - } else if ( pm->cmd.forwardmove > 0 || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { - PM_ContinueLegsAnim( LEGS_RUN ); - PM_ContinueTorsoAnim( TORSO_RUN ); // BFP - Keep the torso - } - } else { - if ( pm->cmd.forwardmove < 0 ) { - PM_ContinueLegsAnim( LEGS_BACK ); - } else if ( pm->cmd.forwardmove > 0 || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { - PM_ContinueLegsAnim( LEGS_WALK ); - } - PM_ContinueTorsoAnim( TORSO_STAND ); // BFP - Keep the torso - } + // If it's trying to crouch, then play the jump animation once + SLOPES_NEARGROUND_ANIM_HANDLING( 0 ) } #if 0 @@ -1735,9 +1734,8 @@ static void PM_FlightAnimation( void ) { // BFP - Flight if ( ( pm->ps->pm_flags & PMF_FLYING ) && pm->ps->pm_time <= 0 ) { - // make sure to handle the PMF flags + // make sure to handle the PMF flag pm->ps->pm_flags &= ~PMF_FALLING; - pm->ps->pm_flags &= ~PMF_NEARGROUND; CONTINUEFLY_ANIM_HANDLING() return; @@ -1750,13 +1748,14 @@ static void PM_FlightAnimation( void ) { // BFP - Flight // stops entering again here and don't change the animation to backwards/forward pm->ps->pm_flags |= PMF_FALLING; + pm->ps->pm_flags &= ~PMF_NEARGROUND; if ( pm->cmd.forwardmove < 0 ) { // when failing backwards after flying PM_StartLegsAnim( LEGS_JUMPB ); } else { PM_StartLegsAnim( LEGS_JUMP ); } - PM_ContinueTorsoAnim( TORSO_STAND ); + TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ); } } @@ -1827,7 +1826,7 @@ PM_HitStunAnimation static void PM_HitStunAnimation( void ) { // BFP - Hit stun if ( pm->ps->pm_flags & PMF_HITSTUN ) { - PM_ContinueTorsoAnim( TORSO_STUN ); + PM_StartTorsoAnim( TORSO_STUN ); PM_StartLegsAnim( LEGS_IDLECR ); } @@ -2167,18 +2166,6 @@ static qboolean PM_EnableFlight( void ) { // BFP - Flight return qfalse; } - if ( pm->ps->pm_flags & PMF_FLYING ) { - if ( ( pml.groundTrace.contents & MASK_PLAYERSOLID ) && pm->ps->groundEntityNum != ENTITYNUM_NONE ) { - // do a smooth jump animation like BFP does - if ( !( pm->cmd.buttons & BUTTON_KI_CHARGE ) ) { - pm->ps->pm_time = 500; - } - pm->ps->velocity[2] = JUMP_VELOCITY; - PM_ForceLegsAnim( LEGS_JUMP ); - } - pm->ps->groundEntityNum = ENTITYNUM_NONE; - } - return qtrue; } @@ -2526,6 +2513,7 @@ void Pmove (pmove_t *pmove) { } // BFP - Undefine the macros +#undef TORSOSTATUS_ANIM_HANDLING #undef FORCEJUMP_ANIM_HANDLING #undef CONTINUEFLY_ANIM_HANDLING #undef SLOPES_NEARGROUND_ANIM_HANDLING From fb2a33ce7b4647d53fbd92f0df1a175f5c143d2f Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sun, 3 Mar 2024 23:58:10 +0100 Subject: [PATCH 046/374] cgame - game: Fix client visuals about flight, ki boost, dash smoke and antigrav rock particles; now PW_FLIGHT and PW_HASTE are reused for flight and ki boost statuses. Disable (remove) unused EF flags: EF_KAMIKAZE and EF_AWARD_DENIED, disable unused particle functions and types, add events for later and apply some cleanup in the code --- source/cgame/cg_event.c | 52 +- source/cgame/cg_local.h | 19 +- source/cgame/cg_main.c | 6 +- source/cgame/cg_particles.c | 994 ++++++++++++++++++++---------------- source/cgame/cg_players.c | 150 +++--- source/cgame/cg_view.c | 4 +- source/game/bg_pmove.c | 58 +-- source/game/bg_public.h | 33 +- source/game/g_active.c | 53 +- source/game/g_client.c | 6 +- source/game/g_cmds.c | 12 +- source/game/g_combat.c | 7 +- source/game/g_items.c | 3 + source/game/g_target.c | 17 + 14 files changed, 805 insertions(+), 609 deletions(-) diff --git a/source/cgame/cg_event.c b/source/cgame/cg_event.c index bcad970..35826aa 100644 --- a/source/cgame/cg_event.c +++ b/source/cgame/cg_event.c @@ -541,6 +541,8 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { case EV_JUMP_PAD: DEBUGNAME("EV_JUMP_PAD"); // CG_Printf( "EV_JUMP_PAD w/effect #%i\n", es->eventParm ); +// BFP - No smoke puff effect when using a jump pad +#if 0 { localEntity_t *smoke; vec3_t up = {0, 0, 1}; @@ -554,6 +556,7 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { LEF_PUFF_DONT_SCALE, cgs.media.smokePuffShader ); } +#endif // boing sound at origin, jump sound on player trap_S_StartSound ( cent->lerpOrigin, -1, CHAN_VOICE, cgs.media.jumpPadSound ); @@ -563,7 +566,7 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { case EV_JUMP: DEBUGNAME("EV_JUMP"); // BFP - Use the second jump sound when using ki boost only when it isn't flying - if ( ( es->eFlags & EF_AURA ) && !( cg.predictedPlayerState.pm_flags & PMF_FLYING ) ) { + if ( ( es->eFlags & EF_AURA ) && !( cent->currentState.powerups & ( 1 << PW_FLIGHT ) ) ) { trap_S_StartSound (NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "sound/bfp/jump2.wav" ) ); // BFP - Ki boost jump sound } else { trap_S_StartSound (NULL, es->number, CHAN_VOICE, CG_CustomSound( es->number, "sound/bfp/jump1.wav" ) ); // BFP - Normal jump sound @@ -674,6 +677,43 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { CG_FireWeapon( cent ); break; + case EV_MELEE_READY: + // DEBUGNAME("EV_MELEE_READY"); + break; + + // BFP - TODO: Implement EV_MELEE (when punching someone using Melee) + case EV_MELEE: + DEBUGNAME("EV_MELEE"); + break; + + // BFP - TODO: Implement EV_TIER_0-4 (Tiers) + case EV_TIER_0: + DEBUGNAME("EV_TIER_0"); + break; + + case EV_TIER_1: + DEBUGNAME("EV_TIER_1"); + break; + + case EV_TIER_2: + DEBUGNAME("EV_TIER_2"); + break; + + case EV_TIER_3: + DEBUGNAME("EV_TIER_3"); + break; + + case EV_TIER_4: + DEBUGNAME("EV_TIER_4"); + break; + // BFP - TODO: Implement EV_TIER_0-4 (Tiers) ^ + + // BFP - A normal jump sound is played when enables the flight + case EV_ENABLE_FLIGHT: + // DEBUGNAME("EV_ENABLE_FLIGHT"); + trap_S_StartSound (NULL, es->number, CHAN_BODY, CG_CustomSound( es->number, "sound/bfp/jump1.wav" ) ); + break; + case EV_USE_ITEM0: DEBUGNAME("EV_USE_ITEM0"); CG_UseItem( cent ); @@ -796,6 +836,11 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { CG_MissileHitWall( es->weapon, 0, position, dir, IMPACTSOUND_METAL ); break; + // BFP - TODO: Implement EV_MISSILE_DETONATE (it has been used on ki grenade bounces and ki disc, that happens when these explode after some time) + case EV_MISSILE_DETONATE: + DEBUGNAME("EV_MISSILE_DETONATE"); + break; + case EV_RAILTRAIL: DEBUGNAME("EV_RAILTRAIL"); cent->currentState.weapon = WP_RAILGUN; @@ -990,9 +1035,10 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { // don't play gib sound when using the kamikaze because it interferes // with the kamikaze sound, downside is that the gib sound will also // not be played when someone is gibbed while just carrying the kamikaze - if ( !(es->eFlags & EF_KAMIKAZE) ) { + // BFP - No EF_KAMIKAZE flag + // if ( !(es->eFlags & EF_KAMIKAZE) ) { trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.gibSound ); - } + // } CG_GibPlayer( cent->lerpOrigin ); break; diff --git a/source/cgame/cg_local.h b/source/cgame/cg_local.h index 92ebf7e..ba60bbd 100644 --- a/source/cgame/cg_local.h +++ b/source/cgame/cg_local.h @@ -1486,22 +1486,27 @@ qboolean trap_GetEntityToken( char *buffer, int bufferSize ); void CG_ClearParticles (void); void CG_AddParticles (void); -void CG_ParticleSnow (qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb, float range, int snum); void CG_ParticleSmoke (qhandle_t pshader, centity_t *cent); -void CG_AddParticleShrapnel (localEntity_t *le); -void CG_ParticleSnowFlurry (qhandle_t pshader, centity_t *cent); void CG_ParticleBulletDebris (vec3_t org, vec3_t vel, int duration); void CG_ParticleSparks (vec3_t org, vec3_t vel, int duration, float x, float y, float speed); void CG_ParticleDust (centity_t *cent, vec3_t origin, vec3_t dir); void CG_ParticleMisc (qhandle_t pshader, vec3_t origin, int size, int duration, float alpha); void CG_ParticleExplosion (char *animStr, vec3_t origin, vec3_t vel, int duration, int sizeStart, int sizeEnd); // BFP - Bubble particle -void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb, float range, int snum); +void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb, float range, int snum); // BFP - Dash smoke particle for ki boost when moving in the ground -void CG_ParticleDashSmoke (centity_t *cent, qhandle_t pshader, vec3_t origin); +void CG_ParticleDashSmoke (centity_t *cent, qhandle_t pshader, vec3_t origin); // BFP - Antigrav rock particles for charging -void CG_ParticleAntigravRock (qhandle_t pshader, centity_t *cent, vec3_t origin); +void CG_ParticleAntigravRock (qhandle_t pshader, centity_t *cent, vec3_t origin); +void CG_AntigravRockHandling (centity_t *cent); + +// BFP - Unused particle stuff, saved for later :P +#if 0 +void CG_ParticleSnow (qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb, float range, int snum); +void CG_ParticleSnowFlurry (qhandle_t pshader, centity_t *cent); +int CG_NewParticleArea ( int num ); // BFP - Unused function for particles, looks like here is to determine in the areas +#endif + extern qboolean initparticles; -int CG_NewParticleArea ( int num ); diff --git a/source/cgame/cg_main.c b/source/cgame/cg_main.c index e1f50c2..7d656b1 100644 --- a/source/cgame/cg_main.c +++ b/source/cgame/cg_main.c @@ -684,7 +684,9 @@ static void CG_RegisterGraphics( void ) { } CG_ClearParticles (); -/* + +// BFP - Unused function for particles, looks like here is to determine in the areas +#if 0 for (i=1; itype == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY) {// create a front facing polygon @@ -212,7 +216,6 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) p->org[2] += (p->start - p->end); } - if (p->type == P_WEATHER_TURBULENT) { p->vel[0] = crandom() * 16; @@ -264,7 +267,9 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) TRIverts[2].modulate[2] = 255; TRIverts[2].modulate[3] = 255 * p->alpha; } - else if (p->type == P_SPRITE) + // else if ... +#endif + if (p->type == P_SPRITE) { vec3_t rr, ru; vec3_t rotate_ang; @@ -342,9 +347,12 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) || p->type == P_ANTIGRAV_ROCK) // BFP - Added antigrav rock type {// create a front rotating facing polygon +// BFP - No smoke distance +#if 0 if ( p->type == P_SMOKE_IMPACT && Distance( cg.snap->ps.origin, org ) > 1024) { return; } +#endif if (p->color == BLOODRED) VectorSet (color, 0.22f, 0.0f, 0.0f); @@ -412,13 +420,30 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) // BFP - Bubble types here if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) { + // BFP - Apply less end time to remove particles if the player is still charging + if (p->type == P_BUBBLE) { + if ( ( cg.snap->ps.eFlags & EF_AURA ) + && ( cg.snap->ps.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE + && !p->link ) + { + p->endtime = timenonscaled + 400; + p->link = qtrue; + } + if ( ( cg.snap->ps.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_CHARGE + && p->link ) + { + p->endtime = timenonscaled + 2000 + (crandom() * 150); + p->link = qfalse; + } + } + if (org[2] > p->end) { p->time = timenonscaled; VectorCopy (org, p->org); // Ridah, fixes rare snow flakes that flicker on the ground // BFP - Stop shivering, before: ( p->start + crandom () * 4 ) - p->org[2] = ( p->start ); + p->org[2] = ( p->start - p->end ); // BFP - Make move less if (p->type == P_BUBBLE_TURBULENT) { @@ -434,31 +459,32 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) // BFP - Antigrav rock type if (p->type == P_ANTIGRAV_ROCK) { - // BFP - To detect if there is something solid - trace_t trace; - CG_Trace( &trace, p->org, vec3_origin, vec3_origin, org, -1, MASK_PLAYERSOLID ); - - // BFP - Make each particle fall when they aren't on ki charging status - if ( !( cg.snap->ps.pm_flags & PMF_KI_CHARGE ) && !p->link ) { - p->endtime = timenonscaled + 1650; - p->link = qtrue; - } - // BFP - When the particle, checked to be fallen, won't be reactivated when entering ki charging status again - if (p->link) { + if (p->link) + { + // BFP - To detect if there is something solid + trace_t trace; + // contents should be MASK_DEADSOLID, so the particles don't touch any entity like the player + CG_Trace( &trace, p->org, vec3_origin, vec3_origin, org, -1, MASK_DEADSOLID ); + p->time = timenonscaled; + p->snum = 1; // handle the p->snum when already entered in this phase for correction of client side visuals + p->vel[0] = 0; + p->vel[1] = 0; + p->accel[0] = 0; + p->accel[1] = 0; // not hit anything or not a collider if ( trace.fraction == 1.0f && p->roll > 0 ) { VectorCopy (org, p->org); - p->vel[2] -= 30; + p->vel[2] -= 50; p->accel[2] -= 200; } else // bouncing { // BFP - TODO: Temporary solution... Make bouncing more interactive when there's a mover moving - if ( trace.fraction <= 0 // if the particle is touching a mover and moves down, so keep bouncing - && cg.snap->ps.groundEntityNum != ENTITYNUM_NONE ) { + // if the particle is touching a mover and moves down, so keep bouncing + if ( trace.fraction <= 0 ) { p->roll = 10; } else { p->vel[2] = p->accel[2] = (p->roll > 0) ? 50 * p->roll : 0; @@ -466,6 +492,13 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) } } } + + // BFP - When reaching into this top, remove the particle! + if (org[2] > p->end) + { + p->next = NULL; + p->type = p->color = p->alpha = p->snum = 0; + } } if (p->rotate) @@ -601,6 +634,7 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) verts[3].modulate[3] = 255 * alpha; } +#if 0 /* // BFP - Unused particle type conditionals */ else if (p->type == P_FLAT_SCALEUP) { float width, height; @@ -711,6 +745,7 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) verts[3].modulate[3] = 255; } +#endif // Ridah else if (p->type == P_ANIM) { vec3_t rr, ru; @@ -804,9 +839,11 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) return; } +#if 0 /* // BFP - Unused particle type conditionals */ if (p->type == P_WEATHER || p->type == P_WEATHER_TURBULENT || p->type == P_WEATHER_FLURRY) trap_R_AddPolyToScene( p->pshader, 3, TRIverts ); else +#endif trap_R_AddPolyToScene( p->pshader, 4, verts ); } @@ -866,7 +903,9 @@ void CG_AddParticles (void) } if (p->type == P_SMOKE || p->type == P_ANIM || p->type == P_BLEED || p->type == P_SMOKE_IMPACT +#if 0 /* // BFP - Unused particle type conditionals */ || p->type == P_WEATHER_FLURRY || p->type == P_FLAT_SCALEUP_FADE +#endif || p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT // BFP - Add P_BUBBLE types to remove particles || p->type == P_ANTIGRAV_ROCK) // BFP - Add P_ANTIGRAV_ROCK to remove particles { @@ -874,7 +913,7 @@ void CG_AddParticles (void) { p->next = free_particles; free_particles = p; - p->type = p->color = p->alpha = 0; + p->type = p->color = p->alpha = p->snum = 0; continue; } } @@ -916,131 +955,6 @@ void CG_AddParticles (void) active_particles = active; } -void CG_ParticleSnowFlurry (qhandle_t pshader, centity_t *cent) -{ - cparticle_t *p; - qboolean turb = qtrue; - - if (!pshader) - CG_Printf ("CG_ParticleSnowFlurry pshader == ZERO!\n"); - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - p->time = timenonscaled; - p->color = 0; - p->alpha = 0.90f; - p->alphavel = 0; - - p->start = cent->currentState.origin2[0]; - p->end = cent->currentState.origin2[1]; - - p->endtime = timenonscaled + cent->currentState.time; - p->startfade = timenonscaled + cent->currentState.time2; - - p->pshader = pshader; - - if (rand()%100 > 90) - { - p->height = 32; - p->width = 32; - p->alpha = 0.10f; - } - else - { - p->height = 1; - p->width = 1; - } - - p->vel[2] = -20; - - p->type = P_WEATHER_FLURRY; - - if (turb) - p->vel[2] = -10; - - VectorCopy(cent->currentState.origin, p->org); - - p->org[0] = p->org[0]; - p->org[1] = p->org[1]; - p->org[2] = p->org[2]; - - p->vel[0] = p->vel[1] = 0; - - p->accel[0] = p->accel[1] = p->accel[2] = 0; - - p->vel[0] += cent->currentState.angles[0] * 32 + (crandom() * 16); - p->vel[1] += cent->currentState.angles[1] * 32 + (crandom() * 16); - p->vel[2] += cent->currentState.angles[2]; - - if (turb) - { - p->accel[0] = crandom () * 16; - p->accel[1] = crandom () * 16; - } - -} - -void CG_ParticleSnow (qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb, float range, int snum) -{ - cparticle_t *p; - - if (!pshader) - CG_Printf ("CG_ParticleSnow pshader == ZERO!\n"); - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - p->time = timenonscaled; - p->color = 0; - p->alpha = 0.40f; - p->alphavel = 0; - p->start = origin[2]; - p->end = origin2[2]; - p->pshader = pshader; - p->height = 1; - p->width = 1; - - p->vel[2] = -50; - - if (turb) - { - p->type = P_WEATHER_TURBULENT; - p->vel[2] = -50 * 1.3; - } - else - { - p->type = P_WEATHER; - } - - VectorCopy(origin, p->org); - - p->org[0] = p->org[0] + ( crandom() * range); - p->org[1] = p->org[1] + ( crandom() * range); - p->org[2] = p->org[2] + ( crandom() * (p->start - p->end)); - - p->vel[0] = p->vel[1] = 0; - - p->accel[0] = p->accel[1] = p->accel[2] = 0; - - if (turb) - { - p->vel[0] = crandom() * 16; - p->vel[1] = crandom() * 16; - } - - // Rafael snow pvs check - p->snum = snum; - p->link = qtrue; - -} - void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb, float range, int snum) { cparticle_t *p; @@ -1056,7 +970,7 @@ void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_ p->time = timenonscaled; // BFP - Add end time to remove particles, if there's no end time the particles will remain there - p->endtime = timenonscaled + 1250 + (crandom() * 20); + p->endtime = timenonscaled + 2000 + (crandom() * 150); p->startfade = timenonscaled + 200; p->color = 0; @@ -1091,7 +1005,7 @@ void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_ VectorSet( p->vel, (rand() % 801) - 400, (rand() % 801) - 400, - 20 ); + 40 ); // dispersion VectorSet( p->accel, @@ -1108,62 +1022,84 @@ void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_ // Rafael snow pvs check p->snum = snum; - p->link = qtrue; + p->link = qfalse; } -void CG_ParticleSmoke (qhandle_t pshader, centity_t *cent) +// BFP - Particle for dash smoke when using ki boost and moving in the ground +void CG_ParticleDashSmoke (centity_t *cent, qhandle_t pshader, vec3_t origin) { - - // using cent->density = enttime - // cent->frame = startfade cparticle_t *p; - if (!pshader) - CG_Printf ("CG_ParticleSmoke == ZERO!\n"); + // if (!pshader) CG_Printf ("CG_ParticleDashSmoke pshader == ZERO!\n"); + + // Too much smoke... + // That cent->trailTime can be handled to avoid spawning too much and only spawn when the game isn't paused, hehehe :P + if ( cent->trailTime > cg.time ) { + return; + } + cent->trailTime += 50; + if ( cent->trailTime < cg.time ) { + cent->trailTime = cg.time; + } if (!free_particles) return; + p = free_particles; free_particles = p->next; p->next = active_particles; active_particles = p; + p->time = timenonscaled; - - p->endtime = timenonscaled + cent->currentState.time; - p->startfade = timenonscaled + cent->currentState.time2; - - p->color = 0; - p->alpha = 1.0; - p->alphavel = 0; + + p->alpha = 0.45; + p->alphavel = -0.1; + + p->pshader = pshader; p->start = cent->currentState.origin[2]; p->end = cent->currentState.origin2[2]; - p->pshader = pshader; - p->rotate = qfalse; - p->height = 8; - p->width = 8; - p->endheight = 32; - p->endwidth = 32; - p->type = P_SMOKE; - - VectorCopy(cent->currentState.origin, p->org); - p->vel[0] = p->vel[1] = 0; - p->accel[0] = p->accel[1] = p->accel[2] = 0; + p->endtime = timenonscaled + 2000; + p->startfade = timenonscaled + 100; - p->vel[2] = 5; + p->height = p->width = 25; - if (cent->currentState.frame == 1)// reverse gravity - p->vel[2] *= -1; + p->endheight = p->height * 2; + p->endwidth = p->width * 2; - p->roll = 8 + (crandom() * 4); -} + p->type = P_SMOKE_IMPACT; + + VectorCopy( origin, p->org ); + VectorSet( p->vel, + (rand() % 401) - 200, + (rand() % 401) - 200, + 20 ); + // dispersion + VectorSet( p->accel, + crandom() * 10, + crandom() * 10, + 1400 ); +} -void CG_ParticleBulletDebris (vec3_t org, vec3_t vel, int duration) +// BFP - Antigrav rock particles for ki charging status +void CG_ParticleAntigravRock (qhandle_t pshader, centity_t *cent, vec3_t origin) { - cparticle_t *p; + // if (!pshader) CG_Printf ("CG_ParticleAntigravRock == ZERO!\n"); + + // Too many rocks... That cent->dustTrailTime can be handled to avoid spawning too many, hehehe :P + // cent->dustTrailTime was unused on Q3 before, so now it's being used for this kind of particles + // reusing cent->trailTime would make the time more delayed to spawn the particles, so not visually good + if ( cent->dustTrailTime > timenonscaled ) { + return; + } + cent->dustTrailTime += 20; + if ( cent->dustTrailTime < timenonscaled ) { + cent->dustTrailTime = timenonscaled; + } + if (!free_particles) return; p = free_particles; @@ -1171,31 +1107,163 @@ void CG_ParticleBulletDebris (vec3_t org, vec3_t vel, int duration) p->next = active_particles; active_particles = p; p->time = timenonscaled; - - p->endtime = timenonscaled + duration; - p->startfade = timenonscaled + duration/2; - - p->color = EMISIVEFADE; - p->alpha = 1.0; - p->alphavel = 0; - p->height = 0.5; - p->width = 0.5; - p->endheight = 0.5; - p->endwidth = 0.5; + p->endtime = timenonscaled + 450 + (crandom() * 20); - p->pshader = cgs.media.tracerShader; + p->color = 0; + p->alpha = 1; + p->alphavel = 0; + p->pshader = pshader; + p->height = p->width = 2 + (crandom() * 0.5); + p->type = P_ANTIGRAV_ROCK; - p->type = P_SMOKE; - - VectorCopy(org, p->org); + VectorCopy( origin, p->org ); - p->vel[0] = vel[0]; - p->vel[1] = vel[1]; - p->vel[2] = vel[2]; - p->accel[0] = p->accel[1] = p->accel[2] = 0; + p->org[0] += (crandom() * 50); + p->org[1] += (crandom() * 50); - p->accel[2] = -60; + p->start = cent->currentState.origin[2]; + // maybe BFP used to debug the client side visual of the other player with this top limit + p->end = (cent->currentState.clientNum != cg.snap->ps.clientNum) + ? p->org[2] + 130 + (crandom() * 10) + : p->org[2] + 170 + (crandom() * 10); + + p->vel[0] = 0; + p->vel[1] = 0; + // maybe BFP used to debug the client side visual of the other player with this velocity + p->vel[2] = (cent->currentState.clientNum != cg.snap->ps.clientNum) + ? 200 + : 470; + + p->accel[0] = 0; + p->accel[1] = 0; + // maybe BFP used to debug the client side visual of the other player with this acceleration + p->accel[2] = (cent->currentState.clientNum != cg.snap->ps.clientNum) + ? 10 + : 20; + + p->roll = 5; // used as bounce counter + p->link = qfalse; // to handle the ki charging status + p->snum = 0; // to handle the client side visuals +} + +// BFP - To handle the client side visuals of antigrav rock particles +void CG_AntigravRockHandling (centity_t *cent) +{ + cparticle_t *p, *next; + + for (p=active_particles ; p ; p=next) + { + next = p->next; + if (p->type == P_ANTIGRAV_ROCK) + { + if ( cent->currentState.clientNum == cg.snap->ps.clientNum + && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_CHARGE ) + { + // BFP - Make each particle fall when they aren't on ki charging status + if (!p->link && !p->snum) // to handle the client side visuals + { + p->endtime = timenonscaled + 1650; + p->link = qtrue; + } + } + // if the player sees the other player doing that, the handling is different from itself, + // to correct the client side visuals in this case + if ( cent->currentState.clientNum != cg.snap->ps.clientNum + && ( cent->currentState.eFlags & EF_AURA ) + && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE + && !p->snum ) { // use p->snum to handle the client side visual of the other player + p->link = qfalse; // keep this way, otherwise the rocks fall + } + } + } +} + + +void CG_ParticleSmoke (qhandle_t pshader, centity_t *cent) +{ + + // using cent->density = enttime + // cent->frame = startfade + cparticle_t *p; + + // if (!pshader) CG_Printf ("CG_ParticleSmoke == ZERO!\n"); + + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + p->time = timenonscaled; + + p->endtime = timenonscaled + cent->currentState.time; + p->startfade = timenonscaled + cent->currentState.time2; + + p->color = 0; + p->alpha = 1.0; + p->alphavel = 0; + p->start = cent->currentState.origin[2]; + p->end = cent->currentState.origin2[2]; + p->pshader = pshader; + p->rotate = qfalse; + p->height = 8; + p->width = 8; + p->endheight = 32; + p->endwidth = 32; + p->type = P_SMOKE; + + VectorCopy(cent->currentState.origin, p->org); + + p->vel[0] = p->vel[1] = 0; + p->accel[0] = p->accel[1] = p->accel[2] = 0; + + p->vel[2] = 5; + + if (cent->currentState.frame == 1)// reverse gravity + p->vel[2] *= -1; + + p->roll = 8 + (crandom() * 4); +} + + +void CG_ParticleBulletDebris (vec3_t org, vec3_t vel, int duration) +{ + + cparticle_t *p; + + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + p->time = timenonscaled; + + p->endtime = timenonscaled + duration; + p->startfade = timenonscaled + duration/2; + + p->color = EMISIVEFADE; + p->alpha = 1.0; + p->alphavel = 0; + + p->height = 0.5; + p->width = 0.5; + p->endheight = 0.5; + p->endwidth = 0.5; + + p->pshader = cgs.media.tracerShader; + + p->type = P_SMOKE; + + VectorCopy(org, p->org); + + p->vel[0] = vel[0]; + p->vel[1] = vel[1]; + p->vel[2] = vel[2]; + p->accel[0] = p->accel[1] = p->accel[2] = 0; + + p->accel[2] = -60; p->vel[2] += -20; } @@ -1205,7 +1273,6 @@ void CG_ParticleBulletDebris (vec3_t org, vec3_t vel, int duration) CG_ParticleExplosion ====================== */ - void CG_ParticleExplosion (char *animStr, vec3_t origin, vec3_t vel, int duration, int sizeStart, int sizeEnd) { cparticle_t *p; @@ -1259,13 +1326,193 @@ void CG_ParticleExplosion (char *animStr, vec3_t origin, vec3_t vel, int duratio } -// Rafael Shrapnel -void CG_AddParticleShrapnel (localEntity_t *le) +void CG_ParticleSparks (vec3_t org, vec3_t vel, int duration, float x, float y, float speed) { - return; + cparticle_t *p; + + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + p->time = timenonscaled; + + p->endtime = timenonscaled + duration; + p->startfade = timenonscaled + duration/2; + + p->color = EMISIVEFADE; + p->alpha = 0.4f; + p->alphavel = 0; + + p->height = 0.5; + p->width = 0.5; + p->endheight = 0.5; + p->endwidth = 0.5; + + p->pshader = cgs.media.tracerShader; + + p->type = P_SMOKE; + + VectorCopy(org, p->org); + + p->org[0] += (crandom() * x); + p->org[1] += (crandom() * y); + + p->vel[0] = vel[0]; + p->vel[1] = vel[1]; + p->vel[2] = vel[2]; + + p->accel[0] = p->accel[1] = p->accel[2] = 0; + + p->vel[0] += (crandom() * 4); + p->vel[1] += (crandom() * 4); + p->vel[2] += (20 + (crandom() * 10)) * speed; + + p->accel[0] = crandom () * 4; + p->accel[1] = crandom () * 4; + } -// done. +void CG_ParticleDust (centity_t *cent, vec3_t origin, vec3_t dir) +{ + float length; + float dist; + float crittersize; + vec3_t angles, forward; + vec3_t point; + cparticle_t *p; + int i; + + dist = 0; + + VectorNegate (dir, dir); + length = VectorLength (dir); + vectoangles (dir, angles); + AngleVectors (angles, forward, NULL, NULL); + + crittersize = LARGESIZE; + + if (length) + dist = length / crittersize; + + if (dist < 1) + dist = 1; + + VectorCopy (origin, point); + + for (i=0; inext; + p->next = active_particles; + active_particles = p; + + p->time = timenonscaled; + p->alpha = 5.0; + p->alphavel = 0; + p->roll = 0; + + p->pshader = cgs.media.smokePuffShader; + + // RF, stay around for long enough to expand and dissipate naturally + if (length) + p->endtime = timenonscaled + 4500 + (crandom() * 3500); + else + p->endtime = timenonscaled + 750 + (crandom() * 500); + + p->startfade = timenonscaled; + + p->width = LARGESIZE; + p->height = LARGESIZE; + + // RF, expand while falling + p->endheight = LARGESIZE*3.0; + p->endwidth = LARGESIZE*3.0; + + if (!length) + { + p->width *= 0.2f; + p->height *= 0.2f; + + p->endheight = NORMALSIZE; + p->endwidth = NORMALSIZE; + } + + p->type = P_SMOKE; + + VectorCopy( point, p->org ); + + p->vel[0] = crandom()*6; + p->vel[1] = crandom()*6; + p->vel[2] = random()*20; + + // RF, add some gravity/randomness + p->accel[0] = crandom()*3; + p->accel[1] = crandom()*3; + p->accel[2] = -PARTICLE_GRAVITY*0.4; + + VectorClear( p->accel ); + + p->rotate = qfalse; + + p->roll = rand()%179; + + p->alpha = 0.75; + + } + + +} + +void CG_ParticleMisc (qhandle_t pshader, vec3_t origin, int size, int duration, float alpha) +{ + cparticle_t *p; + + // if (!pshader) CG_Printf ("CG_ParticleImpactSmokePuff pshader == ZERO!\n"); + + if (!free_particles) + return; + + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + p->time = timenonscaled; + p->alpha = 1.0; + p->alphavel = 0; + p->roll = rand()%179; + + p->pshader = pshader; + + if (duration > 0) + p->endtime = timenonscaled + duration; + else + p->endtime = duration; + + p->startfade = timenonscaled; + + p->width = size; + p->height = size; + + p->endheight = size; + p->endwidth = size; + + p->type = P_SPRITE; + + VectorCopy( origin, p->org ); + + p->rotate = qfalse; +} + +// BFP - Unused function for particles, looks like here is to determine in the areas +// CG_SnowLink was never used in Q3 +#if 0 int CG_NewParticleArea (int num) { // const char *str; @@ -1351,60 +1598,83 @@ void CG_SnowLink (centity_t *cent, qboolean particleOn) } } +#endif -// BFP - Particle for dash smoke when using ki boost and moving in the ground -void CG_ParticleDashSmoke (centity_t *cent, qhandle_t pshader, vec3_t origin) + +// BFP - Unused particle stuff, saved for later :P +#if 0 +void CG_ParticleSnowFlurry (qhandle_t pshader, centity_t *cent) { cparticle_t *p; + qboolean turb = qtrue; - // if (!pshader) CG_Printf ("CG_ParticleDashSmoke pshader == ZERO!\n"); + // if (!pshader) CG_Printf ("CG_ParticleSnowFlurry pshader == ZERO!\n"); if (!free_particles) return; - p = free_particles; free_particles = p->next; p->next = active_particles; active_particles = p; - p->time = timenonscaled; + p->color = 0; + p->alpha = 0.90f; + p->alphavel = 0; - p->alpha = 0.45; - p->alphavel = -0.1; - + p->start = cent->currentState.origin2[0]; + p->end = cent->currentState.origin2[1]; + + p->endtime = timenonscaled + cent->currentState.time; + p->startfade = timenonscaled + cent->currentState.time2; + p->pshader = pshader; - p->start = cent->currentState.origin[2]; - p->end = cent->currentState.origin2[2]; + + if (rand()%100 > 90) + { + p->height = 32; + p->width = 32; + p->alpha = 0.10f; + } + else + { + p->height = 1; + p->width = 1; + } - p->endtime = timenonscaled + 2000; - p->startfade = timenonscaled + 100; + p->vel[2] = -20; - p->height = p->width = 25; + p->type = P_WEATHER_FLURRY; + + if (turb) + p->vel[2] = -10; + + VectorCopy(cent->currentState.origin, p->org); - p->endheight = p->height * 2; - p->endwidth = p->width * 2; + p->org[0] = p->org[0]; + p->org[1] = p->org[1]; + p->org[2] = p->org[2]; + + p->vel[0] = p->vel[1] = 0; + + p->accel[0] = p->accel[1] = p->accel[2] = 0; - p->type = P_SMOKE_IMPACT; + p->vel[0] += cent->currentState.angles[0] * 32 + (crandom() * 16); + p->vel[1] += cent->currentState.angles[1] * 32 + (crandom() * 16); + p->vel[2] += cent->currentState.angles[2]; - VectorCopy( origin, p->org ); - VectorSet( p->vel, - (rand() % 401) - 200, - (rand() % 401) - 200, - 20 ); + if (turb) + { + p->accel[0] = crandom () * 16; + p->accel[1] = crandom () * 16; + } - // dispersion - VectorSet( p->accel, - crandom() * 10, - crandom() * 10, - 1400 ); } -// BFP - Antigrav rock particles for ki charging status -void CG_ParticleAntigravRock (qhandle_t pshader, centity_t *cent, vec3_t origin) +void CG_ParticleSnow (qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb, float range, int snum) { cparticle_t *p; - // if (!pshader) CG_Printf ("CG_ParticleAntigravRock == ZERO!\n"); + // if (!pshader) CG_Printf ("CG_ParticleSnow pshader == ZERO!\n"); if (!free_particles) return; @@ -1413,40 +1683,54 @@ void CG_ParticleAntigravRock (qhandle_t pshader, centity_t *cent, vec3_t origin) p->next = active_particles; active_particles = p; p->time = timenonscaled; - - p->endtime = timenonscaled + 450 + (crandom() * 20); - p->startfade = timenonscaled + 200; - p->roll = 5; // used as bounce counter - p->link = qfalse; // to handle the ki charging status - p->color = 0; - p->alpha = 1; + p->alpha = 0.40f; p->alphavel = 0; - p->start = cent->currentState.origin[2]; - p->end = cent->currentState.origin2[2]; + p->start = origin[2]; + p->end = origin2[2]; p->pshader = pshader; - p->height = p->width = 2 + (crandom() * 0.5); - p->type = P_ANTIGRAV_ROCK; + p->height = 1; + p->width = 1; + + p->vel[2] = -50; - VectorCopy( origin, p->org ); + if (turb) + { + p->type = P_WEATHER_TURBULENT; + p->vel[2] = -50 * 1.3; + } + else + { + p->type = P_WEATHER; + } + + VectorCopy(origin, p->org); - p->org[0] += (crandom() * 40); - p->org[1] += (crandom() * 40); + p->org[0] = p->org[0] + ( crandom() * range); + p->org[1] = p->org[1] + ( crandom() * range); + p->org[2] = p->org[2] + ( crandom() * (p->start - p->end)); p->vel[0] = p->vel[1] = 0; - p->accel[0] = p->accel[1] = 0; + + p->accel[0] = p->accel[1] = p->accel[2] = 0; + + if (turb) + { + p->vel[0] = crandom() * 16; + p->vel[1] = crandom() * 16; + } + + // Rafael snow pvs check + p->snum = snum; + p->link = qtrue; - p->vel[2] = 20; - p->accel[2] = 1000; } -#if 0 void CG_ParticleImpactSmokePuff (qhandle_t pshader, vec3_t origin) { cparticle_t *p; - if (!pshader) - CG_Printf ("CG_ParticleImpactSmokePuff pshader == ZERO!\n"); + // if (!pshader) CG_Printf ("CG_ParticleImpactSmokePuff pshader == ZERO!\n"); if (!free_particles) return; @@ -1485,8 +1769,7 @@ void CG_Particle_Bleed (qhandle_t pshader, vec3_t start, vec3_t dir, int fleshEn { cparticle_t *p; - if (!pshader) - CG_Printf ("CG_Particle_Bleed pshader == ZERO!\n"); + // if (!pshader) CG_Printf ("CG_Particle_Bleed pshader == ZERO!\n"); if (!free_particles) return; @@ -1546,8 +1829,7 @@ void CG_Particle_OilParticle (qhandle_t pshader, centity_t *cent) ratio =(float)1 - ((float)time / (float)time2); - if (!pshader) - CG_Printf ("CG_Particle_OilParticle == ZERO!\n"); + // if (!pshader) CG_Printf ("CG_Particle_OilParticle == ZERO!\n"); if (!free_particles) return; @@ -1599,8 +1881,7 @@ void CG_Particle_OilSlick (qhandle_t pshader, centity_t *cent) { cparticle_t *p; - if (!pshader) - CG_Printf ("CG_Particle_OilSlick == ZERO!\n"); + // if (!pshader) CG_Printf ("CG_Particle_OilSlick == ZERO!\n"); if (!free_particles) return; @@ -1742,8 +2023,7 @@ void CG_BloodPool (localEntity_t *le, qhandle_t pshader, trace_t *tr) vec3_t start; float rndSize; - if (!pshader) - CG_Printf ("CG_BloodPool pshader == ZERO!\n"); + // if (!pshader) CG_Printf ("CG_BloodPool pshader == ZERO!\n"); if (!free_particles) return; @@ -1872,187 +2152,3 @@ void CG_ParticleBloodCloud (centity_t *cent, vec3_t origin, vec3_t dir) } #endif - -void CG_ParticleSparks (vec3_t org, vec3_t vel, int duration, float x, float y, float speed) -{ - cparticle_t *p; - - if (!free_particles) - return; - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - p->time = timenonscaled; - - p->endtime = timenonscaled + duration; - p->startfade = timenonscaled + duration/2; - - p->color = EMISIVEFADE; - p->alpha = 0.4f; - p->alphavel = 0; - - p->height = 0.5; - p->width = 0.5; - p->endheight = 0.5; - p->endwidth = 0.5; - - p->pshader = cgs.media.tracerShader; - - p->type = P_SMOKE; - - VectorCopy(org, p->org); - - p->org[0] += (crandom() * x); - p->org[1] += (crandom() * y); - - p->vel[0] = vel[0]; - p->vel[1] = vel[1]; - p->vel[2] = vel[2]; - - p->accel[0] = p->accel[1] = p->accel[2] = 0; - - p->vel[0] += (crandom() * 4); - p->vel[1] += (crandom() * 4); - p->vel[2] += (20 + (crandom() * 10)) * speed; - - p->accel[0] = crandom () * 4; - p->accel[1] = crandom () * 4; - -} - -void CG_ParticleDust (centity_t *cent, vec3_t origin, vec3_t dir) -{ - float length; - float dist; - float crittersize; - vec3_t angles, forward; - vec3_t point; - cparticle_t *p; - int i; - - dist = 0; - - VectorNegate (dir, dir); - length = VectorLength (dir); - vectoangles (dir, angles); - AngleVectors (angles, forward, NULL, NULL); - - crittersize = LARGESIZE; - - if (length) - dist = length / crittersize; - - if (dist < 1) - dist = 1; - - VectorCopy (origin, point); - - for (i=0; inext; - p->next = active_particles; - active_particles = p; - - p->time = timenonscaled; - p->alpha = 5.0; - p->alphavel = 0; - p->roll = 0; - - p->pshader = cgs.media.smokePuffShader; - - // RF, stay around for long enough to expand and dissipate naturally - if (length) - p->endtime = timenonscaled + 4500 + (crandom() * 3500); - else - p->endtime = timenonscaled + 750 + (crandom() * 500); - - p->startfade = timenonscaled; - - p->width = LARGESIZE; - p->height = LARGESIZE; - - // RF, expand while falling - p->endheight = LARGESIZE*3.0; - p->endwidth = LARGESIZE*3.0; - - if (!length) - { - p->width *= 0.2f; - p->height *= 0.2f; - - p->endheight = NORMALSIZE; - p->endwidth = NORMALSIZE; - } - - p->type = P_SMOKE; - - VectorCopy( point, p->org ); - - p->vel[0] = crandom()*6; - p->vel[1] = crandom()*6; - p->vel[2] = random()*20; - - // RF, add some gravity/randomness - p->accel[0] = crandom()*3; - p->accel[1] = crandom()*3; - p->accel[2] = -PARTICLE_GRAVITY*0.4; - - VectorClear( p->accel ); - - p->rotate = qfalse; - - p->roll = rand()%179; - - p->alpha = 0.75; - - } - - -} - -void CG_ParticleMisc (qhandle_t pshader, vec3_t origin, int size, int duration, float alpha) -{ - cparticle_t *p; - - // if (!pshader) CG_Printf ("CG_ParticleImpactSmokePuff pshader == ZERO!\n"); - - if (!free_particles) - return; - - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - p->time = timenonscaled; - p->alpha = 1.0; - p->alphavel = 0; - p->roll = rand()%179; - - p->pshader = pshader; - - if (duration > 0) - p->endtime = timenonscaled + duration; - else - p->endtime = duration; - - p->startfade = timenonscaled; - - p->width = size; - p->height = size; - - p->endheight = size; - p->endwidth = size; - - p->type = P_SPRITE; - - VectorCopy( origin, p->org ); - - p->rotate = qfalse; -} diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index 520e995..fbcb11d 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -1440,10 +1440,10 @@ static void CG_PlayerAngles( centity_t *cent, vec3_t legs[3], vec3_t torso[3], v dest = headAngles[PITCH] * 0.75f; } // BFP - When flying, set the legs in the first case - if ( cg.predictedPlayerState.pm_flags & PMF_FLYING ) { + if ( cent->currentState.powerups & ( 1 << PW_FLIGHT ) ) { CG_SwingAngles( dest, 15, 30, 0.1f, ¢->pe.legs.pitchAngle, ¢->pe.legs.pitching ); legsAngles[PITCH] = cent->pe.legs.pitchAngle; - } + } else if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE ) {} // BFP - When flying, set the torso correctly into these angles CG_SwingAngles( dest, 30, 30, 0.1f, ¢->pe.torso.pitchAngle, ¢->pe.torso.pitching ); @@ -1460,8 +1460,6 @@ static void CG_PlayerAngles( centity_t *cent, vec3_t legs[3], vec3_t torso[3], v // --------- roll ------------- - // BFP - TODO: Make forward and backwards movements smooth when starting to move - // lean towards the direction of travel VectorCopy( cent->currentState.pos.trDelta, velocity ); speed = VectorNormalize( velocity ); @@ -1482,10 +1480,12 @@ static void CG_PlayerAngles( centity_t *cent, vec3_t legs[3], vec3_t torso[3], v side = speed * DotProduct( velocity, axis[0] ); legsAngles[PITCH] += side; - // BFP - Make the torso move the pitch angle a bit - AnglesToAxis( torsoAngles, axis ); - side = speed * DotProduct( velocity, axis[0] ); - torsoAngles[PITCH] += side; + // BFP - Make the torso move the pitch angle a bit in the flight + if ( cent->currentState.powerups & ( 1 << PW_FLIGHT ) ) { + AnglesToAxis( torsoAngles, axis ); + side = speed * DotProduct( velocity, axis[0] ); + torsoAngles[PITCH] += side; + } } // BFP - Don't make every player forced to see this way with their legs to the others @@ -1516,40 +1516,32 @@ static void CG_PlayerAngles( centity_t *cent, vec3_t legs[3], vec3_t torso[3], v //========================================================================== +// BFP - No smoke puff effect +#if 0 /* =============== CG_HasteTrail =============== */ -static void CG_HasteTrail( centity_t *cent, vec3_t endPos ) { // BFP - Second parameter added for smoke particles - // BFP - No smoke puff effect -#if 0 +static void CG_HasteTrail( centity_t *cent ) { localEntity_t *smoke; vec3_t origin; int anim; -#endif if ( cent->trailTime > cg.time ) { return; } - // BFP - No handling running and backwards animations -#if 0 + anim = cent->pe.legs.animationNumber & ~ANIM_TOGGLEBIT; if ( anim != LEGS_RUN && anim != LEGS_BACK ) { return; } -#endif - cent->trailTime += 50; // BFP - Before: += 100 + cent->trailTime += 100; if ( cent->trailTime < cg.time ) { cent->trailTime = cg.time; } - // BFP - Apply dash smoke particle for the trail, if the function were used directly, it would generate too many particles than we expected - CG_ParticleDashSmoke( cent, cgs.media.particleSmokeShader, endPos ); - - // BFP - No smoke puff effect -#if 0 VectorCopy( cent->lerpOrigin, origin ); origin[2] -= 16; @@ -1564,8 +1556,8 @@ static void CG_HasteTrail( centity_t *cent, vec3_t endPos ) { // BFP - Second pa // use the optimized local entity add smoke->leType = LE_SCALE_FADE; -#endif } +#endif /* =============== @@ -1871,15 +1863,6 @@ static qboolean CG_PlayerShadow( centity_t *cent, float *shadowPlane ) { *shadowPlane = 0; - if ( cg_shadows.integer == 0 ) { - return qfalse; - } - - // no shadows when invisible - if ( cent->currentState.powerups & ( 1 << PW_INVIS ) ) { - return qfalse; - } - // send a trace down from the player to the ground VectorCopy( cent->lerpOrigin, end ); end[2] -= SHADOW_DISTANCE; @@ -1891,44 +1874,59 @@ static qboolean CG_PlayerShadow( centity_t *cent, float *shadowPlane ) { // BFP - Dash smoke and bubble particles when using ki boost on the ground or above the water contents = CG_PointContents( trace.endpos, -1 ); if ( cent->currentState.eFlags & EF_AURA ) { - if ( !( cg.snap->ps.pm_flags & PMF_KI_CHARGE ) && - ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_RUN + if ( !( cent->currentState.powerups & ( 1 << PW_HASTE ) ) + && ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_RUN || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_BACK || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYA || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYB ) ) { - if ( ( !( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) - && trace.fraction <= 0.70f ) + if ( !( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) + && ( trace.fraction <= 0.70f // If the player is stepping a mover: - || cg.snap->ps.groundEntityNum != ENTITYNUM_NONE ) { - CG_HasteTrail( cent, trace.endpos ); - } else if ( waterTrace.fraction >= 0.10f && waterTrace.fraction <= 0.70f ) { - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, waterTrace.endpos, end, 1, 0, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, waterTrace.endpos, end, 1, 0, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, waterTrace.endpos, end, 1, 0, 0 ); + || cent->currentState.groundEntityNum != ENTITYNUM_NONE ) ) { + // BFP - Apply dash smoke particle for the trail, if the function were used directly, it would generate too many particles than we expected + CG_ParticleDashSmoke( cent, cgs.media.particleSmokeShader, trace.endpos ); } - } else if ( ( cg.snap->ps.pm_flags & PMF_KI_CHARGE ) // BFP - Antigrav rock particles on ki charging status - && ( ( !( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) - && trace.fraction <= 0.50f ) - // If the player is stepping a mover: - || cg.snap->ps.groundEntityNum != ENTITYNUM_NONE ) ) { - // BFP - Spawn randomly the antigrav rock shaders with the particles - int shaderIndex = rand() % 3; - switch ( shaderIndex ) { - case 0: { - CG_ParticleAntigravRock( cgs.media.pebbleShader1, cent, trace.endpos ); - break; - } - case 1: { - CG_ParticleAntigravRock( cgs.media.pebbleShader2, cent, trace.endpos ); - break; - } - default: { - CG_ParticleAntigravRock( cgs.media.pebbleShader3, cent, trace.endpos ); + + if ( waterTrace.fraction >= 0.10f && waterTrace.fraction <= 0.70f ) { + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, waterTrace.endpos, end, 1, 10, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, waterTrace.endpos, end, 1, 10, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, waterTrace.endpos, end, 1, 10, 0 ); + } + } + + if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE ) { // BFP - Antigrav rock particles on ki charging status + if ( !( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) + && ( trace.fraction <= 0.30f + // If the player is stepping a mover: + || cent->currentState.groundEntityNum != ENTITYNUM_NONE ) ) { + // BFP - Spawn randomly the antigrav rock shaders with the particles + int shaderIndex = rand() % 3; + switch ( shaderIndex ) { + case 0: { + CG_ParticleAntigravRock( cgs.media.pebbleShader1, cent, trace.endpos ); + break; + } + case 1: { + CG_ParticleAntigravRock( cgs.media.pebbleShader2, cent, trace.endpos ); + break; + } + default: { + CG_ParticleAntigravRock( cgs.media.pebbleShader3, cent, trace.endpos ); + } } } } } + if ( cg_shadows.integer == 0 ) { + return qfalse; + } + + // no shadows when invisible + if ( cent->currentState.powerups & ( 1 << PW_INVIS ) ) { + return qfalse; + } + // no shadow if too high if ( trace.fraction == 1.0 || trace.startsolid || trace.allsolid ) { return qfalse; @@ -2073,7 +2071,8 @@ void CG_AddRefEntityWithPowerups( refEntity_t *ent, entityState_t *state, int te // BFP - If the player is using lightweight auras or their own small aura if ( ( state->eFlags & EF_AURA ) && ( cg_lightweightAuras.integer > 0 - || cg_smallOwnAura.integer > 0 ) ) { + || ( state->clientNum == cg.snap->ps.clientNum + && cg_smallOwnAura.integer > 0 ) ) ) { // BFP - TODO: If player is transformed: // ent->customShader = cgs.media.auraYellowShader; @@ -2197,7 +2196,7 @@ void CG_Player( centity_t *cent ) { // get the player model information renderfx = 0; - if ( cent->currentState.number == cg.snap->ps.clientNum ) { + if ( clientNum == cg.snap->ps.clientNum ) { if (!cg.renderingThirdPerson) { renderfx = RF_THIRD_PERSON; // only draw in mirrors } /*else { // BFP - cg_cameraMode cvar doesn't exist @@ -2227,6 +2226,9 @@ void CG_Player( centity_t *cent ) { // add the shadow shadow = CG_PlayerShadow( cent, &shadowPlane ); + // BFP - Handle the antigrav rock particles when the player is charging + CG_AntigravRockHandling( cent ); + // add a water splash if partially in and out of water CG_PlayerSplash( cent ); @@ -2338,9 +2340,11 @@ void CG_Player( centity_t *cent ) { } // Macro for the dynamic aura light, note: when charging it changes the shinning a bit + // Aura lights like cg_smallOwnAura only can be shown to itself and not the other clients, + // the other clients only show small lights #define AURA_LIGHT(r, g, b) \ if ( cg_lightAuras.integer > 0 ) { \ - if ( cg_smallOwnAura.integer > 0 ) { \ + if ( clientNum == cg.snap->ps.clientNum && cg_smallOwnAura.integer > 0 ) { \ trap_R_AddLightToScene( cent->lerpOrigin, 200, r, g, b ); \ trap_R_AddLightToScene( cent->lerpOrigin, 200, r, g, b ); \ if ( !( cg.predictedPlayerState.pm_flags & PMF_KI_CHARGE ) ) { \ @@ -2356,7 +2360,7 @@ void CG_Player( centity_t *cent ) { trap_R_AddLightToScene( cent->lerpOrigin, 100 + (rand()&100), r, g, b ); \ trap_R_AddLightToScene( cent->lerpOrigin, 100 + (rand()&100), r, g, b ); \ } \ - } else if ( cg_lightweightAuras.integer > 0 || cg_polygonAura.integer > 0 || cg_highPolyAura.integer > 0 ) { \ + } else if ( clientNum != cg.snap->ps.clientNum || cg_lightweightAuras.integer > 0 || cg_polygonAura.integer > 0 || cg_highPolyAura.integer > 0 ) { \ trap_R_AddLightToScene( cent->lerpOrigin, 50 + (rand()&100), r, g, b ); \ trap_R_AddLightToScene( cent->lerpOrigin, 50 + (rand()&100), r, g, b ); \ trap_R_AddLightToScene( cent->lerpOrigin, 50 + (rand()&100), r, g, b ); \ @@ -2391,17 +2395,19 @@ void CG_Player( centity_t *cent ) { if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYA || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYB ) { - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 1, 0, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 1, 0, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 1, 0, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 1, 10, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 1, 10, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 1, 10, 0 ); } else if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE ) { bubbleOrigin[2] += -10; // put the origin a little below - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 0, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 0, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 0, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 0, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 0, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); } } @@ -2445,7 +2451,7 @@ void CG_Player( centity_t *cent ) { VectorCopy( aura2.origin, aura2.oldorigin ); // don't positionally lerp at all // Ki boost and ki charge sounds - if ( ( cent->currentState.torsoAnim & ~ANIM_TOGGLEBIT ) == TORSO_CHARGE ) { + if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE ) { trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, cgs.media.kiChargeSound ); } else { diff --git a/source/cgame/cg_view.c b/source/cgame/cg_view.c index e620fc8..7aa4933 100644 --- a/source/cgame/cg_view.c +++ b/source/cgame/cg_view.c @@ -339,9 +339,9 @@ static void CG_OffsetThirdPersonView( void ) { rightAngled = LERP( lastRightAngled, 0.0f, (float)(cg.frametime / 1000.00f) * 20.0f ); upAngled = LERP( lastUpAngled, 0.0f, (float)(cg.frametime / 1000.00f) * 20.0f ); - if ( cg_flytilt.integer >= 1 + if ( cg_flytilt.integer > 0 && ( cg.predictedPlayerState.eFlags & EF_AURA ) - && ( cg.predictedPlayerState.pm_flags & PMF_FLYING ) + && cg.predictedPlayerState.powerups[PW_FLIGHT] > 0 && !( cg.predictedPlayerState.pm_flags & PMF_KI_CHARGE ) ) { if ( cmd.rightmove < 0 ) { // Left focusAngles[ROLL] = LERP( lastAngled, -20.0f, (float)(cg.frametime / 1000.00f) * 15.0f ); diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index 196a170..5703e9d 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -252,7 +252,7 @@ static void PM_Friction( void ) { // apply flying friction // BFP - Flight - if ( pm->ps->pm_flags & PMF_FLYING ) { + if ( pm->ps->powerups[PW_FLIGHT] > 0 ) { control = speed < pm_stopspeed ? pm_stopspeed : speed; drop += control*pm_flightfriction*pml.frametime; } @@ -526,7 +526,7 @@ static void PM_WaterMove( void ) { // BFP - Avoid adding friction in the water while charging and flying if ( ( ( pm->ps->pm_flags & PMF_KI_CHARGE ) || ( pm->cmd.buttons & BUTTON_KI_CHARGE ) ) - && ( pm->ps->pm_flags & PMF_FLYING ) ) { + && pm->ps->powerups[PW_FLIGHT] > 0 ) { return; } @@ -624,7 +624,7 @@ static void PM_FlyMove( void ) { VectorCopy (wishvel, wishdir); wishspeed = VectorNormalize(wishdir); if ( !( pm->ps->pm_flags & PMF_INVULEXPAND ) // BFP - Don't increase the speed when blocking - && ( ( pm->ps->pm_flags & PMF_KI_BOOST ) || ( pm->cmd.buttons & BUTTON_KI_USE ) ) ) { + && ( pm->ps->powerups[PW_HASTE] > 0 || ( pm->cmd.buttons & BUTTON_KI_USE ) ) ) { wishspeed *= scale; } @@ -1189,14 +1189,14 @@ static void PM_GroundTrace( void ) { } // BFP - Make sure to handle the PMF flags when the player isn't flying - if ( !( pm->ps->pm_flags & PMF_FLYING ) ) { + if ( pm->ps->powerups[PW_FLIGHT] <= 0 ) { pm->ps->pm_flags |= PMF_FALLING; pm->ps->pm_flags &= ~PMF_NEARGROUND; } // BFP - If the player is in the ground, then jump! // And make sure to handle the PMF flag when the player isn't flying and falling - if ( ( pm->ps->pm_flags & PMF_FLYING ) + if ( pm->ps->powerups[PW_FLIGHT] > 0 && ( pm->ps->pm_flags & PMF_FALLING ) && !( pm->ps->pm_flags & PMF_NEARGROUND ) ) { if ( pml.groundTrace.contents & MASK_PLAYERSOLID ) { @@ -1226,7 +1226,7 @@ static void PM_GroundTrace( void ) { pml.walking = qfalse; // BFP - If flying, prevent from doing a jumping action on slopes - if ( pm->ps->pm_flags & PMF_FLYING ) { + if ( pm->ps->powerups[PW_FLIGHT] > 0 ) { return; } @@ -1251,7 +1251,7 @@ static void PM_GroundTrace( void ) { // BFP - NOTE: Originally, BFP doesn't stop "groundtracing" until here when the player is flying // BFP - If flying, prevent from doing a jumping action on flat ground - if ( pm->ps->pm_flags & PMF_FLYING ) { + if ( pm->ps->powerups[PW_FLIGHT] > 0 ) { // BFP - To stick to the movers if the player is near to them pm->ps->groundEntityNum = trace.entityNum; PM_AddTouchEnt( trace.entityNum ); @@ -1274,7 +1274,7 @@ static void PM_GroundTrace( void ) { // BFP - Handle when the player isn't flying if ( pm->ps->groundEntityNum == ENTITYNUM_NONE - && !( pm->ps->pm_flags & PMF_FLYING ) ) { + && pm->ps->powerups[PW_FLIGHT] <= 0 ) { // just hit the ground if ( pm->debugLevel ) { Com_Printf("%i:Land\n", c_pmove); @@ -1438,7 +1438,7 @@ static void PM_Footsteps( void ) { } // BFP - Avoid when flying - if ( pm->ps->pm_flags & PMF_FLYING ) { + if ( pm->ps->powerups[PW_FLIGHT] > 0 ) { return; } @@ -1578,7 +1578,7 @@ static void PM_WaterEvents( void ) { // FIXME? if (pml.previous_waterlevel && !pm->waterlevel) { PM_AddEvent( EV_WATER_LEAVE ); // BFP - Handle jumping animation when getting out of the water - if ( !( pm->ps->pm_flags & PMF_FLYING ) + if ( pm->ps->powerups[PW_FLIGHT] <= 0 && ( pm->ps->pm_flags & PMF_FALLING ) ) { pm->ps->pm_flags &= ~PMF_FALLING; FORCEJUMP_ANIM_HANDLING(); @@ -1682,7 +1682,7 @@ static void PM_TorsoAnimation( void ) { // BFP - Falling distantly from the ground if ( trace.fraction == 1.0 && !( pm->ps->pm_flags & PMF_NEARGROUND ) - && !( pm->ps->pm_flags & PMF_FLYING ) ) { + && pm->ps->powerups[PW_FLIGHT] <= 0 ) { pm->ps->pm_flags |= PMF_NEARGROUND; FORCEJUMP_ANIM_HANDLING(); TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ); @@ -1696,7 +1696,7 @@ static void PM_TorsoAnimation( void ) { // Handle the player movement animation when stopping to fly and falling near to the ground // that happens when PMF_FALLING flag isn't handled correctly if ( ( pml.groundTrace.contents & MASK_PLAYERSOLID ) - && !( pm->ps->pm_flags & PMF_FLYING ) + && pm->ps->powerups[PW_FLIGHT] <= 0 && !( pm->ps->pm_flags & PMF_FALLING ) && ( pm->ps->pm_flags & PMF_NEARGROUND ) ) { pm->ps->pm_flags |= PMF_FALLING; @@ -1705,7 +1705,7 @@ static void PM_TorsoAnimation( void ) { // BFP - That happens when the player is landing nearly if ( !( pm->ps->pm_flags & PMF_NEARGROUND ) - && !( pm->ps->pm_flags & PMF_FLYING ) + && pm->ps->powerups[PW_FLIGHT] <= 0 && pm->ps->groundEntityNum == ENTITYNUM_NONE // hasn't touched the ground yet && ( pml.groundTrace.contents & MASK_PLAYERSOLID ) ) { @@ -1732,7 +1732,7 @@ PM_FlightAnimation */ static void PM_FlightAnimation( void ) { // BFP - Flight - if ( ( pm->ps->pm_flags & PMF_FLYING ) && pm->ps->pm_time <= 0 ) { + if ( pm->ps->powerups[PW_FLIGHT] > 0 && pm->ps->pm_time <= 0 ) { // make sure to handle the PMF flag pm->ps->pm_flags &= ~PMF_FALLING; @@ -1744,7 +1744,7 @@ static void PM_FlightAnimation( void ) { // BFP - Flight // Handle the player movement animation if trying to change quickly the direction of forward or backward if ( !( pml.groundTrace.contents & MASK_PLAYERSOLID ) && !( pm->ps->pm_flags & PMF_FALLING ) - && !( pm->ps->pm_flags & PMF_FLYING ) ) { + && pm->ps->powerups[PW_FLIGHT] <= 0 ) { // stops entering again here and don't change the animation to backwards/forward pm->ps->pm_flags |= PMF_FALLING; @@ -1777,7 +1777,7 @@ static void PM_KiChargeAnimation( void ) { // BFP - Ki Charge pm->ps->pm_time = 0; // do jump animation if it's falling if ( !( pml.groundTrace.contents & MASK_PLAYERSOLID ) - && !( pm->ps->pm_flags & PMF_FLYING ) + && pm->ps->powerups[PW_FLIGHT] <= 0 && ( pm->ps->pm_flags & PMF_FALLING ) && pm->waterlevel <= 1 ) { // Don't force inside the water pm->ps->pm_flags &= ~PMF_FALLING; // Handle PMF_FALLING when falling @@ -1806,15 +1806,15 @@ static void PM_KiChargeAnimation( void ) { // BFP - Ki Charge if ( !( pm->ps->pm_flags & PMF_KI_CHARGE ) ) { pm->ps->pm_time = 300; } - pm->ps->pm_flags &= ~PMF_KI_BOOST; + pm->ps->powerups[PW_HASTE] = 0; pm->ps->pm_flags |= PMF_KI_CHARGE; PM_ContinueTorsoAnim( TORSO_CHARGE ); PM_ContinueLegsAnim( LEGS_CHARGE ); } // handle the button to avoid toggling ki boost when already used "kiusetoggle" key bind - if ( ( pm->cmd.buttons & BUTTON_KI_USE ) && ( pm->ps->pm_flags & PMF_KI_BOOST ) ) { - pm->ps->pm_flags &= ~PMF_KI_BOOST; + if ( ( pm->cmd.buttons & BUTTON_KI_USE ) && ( pm->ps->powerups[PW_HASTE] > 0 ) ) { + pm->ps->powerups[PW_HASTE] = 0; } } @@ -1832,7 +1832,7 @@ static void PM_HitStunAnimation( void ) { // BFP - Hit stun // When the player doesn't have more ki, play hit stun animation if ( pm->ps->stats[STAT_KI] <= 0 && !( pm->ps->pm_flags & PMF_HITSTUN ) - || ( ( pm->ps->pm_flags & PMF_FLYING ) && pm->ps->stats[STAT_KI] <= 24 ) // BFP - TODO: Apply some timer if used any ki, if flying and has less ki, then hit stun (also BFP does that) + || ( pm->ps->powerups[PW_FLIGHT] > 0 && pm->ps->stats[STAT_KI] <= 24 ) // BFP - TODO: Apply some timer if used any ki, if flying and has less ki, then hit stun (also BFP does that) || ( ( pm->cmd.buttons & BUTTON_ATTACK ) && ( pm->ps->pm_flags & PMF_HITSTUN ) ) ) { pm->ps->pm_time = 1000; pm->ps->pm_flags |= PMF_HITSTUN; @@ -2123,7 +2123,7 @@ void PM_UpdateViewAngles( playerState_t *ps, const usercmd_t *cmd ) { // circularly clamp the angles with deltas for (i=0 ; i<3 ; i++) { temp = cmd->angles[i] + ps->delta_angles[i]; - if ( i == PITCH && !( ps->pm_flags & PMF_FLYING ) ) { // BFP - Avoid that when flying + if ( i == PITCH && ps->powerups[PW_FLIGHT] <= 0 ) { // BFP - Avoid that when flying // don't let the player look up or down more than 90 degrees if ( temp > 16000 ) { ps->delta_angles[i] = 16000 - cmd->angles[i]; @@ -2151,17 +2151,17 @@ static qboolean PM_EnableFlight( void ) { // BFP - Flight return qfalse; } - if ( !( pm->ps->pm_flags & PMF_FLYING ) ) { + if ( pm->ps->powerups[PW_FLIGHT] <= 0 ) { return qfalse; } // Handle the PMF flag if it's already flying - if ( ( pm->ps->pm_flags & PMF_FLYING ) && !( pm->ps->pm_flags & PMF_FALLING ) ) { + if ( pm->ps->powerups[PW_FLIGHT] > 0 && !( pm->ps->pm_flags & PMF_FALLING ) ) { return qtrue; } // do not proceed to the jump event while enables the flight in the charging status - if ( ( pm->ps->pm_flags & PMF_KI_CHARGE ) && ( pm->ps->pm_flags & PMF_FLYING ) ) { + if ( ( pm->ps->pm_flags & PMF_KI_CHARGE ) && pm->ps->powerups[PW_FLIGHT] > 0 ) { pm->ps->groundEntityNum = ENTITYNUM_NONE; return qfalse; } @@ -2191,7 +2191,7 @@ static void PM_KiCharge( void ) { // BFP - Ki Charge pm->cmd.buttons &= ~( BUTTON_ATTACK | BUTTON_KI_USE | BUTTON_MELEE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ); } - if ( !( pm->ps->pm_flags & PMF_FLYING ) ) { + if ( pm->ps->powerups[PW_FLIGHT] <= 0 ) { pm->ps->pm_flags |= PMF_FALLING; // Handle PMF_FALLING flag } @@ -2213,8 +2213,8 @@ static void PM_HitStun( void ) { // BFP - Hit stun pm->cmd.buttons &= ~( BUTTON_MELEE | BUTTON_KI_USE | BUTTON_KI_CHARGE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ); } - pm->ps->pm_flags &= ~PMF_FLYING; - pm->ps->pm_flags &= ~PMF_KI_BOOST; + pm->ps->powerups[PW_FLIGHT] = 0; + pm->ps->powerups[PW_HASTE] = 0; pm->ps->eFlags &= ~EF_AURA; // BFP - NOTE: BFP doesn't handle nothing the button directions when there's hit stun @@ -2332,8 +2332,8 @@ void PmoveSingle (pmove_t *pmove) { if ( pm->ps->pm_type >= PM_DEAD ) { // BFP - If player is dead, disable the following statuses - pm->ps->pm_flags &= ~PMF_FLYING; - pm->ps->pm_flags &= ~PMF_KI_BOOST; + pm->ps->powerups[PW_FLIGHT] = 0; + pm->ps->powerups[PW_HASTE] = 0; pm->ps->eFlags &= ~EF_AURA; // BFP - NOTE: disabled for notes, don't allow pressing these buttons diff --git a/source/game/bg_public.h b/source/game/bg_public.h index 0dedc07..02f3900 100644 --- a/source/game/bg_public.h +++ b/source/game/bg_public.h @@ -142,7 +142,6 @@ typedef enum { // pmove->pm_flags #define PMF_DUCKED 1 #define PMF_JUMP_HELD 2 -#define PMF_FLYING 4 // BFP - Flight // BFP - PMF_BACKWARDS_JUMP is unused // #define PMF_BACKWARDS_JUMP 8 // go into backwards land #define PMF_NEARGROUND 8 // BFP - Near ground check @@ -153,7 +152,7 @@ typedef enum { #define PMF_FALLING 32 // BFP - Falling status // BFP - PMF_TIME_KNOCKBACK is unused // #define PMF_TIME_KNOCKBACK 64 // pm_time is an air-accelerate only time -#define PMF_KI_BOOST 128 // BFP - Using Ki +#define PMF_KI_CHARGE 128 // BFP - Ki charge // BFP - PMF_TIME_WATERJUMP is unused // #define PMF_TIME_WATERJUMP 256 // pm_time is waterjump #define PMF_RESPAWNED 512 // clear after attack and jump buttons come up @@ -164,7 +163,6 @@ typedef enum { #define PMF_FOLLOW 4096 // spectate following another player // BFP - PMF_SCOREBOARD is unused // #define PMF_SCOREBOARD 8192 // spectate as a scoreboard -#define PMF_KI_CHARGE 8192 // BFP - Ki charge // BFP - TODO: Reuse the following flag (used on Team Arena), change name if it'll be used #define PMF_INVULEXPAND 16384 // invulnerability sphere set to full size // BFP - Last pm_flag after 32768. That's the limit of pm_flags, it can't reach more @@ -264,7 +262,8 @@ typedef enum { #define EF_AWARD_GAUNTLET 0x00000040 // draw a gauntlet sprite #define EF_NODRAW 0x00000080 // may have an event, but no model (unspawned items) #define EF_FIRING 0x00000100 // for lightning gun -#define EF_KAMIKAZE 0x00000200 +// BFP - No EF_KAMIKAZE flag +// #define EF_KAMIKAZE 0x00000200 #define EF_MOVER_STOP 0x00000400 // will push otherwise #define EF_AWARD_CAP 0x00000800 // draw the capture sprite #define EF_TALK 0x00001000 // draw a talk balloon @@ -273,22 +272,20 @@ typedef enum { #define EF_AWARD_IMPRESSIVE 0x00008000 // draw an impressive sprite #define EF_AWARD_DEFEND 0x00010000 // draw a defend sprite #define EF_AWARD_ASSIST 0x00020000 // draw a assist sprite -#define EF_AWARD_DENIED 0x00040000 // denied +// BFP - Unused EF flag +// #define EF_AWARD_DENIED 0x00040000 // denied #define EF_TEAMVOTED 0x00080000 // already cast a team vote -// BFP - NOTE: Should use PW_* instead using pm_flags? -// That goes for PW_HASTE and PW_FLIGHT, instead using PMF_KI_BOOST and PMF_FLYING - // NOTE: may not have more than 16 typedef enum { PW_NONE, PW_QUAD, PW_BATTLESUIT, - PW_HASTE, + PW_HASTE, // BFP - Used for ki boost status PW_INVIS, PW_REGEN, - PW_FLIGHT, + PW_FLIGHT, // BFP - Used for flying status PW_REDFLAG, PW_BLUEFLAG, @@ -355,9 +352,24 @@ typedef enum { #define EVENT_VALID_MSEC 300 +// BFP - NOTE: Take a look about original BFP events, the events (and event numbers) should be the same typedef enum { EV_NONE, + EV_MELEE_READY, // BFP - EV_MELEE_READY (10), preparing melee + EV_MELEE, // BFP - EV_MELEE (11), melee attack + + // EV_TIER_RESET, // EV_TIER_RESET (13), reset tier when the player respawns and changes to the default or a bit less ki energy? + + // BFP - EV_TIER_0-4 (14-18), when the player frags, increases their PL and obtains a new skill (in the last tier, transforms) + EV_TIER_0, + EV_TIER_1, + EV_TIER_2, + EV_TIER_3, + EV_TIER_4, + + EV_ENABLE_FLIGHT, // BFP - EV_ENABLE_FLIGHT (22), enable flight + EV_FOOTSTEP, EV_FOOTSTEP_METAL, EV_FOOTSPLASH, @@ -426,6 +438,7 @@ typedef enum { EV_SHOTGUN, EV_BULLET, // otherEntity is the shooter + EV_MISSILE_DETONATE, // BFP - EV_MISSILE_DETONATE (76), when ki attack explodes after some time EV_PAIN, EV_DEATH1, EV_DEATH2, diff --git a/source/game/g_active.c b/source/game/g_active.c index 2935917..afaf801 100644 --- a/source/game/g_active.c +++ b/source/game/g_active.c @@ -430,7 +430,7 @@ void ClientTimerActions( gentity_t *ent, int msec ) { } // BFP - Ki up/down when flying/ki use - if ( client->ps.pm_flags & PMF_FLYING ) { + if ( client->ps.powerups[PW_FLIGHT] > 0 ) { // BFP - TODO: Add cvar for flight cost @@ -447,7 +447,7 @@ void ClientTimerActions( gentity_t *ent, int msec ) { // BFP - if ki drops to 0, disable flight if ( client->ps.stats[STAT_KI] <= 0 ) { client->ps.stats[STAT_KI] = 0; - client->ps.pm_flags &= ~PMF_FLYING; + client->ps.powerups[PW_FLIGHT] = 0; // Com_Printf( "ki amount: %d\n", client->ps.stats[STAT_KI] ); } @@ -731,33 +731,36 @@ void ClientThink_real( gentity_t *ent ) { // set speed client->ps.speed = g_speed.value; - // BFP - Ki use has 2 options: "kiusetoggle" to toggle and "+button8" when key is being hold - if ( !( client->ps.pm_flags & PMF_HITSTUN ) - && ( ( ucmd->buttons & BUTTON_KI_USE ) // BFP - Using Ki - || ( client->ps.pm_flags & PMF_KI_BOOST ) ) ) { // BFP - When "kiusetoggle" is binded, enables/disables - if ( !( client->ps.pm_flags & PMF_FLYING ) ) { - client->ps.speed *= 2.5; + if ( client->ps.pm_type != PM_DEAD && client->ps.pm_type != PM_SPECTATOR ) { + + // BFP - Ki use has 2 options: "kiusetoggle" to toggle and "+button8" when key is being hold + if ( !( client->ps.pm_flags & PMF_HITSTUN ) + && ( ( ucmd->buttons & BUTTON_KI_USE ) // BFP - Using Ki + || client->ps.powerups[PW_HASTE] > 0 ) ) { // BFP - When "kiusetoggle" is binded, enables/disables + if ( client->ps.powerups[PW_FLIGHT] <= 0 ) { + client->ps.speed *= 2.5; + } + client->ps.eFlags |= EF_AURA; + } else { + if ( !( ucmd->buttons & BUTTON_KI_CHARGE ) ) { // BFP - If it's charging while it was using ki boost, don't remove the aura! + client->ps.eFlags &= ~EF_AURA; + } } - client->ps.eFlags |= EF_AURA; - } else { - if ( !( ucmd->buttons & BUTTON_KI_CHARGE ) ) { // BFP - If it's charging while it was using ki boost, don't remove the aura! - client->ps.eFlags &= ~EF_AURA; + + // BFP - Ki Charge + if ( ( ucmd->buttons & BUTTON_KI_CHARGE ) && client->ps.pm_time <= 0 + && ( client->ps.pm_flags & PMF_KI_CHARGE ) ) { + client->ps.eFlags |= EF_AURA; } - } - // BFP - Ki Charge - if ( ( ucmd->buttons & BUTTON_KI_CHARGE ) && client->ps.pm_time <= 0 - && ( client->ps.pm_flags & PMF_KI_CHARGE ) ) { - client->ps.eFlags |= EF_AURA; - } + if ( client->ps.powerups[PW_FLIGHT] > 0 ) { // BFP - Flight speed + client->ps.speed *= 2; + } + // BFP - TODO: When charging a ki attack like beam wave, consult FlyingThink and SpectatorThink if that's the case - if ( client->ps.pm_flags & PMF_FLYING ) { // BFP - Flight speed - client->ps.speed *= 1.5; + // BFP - Enable flight + FlyingThink( ent, ucmd ); // prevents client-server side issues when there's other client in-game } - // BFP - TODO: When charging a ki attack like beam wave, consult FlyingThink and SpectatorThink if that's the case - - // BFP - Enable flight - FlyingThink( ent, ucmd ); // prevents client-server side issues when there's other client in-game // BFP - no hook #if 0 @@ -990,6 +993,8 @@ void ClientEndFrame( gentity_t *ent ) { // turn off any expired powerups for ( i = 0 ; i < MAX_POWERUPS ; i++ ) { + // BFP - Flight and haste are skipped, these are treated for player status + if ( i == PW_FLIGHT || i == PW_HASTE ) continue; if ( ent->client->ps.powerups[ i ] < level.time ) { ent->client->ps.powerups[ i ] = 0; } diff --git a/source/game/g_client.c b/source/game/g_client.c index 59284a1..bf5c134 100644 --- a/source/game/g_client.c +++ b/source/game/g_client.c @@ -1080,7 +1080,7 @@ void ClientSpawn(gentity_t *ent) { client->pers.teamState.state = TEAM_ACTIVE; // always clear the kamikaze flag - ent->s.eFlags &= ~EF_KAMIKAZE; + // ent->s.eFlags &= ~EF_KAMIKAZE; // BFP - No EF_KAMIKAZE flag // toggle the teleport bit so the client knows to not lerp // and never clear the voted flag @@ -1148,9 +1148,9 @@ void ClientSpawn(gentity_t *ent) { client->ps.clientNum = index; - // TODO: BFP - list of 5 skills + // BFP - TODO: list of 5 skills - client->ps.stats[STAT_KI] = 1000; // BFP - give ki at start + client->ps.stats[STAT_KI] = 8160.0f; // BFP - TODO: give ki at start client->ps.stats[STAT_WEAPONS] = ( 1 << WP_MACHINEGUN ); client->ps.ammo[WP_MACHINEGUN] = 100; diff --git a/source/game/g_cmds.c b/source/game/g_cmds.c index 4cf81a9..c9c07fc 100644 --- a/source/game/g_cmds.c +++ b/source/game/g_cmds.c @@ -1604,10 +1604,10 @@ void Cmd_BFP_Fly_f( gentity_t* ent ) { // BFP - Flight if ( ent->client->ps.pm_type != PM_DEAD ) { // do not play the sound in the charging status - if ( !( ent->client->ps.pm_flags & PMF_FLYING ) && !( ent->client->ps.pm_flags & PMF_KI_CHARGE ) ) { - G_AddEvent( ent, EV_JUMP, 0 ); // play jump sound + if ( ent->client->ps.powerups[PW_FLIGHT] <= 0 && !( ent->client->ps.pm_flags & PMF_KI_CHARGE ) ) { + G_AddEvent( ent, EV_ENABLE_FLIGHT, 0 ); // play the sound } - ent->client->ps.pm_flags ^= PMF_FLYING; + ent->client->ps.powerups[PW_FLIGHT] ^= 1; } } @@ -1640,7 +1640,7 @@ void Cmd_BFP_SetKiUse_f( gentity_t* ent ) { // BFP - Set Ki use // BFP - NOTE: Originally, an unfinished command... #if 0 if ( ent->client->ps.pm_type != PM_DEAD ) { - ent->client->ps.pm_flags |= PMF_KI_BOOST; + ent->client->ps.powerups[PW_HASTE] = 1; } #endif } @@ -1653,7 +1653,7 @@ Cmd_BFP_KiUseToggle_f void Cmd_BFP_KiUseToggle_f( gentity_t* ent ) { // BFP - Ki use toggle if ( ent->client->ps.pm_type != PM_DEAD ) { - ent->client->ps.pm_flags ^= PMF_KI_BOOST; + ent->client->ps.powerups[PW_HASTE] ^= 1; } } @@ -1666,7 +1666,7 @@ void Cmd_BFP_SetKiIdle_f( gentity_t* ent ) { // BFP - Set Ki idle // BFP - NOTE: originally... Ki idling means disabling the ki? Sounds like it isn't operating... if ( ent->client->ps.pm_type != PM_DEAD ) { - ent->client->ps.pm_flags &= ~PMF_KI_BOOST; + ent->client->ps.powerups[PW_HASTE] = 0; } } diff --git a/source/game/g_combat.c b/source/game/g_combat.c index c9cd729..e75b1da 100644 --- a/source/game/g_combat.c +++ b/source/game/g_combat.c @@ -160,6 +160,8 @@ void GibEntity( gentity_t *self, int killer ) { gentity_t *ent; int i; +// BFP - No EF_KAMIKAZE flag +#if 0 //if this entity still has kamikaze if (self->s.eFlags & EF_KAMIKAZE) { // check if there is a kamikaze timer around for this owner @@ -175,6 +177,7 @@ void GibEntity( gentity_t *self, int killer ) { break; } } +#endif G_AddEvent( self, EV_GIB_PLAYER, killer ); self->takedamage = qfalse; self->s.eType = ET_INVISIBLE; @@ -761,9 +764,9 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, damage *= 0.5; } -// BFP - TODO: Make hit stun received from melee attack with PMF_KI_BOOST +// BFP - TODO: Make hit stun received from melee attack with PW_HASTE #if 0 - if ( g_hitStun.integer >= 1 && ( attacker->client->ps.pm_flags & PMF_KI_BOOST ) + if ( g_hitStun.integer >= 1 && ( attacker->client->ps.powerups[PW_HASTE] > 0 ) && targ != attacker && !OnSameTeam (targ, attacker) ) { attacker->client->ps.hitStunTime = -3; // just an idea, enable the hit stun with a conditional of == -3 } diff --git a/source/game/g_items.c b/source/game/g_items.c index 0dc67ba..5c81053 100644 --- a/source/game/g_items.c +++ b/source/game/g_items.c @@ -120,9 +120,12 @@ int Pickup_Holdable( gentity_t *ent, gentity_t *other ) { other->client->ps.stats[STAT_HOLDABLE_ITEM] = ent->item - bg_itemlist; +// BFP - No EF_KAMIKAZE flag +#if 0 if( ent->item->giTag == HI_KAMIKAZE ) { other->client->ps.eFlags |= EF_KAMIKAZE; } +#endif return RESPAWN_HOLDABLE; } diff --git a/source/game/g_target.c b/source/game/g_target.c index 062d058..fccdb42 100644 --- a/source/game/g_target.c +++ b/source/game/g_target.c @@ -65,6 +65,19 @@ takes away all the activators powerups. Used to drop flight powerups into death puts. */ void Use_target_remove_powerups( gentity_t *ent, gentity_t *other, gentity_t *activator ) { + // BFP - To keep flight and ki boost statuses + int keepPW[MAX_POWERUPS]; + + // BFP - NOTE: Originally, on BFP, they used PMF flags to keep the statuses, + // as long as these weren't affected from that, + // when the powerups variable is being reset entering in a target_remove_powerups zone. + // BFP original solution was ugly, because the client side visual of CG_PlayerAngles + // didn't handle the positions of the legs. + // This solution here is better than the original one. + + keepPW[PW_FLIGHT] = activator->client->ps.powerups[PW_FLIGHT]; + keepPW[PW_HASTE] = activator->client->ps.powerups[PW_HASTE]; + if( !activator->client ) { return; } @@ -78,6 +91,10 @@ void Use_target_remove_powerups( gentity_t *ent, gentity_t *other, gentity_t *ac } memset( activator->client->ps.powerups, 0, sizeof( activator->client->ps.powerups ) ); + + // BFP - Keep the statuses! + activator->client->ps.powerups[PW_FLIGHT] = keepPW[PW_FLIGHT]; + activator->client->ps.powerups[PW_HASTE] = keepPW[PW_HASTE]; } void SP_target_remove_powerups( gentity_t *ent ) { From cf6aed9194e2223473aae1f5684dd59811dd508e Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sat, 9 Mar 2024 00:24:43 +0100 Subject: [PATCH 047/374] cgame: Implement correctly bubble particles when these are getting outside water --- source/cgame/cg_particles.c | 101 +++++++++++++++++++++++------------- source/cgame/cg_players.c | 9 ++-- 2 files changed, 67 insertions(+), 43 deletions(-) diff --git a/source/cgame/cg_particles.c b/source/cgame/cg_particles.c index 8988fad..acfba60 100644 --- a/source/cgame/cg_particles.c +++ b/source/cgame/cg_particles.c @@ -143,6 +143,8 @@ int timenonscaled; #define NORMALSIZE 16 #define LARGESIZE 32 +// BFP - Function to handle bubbles +void CG_BubblesWaterHandling( cparticle_t *p, vec3_t org ); /* =============== @@ -420,38 +422,21 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) // BFP - Bubble types here if (p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) { - // BFP - Apply less end time to remove particles if the player is still charging + CG_BubblesWaterHandling( p, org ); + + // BFP - Apply more end time to remove particles if the player stops charging if (p->type == P_BUBBLE) { - if ( ( cg.snap->ps.eFlags & EF_AURA ) - && ( cg.snap->ps.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE + if ( ( cg.snap->ps.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_CHARGE && !p->link ) { - p->endtime = timenonscaled + 400; + p->endtime = timenonscaled + 2500 + (crandom() * 150); p->link = qtrue; } - if ( ( cg.snap->ps.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_CHARGE - && p->link ) + } else { + if ( !p->link ) { - p->endtime = timenonscaled + 2000 + (crandom() * 150); - p->link = qfalse; - } - } - - if (org[2] > p->end) - { - p->time = timenonscaled; - VectorCopy (org, p->org); // Ridah, fixes rare snow flakes that flicker on the ground - - // BFP - Stop shivering, before: ( p->start + crandom () * 4 ) - p->org[2] = ( p->start - p->end ); - - // BFP - Make move less - if (p->type == P_BUBBLE_TURBULENT) { - p->vel[0] *= 0.95; - p->vel[1] *= 0.95; - } else { - p->vel[0] *= 0.9; - p->vel[1] *= 0.9; + p->endtime = timenonscaled + 500 + (crandom() * 150); + p->link = qtrue; } } } @@ -485,7 +470,7 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) // BFP - TODO: Temporary solution... Make bouncing more interactive when there's a mover moving // if the particle is touching a mover and moves down, so keep bouncing if ( trace.fraction <= 0 ) { - p->roll = 10; + p->roll = 16; } else { p->vel[2] = p->accel[2] = (p->roll > 0) ? 50 * p->roll : 0; p->roll--; // that decreases bounces @@ -970,7 +955,7 @@ void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_ p->time = timenonscaled; // BFP - Add end time to remove particles, if there's no end time the particles will remain there - p->endtime = timenonscaled + 2000 + (crandom() * 150); + p->endtime = timenonscaled + 400; p->startfade = timenonscaled + 200; p->color = 0; @@ -1003,28 +988,70 @@ void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_ { p->type = P_BUBBLE; VectorSet( p->vel, - (rand() % 801) - 400, - (rand() % 801) - 400, - 40 ); + (rand() % 521) - 250, + (rand() % 521) - 250, + 20 ); // dispersion VectorSet( p->accel, - crandom() * 20, - crandom() * 20, - 2000 ); + crandom() * 10, + crandom() * 10, + 800 ); } VectorCopy(origin, p->org); p->org[0] += (crandom() * range); p->org[1] += (crandom() * range); - p->org[2] += (crandom() * (p->start - p->end)); + p->org[2] += (crandom() * 5); - // Rafael snow pvs check - p->snum = snum; + p->snum = 3 - (crandom() * 6); // used to randomize where the bubbles stop when these touches the surface p->link = qfalse; } +// BFP - Handle bubble particles when reaching to the top +void CG_BubblesWaterHandling( cparticle_t *p, vec3_t org ) { + trace_t trace; + vec3_t start, end; + int contents; + + VectorCopy( org, end ); + end[2] -= 15; + + VectorCopy( org, start ); + start[2] += 10; + + // trace down to find the surface + trap_CM_BoxTrace( &trace, start, end, vec3_origin, vec3_origin, 0, CONTENTS_WATER ); + + // if the particle is touching something solid, it will skip instead stopping + contents = trap_CM_PointContents( start, 0 ); + if ( contents & (CONTENTS_WATER | CONTENTS_SOLID) ) { + return; + } + + contents = trap_CM_PointContents( trace.endpos, 0 ); + if ( !( contents & CONTENTS_WATER ) ) { + p->time = timenonscaled; + VectorCopy (trace.endpos, p->org); + p->org[2] = trace.endpos[2] - p->snum; + + // trace again if the bubble went outside, then set it near to the surface + contents = trap_CM_PointContents( p->org, 0 ); + if ( !( contents & CONTENTS_WATER ) ) { + p->org[2] = trace.endpos[2]; + } + + // BFP - Stop going up and decrease dispersion speed + p->vel[2] = 0; + VectorClear( p->accel ); + + // BFP - Make move less + p->vel[0] *= 0.9; + p->vel[1] *= 0.9; + } +} + // BFP - Particle for dash smoke when using ki boost and moving in the ground void CG_ParticleDashSmoke (centity_t *cent, qhandle_t pshader, vec3_t origin) { diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index fbcb11d..1070605 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -2378,15 +2378,12 @@ void CG_Player( centity_t *cent ) { // BFP - TODO: Create a new function "CG_KiTrail" only when moving to draw ki trail and add the cvar for the length // BFP - Trace for bubble particles only when moving in the water and charging - int destContentType; - vec3_t start; - - destContentType = CG_PointContents( cent->lerpOrigin, -1 ); + int destContentType = CG_PointContents( legs.origin, -1 ); // spawning bubble particles if ( destContentType & CONTENTS_WATER ) { trace_t trace; - vec3_t bubbleOrigin; + vec3_t start, bubbleOrigin; VectorCopy( legs.origin, bubbleOrigin ); trap_CM_BoxTrace( &trace, start, bubbleOrigin, NULL, NULL, 0, CONTENTS_WATER ); @@ -2399,7 +2396,7 @@ void CG_Player( centity_t *cent ) { CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 1, 10, 0 ); CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 1, 10, 0 ); } else if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE ) { - bubbleOrigin[2] += -10; // put the origin a little below + bubbleOrigin[2] += -7; // put the origin a little below CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); From 19c49e64cef5919ef6783740a347334b2351e1e4 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sun, 24 Mar 2024 18:42:58 +0100 Subject: [PATCH 048/374] cgame: Optimize particles code and remove an useless extern variable in cg_local.h --- source/cgame/cg_local.h | 4 ---- source/cgame/cg_particles.c | 18 +++++++++--------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/source/cgame/cg_local.h b/source/cgame/cg_local.h index ba60bbd..da3e55e 100644 --- a/source/cgame/cg_local.h +++ b/source/cgame/cg_local.h @@ -1506,7 +1506,3 @@ void CG_ParticleSnow (qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb void CG_ParticleSnowFlurry (qhandle_t pshader, centity_t *cent); int CG_NewParticleArea ( int num ); // BFP - Unused function for particles, looks like here is to determine in the areas #endif - -extern qboolean initparticles; - - diff --git a/source/cgame/cg_particles.c b/source/cgame/cg_particles.c index acfba60..9120be8 100644 --- a/source/cgame/cg_particles.c +++ b/source/cgame/cg_particles.c @@ -127,18 +127,18 @@ static int numShaderAnims; #define PARTICLE_GRAVITY 40 #define MAX_PARTICLES 1024 * 8 -cparticle_t *active_particles, *free_particles; -cparticle_t particles[MAX_PARTICLES]; -int cl_numparticles = MAX_PARTICLES; +static cparticle_t *active_particles, *free_particles; +static cparticle_t particles[MAX_PARTICLES]; +static int cl_numparticles = MAX_PARTICLES; -qboolean initparticles = qfalse; -vec3_t vforward, vright, vup; -vec3_t rforward, rright, rup; +static qboolean initparticles = qfalse; +static vec3_t vforward, vright, vup; +static vec3_t rforward, rright, rup; -float oldtime; +static float oldtime; // BFP - NOTE: Particles use non-timescaled, before it was timescaled by game using cg.time -int timenonscaled; +static int timenonscaled; #define NORMALSIZE 16 #define LARGESIZE 32 @@ -996,7 +996,7 @@ void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_ VectorSet( p->accel, crandom() * 10, crandom() * 10, - 800 ); + 900 ); } VectorCopy(origin, p->org); From d4f1568db789aae9b01e16e1b16f284ec291d50e Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sun, 24 Mar 2024 18:51:37 +0100 Subject: [PATCH 049/374] game: When using ki charge after moving with ki boost, make deceleration smoother --- source/game/bg_pmove.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index 5703e9d..0a7e152 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -2185,13 +2185,19 @@ static void PM_KiCharge( void ) { // BFP - Ki Charge pm->cmd.forwardmove = pm->cmd.rightmove = pm->cmd.upmove = 0; - VectorClear( pm->ps->velocity ); + // Decelerate the fall + pm->ps->velocity[2] *= 0.85; if ( pm->cmd.buttons & ( BUTTON_ATTACK | BUTTON_KI_USE | BUTTON_MELEE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ) ) { pm->cmd.buttons &= ~( BUTTON_ATTACK | BUTTON_KI_USE | BUTTON_MELEE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ); } if ( pm->ps->powerups[PW_FLIGHT] <= 0 ) { + // Decelerate smoothly when it's on air + if ( !( pml.groundTrace.contents & MASK_PLAYERSOLID ) ) { + pm->ps->velocity[0] *= 0.85; + pm->ps->velocity[1] *= 0.85; + } pm->ps->pm_flags |= PMF_FALLING; // Handle PMF_FALLING flag } From b795755985db3c1c5219d0034e9041ac8f3b2438 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sun, 24 Mar 2024 19:58:46 +0100 Subject: [PATCH 050/374] game: Implement block, transfer health damage to ki and deflect some ki attacks --- README.md | 2 +- docs/bfp_cvars_task.md | 8 ++--- source/game/bg_pmove.c | 4 +-- source/game/bg_public.h | 2 ++ source/game/g_active.c | 79 +++++++++++++++++++++++++++++++++++++++++ source/game/g_combat.c | 9 +++-- source/game/g_cvar.h | 10 +++--- source/game/g_missile.c | 16 +++++++++ 8 files changed, 116 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index cff493d..f8c9cc7 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ A legendary 90s era Quake 3 Arena mod. - [ ] Powerlevel and Power Tiers indicated on old docs - [ ] Hit Stun (makes player can't use ki, melee, block and charge) - [ ] Power Struggles (when two beam attacks collide) -- [ ] Blocking (consumes ki energy, transfers all damage to ki instead of health, deflect missile attacks, more info on old docs) +- [x] ~~Blocking (consumes ki energy, transfers all damage to ki instead of health, deflect missile attacks, more info on old docs)~~ - [ ] Short-Range Teleport (when pressing 2 times left or right) - [ ] Transformations (related to Power Tiers) - [ ] Attacksets (configurable for cfgs) diff --git a/docs/bfp_cvars_task.md b/docs/bfp_cvars_task.md index 8d4d955..2c4f29d 100644 --- a/docs/bfp_cvars_task.md +++ b/docs/bfp_cvars_task.md @@ -3,14 +3,10 @@ ## PENDING: - g_basepl [1-999]: set the starting power level from one thousand to one mil. -- g_blockLength = "3" -- g_blockDelay = "2" - g_kiChargePct = "15" - g_kiCharge = "0" - g_kiRegenPct = "0.6" - g_kiRegen = "0" -- g_blockCostPct = "3" -- g_blockCost = "0" - g_boostCostPct = "0" - g_boostCost = "150" - g_flightCostPct = "0" @@ -72,6 +68,10 @@ - [x] ~~cg_polygonAura~~ - [x] ~~cg_highPolyAura~~ - [x] ~~g_noFlight (disables "fly" bind too, original BFP has a leak though)~~ +- [x] ~~g_blockLength~~ +- [x] ~~g_blockDelay~~ +- [x] ~~g_blockCost~~ +- [x] ~~g_blockCostPct~~ #### Cvar Gametypes: diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index 0a7e152..8c6216e 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -48,7 +48,7 @@ float pm_spectatorfriction = 5.0f; int c_pmove = 0; // BFP - TODO: Macro for torso handling, since the code looked repetitive, so this macro makes the code a bit shorter -#define TORSOSTATUS_ANIM_HANDLING(other_torsostatus) ( pm->ps->pm_flags & PMF_INVULEXPAND ) ? PM_ContinueTorsoAnim( TORSO_BLOCK ) : PM_ContinueTorsoAnim( other_torsostatus ) +#define TORSOSTATUS_ANIM_HANDLING(other_torsostatus) ( pm->ps->pm_flags & PMF_BLOCK ) ? PM_ContinueTorsoAnim( TORSO_BLOCK ) : PM_ContinueTorsoAnim( other_torsostatus ) // BFP - Macro for jump handling, since the code looked repetitive, so this macro makes the code a bit shorter #define FORCEJUMP_ANIM_HANDLING() ( pm->cmd.forwardmove >= 0 ) ? PM_ForceLegsAnim( LEGS_JUMP ) : PM_ForceLegsAnim( LEGS_JUMPB ) @@ -623,7 +623,7 @@ static void PM_FlyMove( void ) { VectorCopy (wishvel, wishdir); wishspeed = VectorNormalize(wishdir); - if ( !( pm->ps->pm_flags & PMF_INVULEXPAND ) // BFP - Don't increase the speed when blocking + if ( !( pm->ps->pm_flags & PMF_BLOCK ) // BFP - Don't increase the speed when blocking && ( pm->ps->powerups[PW_HASTE] > 0 || ( pm->cmd.buttons & BUTTON_KI_USE ) ) ) { wishspeed *= scale; } diff --git a/source/game/bg_public.h b/source/game/bg_public.h index 02f3900..fc541a8 100644 --- a/source/game/bg_public.h +++ b/source/game/bg_public.h @@ -142,6 +142,7 @@ typedef enum { // pmove->pm_flags #define PMF_DUCKED 1 #define PMF_JUMP_HELD 2 +#define PMF_BLOCK 4 // BFP - Block // BFP - PMF_BACKWARDS_JUMP is unused // #define PMF_BACKWARDS_JUMP 8 // go into backwards land #define PMF_NEARGROUND 8 // BFP - Near ground check @@ -218,6 +219,7 @@ void Pmove (pmove_t *pmove); typedef enum { STAT_HEALTH, STAT_KI, // BFP - KI amount + STAT_BLOCK, // BFP - Block amount treated as time STAT_HOLDABLE_ITEM, STAT_WEAPONS, // 16 bit fields STAT_ARMOR, diff --git a/source/game/g_active.c b/source/game/g_active.c index afaf801..11f77a7 100644 --- a/source/game/g_active.c +++ b/source/game/g_active.c @@ -735,6 +735,7 @@ void ClientThink_real( gentity_t *ent ) { // BFP - Ki use has 2 options: "kiusetoggle" to toggle and "+button8" when key is being hold if ( !( client->ps.pm_flags & PMF_HITSTUN ) + && !( client->ps.pm_flags & PMF_BLOCK ) && ( ( ucmd->buttons & BUTTON_KI_USE ) // BFP - Using Ki || client->ps.powerups[PW_HASTE] > 0 ) ) { // BFP - When "kiusetoggle" is binded, enables/disables if ( client->ps.powerups[PW_FLIGHT] <= 0 ) { @@ -747,6 +748,84 @@ void ClientThink_real( gentity_t *ent ) { } } + // BFP - Block, reflect ki attacks and reduce health damage + // Block handling: + // Initialize the blocking and start the block length duration, specifically, ki boost and aura are disabled + if ( !( client->ps.pm_flags & PMF_BLOCK ) + && ( ucmd->buttons & BUTTON_BLOCK ) + && client->ps.stats[STAT_BLOCK] <= 0 ) { + client->ps.pm_flags |= PMF_BLOCK; + client->ps.powerups[PW_HASTE] = 0; + client->ps.eFlags &= ~EF_AURA; + ucmd->buttons &= ~BUTTON_KI_USE; + client->ps.stats[STAT_BLOCK] = (g_blockLength.integer * 100); + } + + // Handle block status (it's like block time) + if ( client->ps.stats[STAT_BLOCK] >= 0 ) { + client->ps.stats[STAT_BLOCK]--; + // Print debug +#if 0 + if ( ( client->ps.pm_flags & PMF_BLOCK ) && client->ps.stats[STAT_BLOCK] <= (g_blockLength.integer * 100) ) + Com_Printf( "BLOCK LENGTH: %d\n", client->ps.stats[STAT_BLOCK] ); + else if ( !( client->ps.pm_flags & PMF_BLOCK ) && client->ps.stats[STAT_BLOCK] <= (g_blockDelay.integer * 100) ) + Com_Printf( "BLOCK DELAY: %d\n", client->ps.stats[STAT_BLOCK] ); +#endif + } + + // BFP - Blocking status. Ki energy is being consumed and ki boost can't be used + if ( ( client->ps.pm_flags & PMF_BLOCK ) + && client->ps.stats[STAT_BLOCK] <= (g_blockLength.integer * 100) + && client->ps.stats[STAT_BLOCK] >= 0 ) { + + // BFP - NOTE: Approximate calculation of ki consumption while blocking + float blockCostPct = g_blockCostPct.integer * 0.1; // Percentage of ki consumed per millisecond + float bCost = g_blockCost.integer > 0 ? g_blockCost.integer : 1; // Absolute value of ki consumed per millisecond + float kiBlockConsume = bCost / (g_blockLength.integer * 1000.0); + float totalBlockConsume; + // Random variable to make an approximate calculation of the ki consumption while using block + float rndkiConsume = rand() % 2; + + // BFP - TODO: Implement random calculations correctly? + if ( crandom() > 0.5 && crandom() < 0.8 ) { + rndkiConsume = rand() % 1; + } else if ( crandom() > 0.2 && crandom() < 0.5 ) { + rndkiConsume = random() + 0.38; + } + + // Calculate total ki being consumed + totalBlockConsume = kiBlockConsume * (g_blockLength.integer * 1000.0) * rndkiConsume; + + client->ps.stats[STAT_KI] -= totalBlockConsume; + } + + // When the block length duration has been expired, then start the delay to avoid user + if ( ( client->ps.pm_flags & PMF_BLOCK ) + && client->ps.stats[STAT_BLOCK] <= (g_blockLength.integer * 100) + && client->ps.stats[STAT_BLOCK] <= 0 ) { + client->ps.pm_flags &= ~PMF_BLOCK; + client->ps.stats[STAT_BLOCK] = (g_blockDelay.integer * 100); + } + + // If the block length duration hasn't been expired yet and + // pressing ki charge (if the aura is lighting) or attack buttons, then stop blocking and start the delay + if ( ( client->ps.pm_flags & PMF_BLOCK ) + && ( ( ucmd->buttons & BUTTON_MELEE ) + || ( ucmd->buttons & BUTTON_ATTACK ) + || ( client->ps.eFlags & EF_AURA ) ) ) { + client->ps.pm_flags &= ~PMF_BLOCK; + client->ps.stats[STAT_BLOCK] = (g_blockDelay.integer * 100); + } + + // Handle the delay and don't leave the user get away with it + if ( !( client->ps.pm_flags & PMF_BLOCK ) + && client->ps.stats[STAT_BLOCK] <= (g_blockDelay.integer * 100) + && client->ps.stats[STAT_BLOCK] >= 0 ) { + client->ps.pm_flags &= ~PMF_BLOCK; + ucmd->buttons &= ~BUTTON_BLOCK; // If the user holds the key, when that ends, then immediately enters to this status again + } + // BFP - End of block handling + // BFP - Ki Charge if ( ( ucmd->buttons & BUTTON_KI_CHARGE ) && client->ps.pm_time <= 0 && ( client->ps.pm_flags & PMF_KI_CHARGE ) ) { diff --git a/source/game/g_combat.c b/source/game/g_combat.c index e75b1da..5cc36b8 100644 --- a/source/game/g_combat.c +++ b/source/game/g_combat.c @@ -775,7 +775,8 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, // add to the attacker's hit counter (if the target isn't a general entity like a prox mine) if ( attacker->client && targ != attacker && targ->health > 0 && targ->s.eType != ET_MISSILE - && targ->s.eType != ET_GENERAL) { + && targ->s.eType != ET_GENERAL + && !( client->ps.pm_flags & PMF_BLOCK ) ) { // BFP - When blocking, don't receive any hit if ( OnSameTeam( targ, attacker ) ) { attacker->client->ps.persistant[PERS_HITS]--; } else { @@ -808,7 +809,8 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, // add to the damage inflicted on a player this frame // the total will be turned into screen blends and view angle kicks // at the end of the frame - if ( client ) { + if ( client + && !( client->ps.pm_flags & PMF_BLOCK ) ) { // BFP - When blocking, don't receive screams of pain if ( attacker ) { client->ps.persistant[PERS_ATTACKER] = attacker->s.number; } else { @@ -838,7 +840,8 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, } // do the damage - if (take) { + if (take + && !( client->ps.pm_flags & PMF_BLOCK )) { // BFP - When blocking, don't receive damage targ->health = targ->health - take; if ( targ->client ) { targ->client->ps.stats[STAT_HEALTH] = targ->health; diff --git a/source/game/g_cvar.h b/source/game/g_cvar.h index 941c391..565378d 100644 --- a/source/game/g_cvar.h +++ b/source/game/g_cvar.h @@ -76,15 +76,17 @@ G_CVAR( g_maxSpawnPL, "g_maxSpawnPL", "999", 0, 0, qtrue ) // BFP - Max spawn po G_CVAR( g_flightCost, "g_flightCost", "50", 0, 0, qtrue ) // BFP - Flight cost G_CVAR( g_flightCostPct, "g_flightCostPct", "0", 0, 0, qtrue ) // BFP - Flight cost percentage G_CVAR( g_boostCost, "g_boostCost", "350", 0, 0, qtrue ) // BFP - Boost cost -G_CVAR( g_boostCostPct, "g_boostCostPct", "3", 0, 0, qtrue ) // BFP - Boost cost percentage +G_CVAR( g_boostCostPct, "g_boostCostPct", "0", 0, 0, qtrue ) // BFP - Boost cost percentage + G_CVAR( g_blockCost, "g_blockCost", "2", 0, 0, qtrue ) // BFP - Block cost -G_CVAR( g_blockCostPct, "g_blockCostPct", "3", 0, 0, qtrue ) // BFP - Block cost percentage +G_CVAR( g_blockCostPct, "g_blockCostPct", "0", 0, 0, qtrue ) // BFP - Block cost percentage +G_CVAR( g_blockDelay, "g_blockDelay", "2", 0, 0, qtrue ) // BFP - Block delay +G_CVAR( g_blockLength, "g_blockLength", "2", 0, 0, qtrue ) // BFP - Block length + G_CVAR( g_kiRegen, "g_kiRegen", "0", 0, 0, qtrue ) // BFP - Ki regeneration G_CVAR( g_kiRegenPct, "g_kiRegenPct", "0.6", 0, 0, qtrue ) // BFP - Ki regeneration percentage G_CVAR( g_kiCharge, "g_kiCharge", "0", 0, 0, qtrue ) // BFP - Ki charge G_CVAR( g_kiChargePct, "g_kiChargePct", "15", 0, 0, qtrue ) // BFP - Ki charge percentage -G_CVAR( g_blockDelay, "g_blockDelay", "2", 0, 0, qtrue ) // BFP - Block delay -G_CVAR( g_blockLength, "g_blockLength", "3", 0, 0, qtrue ) // BFP - Block length G_CVAR( g_podiumDist, "g_podiumDist", "80", 0, 0, qfalse ) G_CVAR( g_podiumDrop, "g_podiumDrop", "70", 0, 0, qfalse ) diff --git a/source/game/g_missile.c b/source/game/g_missile.c index d56e45b..77eb1e8 100644 --- a/source/game/g_missile.c +++ b/source/game/g_missile.c @@ -116,6 +116,22 @@ void G_MissileImpact( gentity_t *ent, trace_t *trace ) { if ( ent->damage ) { vec3_t velocity; + // BFP - When blocking... Deflect the projectile! + if ( other->client->ps.pm_flags & PMF_BLOCK ) { + // PUSH! + BG_EvaluateTrajectoryDelta( &ent->s.pos, level.time, velocity ); + if ( VectorLength( velocity ) == 0 ) { + velocity[2] = 1; + } + G_Damage (other, ent, &g_entities[ent->r.ownerNum], velocity, + ent->s.origin, ent->damage, + 0, ent->methodOfDeath); + + // DEFLECT! + G_BounceMissile( ent, trace ); + return; + } + if( LogAccuracyHit( other, &g_entities[ent->r.ownerNum] ) ) { g_entities[ent->r.ownerNum].client->accuracy_hits++; hitClient = qtrue; From 691c58a59886d932ac4ccc1b97c55587a084f282 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sun, 24 Mar 2024 23:05:42 +0100 Subject: [PATCH 051/374] game: Fix interactions with bounce pads and push something during flight status --- source/game/bg_misc.c | 3 +++ source/game/g_trigger.c | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/source/game/bg_misc.c b/source/game/bg_misc.c index 812b639..2fc9eb9 100644 --- a/source/game/bg_misc.c +++ b/source/game/bg_misc.c @@ -1083,10 +1083,13 @@ void BG_TouchJumpPad( playerState_t *ps, entityState_t *jumppad ) { return; } +// BFP - Flight status can be interacted to bounce pads +#if 0 // flying characters don't hit bounce pads if ( ps->powerups[PW_FLIGHT] ) { return; } +#endif // if we didn't hit this same jumppad the previous frame // then don't play the event sound again if we are in a fat trigger diff --git a/source/game/g_trigger.c b/source/game/g_trigger.c index 9db2304..3cb8b57 100644 --- a/source/game/g_trigger.c +++ b/source/game/g_trigger.c @@ -221,9 +221,13 @@ void Use_target_push( gentity_t *self, gentity_t *other, gentity_t *activator ) if ( activator->client->ps.pm_type != PM_NORMAL ) { return; } + +// BFP - Flight status can be interacted to push something +#if 0 if ( activator->client->ps.powerups[PW_FLIGHT] ) { return; } +#endif VectorCopy (self->s.origin2, activator->client->ps.velocity); From 747d05c878f5082fc18d7a853a20473267417aa2 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Wed, 27 Mar 2024 01:25:55 +0100 Subject: [PATCH 052/374] game: Fix mistake on pmove timers when decreasing to 0, fix ki charge animations when falling from a slope (when reaches to downside, it does some footstep), don't jump when enabling flight while charging and adjust the fall velocity when charging --- source/game/bg_pmove.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index 8c6216e..b1ee605 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -71,6 +71,7 @@ int c_pmove = 0; return; \ } \ } else { \ + /* If it's trying to crouch, then play the jump animation once */ \ if ( pm->ps->pm_flags & PMF_DUCKED ) { \ pm->ps->pm_flags |= PMF_NEARGROUND; \ FORCEJUMP_ANIM_HANDLING(); \ @@ -1203,11 +1204,11 @@ static void PM_GroundTrace( void ) { // do a smooth jump animation like BFP does if ( !( pm->cmd.buttons & BUTTON_KI_CHARGE ) ) { pm->ps->pm_time = 500; + pm->ps->velocity[2] = JUMP_VELOCITY; + PM_ForceLegsAnim( LEGS_JUMP ); } pml.groundPlane = qfalse; // jumping away pml.walking = qfalse; - pm->ps->velocity[2] = JUMP_VELOCITY; - PM_ForceLegsAnim( LEGS_JUMP ); } pm->ps->pm_flags &= ~PMF_FALLING; pm->ps->groundEntityNum = ENTITYNUM_NONE; @@ -1442,6 +1443,11 @@ static void PM_Footsteps( void ) { return; } + // BFP - Avoid when charging + if ( pm->ps->pm_flags & PMF_KI_CHARGE ) { + return; + } + // // calculate speed and cycle to be used for // all cyclic walking effects @@ -1708,8 +1714,6 @@ static void PM_TorsoAnimation( void ) { && pm->ps->powerups[PW_FLIGHT] <= 0 && pm->ps->groundEntityNum == ENTITYNUM_NONE // hasn't touched the ground yet && ( pml.groundTrace.contents & MASK_PLAYERSOLID ) ) { - - // If it's trying to crouch, then play the jump animation once SLOPES_NEARGROUND_ANIM_HANDLING( 0 ) } @@ -2072,14 +2076,11 @@ PM_DropTimers static void PM_DropTimers( void ) { // drop misc timing counter if ( pm->ps->pm_time ) { - // BFP - No handling PMF_ALL_TIMES -#if 0 if ( pml.msec >= pm->ps->pm_time ) { - pm->ps->pm_flags &= ~PMF_ALL_TIMES; + // BFP - No handling PMF_ALL_TIMES + // pm->ps->pm_flags &= ~PMF_ALL_TIMES; pm->ps->pm_time = 0; - } else -#endif - { + } else { pm->ps->pm_time -= pml.msec; } } @@ -2185,18 +2186,16 @@ static void PM_KiCharge( void ) { // BFP - Ki Charge pm->cmd.forwardmove = pm->cmd.rightmove = pm->cmd.upmove = 0; - // Decelerate the fall - pm->ps->velocity[2] *= 0.85; - if ( pm->cmd.buttons & ( BUTTON_ATTACK | BUTTON_KI_USE | BUTTON_MELEE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ) ) { pm->cmd.buttons &= ~( BUTTON_ATTACK | BUTTON_KI_USE | BUTTON_MELEE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ); } if ( pm->ps->powerups[PW_FLIGHT] <= 0 ) { - // Decelerate smoothly when it's on air - if ( !( pml.groundTrace.contents & MASK_PLAYERSOLID ) ) { - pm->ps->velocity[0] *= 0.85; - pm->ps->velocity[1] *= 0.85; + // Don't move from the position when falling + if ( !( pml.groundTrace.contents & MASK_PLAYERSOLID ) + && pm->ps->groundEntityNum == ENTITYNUM_NONE ) { + pm->ps->velocity[0] = 0; + pm->ps->velocity[1] = 0; } pm->ps->pm_flags |= PMF_FALLING; // Handle PMF_FALLING flag } @@ -2338,7 +2337,7 @@ void PmoveSingle (pmove_t *pmove) { if ( pm->ps->pm_type >= PM_DEAD ) { // BFP - If player is dead, disable the following statuses - pm->ps->powerups[PW_FLIGHT] = 0; + pm->ps->powerups[PW_FLIGHT] = 0; pm->ps->powerups[PW_HASTE] = 0; pm->ps->eFlags &= ~EF_AURA; From 9f3c68184138d563fa2465a33dffeccbdd25c360 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Fri, 29 Mar 2024 00:20:41 +0100 Subject: [PATCH 053/374] cgame: Tweak the movements of bubble particles and use antigrav rock particles only when the player isn't moving --- source/cgame/cg_event.c | 10 +++---- source/cgame/cg_local.h | 2 +- source/cgame/cg_particles.c | 53 ++++++++++++++++++++++--------------- source/cgame/cg_players.c | 17 +++++++----- source/cgame/cg_weapons.c | 6 ++--- 5 files changed, 52 insertions(+), 36 deletions(-) diff --git a/source/cgame/cg_event.c b/source/cgame/cg_event.c index 35826aa..3f71db2 100644 --- a/source/cgame/cg_event.c +++ b/source/cgame/cg_event.c @@ -593,11 +593,11 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { vec3_t end = {0, 0, 1}; // Blub, blub, blub... - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 1, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 1, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 1, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 1, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 1, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 700, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 700, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 700, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 700, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 700, 20, 0 ); } break; case EV_WATER_CLEAR: diff --git a/source/cgame/cg_local.h b/source/cgame/cg_local.h index da3e55e..a5accff 100644 --- a/source/cgame/cg_local.h +++ b/source/cgame/cg_local.h @@ -1493,7 +1493,7 @@ void CG_ParticleDust (centity_t *cent, vec3_t origin, vec3_t dir); void CG_ParticleMisc (qhandle_t pshader, vec3_t origin, int size, int duration, float alpha); void CG_ParticleExplosion (char *animStr, vec3_t origin, vec3_t vel, int duration, int sizeStart, int sizeEnd); // BFP - Bubble particle -void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb, float range, int snum); +void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_t origin2, int turbtime, float range, int snum); // BFP - Dash smoke particle for ki boost when moving in the ground void CG_ParticleDashSmoke (centity_t *cent, qhandle_t pshader, vec3_t origin); // BFP - Antigrav rock particles for charging diff --git a/source/cgame/cg_particles.c b/source/cgame/cg_particles.c index 9120be8..20e2b49 100644 --- a/source/cgame/cg_particles.c +++ b/source/cgame/cg_particles.c @@ -432,12 +432,6 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) p->endtime = timenonscaled + 2500 + (crandom() * 150); p->link = qtrue; } - } else { - if ( !p->link ) - { - p->endtime = timenonscaled + 500 + (crandom() * 150); - p->link = qtrue; - } } } @@ -940,7 +934,7 @@ void CG_AddParticles (void) active_particles = active; } -void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_t origin2, int turb, float range, int snum) +void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_t origin2, int turbtime, float range, int snum) { cparticle_t *p; @@ -955,7 +949,7 @@ void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_ p->time = timenonscaled; // BFP - Add end time to remove particles, if there's no end time the particles will remain there - p->endtime = timenonscaled + 400; + p->endtime = timenonscaled + 600; p->startfade = timenonscaled + 200; p->color = 0; @@ -965,13 +959,20 @@ void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_ p->start = cent->currentState.origin[2]; p->end = cent->currentState.origin2[2]; p->pshader = pshader; - p->height = p->width = 2 + (crandom() * 0.5); + p->height = p->width = (rand() % 2) + 1; - if (turb) + VectorCopy(origin, p->org); + + if (turbtime) { p->type = P_BUBBLE_TURBULENT; // BFP - Apply end time to remove particles in that case, if there's no end time the particles will remain there - p->endtime = timenonscaled + 700; + p->endtime = timenonscaled + turbtime; + p->height = p->width = (rand() % 1) + 2; + + p->org[0] += (rand() % (int)range) + (crandom() * range); + p->org[1] += (rand() % (int)range) + (crandom() * range); + p->org[2] += (rand() % (int)20); VectorSet( p->vel, (rand() % 401) - 200, @@ -980,13 +981,18 @@ void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_ // dispersion VectorSet( p->accel, - crandom() * 20, - crandom() * 20, + crandom() * 10, + crandom() * 10, 300 ); } else { p->type = P_BUBBLE; + + p->org[0] += (crandom() * range); + p->org[1] += (crandom() * range); + p->org[2] += (crandom() * 5); + VectorSet( p->vel, (rand() % 521) - 250, (rand() % 521) - 250, @@ -999,12 +1005,6 @@ void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_ 900 ); } - VectorCopy(origin, p->org); - - p->org[0] += (crandom() * range); - p->org[1] += (crandom() * range); - p->org[2] += (crandom() * 5); - p->snum = 3 - (crandom() * 6); // used to randomize where the bubbles stop when these touches the surface p->link = qfalse; } @@ -1021,6 +1021,15 @@ void CG_BubblesWaterHandling( cparticle_t *p, vec3_t org ) { VectorCopy( org, start ); start[2] += 10; + // BFP - Make move less + if ( p->vel[0] > -0.9 && p->vel[0] < 0.9 ) p->vel[0] = 0; + if ( p->vel[1] > -0.9 && p->vel[1] < 0.9 ) p->vel[1] = 0; + if ( p->vel[0] != 0 ) p->vel[0] *= 0.99; + if ( p->vel[1] != 0 ) p->vel[1] *= 0.99; + + // Decelerate + if ( p->accel[2] > 0 ) p->accel[2]--; + // trace down to find the surface trap_CM_BoxTrace( &trace, start, end, vec3_origin, vec3_origin, 0, CONTENTS_WATER ); @@ -1047,8 +1056,10 @@ void CG_BubblesWaterHandling( cparticle_t *p, vec3_t org ) { VectorClear( p->accel ); // BFP - Make move less - p->vel[0] *= 0.9; - p->vel[1] *= 0.9; + if ( p->vel[0] >= -1 && p->vel[0] <= 0.9 ) p->vel[0] = 0; + else p->vel[0] *= 0.9; + if ( p->vel[1] >= -1 && p->vel[1] <= 0.9 ) p->vel[1] = 0; + else p->vel[1] *= 0.9; } } diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index 1070605..04ed4bc 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -1887,15 +1887,20 @@ static qboolean CG_PlayerShadow( centity_t *cent, float *shadowPlane ) { CG_ParticleDashSmoke( cent, cgs.media.particleSmokeShader, trace.endpos ); } + waterTrace.endpos[2] -= 20; // BFP - Put a bit down to make the bubbles move if ( waterTrace.fraction >= 0.10f && waterTrace.fraction <= 0.70f ) { - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, waterTrace.endpos, end, 1, 10, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, waterTrace.endpos, end, 1, 10, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, waterTrace.endpos, end, 1, 10, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, waterTrace.endpos, end, 700, 10, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, waterTrace.endpos, end, 700, 10, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, waterTrace.endpos, end, 700, 10, 0 ); } } if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE ) { // BFP - Antigrav rock particles on ki charging status if ( !( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) + // if the player isn't moving + && !cent->currentState.pos.trDelta[0] + && !cent->currentState.pos.trDelta[1] + && !cent->currentState.pos.trDelta[2] && ( trace.fraction <= 0.30f // If the player is stepping a mover: || cent->currentState.groundEntityNum != ENTITYNUM_NONE ) ) { @@ -2392,9 +2397,9 @@ void CG_Player( centity_t *cent ) { if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYA || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYB ) { - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 1, 10, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 1, 10, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 1, 10, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 700, 10, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 700, 10, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 700, 10, 0 ); } else if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE ) { bubbleOrigin[2] += -7; // put the origin a little below diff --git a/source/cgame/cg_weapons.c b/source/cgame/cg_weapons.c index 260389d..0f2e243 100644 --- a/source/cgame/cg_weapons.c +++ b/source/cgame/cg_weapons.c @@ -329,9 +329,9 @@ static void CG_RocketTrail( centity_t *ent, const weaponInfo_t *wi ) { if ( ( contents & lastContents & CONTENTS_WATER ) && cg.frametime > 0.0f ) { // BFP - If paused, don't spawn bubble particles (cg_paused.integer < 1 is another solution, but not good enough for server responses) // BFP - Apply particle bubble effect in that case - CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 1, 0, 0 ); - CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 1, 0, 0 ); - CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 1, 0, 0 ); + CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 1200, 20, 0 ); + CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 1200, 20, 0 ); + CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 1200, 20, 0 ); // CG_BubbleTrail( lastPos, origin, 8 ); } return; From 896230039e73a0e1f80982c44c85c97302f65456 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 15 Apr 2024 01:19:40 +0200 Subject: [PATCH 054/374] game: Add 'block' alternative command and apply block stats time as pml.msec, so that depends of pmove time --- source/game/bg_pmove.c | 20 ++++++++++++++++++++ source/game/g_active.c | 24 ++++++------------------ source/game/g_cmds.c | 21 ++++++++++++--------- 3 files changed, 38 insertions(+), 27 deletions(-) diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index b1ee605..90043f9 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -2226,6 +2226,23 @@ static void PM_HitStun( void ) { // BFP - Hit stun pm->cmd.upmove = 0; } +/* +================ +PM_BlockTime + +Handle block status (treated as block time) +================ +*/ +static void PM_BlockTime( void ) { // BFP - Block + if ( pm->ps->stats[STAT_BLOCK] >= 0 ) { + pm->ps->stats[STAT_BLOCK] -= pml.msec; + // Print block length duration debug +#if 0 + Com_Printf( "BLOCK LENGTH: %d\n", pm->ps->stats[STAT_BLOCK] ); +#endif + } +} + /* ================ PmoveSingle @@ -2402,6 +2419,9 @@ void PmoveSingle (pmove_t *pmove) { PM_DeadMove (); } + // BFP - Block + PM_BlockTime(); + PM_DropTimers(); // BFP - Flight diff --git a/source/game/g_active.c b/source/game/g_active.c index 11f77a7..96053a1 100644 --- a/source/game/g_active.c +++ b/source/game/g_active.c @@ -758,24 +758,12 @@ void ClientThink_real( gentity_t *ent ) { client->ps.powerups[PW_HASTE] = 0; client->ps.eFlags &= ~EF_AURA; ucmd->buttons &= ~BUTTON_KI_USE; - client->ps.stats[STAT_BLOCK] = (g_blockLength.integer * 100); - } - - // Handle block status (it's like block time) - if ( client->ps.stats[STAT_BLOCK] >= 0 ) { - client->ps.stats[STAT_BLOCK]--; - // Print debug -#if 0 - if ( ( client->ps.pm_flags & PMF_BLOCK ) && client->ps.stats[STAT_BLOCK] <= (g_blockLength.integer * 100) ) - Com_Printf( "BLOCK LENGTH: %d\n", client->ps.stats[STAT_BLOCK] ); - else if ( !( client->ps.pm_flags & PMF_BLOCK ) && client->ps.stats[STAT_BLOCK] <= (g_blockDelay.integer * 100) ) - Com_Printf( "BLOCK DELAY: %d\n", client->ps.stats[STAT_BLOCK] ); -#endif + client->ps.stats[STAT_BLOCK] = (g_blockLength.integer * 1000); } // BFP - Blocking status. Ki energy is being consumed and ki boost can't be used if ( ( client->ps.pm_flags & PMF_BLOCK ) - && client->ps.stats[STAT_BLOCK] <= (g_blockLength.integer * 100) + && client->ps.stats[STAT_BLOCK] <= (g_blockLength.integer * 1000) && client->ps.stats[STAT_BLOCK] >= 0 ) { // BFP - NOTE: Approximate calculation of ki consumption while blocking @@ -801,10 +789,10 @@ void ClientThink_real( gentity_t *ent ) { // When the block length duration has been expired, then start the delay to avoid user if ( ( client->ps.pm_flags & PMF_BLOCK ) - && client->ps.stats[STAT_BLOCK] <= (g_blockLength.integer * 100) + && client->ps.stats[STAT_BLOCK] <= (g_blockLength.integer * 1000) && client->ps.stats[STAT_BLOCK] <= 0 ) { client->ps.pm_flags &= ~PMF_BLOCK; - client->ps.stats[STAT_BLOCK] = (g_blockDelay.integer * 100); + client->ps.stats[STAT_BLOCK] = (g_blockDelay.integer * 1000); } // If the block length duration hasn't been expired yet and @@ -814,12 +802,12 @@ void ClientThink_real( gentity_t *ent ) { || ( ucmd->buttons & BUTTON_ATTACK ) || ( client->ps.eFlags & EF_AURA ) ) ) { client->ps.pm_flags &= ~PMF_BLOCK; - client->ps.stats[STAT_BLOCK] = (g_blockDelay.integer * 100); + client->ps.stats[STAT_BLOCK] = (g_blockDelay.integer * 1000); } // Handle the delay and don't leave the user get away with it if ( !( client->ps.pm_flags & PMF_BLOCK ) - && client->ps.stats[STAT_BLOCK] <= (g_blockDelay.integer * 100) + && client->ps.stats[STAT_BLOCK] <= (g_blockDelay.integer * 1000) && client->ps.stats[STAT_BLOCK] >= 0 ) { client->ps.pm_flags &= ~PMF_BLOCK; ucmd->buttons &= ~BUTTON_BLOCK; // If the user holds the key, when that ends, then immediately enters to this status again diff --git a/source/game/g_cmds.c b/source/game/g_cmds.c index c9c07fc..1b891a6 100644 --- a/source/game/g_cmds.c +++ b/source/game/g_cmds.c @@ -1690,12 +1690,17 @@ void Cmd_BFP_SelectCharacter_f( gentity_t* ent ) { // BFP - Select character G_Printf( "Character: %s\n", characterselected ); } -void Cmd_BFP_StartBlock_f( gentity_t* ent ) { // BFP - TODO: Start block - Com_Printf( "Cmd_BFP_StartBlock_f\n" ); -} +/* +================= +Cmd_BFP_Block_f +================= +*/ +void Cmd_BFP_Block_f( gentity_t* ent ) { // BFP - Block -void Cmd_BFP_StopBlock_f( gentity_t* ent ) { // BFP - TODO: Stop block - Com_Printf( "Cmd_BFP_StopBlock_f\n" ); + if ( ent->client->ps.pm_type != PM_DEAD ) { + ent->client->ps.pm_flags |= PMF_BLOCK; + ent->client->ps.stats[STAT_BLOCK] = (g_blockLength.integer * 1000); + } } void Cmd_BFP_StartMelee_f( gentity_t* ent ) { // BFP - TODO: Start melee @@ -1826,10 +1831,8 @@ void ClientCommand( int clientNum ) { Cmd_BFP_SetKiIdle_f( ent ); else if (Q_stricmp (cmd, "selectcharacter") == 0) // BFP - Select character Cmd_BFP_SelectCharacter_f( ent ); - else if (Q_stricmp (cmd, "start_block") == 0) // BFP - TODO: Start Block - Cmd_BFP_StartBlock_f( ent ); - else if (Q_stricmp (cmd, "stop_block") == 0) // BFP - TODO: Stop block - Cmd_BFP_StopBlock_f( ent ); + else if (Q_stricmp (cmd, "block") == 0) // BFP - Block + Cmd_BFP_Block_f( ent ); else if (Q_stricmp (cmd, "start_melee") == 0) // BFP - TODO: Start melee Cmd_BFP_StartMelee_f( ent ); else if (Q_stricmp (cmd, "stop_melee") == 0) // BFP - TODO: Stop melee From 61b4f4cf59e3e23a994bf5912425c43b7729a2fe Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Tue, 30 Apr 2024 00:12:05 +0200 Subject: [PATCH 055/374] game: Handle ki boost status even if ki boost bind key was enabled --- source/game/g_active.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/game/g_active.c b/source/game/g_active.c index 96053a1..5f43620 100644 --- a/source/game/g_active.c +++ b/source/game/g_active.c @@ -741,10 +741,12 @@ void ClientThink_real( gentity_t *ent ) { if ( client->ps.powerups[PW_FLIGHT] <= 0 ) { client->ps.speed *= 2.5; } + client->ps.powerups[PW_HASTE] = 1; // Handle ki boost status client->ps.eFlags |= EF_AURA; } else { if ( !( ucmd->buttons & BUTTON_KI_CHARGE ) ) { // BFP - If it's charging while it was using ki boost, don't remove the aura! client->ps.eFlags &= ~EF_AURA; + client->ps.powerups[PW_HASTE] = 0; // Handle ki boost status } } From b056644cc46c51d41442a31e654f4bf03da3191d Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Wed, 1 May 2024 21:03:24 +0200 Subject: [PATCH 056/374] game: Make g_noFlight and block g_cvars display to the client (CVAR_ARCHIVE does that) --- source/game/g_cvar.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/game/g_cvar.h b/source/game/g_cvar.h index 565378d..fa78c7b 100644 --- a/source/game/g_cvar.h +++ b/source/game/g_cvar.h @@ -70,7 +70,7 @@ G_CVAR( g_meleeRange, "g_meleeRange", "32", 0, 0, qtrue ) // BFP - Melee range G_CVAR( g_chargeDelay, "g_chargeDelay", "750", 0, 0, qtrue ) // BFP - Charge delay G_CVAR( g_hitStun, "g_hitStun", "", 0, 0, qtrue ) // BFP - Hit stun G_CVAR( g_meleeOnly, "g_meleeOnly", "", 0, 0, qtrue ) // BFP - Melee only -G_CVAR( g_noFlight, "g_noFlight", "0", CVAR_SERVERINFO | CVAR_USERINFO | CVAR_LATCH, 0, qtrue ) // BFP - No flight +G_CVAR( g_noFlight, "g_noFlight", "0", CVAR_SERVERINFO | CVAR_USERINFO | CVAR_LATCH | CVAR_ARCHIVE, 0, qtrue ) // BFP - No flight G_CVAR( g_plKillBonusPct, "g_plKillBonusPct", ".1", 0, 0, qtrue ) // BFP - Kill bonus percentage G_CVAR( g_maxSpawnPL, "g_maxSpawnPL", "999", 0, 0, qtrue ) // BFP - Max spawn powerlevel G_CVAR( g_flightCost, "g_flightCost", "50", 0, 0, qtrue ) // BFP - Flight cost @@ -78,10 +78,10 @@ G_CVAR( g_flightCostPct, "g_flightCostPct", "0", 0, 0, qtrue ) // BFP - Flight c G_CVAR( g_boostCost, "g_boostCost", "350", 0, 0, qtrue ) // BFP - Boost cost G_CVAR( g_boostCostPct, "g_boostCostPct", "0", 0, 0, qtrue ) // BFP - Boost cost percentage -G_CVAR( g_blockCost, "g_blockCost", "2", 0, 0, qtrue ) // BFP - Block cost -G_CVAR( g_blockCostPct, "g_blockCostPct", "0", 0, 0, qtrue ) // BFP - Block cost percentage -G_CVAR( g_blockDelay, "g_blockDelay", "2", 0, 0, qtrue ) // BFP - Block delay -G_CVAR( g_blockLength, "g_blockLength", "2", 0, 0, qtrue ) // BFP - Block length +G_CVAR( g_blockCost, "g_blockCost", "2", CVAR_ARCHIVE, 0, qtrue ) // BFP - Block cost +G_CVAR( g_blockCostPct, "g_blockCostPct", "0", CVAR_ARCHIVE, 0, qtrue ) // BFP - Block cost percentage +G_CVAR( g_blockDelay, "g_blockDelay", "2", CVAR_ARCHIVE, 0, qtrue ) // BFP - Block delay +G_CVAR( g_blockLength, "g_blockLength", "2", CVAR_ARCHIVE, 0, qtrue ) // BFP - Block length G_CVAR( g_kiRegen, "g_kiRegen", "0", 0, 0, qtrue ) // BFP - Ki regeneration G_CVAR( g_kiRegenPct, "g_kiRegenPct", "0.6", 0, 0, qtrue ) // BFP - Ki regeneration percentage From fa541d5f29aa4bef24c9d5ace1498b1654c46579 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Thu, 9 May 2024 00:44:20 +0200 Subject: [PATCH 057/374] game: Fix weird bug in blocking feature, the doors deflect projectiles --- source/game/g_missile.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/game/g_missile.c b/source/game/g_missile.c index 77eb1e8..c16893e 100644 --- a/source/game/g_missile.c +++ b/source/game/g_missile.c @@ -117,7 +117,7 @@ void G_MissileImpact( gentity_t *ent, trace_t *trace ) { vec3_t velocity; // BFP - When blocking... Deflect the projectile! - if ( other->client->ps.pm_flags & PMF_BLOCK ) { + if ( other->client && ( other->client->ps.pm_flags & PMF_BLOCK ) ) { // PUSH! BG_EvaluateTrajectoryDelta( &ent->s.pos, level.time, velocity ); if ( VectorLength( velocity ) == 0 ) { From 19eb1bcf74e835dc2f8f10b386a1252a2cb05b89 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Fri, 31 May 2024 18:34:55 +0200 Subject: [PATCH 058/374] cgame: Add cg_playHitSound cvar, turn on or off the q3 hit 'ping' --- docs/bfp_cvars_task.md | 2 +- source/cgame/cg_cvar.h | 1 + source/cgame/cg_playerstate.c | 5 ++++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/bfp_cvars_task.md b/docs/bfp_cvars_task.md index 2c4f29d..e76c269 100644 --- a/docs/bfp_cvars_task.md +++ b/docs/bfp_cvars_task.md @@ -46,7 +46,6 @@ - cg_explosionSmoke [0/1]: turn on or off the explosion smoke. - cg_explosionRing [0/1]: turn on or off the explosion ring. - cg_particles [0/1]: turn on or off particle effects. -- cg_playHitSound [0/1]: turn on or off the q3 hit "ping". ## COMPLETED: @@ -67,6 +66,7 @@ - [x] ~~cg_lightweightAuras~~ - [x] ~~cg_polygonAura~~ - [x] ~~cg_highPolyAura~~ +- [x] ~~cg_playHitSound~~ - [x] ~~g_noFlight (disables "fly" bind too, original BFP has a leak though)~~ - [x] ~~g_blockLength~~ - [x] ~~g_blockDelay~~ diff --git a/source/cgame/cg_cvar.h b/source/cgame/cg_cvar.h index 40da24e..44a6883 100644 --- a/source/cgame/cg_cvar.h +++ b/source/cgame/cg_cvar.h @@ -65,6 +65,7 @@ CG_CVAR( cg_tracerChance, "cg_tracerchance", "0.4", CVAR_CHEAT ) CG_CVAR( cg_tracerWidth, "cg_tracerwidth", "1", CVAR_CHEAT ) CG_CVAR( cg_tracerLength, "cg_tracerlength", "100", CVAR_CHEAT ) CG_CVAR( cg_flytilt, "cg_flytilt", "1", CVAR_ARCHIVE ) // BFP - Fly tilt +CG_CVAR( cg_playHitSound, "cg_playHitSound", "0", CVAR_ARCHIVE ) // BFP - Play hit sound CG_CVAR( cg_thirdPersonRange, "cg_thirdPersonRange", "110", CVAR_ARCHIVE ) // BFP CG_CVAR( cg_thirdPersonAngle, "cg_thirdPersonAngle", "0", CVAR_ARCHIVE ) // BFP CG_CVAR( cg_thirdPersonHeight, "cg_thirdPersonHeight", "-60", CVAR_ARCHIVE ) // BFP - Camera height diff --git a/source/cgame/cg_playerstate.c b/source/cgame/cg_playerstate.c index 9eb34d2..4d2081c 100644 --- a/source/cgame/cg_playerstate.c +++ b/source/cgame/cg_playerstate.c @@ -313,7 +313,10 @@ void CG_CheckLocalSounds( playerState_t *ps, playerState_t *ops ) { cg.opponentHitBlendTime = cg.time + 0.5f; // BFP - For crosshair opponent hit effect armor = ps->persistant[PERS_ATTACKEE_ARMOR] & 0xff; health = ps->persistant[PERS_ATTACKEE_ARMOR] >> 8; - trap_S_StartLocalSound( cgs.media.hitSound, CHAN_LOCAL_SOUND ); + // BFP - Play hit sound + if ( cg_playHitSound.integer > 0 ) { + trap_S_StartLocalSound( cgs.media.hitSound, CHAN_LOCAL_SOUND ); + } } else if ( ps->persistant[PERS_HITS] < ops->persistant[PERS_HITS] ) { trap_S_StartLocalSound( cgs.media.hitTeamSound, CHAN_LOCAL_SOUND ); } From f9c05fb424de28c737531570f82bbe6a1de1b567 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Fri, 31 May 2024 19:25:50 +0200 Subject: [PATCH 059/374] cgame - game: Implement melee feature and complete hit stun feature --- README.md | 4 +- docs/bfp_cvars_task.md | 9 ++- source/cgame/cg_event.c | 36 +++++++-- source/game/bg_pmove.c | 95 ++++++++++++++++++++--- source/game/bg_public.h | 3 + source/game/g_active.c | 15 ++++ source/game/g_cmds.c | 12 +-- source/game/g_combat.c | 8 -- source/game/g_cvar.h | 8 +- source/game/g_local.h | 3 +- source/game/g_weapon.c | 163 ++++++++++++++++++++++++++++++++++++++++ 11 files changed, 315 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index f8c9cc7..cead704 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ A legendary 90s era Quake 3 Arena mod. # TODO list: - [x] ~~Toggeable flight (bind key). Hint: FLIGHT POWERUP~~ -- [ ] Melee feature +- [x] ~~Melee feature~~ - [x] ~~Remove weapon visuals (models and stuff)~~ - [x] ~~Animations as listed on the old docs~~ - [x] ~~Bind key to recover ki energy~~ @@ -45,7 +45,7 @@ A legendary 90s era Quake 3 Arena mod. - [x] ~~Third person traceable crosshair~~ - [ ] Make ki energy regeneration, ki use, attacks, charging balance indicated on old docs - [ ] Powerlevel and Power Tiers indicated on old docs -- [ ] Hit Stun (makes player can't use ki, melee, block and charge) +- [x] ~~Hit Stun (makes player can't use ki, melee, block and charge)~~ - [ ] Power Struggles (when two beam attacks collide) - [x] ~~Blocking (consumes ki energy, transfers all damage to ki instead of health, deflect missile attacks, more info on old docs)~~ - [ ] Short-Range Teleport (when pressing 2 times left or right) diff --git a/docs/bfp_cvars_task.md b/docs/bfp_cvars_task.md index e76c269..b48fe66 100644 --- a/docs/bfp_cvars_task.md +++ b/docs/bfp_cvars_task.md @@ -12,9 +12,6 @@ - g_flightCostPct = "0" - g_flightCost = "50" - g_chargeDelay = "250" -- g_meleeRange = "32" -- g_meleeDiveRange = "700" -- g_meleeDamage = "10" #### Cvar Gametypes: @@ -29,7 +26,6 @@ ## WIP: -- g_hitStun [0/1]: turn on or off the melee hit stun. #### Cvar Gametypes: @@ -72,6 +68,11 @@ - [x] ~~g_blockDelay~~ - [x] ~~g_blockCost~~ - [x] ~~g_blockCostPct~~ +- [x] ~~g_hitStun~~ +- [x] ~~g_meleeOnly~~ +- [x] ~~g_meleeRange~~ +- [x] ~~g_meleeDiveRange~~ +- [x] ~~g_meleeDamage~~ #### Cvar Gametypes: diff --git a/source/cgame/cg_event.c b/source/cgame/cg_event.c index 3f71db2..9023f6a 100644 --- a/source/cgame/cg_event.c +++ b/source/cgame/cg_event.c @@ -222,9 +222,15 @@ static void CG_Obituary( entityState_t *ent ) { case MOD_GRAPPLE: message = "was caught by"; break; + // BFP - No gauntlet +#if 0 case MOD_GAUNTLET: message = "was pummeled by"; break; +#endif + case MOD_MELEE: // BFP - Melee + message = "was beaten up by"; + break; case MOD_MACHINEGUN: message = "was machinegunned by"; break; @@ -677,14 +683,34 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { CG_FireWeapon( cent ); break; - case EV_MELEE_READY: - // DEBUGNAME("EV_MELEE_READY"); - break; - - // BFP - TODO: Implement EV_MELEE (when punching someone using Melee) + // BFP - Melee case EV_MELEE: + { + int rndMeleeSnd = rand() % 5; DEBUGNAME("EV_MELEE"); + switch ( rndMeleeSnd ) { + case 0: { + trap_S_StartSound (NULL, es->number, CHAN_BODY, CG_CustomSound( es->number, "sound/bfp/melee_hit1.wav" ) ); + break; + } + case 1: { + trap_S_StartSound (NULL, es->number, CHAN_BODY, CG_CustomSound( es->number, "sound/bfp/melee_hit2.wav" ) ); + break; + } + case 2: { + trap_S_StartSound (NULL, es->number, CHAN_BODY, CG_CustomSound( es->number, "sound/bfp/melee_hit3.wav" ) ); + break; + } + case 3: { + trap_S_StartSound (NULL, es->number, CHAN_BODY, CG_CustomSound( es->number, "sound/bfp/melee_hit4.wav" ) ); + break; + } + default: { + trap_S_StartSound (NULL, es->number, CHAN_BODY, CG_CustomSound( es->number, "sound/bfp/melee_hit5.wav" ) ); + } + } break; + } // BFP - TODO: Implement EV_TIER_0-4 (Tiers) case EV_TIER_0: diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index 90043f9..938732e 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -48,7 +48,10 @@ float pm_spectatorfriction = 5.0f; int c_pmove = 0; // BFP - TODO: Macro for torso handling, since the code looked repetitive, so this macro makes the code a bit shorter -#define TORSOSTATUS_ANIM_HANDLING(other_torsostatus) ( pm->ps->pm_flags & PMF_BLOCK ) ? PM_ContinueTorsoAnim( TORSO_BLOCK ) : PM_ContinueTorsoAnim( other_torsostatus ) +#define TORSOSTATUS_ANIM_HANDLING(other_torsostatus) \ + ( pm->ps->pm_flags & PMF_BLOCK ) ? PM_ContinueTorsoAnim( TORSO_BLOCK ) : \ + ( ( pm->cmd.buttons & BUTTON_MELEE ) && !( pm->ps->pm_flags & PMF_MELEE ) ) ? PM_ContinueTorsoAnim( TORSO_MELEE_READY ) : \ + ( pm->ps->pm_flags & PMF_MELEE ) ? PM_ContinueTorsoAnim( TORSO_MELEE_STRIKE ) : PM_ContinueTorsoAnim( other_torsostatus ) // BFP - Macro for jump handling, since the code looked repetitive, so this macro makes the code a bit shorter #define FORCEJUMP_ANIM_HANDLING() ( pm->cmd.forwardmove >= 0 ) ? PM_ForceLegsAnim( LEGS_JUMP ) : PM_ForceLegsAnim( LEGS_JUMPB ) @@ -59,6 +62,12 @@ int c_pmove = 0; else if ( pm->cmd.forwardmove < 0 ) { TORSOSTATUS_ANIM_HANDLING( TORSO_FLYB ); PM_ContinueLegsAnim( LEGS_FLYB ); } \ else { TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ); PM_ContinueLegsAnim( LEGS_FLYIDLE ); } +// BFP - Macro for melee strike handling, since the code looked repetitive, so this macro makes the code a bit shorter +#define CONTINUEMELEESTRIKE_LEGS_ANIM_HANDLING(condition) \ + /* Keep moving the legs when the player is attacking to the target through melee. If the condition variable isn't used leave using this value: 1 */ \ + if ( ( condition ) && ( pm->ps->pm_flags & PMF_MELEE ) \ + && !( pm->ps->pm_flags & PMF_HITSTUN ) && !( pm->ps->pm_flags & PMF_KI_CHARGE ) ) { PM_ContinueLegsAnim( LEGS_MELEE_STRIKE ); } + // BFP - Macro for movement handling in the slopes and when being near to the ground, since the code looked repetitive, so this macro makes the code a bit shorter #define SLOPES_NEARGROUND_ANIM_HANDLING(is_slope) \ if (is_slope) { \ @@ -78,7 +87,8 @@ int c_pmove = 0; return; \ } \ } \ - if ( !pm->cmd.forwardmove && !pm->cmd.rightmove ) { PM_ContinueLegsAnim( LEGS_IDLE ); return; } \ + /* If it's very near to the other entity and the melee strike is executed, continue playing the melee strike legs animation */ \ + if ( !pm->cmd.forwardmove && !pm->cmd.rightmove ) { PM_ContinueLegsAnim( LEGS_IDLE ); CONTINUEMELEESTRIKE_LEGS_ANIM_HANDLING( 1 ) return; } \ if ( !( pm->cmd.buttons & BUTTON_WALKING ) ) { \ if ( pm->cmd.forwardmove < 0 ) { PM_ContinueLegsAnim( LEGS_BACK ); TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ); } \ else if ( pm->cmd.forwardmove > 0 \ @@ -88,7 +98,8 @@ int c_pmove = 0; else if ( pm->cmd.forwardmove > 0 \ || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) ) { PM_ContinueLegsAnim( LEGS_WALK ); } \ TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ); \ - } + } \ + CONTINUEMELEESTRIKE_LEGS_ANIM_HANDLING( 1 ) /* =============== @@ -589,6 +600,9 @@ static void PM_WaterMove( void ) { // BFP - Water animation handling, uses flying animation in that case CONTINUEFLY_ANIM_HANDLING() + // BFP - Melee strike legs animation + CONTINUEMELEESTRIKE_LEGS_ANIM_HANDLING( 1 ) + PM_SlideMove( qfalse ); } @@ -1055,16 +1069,32 @@ static void PM_CrashLand( void ) { PM_CheckStuck ============= */ -/* -void PM_CheckStuck(void) { +static void PM_CheckStuck(void) { + // BFP - NOTE: Curiously and originally, BFP uses this function to animate when the player is stuck, + // that can be tested when the player is pretty near to the other player + // or being stuck in the same origin as the other player, specially outside water. + // It has been implemented when melee animations were being used trace_t trace; pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, pm->ps->origin, pm->ps->clientNum, pm->tracemask); if (trace.allsolid) { //int shit = qtrue; + + // BFP - TODO: Ki attack animation handling (these are for torso animations) + // Try to handle the animations when the player is shooting + + // BFP - Handle the animations when being stuck! (Only outside water) + if ( pm->waterlevel < 1 ) { + if ( pm->cmd.forwardmove < 0 ) { + PM_ContinueLegsAnim( LEGS_JUMPB ); + } else { + PM_ContinueLegsAnim( LEGS_JUMP ); + } + } + // BFP - Melee strike legs animation + CONTINUEMELEESTRIKE_LEGS_ANIM_HANDLING( 1 ) } } -*/ /* ============= @@ -1438,8 +1468,10 @@ static void PM_Footsteps( void ) { return; } - // BFP - Avoid when flying + // BFP - Avoid when flying (for melee strike animation, that's applied) if ( pm->ps->powerups[PW_FLIGHT] > 0 ) { + // BFP - Melee strike legs animation, don't apply if it's playing the starting jump animation in the flight status + CONTINUEMELEESTRIKE_LEGS_ANIM_HANDLING( pm->ps->pm_time <= 0 ) return; } @@ -1471,6 +1503,9 @@ static void PM_Footsteps( void ) { PM_ContinueLegsAnim( LEGS_SWIM ); } #endif + // BFP - PM_CheckStuck has been moved here, Q3 and the rest of mods hadn't used this + PM_CheckStuck(); + return; } @@ -1487,6 +1522,8 @@ static void PM_Footsteps( void ) { } else if ( !( pm->ps->pm_flags & PMF_DUCKED ) ) { // BFP - Handle the legs while it isn't doing nothing PM_ContinueLegsAnim( LEGS_IDLE ); } + // BFP - Melee strike legs animation + CONTINUEMELEESTRIKE_LEGS_ANIM_HANDLING( 1 ) return; } @@ -1539,6 +1576,9 @@ static void PM_Footsteps( void ) { } } + // BFP - Melee strike legs animation + CONTINUEMELEESTRIKE_LEGS_ANIM_HANDLING( 1 ) + // check for footstep / splash sounds old = pm->ps->bobCycle; pm->ps->bobCycle = (int)( old + bobmove * pml.msec ) & 255; @@ -1670,7 +1710,7 @@ static void PM_TorsoAnimation( void ) { trace_t trace; vec3_t point; - // BFP - TODO: Melee and ki attack animation handling (these are for torso animations) + // BFP - TODO: Ki attack animation handling (these are for torso animations) // Keep in mind about the implementations of the steep slopes, // TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ) and // !pm->cmd.forwardmove && !pm->cmd.rightmove && !pm->cmd.buttons thingies @@ -1717,6 +1757,9 @@ static void PM_TorsoAnimation( void ) { SLOPES_NEARGROUND_ANIM_HANDLING( 0 ) } + // BFP - Melee strike legs animation, don't apply if it isn't touching the ground + CONTINUEMELEESTRIKE_LEGS_ANIM_HANDLING( pm->ps->groundEntityNum != ENTITYNUM_NONE ) + #if 0 if ( pm->ps->weaponstate == WEAPON_READY ) { if ( pm->ps->weapon == WP_GAUNTLET ) { @@ -1853,6 +1896,20 @@ static void PM_HitStunAnimation( void ) { // BFP - Hit stun } } +/* +============== +PM_Melee +============== +*/ +static void PM_Melee( void ) { // BFP - Melee + // Don't allow pressing ki attack and block buttons when melee is being used + if ( ( pm->ps->pm_flags & PMF_MELEE ) + || ( pm->cmd.buttons & BUTTON_MELEE ) ) { + pm->cmd.buttons &= ~( BUTTON_ATTACK | BUTTON_BLOCK ); + } +} + + /* ============== PM_Weapon @@ -1907,6 +1964,11 @@ static void PM_Weapon( void ) { pm->ps->weaponTime -= pml.msec; } + // BFP - Hit stun melee delay time + if ( pm->ps->stats[STAT_HITSTUN_MELEE_DELAY] > 0 ) { + pm->ps->stats[STAT_HITSTUN_MELEE_DELAY] -= pml.msec; + } + // check for weapon change // can't change if weapon is firing, but can change // again if lowering or raising @@ -1926,6 +1988,16 @@ static void PM_Weapon( void ) { return; } + // BFP - Melee, avoid shooting if the player is in this status + if ( pm->cmd.buttons & BUTTON_MELEE ) { + // Melee fight handling + if ( pm->gauntletHit && pm->ps->weaponTime <= 0 ) { + pm->ps->weaponTime += 300; + pm->ps->pm_flags |= PMF_MELEE; + } + return; + } + // BFP - No weapon raising handling #if 0 if ( pm->ps->weaponstate == WEAPON_RAISING ) { @@ -2422,6 +2494,9 @@ void PmoveSingle (pmove_t *pmove) { // BFP - Block PM_BlockTime(); + // BFP - Melee + PM_Melee(); + PM_DropTimers(); // BFP - Flight @@ -2532,14 +2607,12 @@ void Pmove (pmove_t *pmove) { pmove->cmd.upmove = 20; } } - - //PM_CheckStuck(); - } // BFP - Undefine the macros #undef TORSOSTATUS_ANIM_HANDLING #undef FORCEJUMP_ANIM_HANDLING #undef CONTINUEFLY_ANIM_HANDLING +#undef CONTINUEMELEESTRIKE_LEGS_ANIM_HANDLING #undef SLOPES_NEARGROUND_ANIM_HANDLING diff --git a/source/game/bg_public.h b/source/game/bg_public.h index fc541a8..e3dfcba 100644 --- a/source/game/bg_public.h +++ b/source/game/bg_public.h @@ -148,6 +148,7 @@ typedef enum { #define PMF_NEARGROUND 8 // BFP - Near ground check // BFP - PMF_BACKWARDS_RUN is unused // #define PMF_BACKWARDS_RUN 16 // coast down to backwards run +#define PMF_MELEE 16 // BFP - Melee // BFP - PMF_TIME_LAND is unused // #define PMF_TIME_LAND 32 // pm_time is time before rejump #define PMF_FALLING 32 // BFP - Falling status @@ -220,6 +221,7 @@ typedef enum { STAT_HEALTH, STAT_KI, // BFP - KI amount STAT_BLOCK, // BFP - Block amount treated as time + STAT_HITSTUN_MELEE_DELAY, // BFP - Hitstun delay time status STAT_HOLDABLE_ITEM, STAT_WEAPONS, // 16 bit fields STAT_ARMOR, @@ -680,6 +682,7 @@ typedef enum { typedef enum { MOD_UNKNOWN, MOD_SHOTGUN, + MOD_MELEE, // BFP - Melee MOD_GAUNTLET, MOD_MACHINEGUN, MOD_GRENADE, diff --git a/source/game/g_active.c b/source/game/g_active.c index 5f43620..57b9dfd 100644 --- a/source/game/g_active.c +++ b/source/game/g_active.c @@ -816,6 +816,11 @@ void ClientThink_real( gentity_t *ent ) { } // BFP - End of block handling + // BFP - Melee handling + if ( !( ucmd->buttons & BUTTON_MELEE ) ) { + client->ps.pm_flags &= ~PMF_MELEE; + } + // BFP - Ki Charge if ( ( ucmd->buttons & BUTTON_KI_CHARGE ) && client->ps.pm_time <= 0 && ( client->ps.pm_flags & PMF_KI_CHARGE ) ) { @@ -845,12 +850,22 @@ void ClientThink_real( gentity_t *ent ) { memset (&pm, 0, sizeof(pm)); +// BFP - No gauntlet hit check +#if 0 // check for the hit-scan gauntlet, don't let the action // go through as an attack unless it actually hits something if ( client->ps.weapon == WP_GAUNTLET && !( ucmd->buttons & BUTTON_TALK ) && ( ucmd->buttons & BUTTON_ATTACK ) && client->ps.weaponTime <= 0 ) { pm.gauntletHit = CheckGauntletAttack( ent ); } +#endif + + // BFP - Melee + if ( !( ucmd->buttons & BUTTON_TALK ) && ( ucmd->buttons & BUTTON_MELEE ) + && !( client->ps.pm_flags & PMF_KI_CHARGE ) + && client->ps.weaponTime <= 0 ) { + pm.gauntletHit = CheckMeleeAttack( ent ); + } if ( ent->flags & FL_FORCE_GESTURE ) { ent->flags &= ~FL_FORCE_GESTURE; diff --git a/source/game/g_cmds.c b/source/game/g_cmds.c index 1b891a6..e700764 100644 --- a/source/game/g_cmds.c +++ b/source/game/g_cmds.c @@ -1703,12 +1703,12 @@ void Cmd_BFP_Block_f( gentity_t* ent ) { // BFP - Block } } -void Cmd_BFP_StartMelee_f( gentity_t* ent ) { // BFP - TODO: Start melee - Com_Printf( "Cmd_BFP_StartMelee_f\n" ); +void Cmd_BFP_StartMelee_f( gentity_t* ent ) { // BFP - Start melee + // BFP - NOTE: That command was left without finishing the implementation to start melee } -void Cmd_BFP_StopMelee_f( gentity_t* ent ) { // BFP - TODO: Stop melee - Com_Printf( "Cmd_BFP_StopMelee_f\n" ); +void Cmd_BFP_StopMelee_f( gentity_t* ent ) { // BFP - Stop melee + // BFP - NOTE: That command was left without finishing the implementation to stop melee } @@ -1833,9 +1833,9 @@ void ClientCommand( int clientNum ) { Cmd_BFP_SelectCharacter_f( ent ); else if (Q_stricmp (cmd, "block") == 0) // BFP - Block Cmd_BFP_Block_f( ent ); - else if (Q_stricmp (cmd, "start_melee") == 0) // BFP - TODO: Start melee + else if (Q_stricmp (cmd, "start_melee") == 0) // BFP - Start melee Cmd_BFP_StartMelee_f( ent ); - else if (Q_stricmp (cmd, "stop_melee") == 0) // BFP - TODO: Stop melee + else if (Q_stricmp (cmd, "stop_melee") == 0) // BFP - Stop melee Cmd_BFP_StopMelee_f( ent ); else trap_SendServerCommand( clientNum, va("print \"unknown cmd %s\n\"", cmd ) ); diff --git a/source/game/g_combat.c b/source/game/g_combat.c index 5cc36b8..d02469e 100644 --- a/source/game/g_combat.c +++ b/source/game/g_combat.c @@ -764,14 +764,6 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, damage *= 0.5; } -// BFP - TODO: Make hit stun received from melee attack with PW_HASTE -#if 0 - if ( g_hitStun.integer >= 1 && ( attacker->client->ps.powerups[PW_HASTE] > 0 ) - && targ != attacker && !OnSameTeam (targ, attacker) ) { - attacker->client->ps.hitStunTime = -3; // just an idea, enable the hit stun with a conditional of == -3 - } -#endif - // add to the attacker's hit counter (if the target isn't a general entity like a prox mine) if ( attacker->client && targ != attacker && targ->health > 0 && targ->s.eType != ET_MISSILE diff --git a/source/game/g_cvar.h b/source/game/g_cvar.h index fa78c7b..c0092b8 100644 --- a/source/game/g_cvar.h +++ b/source/game/g_cvar.h @@ -64,12 +64,12 @@ G_CVAR( g_blood, "com_blood", "1", 0, 0, qfalse ) G_CVAR( g_basePL, "g_basePL", "150", 0, 0, qtrue ) // BFP - Base powerlevel G_CVAR( g_allowSpectatorChat, "g_allowSpectatorChat", "", 0, 0, qtrue ) // BFP - Allow spectator chat -G_CVAR( g_meleeDamage, "g_meleeDamage", "10", 0, 0, qtrue ) // BFP - Melee damage -G_CVAR( g_meleeDiveRange, "g_meleeDiveRange", "700", 0, 0, qtrue ) // BFP - Melee dive range -G_CVAR( g_meleeRange, "g_meleeRange", "32", 0, 0, qtrue ) // BFP - Melee range +G_CVAR( g_meleeDamage, "g_meleeDamage", "10", CVAR_ARCHIVE, 0, qtrue ) // BFP - Melee damage +G_CVAR( g_meleeDiveRange, "g_meleeDiveRange", "700", CVAR_ARCHIVE, 0, qtrue ) // BFP - Melee dive range +G_CVAR( g_meleeRange, "g_meleeRange", "32", CVAR_ARCHIVE, 0, qtrue ) // BFP - Melee range G_CVAR( g_chargeDelay, "g_chargeDelay", "750", 0, 0, qtrue ) // BFP - Charge delay G_CVAR( g_hitStun, "g_hitStun", "", 0, 0, qtrue ) // BFP - Hit stun -G_CVAR( g_meleeOnly, "g_meleeOnly", "", 0, 0, qtrue ) // BFP - Melee only +G_CVAR( g_meleeOnly, "g_meleeOnly", "0", CVAR_SERVERINFO | CVAR_USERINFO | CVAR_LATCH | CVAR_ARCHIVE, 0, qtrue ) // BFP - Melee only G_CVAR( g_noFlight, "g_noFlight", "0", CVAR_SERVERINFO | CVAR_USERINFO | CVAR_LATCH | CVAR_ARCHIVE, 0, qtrue ) // BFP - No flight G_CVAR( g_plKillBonusPct, "g_plKillBonusPct", ".1", 0, 0, qtrue ) // BFP - Kill bonus percentage G_CVAR( g_maxSpawnPL, "g_maxSpawnPL", "999", 0, 0, qtrue ) // BFP - Max spawn powerlevel diff --git a/source/game/g_local.h b/source/game/g_local.h index a4af6f6..dd4dc11 100644 --- a/source/game/g_local.h +++ b/source/game/g_local.h @@ -544,7 +544,8 @@ void TeleportPlayer( gentity_t *player, vec3_t origin, vec3_t angles ); qboolean LogAccuracyHit( gentity_t *target, gentity_t *attacker ); void CalcMuzzlePoint ( gentity_t *ent, vec3_t forward, vec3_t right, vec3_t up, vec3_t muzzlePoint ); void SnapVectorTowards( vec3_t v, vec3_t to ); -qboolean CheckGauntletAttack( gentity_t *ent ); +// qboolean CheckGauntletAttack( gentity_t *ent ); // BFP - No check gauntlet attack +qboolean CheckMeleeAttack( gentity_t *ent ); // BFP - Melee void Weapon_HookFree (gentity_t *ent); void Weapon_HookThink (gentity_t *ent); diff --git a/source/game/g_weapon.c b/source/game/g_weapon.c index 5dc371e..e0060aa 100644 --- a/source/game/g_weapon.c +++ b/source/game/g_weapon.c @@ -61,6 +61,8 @@ void Weapon_Gauntlet( gentity_t *ent ) { } +// BFP - No check gauntlet attack +#if 0 /* =============== CheckGauntletAttack @@ -112,7 +114,168 @@ qboolean CheckGauntletAttack( gentity_t *ent ) { return qtrue; } +#endif + +/* +=================== +GetEntityNearMeleeRadius +=================== +*/ +gentity_t *GetEntityNearMeleeRadius( vec3_t point, gentity_t *attacker, gentity_t *target ) { // BFP - Melee near radius detection + int i, num, touch[MAX_GENTITIES]; + vec3_t mins, maxs; + gentity_t *prevTarget = target; + + // if already exists, don't apply calculation detection + if ( prevTarget->client ) { + return prevTarget; + } + + VectorAdd( point, attacker->r.mins, mins ); + VectorAdd( point, attacker->r.maxs, maxs ); + num = trap_EntitiesInBox( mins, maxs, touch, MAX_GENTITIES ); + + for ( i = 0 ; i < num ; i++ ) { + target = &g_entities[ touch[i] ]; + if ( target->client && target->client != attacker->client ) { + return target; + } + } + + return prevTarget; +} + +/* +=============== +CheckMeleeAttack +=============== +*/ +qboolean CheckMeleeAttack( gentity_t *attacker ) { // BFP - Melee + trace_t tr; + vec3_t velocity, end; + gentity_t *traceTarget; + + // set aiming directions + AngleVectors( attacker->client->ps.viewangles, forward, NULL, NULL ); + + CalcMuzzlePoint( attacker, forward, NULL, NULL, muzzle ); + VectorMA( muzzle, g_meleeDiveRange.integer, forward, end ); + + // that part is where the target can be detected when the attacker is on air, if not, the trace will be different + trap_Trace( &tr, muzzle, attacker->r.mins, attacker->r.maxs, end, attacker->s.number, MASK_SHOT ); + if ( attacker->client->ps.groundEntityNum != ENTITYNUM_NONE ) { + trap_Trace( &tr, muzzle, NULL, NULL, end, attacker->s.number, MASK_SHOT ); + } + + // when the attacker is very near from the target, continue attacking if that happens + traceTarget = GetEntityNearMeleeRadius( muzzle, attacker, &g_entities[ tr.entityNum ] ); + + // stop melee if there's no entity + if ( !traceTarget->takedamage ) { + attacker->client->ps.pm_flags &= ~PMF_MELEE; + return qfalse; + } + + // the target's corpse is starting to sink, avoid interacting with a sinking corpse, nothing special happens + if ( traceTarget->physicsObject ) { + attacker->client->ps.pm_flags &= ~PMF_MELEE; + return qfalse; + } + + // BFP - NOTE: Apply g_friendlyFire for melee, originally in BFP, friendly fire wasn't never applied + // stop melee if the entity is in the same team + if ( OnSameTeam( traceTarget, attacker ) ) { + attacker->client->ps.pm_flags &= ~PMF_MELEE; + return qfalse; + } + + // ENTITY DETECTED! + if ( traceTarget->client ) { + gentity_t *target; + vec3_t direction; + float distance; + // BFP - Melee range, it isn't known why, but it's the approximation + float rangeMultiplier = g_meleeRange.integer + 45; + + VectorSubtract( traceTarget->client->ps.origin, attacker->client->ps.origin, direction ); + distance = VectorLength( direction ); + + // distance from the attacker and the target, more range = attacker can attack at that distance without being teleported + // the distance needs to be greater than 25, otherwise it won't respect the lengths around the target + if ( distance >= rangeMultiplier && distance >= 25 ) { + // trace only when the player is alive + if ( traceTarget->client->ps.pm_type != PM_DEAD ) { + trap_Trace( &tr, muzzle, attacker->r.mins, attacker->r.maxs, end, attacker->s.number, MASK_PLAYERSOLID ); + } + + // if the target is very near to some brush (solid or surface with no impact) from the map + // avoid the attacker teleporting there, otherwise gets stuck + if ( tr.startsolid || tr.allsolid ) { + attacker->client->ps.pm_flags &= ~PMF_MELEE; + return qfalse; + } + + // if the target position is being covered under something solid (e.g. a brush from the map), + // avoid the attacker teleporting there, otherwise gets stuck + target = &g_entities[ tr.entityNum ]; + if ( target->client->ps.pm_type != PM_DEAD && !target->takedamage ) { + attacker->client->ps.pm_flags &= ~PMF_MELEE; + return qfalse; + } + + // try to trace when the target is dead, that's what BFP originally did, and teleport near the corpse + if ( traceTarget->client->ps.pm_type == PM_DEAD ) { + trap_Trace( &tr, muzzle, attacker->r.mins, attacker->r.maxs, end, attacker->s.number, MASK_PLAYERSOLID ); + } + + // TELEPORT! + if ( attacker->client->ps.origin[2] == target->client->ps.origin[2] ) { + tr.endpos[2] = target->client->ps.origin[2]; + } + VectorCopy( tr.endpos, attacker->client->ps.origin ); + } + + // PUSH AND DEAL DAMAGE! + if ( g_meleeDamage.integer > 0 ) { + float forceMultiplier = 100.0f + 2.0f * (g_meleeDamage.integer - 10); + + // only when the target isn't dead + if ( traceTarget->client->ps.pm_type != PM_DEAD ) { + VectorSubtract( traceTarget->client->ps.origin, attacker->client->ps.origin, velocity ); + VectorNormalize( velocity ); + + // apply the push force (proportional to the melee damage) in the direction of the attack + VectorScale( velocity, g_meleeDamage.integer * forceMultiplier, traceTarget->client->ps.velocity ); + } + + G_Damage ( traceTarget, attacker, attacker, velocity, attacker->s.origin, + g_meleeDamage.integer, 0, MOD_MELEE ); + } + } + + // melee sound event is randomly executed + { + int rndSnd = rand() % 6; + if ( rndSnd > 4 ) { + G_AddEvent( attacker, EV_MELEE, 0 ); + } + } + + // if the attacker is using ki boost, stun the target! (g_hitStun enabled only) + if ( g_hitStun.integer >= 1 + && attacker->client->ps.powerups[PW_HASTE] > 0 + && !( traceTarget->client->ps.pm_flags & PMF_HITSTUN ) + && !( traceTarget->client->ps.pm_flags & PMF_BLOCK ) + && attacker->client->ps.stats[STAT_HITSTUN_MELEE_DELAY] <= 0 ) { + // add 3 seconds to the hitstun when there's no delay + traceTarget->client->ps.pm_time = 3000; + traceTarget->client->ps.pm_flags |= PMF_HITSTUN; + attacker->client->ps.stats[STAT_HITSTUN_MELEE_DELAY] += 6000; + } + + return qtrue; +} /* ====================================================================== From 85af35905b08f62fb77dc67d5fb820a857679327 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sat, 1 Jun 2024 17:28:28 +0200 Subject: [PATCH 060/374] game: Replace some unnecessary STATs used as timers into gclient_s struct variables --- source/game/bg_pmove.c | 25 --------------------- source/game/bg_public.h | 2 -- source/game/g_active.c | 49 +++++++++++++++++++++++++++++------------ source/game/g_cmds.c | 2 +- source/game/g_local.h | 8 +++++++ source/game/g_weapon.c | 4 ++-- 6 files changed, 46 insertions(+), 44 deletions(-) diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index 938732e..0c2380d 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -1964,11 +1964,6 @@ static void PM_Weapon( void ) { pm->ps->weaponTime -= pml.msec; } - // BFP - Hit stun melee delay time - if ( pm->ps->stats[STAT_HITSTUN_MELEE_DELAY] > 0 ) { - pm->ps->stats[STAT_HITSTUN_MELEE_DELAY] -= pml.msec; - } - // check for weapon change // can't change if weapon is firing, but can change // again if lowering or raising @@ -2298,23 +2293,6 @@ static void PM_HitStun( void ) { // BFP - Hit stun pm->cmd.upmove = 0; } -/* -================ -PM_BlockTime - -Handle block status (treated as block time) -================ -*/ -static void PM_BlockTime( void ) { // BFP - Block - if ( pm->ps->stats[STAT_BLOCK] >= 0 ) { - pm->ps->stats[STAT_BLOCK] -= pml.msec; - // Print block length duration debug -#if 0 - Com_Printf( "BLOCK LENGTH: %d\n", pm->ps->stats[STAT_BLOCK] ); -#endif - } -} - /* ================ PmoveSingle @@ -2491,9 +2469,6 @@ void PmoveSingle (pmove_t *pmove) { PM_DeadMove (); } - // BFP - Block - PM_BlockTime(); - // BFP - Melee PM_Melee(); diff --git a/source/game/bg_public.h b/source/game/bg_public.h index e3dfcba..0666ad3 100644 --- a/source/game/bg_public.h +++ b/source/game/bg_public.h @@ -220,8 +220,6 @@ void Pmove (pmove_t *pmove); typedef enum { STAT_HEALTH, STAT_KI, // BFP - KI amount - STAT_BLOCK, // BFP - Block amount treated as time - STAT_HITSTUN_MELEE_DELAY, // BFP - Hitstun delay time status STAT_HOLDABLE_ITEM, STAT_WEAPONS, // 16 bit fields STAT_ARMOR, diff --git a/source/game/g_active.c b/source/game/g_active.c index 57b9dfd..0927979 100644 --- a/source/game/g_active.c +++ b/source/game/g_active.c @@ -732,6 +732,11 @@ void ClientThink_real( gentity_t *ent ) { client->ps.speed = g_speed.value; if ( client->ps.pm_type != PM_DEAD && client->ps.pm_type != PM_SPECTATOR ) { + // BFP - Hit stun melee delay time + if ( client->hitStunMeleeDelayTime > 0 + && level.time >= client->hitStunMeleeDelayTime ) { + client->hitStunMeleeDelayTime = 0; + } // BFP - Ki use has 2 options: "kiusetoggle" to toggle and "+button8" when key is being hold if ( !( client->ps.pm_flags & PMF_HITSTUN ) @@ -755,19 +760,19 @@ void ClientThink_real( gentity_t *ent ) { // Initialize the blocking and start the block length duration, specifically, ki boost and aura are disabled if ( !( client->ps.pm_flags & PMF_BLOCK ) && ( ucmd->buttons & BUTTON_BLOCK ) - && client->ps.stats[STAT_BLOCK] <= 0 ) { + && client->blockTime <= 0 + && client->blockDelayTime <= 0 ) { client->ps.pm_flags |= PMF_BLOCK; client->ps.powerups[PW_HASTE] = 0; client->ps.eFlags &= ~EF_AURA; ucmd->buttons &= ~BUTTON_KI_USE; - client->ps.stats[STAT_BLOCK] = (g_blockLength.integer * 1000); + client->blockTime = level.time + (g_blockLength.integer * 1000); } // BFP - Blocking status. Ki energy is being consumed and ki boost can't be used if ( ( client->ps.pm_flags & PMF_BLOCK ) - && client->ps.stats[STAT_BLOCK] <= (g_blockLength.integer * 1000) - && client->ps.stats[STAT_BLOCK] >= 0 ) { - + && client->blockTime > 0 + && level.time < client->blockTime ) { // BFP - NOTE: Approximate calculation of ki consumption while blocking float blockCostPct = g_blockCostPct.integer * 0.1; // Percentage of ki consumed per millisecond float bCost = g_blockCost.integer > 0 ? g_blockCost.integer : 1; // Absolute value of ki consumed per millisecond @@ -791,29 +796,45 @@ void ClientThink_real( gentity_t *ent ) { // When the block length duration has been expired, then start the delay to avoid user if ( ( client->ps.pm_flags & PMF_BLOCK ) - && client->ps.stats[STAT_BLOCK] <= (g_blockLength.integer * 1000) - && client->ps.stats[STAT_BLOCK] <= 0 ) { + && client->blockTime > 0 + && level.time >= client->blockTime ) { client->ps.pm_flags &= ~PMF_BLOCK; - client->ps.stats[STAT_BLOCK] = (g_blockDelay.integer * 1000); + client->blockTime = 0; + client->blockDelayTime = level.time + (g_blockDelay.integer * 1000); } // If the block length duration hasn't been expired yet and // pressing ki charge (if the aura is lighting) or attack buttons, then stop blocking and start the delay if ( ( client->ps.pm_flags & PMF_BLOCK ) - && ( ( ucmd->buttons & BUTTON_MELEE ) + && ( ( client->ps.pm_flags & PMF_KI_CHARGE ) + || ( ucmd->buttons & BUTTON_KI_CHARGE ) || ( ucmd->buttons & BUTTON_ATTACK ) - || ( client->ps.eFlags & EF_AURA ) ) ) { + || ( ucmd->buttons & BUTTON_MELEE ) ) ) { client->ps.pm_flags &= ~PMF_BLOCK; - client->ps.stats[STAT_BLOCK] = (g_blockDelay.integer * 1000); + client->blockTime = 0; + client->blockDelayTime = level.time + (g_blockDelay.integer * 1000); } + // Debug print block length and delay duration +#if 0 + Com_Printf( "BLOCK LENGTH: %d\n", client->blockTime ); + Com_Printf( "BLOCK DELAY: %d\n", client->blockDelayTime ); +#endif + // Handle the delay and don't leave the user get away with it if ( !( client->ps.pm_flags & PMF_BLOCK ) - && client->ps.stats[STAT_BLOCK] <= (g_blockDelay.integer * 1000) - && client->ps.stats[STAT_BLOCK] >= 0 ) { - client->ps.pm_flags &= ~PMF_BLOCK; + && client->blockDelayTime > 0 + && level.time < client->blockDelayTime ) { + client->blockTime = 0; ucmd->buttons &= ~BUTTON_BLOCK; // If the user holds the key, when that ends, then immediately enters to this status again } + + // Reset block delay time if expired + if ( !( client->ps.pm_flags & PMF_BLOCK ) + && client->blockDelayTime > 0 + && level.time >= client->blockDelayTime ) { + client->blockDelayTime = 0; + } // BFP - End of block handling // BFP - Melee handling diff --git a/source/game/g_cmds.c b/source/game/g_cmds.c index e700764..09f2b4a 100644 --- a/source/game/g_cmds.c +++ b/source/game/g_cmds.c @@ -1699,7 +1699,7 @@ void Cmd_BFP_Block_f( gentity_t* ent ) { // BFP - Block if ( ent->client->ps.pm_type != PM_DEAD ) { ent->client->ps.pm_flags |= PMF_BLOCK; - ent->client->ps.stats[STAT_BLOCK] = (g_blockLength.integer * 1000); + ent->client->blockTime = level.time + (g_blockLength.integer * 1000); } } diff --git a/source/game/g_local.h b/source/game/g_local.h index dd4dc11..0b74558 100644 --- a/source/game/g_local.h +++ b/source/game/g_local.h @@ -314,6 +314,14 @@ struct gclient_s { // like health / armor countdowns and regeneration int timeResidual; + // BFP - Hit stun melee delay time + int hitStunMeleeDelayTime; + + // BFP - Block timers + int blockTime; + int blockDelayTime; + + char *areabits; }; diff --git a/source/game/g_weapon.c b/source/game/g_weapon.c index e0060aa..b7190e0 100644 --- a/source/game/g_weapon.c +++ b/source/game/g_weapon.c @@ -267,11 +267,11 @@ qboolean CheckMeleeAttack( gentity_t *attacker ) { // BFP - Melee && attacker->client->ps.powerups[PW_HASTE] > 0 && !( traceTarget->client->ps.pm_flags & PMF_HITSTUN ) && !( traceTarget->client->ps.pm_flags & PMF_BLOCK ) - && attacker->client->ps.stats[STAT_HITSTUN_MELEE_DELAY] <= 0 ) { + && attacker->client->hitStunMeleeDelayTime <= 0 ) { // add 3 seconds to the hitstun when there's no delay traceTarget->client->ps.pm_time = 3000; traceTarget->client->ps.pm_flags |= PMF_HITSTUN; - attacker->client->ps.stats[STAT_HITSTUN_MELEE_DELAY] += 6000; + attacker->client->hitStunMeleeDelayTime = level.time + 6000; } return qtrue; From cf2e8f04516bd2dcf5b7178043be57a569925363 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Wed, 5 Jun 2024 00:23:42 +0200 Subject: [PATCH 061/374] game: Fix melee attack bug when player is dead --- source/game/g_active.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/game/g_active.c b/source/game/g_active.c index 0927979..5ac2404 100644 --- a/source/game/g_active.c +++ b/source/game/g_active.c @@ -884,7 +884,8 @@ void ClientThink_real( gentity_t *ent ) { // BFP - Melee if ( !( ucmd->buttons & BUTTON_TALK ) && ( ucmd->buttons & BUTTON_MELEE ) && !( client->ps.pm_flags & PMF_KI_CHARGE ) - && client->ps.weaponTime <= 0 ) { + && client->ps.weaponTime <= 0 + && client->ps.pm_type != PM_DEAD ) { pm.gauntletHit = CheckMeleeAttack( ent ); } From 3bab1854227460188cfcbd1d3459cb5007effd0c Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Wed, 5 Jun 2024 14:09:25 +0200 Subject: [PATCH 062/374] cgame - game: Implement Short-Range Teleport --- README.md | 2 +- source/cgame/cg_event.c | 6 ++ source/game/bg_public.h | 2 + source/game/g_active.c | 146 ++++++++++++++++++++++++++++++++++++++++ source/game/g_local.h | 6 ++ 5 files changed, 161 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cead704..94fca28 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ A legendary 90s era Quake 3 Arena mod. - [x] ~~Hit Stun (makes player can't use ki, melee, block and charge)~~ - [ ] Power Struggles (when two beam attacks collide) - [x] ~~Blocking (consumes ki energy, transfers all damage to ki instead of health, deflect missile attacks, more info on old docs)~~ -- [ ] Short-Range Teleport (when pressing 2 times left or right) +- [x] ~~Short-Range Teleport - Zanzoken (when pressing 2 times left or right)~~ - [ ] Transformations (related to Power Tiers) - [ ] Attacksets (configurable for cfgs) - [ ] Skin Config File (explosionModel, explosionShader, missileRotation, missileShader, ... look old docs about that. "Custom plugin models") diff --git a/source/cgame/cg_event.c b/source/cgame/cg_event.c index 9023f6a..177cc61 100644 --- a/source/cgame/cg_event.c +++ b/source/cgame/cg_event.c @@ -712,6 +712,12 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { break; } + // BFP - Short-Range Teleport (Zanzoken) + case EV_ZANZOKEN: + DEBUGNAME("EV_ZANZOKEN"); + trap_S_StartSound (NULL, es->number, CHAN_BODY, CG_CustomSound( es->number, "sound/bfp/srteleport.wav" ) ); + break; + // BFP - TODO: Implement EV_TIER_0-4 (Tiers) case EV_TIER_0: DEBUGNAME("EV_TIER_0"); diff --git a/source/game/bg_public.h b/source/game/bg_public.h index 0666ad3..35c3692 100644 --- a/source/game/bg_public.h +++ b/source/game/bg_public.h @@ -361,6 +361,8 @@ typedef enum { EV_MELEE_READY, // BFP - EV_MELEE_READY (10), preparing melee EV_MELEE, // BFP - EV_MELEE (11), melee attack + EV_ZANZOKEN, // BFP - EV_ZANZOKEN (maybe 12?), ki teleport + // EV_TIER_RESET, // EV_TIER_RESET (13), reset tier when the player respawns and changes to the default or a bit less ki energy? // BFP - EV_TIER_0-4 (14-18), when the player frags, increases their PL and obtains a new skill (in the last tier, transforms) diff --git a/source/game/g_active.c b/source/game/g_active.c index 5ac2404..e64eabf 100644 --- a/source/game/g_active.c +++ b/source/game/g_active.c @@ -631,6 +631,148 @@ void FlyingThink( gentity_t *ent, usercmd_t *ucmd ) { // BFP - Flight } } +/* +============ +Zanzoken +============ +*/ +qboolean Zanzoken( gentity_t *ent, int range ) { // BFP - Short-Range Teleport (Zanzoken) + trace_t tr; + vec3_t right, up, start, direction; + int startRightRange = ( range < 0 ) ? -10 : 10; + + // set diagonal direction, included the up vector for upward detection + AngleVectors( ent->client->ps.viewangles, NULL, right, up ); + + // upward detection, avoid if the player is touching the surface above + VectorMA( ent->client->ps.origin, 10, up, start ); + VectorMA( start, 100, up, direction ); + + trap_Trace( &tr, start, ent->r.mins, ent->r.maxs, direction, ent->s.number, MASK_PLAYERSOLID ); + if ( tr.startsolid || tr.allsolid ) { + return qfalse; + } + + // if there's something solid diagonally, then avoid the teleportation + VectorMA( ent->client->ps.origin, startRightRange, right, start ); + VectorMA( ent->client->ps.origin, range, right, direction ); + + trap_Trace( &tr, start, ent->r.mins, ent->r.maxs, direction, ent->s.number, MASK_PLAYERSOLID ); + if ( tr.startsolid || tr.allsolid ) { + return qfalse; + } + + // TELEPORT! + VectorCopy( tr.endpos, ent->client->ps.origin ); + + // sound event + G_AddEvent( ent, EV_ZANZOKEN, 0 ); + + return qtrue; +} + +/* +================= +ZanzokenHandling +================= +*/ +#define ZANZOKEN_NUMBER_TIMES_ALLOWED 20 +#define ZANZOKEN_ABUSE_DELAY 2000 +static void ZanzokenHandling( gentity_t *ent, usercmd_t *ucmd ) { // BFP - Handling short-range teleport + // zanzoken cannot be used with ki charging status + if ( !( ent->client->ps.pm_flags & PMF_KI_CHARGE ) ) { + // restriction: stop abusing zanzoken technique all time + if ( ent->client->zanzokenNumberTimesAllowed >= ZANZOKEN_NUMBER_TIMES_ALLOWED ) { + ent->client->zanzokenNumberTimesAllowed = 0; + ent->client->zanzokenDelay = level.time; + return; + } + if ( ent->client->zanzokenDelay > 0 + && level.time - ent->client->zanzokenDelay <= ZANZOKEN_ABUSE_DELAY ) { + return; + } + + if ( ucmd->rightmove && ent->client->zanzokenPressTime <= 0 ) { + ent->client->zanzokenPressTime = level.time; + ent->client->zanzokenNow = qfalse; + // handle directions to avoid pressing the opposite + if ( ucmd->rightmove > 0 ) { + ent->client->zanzokenLeft = qfalse; + ent->client->zanzokenRight = qtrue; + } else { + ent->client->zanzokenLeft = qtrue; + ent->client->zanzokenRight = qfalse; + } + } + + // once pressed and having one moment to press again, zanzoken will be possible at these milliseconds + if ( !ucmd->rightmove + && level.time - ent->client->zanzokenPressTime > 100 + && level.time - ent->client->zanzokenPressTime <= 250 + && !ent->client->zanzokenNow ) { + ent->client->zanzokenNow = qtrue; + ent->client->zanzokenNumberTimesAllowed++; + } + + if ( !ucmd->rightmove + && level.time - ent->client->zanzokenPressTime > 250 ) { + ent->client->zanzokenNumberTimesAllowed = 0; + ent->client->zanzokenPressTime = 0; + ent->client->zanzokenNow = qfalse; + ent->client->zanzokenLeft = qfalse; + ent->client->zanzokenRight = qfalse; + return; + } + + // BFP - TODO: Zanzoken ki consume looks relative to powerlevel and the maximum ki quantity + // (so, if it's 8160 as ki max quantity, then consumes 408) + if ( ent->client->ps.stats[STAT_KI] > 408 + && ucmd->rightmove + && ent->client->zanzokenNow ) { + int range = ( ucmd->rightmove > 0 ) ? 500 : -500; + + // handle the directions correctly + if ( ucmd->rightmove > 0 && !ent->client->zanzokenRight ) { + ent->client->zanzokenLeft = qfalse; + ent->client->zanzokenRight = qfalse; + return; + } + if ( ucmd->rightmove < 0 && !ent->client->zanzokenLeft ) { + ent->client->zanzokenLeft = qfalse; + ent->client->zanzokenRight = qfalse; + return; + } + + // put in 1 second delay before the player can 'zanzoken' out of stun + if ( ( ent->client->ps.pm_flags & PMF_HITSTUN ) + && ent->client->ps.pm_time > 2000 ) { + ent->client->zanzokenPressTime = 0; + ent->client->zanzokenNow = qfalse; + ent->client->zanzokenLeft = qfalse; + ent->client->zanzokenRight = qfalse; + return; + } + + if ( Zanzoken( ent, range ) ) { + // block and stun statuses are removed when using zanzoken + if ( ( ent->client->ps.pm_flags & PMF_HITSTUN ) + && ent->client->ps.pm_time <= 2000 ) { + ent->client->ps.pm_flags &= ~PMF_HITSTUN; + ent->client->ps.pm_time = 0; + } + ent->client->ps.pm_flags &= ~PMF_BLOCK; + ent->client->ps.stats[STAT_KI] -= 408; + ent->client->zanzokenPressTime = 0; + ent->client->zanzokenNow = qfalse; + ent->client->zanzokenLeft = qfalse; + ent->client->zanzokenRight = qfalse; + } + } + } +} +#undef ZANZOKEN_NUMBER_TIMES_ALLOWED +#undef ZANZOKEN_ABUSE_DELAY + /* ============== ClientThink @@ -732,6 +874,10 @@ void ClientThink_real( gentity_t *ent ) { client->ps.speed = g_speed.value; if ( client->ps.pm_type != PM_DEAD && client->ps.pm_type != PM_SPECTATOR ) { + + // BFP - Short-Range Teleport (Zanzoken) + ZanzokenHandling( ent, ucmd ); + // BFP - Hit stun melee delay time if ( client->hitStunMeleeDelayTime > 0 && level.time >= client->hitStunMeleeDelayTime ) { diff --git a/source/game/g_local.h b/source/game/g_local.h index 0b74558..e2fac23 100644 --- a/source/game/g_local.h +++ b/source/game/g_local.h @@ -321,6 +321,12 @@ struct gclient_s { int blockTime; int blockDelayTime; + // BFP - Zanzoken handlers + int zanzokenPressTime; + qboolean zanzokenNow; + qboolean zanzokenLeft, zanzokenRight; + int zanzokenNumberTimesAllowed; + int zanzokenDelay; char *areabits; }; From e3a18af1f0ba0b538c23f3d1b7200e9f45fff33c Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Wed, 5 Jun 2024 20:08:41 +0200 Subject: [PATCH 063/374] game: Refactor block handling into a function --- source/game/g_active.c | 167 +++++++++++++++++++++-------------------- 1 file changed, 87 insertions(+), 80 deletions(-) diff --git a/source/game/g_active.c b/source/game/g_active.c index e64eabf..9cd1391 100644 --- a/source/game/g_active.c +++ b/source/game/g_active.c @@ -631,6 +631,92 @@ void FlyingThink( gentity_t *ent, usercmd_t *ucmd ) { // BFP - Flight } } +/* +================= +BlockHandling +================= +*/ +static void BlockHandling( gclient_t *client, usercmd_t *ucmd ) { // BFP - Block, reflect ki attacks and reduce health damage + // initialize the blocking and start the block length duration, specifically, ki boost and aura are disabled + if ( !( client->ps.pm_flags & PMF_BLOCK ) + && ( ucmd->buttons & BUTTON_BLOCK ) + && client->blockTime <= 0 + && client->blockDelayTime <= 0 ) { + client->ps.pm_flags |= PMF_BLOCK; + client->ps.powerups[PW_HASTE] = 0; + client->ps.eFlags &= ~EF_AURA; + ucmd->buttons &= ~BUTTON_KI_USE; + client->blockTime = level.time + (g_blockLength.integer * 1000); + } + + // BFP - Blocking status. Ki energy is being consumed and ki boost can't be used + if ( ( client->ps.pm_flags & PMF_BLOCK ) + && client->blockTime > 0 + && level.time < client->blockTime ) { + // BFP - NOTE: Approximate calculation of ki consumption while blocking + float blockCostPct = g_blockCostPct.integer * 0.1; // percentage of ki consumed per millisecond + float bCost = g_blockCost.integer > 0 ? g_blockCost.integer : 1; // absolute value of ki consumed per millisecond + float kiBlockConsume = bCost / (g_blockLength.integer * 1000.0); + float totalBlockConsume; + // random variable to make an approximate calculation of the ki consumption while using block + float rndkiConsume = rand() % 2; + + // BFP - TODO: Implement random calculations correctly? + if ( crandom() > 0.5 && crandom() < 0.8 ) { + rndkiConsume = rand() % 1; + } else if ( crandom() > 0.2 && crandom() < 0.5 ) { + rndkiConsume = random() + 0.38; + } + + // calculate total ki being consumed + totalBlockConsume = kiBlockConsume * (g_blockLength.integer * 1000.0) * rndkiConsume; + + client->ps.stats[STAT_KI] -= totalBlockConsume; + } + + // when the block length duration has been expired, then start the delay to avoid user + if ( ( client->ps.pm_flags & PMF_BLOCK ) + && client->blockTime > 0 + && level.time >= client->blockTime ) { + client->ps.pm_flags &= ~PMF_BLOCK; + client->blockTime = 0; + client->blockDelayTime = level.time + (g_blockDelay.integer * 1000); + } + + // if the block length duration hasn't been expired yet and + // pressing ki charge (if the aura is lighting) or attack buttons, then stop blocking and start the delay + if ( ( client->ps.pm_flags & PMF_BLOCK ) + && ( ( client->ps.pm_flags & PMF_KI_CHARGE ) + || ( ucmd->buttons & BUTTON_KI_CHARGE ) + || ( ucmd->buttons & BUTTON_ATTACK ) + || ( ucmd->buttons & BUTTON_MELEE ) ) ) { + client->ps.pm_flags &= ~PMF_BLOCK; + client->blockTime = 0; + client->blockDelayTime = level.time + (g_blockDelay.integer * 1000); + } + + // debug print block length and delay duration +#if 0 + Com_Printf( "BLOCK LENGTH: %d\n", client->blockTime ); + Com_Printf( "BLOCK DELAY: %d\n", client->blockDelayTime ); +#endif + + // handle the delay and don't leave the user get away with it + if ( !( client->ps.pm_flags & PMF_BLOCK ) + && client->blockDelayTime > 0 + && level.time < client->blockDelayTime ) { + client->blockTime = 0; + ucmd->buttons &= ~BUTTON_BLOCK; // if the user holds the key, when that ends, then immediately enters to this status again + } + + // reset block delay time if expired + if ( !( client->ps.pm_flags & PMF_BLOCK ) + && client->blockDelayTime > 0 + && level.time >= client->blockDelayTime ) { + client->blockDelayTime = 0; + } +} + /* ============ Zanzoken @@ -902,86 +988,7 @@ void ClientThink_real( gentity_t *ent ) { } // BFP - Block, reflect ki attacks and reduce health damage - // Block handling: - // Initialize the blocking and start the block length duration, specifically, ki boost and aura are disabled - if ( !( client->ps.pm_flags & PMF_BLOCK ) - && ( ucmd->buttons & BUTTON_BLOCK ) - && client->blockTime <= 0 - && client->blockDelayTime <= 0 ) { - client->ps.pm_flags |= PMF_BLOCK; - client->ps.powerups[PW_HASTE] = 0; - client->ps.eFlags &= ~EF_AURA; - ucmd->buttons &= ~BUTTON_KI_USE; - client->blockTime = level.time + (g_blockLength.integer * 1000); - } - - // BFP - Blocking status. Ki energy is being consumed and ki boost can't be used - if ( ( client->ps.pm_flags & PMF_BLOCK ) - && client->blockTime > 0 - && level.time < client->blockTime ) { - // BFP - NOTE: Approximate calculation of ki consumption while blocking - float blockCostPct = g_blockCostPct.integer * 0.1; // Percentage of ki consumed per millisecond - float bCost = g_blockCost.integer > 0 ? g_blockCost.integer : 1; // Absolute value of ki consumed per millisecond - float kiBlockConsume = bCost / (g_blockLength.integer * 1000.0); - float totalBlockConsume; - // Random variable to make an approximate calculation of the ki consumption while using block - float rndkiConsume = rand() % 2; - - // BFP - TODO: Implement random calculations correctly? - if ( crandom() > 0.5 && crandom() < 0.8 ) { - rndkiConsume = rand() % 1; - } else if ( crandom() > 0.2 && crandom() < 0.5 ) { - rndkiConsume = random() + 0.38; - } - - // Calculate total ki being consumed - totalBlockConsume = kiBlockConsume * (g_blockLength.integer * 1000.0) * rndkiConsume; - - client->ps.stats[STAT_KI] -= totalBlockConsume; - } - - // When the block length duration has been expired, then start the delay to avoid user - if ( ( client->ps.pm_flags & PMF_BLOCK ) - && client->blockTime > 0 - && level.time >= client->blockTime ) { - client->ps.pm_flags &= ~PMF_BLOCK; - client->blockTime = 0; - client->blockDelayTime = level.time + (g_blockDelay.integer * 1000); - } - - // If the block length duration hasn't been expired yet and - // pressing ki charge (if the aura is lighting) or attack buttons, then stop blocking and start the delay - if ( ( client->ps.pm_flags & PMF_BLOCK ) - && ( ( client->ps.pm_flags & PMF_KI_CHARGE ) - || ( ucmd->buttons & BUTTON_KI_CHARGE ) - || ( ucmd->buttons & BUTTON_ATTACK ) - || ( ucmd->buttons & BUTTON_MELEE ) ) ) { - client->ps.pm_flags &= ~PMF_BLOCK; - client->blockTime = 0; - client->blockDelayTime = level.time + (g_blockDelay.integer * 1000); - } - - // Debug print block length and delay duration -#if 0 - Com_Printf( "BLOCK LENGTH: %d\n", client->blockTime ); - Com_Printf( "BLOCK DELAY: %d\n", client->blockDelayTime ); -#endif - - // Handle the delay and don't leave the user get away with it - if ( !( client->ps.pm_flags & PMF_BLOCK ) - && client->blockDelayTime > 0 - && level.time < client->blockDelayTime ) { - client->blockTime = 0; - ucmd->buttons &= ~BUTTON_BLOCK; // If the user holds the key, when that ends, then immediately enters to this status again - } - - // Reset block delay time if expired - if ( !( client->ps.pm_flags & PMF_BLOCK ) - && client->blockDelayTime > 0 - && level.time >= client->blockDelayTime ) { - client->blockDelayTime = 0; - } - // BFP - End of block handling + BlockHandling( client, ucmd ); // BFP - Melee handling if ( !( ucmd->buttons & BUTTON_MELEE ) ) { From b61d55f11b5ca9eccccd2e952a1dfd2832a3d689 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Tue, 11 Jun 2024 00:01:30 +0200 Subject: [PATCH 064/374] cgame: Fix First Person vis mode head model display and apply dead camera view when using this view mode like BFP originally did --- source/cgame/cg_players.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index 04ed4bc..30b99de 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -2298,12 +2298,6 @@ void CG_Player( centity_t *cent ) { head.hModel = 0; // 0: no head model display, display pivot only } - // BFP - First person vis mode doesn't have head model to be displayed - if ( cg_drawOwnModel.integer >= 1 && cg_thirdPerson.integer <= 0 - && clientNum == cg.snap->ps.clientNum - && !( cent->currentState.eFlags & EF_DEAD ) ) { - head.hModel = 2; // 2: no head model display and no pivot display - } head.customSkin = ci->headSkin; // BFP - Super Deformed (Chibi style) easter egg for the head model @@ -2318,6 +2312,13 @@ void CG_Player( centity_t *cent ) { head.shadowPlane = shadowPlane; head.renderfx = renderfx; + // BFP - First person vis mode doesn't have head model to be displayed + if ( cg_drawOwnModel.integer >= 1 && cg_thirdPerson.integer <= 0 + && clientNum == cg.snap->ps.clientNum + && !( cent->currentState.eFlags & EF_DEAD ) ) { + memset( &head, 0, sizeof(head) ); + } + CG_AddRefEntityWithPowerups( &head, ¢->currentState, ci->team ); // @@ -2490,7 +2491,17 @@ void CG_Player( centity_t *cent ) { // BFP - First person camera setup if ( cg_thirdPerson.integer <= 0 && clientNum == cg.snap->ps.clientNum ) { // BFP - Avoid every time some player/bot enters in the server and changes the view into the other player - CG_OffsetFirstPersonView( cent, &torso, ci->torsoModel ); + static vec3_t deadOriginDrawOwnModel; + + if ( !( cent->currentState.eFlags & EF_DEAD ) ) { + // BFP - Set dead origin where the player was alive when First person vis mode is being used + VectorCopy( cg.refdef.vieworg, deadOriginDrawOwnModel ); + CG_OffsetFirstPersonView( cent, &torso, ci->torsoModel ); + } else if ( cg.snap->ps.stats[STAT_HEALTH] <= 0 + && ( cent->currentState.eFlags & EF_DEAD ) ) { + VectorCopy( deadOriginDrawOwnModel, cg.refdef.vieworg ); + cg.refdefViewAngles[YAW] = cg.snap->ps.stats[STAT_DEAD_YAW]; + } } } #undef MODEL_SIZE From ee7feae35d368eb47a6db0233ed980677d4829c1 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Thu, 13 Jun 2024 01:28:25 +0200 Subject: [PATCH 065/374] cgame: Adjust turbulent bubbles and antigrav rock particles, reduce MAX_PARTICLES limit multiplying by 3, make antigrav rock, fix when player runs above the ground and near the water's edge, fix antigrav rock particles when the player was dead and has been respawned, and remove unused parameter in bubble particle function --- source/cgame/cg_event.c | 10 ++--- source/cgame/cg_local.h | 2 +- source/cgame/cg_particles.c | 73 +++++++++++++++++++++---------------- source/cgame/cg_players.c | 36 +++++++++--------- source/cgame/cg_weapons.c | 6 +-- 5 files changed, 70 insertions(+), 57 deletions(-) diff --git a/source/cgame/cg_event.c b/source/cgame/cg_event.c index 177cc61..692d08d 100644 --- a/source/cgame/cg_event.c +++ b/source/cgame/cg_event.c @@ -599,11 +599,11 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { vec3_t end = {0, 0, 1}; // Blub, blub, blub... - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 700, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 700, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 700, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 700, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 700, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 700, 20 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 700, 20 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 700, 20 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 700, 20 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 700, 20 ); } break; case EV_WATER_CLEAR: diff --git a/source/cgame/cg_local.h b/source/cgame/cg_local.h index a5accff..bf95501 100644 --- a/source/cgame/cg_local.h +++ b/source/cgame/cg_local.h @@ -1493,7 +1493,7 @@ void CG_ParticleDust (centity_t *cent, vec3_t origin, vec3_t dir); void CG_ParticleMisc (qhandle_t pshader, vec3_t origin, int size, int duration, float alpha); void CG_ParticleExplosion (char *animStr, vec3_t origin, vec3_t vel, int duration, int sizeStart, int sizeEnd); // BFP - Bubble particle -void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_t origin2, int turbtime, float range, int snum); +void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_t origin2, int turbtime, float range); // BFP - Dash smoke particle for ki boost when moving in the ground void CG_ParticleDashSmoke (centity_t *cent, qhandle_t pshader, vec3_t origin); // BFP - Antigrav rock particles for charging diff --git a/source/cgame/cg_particles.c b/source/cgame/cg_particles.c index 20e2b49..b54a06e 100644 --- a/source/cgame/cg_particles.c +++ b/source/cgame/cg_particles.c @@ -125,7 +125,7 @@ static int numShaderAnims; // done. #define PARTICLE_GRAVITY 40 -#define MAX_PARTICLES 1024 * 8 +#define MAX_PARTICLES 1024 * 3 static cparticle_t *active_particles, *free_particles; static cparticle_t particles[MAX_PARTICLES]; @@ -934,7 +934,7 @@ void CG_AddParticles (void) active_particles = active; } -void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_t origin2, int turbtime, float range, int snum) +void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_t origin2, int turbtime, float range) { cparticle_t *p; @@ -970,20 +970,24 @@ void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_ p->endtime = timenonscaled + turbtime; p->height = p->width = (rand() % 1) + 2; - p->org[0] += (rand() % (int)range) + (crandom() * range); - p->org[1] += (rand() % (int)range) + (crandom() * range); + p->org[0] += (crandom() * range); + p->org[1] += (crandom() * range); p->org[2] += (rand() % (int)20); VectorSet( p->vel, - (rand() % 401) - 200, - (rand() % 401) - 200, - 20 ); + (rand() % 521) - 250, + (rand() % 521) - 250, + 30 * (rand() % (int)range) ); // dispersion VectorSet( p->accel, crandom() * 10, crandom() * 10, - 300 ); + 20 * (rand() % (int)range) ); + + // avoid if both upwards are zero or less + if ( p->vel[2] <= 0 ) p->vel[2] = 10 + (rand() % (int)range); + if ( p->accel[2] <= 0 ) p->accel[2] = 10 + (rand() % (int)range); } else { @@ -1014,6 +1018,7 @@ void CG_BubblesWaterHandling( cparticle_t *p, vec3_t org ) { trace_t trace; vec3_t start, end; int contents; + int i; VectorCopy( org, end ); end[2] -= 15; @@ -1021,45 +1026,49 @@ void CG_BubblesWaterHandling( cparticle_t *p, vec3_t org ) { VectorCopy( org, start ); start[2] += 10; - // BFP - Make move less - if ( p->vel[0] > -0.9 && p->vel[0] < 0.9 ) p->vel[0] = 0; - if ( p->vel[1] > -0.9 && p->vel[1] < 0.9 ) p->vel[1] = 0; - if ( p->vel[0] != 0 ) p->vel[0] *= 0.99; - if ( p->vel[1] != 0 ) p->vel[1] *= 0.99; + // decelerate + for (i = 0; i < 2; ++i) { + if (fabs(p->vel[i]) > 0) { + p->vel[i] *= 0.99; + } + } - // Decelerate - if ( p->accel[2] > 0 ) p->accel[2]--; + for (i = 0; i < 2; ++i) { + if (fabs(p->accel[i]) > 0) { + p->accel[i] *= 0.99; + } + } // trace down to find the surface trap_CM_BoxTrace( &trace, start, end, vec3_origin, vec3_origin, 0, CONTENTS_WATER ); // if the particle is touching something solid, it will skip instead stopping - contents = trap_CM_PointContents( start, 0 ); + contents = trap_CM_PointContents( trace.endpos, 0 ); if ( contents & (CONTENTS_WATER | CONTENTS_SOLID) ) { return; } - contents = trap_CM_PointContents( trace.endpos, 0 ); if ( !( contents & CONTENTS_WATER ) ) { p->time = timenonscaled; VectorCopy (trace.endpos, p->org); p->org[2] = trace.endpos[2] - p->snum; + // stop going up and decrease dispersion speed + p->vel[2] = 0; + VectorClear( p->accel ); + // trace again if the bubble went outside, then set it near to the surface contents = trap_CM_PointContents( p->org, 0 ); if ( !( contents & CONTENTS_WATER ) ) { - p->org[2] = trace.endpos[2]; + VectorCopy (trace.endpos, p->org); + } + if ( p->type == P_BUBBLE ) { + if ( p->vel[0] != 0 ) p->vel[0] *= 0.9; + if ( p->vel[1] != 0 ) p->vel[1] *= 0.9; + } else { + if ( p->vel[0] != 0 ) p->vel[0] *= 0.99; + if ( p->vel[1] != 0 ) p->vel[1] *= 0.99; } - - // BFP - Stop going up and decrease dispersion speed - p->vel[2] = 0; - VectorClear( p->accel ); - - // BFP - Make move less - if ( p->vel[0] >= -1 && p->vel[0] <= 0.9 ) p->vel[0] = 0; - else p->vel[0] *= 0.9; - if ( p->vel[1] >= -1 && p->vel[1] <= 0.9 ) p->vel[1] = 0; - else p->vel[1] *= 0.9; } } @@ -1152,7 +1161,7 @@ void CG_ParticleAntigravRock (qhandle_t pshader, centity_t *cent, vec3_t origin) p->alpha = 1; p->alphavel = 0; p->pshader = pshader; - p->height = p->width = 2 + (crandom() * 0.5); + p->height = p->width = (rand() % 2) + 2; p->type = P_ANTIGRAV_ROCK; VectorCopy( origin, p->org ); @@ -1164,14 +1173,14 @@ void CG_ParticleAntigravRock (qhandle_t pshader, centity_t *cent, vec3_t origin) // maybe BFP used to debug the client side visual of the other player with this top limit p->end = (cent->currentState.clientNum != cg.snap->ps.clientNum) ? p->org[2] + 130 + (crandom() * 10) - : p->org[2] + 170 + (crandom() * 10); + : p->org[2] + 200 + (crandom() * 10); p->vel[0] = 0; p->vel[1] = 0; // maybe BFP used to debug the client side visual of the other player with this velocity p->vel[2] = (cent->currentState.clientNum != cg.snap->ps.clientNum) ? 200 - : 470; + : 450; p->accel[0] = 0; p->accel[1] = 0; @@ -1196,6 +1205,7 @@ void CG_AntigravRockHandling (centity_t *cent) if (p->type == P_ANTIGRAV_ROCK) { if ( cent->currentState.clientNum == cg.snap->ps.clientNum + && !( cent->currentState.eFlags & EF_DEAD ) && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_CHARGE ) { // BFP - Make each particle fall when they aren't on ki charging status @@ -1209,6 +1219,7 @@ void CG_AntigravRockHandling (centity_t *cent) // to correct the client side visuals in this case if ( cent->currentState.clientNum != cg.snap->ps.clientNum && ( cent->currentState.eFlags & EF_AURA ) + && !( cent->currentState.eFlags & EF_DEAD ) && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE && !p->snum ) { // use p->snum to handle the client side visual of the other player p->link = qfalse; // keep this way, otherwise the rocks fall diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index 30b99de..074856d 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -1859,7 +1859,7 @@ static qboolean CG_PlayerShadow( centity_t *cent, float *shadowPlane ) { vec3_t end, mins = {-15, -15, 0}, maxs = {15, 15, 2}; trace_t trace, waterTrace; // BFP - Trace for the water float alpha; - int contents; // BFP - To detect if there is water or lava + int contents, waterContents; // BFP - To detect if there is water or lava *shadowPlane = 0; @@ -1888,15 +1888,17 @@ static qboolean CG_PlayerShadow( centity_t *cent, float *shadowPlane ) { } waterTrace.endpos[2] -= 20; // BFP - Put a bit down to make the bubbles move - if ( waterTrace.fraction >= 0.10f && waterTrace.fraction <= 0.70f ) { - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, waterTrace.endpos, end, 700, 10, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, waterTrace.endpos, end, 700, 10, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, waterTrace.endpos, end, 700, 10, 0 ); + if ( ( contents & CONTENTS_WATER ) + && waterTrace.fraction >= 0.10f && waterTrace.fraction <= 0.70f ) { + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, waterTrace.endpos, end, 700, 10 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, waterTrace.endpos, end, 700, 10 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, waterTrace.endpos, end, 700, 10 ); } } + waterContents = CG_PointContents( cent->lerpOrigin, -1 ); // BFP - Detect if the player is entirely under water if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE ) { // BFP - Antigrav rock particles on ki charging status - if ( !( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) + if ( !( waterContents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) // if the player isn't moving && !cent->currentState.pos.trDelta[0] && !cent->currentState.pos.trDelta[1] @@ -2398,19 +2400,19 @@ void CG_Player( centity_t *cent ) { if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYA || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYB ) { - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 700, 10, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 700, 10, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 700, 10, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 700, 10 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 700, 10 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 700, 10 ); } else if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE ) { bubbleOrigin[2] += -7; // put the origin a little below - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20, 0 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20 ); } } @@ -2441,7 +2443,7 @@ void CG_Player( centity_t *cent ) { // trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), 1.0, 1.0, 0 ); // Apply light blinking - if ( ci->team == TEAM_BLUE) { + if ( ci->team == TEAM_BLUE ) { aura.customShader = aura2.customShader = cgs.media.auraBlueShader; AURA_LIGHT( 0.2f, 0.2f, 1.0 ) } else { diff --git a/source/cgame/cg_weapons.c b/source/cgame/cg_weapons.c index 0f2e243..0a56d1a 100644 --- a/source/cgame/cg_weapons.c +++ b/source/cgame/cg_weapons.c @@ -329,9 +329,9 @@ static void CG_RocketTrail( centity_t *ent, const weaponInfo_t *wi ) { if ( ( contents & lastContents & CONTENTS_WATER ) && cg.frametime > 0.0f ) { // BFP - If paused, don't spawn bubble particles (cg_paused.integer < 1 is another solution, but not good enough for server responses) // BFP - Apply particle bubble effect in that case - CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 1200, 20, 0 ); - CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 1200, 20, 0 ); - CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 1200, 20, 0 ); + CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 1200, 10 ); + CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 1200, 10 ); + CG_ParticleBubble( ent, cgs.media.waterBubbleShader, origin, lastPos, 1200, 10 ); // CG_BubbleTrail( lastPos, origin, 8 ); } return; From 957260d6735c09b1f7bedddf8e620fbcbca2e593 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 1 Jul 2024 20:26:43 +0200 Subject: [PATCH 066/374] cgame: Undo the camera orbit third person change and apply cg_cameraOrbitDelay when it's being used --- source/cgame/cg_consolecmds.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/cgame/cg_consolecmds.c b/source/cgame/cg_consolecmds.c index fa6328a..36f6bc1 100644 --- a/source/cgame/cg_consolecmds.c +++ b/source/cgame/cg_consolecmds.c @@ -181,9 +181,10 @@ static void CG_StartOrbit_f( void ) { } if (cg_cameraOrbit.value != 0) { trap_Cvar_Set ("cg_cameraOrbit", "0"); - // trap_Cvar_Set("cg_thirdPerson", "0"); // BFP - don't disable even when restarting the server + trap_Cvar_Set ("cg_thirdPerson", "0"); } else { trap_Cvar_Set("cg_cameraOrbit", "5"); + trap_Cvar_Set("cg_cameraOrbitDelay", "50"); trap_Cvar_Set("cg_thirdPerson", "1"); trap_Cvar_Set("cg_thirdPersonAngle", "0"); trap_Cvar_Set("cg_thirdPersonRange", "110"); From 59f821e8c1381ecee2dfa758a186c344a21265af Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 1 Jul 2024 20:29:21 +0200 Subject: [PATCH 067/374] cgame - game: Implement ki attack sample animations, just for testing reasons, handled at the logical sense, but still needs to implement about reading the files to set the ki attacks and set the attacksets to every character; and the explanation of this has been commented in bg_pmove.c so as not to forget how to start that big implementation. Implement ki attack charge points (included in the HUD), implement READY when ki attack is charged, add ki attack sounds, add g_chargeDelay cvar when using ki charge and add divide ki ball feature to test on plasma weapon. Positionate correctly STUN in the HUD, apply death camera only for First person vis mode, fix underwater bubble particles when the player is very near to the ground and encapsulate function for melee and some dirty unused code removal --- source/cgame/cg_cvar.h | 1 + source/cgame/cg_draw.c | 45 +++- source/cgame/cg_local.h | 6 + source/cgame/cg_main.c | 8 + source/cgame/cg_players.c | 37 +++- source/cgame/cg_weapons.c | 5 + source/game/bg_pmove.c | 445 +++++++++++++++++++++++++------------- source/game/bg_public.h | 11 +- source/game/g_active.c | 293 +++++++++++++++++++++---- source/game/g_client.c | 3 - source/game/g_cvar.h | 2 +- source/game/g_local.h | 5 + source/game/g_missile.c | 122 +++++++++++ 13 files changed, 782 insertions(+), 201 deletions(-) diff --git a/source/cgame/cg_cvar.h b/source/cgame/cg_cvar.h index 44a6883..57caa11 100644 --- a/source/cgame/cg_cvar.h +++ b/source/cgame/cg_cvar.h @@ -31,6 +31,7 @@ CG_CVAR( cg_drawAttacker, "cg_drawAttacker", "1", CVAR_ARCHIVE ) CG_CVAR( cg_drawCrosshair, "cg_drawCrosshair", "4", CVAR_ARCHIVE ) CG_CVAR( cg_drawCrosshairNames, "cg_drawCrosshairNames", "1", CVAR_ARCHIVE ) CG_CVAR( cg_drawRewards, "cg_drawRewards", "1", CVAR_ARCHIVE ) +CG_CVAR( cg_chargeupAlert, "cg_chargeupAlert", "1", CVAR_ARCHIVE ) // BFP - Ready message when charging attacks CG_CVAR( cg_crosshairColor, "cg_crosshairColor", "7", CVAR_ARCHIVE ) // BFP - Crosshair color CG_CVAR( cg_crosshairSize, "cg_crosshairSize", "24", CVAR_ARCHIVE ) CG_CVAR( cg_crosshairHealth, "cg_crosshairHealth", "1", CVAR_ARCHIVE ) diff --git a/source/cgame/cg_draw.c b/source/cgame/cg_draw.c index b546fe4..e8d6ee2 100644 --- a/source/cgame/cg_draw.c +++ b/source/cgame/cg_draw.c @@ -2084,10 +2084,49 @@ static void CG_DrawHitStun( void ) { // BFP - Hit stun bottom centerprint s = "Stun"; } w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; - UI_DrawProportionalString( 320 - w / 2, SCREEN_HEIGHT - ( BIGCHAR_HEIGHT * 6 ) + 23, + UI_DrawProportionalString( 320 - w / 2, SCREEN_HEIGHT - ( BIGCHAR_HEIGHT * 6 ) + 24, s, UI_SMALLFONT, colorWhite ); if ( t > 0 && ( cg.predictedPlayerState.pm_flags & PMF_HITSTUN ) ) { - CG_DrawField ( 320 - w - 16, SCREEN_HEIGHT - ( BIGCHAR_HEIGHT * 4 ) + 13, 3, t ); + CG_DrawField ( 320 - w - 16, SCREEN_HEIGHT - ( BIGCHAR_HEIGHT * 4 ) + 12, 3, t ); + } +} + +/* +================= +CG_DrawReadyKiAttack +================= +*/ +static void CG_DrawReadyKiAttack( void ) { // BFP - Ready message in the bottom centerprint when charging attacks + const char *s; + int w; + + s = ""; // avoid printing when there are no status changes, for dll and shared objects + if ( cg_chargeupAlert.integer <= 0 ) { // if disabled, don't show it + return; + } + if ( cg.predictedPlayerState.stats[STAT_READY_KI_ATTACK] ) { + s = "Ready"; + } + w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH; + UI_DrawProportionalString( 327 - w / 2, SCREEN_HEIGHT - ( BIGCHAR_HEIGHT * 6 ) + 76, + s, UI_SMALLFONT, colorWhite ); +} + +/* +===================== +CG_DrawKiAttackChargeUpPoints +===================== +*/ +static void CG_DrawKiAttackChargeUpPoints( void ) { // BFP - Ki attack charge up points + int x = 105, y = 412, i; + + if ( cg.predictedPlayerState.stats[STAT_KI_ATTACK_CHARGE] > 0 ) { + for ( i = 1; i <= 6; ++i ) { + if ( cg.predictedPlayerState.stats[STAT_KI_ATTACK_CHARGE] >= i ) { + CG_DrawPic( x, y, BIGCHAR_WIDTH - 2, BIGCHAR_HEIGHT - 2, cgs.media.chargeupbuttgreen ); + } + x += 16; + } } } @@ -2245,6 +2284,8 @@ static void CG_Draw2D( void ) { CG_DrawStatusBar(); CG_DrawKiWarning(); // BFP - ki warning CG_DrawHitStun(); // BFP - Hit stun bottom centerprint + CG_DrawKiAttackChargeUpPoints(); // BFP - Ki attack charge up points + CG_DrawReadyKiAttack(); // BFP - Ready message in the bottom centerprint when charging attacks CG_DrawCrosshair(); CG_DrawCrosshairNames(); CG_DrawWeaponSelect(); diff --git a/source/cgame/cg_local.h b/source/cgame/cg_local.h index bf95501..b059d32 100644 --- a/source/cgame/cg_local.h +++ b/source/cgame/cg_local.h @@ -711,6 +711,9 @@ typedef struct { qhandle_t backTileShader; qhandle_t noammoShader; + // BFP - Ki attack charge up points + qhandle_t chargeupbuttgreen; + qhandle_t smokePuffShader; qhandle_t smokePuffRageProShader; qhandle_t shotgunSmokePuffShader; @@ -914,6 +917,9 @@ typedef struct { sfxHandle_t kiChargeSound; // BFP - Ki charge sound sfxHandle_t kiUseSound; // BFP - Ki use sound + sfxHandle_t defaultKiBeamExplosionWaveSound; // BFP - Default ki beam and ki explosion wave sound + sfxHandle_t defaultKiFiringAttackSound; // BFP - Default ki firing sound + sfxHandle_t defaultKiChargingSound; // BFP - Default ki attack charging sound } cgMedia_t; diff --git a/source/cgame/cg_main.c b/source/cgame/cg_main.c index 7d656b1..355d6ef 100644 --- a/source/cgame/cg_main.c +++ b/source/cgame/cg_main.c @@ -468,6 +468,11 @@ static void CG_RegisterSounds( void ) { cgs.media.kiChargeSound = trap_S_RegisterSound("sound/bfp/kicharge1.wav", qfalse); // BFP - Ki charge sound cgs.media.kiUseSound = trap_S_RegisterSound("sound/bfp/kiuse1.wav", qfalse); // BFP - Ki use sound + cgs.media.defaultKiChargingSound = trap_S_RegisterSound("sound/bfp/attackcharge1.wav", qfalse); // BFP - Default ki charging attack sound + + // BFP - NOTE: Sounds like that are reusing Q3 ones + cgs.media.defaultKiBeamExplosionWaveSound = trap_S_RegisterSound("sound/weapons/rocket/rockfly.wav", qfalse); // BFP - Default ki beam and ki explosion wave sound + cgs.media.defaultKiFiringAttackSound = trap_S_RegisterSound("sound/weapons/bfg/bfg_fire.wav", qfalse); // BFP - Default ki firing sound } @@ -548,6 +553,9 @@ static void CG_RegisterGraphics( void ) { cgs.media.backTileShader = trap_R_RegisterShader( "gfx/2d/backtile" ); cgs.media.noammoShader = trap_R_RegisterShader( "icons/noammo" ); + // BFP - Ki attack charge up points + cgs.media.chargeupbuttgreen = trap_R_RegisterShader( "menu/art/chargeupbuttgreen" ); + // powerup shaders cgs.media.quadShader = trap_R_RegisterShader("powerups/quad" ); cgs.media.quadWeaponShader = trap_R_RegisterShader("powerups/quadWeapon" ); diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index 074856d..297704c 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -1773,6 +1773,35 @@ static void CG_PlayerPowerups( centity_t *cent, refEntity_t *torso ) { } +/* +=============== +CG_KiAttackSounds +=============== +*/ +static void CG_KiAttackSounds( centity_t *cent ) { // BFP - Ki attack sounds + switch ( cg.predictedPlayerState.weaponstate ) { + case WEAPON_KIEXPLOSIONWAVE: + trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, + vec3_origin, cgs.media.defaultKiBeamExplosionWaveSound ); + break; + case WEAPON_BEAMFIRING: + trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, + vec3_origin, cgs.media.defaultKiBeamExplosionWaveSound ); + break; + case WEAPON_FIRING: + // ki attacks like eyebeam shouldn't use that kind of firing sound + if ( cg.predictedPlayerState.weapon != WP_LIGHTNING ) { + trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, + vec3_origin, cgs.media.defaultKiFiringAttackSound ); + } + break; + case WEAPON_CHARGING: + trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, + vec3_origin, cgs.media.defaultKiChargingSound ); + } +} + + /* =============== CG_PlayerFloatSprite @@ -2404,7 +2433,7 @@ void CG_Player( centity_t *cent ) { CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 700, 10 ); CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 700, 10 ); } else if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE ) { - bubbleOrigin[2] += -7; // put the origin a little below + bubbleOrigin[2] += -3; // put the origin a little below CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20 ); CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20 ); @@ -2482,6 +2511,9 @@ void CG_Player( centity_t *cent ) { } } + // BFP - Ki attack sounds + CG_KiAttackSounds( cent ); + // // add the gun / barrel / flash // @@ -2500,7 +2532,8 @@ void CG_Player( centity_t *cent ) { VectorCopy( cg.refdef.vieworg, deadOriginDrawOwnModel ); CG_OffsetFirstPersonView( cent, &torso, ci->torsoModel ); } else if ( cg.snap->ps.stats[STAT_HEALTH] <= 0 - && ( cent->currentState.eFlags & EF_DEAD ) ) { + && ( cent->currentState.eFlags & EF_DEAD ) + && cg_drawOwnModel.integer >= 1 ) { // BFP - Death camera only for First person vis VectorCopy( deadOriginDrawOwnModel, cg.refdef.vieworg ); cg.refdefViewAngles[YAW] = cg.snap->ps.stats[STAT_DEAD_YAW]; } diff --git a/source/cgame/cg_weapons.c b/source/cgame/cg_weapons.c index 0a56d1a..3dc4950 100644 --- a/source/cgame/cg_weapons.c +++ b/source/cgame/cg_weapons.c @@ -1578,6 +1578,11 @@ void CG_FireWeapon( centity_t *cent ) { } } + // BFP - Just testing, WP_SHOTGUN treated as ki explosion example + if ( ent->weapon == WP_SHOTGUN ) { + return; + } + // play quad sound if needed if ( cent->currentState.powerups & ( 1 << PW_QUAD ) ) { trap_S_StartSound (NULL, cent->currentState.number, CHAN_ITEM, cgs.media.quadSound ); diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index 0c2380d..feeb028 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -47,11 +47,70 @@ float pm_spectatorfriction = 5.0f; int c_pmove = 0; -// BFP - TODO: Macro for torso handling, since the code looked repetitive, so this macro makes the code a bit shorter +// BFP - Macro for torso handling when using ki attacks, since the code looked repetitive, so this macro makes the code a bit shorter +/* BFP - TODO: When implementing ki attacks, look up about the properties of the ki attacks from cfg and correct animation changes if required +And tweak pmove_t struct, so we can handle that on g_active.c (like gauntletHit), adding: +attackType ("beam", "hitscan", "missile", "rdmissile", "sbeam" or "forcefield"), // type of attack +randomWeaponTime (int, number of miliseconds), // random weapon time, maybe the max msec range of the random value +chargeAttack (int / qboolean), // charging yes or no +chargeAutoFire (int / qboolean), // even if it's charging the ki attack, fire +minCharge (int [0-6]), // min charge points +maxCharge (int [0-6]), // max charge points +loopAnim (int / qboolean), // Maybe it's: use PM_ContinueTorsoAnim, if not: PM_StartTorsoAnim +noAttackAnim (int / qboolean), // no animation strike yes or no +priority (int [0-2]), // if 2, it'll act like a overpowered forcefield, if 1 like a beam, if 0 nothing +movementPenalty (int, number of seconds) // enters WEAPON_STUN when the ki attack was being used +----- +The following sample testing torso ki attack animations are used with: +(ultimate_blast) WP_BFG would be "beam", chargeAttack 1, chargeAutoFire 0, loopingAnim 0, noAttackAnim 0, priority 1, movementPenalty 0 +(finger_blast) WP_MACHINEGUN would be "hitscan", chargeAttack 0, chargeAutoFire 0, loopingAnim 1, noAttackAnim 0, priority 0, movementPenalty 0 +(ki_blast) WP_ROCKET_LAUNCHER would be "missile", chargeAttack 0, chargeAutoFire 0, loopingAnim 0, noAttackAnim 0, priority 0, movementPenalty 0 +(super_homing) WP_GRENADE_LAUNCHER would be "missile", chargeAttack 1, chargeAutoFire 0, loopingAnim 1, noAttackAnim 0, priority 0, movementPenalty 0 +(finger_beam) WP_RAILGUN would be "hitscan", chargeAttack 0, chargeAutoFire 0, loopingAnim 0, noAttackAnim 0, priority 0, movementPenalty 0 +(eyebeam) WP_LIGHTNING would be "hitscan", chargeAttack 0, chargeAutoFire 0, loopingAnim 0, noAttackAnim 0, priority 0, movementPenalty 0 +(homing_special) WP_PLASMAGUN would be "rdmissile", chargeAttack 1, chargeAutoFire 0, loopingAnim 0, noAttackAnim 0, priority 0, movementPenalty 0 +(aga) WP_SHOTGUN would be "forcefield", chargeAttack 1, chargeAutoFire 1, loopingAnim 1, noAttackAnim 0, priority 2, movementPenalty 2 +(blinding_flash) would be "forcefield", chargeAttack 1, chargeAutoFire 0, loopingAnim 0, noAttackAnim 1, priority 0, movementPenalty 0 + +About "sbeam" attackType would be like a beam that, by holding down the attack key, +you direct it wherever you want by moving the cursor. +If you stop pressing the attack key, it explodes to the point where it arrived. +This attackType was originally left unfinished, +so there's a bug: after colliding the beam into something solid and +keep holding down the attack key, keeps muzzling and +doesn't shoot anything while the ki is wasted out of control. +*/ +#define KI_ATTACK_TORSO_ANIM_HANDLING() \ + if ( ( pm->cmd.buttons & BUTTON_ATTACK ) && !( pm->ps->pm_flags & PMF_KI_ATTACK ) ) { \ + switch( pm->ps->weapon ) { \ + case WP_ROCKET_LAUNCHER: { PM_StartTorsoAnim( TORSO_ATTACK1_PREPARE ); break; } \ + case WP_GRENADE_LAUNCHER: { PM_ContinueTorsoAnim( TORSO_ATTACK2_PREPARE ); break; } \ + case WP_RAILGUN: { PM_StartTorsoAnim( TORSO_ATTACK3_PREPARE ); break; } \ + case WP_PLASMAGUN: { PM_ContinueTorsoAnim( TORSO_ATTACK3_PREPARE ); break; } \ + case WP_SHOTGUN: \ + case WP_BFG: { PM_ContinueTorsoAnim( TORSO_ATTACK4_PREPARE ); break; } \ + } \ + } else if ( pm->ps->pm_flags & PMF_KI_ATTACK ) { \ + pm->cmd.buttons &= ~BUTTON_GESTURE; \ + switch( pm->ps->weapon ) { \ + default: \ + case WP_MACHINEGUN: { PM_ContinueTorsoAnim( TORSO_ATTACK0_STRIKE ); break; } \ + case WP_ROCKET_LAUNCHER: { PM_ContinueTorsoAnim( TORSO_ATTACK1_STRIKE ); break; } \ + case WP_GRENADE_LAUNCHER: { PM_ContinueTorsoAnim( TORSO_ATTACK2_STRIKE ); break; } \ + case WP_PLASMAGUN: \ + case WP_RAILGUN: { PM_ContinueTorsoAnim( TORSO_ATTACK3_STRIKE ); break; } \ + case WP_SHOTGUN: \ + case WP_BFG: { PM_ContinueTorsoAnim( TORSO_ATTACK4_STRIKE ); break; } \ + } \ + } + +// BFP - Macro for torso handling, since the code looked repetitive, so this macro makes the code a bit shorter #define TORSOSTATUS_ANIM_HANDLING(other_torsostatus) \ - ( pm->ps->pm_flags & PMF_BLOCK ) ? PM_ContinueTorsoAnim( TORSO_BLOCK ) : \ - ( ( pm->cmd.buttons & BUTTON_MELEE ) && !( pm->ps->pm_flags & PMF_MELEE ) ) ? PM_ContinueTorsoAnim( TORSO_MELEE_READY ) : \ - ( pm->ps->pm_flags & PMF_MELEE ) ? PM_ContinueTorsoAnim( TORSO_MELEE_STRIKE ) : PM_ContinueTorsoAnim( other_torsostatus ) + if ( pm->ps->pm_flags & PMF_BLOCK ) PM_ContinueTorsoAnim( TORSO_BLOCK ); \ + else if ( ( pm->cmd.buttons & BUTTON_MELEE ) && !( pm->ps->pm_flags & PMF_MELEE ) ) PM_ContinueTorsoAnim( TORSO_MELEE_READY ); \ + else if ( pm->ps->pm_flags & PMF_MELEE ) PM_ContinueTorsoAnim( TORSO_MELEE_STRIKE ); \ + else KI_ATTACK_TORSO_ANIM_HANDLING() \ + else PM_ContinueTorsoAnim( other_torsostatus ) // BFP - Macro for jump handling, since the code looked repetitive, so this macro makes the code a bit shorter #define FORCEJUMP_ANIM_HANDLING() ( pm->cmd.forwardmove >= 0 ) ? PM_ForceLegsAnim( LEGS_JUMP ) : PM_ForceLegsAnim( LEGS_JUMPB ) @@ -1080,9 +1139,6 @@ static void PM_CheckStuck(void) { if (trace.allsolid) { //int shit = qtrue; - // BFP - TODO: Ki attack animation handling (these are for torso animations) - // Try to handle the animations when the player is shooting - // BFP - Handle the animations when being stuck! (Only outside water) if ( pm->waterlevel < 1 ) { if ( pm->cmd.forwardmove < 0 ) { @@ -1232,9 +1288,21 @@ static void PM_GroundTrace( void ) { && !( pm->ps->pm_flags & PMF_NEARGROUND ) ) { if ( pml.groundTrace.contents & MASK_PLAYERSOLID ) { // do a smooth jump animation like BFP does - if ( !( pm->cmd.buttons & BUTTON_KI_CHARGE ) ) { - pm->ps->pm_time = 500; + if ( !( pm->cmd.buttons & BUTTON_KI_CHARGE ) + && pm->ps->weaponstate != WEAPON_KIEXPLOSIONWAVE + && pm->ps->weaponstate != WEAPON_STUN ) { + pm->ps->pm_time = 550; pm->ps->velocity[2] = JUMP_VELOCITY; + if ( !( pm->ps->pm_flags & PMF_KI_ATTACK ) + && !( pm->ps->pm_flags & PMF_MELEE ) ) { + if ( pm->cmd.forwardmove > 0 ) { + TORSOSTATUS_ANIM_HANDLING( TORSO_FLYA ); + } else if ( pm->cmd.forwardmove < 0 ) { + TORSOSTATUS_ANIM_HANDLING( TORSO_FLYB ); + } else { + TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ); + } + } PM_ForceLegsAnim( LEGS_JUMP ); } pml.groundPlane = qfalse; // jumping away @@ -1468,6 +1536,19 @@ static void PM_Footsteps( void ) { return; } + // BFP - Ki explosion wave state + if ( pm->ps->weaponstate == WEAPON_KIEXPLOSIONWAVE ) { + PM_ContinueLegsAnim( LEGS_IDLE ); + return; + } + + // BFP - Ki explosion wave stun state + if ( pm->ps->weaponstate == WEAPON_STUN ) { + PM_ContinueTorsoAnim( TORSO_STUN ); + PM_ContinueLegsAnim( LEGS_IDLE ); + return; + } + // BFP - Avoid when flying (for melee strike animation, that's applied) if ( pm->ps->powerups[PW_FLIGHT] > 0 ) { // BFP - Melee strike legs animation, don't apply if it's playing the starting jump animation in the flight status @@ -1488,30 +1569,23 @@ static void PM_Footsteps( void ) { + pm->ps->velocity[1] * pm->ps->velocity[1] ); if ( pm->ps->groundEntityNum == ENTITYNUM_NONE ) { + // BFP - PM_CheckStuck has been moved here, Q3 and the rest of mods hadn't used this + PM_CheckStuck(); - // BFP - Unused -#if 0 - if ( pm->ps->powerups[PW_INVULNERABILITY] ) { - PM_ContinueLegsAnim( LEGS_IDLECR ); - } -#endif - - // BFP - Unused -#if 0 - // airborne leaves position in cycle intact, but doesn't advance + // BFP - Water animation handling, uses flying animation in that case + // also keep the torso if ( pm->waterlevel > 1 ) { - PM_ContinueLegsAnim( LEGS_SWIM ); + CONTINUEFLY_ANIM_HANDLING() + } else { + // BFP - Keep the torso when using a ki attack even after charged + KI_ATTACK_TORSO_ANIM_HANDLING() } -#endif - // BFP - PM_CheckStuck has been moved here, Q3 and the rest of mods hadn't used this - PM_CheckStuck(); return; } // if not trying to move - if ( !pm->cmd.forwardmove && !pm->cmd.rightmove - && !( pm->ps->pm_flags & PMF_HITSTUN ) ) { + if ( !pm->cmd.forwardmove && !pm->cmd.rightmove ) { if ( pm->xyspeed < 5 ) { pm->ps->bobCycle = 0; // start at beginning of cycle again if ( pm->ps->pm_flags & PMF_DUCKED ) { @@ -1667,7 +1741,8 @@ static void PM_BeginWeaponChange( int weapon ) { PM_AddEvent( EV_CHANGE_WEAPON ); pm->ps->weaponstate = WEAPON_DROPPING; - pm->ps->weaponTime += 200; + // BFP - Don't add weaponTime when changing ki attack + // pm->ps->weaponTime += 200; // BFP - Non-existant animation // PM_StartTorsoAnim( TORSO_DROP ); } @@ -1692,7 +1767,8 @@ static void PM_FinishWeaponChange( void ) { pm->ps->weapon = weapon; pm->ps->weaponstate = WEAPON_RAISING; - pm->ps->weaponTime += 250; + // BFP - Don't add weaponTime when changing ki attack + // pm->ps->weaponTime += 250; // BFP - Non-existant animation // PM_StartTorsoAnim( TORSO_RAISE ); } @@ -1710,11 +1786,6 @@ static void PM_TorsoAnimation( void ) { trace_t trace; vec3_t point; - // BFP - TODO: Ki attack animation handling (these are for torso animations) - // Keep in mind about the implementations of the steep slopes, - // TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ) and - // !pm->cmd.forwardmove && !pm->cmd.rightmove && !pm->cmd.buttons thingies - // BFP - No ground trace handling in the water if ( pm->waterlevel > 1 ) { return; @@ -1849,10 +1920,6 @@ static void PM_KiChargeAnimation( void ) { // BFP - Ki Charge } if ( pm->cmd.buttons & BUTTON_KI_CHARGE ) { - // do a smooth ki charge animation and appearing the aura like BFP does - if ( !( pm->ps->pm_flags & PMF_KI_CHARGE ) ) { - pm->ps->pm_time = 300; - } pm->ps->powerups[PW_HASTE] = 0; pm->ps->pm_flags |= PMF_KI_CHARGE; PM_ContinueTorsoAnim( TORSO_CHARGE ); @@ -1909,6 +1976,35 @@ static void PM_Melee( void ) { // BFP - Melee } } +/* +============== +PM_KiExplosionWave + +Handle ki explosion wave during and at the end of its use +============== +*/ +static void PM_KiExplosionWave( void ) { // BFP - Ki explosion wave handling + // ki explosion wave state + if ( pm->ps->weaponstate == WEAPON_KIEXPLOSIONWAVE ) { + // don't move, also these keys cannot be used; blocking, ki charge and ki boost statuses are removed + pm->cmd.forwardmove = pm->cmd.rightmove = pm->cmd.upmove = 0; + pm->cmd.buttons &= ~( BUTTON_KI_USE | BUTTON_KI_CHARGE | BUTTON_BLOCK ); + pm->ps->pm_flags &= ~( PMF_KI_CHARGE | PMF_BLOCK ); + pm->ps->powerups[PW_HASTE] = 0; + return; + } + + // ki explosion wave stun state + if ( pm->ps->weaponstate == WEAPON_STUN ) { + // don't move, also these keys cannot be used; melee, attacking, blocking, ki charge and ki boost statuses are removed + pm->cmd.forwardmove = pm->cmd.rightmove = pm->cmd.upmove = 0; + pm->cmd.buttons &= ~( BUTTON_ATTACK | BUTTON_KI_CHARGE | BUTTON_KI_USE | BUTTON_BLOCK | BUTTON_MELEE ); + pm->ps->pm_flags &= ~( PMF_KI_ATTACK | PMF_KI_CHARGE | PMF_BLOCK | PMF_MELEE ); + pm->ps->powerups[PW_HASTE] = 0; + return; + } +} + /* ============== @@ -1922,6 +2018,9 @@ static void PM_Weapon( void ) { // BFP - Hit stun, avoid shooting if the player is in this status if ( pm->ps->pm_flags & PMF_HITSTUN ) { + pm->ps->stats[STAT_READY_KI_ATTACK] = qfalse; + pm->ps->stats[STAT_KI_ATTACK_CHARGE] = 0; + pm->ps->weaponTime = 0; return; } @@ -1958,7 +2057,6 @@ static void PM_Weapon( void ) { pm->ps->pm_flags &= ~PMF_USE_ITEM_HELD; } - // make weapon function if ( pm->ps->weaponTime > 0 ) { pm->ps->weaponTime -= pml.msec; @@ -1967,24 +2065,29 @@ static void PM_Weapon( void ) { // check for weapon change // can't change if weapon is firing, but can change // again if lowering or raising - if ( pm->ps->weaponTime <= 0 || pm->ps->weaponstate != WEAPON_FIRING ) { + if ( pm->ps->weaponstate != WEAPON_BEAMFIRING // BFP - Avoid if the beam is still firing + && pm->ps->weaponstate != WEAPON_STUN // BFP - Avoid when being stunned + && ( pm->ps->weaponTime <= 0 || pm->ps->weaponstate != WEAPON_FIRING ) ) { if ( pm->ps->weapon != pm->cmd.weapon ) { PM_BeginWeaponChange( pm->cmd.weapon ); } } - if ( pm->ps->weaponTime > 0 ) { - return; - } - // change weapon if time - if ( pm->ps->weaponstate == WEAPON_DROPPING ) { + if ( pm->ps->weaponstate == WEAPON_DROPPING + && pm->ps->weaponTime <= 0 ) { // BFP - Handling ki attack animations when these already shoot PM_FinishWeaponChange(); return; } // BFP - Melee, avoid shooting if the player is in this status if ( pm->cmd.buttons & BUTTON_MELEE ) { + // only use when there's no dividing ki ball until it has been divided or collided, + // unless if the player wanna change the weapon from this state + if ( pm->ps->weaponstate != WEAPON_DIVIDINGKIBALLFIRING ) { + pm->ps->weaponstate = WEAPON_READY; + pm->ps->stats[STAT_KI_ATTACK_CHARGE] = 0; + } // Melee fight handling if ( pm->gauntletHit && pm->ps->weaponTime <= 0 ) { pm->ps->weaponTime += 300; @@ -1993,130 +2096,152 @@ static void PM_Weapon( void ) { return; } - // BFP - No weapon raising handling -#if 0 - if ( pm->ps->weaponstate == WEAPON_RAISING ) { - pm->ps->weaponstate = WEAPON_READY; - if ( pm->ps->weapon == WP_GAUNTLET ) { - PM_StartTorsoAnim( TORSO_STAND2 ); - } else { - PM_StartTorsoAnim( TORSO_STAND ); + // BFP - Weapon states, Q3 doesn't have this way + switch( pm->ps->weaponstate ) { + case WEAPON_READY: + if ( pm->ps->weaponTime <= 0 ) { + pm->ps->weaponTime = 0; + pm->ps->pm_flags &= ~PMF_KI_ATTACK; + // check for fire + if ( pm->cmd.buttons & BUTTON_ATTACK ) { + + // BFP - NOTE: These are just examples of ki charging and shooting, + // - WP_GRENADE_LAUNCHER should be like WP_MACHINEGUN and WP_LIGHTNINGGUN to keep the continuous shooting animations + // WP_GRENADE_LAUNCHER is used as example of charge homing ball shot + // - WP_SHOTGUN is used as example of ki explosion wave + // - WP_PLASMAGUN is used as example of dividing ki ball + // - WP_BFG is used as example of ki beam + switch( pm->ps->weapon ) { + case WP_GRENADE_LAUNCHER: + case WP_PLASMAGUN: + case WP_BFG: + pm->ps->weaponstate = WEAPON_CHARGING; + break; + case WP_SHOTGUN: + pm->ps->weaponstate = WEAPON_KIEXPLOSIONWAVE; + break; + default: + pm->ps->weaponstate = WEAPON_FIRING; + break; + } + } + } + if ( !( pm->cmd.buttons & BUTTON_ATTACK ) ) { + pm->ps->stats[STAT_KI_ATTACK_CHARGE] = 0; } - return; - } -#endif - - // check for fire - if ( ! (pm->cmd.buttons & BUTTON_ATTACK) ) { - pm->ps->weaponTime = 0; - pm->ps->weaponstate = WEAPON_READY; - return; - } - // BFP - No weapon gauntlet handling -#if 0 - // start the animation even if out of ammo - if ( pm->ps->weapon == WP_GAUNTLET ) { - // the guantlet only "fires" when it actually hits something - if ( !pm->gauntletHit ) { + break; + case WEAPON_DROPPING: + case WEAPON_RAISING: + if ( pm->ps->weaponTime <= 0 ) { pm->ps->weaponTime = 0; + pm->ps->stats[STAT_KI_ATTACK_CHARGE] = 0; pm->ps->weaponstate = WEAPON_READY; - return; } - PM_StartTorsoAnim( TORSO_STAND ); - } else { - PM_StartTorsoAnim( TORSO_STAND ); - } -#endif - - pm->ps->weaponstate = WEAPON_FIRING; - -// BFP - disable ammo stuff, take ki instead \o/ -#if 0 - // check for out of ammo - if ( ! pm->ps->ammo[ pm->ps->weapon ] ) { - PM_AddEvent( EV_NOAMMO ); - pm->ps->weaponTime += 500; - return; - } - - // take an ammo away if not infinite - if ( pm->ps->ammo[pm->ps->weapon] != -1 ) { - pm->ps->ammo[pm->ps->weapon]--; - } -#endif - - // fire weapon - PM_AddEvent( EV_FIRE_WEAPON ); - - // BFP - TODO: - // 1st attackset simple ki shot attack: - // pm->ps->stats[STAT_KI] -= 10; - - // 2nd attackset second simple ki shot attack: - // pm->ps->stats[STAT_KI] -= 100; - - // 3rd attackset ki blasts: - // pm->ps->stats[STAT_KI] -= 240; - - // 4th attackset charging some ki attack: - // pm->ps->stats[STAT_KI] -= 250; // reduces every time you stand until you shot or stop - - // 5th attackset charging some ki attack: - // pm->ps->stats[STAT_KI] -= 1000; // reduces every time you stand until you shot or stop - - - switch( pm->ps->weapon ) { - default: - case WP_GAUNTLET: - addTime = 400; - pm->ps->stats[STAT_KI] -= 0; - break; - case WP_MACHINEGUN: - addTime = 100; - pm->ps->stats[STAT_KI] -= 50; - break; - case WP_SHOTGUN: - addTime = 1000; - pm->ps->stats[STAT_KI] -= 100; - break; - case WP_GRENADE_LAUNCHER: - addTime = 800; - pm->ps->stats[STAT_KI] -= 100; break; - case WP_ROCKET_LAUNCHER: - addTime = 800; - pm->ps->stats[STAT_KI] -= 50; + case WEAPON_CHARGING: + if ( pm->ps->weaponTime <= 0 ) { + break; + } + + if ( !( pm->cmd.buttons & BUTTON_ATTACK ) ) { + // BFP - When the ki attack is fully charged, enter beam firing state + // or enter dividing ki ball firing state if it's a dividing ki ball + +#define FIRE_CHARGED_STATE(wepstate) \ + pm->ps->pm_flags |= PMF_KI_ATTACK; \ + pm->ps->weaponstate = wepstate; + + switch( pm->ps->weapon ) { + case WP_GRENADE_LAUNCHER: + FIRE_CHARGED_STATE( WEAPON_EXPLODING_KIBALLFIRING ) + break; + case WP_PLASMAGUN: + FIRE_CHARGED_STATE( WEAPON_DIVIDINGKIBALLFIRING ) + break; + case WP_BFG: + FIRE_CHARGED_STATE( WEAPON_BEAMFIRING ) + } + pm->ps->stats[STAT_KI_ATTACK_CHARGE] = 0; + } break; - case WP_LIGHTNING: - addTime = 50; - pm->ps->stats[STAT_KI] -= 70; + case WEAPON_FIRING: + if ( !( pm->cmd.buttons & BUTTON_ATTACK ) ) { + pm->ps->weaponstate = WEAPON_READY; + break; + } + + // fire weapon + switch( pm->ps->weapon ) { + case WP_MACHINEGUN: + case WP_ROCKET_LAUNCHER: + case WP_RAILGUN: + pm->ps->weaponstate = WEAPON_READY; + pm->ps->pm_flags |= PMF_KI_ATTACK; + //PM_AddEvent( EV_FIRE_WEAPON ); + break; + case WP_LIGHTNING: + pm->ps->pm_flags |= PMF_KI_ATTACK; + } break; - case WP_PLASMAGUN: - addTime = 100; - pm->ps->stats[STAT_KI] -= 120; + // BFP - NOTE: The beam is triggering until pressing the attack key again after holded, using ki charge or blocking + // Pressing attack key again or changing weapon, the beam is exploded before the impact + case WEAPON_BEAMFIRING: + if ( ( pm->cmd.buttons & BUTTON_ATTACK ) + || ( pm->ps->pm_flags & PMF_KI_CHARGE ) + || ( pm->ps->pm_flags & PMF_BLOCK ) + || !( pm->ps->pm_flags & PMF_KI_ATTACK ) ) { + pm->ps->pm_flags &= ~PMF_KI_ATTACK; + pm->ps->weaponstate = WEAPON_READY; + } break; - case WP_RAILGUN: - addTime = 1500; - pm->ps->stats[STAT_KI] -= 150; + // BFP - NOTE: That happens when the player uses a quick ki explosion themself or a homing ki ball is being triggered + case WEAPON_EXPLODING_KIBALLFIRING: + if ( pm->ps->weaponTime <= 0 ) { + pm->ps->pm_flags &= ~PMF_KI_ATTACK; + pm->ps->weaponstate = WEAPON_READY; + pm->ps->weaponTime = 0; + } break; - case WP_BFG: - addTime = 200; - pm->ps->stats[STAT_KI] -= 20; + // BFP - NOTE: The dividing ki ball is triggering until pressing the attack key again after holded or changing weapon + case WEAPON_DIVIDINGKIBALLFIRING: + if ( pm->cmd.buttons & BUTTON_ATTACK ) { + pm->ps->pm_flags &= ~PMF_KI_ATTACK; + pm->ps->weaponstate = WEAPON_READY; + pm->ps->weaponTime += 100; + } break; - case WP_GRAPPLING_HOOK: - addTime = 400; - pm->ps->stats[STAT_KI] -= 100; + // BFP - NOTE: That ki explosion wave is triggering until stop pressing the attack key or changing weapon, + // also when stopped enters in WEAPON_STUN state in 1 sec + case WEAPON_KIEXPLOSIONWAVE: + if ( pm->ps->weaponTime <= 0 ) { + if ( pm->ps->stats[STAT_KI_ATTACK_CHARGE] >= 1 ) { + pm->ps->pm_flags |= PMF_KI_ATTACK; + PM_AddEvent( EV_FIRE_WEAPON ); + } + } + if ( !( pm->cmd.buttons & BUTTON_ATTACK ) + || ( pm->cmd.buttons & BUTTON_MELEE ) ) { + pm->ps->weaponTime = 1000; + pm->ps->weaponstate = WEAPON_STUN; + } + + // fall even whether the player is flying + pm->ps->velocity[2] -= pm->ps->gravity * 2 * pml.frametime; break; - } + // BFP - NOTE: This stun state makes the player can't move in 1 sec, it's different from "hit stun" + case WEAPON_STUN: + if ( pm->ps->weaponTime <= 0 ) { + pm->ps->weaponTime = 0; + pm->ps->weaponstate = WEAPON_READY; + } + pm->ps->stats[STAT_KI_ATTACK_CHARGE] = 0; - // BFP - Ki Use - if ( pm->cmd.buttons & BUTTON_KI_USE ) { - addTime /= 1.3; + // fall even whether the player is flying + pm->ps->velocity[2] -= pm->ps->gravity * 2 * pml.frametime; } - - pm->ps->weaponTime += addTime; } +#undef FIRE_CHARGED_STATE /* ================ @@ -2251,6 +2376,12 @@ static void PM_KiCharge( void ) { // BFP - Ki Charge return; } + // BFP - Ki explosion wave and stun after using it, avoid charging also + if ( pm->ps->weaponstate == WEAPON_KIEXPLOSIONWAVE + || pm->ps->weaponstate == WEAPON_STUN ) { + return; + } + pm->cmd.forwardmove = pm->cmd.rightmove = pm->cmd.upmove = 0; if ( pm->cmd.buttons & ( BUTTON_ATTACK | BUTTON_KI_USE | BUTTON_MELEE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ) ) { @@ -2281,13 +2412,15 @@ Receives hit stun */ static void PM_HitStun( void ) { // BFP - Hit stun - if ( pm->cmd.buttons & ( BUTTON_MELEE | BUTTON_KI_USE | BUTTON_KI_CHARGE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ) ) { - pm->cmd.buttons &= ~( BUTTON_MELEE | BUTTON_KI_USE | BUTTON_KI_CHARGE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ); + if ( pm->cmd.buttons & ( BUTTON_MELEE | BUTTON_KI_USE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ) ) { + pm->cmd.buttons &= ~( BUTTON_MELEE | BUTTON_KI_USE | BUTTON_BLOCK | BUTTON_ENABLEFLIGHT ); } pm->ps->powerups[PW_FLIGHT] = 0; pm->ps->powerups[PW_HASTE] = 0; + pm->ps->pm_flags &= ~PMF_KI_ATTACK; pm->ps->eFlags &= ~EF_AURA; + pm->ps->weaponstate = WEAPON_READY; // BFP - NOTE: BFP doesn't handle nothing the button directions when there's hit stun pm->cmd.upmove = 0; @@ -2472,6 +2605,9 @@ void PmoveSingle (pmove_t *pmove) { // BFP - Melee PM_Melee(); + // BFP - Ki explosion wave handling + PM_KiExplosionWave(); + PM_DropTimers(); // BFP - Flight @@ -2585,6 +2721,7 @@ void Pmove (pmove_t *pmove) { } // BFP - Undefine the macros +#undef KI_ATTACK_TORSO_ANIM_HANDLING #undef TORSOSTATUS_ANIM_HANDLING #undef FORCEJUMP_ANIM_HANDLING #undef CONTINUEFLY_ANIM_HANDLING diff --git a/source/game/bg_public.h b/source/game/bg_public.h index 35c3692..644538e 100644 --- a/source/game/bg_public.h +++ b/source/game/bg_public.h @@ -136,7 +136,13 @@ typedef enum { WEAPON_READY, WEAPON_RAISING, WEAPON_DROPPING, - WEAPON_FIRING + WEAPON_CHARGING, // BFP - Ki attack charging + WEAPON_FIRING, + WEAPON_BEAMFIRING, // BFP - Beam fire + WEAPON_EXPLODING_KIBALLFIRING, // BFP - Quick ki explosion and homing ball fire + WEAPON_DIVIDINGKIBALLFIRING, // BFP - Dividing ball fire + WEAPON_KIEXPLOSIONWAVE, // BFP - Ki explosion wave + WEAPON_STUN // BFP - Stun status (not hit stun) when using ki explosion wave } weaponstate_t; // pmove->pm_flags @@ -154,6 +160,7 @@ typedef enum { #define PMF_FALLING 32 // BFP - Falling status // BFP - PMF_TIME_KNOCKBACK is unused // #define PMF_TIME_KNOCKBACK 64 // pm_time is an air-accelerate only time +#define PMF_KI_ATTACK 64 // BFP - Ki attack #define PMF_KI_CHARGE 128 // BFP - Ki charge // BFP - PMF_TIME_WATERJUMP is unused // #define PMF_TIME_WATERJUMP 256 // pm_time is waterjump @@ -220,6 +227,8 @@ void Pmove (pmove_t *pmove); typedef enum { STAT_HEALTH, STAT_KI, // BFP - KI amount + STAT_KI_ATTACK_CHARGE, // BFP - Ki charging points + STAT_READY_KI_ATTACK, // BFP - Ready ki attack notification STAT_HOLDABLE_ITEM, STAT_WEAPONS, // 16 bit fields STAT_ARMOR, diff --git a/source/game/g_active.c b/source/game/g_active.c index 9cd1391..92de3d0 100644 --- a/source/game/g_active.c +++ b/source/game/g_active.c @@ -717,6 +717,27 @@ static void BlockHandling( gclient_t *client, usercmd_t *ucmd ) { // BFP - Block } } +/* +================= +MeleeHandling +================= +*/ +static void MeleeHandling( gentity_t *ent, usercmd_t *ucmd, pmove_t *pm ) { // BFP - Melee + gclient_t *client; + + client = ent->client; + + if ( !( ucmd->buttons & BUTTON_MELEE ) ) { + client->ps.pm_flags &= ~PMF_MELEE; + } + + if ( !( ucmd->buttons & BUTTON_TALK ) && ( ucmd->buttons & BUTTON_MELEE ) + && !( client->ps.pm_flags & PMF_KI_CHARGE ) + && client->ps.weaponTime <= 0 ) { + pm->gauntletHit = CheckMeleeAttack( ent ); + } +} + /* ============ Zanzoken @@ -765,8 +786,10 @@ ZanzokenHandling #define ZANZOKEN_NUMBER_TIMES_ALLOWED 20 #define ZANZOKEN_ABUSE_DELAY 2000 static void ZanzokenHandling( gentity_t *ent, usercmd_t *ucmd ) { // BFP - Handling short-range teleport - // zanzoken cannot be used with ki charging status - if ( !( ent->client->ps.pm_flags & PMF_KI_CHARGE ) ) { + // zanzoken cannot be used with ki charging status and using explosion wave even while being stun after using explosion wave + if ( !( ent->client->ps.pm_flags & PMF_KI_CHARGE ) + && ( ent->client->ps.weaponstate != WEAPON_KIEXPLOSIONWAVE + && ent->client->ps.weaponstate != WEAPON_STUN ) ) { // restriction: stop abusing zanzoken technique all time if ( ent->client->zanzokenNumberTimesAllowed >= ZANZOKEN_NUMBER_TIMES_ALLOWED ) { ent->client->zanzokenNumberTimesAllowed = 0; @@ -859,6 +882,209 @@ static void ZanzokenHandling( gentity_t *ent, usercmd_t *ucmd ) { // BFP - Handl #undef ZANZOKEN_NUMBER_TIMES_ALLOWED #undef ZANZOKEN_ABUSE_DELAY +/* +================= +KiAttackWeaponHandling +================= +*/ +#define ATTACK_CHARGE_LIMIT 6 // BFP - Ki attack charge limit +// BFP - TODO: Use pmove_t variable to handle the ki attacks and send the info to bg_pmove.c +static void KiAttackWeaponHandling( gentity_t *ent, usercmd_t *ucmd, pmove_t *pm ) { + gclient_t *client; + int addTime; + + client = ent->client; + + // BFP - Hit stun, avoid shooting if the player is in this status + if ( client->ps.pm_flags & PMF_HITSTUN ) { + return; + } + +#define KI_CONSUME(addTime, kiconsume) \ + client->ps.stats[STAT_KI] -= kiconsume; \ + client->ps.weaponTime += addTime; + +#define CHARGE_KI_ATTACK_STATE(minCharge, maxCharge, addTime, kiconsume) \ + if ( client->ps.stats[STAT_KI_ATTACK_CHARGE] < maxCharge ) { \ + ++client->ps.stats[STAT_KI_ATTACK_CHARGE]; \ + } \ + if ( client->ps.stats[STAT_KI_ATTACK_CHARGE] >= minCharge ) { \ + client->ps.stats[STAT_READY_KI_ATTACK] = qtrue; \ + } \ + KI_CONSUME( addTime, kiconsume ) + + // Weapon states, Q3 doesn't have this way + switch( client->ps.weaponstate ) { + case WEAPON_READY: + client->ps.stats[STAT_READY_KI_ATTACK] = qfalse; + if ( client->ps.weaponTime <= 0 ) { + // check for fire + if ( ucmd->buttons & BUTTON_ATTACK ) { + + // BFP - NOTE: These are just examples of ki charging and shooting, + // - WP_GRENADE_LAUNCHER should be like WP_MACHINEGUN and WP_LIGHTNINGGUN to keep the continuous shooting animations + // WP_GRENADE_LAUNCHER is used as example of charge homing ball shot + // - WP_SHOTGUN is used as example of ki explosion wave + // - WP_PLASMAGUN is used as example of dividing ki ball + // - WP_BFG is used as example of ki beam + switch( client->ps.weapon ) { + case WP_SHOTGUN: // add time to handle ki explosion wave animation + client->ps.weaponTime += 700; + break; + case WP_LIGHTNING: // only play once this sound for ki attacks like eyebeam + G_AddEvent( ent, EV_FIRE_WEAPON, 0 ); + break; + case WP_GRENADE_LAUNCHER: + case WP_PLASMAGUN: + case WP_BFG: + default: + break; + } + } + } + if ( !( ucmd->buttons & BUTTON_ATTACK ) ) { + // BFP - When the ki attack is fully charged, enter beam firing state + // or enter dividing ki ball firing state if it's a dividing ki ball + + // BFP - TODO: Apply minCharge and maxCharge from reading bfp_weapon.cfg + switch( client->ps.weapon ) { + case WP_GRENADE_LAUNCHER: + break; + case WP_PLASMAGUN: + break; + case WP_BFG: + break; + } + } + break; + case WEAPON_DROPPING: + case WEAPON_RAISING: + break; + case WEAPON_CHARGING: + // BFP - Shoot the projectile or beam already charged surpassing the minimum + if ( !( ucmd->buttons & BUTTON_ATTACK ) ) { + client->ps.stats[STAT_READY_KI_ATTACK] = qfalse; + // no fully charged, skip... + // BFP - TODO: Apply minCharge in that condition also + if ( client->ps.stats[STAT_KI_ATTACK_CHARGE] < 2 ) { + client->ps.weaponstate = WEAPON_READY; + break; + } + // Fire and make a sound + FireWeapon( ent ); + G_AddEvent( ent, EV_FIRE_WEAPON, 0 ); + + // Handle the animation for the start of beam or ball shoot + switch( client->ps.weapon ) { + case WP_GRENADE_LAUNCHER: + case WP_BFG: + client->ps.weaponTime += 500; + } + } + + if ( client->ps.weaponTime <= 0 ) { + // check for fire + if ( ucmd->buttons & BUTTON_ATTACK ) { + + // BFP - NOTE: These are just examples of ki charging and shooting, + // - WP_GRENADE_LAUNCHER should be like WP_MACHINEGUN and WP_LIGHTNING to keep the continuous shooting animations + // WP_GRENADE_LAUNCHER is used as example of charge homing ball shot + // - WP_SHOTGUN is used as example of ki explosion wave + // - WP_PLASMAGUN is used as example of dividing ki ball + // - WP_BFG is used as example of ki beam + + // BFP - TODO: Also? Apply minCharge and maxCharge from reading bfp_weapon.cfg + switch( client->ps.weapon ) { + case WP_GRENADE_LAUNCHER: + CHARGE_KI_ATTACK_STATE( 2, 2, 700, 20 ) + break; + case WP_PLASMAGUN: + CHARGE_KI_ATTACK_STATE( 2, ATTACK_CHARGE_LIMIT, 1000, 120 ) + client->divideBallKiCharged = client->ps.stats[STAT_KI_ATTACK_CHARGE]; + break; + case WP_BFG: + CHARGE_KI_ATTACK_STATE( 2, ATTACK_CHARGE_LIMIT, 1000, 20 ) + break; + default: + break; + } + } + } + break; + case WEAPON_FIRING: + if ( ucmd->buttons & BUTTON_ATTACK ) { + if ( client->ps.weaponTime <= 0 + && client->ps.weapon != WP_LIGHTNING ) { + client->ps.pm_flags &= ~PMF_KI_ATTACK; + } + +#define KI_CONSUME_ADDTIME(weptime, kiconsume) \ + addTime = weptime; \ + client->ps.stats[STAT_KI] -= kiconsume; + + switch( client->ps.weapon ) { + default: + case WP_MACHINEGUN: + FireWeapon( ent ); + G_AddEvent( ent, EV_FIRE_WEAPON, 0 ); + KI_CONSUME_ADDTIME( 100, 10 ) + break; + case WP_ROCKET_LAUNCHER: + FireWeapon( ent ); + G_AddEvent( ent, EV_FIRE_WEAPON, 0 ); + KI_CONSUME_ADDTIME( 800, 50 ) + break; + case WP_LIGHTNING: + if ( client->ps.weaponTime <= 0 ) { + FireWeapon( ent ); + KI_CONSUME_ADDTIME( 50, 70 ) + } + break; + case WP_RAILGUN: + FireWeapon( ent ); + G_AddEvent( ent, EV_FIRE_WEAPON, 0 ); + KI_CONSUME_ADDTIME( 1500, 150 ) + break; + } + + client->ps.weaponTime += addTime; + } + break; + // BFP - NOTE: The beam is triggering until pressing the attack key again after holded, using ki charge or blocking + // Pressing attack key again or changing weapon, the beam is exploded before the impact + case WEAPON_BEAMFIRING: + break; + // BFP - NOTE: That happens when the player uses a quick ki explosion themself or a homing ki ball is being triggered + case WEAPON_EXPLODING_KIBALLFIRING: + break; + // BFP - NOTE: The dividing ki ball is triggering until pressing the attack key again after holded or changing weapon + case WEAPON_DIVIDINGKIBALLFIRING: + if ( ucmd->buttons & BUTTON_ATTACK ) { + KI_CONSUME( 0, 120 ) + } + break; + // BFP - NOTE: That ki explosion wave is triggering until stop pressing the attack key or changing weapon, + // also when stopped enters in WEAPON_STUN state in 1 sec + case WEAPON_KIEXPLOSIONWAVE: + if ( client->ps.weaponTime <= 0 ) { + KI_CONSUME( 200, 20 ) + if ( client->ps.stats[STAT_KI_ATTACK_CHARGE] < ATTACK_CHARGE_LIMIT ) { + ++client->ps.stats[STAT_KI_ATTACK_CHARGE]; + } + } + + // fall even whether the player is flying + //client->ps.velocity[2] -= client->ps.gravity * pml.frametime; + break; + // BFP - NOTE: This stun state makes the player can't move in 1 sec, it's different from "hit stun" + case WEAPON_STUN: + break; + } +} +#undef KI_CONSUME +#undef CHARGE_KI_ATTACK_STATE +#undef KI_CONSUME_ADDTIME + /* ============== ClientThink @@ -959,11 +1185,28 @@ void ClientThink_real( gentity_t *ent ) { // set speed client->ps.speed = g_speed.value; +// BFP - no hook +#if 0 + // Let go of the hook if we aren't firing + if ( client->ps.weapon == WP_GRAPPLING_HOOK && + client->hook && !( ucmd->buttons & BUTTON_ATTACK ) ) { + Weapon_HookFree(client->hook); + } +#endif + + // set up for pmove + oldEventSequence = client->ps.eventSequence; + + memset (&pm, 0, sizeof(pm)); + if ( client->ps.pm_type != PM_DEAD && client->ps.pm_type != PM_SPECTATOR ) { // BFP - Short-Range Teleport (Zanzoken) ZanzokenHandling( ent, ucmd ); + // BFP - Ki attack handling (as weapon handling) + KiAttackWeaponHandling( ent, ucmd, &pm ); + // BFP - Hit stun melee delay time if ( client->hitStunMeleeDelayTime > 0 && level.time >= client->hitStunMeleeDelayTime ) { @@ -974,7 +1217,9 @@ void ClientThink_real( gentity_t *ent ) { if ( !( client->ps.pm_flags & PMF_HITSTUN ) && !( client->ps.pm_flags & PMF_BLOCK ) && ( ( ucmd->buttons & BUTTON_KI_USE ) // BFP - Using Ki - || client->ps.powerups[PW_HASTE] > 0 ) ) { // BFP - When "kiusetoggle" is binded, enables/disables + || client->ps.powerups[PW_HASTE] > 0 ) // BFP - When "kiusetoggle" is binded, enables/disables + && ( client->ps.weaponstate != WEAPON_KIEXPLOSIONWAVE + && client->ps.weaponstate != WEAPON_STUN ) ) { if ( client->ps.powerups[PW_FLIGHT] <= 0 ) { client->ps.speed *= 2.5; } @@ -985,15 +1230,19 @@ void ClientThink_real( gentity_t *ent ) { client->ps.eFlags &= ~EF_AURA; client->ps.powerups[PW_HASTE] = 0; // Handle ki boost status } + + // BFP - g_chargeDelay cvar for ki charge animation and appearing the aura after this time + if ( ( ucmd->buttons & BUTTON_KI_CHARGE ) + && !( client->ps.pm_flags & PMF_KI_CHARGE ) ) { + client->ps.pm_time = ( g_chargeDelay.integer > 0 ) ? g_chargeDelay.integer : 0; + } } // BFP - Block, reflect ki attacks and reduce health damage BlockHandling( client, ucmd ); // BFP - Melee handling - if ( !( ucmd->buttons & BUTTON_MELEE ) ) { - client->ps.pm_flags &= ~PMF_MELEE; - } + MeleeHandling( ent, ucmd, &pm ); // BFP - Ki Charge if ( ( ucmd->buttons & BUTTON_KI_CHARGE ) && client->ps.pm_time <= 0 @@ -1010,38 +1259,6 @@ void ClientThink_real( gentity_t *ent ) { FlyingThink( ent, ucmd ); // prevents client-server side issues when there's other client in-game } -// BFP - no hook -#if 0 - // Let go of the hook if we aren't firing - if ( client->ps.weapon == WP_GRAPPLING_HOOK && - client->hook && !( ucmd->buttons & BUTTON_ATTACK ) ) { - Weapon_HookFree(client->hook); - } -#endif - - // set up for pmove - oldEventSequence = client->ps.eventSequence; - - memset (&pm, 0, sizeof(pm)); - -// BFP - No gauntlet hit check -#if 0 - // check for the hit-scan gauntlet, don't let the action - // go through as an attack unless it actually hits something - if ( client->ps.weapon == WP_GAUNTLET && !( ucmd->buttons & BUTTON_TALK ) && - ( ucmd->buttons & BUTTON_ATTACK ) && client->ps.weaponTime <= 0 ) { - pm.gauntletHit = CheckGauntletAttack( ent ); - } -#endif - - // BFP - Melee - if ( !( ucmd->buttons & BUTTON_TALK ) && ( ucmd->buttons & BUTTON_MELEE ) - && !( client->ps.pm_flags & PMF_KI_CHARGE ) - && client->ps.weaponTime <= 0 - && client->ps.pm_type != PM_DEAD ) { - pm.gauntletHit = CheckMeleeAttack( ent ); - } - if ( ent->flags & FL_FORCE_GESTURE ) { ent->flags &= ~FL_FORCE_GESTURE; ent->client->pers.cmd.buttons |= BUTTON_GESTURE; diff --git a/source/game/g_client.c b/source/game/g_client.c index bf5c134..0906efa 100644 --- a/source/game/g_client.c +++ b/source/game/g_client.c @@ -1167,9 +1167,6 @@ void ClientSpawn(gentity_t *ent) { client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_BFG ); client->ps.ammo[WP_BFG] = 100; - // TODO: BFP - Gauntlet must be replaced as a bind key (Alt key), - // it will use fight animation (using kicks and fists) - client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_GAUNTLET ); client->ps.ammo[WP_GAUNTLET] = -1; client->ps.ammo[WP_GRAPPLING_HOOK] = -1; diff --git a/source/game/g_cvar.h b/source/game/g_cvar.h index c0092b8..77fcc4a 100644 --- a/source/game/g_cvar.h +++ b/source/game/g_cvar.h @@ -67,7 +67,7 @@ G_CVAR( g_allowSpectatorChat, "g_allowSpectatorChat", "", 0, 0, qtrue ) // BFP - G_CVAR( g_meleeDamage, "g_meleeDamage", "10", CVAR_ARCHIVE, 0, qtrue ) // BFP - Melee damage G_CVAR( g_meleeDiveRange, "g_meleeDiveRange", "700", CVAR_ARCHIVE, 0, qtrue ) // BFP - Melee dive range G_CVAR( g_meleeRange, "g_meleeRange", "32", CVAR_ARCHIVE, 0, qtrue ) // BFP - Melee range -G_CVAR( g_chargeDelay, "g_chargeDelay", "750", 0, 0, qtrue ) // BFP - Charge delay +G_CVAR( g_chargeDelay, "g_chargeDelay", "750", CVAR_ARCHIVE, 0, qtrue ) // BFP - Charge delay G_CVAR( g_hitStun, "g_hitStun", "", 0, 0, qtrue ) // BFP - Hit stun G_CVAR( g_meleeOnly, "g_meleeOnly", "0", CVAR_SERVERINFO | CVAR_USERINFO | CVAR_LATCH | CVAR_ARCHIVE, 0, qtrue ) // BFP - Melee only G_CVAR( g_noFlight, "g_noFlight", "0", CVAR_SERVERINFO | CVAR_USERINFO | CVAR_LATCH | CVAR_ARCHIVE, 0, qtrue ) // BFP - No flight diff --git a/source/game/g_local.h b/source/game/g_local.h index e2fac23..7577ebd 100644 --- a/source/game/g_local.h +++ b/source/game/g_local.h @@ -85,6 +85,8 @@ struct gentity_s { qboolean neverFree; // if true, FreeEntity will only unlink // bodyque uses this + qboolean enabledivide; // BFP - Projectile state for dividing ball + int flags; // FL_* variables char *model; @@ -328,6 +330,9 @@ struct gclient_s { int zanzokenNumberTimesAllowed; int zanzokenDelay; + // BFP - Charged points for ki dividing ball + int divideBallKiCharged; + char *areabits; }; diff --git a/source/game/g_missile.c b/source/game/g_missile.c index c16893e..d57c864 100644 --- a/source/game/g_missile.c +++ b/source/game/g_missile.c @@ -237,6 +237,8 @@ void G_RunMissile( gentity_t *ent ) { vec3_t origin; trace_t tr; int passent; + // BFP - Shortcut variable to make sure who is using this projectile + gclient_t *client = g_entities[ ent->r.ownerNum ].client; // get current position BG_EvaluateTrajectory( &ent->s.pos, level.time, origin ); @@ -263,7 +265,127 @@ void G_RunMissile( gentity_t *ent ) { trap_LinkEntity( ent ); + // BFP - When the player stopped shooting the charged beam/projectile by pressing the attack key + // These are sample weapons used as examples for BFP: + + // WP_BFG would be the beam + if ( client + && client->ps.weaponstate != WEAPON_BEAMFIRING + && ent->s.weapon == WP_BFG ) { + client->ps.pm_flags &= ~PMF_KI_ATTACK; + G_MissileImpact( ent, &tr ); + } + + // WP_PLASMAGUN would be that dividing ball, when pressing the attack key again, divides by the number of balls depending on the ki attack charge points had + if ( client + && !( client->ps.pm_flags & PMF_KI_ATTACK ) + && client->ps.weapon == WP_PLASMAGUN + && ent->s.weapon == WP_PLASMAGUN + && !ent->enabledivide ) { + client->ps.weaponstate = WEAPON_DIVIDINGKIBALLFIRING; + client->ps.pm_flags |= PMF_KI_ATTACK; + } + + if ( client + && ( client->pers.cmd.buttons & BUTTON_ATTACK ) + && client->ps.weapon == WP_PLASMAGUN + && ent->s.weapon == WP_PLASMAGUN + && !ent->enabledivide ) { + vec3_t dir, angles; + gentity_t *proj1 = NULL, *proj2 = NULL, *proj3 = NULL; + + // BFP - TODO: Apply minCharge and maxCharge from reading bfp_weapon.cfg + + // if charge attack is 2: + // horizontal: + // ← → + // ↓ + if ( client->divideBallKiCharged >= 2 ) { + angles[PITCH] = 0; + angles[YAW] -= 270; + angles[ROLL] = 0; + AngleVectors( angles, dir, NULL, NULL ); + proj1 = fire_plasma( ent, ent->r.currentOrigin, dir ); + VectorCopy( proj1->s.angles, angles ); + + angles[PITCH] = 0; + angles[YAW] -= 360; + angles[ROLL] = 0; + AngleVectors( angles, dir, NULL, NULL ); + proj2 = fire_plasma( ent, ent->r.currentOrigin, dir ); + VectorCopy( proj2->s.angles, angles ); + + angles[PITCH] = 0; + angles[YAW] -= 90; + angles[ROLL] = 0; + AngleVectors( angles, dir, NULL, NULL ); + proj3 = fire_plasma( ent, ent->r.currentOrigin, dir ); + VectorCopy( proj3->s.angles, angles ); + } + + // if charge attack is 3: + // horizontal: + // ↑ + // ← → + // ↓ + if ( client->divideBallKiCharged >= 3 ) { + angles[PITCH] = 0; + angles[YAW] -= 180; + angles[ROLL] = 0; + AngleVectors( angles, dir, NULL, NULL ); + proj3 = fire_plasma( ent, ent->r.currentOrigin, dir ); + } + + // if charge attack is 4: + // horizontal: + // ↑ + // ← → + // ↓ + // vertical: ↑ + if ( client->divideBallKiCharged >= 4 ) { + angles[PITCH] -= 90; + angles[YAW] = 0; + angles[ROLL] = 0; + AngleVectors( angles, dir, NULL, NULL ); + proj3 = fire_plasma( ent, ent->r.currentOrigin, dir ); + } + + // if charge attack is 5 and above: + // horizontal: + // ↑ + // ← → + // ↓ + // vertical: ↑ and ↓ + if ( client->divideBallKiCharged >= 5 ) { + angles[PITCH] -= 180; + angles[YAW] = 0; + angles[ROLL] = 0; + AngleVectors( angles, dir, NULL, NULL ); + proj3 = fire_plasma( ent, ent->r.currentOrigin, dir ); + } + + client->ps.pm_flags &= ~PMF_KI_ATTACK; + + ent->enabledivide = qtrue; + G_FreeEntity( ent ); + } + + if ( client + && client->ps.weapon == WP_PLASMAGUN + && client->ps.weaponstate == WEAPON_DIVIDINGKIBALLFIRING + && ent->s.weapon == WP_PLASMAGUN ) { + client->ps.pm_flags |= PMF_KI_ATTACK; + } + if ( tr.fraction != 1 ) { + + // BFP - When the charged projectile touches into something, disable ki attack PMF flag + if ( client + && ( client->ps.weaponstate == WEAPON_BEAMFIRING + || client->ps.weaponstate == WEAPON_DIVIDINGKIBALLFIRING ) ) { + client->ps.pm_flags &= ~PMF_KI_ATTACK; + } + // never explode or bounce on sky if ( tr.surfaceFlags & SURF_NOIMPACT ) { // BFP - no hook From c6f1ad6d7ea0397f921ed3eccde8c1800fa01552 Mon Sep 17 00:00:00 2001 From: --local Date: Wed, 3 Jul 2024 23:14:44 +0200 Subject: [PATCH 068/374] cgame - game: Reduce maximum press time a bit on Zanzoken, rename variable gauntletHit to meleeHit in pmove_t struct, apply enabledivide in the sample plasma weapon to test the dividing ki ball, move and optimize the handling dividing ki ball into a static function, and fix melee animation when ki attack status is being used --- source/cgame/cg_predict.c | 6 +- source/game/bg_pmove.c | 10 ++- source/game/bg_public.h | 2 +- source/game/g_active.c | 8 +- source/game/g_missile.c | 164 +++++++++++++++++++++----------------- 5 files changed, 104 insertions(+), 86 deletions(-) diff --git a/source/cgame/cg_predict.c b/source/cgame/cg_predict.c index 9e1e1cb..0483134 100644 --- a/source/cgame/cg_predict.c +++ b/source/cgame/cg_predict.c @@ -564,9 +564,9 @@ void CG_PredictPlayerState( void ) { } } - // don't predict gauntlet firing, which is only supposed to happen - // when it actually inflicts damage - cg_pmove.gauntletHit = qfalse; + // BFP - don't predict melee attack, which is only supposed to happen + // when it actually inflicts damage (on Q3 comment says the same, but with gauntlet :P) + cg_pmove.meleeHit = qfalse; if ( cg_pmove.pmove_fixed ) { cg_pmove.cmd.serverTime = ((cg_pmove.cmd.serverTime + pmove_msec.integer-1) / pmove_msec.integer) * pmove_msec.integer; diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index feeb028..8652eed 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -49,7 +49,7 @@ int c_pmove = 0; // BFP - Macro for torso handling when using ki attacks, since the code looked repetitive, so this macro makes the code a bit shorter /* BFP - TODO: When implementing ki attacks, look up about the properties of the ki attacks from cfg and correct animation changes if required -And tweak pmove_t struct, so we can handle that on g_active.c (like gauntletHit), adding: +And tweak pmove_t struct, so we can handle that on g_active.c (like meleeHit), adding: attackType ("beam", "hitscan", "missile", "rdmissile", "sbeam" or "forcefield"), // type of attack randomWeaponTime (int, number of miliseconds), // random weapon time, maybe the max msec range of the random value chargeAttack (int / qboolean), // charging yes or no @@ -1577,8 +1577,10 @@ static void PM_Footsteps( void ) { if ( pm->waterlevel > 1 ) { CONTINUEFLY_ANIM_HANDLING() } else { - // BFP - Keep the torso when using a ki attack even after charged - KI_ATTACK_TORSO_ANIM_HANDLING() + // BFP - Keep the torso when using a ki attack even after charged, avoid when melee is being used + if ( !( pm->cmd.buttons & BUTTON_MELEE ) ) { + KI_ATTACK_TORSO_ANIM_HANDLING() + } } return; @@ -2089,7 +2091,7 @@ static void PM_Weapon( void ) { pm->ps->stats[STAT_KI_ATTACK_CHARGE] = 0; } // Melee fight handling - if ( pm->gauntletHit && pm->ps->weaponTime <= 0 ) { + if ( pm->meleeHit && pm->ps->weaponTime <= 0 ) { pm->ps->weaponTime += 300; pm->ps->pm_flags |= PMF_MELEE; } diff --git a/source/game/bg_public.h b/source/game/bg_public.h index 644538e..3aa5506 100644 --- a/source/game/bg_public.h +++ b/source/game/bg_public.h @@ -190,7 +190,7 @@ typedef struct { int tracemask; // collide against these types of surfaces int debugLevel; // if set, diagnostic output will be printed qboolean noFootsteps; // if the game is setup for no footsteps by the server - qboolean gauntletHit; // true if a gauntlet attack would actually hit something + qboolean meleeHit; // BFP - before: gauntletHit - true if a melee attack would actually hit something int framecount; diff --git a/source/game/g_active.c b/source/game/g_active.c index 92de3d0..1eb6e29 100644 --- a/source/game/g_active.c +++ b/source/game/g_active.c @@ -734,7 +734,7 @@ static void MeleeHandling( gentity_t *ent, usercmd_t *ucmd, pmove_t *pm ) { // B if ( !( ucmd->buttons & BUTTON_TALK ) && ( ucmd->buttons & BUTTON_MELEE ) && !( client->ps.pm_flags & PMF_KI_CHARGE ) && client->ps.weaponTime <= 0 ) { - pm->gauntletHit = CheckMeleeAttack( ent ); + pm->meleeHit = CheckMeleeAttack( ent ); } } @@ -815,16 +815,17 @@ static void ZanzokenHandling( gentity_t *ent, usercmd_t *ucmd ) { // BFP - Handl } // once pressed and having one moment to press again, zanzoken will be possible at these milliseconds +#define MAX_ZANZOKEN_PRESS_TIME 240 if ( !ucmd->rightmove && level.time - ent->client->zanzokenPressTime > 100 - && level.time - ent->client->zanzokenPressTime <= 250 + && level.time - ent->client->zanzokenPressTime <= MAX_ZANZOKEN_PRESS_TIME && !ent->client->zanzokenNow ) { ent->client->zanzokenNow = qtrue; ent->client->zanzokenNumberTimesAllowed++; } if ( !ucmd->rightmove - && level.time - ent->client->zanzokenPressTime > 250 ) { + && level.time - ent->client->zanzokenPressTime > MAX_ZANZOKEN_PRESS_TIME ) { ent->client->zanzokenNumberTimesAllowed = 0; ent->client->zanzokenPressTime = 0; ent->client->zanzokenNow = qfalse; @@ -832,6 +833,7 @@ static void ZanzokenHandling( gentity_t *ent, usercmd_t *ucmd ) { // BFP - Handl ent->client->zanzokenRight = qfalse; return; } +#undef MAX_ZANZOKEN_PRESS_TIME // BFP - TODO: Zanzoken ki consume looks relative to powerlevel and the maximum ki quantity // (so, if it's 8160 as ki max quantity, then consumes 408) diff --git a/source/game/g_missile.c b/source/game/g_missile.c index d57c864..a36d614 100644 --- a/source/game/g_missile.c +++ b/source/game/g_missile.c @@ -24,6 +24,92 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define MISSILE_PRESTEP_TIME 50 +/* +================ +HandleDivideKiBall +================ +*/ +static void HandleDivideKiBall( gentity_t *ent, gclient_t *client ) { // BFP - WP_PLASMAGUN would be that dividing ball, when pressing the attack key again, divides by the number of balls depending on the ki attack charge points had + vec3_t dir, angles; + int i; + int chargePoints = client->divideBallKiCharged; + int projectiles_to_spawn; + int yawAdjustments[6] = { + // if charge attack is 2: + // horizontal: + // ← → + // ↓ + -270, -360, -90, + // if charge attack is 3: + // horizontal: + // ↑ + // ← → + // ↓ + -180, + 0, 0 + }; + int pitchAdjustments[6] = { + 0, 0, 0, 0, + // if charge attack is 4: + // horizontal: + // ↑ + // ← → + // ↓ + // vertical: ↑ + -90, + // if charge attack is 5 and above: + // horizontal: + // ↑ + // ← → + // ↓ + // vertical: ↑ and ↓ + 90 + }; + + // BFP - TODO: Apply minCharge and maxCharge from reading bfp_weapon.cfg + if ( chargePoints < 2 ) { + return; + } + + // determine the number of projectiles to spawn based on the ki attack charge points + switch( chargePoints ) { + case 2: + projectiles_to_spawn = 3; + break; + case 3: + projectiles_to_spawn = 4; + break; + case 4: + projectiles_to_spawn = 5; + break; + case 5: + case 6: + projectiles_to_spawn = 6; + break; + default: + projectiles_to_spawn = 0; + break; + } + + if ( projectiles_to_spawn == 0 ) { + return; + } + + for ( i = 0; i < projectiles_to_spawn; i++ ) { + gentity_t *proj = NULL; + VectorCopy( ent->s.angles, angles ); + + angles[YAW] += yawAdjustments[i]; + angles[PITCH] += pitchAdjustments[i]; + + AngleVectors( angles, dir, NULL, NULL ); + proj = fire_plasma( ent, ent->r.currentOrigin, dir ); + VectorCopy( proj->s.angles, angles ); + } + + client->ps.pm_flags &= ~PMF_KI_ATTACK; +} + /* ================ G_BounceMissile @@ -291,81 +377,7 @@ void G_RunMissile( gentity_t *ent ) { && client->ps.weapon == WP_PLASMAGUN && ent->s.weapon == WP_PLASMAGUN && !ent->enabledivide ) { - vec3_t dir, angles; - gentity_t *proj1 = NULL, *proj2 = NULL, *proj3 = NULL; - - // BFP - TODO: Apply minCharge and maxCharge from reading bfp_weapon.cfg - - // if charge attack is 2: - // horizontal: - // ← → - // ↓ - if ( client->divideBallKiCharged >= 2 ) { - angles[PITCH] = 0; - angles[YAW] -= 270; - angles[ROLL] = 0; - AngleVectors( angles, dir, NULL, NULL ); - proj1 = fire_plasma( ent, ent->r.currentOrigin, dir ); - VectorCopy( proj1->s.angles, angles ); - - angles[PITCH] = 0; - angles[YAW] -= 360; - angles[ROLL] = 0; - AngleVectors( angles, dir, NULL, NULL ); - proj2 = fire_plasma( ent, ent->r.currentOrigin, dir ); - VectorCopy( proj2->s.angles, angles ); - - angles[PITCH] = 0; - angles[YAW] -= 90; - angles[ROLL] = 0; - AngleVectors( angles, dir, NULL, NULL ); - proj3 = fire_plasma( ent, ent->r.currentOrigin, dir ); - VectorCopy( proj3->s.angles, angles ); - } - - // if charge attack is 3: - // horizontal: - // ↑ - // ← → - // ↓ - if ( client->divideBallKiCharged >= 3 ) { - angles[PITCH] = 0; - angles[YAW] -= 180; - angles[ROLL] = 0; - AngleVectors( angles, dir, NULL, NULL ); - proj3 = fire_plasma( ent, ent->r.currentOrigin, dir ); - } - - // if charge attack is 4: - // horizontal: - // ↑ - // ← → - // ↓ - // vertical: ↑ - if ( client->divideBallKiCharged >= 4 ) { - angles[PITCH] -= 90; - angles[YAW] = 0; - angles[ROLL] = 0; - AngleVectors( angles, dir, NULL, NULL ); - proj3 = fire_plasma( ent, ent->r.currentOrigin, dir ); - } - - // if charge attack is 5 and above: - // horizontal: - // ↑ - // ← → - // ↓ - // vertical: ↑ and ↓ - if ( client->divideBallKiCharged >= 5 ) { - angles[PITCH] -= 180; - angles[YAW] = 0; - angles[ROLL] = 0; - AngleVectors( angles, dir, NULL, NULL ); - proj3 = fire_plasma( ent, ent->r.currentOrigin, dir ); - } - - client->ps.pm_flags &= ~PMF_KI_ATTACK; - + HandleDivideKiBall( ent, client ); ent->enabledivide = qtrue; G_FreeEntity( ent ); } @@ -438,6 +450,8 @@ gentity_t *fire_plasma (gentity_t *self, vec3_t start, vec3_t dir) { bolt->clipmask = MASK_SHOT; bolt->target_ent = NULL; + bolt->enabledivide = qfalse; // BFP - For dividing ki ball + bolt->s.pos.trType = TR_LINEAR; bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME; // move a bit on the very first frame VectorCopy( start, bolt->s.pos.trBase ); From 714c117639b1290c455a534fdb9633422ce46036 Mon Sep 17 00:00:00 2001 From: --local Date: Thu, 4 Jul 2024 17:32:53 +0200 Subject: [PATCH 069/374] game: Implement breakable map entities --- README.md | 1 + source/game/g_combat.c | 8 ++++++++ source/game/g_mover.c | 17 +++++++++++++++++ source/game/g_spawn.c | 4 +++- source/game/g_weapon.c | 6 ++++++ 5 files changed, 35 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 94fca28..4271d12 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ A legendary 90s era Quake 3 Arena mod. - [x] ~~Bind key to toggle speed (ki boost). HINT: HASTE POWERUP~~ - [x] ~~Replace ammo to ki energy stamina~~ - [x] ~~Third person traceable crosshair~~ +- [x] ~~Breakable map entities ("func_breakable")~~ - [ ] Make ki energy regeneration, ki use, attacks, charging balance indicated on old docs - [ ] Powerlevel and Power Tiers indicated on old docs - [x] ~~Hit Stun (makes player can't use ki, melee, block and charge)~~ diff --git a/source/game/g_combat.c b/source/game/g_combat.c index d02469e..4e54411 100644 --- a/source/game/g_combat.c +++ b/source/game/g_combat.c @@ -676,6 +676,14 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, if ( targ->use && targ->moverState == MOVER_POS1 ) { targ->use( targ, inflictor, attacker ); } + // BFP - For breakable map entities + if ( targ->takedamage && targ->health > 0 ) { + if ( damage < 1 ) { + damage = 1; + } + take = damage; + targ->health = targ->health - take; + } return; } // reduce damage by the attacker's handicap value diff --git a/source/game/g_mover.c b/source/game/g_mover.c index c496b10..4a9bd27 100644 --- a/source/game/g_mover.c +++ b/source/game/g_mover.c @@ -1574,3 +1574,20 @@ void SP_func_pendulum(gentity_t *ent) { ent->s.apos.trType = TR_SINE; ent->s.apos.trDelta[2] = speed; } + + +// BFP - Breakable map entities +void func_breakable_use( gentity_t *ent, gentity_t *other, gentity_t *activator ) { + if ( ent->health <= 0 ) { + G_FreeEntity( ent ); + } +} + +void SP_func_breakable( gentity_t *ent ) { + trap_SetBrushModel( ent, ent->model ); + ent->s.eType = ET_MOVER; + ent->r.contents = CONTENTS_SOLID; + ent->health = 100; + ent->takedamage = qtrue; + ent->use = func_breakable_use; +} diff --git a/source/game/g_spawn.c b/source/game/g_spawn.c index dfd193c..217c361 100644 --- a/source/game/g_spawn.c +++ b/source/game/g_spawn.c @@ -143,6 +143,7 @@ void SP_func_button (gentity_t *ent); void SP_func_door (gentity_t *ent); void SP_func_train (gentity_t *ent); void SP_func_timer (gentity_t *self); +void SP_func_breakable (gentity_t *ent); // BFP - Breakable map entities void SP_trigger_always (gentity_t *ent); void SP_trigger_multiple (gentity_t *ent); @@ -186,7 +187,7 @@ void SP_team_CTF_blueplayer( gentity_t *ent ); void SP_team_CTF_redspawn( gentity_t *ent ); void SP_team_CTF_bluespawn( gentity_t *ent ); -void SP_item_botroam( gentity_t *ent ) {}; +void SP_item_botroam( gentity_t *ent ) { (void)ent; } spawn_t spawns[] = { // info entities don't do anything at all, but provide positional @@ -207,6 +208,7 @@ spawn_t spawns[] = { {"func_pendulum", SP_func_pendulum}, {"func_train", SP_func_train}, {"func_group", SP_info_null}, + {"func_breakable", SP_func_breakable}, // BFP - Breakable map entities {"func_timer", SP_func_timer}, // rename trigger_timer? // Triggers are brush objects that cause an effect when contacted diff --git a/source/game/g_weapon.c b/source/game/g_weapon.c index b7190e0..a4671db 100644 --- a/source/game/g_weapon.c +++ b/source/game/g_weapon.c @@ -177,6 +177,12 @@ qboolean CheckMeleeAttack( gentity_t *attacker ) { // BFP - Melee return qfalse; } + // avoid if the entity isn't a player (e.g. a breakable map entity) + if ( traceTarget->s.eType != ET_PLAYER ) { + attacker->client->ps.pm_flags &= ~PMF_MELEE; + return qfalse; + } + // the target's corpse is starting to sink, avoid interacting with a sinking corpse, nothing special happens if ( traceTarget->physicsObject ) { attacker->client->ps.pm_flags &= ~PMF_MELEE; From a90fd3764c0921f573b4248d3ec3e5cd3a15e3b1 Mon Sep 17 00:00:00 2001 From: --local Date: Thu, 8 Aug 2024 00:15:09 +0200 Subject: [PATCH 070/374] game: Add Vector4Set macro to set values for a vec4_t variable --- source/game/q_shared.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/game/q_shared.h b/source/game/q_shared.h index 2b145f6..cbc6c59 100644 --- a/source/game/q_shared.h +++ b/source/game/q_shared.h @@ -656,6 +656,8 @@ typedef struct { #define VectorNegate(a,b) ((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2]) #define VectorSet(v, x, y, z) ((v)[0]=(x), (v)[1]=(y), (v)[2]=(z)) #define Vector4Copy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3]) +// BFP - Vector4Set helps to set the 4 values for a vec4_t variable, making the code shorter in a single line +#define Vector4Set(v,w,x,y,z) ((v)[0]=(w), (v)[1]=(x), (v)[2]=(y), (v)[3]=(z)) #define SnapVector(v) {v[0]=((int)(v[0]));v[1]=((int)(v[1]));v[2]=((int)(v[2]));} // just in case you do't want to use the macros From 5eebe4c23bdfce366af12c8e5b11005bad7c2ee2 Mon Sep 17 00:00:00 2001 From: --local Date: Thu, 8 Aug 2024 00:51:26 +0200 Subject: [PATCH 071/374] cgame: Add ki trails --- Makefile | 1 + MakefileQVM | 2 +- README.md | 2 + docs/bfp_cvars_task.md | 2 +- source/cgame/cg_cvar.h | 1 + source/cgame/cg_local.h | 14 +++++ source/cgame/cg_main.c | 8 +++ source/cgame/cg_players.c | 44 ++++++++++++- source/cgame/cg_trails.c | 128 ++++++++++++++++++++++++++++++++++++++ source/cgame/cgame.bat | 2 + source/cgame/cgame.q3asm | 1 + 11 files changed, 201 insertions(+), 4 deletions(-) create mode 100644 source/cgame/cg_trails.c diff --git a/Makefile b/Makefile index 8a8df47..f14c704 100644 --- a/Makefile +++ b/Makefile @@ -395,6 +395,7 @@ CGOBJ_ = \ $(B)/cgame/cg_scoreboard.o \ $(B)/cgame/cg_servercmds.o \ $(B)/cgame/cg_snapshot.o \ + $(B)/cgame/cg_trails.o \ $(B)/cgame/cg_view.o \ $(B)/cgame/cg_weapons.o \ \ diff --git a/MakefileQVM b/MakefileQVM index a140d4d..60ce985 100644 --- a/MakefileQVM +++ b/MakefileQVM @@ -89,7 +89,7 @@ CG_SRC = \ cg_main $(CGDIR)/cg_syscalls.asm \ cg_consolecmds cg_draw cg_drawtools cg_effects cg_ents cg_event cg_info \ cg_localents cg_marks cg_particles cg_players cg_playerstate cg_predict cg_scoreboard \ - cg_servercmds cg_snapshot cg_view cg_weapons \ + cg_servercmds cg_snapshot cg_trails cg_view cg_weapons \ bg_slidemove bg_pmove bg_lib bg_misc \ q_math q_shared \ diff --git a/README.md b/README.md index 4271d12..51fe9e5 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,7 @@ A legendary 90s era Quake 3 Arena mod. - [x] ~~Replace ammo to ki energy stamina~~ - [x] ~~Third person traceable crosshair~~ - [x] ~~Breakable map entities ("func_breakable")~~ +- [x] ~~Ki trails (use ki to move, cg_kiTrail >10 )~~ - [ ] Make ki energy regeneration, ki use, attacks, charging balance indicated on old docs - [ ] Powerlevel and Power Tiers indicated on old docs - [x] ~~Hit Stun (makes player can't use ki, melee, block and charge)~~ @@ -372,6 +373,7 @@ The information in the map file can be useful for debugging and performance anal #### Added source code files: - cg_cvar.h +- cg_trails.c - g_cvar.h - ui_bfpoptions.c - ui_cvar.h diff --git a/docs/bfp_cvars_task.md b/docs/bfp_cvars_task.md index b48fe66..4f643fb 100644 --- a/docs/bfp_cvars_task.md +++ b/docs/bfp_cvars_task.md @@ -35,7 +35,6 @@ - cg_stfu [0/1]: disable character voices when firing attacks. - cg_lowpolysphere [0/1]: force the use of a lower polycount sphere. -- cg_kitrail [0-99]: set the length of the ki trail. 0 turns it off. - cg_lightexplosions [0/1]: turn on or off the explosion dynamic lights. - cg_chargeupAlert [0/1]: turn on or off the "ready" message when charging attacks. - cg_explosionShell [0/1]: turn on or off the explosion shell. @@ -47,6 +46,7 @@ ## COMPLETED: - [x] ~~cg_superdeformed~~ +- [x] ~~cg_kiTrail~~ - [x] ~~cg_yrgolroxor~~ - [x] ~~cg_thirdPersonHeight~~ - [x] ~~cg_fixedThirdPerson~~ diff --git a/source/cgame/cg_cvar.h b/source/cgame/cg_cvar.h index 57caa11..59c880a 100644 --- a/source/cgame/cg_cvar.h +++ b/source/cgame/cg_cvar.h @@ -66,6 +66,7 @@ CG_CVAR( cg_tracerChance, "cg_tracerchance", "0.4", CVAR_CHEAT ) CG_CVAR( cg_tracerWidth, "cg_tracerwidth", "1", CVAR_CHEAT ) CG_CVAR( cg_tracerLength, "cg_tracerlength", "100", CVAR_CHEAT ) CG_CVAR( cg_flytilt, "cg_flytilt", "1", CVAR_ARCHIVE ) // BFP - Fly tilt +CG_CVAR( cg_kiTrail, "cg_kiTrail", "50", CVAR_ARCHIVE ) // BFP - Ki trail length CG_CVAR( cg_playHitSound, "cg_playHitSound", "0", CVAR_ARCHIVE ) // BFP - Play hit sound CG_CVAR( cg_thirdPersonRange, "cg_thirdPersonRange", "110", CVAR_ARCHIVE ) // BFP CG_CVAR( cg_thirdPersonAngle, "cg_thirdPersonAngle", "0", CVAR_ARCHIVE ) // BFP diff --git a/source/cgame/cg_local.h b/source/cgame/cg_local.h index b059d32..bbf7eb3 100644 --- a/source/cgame/cg_local.h +++ b/source/cgame/cg_local.h @@ -140,6 +140,7 @@ typedef struct { int painTime; int painDirection; // flip from 0 to 1 int lightningFiring; + int kiTrailTime; // BFP - Ki trail time // railgun trail spawning vec3_t railgunImpact; @@ -784,6 +785,11 @@ typedef struct { qhandle_t auraBlueShader; qhandle_t auraYellowShader; + // BFP - Ki trail shaders + qhandle_t kiTrailRedShader; + qhandle_t kiTrailBlueShader; + qhandle_t kiTrailYellowShader; + // scoreboard headers qhandle_t scoreboardName; qhandle_t scoreboardPing; @@ -1247,6 +1253,14 @@ void CG_BubbleTrail( vec3_t start, vec3_t end, float spacing ); void CG_SpawnEffect( vec3_t org ); void CG_ScorePlum( int client, vec3_t org, int score ); +// BFP - Ki trail +// +// cg_trails.c +// +void CG_InitKiTrails( void ); +void CG_ResetKiTrail( int entityNum, vec3_t origin ); +void CG_KiTrail( int entityNum, vec3_t origin, qboolean remove, qhandle_t hShader ); + void CG_GibPlayer( vec3_t playerOrigin ); void CG_BigExplode( vec3_t playerOrigin ); diff --git a/source/cgame/cg_main.c b/source/cgame/cg_main.c index 355d6ef..6986891 100644 --- a/source/cgame/cg_main.c +++ b/source/cgame/cg_main.c @@ -637,6 +637,11 @@ static void CG_RegisterGraphics( void ) { cgs.media.auraRedShader = trap_R_RegisterShader( "powerups/redtiny" ); cgs.media.auraYellowShader = trap_R_RegisterShader( "powerups/yellowtiny" ); + // BFP - Ki trail shaders + cgs.media.kiTrailBlueShader = trap_R_RegisterShader( "powerups/bluekitrail" ); + cgs.media.kiTrailRedShader = trap_R_RegisterShader( "powerups/redkitrail" ); + cgs.media.kiTrailYellowShader = trap_R_RegisterShader( "powerups/yellowkitrail" ); + memset( cg_items, 0, sizeof( cg_items ) ); memset( cg_weapons, 0, sizeof( cg_weapons ) ); @@ -878,6 +883,9 @@ void CG_Init( int serverMessageNum, int serverCommandSequence, int clientNum ) { CG_InitMarkPolys(); + // BFP - Initialize ki trails + CG_InitKiTrails(); + // remove the last loading update cg.infoScreenText[0] = 0; diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index 297704c..b8115ef 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -2206,6 +2206,9 @@ void CG_Player( centity_t *cent ) { float shadowPlane; int model_i, model_j; // BFP - For model sizes vec3_t auraInverseRotation; // BFP - For aura inverse rotation + // BFP - Ki trail setup + vec3_t kiTrailOrigin; + qhandle_t kiTrailShader; // BFP - Macro for the size of a model #define MODEL_SIZE(model, model_size) \ @@ -2224,6 +2227,14 @@ void CG_Player( centity_t *cent ) { } ci = &cgs.clientinfo[ clientNum ]; + // BFP - Ki trail shader set + kiTrailShader = cgs.media.kiTrailRedShader; + // BFP - TODO: Add yellow ki trail only when the player is transformed, but don't override when playing a team gamemode + // kiTrailShader = cgs.media.kiTrailYellowShader; + if ( ci->team == TEAM_BLUE ) { + kiTrailShader = cgs.media.kiTrailBlueShader; + } + // it is possible to see corpses from disconnected players that may // not have valid clientinfo if ( !ci->infoValid ) { @@ -2352,6 +2363,12 @@ void CG_Player( centity_t *cent ) { CG_AddRefEntityWithPowerups( &head, ¢->currentState, ci->team ); + // BFP - Origin setup for ki trails + #define KI_TRAIL_ZPOS 5 + VectorCopy( cent->currentState.pos.trBase, kiTrailOrigin ); + kiTrailOrigin[2] += KI_TRAIL_ZPOS; + #undef KI_TRAIL_ZPOS + // // BFP - Aura // @@ -2411,12 +2428,29 @@ void CG_Player( centity_t *cent ) { } \ } - if ( cent->currentState.eFlags & EF_AURA ) { - // BFP - TODO: Create a new function "CG_KiTrail" only when moving to draw ki trail and add the cvar for the length + // Macro to remove ki trails + #define REMOVING_KI_TRAILS(clientNum, kiTrailOrigin, kiTrailShader, fastRemove) \ + if ( cg.time > cent->pe.kiTrailTime ) { /* reset ki trail position avoid being zeroed */ \ + CG_ResetKiTrail( clientNum, kiTrailOrigin ); \ + } else { /* ki trails keep running in that moment, but their segments are being removed */ \ + CG_KiTrail( clientNum, kiTrailOrigin, fastRemove, kiTrailShader ); \ + } + if ( cent->currentState.eFlags & EF_AURA ) { // BFP - Trace for bubble particles only when moving in the water and charging int destContentType = CG_PointContents( legs.origin, -1 ); + // BFP - Ki trail + if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_CHARGE + && cg_kiTrail.integer >= 10 ) { + // apply time for using ki trail + cent->pe.kiTrailTime = cg.time + cg_kiTrail.integer*5; + + CG_KiTrail( clientNum, kiTrailOrigin, qfalse, kiTrailShader ); + } else { // handle when the ki trail was being used previously + REMOVING_KI_TRAILS( clientNum, kiTrailOrigin, kiTrailShader, qtrue ) + } + // spawning bubble particles if ( destContentType & CONTENTS_WATER ) { trace_t trace; @@ -2509,6 +2543,11 @@ void CG_Player( centity_t *cent ) { trap_R_AddRefEntityToScene( &aura2 ); } } + } else { + // BFP - Ki trail being removed + if ( cg_kiTrail.integer >= 10 ) { + REMOVING_KI_TRAILS( clientNum, kiTrailOrigin, kiTrailShader, qtrue ) + } } // BFP - Ki attack sounds @@ -2542,6 +2581,7 @@ void CG_Player( centity_t *cent ) { #undef MODEL_SIZE #undef AURA_ANIMS #undef AURA_LIGHT +#undef REMOVING_KI_TRAILS /* =============== diff --git a/source/cgame/cg_trails.c b/source/cgame/cg_trails.c new file mode 100644 index 0000000..d704bcc --- /dev/null +++ b/source/cgame/cg_trails.c @@ -0,0 +1,128 @@ +#include "cg_local.h" + +#define KI_TRAIL_SEGMENTS 99 +#define KI_TRAIL_WIDTH 15 + +typedef struct { + vec3_t segments[KI_TRAIL_SEGMENTS]; + int numSegments; +} kiTrail_t; + +static kiTrail_t cg_kiTrails[MAX_GENTITIES]; + +/* +=============== +CG_InitKiTrails + +Initializes the array of trails for all centities. +Should be called from CG_Init in cg_main.c +=============== +*/ +void CG_InitKiTrails( void ) { + memset( &cg_kiTrails, 0, sizeof(cg_kiTrails) ); +} + +/* +=============== +CG_ResetKiTrail + +Reset entity's ki trail. +Should be called whenever an entity that has to use a trail, wasn't in the PVS the previous frame. +entityNum: Valid entity number +origin: Point from where the trail should start. + (This should be equal to the entity's current position.) +===================== +*/ +void CG_ResetKiTrail( int entityNum, vec3_t origin ) { + int i; + + for ( i = 0; i < KI_TRAIL_SEGMENTS; i++ ) { + VectorCopy( origin, cg_kiTrails[entityNum].segments[i] ); + } + cg_kiTrails[entityNum].numSegments = 0; +} + +/* +===================== +CG_KiTrail + +Adds ki trail segments +===================== +*/ +void CG_KiTrail( int entityNum, vec3_t origin, qboolean remove, qhandle_t hShader ) { + int i, j; + polyVert_t verts[4]; + + if ( entityNum < 0 || entityNum >= MAX_GENTITIES ) { + return; + } + + if ( remove ) { // removes every segment + cg_kiTrails[entityNum].numSegments--; + } else { + if ( cg_kiTrails[entityNum].numSegments < KI_TRAIL_SEGMENTS ) { + cg_kiTrails[entityNum].numSegments++; + } + } + + // shift points down the buffer + for ( i = cg_kiTrails[entityNum].numSegments - 1; i > 0; i-- ) { + VectorCopy( cg_kiTrails[entityNum].segments[i - 1], cg_kiTrails[entityNum].segments[i] ); + } + + // add the current position at the start + VectorCopy( origin, cg_kiTrails[entityNum].segments[0] ); + + for ( i = 0; i < cg_kiTrails[entityNum].numSegments - 1; i++ ) { + // loop to render the segment 3 times + for ( j = 0; j < 3; j++ ) { + vec3_t start, end, forward, right; + vec3_t viewAxis[3]; + int kiTrailLength = cg_kiTrail.integer; + + if ( kiTrailLength > KI_TRAIL_SEGMENTS ) { + kiTrailLength = KI_TRAIL_SEGMENTS; + } + + if ( i > kiTrailLength ) { + return; + } + + if ( i + j >= cg_kiTrails[entityNum].numSegments - 1 ) { + return; + } + + VectorCopy( cg_kiTrails[entityNum].segments[i + j], start ); + VectorCopy( cg_kiTrails[entityNum].segments[i + j + 1], end ); + + VectorSubtract( end, start, forward ); + VectorNormalize( forward ); + + VectorSubtract( cg.refdef.vieworg, start, viewAxis[0] ); + CrossProduct( viewAxis[0], forward, right ); + VectorNormalize( right ); + + VectorMA( end, KI_TRAIL_WIDTH, right, verts[0].xyz ); + verts[0].st[0] = 0; + verts[0].st[1] = 1; + Vector4Set( verts[0].modulate, 255, 255, 255, 255 ); + + VectorMA( end, -KI_TRAIL_WIDTH, right, verts[1].xyz ); + verts[1].st[0] = 1; + verts[1].st[1] = 0; + Vector4Set( verts[1].modulate, 255, 255, 255, 255 ); + + VectorMA( start, -KI_TRAIL_WIDTH, right, verts[2].xyz ); + verts[2].st[0] = 1; + verts[2].st[1] = 0; + Vector4Set( verts[2].modulate, 255, 255, 255, 255 ); + + VectorMA( start, KI_TRAIL_WIDTH, right, verts[3].xyz ); + verts[3].st[0] = 0; + verts[3].st[1] = 1; + Vector4Set( verts[3].modulate, 255, 255, 255, 255 ); + + trap_R_AddPolyToScene( hShader, 4, verts ); + } + } +} diff --git a/source/cgame/cgame.bat b/source/cgame/cgame.bat index 343f717..ce03fcb 100644 --- a/source/cgame/cgame.bat +++ b/source/cgame/cgame.bat @@ -54,6 +54,8 @@ set cc=..\..\..\tools\bin\lcc.exe -DQ3_VM -S -Wf-target=bytecode -Wf-g -I%src%\c @if errorlevel 1 goto quit %cc% %src%/cgame/cg_snapshot.c @if errorlevel 1 goto quit +%cc% %src%/cgame/cg_trails.c +@if errorlevel 1 goto quit %cc% %src%/cgame/cg_view.c @if errorlevel 1 goto quit %cc% %src%/cgame/cg_weapons.c diff --git a/source/cgame/cgame.q3asm b/source/cgame/cgame.q3asm index 8e69ed5..957c050 100644 --- a/source/cgame/cgame.q3asm +++ b/source/cgame/cgame.q3asm @@ -17,6 +17,7 @@ cg_predict cg_scoreboard cg_servercmds cg_snapshot +cg_trails cg_view cg_weapons bg_slidemove From 883d14df8fb605eeb5249bf9106947dd680db8f7 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Fri, 9 Aug 2024 21:34:07 +0200 Subject: [PATCH 072/374] game: Add VectorArray2Set macro to set values for a vec2_t variable (or any array of 2) and explain correctly Vector4Set macro comment --- source/game/q_shared.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/game/q_shared.h b/source/game/q_shared.h index cbc6c59..bf312dc 100644 --- a/source/game/q_shared.h +++ b/source/game/q_shared.h @@ -656,7 +656,9 @@ typedef struct { #define VectorNegate(a,b) ((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2]) #define VectorSet(v, x, y, z) ((v)[0]=(x), (v)[1]=(y), (v)[2]=(z)) #define Vector4Copy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3]) -// BFP - Vector4Set helps to set the 4 values for a vec4_t variable, making the code shorter in a single line +// BFP - VectorArray2Set sets the 2 values of a vec2_t variable (or any array of 2) in a single line +#define VectorArray2Set(v,x,y) ((v)[0]=(x), (v)[1]=(y)) +// BFP - Vector4Set sets the 4 values of a vec4_t variable (or any array of 4) in a single line #define Vector4Set(v,w,x,y,z) ((v)[0]=(w), (v)[1]=(x), (v)[2]=(y), (v)[3]=(z)) #define SnapVector(v) {v[0]=((int)(v[0]));v[1]=((int)(v[1]));v[2]=((int)(v[2]));} From ad88d69304c51f423528bdba78962609d766b1b0 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Fri, 9 Aug 2024 21:36:15 +0200 Subject: [PATCH 073/374] cgame: Apply some parts of the code using VectorArray2Set and Vector4Set, that shortens the number of lines of code --- source/cgame/cg_particles.c | 219 +++++++++--------------------------- source/cgame/cg_players.c | 37 ++---- source/cgame/cg_trails.c | 12 +- source/cgame/cg_weapons.c | 32 ++---- 4 files changed, 76 insertions(+), 224 deletions(-) diff --git a/source/cgame/cg_particles.c b/source/cgame/cg_particles.c index b54a06e..565ecbe 100644 --- a/source/cgame/cg_particles.c +++ b/source/cgame/cg_particles.c @@ -242,32 +242,20 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) VectorMA (org, -p->height, vup, point); VectorMA (point, -p->width, vright, point); VectorCopy( point, TRIverts[0].xyz ); - TRIverts[0].st[0] = 1; - TRIverts[0].st[1] = 0; - TRIverts[0].modulate[0] = 255; - TRIverts[0].modulate[1] = 255; - TRIverts[0].modulate[2] = 255; - TRIverts[0].modulate[3] = 255 * p->alpha; + VectorArray2Set( TRIverts[0].st, 1, 0 ); + Vector4Set( TRIverts[0].modulate, 255, 255, 255, 255 * p->alpha ); VectorMA (org, p->height, vup, point); VectorMA (point, -p->width, vright, point); VectorCopy (point, TRIverts[1].xyz); - TRIverts[1].st[0] = 0; - TRIverts[1].st[1] = 0; - TRIverts[1].modulate[0] = 255; - TRIverts[1].modulate[1] = 255; - TRIverts[1].modulate[2] = 255; - TRIverts[1].modulate[3] = 255 * p->alpha; + VectorArray2Set( TRIverts[0].st, 0, 0 ); + Vector4Set( TRIverts[1].modulate, 255, 255, 255, 255 * p->alpha ); VectorMA (org, p->height, vup, point); VectorMA (point, p->width, vright, point); VectorCopy (point, TRIverts[2].xyz); - TRIverts[2].st[0] = 0; - TRIverts[2].st[1] = 1; - TRIverts[2].modulate[0] = 255; - TRIverts[2].modulate[1] = 255; - TRIverts[2].modulate[2] = 255; - TRIverts[2].modulate[3] = 255 * p->alpha; + VectorArray2Set( TRIverts[0].st, 0, 1 ); + Vector4Set( TRIverts[2].modulate, 255, 255, 255, 255 * p->alpha ); } // else if ... #endif @@ -298,12 +286,8 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) VectorMA (point, -width, vright, point); } VectorCopy (point, verts[0].xyz); - verts[0].st[0] = 0; - verts[0].st[1] = 0; - verts[0].modulate[0] = 255; - verts[0].modulate[1] = 255; - verts[0].modulate[2] = 255; - verts[0].modulate[3] = 255; + VectorArray2Set( verts[0].st, 0, 0 ); + Vector4Set( verts[0].modulate, 255, 255, 255, 255 ); if (p->roll) { VectorMA (point, 2*height, ru, point); @@ -311,12 +295,8 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) VectorMA (point, 2*height, vup, point); } VectorCopy (point, verts[1].xyz); - verts[1].st[0] = 0; - verts[1].st[1] = 1; - verts[1].modulate[0] = 255; - verts[1].modulate[1] = 255; - verts[1].modulate[2] = 255; - verts[1].modulate[3] = 255; + VectorArray2Set( verts[1].st, 0, 1 ); + Vector4Set( verts[1].modulate, 255, 255, 255, 255 ); if (p->roll) { VectorMA (point, 2*width, rr, point); @@ -324,12 +304,8 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) VectorMA (point, 2*width, vright, point); } VectorCopy (point, verts[2].xyz); - verts[2].st[0] = 1; - verts[2].st[1] = 1; - verts[2].modulate[0] = 255; - verts[2].modulate[1] = 255; - verts[2].modulate[2] = 255; - verts[2].modulate[3] = 255; + VectorArray2Set( verts[2].st, 1, 1 ); + Vector4Set( verts[2].modulate, 255, 255, 255, 255 ); if (p->roll) { VectorMA (point, -2*height, ru, point); @@ -337,12 +313,8 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) VectorMA (point, -2*height, vup, point); } VectorCopy (point, verts[3].xyz); - verts[3].st[0] = 1; - verts[3].st[1] = 0; - verts[3].modulate[0] = 255; - verts[3].modulate[1] = 255; - verts[3].modulate[2] = 255; - verts[3].modulate[3] = 255; + VectorArray2Set( verts[3].st, 1, 0 ); + Vector4Set( verts[3].modulate, 255, 255, 255, 255 ); } else if (p->type == P_SMOKE || p->type == P_SMOKE_IMPACT || p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT // BFP - Bubble types moved here for better management @@ -491,12 +463,8 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) VectorMA (point, -p->width, vright, point); } VectorCopy (point, verts[0].xyz); - verts[0].st[0] = 0; - verts[0].st[1] = 0; - verts[0].modulate[0] = 255 * color[0]; - verts[0].modulate[1] = 255 * color[1]; - verts[0].modulate[2] = 255 * color[2]; - verts[0].modulate[3] = 255 * invratio; + VectorArray2Set( verts[0].st, 0, 0 ); + Vector4Set( verts[0].modulate, 255 * color[0], 255 * color[1], 255 * color[2], 255 * invratio ); if (p->rotate) { @@ -509,12 +477,8 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) VectorMA (point, p->width, vright, point); } VectorCopy (point, verts[1].xyz); - verts[1].st[0] = 0; - verts[1].st[1] = 1; - verts[1].modulate[0] = 255 * color[0]; - verts[1].modulate[1] = 255 * color[1]; - verts[1].modulate[2] = 255 * color[2]; - verts[1].modulate[3] = 255 * invratio; + VectorArray2Set( verts[1].st, 0, 1 ); + Vector4Set( verts[1].modulate, 255 * color[0], 255 * color[1], 255 * color[2], 255 * invratio ); if (p->rotate) { @@ -527,12 +491,8 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) VectorMA (point, p->width, vright, point); } VectorCopy (point, verts[2].xyz); - verts[2].st[0] = 1; - verts[2].st[1] = 1; - verts[2].modulate[0] = 255 * color[0]; - verts[2].modulate[1] = 255 * color[1]; - verts[2].modulate[2] = 255 * color[2]; - verts[2].modulate[3] = 255 * invratio; + VectorArray2Set( verts[2].st, 1, 1 ); + Vector4Set( verts[2].modulate, 255 * color[0], 255 * color[1], 255 * color[2], 255 * invratio ); if (p->rotate) { @@ -545,12 +505,8 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) VectorMA (point, -p->width, vright, point); } VectorCopy (point, verts[3].xyz); - verts[3].st[0] = 1; - verts[3].st[1] = 0; - verts[3].modulate[0] = 255 * color[0]; - verts[3].modulate[1] = 255 * color[1]; - verts[3].modulate[2] = 255 * color[2]; - verts[3].modulate[3] = 255 * invratio; + VectorArray2Set( verts[3].st, 1, 0 ); + Vector4Set( verts[3].modulate, 255 * color[0], 255 * color[1], 255 * color[2], 255 * invratio ); } else if (p->type == P_BLEED) { @@ -575,42 +531,26 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) VectorMA (org, -p->height, ru, point); VectorMA (point, -p->width, rr, point); VectorCopy (point, verts[0].xyz); - verts[0].st[0] = 0; - verts[0].st[1] = 0; - verts[0].modulate[0] = 111; - verts[0].modulate[1] = 19; - verts[0].modulate[2] = 9; - verts[0].modulate[3] = 255 * alpha; + VectorArray2Set( verts[0].st, 0, 0 ); + Vector4Set( verts[0].modulate, 111, 19, 9, 255 * alpha ); VectorMA (org, -p->height, ru, point); VectorMA (point, p->width, rr, point); VectorCopy (point, verts[1].xyz); - verts[1].st[0] = 0; - verts[1].st[1] = 1; - verts[1].modulate[0] = 111; - verts[1].modulate[1] = 19; - verts[1].modulate[2] = 9; - verts[1].modulate[3] = 255 * alpha; + VectorArray2Set( verts[1].st, 0, 1 ); + Vector4Set( verts[1].modulate, 111, 19, 9, 255 * alpha ); VectorMA (org, p->height, ru, point); VectorMA (point, p->width, rr, point); - VectorCopy (point, verts[2].xyz); - verts[2].st[0] = 1; - verts[2].st[1] = 1; - verts[2].modulate[0] = 111; - verts[2].modulate[1] = 19; - verts[2].modulate[2] = 9; - verts[2].modulate[3] = 255 * alpha; + VectorCopy (point, verts[2].xyz); + VectorArray2Set( verts[2].st, 1, 1 ); + Vector4Set( verts[2].modulate, 111, 19, 9, 255 * alpha ); VectorMA (org, p->height, ru, point); VectorMA (point, -p->width, rr, point); VectorCopy (point, verts[3].xyz); - verts[3].st[0] = 1; - verts[3].st[1] = 0; - verts[3].modulate[0] = 111; - verts[3].modulate[1] = 19; - verts[3].modulate[2] = 9; - verts[3].modulate[3] = 255 * alpha; + VectorArray2Set( verts[3].st, 1, 0 ); + Vector4Set( verts[3].modulate, 111, 19, 9, 255 * alpha ); } #if 0 /* // BFP - Unused particle type conditionals */ @@ -643,42 +583,26 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) VectorCopy (org, verts[0].xyz); verts[0].xyz[0] -= sinR; verts[0].xyz[1] -= cosR; - verts[0].st[0] = 0; - verts[0].st[1] = 0; - verts[0].modulate[0] = 255 * color[0]; - verts[0].modulate[1] = 255 * color[1]; - verts[0].modulate[2] = 255 * color[2]; - verts[0].modulate[3] = 255; + VectorArray2Set( verts[0].st, 0, 0 ); + Vector4Set( verts[0].modulate, 255 * color[0], 255 * color[1], 255 * color[2], 255 ); VectorCopy (org, verts[1].xyz); verts[1].xyz[0] -= cosR; verts[1].xyz[1] += sinR; - verts[1].st[0] = 0; - verts[1].st[1] = 1; - verts[1].modulate[0] = 255 * color[0]; - verts[1].modulate[1] = 255 * color[1]; - verts[1].modulate[2] = 255 * color[2]; - verts[1].modulate[3] = 255; + VectorArray2Set( verts[1].st, 0, 1 ); + Vector4Set( verts[1].modulate, 255 * color[0], 255 * color[1], 255 * color[2], 255 ); VectorCopy (org, verts[2].xyz); verts[2].xyz[0] += sinR; verts[2].xyz[1] += cosR; - verts[2].st[0] = 1; - verts[2].st[1] = 1; - verts[2].modulate[0] = 255 * color[0]; - verts[2].modulate[1] = 255 * color[1]; - verts[2].modulate[2] = 255 * color[2]; - verts[2].modulate[3] = 255; + VectorArray2Set( verts[2].st, 1, 1 ); + Vector4Set( verts[2].modulate, 255 * color[0], 255 * color[1], 255 * color[2], 255 ); VectorCopy (org, verts[3].xyz); verts[3].xyz[0] += cosR; verts[3].xyz[1] -= sinR; - verts[3].st[0] = 1; - verts[3].st[1] = 0; - verts[3].modulate[0] = 255 * color[0]; - verts[3].modulate[1] = 255 * color[1]; - verts[3].modulate[2] = 255 * color[2]; - verts[3].modulate[3] = 255; + VectorArray2Set( verts[3].st, 1, 0 ); + Vector4Set( verts[3].modulate, 255 * color[0], 255 * color[1], 255 * color[2], 255 ); } else if (p->type == P_FLAT) { @@ -686,43 +610,26 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) VectorCopy (org, verts[0].xyz); verts[0].xyz[0] -= p->height; verts[0].xyz[1] -= p->width; - verts[0].st[0] = 0; - verts[0].st[1] = 0; - verts[0].modulate[0] = 255; - verts[0].modulate[1] = 255; - verts[0].modulate[2] = 255; - verts[0].modulate[3] = 255; + VectorArray2Set( verts[0].st, 0, 0 ); + Vector4Set( verts[0].modulate, 255, 255, 255, 255 ); VectorCopy (org, verts[1].xyz); verts[1].xyz[0] -= p->height; verts[1].xyz[1] += p->width; - verts[1].st[0] = 0; - verts[1].st[1] = 1; - verts[1].modulate[0] = 255; - verts[1].modulate[1] = 255; - verts[1].modulate[2] = 255; - verts[1].modulate[3] = 255; + VectorArray2Set( verts[1].st, 0, 1 ); + Vector4Set( verts[1].modulate, 255, 255, 255, 255 ); VectorCopy (org, verts[2].xyz); verts[2].xyz[0] += p->height; verts[2].xyz[1] += p->width; - verts[2].st[0] = 1; - verts[2].st[1] = 1; - verts[2].modulate[0] = 255; - verts[2].modulate[1] = 255; - verts[2].modulate[2] = 255; - verts[2].modulate[3] = 255; + VectorArray2Set( verts[2].st, 1, 1 ); + Vector4Set( verts[2].modulate, 255, 255, 255, 255 ); VectorCopy (org, verts[3].xyz); verts[3].xyz[0] += p->height; verts[3].xyz[1] -= p->width; - verts[3].st[0] = 1; - verts[3].st[1] = 0; - verts[3].modulate[0] = 255; - verts[3].modulate[1] = 255; - verts[3].modulate[2] = 255; - verts[3].modulate[3] = 255; - + VectorArray2Set( verts[3].st, 1, 0 ); + Vector4Set( verts[3].modulate, 255, 255, 255, 255 ); } #endif // Ridah @@ -764,12 +671,8 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) VectorMA (point, -width, vright, point); } VectorCopy (point, verts[0].xyz); - verts[0].st[0] = 0; - verts[0].st[1] = 0; - verts[0].modulate[0] = 255; - verts[0].modulate[1] = 255; - verts[0].modulate[2] = 255; - verts[0].modulate[3] = 255; + VectorArray2Set( verts[0].st, 0, 0 ); + Vector4Set( verts[0].modulate, 255, 255, 255, 255 ); if (p->roll) { VectorMA (point, 2*height, ru, point); @@ -777,12 +680,8 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) VectorMA (point, 2*height, vup, point); } VectorCopy (point, verts[1].xyz); - verts[1].st[0] = 0; - verts[1].st[1] = 1; - verts[1].modulate[0] = 255; - verts[1].modulate[1] = 255; - verts[1].modulate[2] = 255; - verts[1].modulate[3] = 255; + VectorArray2Set( verts[1].st, 0, 1 ); + Vector4Set( verts[1].modulate, 255, 255, 255, 255 ); if (p->roll) { VectorMA (point, 2*width, rr, point); @@ -790,12 +689,8 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) VectorMA (point, 2*width, vright, point); } VectorCopy (point, verts[2].xyz); - verts[2].st[0] = 1; - verts[2].st[1] = 1; - verts[2].modulate[0] = 255; - verts[2].modulate[1] = 255; - verts[2].modulate[2] = 255; - verts[2].modulate[3] = 255; + VectorArray2Set( verts[2].st, 1, 1 ); + Vector4Set( verts[2].modulate, 255, 255, 255, 255 ); if (p->roll) { VectorMA (point, -2*height, ru, point); @@ -803,12 +698,8 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) VectorMA (point, -2*height, vup, point); } VectorCopy (point, verts[3].xyz); - verts[3].st[0] = 1; - verts[3].st[1] = 0; - verts[3].modulate[0] = 255; - verts[3].modulate[1] = 255; - verts[3].modulate[2] = 255; - verts[3].modulate[3] = 255; + VectorArray2Set( verts[3].st, 1, 0 ); + Vector4Set( verts[3].modulate, 255, 255, 255, 255 ); } // done. diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index b8115ef..2f8458e 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -2036,42 +2036,26 @@ static void CG_PlayerSplash( centity_t *cent ) { VectorCopy( trace.endpos, verts[0].xyz ); verts[0].xyz[0] -= 32; verts[0].xyz[1] -= 32; - verts[0].st[0] = 0; - verts[0].st[1] = 0; - verts[0].modulate[0] = 255; - verts[0].modulate[1] = 255; - verts[0].modulate[2] = 255; - verts[0].modulate[3] = 255; + VectorArray2Set( verts[0].st, 0, 0 ); + Vector4Set( verts[0].modulate, 255, 255, 255, 255 ); VectorCopy( trace.endpos, verts[1].xyz ); verts[1].xyz[0] -= 32; verts[1].xyz[1] += 32; - verts[1].st[0] = 0; - verts[1].st[1] = 1; - verts[1].modulate[0] = 255; - verts[1].modulate[1] = 255; - verts[1].modulate[2] = 255; - verts[1].modulate[3] = 255; + VectorArray2Set( verts[1].st, 0, 1 ); + Vector4Set( verts[1].modulate, 255, 255, 255, 255 ); VectorCopy( trace.endpos, verts[2].xyz ); verts[2].xyz[0] += 32; verts[2].xyz[1] += 32; - verts[2].st[0] = 1; - verts[2].st[1] = 1; - verts[2].modulate[0] = 255; - verts[2].modulate[1] = 255; - verts[2].modulate[2] = 255; - verts[2].modulate[3] = 255; + VectorArray2Set( verts[2].st, 1, 1 ); + Vector4Set( verts[2].modulate, 255, 255, 255, 255 ); VectorCopy( trace.endpos, verts[3].xyz ); verts[3].xyz[0] += 32; verts[3].xyz[1] -= 32; - verts[3].st[0] = 1; - verts[3].st[1] = 0; - verts[3].modulate[0] = 255; - verts[3].modulate[1] = 255; - verts[3].modulate[2] = 255; - verts[3].modulate[3] = 255; + VectorArray2Set( verts[3].st, 1, 0 ); + Vector4Set( verts[3].modulate, 255, 255, 255, 255 ); trap_R_AddPolyToScene( cgs.media.wakeMarkShader, 4, verts ); } @@ -2159,10 +2143,7 @@ int CG_LightVerts( vec3_t normal, int numVerts, polyVert_t *verts ) for (i = 0; i < numVerts; i++) { incoming = DotProduct (normal, lightDir); if ( incoming <= 0 ) { - verts[i].modulate[0] = ambientLight[0]; - verts[i].modulate[1] = ambientLight[1]; - verts[i].modulate[2] = ambientLight[2]; - verts[i].modulate[3] = 255; + Vector4Set( verts[i].modulate, ambientLight[0], ambientLight[1], ambientLight[2], 255 ); continue; } j = ( ambientLight[0] + incoming * directedLight[0] ); diff --git a/source/cgame/cg_trails.c b/source/cgame/cg_trails.c index d704bcc..1fba716 100644 --- a/source/cgame/cg_trails.c +++ b/source/cgame/cg_trails.c @@ -103,23 +103,19 @@ void CG_KiTrail( int entityNum, vec3_t origin, qboolean remove, qhandle_t hShade VectorNormalize( right ); VectorMA( end, KI_TRAIL_WIDTH, right, verts[0].xyz ); - verts[0].st[0] = 0; - verts[0].st[1] = 1; + VectorArray2Set( verts[0].st, 0, 1 ); Vector4Set( verts[0].modulate, 255, 255, 255, 255 ); VectorMA( end, -KI_TRAIL_WIDTH, right, verts[1].xyz ); - verts[1].st[0] = 1; - verts[1].st[1] = 0; + VectorArray2Set( verts[1].st, 1, 0 ); Vector4Set( verts[1].modulate, 255, 255, 255, 255 ); VectorMA( start, -KI_TRAIL_WIDTH, right, verts[2].xyz ); - verts[2].st[0] = 1; - verts[2].st[1] = 0; + VectorArray2Set( verts[2].st, 1, 0 ); Vector4Set( verts[2].modulate, 255, 255, 255, 255 ); VectorMA( start, KI_TRAIL_WIDTH, right, verts[3].xyz ); - verts[3].st[0] = 0; - verts[3].st[1] = 1; + VectorArray2Set( verts[3].st, 0, 1 ); Vector4Set( verts[3].modulate, 255, 255, 255, 255 ); trap_R_AddPolyToScene( hShader, 4, verts ); diff --git a/source/cgame/cg_weapons.c b/source/cgame/cg_weapons.c index 3dc4950..d2b8c32 100644 --- a/source/cgame/cg_weapons.c +++ b/source/cgame/cg_weapons.c @@ -1953,36 +1953,20 @@ void CG_Tracer( vec3_t source, vec3_t dest ) { VectorNormalize( right ); VectorMA( finish, cg_tracerWidth.value, right, verts[0].xyz ); - verts[0].st[0] = 0; - verts[0].st[1] = 1; - verts[0].modulate[0] = 255; - verts[0].modulate[1] = 255; - verts[0].modulate[2] = 255; - verts[0].modulate[3] = 255; + VectorArray2Set( verts[0].st, 0, 1 ); + Vector4Set( verts[0].modulate, 255, 255, 255, 255 ); VectorMA( finish, -cg_tracerWidth.value, right, verts[1].xyz ); - verts[1].st[0] = 1; - verts[1].st[1] = 0; - verts[1].modulate[0] = 255; - verts[1].modulate[1] = 255; - verts[1].modulate[2] = 255; - verts[1].modulate[3] = 255; + VectorArray2Set( verts[1].st, 1, 0 ); + Vector4Set( verts[1].modulate, 255, 255, 255, 255 ); VectorMA( start, -cg_tracerWidth.value, right, verts[2].xyz ); - verts[2].st[0] = 1; - verts[2].st[1] = 1; - verts[2].modulate[0] = 255; - verts[2].modulate[1] = 255; - verts[2].modulate[2] = 255; - verts[2].modulate[3] = 255; + VectorArray2Set( verts[2].st, 1, 1 ); + Vector4Set( verts[2].modulate, 255, 255, 255, 255 ); VectorMA( start, cg_tracerWidth.value, right, verts[3].xyz ); - verts[3].st[0] = 0; - verts[3].st[1] = 0; - verts[3].modulate[0] = 255; - verts[3].modulate[1] = 255; - verts[3].modulate[2] = 255; - verts[3].modulate[3] = 255; + VectorArray2Set( verts[3].st, 0, 0 ); + Vector4Set( verts[3].modulate, 255, 255, 255, 255 ); trap_R_AddPolyToScene( cgs.media.tracerShader, 4, verts ); From 5ffed27683a22a6f5c9b76fffe1f8aa42fe6d3c1 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sat, 10 Aug 2024 18:55:11 +0200 Subject: [PATCH 074/374] cgame: Remove an unused variable in cparticle_t struct and 2 unused enums in particle_type_t --- source/cgame/cg_particles.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/source/cgame/cg_particles.c b/source/cgame/cg_particles.c index 565ecbe..d85b587 100644 --- a/source/cgame/cg_particles.c +++ b/source/cgame/cg_particles.c @@ -39,7 +39,6 @@ typedef struct particle_s vec3_t vel; vec3_t accel; int color; - float colorvel; float alpha; float alphavel; int type; @@ -73,9 +72,7 @@ typedef enum P_NONE, P_ANTIGRAV_ROCK, // BFP - Antigrav rock particles P_SMOKE, - P_ROTATE, P_ANIM, // Ridah - P_BAT, P_BLEED, P_SMOKE_IMPACT, P_BUBBLE, @@ -788,7 +785,7 @@ void CG_AddParticles (void) } } - if ((p->type == P_BAT || p->type == P_SPRITE) && p->endtime < 0) { + if (p->type == P_SPRITE && p->endtime < 0) { // temporary sprite CG_AddParticleToScene (p, p->org, alpha); p->next = free_particles; From 5cfa4db80e21105783bdfac2e63ca42e1992a1c7 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sun, 11 Aug 2024 18:56:40 +0200 Subject: [PATCH 075/374] cgame: Locate where the ki attacks (weapons) can be attached to player tags and fix lightning bolt not displaying with Lightning gun --- source/cgame/cg_weapons.c | 40 ++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/source/cgame/cg_weapons.c b/source/cgame/cg_weapons.c index d2b8c32..07b74b8 100644 --- a/source/cgame/cg_weapons.c +++ b/source/cgame/cg_weapons.c @@ -739,8 +739,6 @@ VIEW WEAPON ======================================================================================== */ -// BFP - TODO: Change animations for BFP - /* ================= CG_MapTorsoToWeaponFrame @@ -1013,6 +1011,8 @@ static void CG_SpawnRailTrail( centity_t *cent, vec3_t origin ) { } +// BFP - TODO: Remove these functions, these won't be used nonetheless +#if 0 /* ====================== CG_MachinegunSpinAngle @@ -1046,7 +1046,6 @@ static float CG_MachinegunSpinAngle( centity_t *cent ) { return angle; } - /* ======================== CG_AddWeaponWithPowerups @@ -1070,6 +1069,7 @@ static void CG_AddWeaponWithPowerups( refEntity_t *gun, int powerups ) { } } } +#endif /* @@ -1081,23 +1081,29 @@ The main player will have this called for BOTH cases, so effects like light and sound should only be done on the world model case. ============= */ +// BFP - TODO: That needs some cleanup and managing correctly the weapons. +// Next time, unused code will be removed for clear and concise logic purposes. +// The same goes to CG_AddWeaponWithPowerups and CG_MachinegunSpinAngle void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent, int team ) { - refEntity_t gun; - refEntity_t barrel; - refEntity_t flash; +#if 0 + refEntity_t gun, barrel; vec3_t angles; +#endif + refEntity_t flash; weapon_t weaponNum; weaponInfo_t *weapon; centity_t *nonPredictedCent; -// int col; weaponNum = cent->currentState.weapon; CG_RegisterWeapon( weaponNum ); weapon = &cg_weapons[weaponNum]; + // BFP - Hide gun model +#if 0 // add the weapon memset( &gun, 0, sizeof( gun ) ); + VectorCopy( parent->lightingOrigin, gun.lightingOrigin ); gun.shadowPlane = parent->shadowPlane; gun.renderfx = parent->renderfx; @@ -1119,11 +1125,11 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent gun.shaderRGBA[3] = 255; } } - - // gun.hModel = weapon->weaponModel; // BFP - Hide weapon model + gun.hModel = weapon->weaponModel; if (!gun.hModel) { return; } +#endif if ( !ps ) { // add weapon ready sound @@ -1137,8 +1143,11 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent } } - CG_PositionEntityOnTag( &gun, parent, parent->hModel, "tag_weapon"); + // BFP - Hide barrel model and unused position entity tag property +#if 0 + // CG_PositionEntityOnTag( &gun, parent, parent->hModel, "tag_weapon"); + // BFP - TODO: Remove that function, it won't be used nonetheless CG_AddWeaponWithPowerups( &gun, cent->currentState.powerups ); // add the spinning barrel @@ -1158,6 +1167,7 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent CG_AddWeaponWithPowerups( &barrel, cent->currentState.powerups ); } +#endif // make sure we aren't looking at cg.predictedPlayerEntity for LG nonPredictedCent = &cg_entities[cent->currentState.clientNum]; @@ -1181,8 +1191,10 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent } } - memset( &flash, 0, sizeof( flash ) ); + // memset( &flash, 0, sizeof( flash ) ); VectorCopy( parent->lightingOrigin, flash.lightingOrigin ); + // BFP - Hide flash model +#if 0 flash.shadowPlane = parent->shadowPlane; flash.renderfx = parent->renderfx; @@ -1204,9 +1216,11 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent flash.shaderRGBA[1] = 255 * ci->color1[1]; flash.shaderRGBA[2] = 255 * ci->color1[2]; } +#endif - CG_PositionRotatedEntityOnTag( &flash, &gun, weapon->weaponModel, "tag_flash"); - trap_R_AddRefEntityToScene( &flash ); + // BFP - NOTE: Here's where the player gets the muzzle attached from some of the tags (apply that to client cfg side) (tag_left, tag_right...) + CG_PositionRotatedEntityOnTag( &flash, parent, parent->hModel, "tag_right"); + // trap_R_AddRefEntityToScene( &flash ); if ( ps || cg.renderingThirdPerson || cent->currentState.number != cg.predictedPlayerState.clientNum ) { From dbc954a3d98948ba8f4578722a2ee25f7d2293fd Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 12 Aug 2024 02:22:14 +0200 Subject: [PATCH 076/374] cgame: Put the floating sprite a bit up and don't show the flag model to the player itself --- source/cgame/cg_players.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index 2f8458e..60bf76c 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -1569,6 +1569,11 @@ static void CG_TrailItem( centity_t *cent, qhandle_t hModel ) { vec3_t angles; vec3_t axis[3]; + // BFP - Don't show the model to the player itself + if ( cent->currentState.clientNum == cg.snap->ps.clientNum ) { + return; + } + VectorCopy( cent->lerpAngles, angles ); angles[PITCH] = 0; angles[ROLL] = 0; @@ -1821,7 +1826,7 @@ static void CG_PlayerFloatSprite( centity_t *cent, qhandle_t shader ) { memset( &ent, 0, sizeof( ent ) ); VectorCopy( cent->lerpOrigin, ent.origin ); - ent.origin[2] += 48; + ent.origin[2] += 70; // BFP - BFP puts the floating sprite a bit up. Q3 default: 48 ent.reType = RT_SPRITE; ent.customShader = shader; ent.radius = 10; @@ -1866,9 +1871,11 @@ static void CG_PlayerSprites( centity_t *cent ) { cent->currentState.number != cg.snap->ps.clientNum && // BFP - Don't show the friend team shader to the player itself cg.snap->ps.persistant[PERS_TEAM] == team && cgs.gametype >= GT_TEAM) { - if (cg_drawFriend.integer) { + // BFP - BFP doesn't use cg_drawFriend to draw that floating friend sprite, keeps enabled always. + // Just wonder if it was some kind of logic reason and looks like that cvar to be removed was also forgotten + // if (cg_drawFriend.integer) { CG_PlayerFloatSprite( cent, cgs.media.friendShader ); - } + // } return; } } From c69a4fe1b1c205429bf3dce45717249aa14056ad Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 12 Aug 2024 02:58:44 +0200 Subject: [PATCH 077/374] game: Apply when being underwater at waterlevel 3 or more, handle flying animation when being underwater, put the trace when landing more down and, fix when player flying up and when player jumps unintentionally --- source/game/bg_pmove.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index 8652eed..2197326 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -690,9 +690,8 @@ static void PM_FlyMove( void ) { VectorClear( wishvel ); } else { for ( i = 0; i < 3; i++ ) { - wishvel[i] = scale * pml.forward[i]*pm->cmd.forwardmove + scale * pml.right[i]*pm->cmd.rightmove; + wishvel[i] = scale * pml.forward[i]*pm->cmd.forwardmove + scale * pml.right[i]*pm->cmd.rightmove + scale * pml.up[i]*pm->cmd.upmove; } - wishvel[2] += scale * pm->cmd.upmove; } VectorCopy (wishvel, wishdir); @@ -1398,7 +1397,12 @@ static void PM_GroundTrace( void ) { pm->ps->groundEntityNum = trace.entityNum; // don't reset the z velocity for slopes - pm->ps->velocity[2] = 0; // BFP - Avoid jumping unintentionally when that happens + // pm->ps->velocity[2] = 0; + + // BFP - Avoid jumping unintentionally when that happens + if ( trace.plane.normal[2] == 1.0 ) { + pm->ps->velocity[2] = 0; + } PM_AddTouchEnt( trace.entityNum ); } @@ -1572,9 +1576,9 @@ static void PM_Footsteps( void ) { // BFP - PM_CheckStuck has been moved here, Q3 and the rest of mods hadn't used this PM_CheckStuck(); - // BFP - Water animation handling, uses flying animation in that case + // BFP - Underwater animation handling, uses flying animation in that case // also keep the torso - if ( pm->waterlevel > 1 ) { + if ( pm->waterlevel > 2 ) { CONTINUEFLY_ANIM_HANDLING() } else { // BFP - Keep the torso when using a ki attack even after charged, avoid when melee is being used @@ -1700,9 +1704,7 @@ static void PM_WaterEvents( void ) { // FIXME? if (pml.previous_waterlevel && !pm->waterlevel) { PM_AddEvent( EV_WATER_LEAVE ); // BFP - Handle jumping animation when getting out of the water - if ( pm->ps->powerups[PW_FLIGHT] <= 0 - && ( pm->ps->pm_flags & PMF_FALLING ) ) { - pm->ps->pm_flags &= ~PMF_FALLING; + if ( pm->ps->powerups[PW_FLIGHT] <= 0 ) { FORCEJUMP_ANIM_HANDLING(); } } @@ -1794,7 +1796,7 @@ static void PM_TorsoAnimation( void ) { } VectorCopy( pm->ps->origin, point ); - point[2] -= 64; + point[2] -= 128; // BFP - Put more down, obviously it was 64, but BFP does that pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask); pml.groundTrace = trace; From 214ab4e57f116161d7c3469e30be896b965411ba Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 12 Aug 2024 13:18:58 +0200 Subject: [PATCH 078/374] game: Double jump velocity when using ki boost and apply backwards movement when getting out from water into some spot --- source/game/bg_pmove.c | 63 ++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index 2197326..81f7da4 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -494,6 +494,11 @@ static qboolean PM_CheckJump( void ) { pm->ps->groundEntityNum = ENTITYNUM_NONE; pm->ps->velocity[2] = JUMP_VELOCITY; + // BFP - Double jump velocity when using ki boost + if ( pm->ps->powerups[PW_HASTE] > 0 ) { + pm->ps->velocity[2] *= 2; + } + PM_AddEvent( EV_JUMP ); // BFP - No PMF_BACKWARDS_JUMP handling (code removed) @@ -510,9 +515,12 @@ PM_CheckWaterJump ============= */ static qboolean PM_CheckWaterJump( void ) { - vec3_t spot; + // BFP - Apply for backwards too, Q3 doesn't have that + vec3_t spot, backwardSpot; int cont; - vec3_t flatforward; + vec3_t flatforward, flatbackward; +#define WATER_JUMP_HORIZONTAL_VELOCITY 200 +#define WATER_JUMP_VERTICAL_VELOCITY 250 if (pm->ps->pm_time) { return qfalse; @@ -528,31 +536,44 @@ static qboolean PM_CheckWaterJump( void ) { flatforward[2] = 0; VectorNormalize (flatforward); - VectorMA (pm->ps->origin, 30, flatforward, spot); + // backward direction + flatbackward[0] = -pml.forward[0]; + flatbackward[1] = -pml.forward[1]; + flatbackward[2] = 0; + VectorNormalize( flatbackward ); + + // check forward + VectorMA ( pm->ps->origin, 30, flatforward, spot ); spot[2] += 4; - cont = pm->pointcontents (spot, pm->ps->clientNum ); - if ( !(cont & CONTENTS_SOLID) ) { - return qfalse; + cont = pm->pointcontents( spot, pm->ps->clientNum ); + if ( cont & CONTENTS_SOLID ) { + spot[2] += 16; + cont = pm->pointcontents( spot, pm->ps->clientNum ); + if ( !cont ) { + VectorScale( pml.forward, WATER_JUMP_HORIZONTAL_VELOCITY, pm->ps->velocity ); + pm->ps->velocity[2] = WATER_JUMP_VERTICAL_VELOCITY; + return qtrue; + } } - spot[2] += 16; - cont = pm->pointcontents (spot, pm->ps->clientNum ); - if ( cont ) { - return qfalse; + // check backward + VectorMA( pm->ps->origin, 30, flatbackward, spot ); + spot[2] += 4; + cont = pm->pointcontents( spot, pm->ps->clientNum ); + if ( cont & CONTENTS_SOLID ) { + spot[2] += 16; + cont = pm->pointcontents( spot, pm->ps->clientNum ); + if ( !cont ) { + VectorScale( pml.forward, -WATER_JUMP_HORIZONTAL_VELOCITY, pm->ps->velocity ); + pm->ps->velocity[2] = WATER_JUMP_VERTICAL_VELOCITY; + return qtrue; + } } - // jump out of water - VectorScale (pml.forward, 200, pm->ps->velocity); - pm->ps->velocity[2] = 250; // BFP - before 350 - - // BFP - No handling PMF_TIME_WATERJUMP -#if 0 - pm->ps->pm_flags |= PMF_TIME_WATERJUMP; - pm->ps->pm_time = 2000; -#endif - - return qtrue; + return qfalse; } +#undef WATER_JUMP_HORIZONTAL_VELOCITY +#undef WATER_JUMP_VERTICAL_VELOCITY //============================================================================ From d50c83fbc6a6c7dc33f9610acdb128cb637dca09 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Wed, 14 Aug 2024 23:52:42 +0200 Subject: [PATCH 079/374] cgame: Fix bubbles when passing through something solid, so now it's better handled when being grazed to the surface are removed, and increase MAX_PARTICLES limit a bit multiplying by 5 --- source/cgame/cg_particles.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/source/cgame/cg_particles.c b/source/cgame/cg_particles.c index d85b587..37ebee3 100644 --- a/source/cgame/cg_particles.c +++ b/source/cgame/cg_particles.c @@ -750,7 +750,8 @@ void CG_AddParticles (void) oldtime = timenonscaled; - active = tail = NULL; + active = NULL; + tail = NULL; for (p=active_particles ; p ; p=next) { @@ -909,7 +910,7 @@ void CG_BubblesWaterHandling( cparticle_t *p, vec3_t org ) { int i; VectorCopy( org, end ); - end[2] -= 15; + end[2] -= 1; VectorCopy( org, start ); start[2] += 10; @@ -932,10 +933,6 @@ void CG_BubblesWaterHandling( cparticle_t *p, vec3_t org ) { // if the particle is touching something solid, it will skip instead stopping contents = trap_CM_PointContents( trace.endpos, 0 ); - if ( contents & (CONTENTS_WATER | CONTENTS_SOLID) ) { - return; - } - if ( !( contents & CONTENTS_WATER ) ) { p->time = timenonscaled; VectorCopy (trace.endpos, p->org); @@ -947,6 +944,11 @@ void CG_BubblesWaterHandling( cparticle_t *p, vec3_t org ) { // trace again if the bubble went outside, then set it near to the surface contents = trap_CM_PointContents( p->org, 0 ); + if ( contents & CONTENTS_SOLID ) { // remove when grazing something solid + p->next = NULL; + p->type = p->color = p->alpha = 0; + return; + } if ( !( contents & CONTENTS_WATER ) ) { VectorCopy (trace.endpos, p->org); } @@ -954,8 +956,8 @@ void CG_BubblesWaterHandling( cparticle_t *p, vec3_t org ) { if ( p->vel[0] != 0 ) p->vel[0] *= 0.9; if ( p->vel[1] != 0 ) p->vel[1] *= 0.9; } else { - if ( p->vel[0] != 0 ) p->vel[0] *= 0.99; - if ( p->vel[1] != 0 ) p->vel[1] *= 0.99; + if ( p->vel[0] != 0 ) p->vel[0] *= 0.97; + if ( p->vel[1] != 0 ) p->vel[1] *= 0.97; } } } From 696cc6f4f8c3124e8c3125c7a5220fad87b3fae9 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Fri, 16 Aug 2024 10:48:30 +0200 Subject: [PATCH 080/374] cgame: Apply a cvar to enable/disable particles --- source/cgame/cg_cvar.h | 1 + source/cgame/cg_view.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/source/cgame/cg_cvar.h b/source/cgame/cg_cvar.h index 59c880a..4dcbba7 100644 --- a/source/cgame/cg_cvar.h +++ b/source/cgame/cg_cvar.h @@ -40,6 +40,7 @@ CG_CVAR( cg_crosshairY, "cg_crosshairY", "0", CVAR_ARCHIVE ) CG_CVAR( cg_brassTime, "cg_brassTime", "2500", CVAR_ARCHIVE ) CG_CVAR( cg_simpleItems, "cg_simpleItems", "0", CVAR_ARCHIVE ) CG_CVAR( cg_addMarks, "cg_marks", "1", CVAR_ARCHIVE ) +CG_CVAR( cg_particles, "cg_particles", "1", CVAR_ARCHIVE ) // BFP - Particles CG_CVAR( cg_lagometer, "cg_lagometer", "1", CVAR_ARCHIVE ) CG_CVAR( cg_railTrailTime, "cg_railTrailTime", "400", CVAR_ARCHIVE ) CG_CVAR( cg_gun_frame, "cg_gun_frame", "", CVAR_ROM ) diff --git a/source/cgame/cg_view.c b/source/cgame/cg_view.c index 7aa4933..497c77e 100644 --- a/source/cgame/cg_view.c +++ b/source/cgame/cg_view.c @@ -952,7 +952,10 @@ void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demo if ( !cg.hyperspace ) { CG_AddPacketEntities(); // adter calcViewValues, so predicted player state is correct CG_AddMarks(); - CG_AddParticles (); + // BFP - Enable/disable particles + if ( cg_particles.integer > 0 ) { + CG_AddParticles (); + } CG_AddLocalEntities(); } CG_AddViewWeapon( &cg.predictedPlayerState ); From 145706235c3c083dd26ed26adc7bd07fc199668d Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Fri, 16 Aug 2024 12:24:12 +0200 Subject: [PATCH 081/374] cgame: Change cent->currentState.number into cent->currentState.clientNum to apply only on client numbers and fix ki trails when the player left its corpse and has been respawned --- source/cgame/cg_players.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index 60bf76c..e85709b 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -1786,22 +1786,22 @@ CG_KiAttackSounds static void CG_KiAttackSounds( centity_t *cent ) { // BFP - Ki attack sounds switch ( cg.predictedPlayerState.weaponstate ) { case WEAPON_KIEXPLOSIONWAVE: - trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, + trap_S_AddLoopingSound( cent->currentState.clientNum, cent->lerpOrigin, vec3_origin, cgs.media.defaultKiBeamExplosionWaveSound ); break; case WEAPON_BEAMFIRING: - trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, + trap_S_AddLoopingSound( cent->currentState.clientNum, cent->lerpOrigin, vec3_origin, cgs.media.defaultKiBeamExplosionWaveSound ); break; case WEAPON_FIRING: // ki attacks like eyebeam shouldn't use that kind of firing sound if ( cg.predictedPlayerState.weapon != WP_LIGHTNING ) { - trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, + trap_S_AddLoopingSound( cent->currentState.clientNum, cent->lerpOrigin, vec3_origin, cgs.media.defaultKiFiringAttackSound ); } break; case WEAPON_CHARGING: - trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, + trap_S_AddLoopingSound( cent->currentState.clientNum, cent->lerpOrigin, vec3_origin, cgs.media.defaultKiChargingSound ); } } @@ -1852,7 +1852,7 @@ static void CG_PlayerSprites( centity_t *cent ) { // BFP - A macro to check if there's some eflag enabled, also don't show the float sprite to the player itself #define FLOATSPRITE_CHECK(eflag, flspriteshader) \ - if ( ( cent->currentState.eFlags & eflag ) && cent->currentState.number != cg.snap->ps.clientNum ) { \ + if ( ( cent->currentState.eFlags & eflag ) && cent->currentState.clientNum != cg.snap->ps.clientNum ) { \ CG_PlayerFloatSprite( cent, flspriteshader ); \ return; \ } @@ -1868,7 +1868,7 @@ static void CG_PlayerSprites( centity_t *cent ) { team = cgs.clientinfo[ cent->currentState.clientNum ].team; if ( !(cent->currentState.eFlags & EF_DEAD) && - cent->currentState.number != cg.snap->ps.clientNum && // BFP - Don't show the friend team shader to the player itself + cent->currentState.clientNum != cg.snap->ps.clientNum && // BFP - Don't show the friend team shader to the player itself cg.snap->ps.persistant[PERS_TEAM] == team && cgs.gametype >= GT_TEAM) { // BFP - BFP doesn't use cg_drawFriend to draw that floating friend sprite, keeps enabled always. @@ -2351,9 +2351,14 @@ void CG_Player( centity_t *cent ) { CG_AddRefEntityWithPowerups( &head, ¢->currentState, ci->team ); + // BFP - If the entity is a corpse, avoid drawing ki trails to the dead + if ( cent->currentState.eFlags & EF_DEAD ) { + return; + } + // BFP - Origin setup for ki trails #define KI_TRAIL_ZPOS 5 - VectorCopy( cent->currentState.pos.trBase, kiTrailOrigin ); + VectorCopy( cent->lerpOrigin, kiTrailOrigin ); kiTrailOrigin[2] += KI_TRAIL_ZPOS; #undef KI_TRAIL_ZPOS @@ -2508,10 +2513,10 @@ void CG_Player( centity_t *cent ) { // Ki boost and ki charge sounds if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE ) { - trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, + trap_S_AddLoopingSound( cent->currentState.clientNum, cent->lerpOrigin, vec3_origin, cgs.media.kiChargeSound ); } else { - trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, + trap_S_AddLoopingSound( cent->currentState.clientNum, cent->lerpOrigin, vec3_origin, cgs.media.kiUseSound ); } From ec2085f85130bb40e45b604bcf4582e5bcc7b3e2 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Fri, 16 Aug 2024 14:26:11 +0200 Subject: [PATCH 082/374] cgame - game: Implement instant character model changing, remove force model and defer player model logics, and apply compilation safety in player_die function when attacker parameter is NULL --- README.md | 1 + source/cgame/cg_cvar.h | 4 +-- source/cgame/cg_main.c | 12 ++++++-- source/cgame/cg_players.c | 62 ++++++++++++++++++++++---------------- source/game/g_client.c | 63 ++++++++++++++++++++------------------- source/game/g_combat.c | 18 +++++++---- source/game/g_local.h | 4 +++ 7 files changed, 98 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index 51fe9e5..3b78d16 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ A legendary 90s era Quake 3 Arena mod. - [x] ~~Third person traceable crosshair~~ - [x] ~~Breakable map entities ("func_breakable")~~ - [x] ~~Ki trails (use ki to move, cg_kiTrail >10 )~~ +- [x] ~~Instant character model changing~~ - [ ] Make ki energy regeneration, ki use, attacks, charging balance indicated on old docs - [ ] Powerlevel and Power Tiers indicated on old docs - [x] ~~Hit Stun (makes player can't use ki, melee, block and charge)~~ diff --git a/source/cgame/cg_cvar.h b/source/cgame/cg_cvar.h index 4dcbba7..0906082 100644 --- a/source/cgame/cg_cvar.h +++ b/source/cgame/cg_cvar.h @@ -86,9 +86,9 @@ CG_CVAR( cg_superdeformed, "cg_superdeformed", "0", CVAR_ARCHIVE ) // BFP - Supe CG_CVAR( cg_yrgolroxor, "cg_yrgolroxor", "0", 0 ) // BFP - Yrgol Roxor easter egg CG_CVAR( cg_teamChatTime, "cg_teamChatTime", "3000", CVAR_ARCHIVE ) CG_CVAR( cg_teamChatHeight, "cg_teamChatHeight", "0", CVAR_ARCHIVE ) -CG_CVAR( cg_forceModel, "cg_forceModel", "0", CVAR_ARCHIVE ) +CG_CVAR( cg_forceModel, "cg_forceModel", "0", CVAR_ARCHIVE ) // BFP - TODO: In the future, remove cg_forceModel, which wasn't removed originally? CG_CVAR( cg_predictItems, "cg_predictItems", "1", CVAR_ARCHIVE ) -CG_CVAR( cg_deferPlayers, "cg_deferPlayers", "1", CVAR_ARCHIVE ) +CG_CVAR( cg_deferPlayers, "cg_deferPlayers", "1", CVAR_ARCHIVE ) // BFP - TODO: In the future, remove cg_deferPlayers, which wasn't removed originally? CG_CVAR( cg_drawTeamOverlay, "cg_drawTeamOverlay", "0", CVAR_ARCHIVE ) CG_CVAR( cg_teamOverlayUserinfo, "teamoverlay", "0", CVAR_ROM | CVAR_USERINFO ) CG_CVAR( cg_stats, "cg_stats", "0", 0 ) diff --git a/source/cgame/cg_main.c b/source/cgame/cg_main.c index 6986891..387c171 100644 --- a/source/cgame/cg_main.c +++ b/source/cgame/cg_main.c @@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // cg_main.c -- initialization and primary entry point for cgame #include "cg_local.h" -int forceModelModificationCount = -1; +// int forceModelModificationCount = -1; void CG_Init( int serverMessageNum, int serverCommandSequence, int clientNum ); void CG_Shutdown( void ); @@ -119,7 +119,7 @@ void CG_RegisterCvars( void ) { trap_Cvar_VariableStringBuffer( "sv_running", var, sizeof( var ) ); cgs.localServer = atoi( var ); - forceModelModificationCount = cg_forceModel.modificationCount; + // forceModelModificationCount = cg_forceModel.modificationCount; trap_Cvar_Register(NULL, "model", DEFAULT_MODEL, CVAR_USERINFO | CVAR_ARCHIVE ); trap_Cvar_Register(NULL, "headmodel", DEFAULT_MODEL, CVAR_USERINFO | CVAR_ARCHIVE ); @@ -127,7 +127,9 @@ void CG_RegisterCvars( void ) { //trap_Cvar_Register(NULL, "team_headmodel", DEFAULT_TEAM_HEAD, CVAR_USERINFO | CVAR_ARCHIVE ); } -/* +// BFP - No force model (In the future, remove cg_forceModel, which wasn't removed originally?) +#if 0 +/* =================== CG_ForceModelChange =================== @@ -145,6 +147,7 @@ static void CG_ForceModelChange( void ) { CG_NewClientInfo( i ); } } +#endif /* ================= @@ -175,11 +178,14 @@ void CG_UpdateCvars( void ) { trap_Cvar_Set( "teamoverlay", "1" ); } + // BFP - No force model (In the future, remove cg_forceModel, which wasn't removed originally?) +#if 0 // if force model changed if ( forceModelModificationCount != cg_forceModel.modificationCount ) { forceModelModificationCount = cg_forceModel.modificationCount; CG_ForceModelChange(); } +#endif } int CG_CrosshairPlayer( void ) { diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index e85709b..8bbae71 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -737,6 +737,8 @@ static void CG_LoadClientInfo( clientInfo_t *ci ) { } } +// BFP - Unused static functions, remove? I think so +#if 0 /* ====================== CG_CopyClientInfoModel @@ -870,6 +872,7 @@ static void CG_SetDeferredClientInfo( clientInfo_t *ci ) { CG_LoadClientInfo( ci ); } +#endif /* @@ -943,6 +946,8 @@ void CG_NewClientInfo( int clientNum ) { // model v = Info_ValueForKey( configstring, "model" ); + // BFP - No force model (In the future, remove cg_forceModel, which wasn't removed originally?) +#if 0 if ( cg_forceModel.integer ) { // forcemodel makes everyone use a single model // to prevent load hitches @@ -971,22 +976,24 @@ void CG_NewClientInfo( int clientNum ) { Q_strncpyz( newInfo.skinName, slash + 1, sizeof( newInfo.skinName ) ); } } - } else { - Q_strncpyz( newInfo.modelName, v, sizeof( newInfo.modelName ) ); + } else +#endif + Q_strncpyz( newInfo.modelName, v, sizeof( newInfo.modelName ) ); - slash = strchr( newInfo.modelName, '/' ); - if ( !slash ) { - // modelName didn not include a skin name - Q_strncpyz( newInfo.skinName, "default", sizeof( newInfo.skinName ) ); - } else { - Q_strncpyz( newInfo.skinName, slash + 1, sizeof( newInfo.skinName ) ); - // truncate modelName - *slash = 0; - } + slash = strchr( newInfo.modelName, '/' ); + if ( !slash ) { + // modelName didn not include a skin name + Q_strncpyz( newInfo.skinName, "default", sizeof( newInfo.skinName ) ); + } else { + Q_strncpyz( newInfo.skinName, slash + 1, sizeof( newInfo.skinName ) ); + // truncate modelName + *slash = 0; } // head model v = Info_ValueForKey( configstring, "hmodel" ); + // BFP - No force model (In the future, remove cg_forceModel, which wasn't removed originally?) +#if 0 if ( cg_forceModel.integer ) { // forcemodel makes everyone use a single model // to prevent load hitches @@ -1015,23 +1022,27 @@ void CG_NewClientInfo( int clientNum ) { Q_strncpyz( newInfo.headSkinName, slash + 1, sizeof( newInfo.headSkinName ) ); } } - } else { - Q_strncpyz( newInfo.headModelName, v, sizeof( newInfo.headModelName ) ); + } else +#endif + Q_strncpyz( newInfo.headModelName, v, sizeof( newInfo.headModelName ) ); - slash = strchr( newInfo.headModelName, '/' ); - if ( !slash ) { - // modelName didn not include a skin name - Q_strncpyz( newInfo.headSkinName, "default", sizeof( newInfo.headSkinName ) ); - } else { - Q_strncpyz( newInfo.headSkinName, slash + 1, sizeof( newInfo.headSkinName ) ); - // truncate modelName - *slash = 0; - } + slash = strchr( newInfo.headModelName, '/' ); + if ( !slash ) { + // modelName didn not include a skin name + Q_strncpyz( newInfo.headSkinName, "default", sizeof( newInfo.headSkinName ) ); + } else { + Q_strncpyz( newInfo.headSkinName, slash + 1, sizeof( newInfo.headSkinName ) ); + // truncate modelName + *slash = 0; } + // BFP - Change the model without impeding with defer + // BFP - TODO: Remove cg_deferPlayers cvar and its unnecessary code in the future +#if 0 // scan for an existing clientinfo that matches this modelname // so we can avoid loading checks if possible - if ( !CG_ScanForExistingClientInfo( &newInfo ) ) { + // if ( !CG_ScanForExistingClientInfo( &newInfo ) ) + // { qboolean forceDefer; forceDefer = trap_MemoryRemaining() < 4000000; @@ -1046,9 +1057,10 @@ void CG_NewClientInfo( int clientNum ) { newInfo.deferred = qfalse; } } else { +#endif CG_LoadClientInfo( &newInfo ); - } - } + // } + // } // replace whatever was there with the new one newInfo.infoValid = qtrue; diff --git a/source/game/g_client.c b/source/game/g_client.c index 0906efa..890e878 100644 --- a/source/game/g_client.c +++ b/source/game/g_client.c @@ -704,6 +704,10 @@ void ClientUserinfoChanged( int clientNum ) { char blueTeam[MAX_INFO_STRING]; char userinfo[MAX_INFO_STRING]; + // BFP - Model prefix load + char newModelPrefix[MAX_QPATH]; + char *oldModelDash, *newModelDash; + ent = g_entities + clientNum; client = ent->client; @@ -779,27 +783,6 @@ void ClientUserinfoChanged( int clientNum ) { team = client->sess.sessionTeam; } -/* NOTE: all client side now - - // team - switch( team ) { - case TEAM_RED: - ForceClientSkin(client, model, "red"); -// ForceClientSkin(client, headModel, "red"); - break; - case TEAM_BLUE: - ForceClientSkin(client, model, "blue"); -// ForceClientSkin(client, headModel, "blue"); - break; - } - // don't ever use a default skin in teamplay, it would just waste memory - // however bots will always join a team but they spawn in as spectator - if ( g_gametype.integer >= GT_TEAM && team == TEAM_SPECTATOR) { - ForceClientSkin(client, model, "red"); -// ForceClientSkin(client, headModel, "red"); - } -*/ - // teamInfo s = Info_ValueForKey( userinfo, "teamoverlay" ); if ( ! *s || atoi( s ) != 0 ) { @@ -807,15 +790,6 @@ void ClientUserinfoChanged( int clientNum ) { } else { client->pers.teamInfo = qfalse; } - /* - s = Info_ValueForKey( userinfo, "cg_pmove_fixed" ); - if ( !*s || atoi( s ) == 0 ) { - client->pers.pmoveFixed = qfalse; - } - else { - client->pers.pmoveFixed = qtrue; - } - */ // team task (0 = none, 1 = offence, 2 = defence) teamTask = atoi(Info_ValueForKey(userinfo, "teamtask")); @@ -844,6 +818,35 @@ void ClientUserinfoChanged( int clientNum ) { trap_SetConfigstring( CS_PLAYERS+clientNum, s ); + // BFP - Model prefix handling + { + // extract model prefixes safely + oldModelDash = strchr(ent->oldModel, '-'); + if ( oldModelDash ) { + Q_strncpyz( ent->oldModelPrefix, ent->oldModel, oldModelDash - ent->oldModel + 1 ); + } else { + Q_strncpyz( ent->oldModelPrefix, ent->oldModel, sizeof( ent->oldModelPrefix ) ); + } + + newModelDash = strchr(model, '-'); + if ( newModelDash ) { + Q_strncpyz( newModelPrefix, model, newModelDash - model + 1 ); + } else { + Q_strncpyz( newModelPrefix, model, sizeof( newModelPrefix ) ); + } + + // compare model prefixes + if ( Q_stricmp( ent->oldModelPrefix, newModelPrefix ) ) { + // prefixes differ, kill the player + ent->flags &= ~FL_GODMODE; + ent->client->ps.stats[STAT_HEALTH] = ent->health = 0; + player_die( ent, ent, NULL, 100000, MOD_UNKNOWN ); + } + + // save the new model as the old model for the next time this function runs + Q_strncpyz( ent->oldModel, model, sizeof( ent->oldModel ) ); + } + // this is not the userinfo, more like the configstring actually G_LogPrintf( "ClientUserinfoChanged: %i %s\n", clientNum, s ); } diff --git a/source/game/g_combat.c b/source/game/g_combat.c index 4e54411..5f85001 100644 --- a/source/game/g_combat.c +++ b/source/game/g_combat.c @@ -334,10 +334,13 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int return; } - // check for an almost capture - CheckAlmostCapture( self, attacker ); - // check for a player that almost brought in cubes - CheckAlmostScored( self, attacker ); + // BFP - For compilation safety from shared objects (.so) and dll + if ( attacker != NULL ) { + // check for an almost capture + CheckAlmostCapture( self, attacker ); + // check for a player that almost brought in cubes + CheckAlmostScored( self, attacker ); + } // BFP - no hook #if 0 @@ -425,8 +428,11 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int AddScore( self, self->r.currentOrigin, -1 ); } - // Add team bonuses - Team_FragBonuses(self, inflictor, attacker); + // BFP - For compilation safety from shared objects (.so) and dll + if ( attacker != NULL ) { + // Add team bonuses + Team_FragBonuses(self, inflictor, attacker); + } // if I committed suicide, the flag does not fall, it returns. if (meansOfDeath == MOD_SUICIDE) { diff --git a/source/game/g_local.h b/source/game/g_local.h index 7577ebd..81d804d 100644 --- a/source/game/g_local.h +++ b/source/game/g_local.h @@ -92,6 +92,10 @@ struct gentity_s { char *model; char *model2; int freetime; // level.time when the object was freed + + // BFP - Model prefix handling + char oldModel[MAX_QPATH]; + char oldModelPrefix[MAX_QPATH]; int eventTime; // events will be cleared EVENT_VALID_MSEC after set qboolean freeAfterEvent; From 4511a381f38866085417f4df74b836c27b5e3887 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sat, 17 Aug 2024 23:12:06 +0200 Subject: [PATCH 083/374] game: Don't display shot effects on the stunned status --- source/game/bg_pmove.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index 81f7da4..611a6e3 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -2444,6 +2444,8 @@ static void PM_HitStun( void ) { // BFP - Hit stun pm->ps->powerups[PW_FLIGHT] = 0; pm->ps->powerups[PW_HASTE] = 0; pm->ps->pm_flags &= ~PMF_KI_ATTACK; + // don't display shot effects on the stunned status + pm->ps->eFlags &= ~EF_FIRING; pm->ps->eFlags &= ~EF_AURA; pm->ps->weaponstate = WEAPON_READY; From 66c7fada39487f971fc3476bb584628a33147004 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Tue, 20 Aug 2024 12:40:36 +0200 Subject: [PATCH 084/374] cgame: Fix antigrav rocks falling in a non-interactable entity place (blocked by a brush or skybox) --- source/cgame/cg_particles.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/cgame/cg_particles.c b/source/cgame/cg_particles.c index 37ebee3..ae4332f 100644 --- a/source/cgame/cg_particles.c +++ b/source/cgame/cg_particles.c @@ -412,8 +412,8 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) { // BFP - To detect if there is something solid trace_t trace; - // contents should be MASK_DEADSOLID, so the particles don't touch any entity like the player - CG_Trace( &trace, p->org, vec3_origin, vec3_origin, org, -1, MASK_DEADSOLID ); + // contents should be CONTENTS_SOLID, so the particles don't touch any entity like the player + CG_Trace( &trace, p->org, vec3_origin, vec3_origin, org, -1, CONTENTS_SOLID ); p->time = timenonscaled; p->snum = 1; // handle the p->snum when already entered in this phase for correction of client side visuals From efd8047daf9cf5b18aee2baf507faa21079016f4 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Tue, 20 Aug 2024 18:31:25 +0200 Subject: [PATCH 085/374] cgame: Cleanup on cg_weapons.c and fix ki use and charge sound aren't playing when using RailGun, Lightning Gun and BFG --- source/cgame/cg_weapons.c | 167 ++------------------------------------ 1 file changed, 5 insertions(+), 162 deletions(-) diff --git a/source/cgame/cg_weapons.c b/source/cgame/cg_weapons.c index 07b74b8..fb2da8b 100644 --- a/source/cgame/cg_weapons.c +++ b/source/cgame/cg_weapons.c @@ -1011,67 +1011,6 @@ static void CG_SpawnRailTrail( centity_t *cent, vec3_t origin ) { } -// BFP - TODO: Remove these functions, these won't be used nonetheless -#if 0 -/* -====================== -CG_MachinegunSpinAngle -====================== -*/ -#define SPIN_SPEED 0.9 -#define COAST_TIME 1000 -static float CG_MachinegunSpinAngle( centity_t *cent ) { - int delta; - float angle; - float speed; - - delta = cg.time - cent->pe.barrelTime; - if ( cent->pe.barrelSpinning ) { - angle = cent->pe.barrelAngle + delta * SPIN_SPEED; - } else { - if ( delta > COAST_TIME ) { - delta = COAST_TIME; - } - - speed = 0.5 * ( SPIN_SPEED + (float)( COAST_TIME - delta ) / COAST_TIME ); - angle = cent->pe.barrelAngle + delta * speed; - } - - if ( cent->pe.barrelSpinning == !(cent->currentState.eFlags & EF_FIRING) ) { - cent->pe.barrelTime = cg.time; - cent->pe.barrelAngle = AngleMod( angle ); - cent->pe.barrelSpinning = !!(cent->currentState.eFlags & EF_FIRING); - } - - return angle; -} - -/* -======================== -CG_AddWeaponWithPowerups -======================== -*/ -static void CG_AddWeaponWithPowerups( refEntity_t *gun, int powerups ) { - // add powerup effects - if ( powerups & ( 1 << PW_INVIS ) ) { - gun->customShader = cgs.media.invisShader; - trap_R_AddRefEntityToScene( gun ); - } else { - trap_R_AddRefEntityToScene( gun ); - - if ( powerups & ( 1 << PW_BATTLESUIT ) ) { - gun->customShader = cgs.media.battleWeaponShader; - trap_R_AddRefEntityToScene( gun ); - } - if ( powerups & ( 1 << PW_QUAD ) ) { - gun->customShader = cgs.media.quadWeaponShader; - trap_R_AddRefEntityToScene( gun ); - } - } -} -#endif - - /* ============= CG_AddPlayerWeapon @@ -1081,15 +1020,7 @@ The main player will have this called for BOTH cases, so effects like light and sound should only be done on the world model case. ============= */ -// BFP - TODO: That needs some cleanup and managing correctly the weapons. -// Next time, unused code will be removed for clear and concise logic purposes. -// The same goes to CG_AddWeaponWithPowerups and CG_MachinegunSpinAngle void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent, int team ) { -#if 0 - refEntity_t gun, barrel; - vec3_t angles; -#endif - refEntity_t flash; weapon_t weaponNum; weaponInfo_t *weapon; centity_t *nonPredictedCent; @@ -1099,38 +1030,6 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent CG_RegisterWeapon( weaponNum ); weapon = &cg_weapons[weaponNum]; - // BFP - Hide gun model -#if 0 - // add the weapon - memset( &gun, 0, sizeof( gun ) ); - - VectorCopy( parent->lightingOrigin, gun.lightingOrigin ); - gun.shadowPlane = parent->shadowPlane; - gun.renderfx = parent->renderfx; - - // set custom shading for railgun refire rate - if ( ps ) { - if ( cg.predictedPlayerState.weapon == WP_RAILGUN - && cg.predictedPlayerState.weaponstate == WEAPON_FIRING ) { - float f; - - f = (float)cg.predictedPlayerState.weaponTime / 1500; - gun.shaderRGBA[1] = 0; - gun.shaderRGBA[0] = - gun.shaderRGBA[2] = 255 * ( 1.0 - f ); - } else { - gun.shaderRGBA[0] = 255; - gun.shaderRGBA[1] = 255; - gun.shaderRGBA[2] = 255; - gun.shaderRGBA[3] = 255; - } - } - gun.hModel = weapon->weaponModel; - if (!gun.hModel) { - return; - } -#endif - if ( !ps ) { // add weapon ready sound cent->pe.lightningFiring = qfalse; @@ -1138,37 +1037,9 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent // lightning gun and guantlet make a different sound when fire is held down trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, weapon->firingSound ); cent->pe.lightningFiring = qtrue; - } else if ( weapon->readySound ) { - trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, weapon->readySound ); } } - // BFP - Hide barrel model and unused position entity tag property -#if 0 - // CG_PositionEntityOnTag( &gun, parent, parent->hModel, "tag_weapon"); - - // BFP - TODO: Remove that function, it won't be used nonetheless - CG_AddWeaponWithPowerups( &gun, cent->currentState.powerups ); - - // add the spinning barrel - if ( weapon->barrelModel ) { - memset( &barrel, 0, sizeof( barrel ) ); - VectorCopy( parent->lightingOrigin, barrel.lightingOrigin ); - barrel.shadowPlane = parent->shadowPlane; - barrel.renderfx = parent->renderfx; - - barrel.hModel = weapon->barrelModel; - angles[YAW] = 0; - angles[PITCH] = 0; - angles[ROLL] = CG_MachinegunSpinAngle( cent ); - AnglesToAxis( angles, barrel.axis ); - - CG_PositionRotatedEntityOnTag( &barrel, &gun, weapon->weaponModel, "tag_barrel" ); - - CG_AddWeaponWithPowerups( &barrel, cent->currentState.powerups ); - } -#endif - // make sure we aren't looking at cg.predictedPlayerEntity for LG nonPredictedCent = &cg_entities[cent->currentState.clientNum]; @@ -1191,47 +1062,19 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent } } - // memset( &flash, 0, sizeof( flash ) ); - VectorCopy( parent->lightingOrigin, flash.lightingOrigin ); - // BFP - Hide flash model -#if 0 - flash.shadowPlane = parent->shadowPlane; - flash.renderfx = parent->renderfx; - - flash.hModel = weapon->flashModel; - if (!flash.hModel) { - return; - } - angles[YAW] = 0; - angles[PITCH] = 0; - angles[ROLL] = crandom() * 10; - AnglesToAxis( angles, flash.axis ); - - // colorize the railgun blast - if ( weaponNum == WP_RAILGUN ) { - clientInfo_t *ci; - - ci = &cgs.clientinfo[ cent->currentState.clientNum ]; - flash.shaderRGBA[0] = 255 * ci->color1[0]; - flash.shaderRGBA[1] = 255 * ci->color1[1]; - flash.shaderRGBA[2] = 255 * ci->color1[2]; - } -#endif - // BFP - NOTE: Here's where the player gets the muzzle attached from some of the tags (apply that to client cfg side) (tag_left, tag_right...) - CG_PositionRotatedEntityOnTag( &flash, parent, parent->hModel, "tag_right"); - // trap_R_AddRefEntityToScene( &flash ); + CG_PositionRotatedEntityOnTag( parent, parent, parent->hModel, "tag_right" ); if ( ps || cg.renderingThirdPerson || cent->currentState.number != cg.predictedPlayerState.clientNum ) { // add lightning bolt - CG_LightningBolt( nonPredictedCent, flash.origin ); + CG_LightningBolt( nonPredictedCent, parent->origin ); // add rail trail - CG_SpawnRailTrail( cent, flash.origin ); + CG_SpawnRailTrail( cent, parent->origin ); if ( weapon->flashDlightColor[0] || weapon->flashDlightColor[1] || weapon->flashDlightColor[2] ) { - trap_R_AddLightToScene( flash.origin, 300 + (rand()&31), weapon->flashDlightColor[0], + trap_R_AddLightToScene( parent->origin, 300 + (rand()&31), weapon->flashDlightColor[0], weapon->flashDlightColor[1], weapon->flashDlightColor[2] ); } } @@ -2084,4 +1927,4 @@ void CG_Bullet( vec3_t end, int sourceEntityNum, vec3_t normal, qboolean flesh, CG_MissileHitWall( WP_MACHINEGUN, 0, end, normal, IMPACTSOUND_DEFAULT ); } -} +} \ No newline at end of file From 03fbd456f7700849961bd79f060bf950ce14dc7b Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sun, 1 Sep 2024 23:40:22 +0200 Subject: [PATCH 086/374] cgame: Implement sprite aura, encapsulate aura setup in a function, move some handling macros and tweak CG_AddRefEntityWithPowerups first parameter. Shader aura implementation isn't completed yet --- source/cgame/cg_cvar.h | 1 + source/cgame/cg_ents.c | 2 +- source/cgame/cg_local.h | 2 +- source/cgame/cg_players.c | 543 +++++++++++++++++++++----------------- 4 files changed, 298 insertions(+), 250 deletions(-) diff --git a/source/cgame/cg_cvar.h b/source/cgame/cg_cvar.h index 0906082..f7aa5ea 100644 --- a/source/cgame/cg_cvar.h +++ b/source/cgame/cg_cvar.h @@ -76,6 +76,7 @@ CG_CVAR( cg_fixedThirdPerson, "cg_fixedThirdPerson", "1", CVAR_ARCHIVE ) // BFP CG_CVAR( cg_drawOwnModel, "cg_drawOwnModel", "1", CVAR_ARCHIVE ) // BFP - toggle first person between traditional and vis modes CG_CVAR( cg_drawKiWarning, "cg_drawKiWarning", "1", CVAR_ARCHIVE ) // BFP - Ki warning CG_CVAR( cg_stableCrosshair, "cg_stableCrosshair", "0", CVAR_ARCHIVE ) // BFP - Accurate crosshair +CG_CVAR( cg_spriteAura, "cg_spriteAura", "0", CVAR_ARCHIVE ) // BFP - Sprite aura CG_CVAR( cg_lightAuras, "cg_lightAuras", "1", CVAR_ARCHIVE ) // BFP - Light auras CG_CVAR( cg_smallOwnAura, "cg_smallOwnAura", "0", CVAR_ARCHIVE ) // BFP - Small own aura CG_CVAR( cg_lightweightAuras, "cg_lightweightAuras", "0", CVAR_ARCHIVE ) // BFP - Lightweight auras diff --git a/source/cgame/cg_ents.c b/source/cgame/cg_ents.c index 98f3190..7c68e3e 100644 --- a/source/cgame/cg_ents.c +++ b/source/cgame/cg_ents.c @@ -455,7 +455,7 @@ static void CG_Missile( centity_t *cent ) { } // add to refresh list, possibly with quad glow - CG_AddRefEntityWithPowerups( &ent, s1, TEAM_FREE ); + CG_AddRefEntityWithPowerups( ent, s1, TEAM_FREE ); } /* diff --git a/source/cgame/cg_local.h b/source/cgame/cg_local.h index bbf7eb3..d68e182 100644 --- a/source/cgame/cg_local.h +++ b/source/cgame/cg_local.h @@ -1153,7 +1153,7 @@ qhandle_t CG_StatusHandle(int task); // void CG_Player( centity_t *cent ); void CG_ResetPlayerEntity( centity_t *cent ); -void CG_AddRefEntityWithPowerups( refEntity_t *ent, entityState_t *state, int team ); +void CG_AddRefEntityWithPowerups( refEntity_t re, entityState_t *state, int team ); void CG_NewClientInfo( int clientNum ); sfxHandle_t CG_CustomSound( int clientNum, const char *soundName ); qboolean CG_GetTagOrientationFromPlayerEntityParentModel( centity_t *cent, refEntity_t *parent, diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index 8bbae71..a1d03d3 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -2081,6 +2081,16 @@ static void CG_PlayerSplash( centity_t *cent ) { +// BFP - Macro for the size of a model +#define MODEL_SIZE(model, model_size) { \ + int m_i, m_j; \ + for ( m_i = 0; m_i < 3; m_i++ ) { \ + for ( m_j = 0; m_j < 3; m_j++ ) { \ + (model).axis[m_i][m_j] *= (model_size); \ + } \ + } \ +} + /* =============== CG_AddRefEntityWithPowerups @@ -2089,60 +2099,298 @@ Adds a piece with modifications or duplications for powerups Also called by CG_Missile for quad rockets, but nobody can tell... =============== */ -void CG_AddRefEntityWithPowerups( refEntity_t *ent, entityState_t *state, int team ) { - +void CG_AddRefEntityWithPowerups( refEntity_t ent, entityState_t *state, int team ) { if ( state->powerups & ( 1 << PW_INVIS ) ) { - ent->customShader = cgs.media.invisShader; - trap_R_AddRefEntityToScene( ent ); - } else { - /* - if ( state->eFlags & EF_KAMIKAZE ) { - if (team == TEAM_BLUE) - ent->customShader = cgs.media.blueKamikazeShader; - else - ent->customShader = cgs.media.redKamikazeShader; - trap_R_AddRefEntityToScene( ent ); - } - else {*/ - trap_R_AddRefEntityToScene( ent ); - //} + ent.customShader = cgs.media.invisShader; + trap_R_AddRefEntityToScene( &ent ); + return; + } + + // render main model + trap_R_AddRefEntityToScene( &ent ); + + // BFP - TODO: If player is transformed: + // render perma-glow when already transformed + /* ent.customShader = cgs.media.auraYellowShader; + if ( ( state->powerups & ( 1 << PW_TRANSFORMED ) ) + && cg_permaglowUltimate.integer > 0 ) { + trap_R_AddRefEntityToScene( &ent ); + }*/ + + ent.customShader = cgs.media.auraRedShader; + if ( team == TEAM_BLUE ) { + ent.customShader = cgs.media.auraBlueShader; + } + + // BFP - TODO: If player is transformed: + // only on non-team gamemodes render when already transformed + /*if ( ( state->powerups & ( 1 << PW_TRANSFORMED ) ) + && cgs.gametype < GT_TEAM ) { + ent.customShader = cgs.media.auraYellowShader; + }*/ + if ( state->eFlags & EF_AURA ) { // BFP - If the player is using lightweight auras or their own small aura - if ( ( state->eFlags & EF_AURA ) - && ( cg_lightweightAuras.integer > 0 - || ( state->clientNum == cg.snap->ps.clientNum - && cg_smallOwnAura.integer > 0 ) ) ) { - // BFP - TODO: If player is transformed: - // ent->customShader = cgs.media.auraYellowShader; - - if ( team == TEAM_BLUE) { - ent->customShader = cgs.media.auraBlueShader; - } else { - ent->customShader = cgs.media.auraRedShader; + if ( ( cg_lightweightAuras.integer > 0 + || ( state->clientNum == cg.snap->ps.clientNum + && cg_smallOwnAura.integer > 0 ) ) + && cg_spriteAura.integer <= 0 ) { + trap_R_AddRefEntityToScene( &ent ); + } + + // BFP - TODO: Shader aura + if ( cg_lightweightAuras.integer <= 0 + && cg_polygonAura.integer <= 0 + && cg_highPolyAura.integer <= 0 + && cg_spriteAura.integer <= 0 + && ( state->clientNum == cg.snap->ps.clientNum + && cg_smallOwnAura.integer <= 0 ) ) { + MODEL_SIZE ( ent, 1.2f ) + trap_R_AddRefEntityToScene( &ent ); + } + } +} + + +/* +============ +CG_Aura + +Adds aura and ki trails +============ +*/ +static void CG_Aura( centity_t *cent, int clientNum, clientInfo_t *ci, int renderfx, refEntity_t legs, qhandle_t kiTrailShader ) { // BFP - Aura and ki trails + refEntity_t aura; + refEntity_t aura2; // secondary aura + vec3_t auraInverseRotation; // for aura inverse rotation + vec3_t kiTrailOrigin; + + memset( &aura, 0, sizeof(aura) ); + memset( &aura2, 0, sizeof(aura2) ); + + // origin setup for ki trails + #define KI_TRAIL_ZPOS 5 + VectorCopy( cent->lerpOrigin, kiTrailOrigin ); + kiTrailOrigin[2] += KI_TRAIL_ZPOS; + #undef KI_TRAIL_ZPOS + + // Macro to handle the aura animations, when idling it sets the aura vertical rotation, so the aura rotates vertically + #define AURA_ANIMS(aura, reversed) \ + if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_RUN \ + || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_JUMP ) { \ + aura.hModel = cgs.media.runauraModel; \ + } else if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_BACK \ + || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_JUMPB \ + || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYB ) { \ + aura.hModel = cgs.media.backauraModel; \ + } else if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYA ) { \ + aura.hModel = cgs.media.flyauraModel; \ + } else { \ + aura.hModel = cgs.media.auraModel; \ + if ( reversed ) { \ + VectorNegate( cg.autoAngles, auraInverseRotation ); \ + AnglesToAxis( auraInverseRotation, aura.axis ); \ + } else { \ + AnglesToAxis( cg.autoAngles, aura.axis ); \ + } \ + } + + // Macro for the dynamic aura light, note: when charging it changes the shinning a bit + // Aura lights like cg_smallOwnAura only can be shown to itself and not the other clients, + // the other clients only show small lights. + // BFP - NOTE: Originally, if cg_spriteAura is on, the lights aren't displayed. + // But that should be removed in the future and just keep cg_lightAuras conditional + #define AURA_LIGHT(r, g, b) \ + if ( cg_lightAuras.integer > 0 && cg_spriteAura.integer <= 0 ) { \ + if ( clientNum == cg.snap->ps.clientNum && cg_smallOwnAura.integer > 0 ) { \ + trap_R_AddLightToScene( cent->lerpOrigin, 200, r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 200, r, g, b ); \ + if ( !( cg.predictedPlayerState.pm_flags & PMF_KI_CHARGE ) ) { \ + trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), r, g, b ); \ + } else { \ + trap_R_AddLightToScene( cent->lerpOrigin, 100 + (rand()&100), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 100 + (rand()&100), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 100 + (rand()&100), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 100 + (rand()&100), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 100 + (rand()&100), r, g, b ); \ + } \ + } else if ( clientNum != cg.snap->ps.clientNum || cg_lightweightAuras.integer > 0 || cg_polygonAura.integer > 0 || cg_highPolyAura.integer > 0 ) { \ + trap_R_AddLightToScene( cent->lerpOrigin, 50 + (rand()&100), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 50 + (rand()&100), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 50 + (rand()&100), r, g, b ); \ + } else { \ + trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&63), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), r, g, b ); \ + trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), r, g, b ); \ + if ( !( cg.predictedPlayerState.pm_flags & PMF_KI_CHARGE ) ) { \ + trap_R_AddLightToScene( cent->lerpOrigin, 100 + (rand()&150), r, g, b ); \ + } \ + } \ + } + + // Macro to remove ki trails + #define REMOVING_KI_TRAILS(clientNum, kiTrailOrigin, kiTrailShader, fastRemove) \ + if ( cg.time > cent->pe.kiTrailTime ) { /* reset ki trail position avoid being zeroed */ \ + CG_ResetKiTrail( clientNum, kiTrailOrigin ); \ + } else { /* ki trails keep running in that moment, but their segments are being removed */ \ + CG_KiTrail( clientNum, kiTrailOrigin, fastRemove, kiTrailShader ); \ + } + + if ( cent->currentState.eFlags & EF_AURA ) { + // trace for bubble particles only when moving in the water and charging + int destContentType = CG_PointContents( legs.origin, -1 ); + + // BFP - Ki trail + if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_CHARGE + && cg_kiTrail.integer >= 10 ) { + // apply time for using ki trail + cent->pe.kiTrailTime = cg.time + cg_kiTrail.integer*5; + + CG_KiTrail( clientNum, kiTrailOrigin, qfalse, kiTrailShader ); + } else { // handle when the ki trail was being used previously + REMOVING_KI_TRAILS( clientNum, kiTrailOrigin, kiTrailShader, qtrue ) + } + + // spawning bubble particles + if ( destContentType & CONTENTS_WATER ) { + trace_t trace; + vec3_t start, bubbleOrigin; + + VectorCopy( legs.origin, bubbleOrigin ); + trap_CM_BoxTrace( &trace, start, bubbleOrigin, NULL, NULL, 0, CONTENTS_WATER ); + + bubbleOrigin[2] += -15; // put the origin below the character's feet + + if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYA + || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYB ) { + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 700, 10 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 700, 10 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 700, 10 ); + } else if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE ) { + bubbleOrigin[2] += -3; // put the origin a little below + + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20 ); } - trap_R_AddRefEntityToScene( ent ); } - if ( state->powerups & ( 1 << PW_QUAD ) ) - { - if (team == TEAM_RED) - ent->customShader = cgs.media.redQuadShader; - else - ent->customShader = cgs.media.quadShader; - trap_R_AddRefEntityToScene( ent ); + // apply the render type + aura.reType = aura2.reType = RT_MODEL; + + // clear the axis to keep the position + AxisClear( aura.axis ); + AxisClear( aura2.axis ); + + // if the player is moving like going forward and backwards, then use other aura model + AURA_ANIMS( aura, 0 ) + AURA_ANIMS( aura2, 1 ) + + // resize the aura + MODEL_SIZE( aura, 1.3f ) + MODEL_SIZE( aura2, 1.49f ) + + // set aura position to the player + VectorCopy( legs.origin, aura.origin ); + VectorCopy( legs.lightingOrigin, aura.lightingOrigin ); + VectorCopy( legs.origin, aura2.origin ); + VectorCopy( legs.lightingOrigin, aura2.lightingOrigin ); + + // BFP - TODO: Add yellow aura only when the player is transformed, but don't override when playing a team gamemode + // aura.customShader = aura2.customShader = cgs.media.auraYellowShader; + // Don't put this line of code here if transformed, just put outside the check EF_AURA conditional + // trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), 1.0, 1.0, 0 ); + + // apply light blinking + if ( ci->team == TEAM_BLUE ) { + aura.customShader = aura2.customShader = cgs.media.auraBlueShader; + AURA_LIGHT( 0.2f, 0.2f, 1.0 ) + } else { + aura.customShader = aura2.customShader = cgs.media.auraRedShader; + AURA_LIGHT( 1.0, 0.2f, 0.2f ) + } + + aura.renderfx = aura2.renderfx = renderfx; + VectorCopy( aura.origin, aura.oldorigin ); // don't positionally lerp at all + VectorCopy( aura2.origin, aura2.oldorigin ); // don't positionally lerp at all + + // ki boost and ki charge sounds + if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE ) { + trap_S_AddLoopingSound( cent->currentState.clientNum, cent->lerpOrigin, + vec3_origin, cgs.media.kiChargeSound ); + } else { + trap_S_AddLoopingSound( cent->currentState.clientNum, cent->lerpOrigin, + vec3_origin, cgs.media.kiUseSound ); } - if ( state->powerups & ( 1 << PW_REGEN ) ) { - if ( ( ( cg.time / 100 ) % 10 ) == 1 ) { - ent->customShader = cgs.media.regenShader; - trap_R_AddRefEntityToScene( ent ); + + // keep the aura pivot tagged in tag_torso + CG_PositionRotatedEntityOnTag( &aura, &legs, ci->legsModel, "tag_torso" ); + CG_PositionRotatedEntityOnTag( &aura2, &legs, ci->legsModel, "tag_torso" ); + + // BFP - Sprite aura + if ( ( cg_spriteAura.integer > 0 && cg_smallOwnAura.integer <= 0 ) + || ( cg_spriteAura.integer > 0 && cg_smallOwnAura.integer > 0 && clientNum != cg.snap->ps.clientNum ) ) { + // BFP - NOTE: What shader was added?? Originally, BFP didn't finish the shader to attach or they forgot... + // That radius looks a bit big for an aura, maybe they thought to fit the texture that way or some circular aura? + // And... What the heck? This sprite view depends of pitch angle until some client connects? + // Also when cg_smallOwnAura cvar is enabled, it doesn't display any aura to the client itself. + // Moreover, the lights are disabled as mentioned previously in AURA_LIGHT macro comments + // In the future, the shader should be added, not sure what kind of aura is this... + float pitchView = cg.refdefViewAngles[PITCH]; + int i, connectedClients = 1; + + for ( i = 0; i < MAX_CLIENTS; i++ ) { + if ( cg_entities[i].currentValid ) { + connectedClients++; + } + } + aura.reType = RT_SPRITE; + aura.customShader = 0; + aura.radius = 75; + if ( connectedClients > 1 ) { + pitchView = -15; + } + aura.rotation = pitchView; + + aura.shaderRGBA[0] = 255; + aura.shaderRGBA[1] = 255; + aura.shaderRGBA[2] = 255; + aura.shaderRGBA[3] = 255; + trap_R_AddRefEntityToScene( &aura ); + return; + } + + // BFP - Small own aura only can be shown to the one who enables it for themself, not everyone + if ( clientNum != cg.snap->ps.clientNum || cg_smallOwnAura.integer <= 0 ) { + // add aura + if ( cg_spriteAura.integer <= 0 && cg_polygonAura.integer > 0 && cg_lightweightAuras.integer <= 0 ) { + trap_R_AddRefEntityToScene( &aura ); + } + + // add secondary aura to make look cooler, a bit bigger than the other + if ( cg_spriteAura.integer <= 0 && cg_polygonAura.integer > 0 && cg_highPolyAura.integer > 0 && cg_lightweightAuras.integer <= 0 ) { + trap_R_AddRefEntityToScene( &aura2 ); } } - if ( state->powerups & ( 1 << PW_BATTLESUIT ) ) { - ent->customShader = cgs.media.battleSuitShader; - trap_R_AddRefEntityToScene( ent ); + } else { + // BFP - Ki trail being removed + if ( cg_kiTrail.integer >= 10 ) { + REMOVING_KI_TRAILS( clientNum, kiTrailOrigin, kiTrailShader, qtrue ) } } } +#undef AURA_ANIMS +#undef AURA_LIGHT +#undef REMOVING_KI_TRAILS + /* ================= @@ -2198,26 +2446,12 @@ void CG_Player( centity_t *cent ) { refEntity_t legs; refEntity_t torso; refEntity_t head; - refEntity_t aura; // BFP - Aura - refEntity_t aura2; // BFP - Secondary aura int clientNum; int renderfx; qboolean shadow; float shadowPlane; - int model_i, model_j; // BFP - For model sizes - vec3_t auraInverseRotation; // BFP - For aura inverse rotation - // BFP - Ki trail setup - vec3_t kiTrailOrigin; qhandle_t kiTrailShader; - // BFP - Macro for the size of a model - #define MODEL_SIZE(model, model_size) \ - for ( model_i = 0; model_i < 3; model_i++ ) { \ - for ( model_j = 0; model_j < 3; model_j++ ) { \ - model.axis[model_i][model_j] *= model_size; \ - } \ - } - // the client number is stored in clientNum. It can't be derived // from the entity number, because a single client may have // multiple corpses on the level using the same clientinfo @@ -2257,8 +2491,6 @@ void CG_Player( centity_t *cent ) { memset( &legs, 0, sizeof(legs) ); memset( &torso, 0, sizeof(torso) ); memset( &head, 0, sizeof(head) ); - memset( &aura, 0, sizeof(aura) ); // BFP - Aura - memset( &aura2, 0, sizeof(aura2) ); // BFP - Secondary aura // get the rotation information CG_PlayerAngles( cent, legs.axis, torso.axis, head.axis ); @@ -2303,7 +2535,7 @@ void CG_Player( centity_t *cent ) { legs.renderfx = renderfx; VectorCopy (legs.origin, legs.oldorigin); // don't positionally lerp at all - CG_AddRefEntityWithPowerups( &legs, ¢->currentState, ci->team ); + CG_AddRefEntityWithPowerups( legs, ¢->currentState, ci->team ); // if the model failed, allow the default nullmodel to be displayed if (!legs.hModel) { @@ -2327,7 +2559,7 @@ void CG_Player( centity_t *cent ) { torso.shadowPlane = shadowPlane; torso.renderfx = renderfx; - CG_AddRefEntityWithPowerups( &torso, ¢->currentState, ci->team ); + CG_AddRefEntityWithPowerups( torso, ¢->currentState, ci->team ); // // add the head @@ -2361,199 +2593,17 @@ void CG_Player( centity_t *cent ) { memset( &head, 0, sizeof(head) ); } - CG_AddRefEntityWithPowerups( &head, ¢->currentState, ci->team ); + CG_AddRefEntityWithPowerups( head, ¢->currentState, ci->team ); // BFP - If the entity is a corpse, avoid drawing ki trails to the dead if ( cent->currentState.eFlags & EF_DEAD ) { return; } - // BFP - Origin setup for ki trails - #define KI_TRAIL_ZPOS 5 - VectorCopy( cent->lerpOrigin, kiTrailOrigin ); - kiTrailOrigin[2] += KI_TRAIL_ZPOS; - #undef KI_TRAIL_ZPOS - // - // BFP - Aura + // BFP - Aura and ki trails // - // Macro to handle the aura animations, when idling it sets the aura vertical rotation, so the aura rotates vertically - #define AURA_ANIMS(aura, reversed) \ - if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_RUN \ - || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_JUMP ) { \ - aura.hModel = cgs.media.runauraModel; \ - } else if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_BACK \ - || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_JUMPB \ - || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYB ) { \ - aura.hModel = cgs.media.backauraModel; \ - } else if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYA ) { \ - aura.hModel = cgs.media.flyauraModel; \ - } else { \ - aura.hModel = cgs.media.auraModel; \ - if ( reversed ) { \ - VectorNegate( cg.autoAngles, auraInverseRotation ); \ - AnglesToAxis( auraInverseRotation, aura.axis ); \ - } else { \ - AnglesToAxis( cg.autoAngles, aura.axis ); \ - } \ - } - - // Macro for the dynamic aura light, note: when charging it changes the shinning a bit - // Aura lights like cg_smallOwnAura only can be shown to itself and not the other clients, - // the other clients only show small lights - #define AURA_LIGHT(r, g, b) \ - if ( cg_lightAuras.integer > 0 ) { \ - if ( clientNum == cg.snap->ps.clientNum && cg_smallOwnAura.integer > 0 ) { \ - trap_R_AddLightToScene( cent->lerpOrigin, 200, r, g, b ); \ - trap_R_AddLightToScene( cent->lerpOrigin, 200, r, g, b ); \ - if ( !( cg.predictedPlayerState.pm_flags & PMF_KI_CHARGE ) ) { \ - trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), r, g, b ); \ - trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), r, g, b ); \ - trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), r, g, b ); \ - trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), r, g, b ); \ - trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), r, g, b ); \ - } else { \ - trap_R_AddLightToScene( cent->lerpOrigin, 100 + (rand()&100), r, g, b ); \ - trap_R_AddLightToScene( cent->lerpOrigin, 100 + (rand()&100), r, g, b ); \ - trap_R_AddLightToScene( cent->lerpOrigin, 100 + (rand()&100), r, g, b ); \ - trap_R_AddLightToScene( cent->lerpOrigin, 100 + (rand()&100), r, g, b ); \ - trap_R_AddLightToScene( cent->lerpOrigin, 100 + (rand()&100), r, g, b ); \ - } \ - } else if ( clientNum != cg.snap->ps.clientNum || cg_lightweightAuras.integer > 0 || cg_polygonAura.integer > 0 || cg_highPolyAura.integer > 0 ) { \ - trap_R_AddLightToScene( cent->lerpOrigin, 50 + (rand()&100), r, g, b ); \ - trap_R_AddLightToScene( cent->lerpOrigin, 50 + (rand()&100), r, g, b ); \ - trap_R_AddLightToScene( cent->lerpOrigin, 50 + (rand()&100), r, g, b ); \ - } else { \ - trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&63), r, g, b ); \ - trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), r, g, b ); \ - trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), r, g, b ); \ - if ( !( cg.predictedPlayerState.pm_flags & PMF_KI_CHARGE ) ) { \ - trap_R_AddLightToScene( cent->lerpOrigin, 100 + (rand()&150), r, g, b ); \ - } \ - } \ - } - - // Macro to remove ki trails - #define REMOVING_KI_TRAILS(clientNum, kiTrailOrigin, kiTrailShader, fastRemove) \ - if ( cg.time > cent->pe.kiTrailTime ) { /* reset ki trail position avoid being zeroed */ \ - CG_ResetKiTrail( clientNum, kiTrailOrigin ); \ - } else { /* ki trails keep running in that moment, but their segments are being removed */ \ - CG_KiTrail( clientNum, kiTrailOrigin, fastRemove, kiTrailShader ); \ - } - - if ( cent->currentState.eFlags & EF_AURA ) { - // BFP - Trace for bubble particles only when moving in the water and charging - int destContentType = CG_PointContents( legs.origin, -1 ); - - // BFP - Ki trail - if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_CHARGE - && cg_kiTrail.integer >= 10 ) { - // apply time for using ki trail - cent->pe.kiTrailTime = cg.time + cg_kiTrail.integer*5; - - CG_KiTrail( clientNum, kiTrailOrigin, qfalse, kiTrailShader ); - } else { // handle when the ki trail was being used previously - REMOVING_KI_TRAILS( clientNum, kiTrailOrigin, kiTrailShader, qtrue ) - } - - // spawning bubble particles - if ( destContentType & CONTENTS_WATER ) { - trace_t trace; - vec3_t start, bubbleOrigin; - - VectorCopy( legs.origin, bubbleOrigin ); - trap_CM_BoxTrace( &trace, start, bubbleOrigin, NULL, NULL, 0, CONTENTS_WATER ); - - bubbleOrigin[2] += -15; // put the origin below the character's feet - - if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYA - || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYB ) { - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 700, 10 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 700, 10 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 700, 10 ); - } else if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE ) { - bubbleOrigin[2] += -3; // put the origin a little below - - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, bubbleOrigin, trace.endpos, 0, 20 ); - } - } - - // Apply the render type - aura.reType = aura2.reType = RT_MODEL; - - // Clear the axis to keep the position - AxisClear( aura.axis ); - AxisClear( aura2.axis ); - - // If the player is moving like going forward and backwards, then use other aura model - AURA_ANIMS( aura, 0 ) - AURA_ANIMS( aura2, 1 ) - - // Resize the aura - MODEL_SIZE( aura, 1.3f ) - MODEL_SIZE( aura2, 1.49f ) - - // Set aura position to the player - VectorCopy( legs.origin, aura.origin ); - VectorCopy( legs.lightingOrigin, aura.lightingOrigin ); - VectorCopy( legs.origin, aura2.origin ); - VectorCopy( legs.lightingOrigin, aura2.lightingOrigin ); - - // BFP - TODO: Add yellow aura only when the player is transformed, but don't override when playing a team gamemode - // aura.customShader = aura2.customShader = cgs.media.auraYellowShader; - // Don't put this line of code here if transformed, just put outside the check EF_AURA conditional - // trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), 1.0, 1.0, 0 ); - - // Apply light blinking - if ( ci->team == TEAM_BLUE ) { - aura.customShader = aura2.customShader = cgs.media.auraBlueShader; - AURA_LIGHT( 0.2f, 0.2f, 1.0 ) - } else { - aura.customShader = aura2.customShader = cgs.media.auraRedShader; - AURA_LIGHT( 1.0, 0.2f, 0.2f ) - } - - aura.renderfx = aura2.renderfx = renderfx; - VectorCopy( aura.origin, aura.oldorigin ); // don't positionally lerp at all - VectorCopy( aura2.origin, aura2.oldorigin ); // don't positionally lerp at all - - // Ki boost and ki charge sounds - if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE ) { - trap_S_AddLoopingSound( cent->currentState.clientNum, cent->lerpOrigin, - vec3_origin, cgs.media.kiChargeSound ); - } else { - trap_S_AddLoopingSound( cent->currentState.clientNum, cent->lerpOrigin, - vec3_origin, cgs.media.kiUseSound ); - } - - // Keep the aura pivot tagged in tag_torso - CG_PositionRotatedEntityOnTag( &aura, &legs, ci->legsModel, "tag_torso" ); - CG_PositionRotatedEntityOnTag( &aura2, &legs, ci->legsModel, "tag_torso" ); - - // BFP - Small own aura only can be shown to the one who enables it for themself, not everyone - if ( clientNum != cg.snap->ps.clientNum || cg_smallOwnAura.integer <= 0 ) { - // Add aura - if ( cg_polygonAura.integer > 0 && cg_lightweightAuras.integer <= 0 ) { - trap_R_AddRefEntityToScene( &aura ); - } - - // Add secondary aura to make look cooler, a bit bigger than the other - if ( cg_polygonAura.integer > 0 && cg_highPolyAura.integer > 0 && cg_lightweightAuras.integer <= 0 ) { - trap_R_AddRefEntityToScene( &aura2 ); - } - } - } else { - // BFP - Ki trail being removed - if ( cg_kiTrail.integer >= 10 ) { - REMOVING_KI_TRAILS( clientNum, kiTrailOrigin, kiTrailShader, qtrue ) - } - } + CG_Aura( cent, clientNum, ci, renderfx, legs, kiTrailShader ); // BFP - Ki attack sounds CG_KiAttackSounds( cent ); @@ -2584,9 +2634,6 @@ void CG_Player( centity_t *cent ) { } } #undef MODEL_SIZE -#undef AURA_ANIMS -#undef AURA_LIGHT -#undef REMOVING_KI_TRAILS /* =============== From 607db32857b15483d386d7d937bb5565de5153c9 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 9 Sep 2024 00:34:21 +0200 Subject: [PATCH 087/374] Add .gitattributes to avoid issues when opening files in some text editors --- .gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6313b56 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf From 1083bde4d9da0ff13f149143f5b9fae851692d84 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 9 Sep 2024 00:34:21 +0200 Subject: [PATCH 088/374] More history about the original source code and fix table of contents --- README.md | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 3b78d16..8ff2f4a 100644 --- a/README.md +++ b/README.md @@ -11,27 +11,27 @@ A legendary 90s era Quake 3 Arena mod. ## *WARNING!* UNDER CONSTRUCTION! ### Table of contents -> > 1. [TODO list](#todo-list) -> > 2. [History](#history) -> > 3. [About the repository](#about-the-repository) -> > 4. [References and clues to know how should be the game](#references-and-clues-to-know-how-should-be-the-game) -> > 5. [How to build](#how-to-build) -> > > 5.1. [Introduction](#introduction)
-> > > 5.2. [Windows](#windows) -> > > > 5.1.1. [Building QVM (using .bat)](#building-qvm-using-bat)
-> > > > 5.1.2. [Building QVM (mingw)](#building-qvm-mingw)
-> > > > 5.1.3. [MSYS2 (mingw) (Building dynamic libraries (.dll))](#msys2-mingw-building-dynamic-libraries-dll)
-> > > > 5.1.4. [Cygwin (mingw) (Building dynamic libraries (.dll))](#cygwin-mingw-building-dynamic-libraries-dll) -> > > -> > > 5.3. [Linux](#linux) -> > > > 5.3.1. [Building QVM (make)](#building-qvm-make)
-> > > > 5.3.2. [Building QVM (using .bat)](#building-qvm-using-bat-1)
-> > > > 5.3.3. [Building shared libraries (.so)](#building-shared-libraries-so) -> > > -> > > 5.4. [Optional](#optional) -> > 6. [Notes](#notes) -> > 7. [Legal](#legal) -> > 8. [Credits](#credits) +> 1. [TODO list](#todo-list) +> 2. [History](#history) +> 3. [About the repository](#about-the-repository) +> 4. [References and clues to know how should be the game](#references-and-clues-to-know-how-should-be-the-game) +> 5. [How to build](#how-to-build) +> > 5.1. [Introduction](#introduction)
+> > 5.2. [Windows](#windows) +> > > 5.2.1. [Building QVM (using .bat)](#building-qvm-using-bat)
+> > > 5.2.2. [Building QVM (mingw)](#building-qvm-mingw)
+> > > 5.2.3. [MSYS2 (mingw) (Building dynamic libraries (.dll))](#msys2-mingw-building-dynamic-libraries-dll)
+> > > 5.2.4. [Cygwin (mingw) (Building dynamic libraries (.dll))](#cygwin-mingw-building-dynamic-libraries-dll) +> > +> > 5.3. [Linux](#linux) +> > > 5.3.1. [Building QVM (make)](#building-qvm-make)
+> > > 5.3.2. [Building QVM (using .bat)](#building-qvm-using-bat-1)
+> > > 5.3.3. [Building shared libraries (.so)](#building-shared-libraries-so) +> > +> > 5.4. [Optional](#optional) +> 6. [Notes](#notes) +> 7. [Legal](#legal) +> 8. [Credits](#credits) # TODO list: @@ -72,7 +72,10 @@ Ended: 2002 Bid For Power is a total conversion for QuakeIII that plays nothing like the original game. Players take control of Ki-powered superheros and battle it out in a mostly aerial fight. The game is highlighted by the work of a great art team and an original style, and the gameplay is extremely fast paced. It can be difficult to keep up with until you get the hang of it. -The source code was lost, but the assets and some docs are in any place. +The source code is said to have started from SDK version 1.17 after the release of Quake 3 Arena (December 2, 1999). It continued to be updated, including the addition of `cg_particles.c` in version 1.29, until version 1.31. +More info can be found in [Quake 3 Arena changelog version history](https://discourse.ioquake.org/t/quake-3-changelog-version-history/375). + +The original source code appears to be lost, but the assets and some docs are available in various places. Nonetheless, not all sources are accessible. #### Old dev journals (1999 - 2002) From 60ad8dd036ad9627ebbd7b9f7be4b13abd129ad3 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 9 Sep 2024 00:34:21 +0200 Subject: [PATCH 089/374] Last moments of Yrgol's dev journal --- docs/yrgol_dev_journal.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/docs/yrgol_dev_journal.md b/docs/yrgol_dev_journal.md index 9878dbb..135f4bb 100644 --- a/docs/yrgol_dev_journal.md +++ b/docs/yrgol_dev_journal.md @@ -1,4 +1,35 @@ +# BFP MAKES YOU TALK IN CAPS - Yrgol - 05/12/2002 + +For those that were wondering who these guys are, the about section has been updated to include character descriptions and a little backstory for all the fighters. + + + +# 1.2 100,000 - Yrgol - 05/10/2002 + +Version 1.2 of Bid For Power has now been downloaded over 100,000 times. I'd like to give a big thanks out to everyone who stayed with us. + + + +# 1.2 Tourney - Yrgol - 05/08/2002 + +With the demise of the XSL there's another BFP tournament forming. They are having a 1v1, 2v2, and 3v3 tournament with signups going on now. +Visit their page at https://web.archive.org/web/20020810122128/http://bfp-allstars.us4n6.org/ + + + +# Its True, Its True! - Yrgol - 05/06/2002 + +1.2 is now ready for download. The files section of this page has been updated. I will be adding more links as the night goes on. + + + +# 28 hours until 1.2 - Yrgol - 05/05/2002 + +1.2 will be released tomorrow at around 9pm eastern. I added a few images to the action section. When the big fuzzy focus on planetquake gets updated they'll have another 8 screenshots which combined with the new images on this page will cover all the new attacks. + + + # BFP 1.1 Update Information - 02/04/2002 by Yrgol The grand list of my updates to the latest build of Bid For Power. Enjoy. From ac7ffff564553f471fc71868935f40b51b5b3ee8 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 9 Sep 2024 00:39:48 +0200 Subject: [PATCH 090/374] Makefile: increase optimization to -O3 --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index f14c704..caf0156 100644 --- a/Makefile +++ b/Makefile @@ -115,7 +115,7 @@ ifeq ($(PLATFORM),linux) BASE_CFLAGS = -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes -pipe - OPTIMIZE = -O2 -fvisibility=hidden -fomit-frame-pointer -ffast-math + OPTIMIZE = -O3 -fvisibility=hidden -fomit-frame-pointer -ffast-math SHLIBEXT=so SHLIBCFLAGS=-fPIC -fvisibility=hidden @@ -170,7 +170,7 @@ ifdef MINGW BASE_CFLAGS = -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes -pipe - OPTIMIZE = -O2 -fvisibility=hidden -fomit-frame-pointer -ffast-math + OPTIMIZE = -O3 -fvisibility=hidden -fomit-frame-pointer -ffast-math SHLIBEXT=dll SHLIBCFLAGS=-fPIC -fvisibility=hidden @@ -221,7 +221,7 @@ ifeq ($(PLATFORM),windows) BASE_CFLAGS = -Wall -fno-strict-aliasing -Wimplicit -Wstrict-prototypes -pipe - OPTIMIZE = -O2 -fvisibility=hidden -fomit-frame-pointer -ffast-math + OPTIMIZE = -O3 -fvisibility=hidden -fomit-frame-pointer -ffast-math SHLIBEXT=dll SHLIBCFLAGS=-fPIC -fvisibility=hidden From 81dcf0bcd177e744dac4643ac9b838de953fcaaf Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 9 Sep 2024 01:26:48 +0200 Subject: [PATCH 091/374] Add scripts to move .pk3 file to ease development --- movepk3.bat | 18 ++++++++++++++++++ movepk3.sh | 16 ++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 movepk3.bat create mode 100644 movepk3.sh diff --git a/movepk3.bat b/movepk3.bat new file mode 100644 index 0000000..d5a4ae3 --- /dev/null +++ b/movepk3.bat @@ -0,0 +1,18 @@ +@echo off +setlocal + +set "SOURCEPK3FILE=.\*.pk3" +rem Change the path to save/overwrite the pk3 file: +set "BFPQ3DIR=%USERPROFILE%\Quake3\bfp" + +if exist "%SOURCEPK3FILE%" ( + echo Moving the file... + move "%SOURCEPK3FILE%" "%BFPQ3DIR%" + TIMEOUT 3 > NUL + echo COMPILED DATETIME: + echo %DATE% %TIME:~0,8% +) else ( + echo ERROR! CHECK THE LOG +) + +endlocal diff --git a/movepk3.sh b/movepk3.sh new file mode 100644 index 0000000..04e0518 --- /dev/null +++ b/movepk3.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +( + SOURCEPK3FILE="./*.pk3" + BFPQ3DIR="$HOME/Quake3/bfp" # change the path to save/overwrite the pk3 file + + if ls $SOURCEPK3FILE 1> /dev/null 2>&1; then + echo "Moving the file..." + mv $SOURCEPK3FILE $BFPQ3DIR + sleep 3 + echo "COMPILED DATETIME:" + date +'%d/%m/%Y %H:%M:%S' + else + echo "ERROR! CHECK THE LOG" + fi +) From 5f712b64bdb98686156ca069db1b9a5ab9f5580a Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 9 Sep 2024 01:30:39 +0200 Subject: [PATCH 092/374] .gitignore: Ignore movepk3 scripts --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 8e6b8f9..4eb8bef 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ .vscode .vscode/* build* -vm* \ No newline at end of file +vm* +movepk3.* \ No newline at end of file From 5ca5fffac6092e24223091362726d48e59041739 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 9 Sep 2024 01:46:18 +0200 Subject: [PATCH 093/374] q3_ui: Fix QVM warnings from q3_ui code, correct arena servers remove button position (original BFP forgot to adjust that), fix player animation controls from ui_players.c and some code cleanup --- source/q3_ui/ui_atoms.c | 4 +- source/q3_ui/ui_controls2.c | 76 +++++++++++++++++++---------------- source/q3_ui/ui_demo2.c | 17 +++++--- source/q3_ui/ui_mem.c | 2 +- source/q3_ui/ui_playermodel.c | 14 +++---- source/q3_ui/ui_players.c | 22 ---------- source/q3_ui/ui_qmenu.c | 2 +- source/q3_ui/ui_servers2.c | 34 ++++++++-------- source/q3_ui/ui_startserver.c | 32 +++++++-------- source/q3_ui/ui_video.c | 24 +++++------ 10 files changed, 109 insertions(+), 118 deletions(-) diff --git a/source/q3_ui/ui_atoms.c b/source/q3_ui/ui_atoms.c index 6fbba58..92397d0 100644 --- a/source/q3_ui/ui_atoms.c +++ b/source/q3_ui/ui_atoms.c @@ -919,7 +919,7 @@ void UI_MouseEvent( int dx, int dy ) if (uis.activemenu->cursor != i) { Menu_SetCursor( uis.activemenu, i ); - ((menucommon_s*)(uis.activemenu->items[uis.activemenu->cursor_prev]))->flags &= ~QMF_HASMOUSEFOCUS; + ((menucommon_s*)(uis.activemenu->items[uis.activemenu->cursor_prev]))->flags &= (unsigned int)~QMF_HASMOUSEFOCUS; if ( !(((menucommon_s*)(uis.activemenu->items[uis.activemenu->cursor]))->flags & QMF_SILENT ) ) { trap_S_StartLocalSound( menu_move_sound, CHAN_LOCAL_SOUND ); @@ -932,7 +932,7 @@ void UI_MouseEvent( int dx, int dy ) if (uis.activemenu->nitems > 0) { // out of any region - ((menucommon_s*)(uis.activemenu->items[uis.activemenu->cursor]))->flags &= ~QMF_HASMOUSEFOCUS; + ((menucommon_s*)(uis.activemenu->items[uis.activemenu->cursor]))->flags &= (unsigned int)~QMF_HASMOUSEFOCUS; } } diff --git a/source/q3_ui/ui_controls2.c b/source/q3_ui/ui_controls2.c index 3c66b8d..986dc6b 100644 --- a/source/q3_ui/ui_controls2.c +++ b/source/q3_ui/ui_controls2.c @@ -161,18 +161,19 @@ typedef struct #define ANIM_WEAPON9 20 #define ANIM_WEAPON10 21 #endif -#define ANIM_KIATTACK1 12 // BFP - (before ANIM_ATTACK) -#define ANIM_KIATTACK2 13 // BFP -#define ANIM_KIATTACK3 14 // BFP -#define ANIM_KIATTACK4 15 // BFP -#define ANIM_KIATTACK5 16 // BFP -#define ANIM_GESTURE 17 -#define ANIM_DIE 18 -#define ANIM_CHAT 19 -#define ANIM_FLY 20 // BFP -#define ANIM_KICHARGE 21 // BFP -#define ANIM_MELEE 22 // BFP -#define ANIM_BLOCK 23 // BFP +#define ANIM_ATTACK 12 +#define ANIM_KIATTACK1 13 // BFP +#define ANIM_KIATTACK2 14 // BFP +#define ANIM_KIATTACK3 15 // BFP +#define ANIM_KIATTACK4 16 // BFP +#define ANIM_KIATTACK5 17 // BFP +#define ANIM_GESTURE 18 +#define ANIM_DIE 19 +#define ANIM_CHAT 20 +#define ANIM_FLY 21 // BFP +#define ANIM_KICHARGE 22 // BFP +#define ANIM_MELEE 23 // BFP +#define ANIM_BLOCK 24 // BFP typedef struct { @@ -296,11 +297,14 @@ static bind_t g_bindings[] = G_BINDING_KEY( "weapon 3", "ki attack 3", ID_KIATTACK3, ANIM_KIATTACK3, '3' ) // BFP - ki attack 3 (before shotgun) G_BINDING_KEY( "weapon 4", "ki attack 4", ID_KIATTACK4, ANIM_KIATTACK4, '4' ) // BFP - ki attack 4 (before grenade launcher) G_BINDING_KEY( "weapon 5", "ki attack 5", ID_KIATTACK5, ANIM_KIATTACK5, '5' ) // BFP - ki attack 5 (before rocket launcher) - //G_BINDING_KEY( "weapon 6", "lightning", ID_WEAPON6, ANIM_WEAPON6, '6' ) // BFP - unused - //G_BINDING_KEY( "weapon 7", "railgun", ID_WEAPON7, ANIM_WEAPON7, '7' ) // BFP - unused - //G_BINDING_KEY( "weapon 8", "plasma gun", ID_WEAPON8, ANIM_WEAPON8, '8' ) // BFP - unused - //G_BINDING_KEY( "weapon 9", "BFG", ID_WEAPON9, ANIM_WEAPON9, '9' ) // BFP - unused - G_BINDING_KEY( "+attack", "attack", ID_ATTACK, ANIM_KIATTACK1, K_CTRL ) + // BFP - unused +#if 0 + G_BINDING_KEY( "weapon 6", "lightning", ID_WEAPON6, ANIM_WEAPON6, '6' ) + G_BINDING_KEY( "weapon 7", "railgun", ID_WEAPON7, ANIM_WEAPON7, '7' ) + G_BINDING_KEY( "weapon 8", "plasma gun", ID_WEAPON8, ANIM_WEAPON8, '8' ) + G_BINDING_KEY( "weapon 9", "BFG", ID_WEAPON9, ANIM_WEAPON9, '9' ) +#endif + G_BINDING_KEY( "+attack", "attack", ID_ATTACK, ANIM_ATTACK, K_CTRL ) G_BINDING_KEY( "+button7", "Melee Combat", ID_MELEE, ANIM_MELEE, K_ALT ) // BFP - melee G_BINDING_KEY( "+button10", "Block", ID_BLOCK, ANIM_BLOCK, K_CTRL ) // BFP - block G_BINDING_KEY( "weapprev", "prev weapon", ID_WEAPPREV, ANIM_IDLE, '[' ) @@ -313,7 +317,7 @@ static bind_t g_bindings[] = G_BINDING_KEY( "+button9", "Charge Ki", ID_KICHARGE, ANIM_KICHARGE, K_MOUSE2 ) // BFP - charge ki control G_BINDING_KEY( "kiusetoggle", "Use Ki (toggle)", ID_KIUSETOGGLE, ANIM_IDLE, 'e' ) // BFP - use ki toggle control G_BINDING_KEY( "+button8", "Use Ki", ID_KIUSE, ANIM_IDLE, K_SHIFT ) // BFP - use ki control - G_BINDING_KEY( (char*)NULL, (char*)NULL, 0, 0, -1 ) + G_BINDING_KEY( (char*)NULL, (char*)NULL, 0, 0, -1 ) }; #undef G_BINDING_KEY @@ -536,6 +540,10 @@ static void Controls_UpdateModel( int anim ) { s_controls.playerTorso = TORSO_CHARGE; break; + case ANIM_ATTACK: + s_controls.playerTorso = TORSO_ATTACK0_STRIKE; + break; + // BFP - Melee case ANIM_MELEE: s_controls.playerLegs = LEGS_MELEE_STRIKE; @@ -682,7 +690,7 @@ static void Controls_Update( void ) { // enable controls in active group (and count number of items for vertical centering) // bk001204 - parentheses for( j = 0; (control = controls[j]) != NULL ; j++ ) { - control->flags &= ~(QMF_GRAYED|QMF_HIDDEN|QMF_INACTIVE); + control->flags &= (unsigned int)~(QMF_GRAYED|QMF_HIDDEN|QMF_INACTIVE); } // position controls @@ -704,24 +712,24 @@ static void Controls_Update( void ) { } // enable action item - ((menucommon_s*)(s_controls.menu.items[s_controls.menu.cursor]))->flags &= ~QMF_GRAYED; + ((menucommon_s*)(s_controls.menu.items[s_controls.menu.cursor]))->flags &= (unsigned int)~QMF_GRAYED; // don't gray out player's name - s_controls.name.generic.flags &= ~QMF_GRAYED; + s_controls.name.generic.flags &= (unsigned int)~QMF_GRAYED; return; } // enable everybody for( i = 0; i < s_controls.menu.nitems; i++ ) { - ((menucommon_s*)(s_controls.menu.items[i]))->flags &= ~QMF_GRAYED; + ((menucommon_s*)(s_controls.menu.items[i]))->flags &= (unsigned int)~QMF_GRAYED; } // makes sure flags are right on the group selection controls - s_controls.looking.generic.flags &= ~(QMF_GRAYED|QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS); - s_controls.movement.generic.flags &= ~(QMF_GRAYED|QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS); - s_controls.weapons.generic.flags &= ~(QMF_GRAYED|QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS); - s_controls.misc.generic.flags &= ~(QMF_GRAYED|QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS); + s_controls.looking.generic.flags &= (unsigned int)~(QMF_GRAYED|QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS); + s_controls.movement.generic.flags &= (unsigned int)~(QMF_GRAYED|QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS); + s_controls.weapons.generic.flags &= (unsigned int)~(QMF_GRAYED|QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS); + s_controls.misc.generic.flags &= (unsigned int)~(QMF_GRAYED|QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS); s_controls.looking.generic.flags |= QMF_PULSEIFFOCUS; s_controls.movement.generic.flags |= QMF_PULSEIFFOCUS; @@ -731,22 +739,22 @@ static void Controls_Update( void ) { // set buttons switch( s_controls.section ) { case C_MOVEMENT: - s_controls.movement.generic.flags &= ~QMF_PULSEIFFOCUS; + s_controls.movement.generic.flags &= (unsigned int)~QMF_PULSEIFFOCUS; s_controls.movement.generic.flags |= (QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS); break; case C_LOOKING: - s_controls.looking.generic.flags &= ~QMF_PULSEIFFOCUS; + s_controls.looking.generic.flags &= (unsigned int)~QMF_PULSEIFFOCUS; s_controls.looking.generic.flags |= (QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS); break; case C_WEAPONS: - s_controls.weapons.generic.flags &= ~QMF_PULSEIFFOCUS; + s_controls.weapons.generic.flags &= (unsigned int)~QMF_PULSEIFFOCUS; s_controls.weapons.generic.flags |= (QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS); break; case C_MISC: - s_controls.misc.generic.flags &= ~QMF_PULSEIFFOCUS; + s_controls.misc.generic.flags &= (unsigned int)~QMF_PULSEIFFOCUS; s_controls.misc.generic.flags |= (QMF_HIGHLIGHT|QMF_HIGHLIGHT_IF_FOCUS); break; } @@ -805,13 +813,13 @@ static void Controls_DrawKeyBinding( void *self ) if (s_controls.waitingforkey) { UI_DrawChar( x, y, '=', UI_CENTER|UI_BLINK|UI_SMALLFONT, text_color_highlight); - UI_DrawString(SCREEN_WIDTH * 0.50, SCREEN_HEIGHT * 0.80, "Waiting for new key ... ESCAPE to cancel", UI_SMALLFONT|UI_CENTER|UI_PULSE, colorWhite ); + UI_DrawString( SCREEN_WIDTH * 0.50, SCREEN_HEIGHT * 0.80, "Waiting for new key ... ESCAPE to cancel", UI_SMALLFONT|UI_CENTER|UI_PULSE, colorWhite ); } else { UI_DrawChar( x, y, 13, UI_CENTER|UI_BLINK|UI_SMALLFONT, text_color_highlight); - UI_DrawString(SCREEN_WIDTH * 0.50, SCREEN_HEIGHT * 0.78, "Press ENTER or CLICK to change", UI_SMALLFONT|UI_CENTER, colorWhite ); - UI_DrawString(SCREEN_WIDTH * 0.50, SCREEN_HEIGHT * 0.82, "Press BACKSPACE to clear", UI_SMALLFONT|UI_CENTER, colorWhite ); + UI_DrawString( SCREEN_WIDTH * 0.50, SCREEN_HEIGHT * 0.78, "Press ENTER or CLICK to change", UI_SMALLFONT|UI_CENTER, colorWhite ); + UI_DrawString( SCREEN_WIDTH * 0.50, SCREEN_HEIGHT * 0.82, "Press BACKSPACE to clear", UI_SMALLFONT|UI_CENTER, colorWhite ); } } else @@ -836,7 +844,7 @@ Controls_StatusBar */ static void Controls_StatusBar( void *self ) { - UI_DrawString(SCREEN_WIDTH * 0.50, SCREEN_HEIGHT * 0.80, "Use Arrow Keys or CLICK to change", UI_SMALLFONT|UI_CENTER, colorWhite ); + UI_DrawString( SCREEN_WIDTH * 0.50, SCREEN_HEIGHT * 0.80, "Use Arrow Keys or CLICK to change", UI_SMALLFONT|UI_CENTER, colorWhite ); } diff --git a/source/q3_ui/ui_demo2.c b/source/q3_ui/ui_demo2.c index 81435c0..87f3b14 100644 --- a/source/q3_ui/ui_demo2.c +++ b/source/q3_ui/ui_demo2.c @@ -170,18 +170,21 @@ static void Demos_MenuInit( void ) { s_demos.banner.color = color_white; s_demos.banner.style = UI_CENTER | UI_BIGFONT; // BFP - modified DEMOS style + // BFP - Arrow position macros +#define ART_ARROWS_X (320-ARROWS_WIDTH/2) +#define ART_ARROWS_Y 400 s_demos.arrows.generic.type = MTYPE_BITMAP; s_demos.arrows.generic.name = ART_ARROWS; s_demos.arrows.generic.flags = QMF_INACTIVE; - s_demos.arrows.generic.x = 320-ARROWS_WIDTH/2; - s_demos.arrows.generic.y = 400; + s_demos.arrows.generic.x = ART_ARROWS_X; + s_demos.arrows.generic.y = ART_ARROWS_Y; s_demos.arrows.width = ARROWS_WIDTH; s_demos.arrows.height = ARROWS_HEIGHT; s_demos.left.generic.type = MTYPE_BITMAP; s_demos.left.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS|QMF_MOUSEONLY; - s_demos.left.generic.x = 320-ARROWS_WIDTH/2; - s_demos.left.generic.y = 400; + s_demos.left.generic.x = ART_ARROWS_X; + s_demos.left.generic.y = ART_ARROWS_Y; s_demos.left.generic.id = ID_LEFT; s_demos.left.generic.callback = Demos_MenuEvent; s_demos.left.width = ARROWS_WIDTH/2; @@ -190,13 +193,15 @@ static void Demos_MenuInit( void ) { s_demos.right.generic.type = MTYPE_BITMAP; s_demos.right.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS|QMF_MOUSEONLY; - s_demos.right.generic.x = 320; - s_demos.right.generic.y = 400; + s_demos.right.generic.x = ART_ARROWS_X+61; + s_demos.right.generic.y = ART_ARROWS_Y; s_demos.right.generic.id = ID_RIGHT; s_demos.right.generic.callback = Demos_MenuEvent; s_demos.right.width = ARROWS_WIDTH/2; s_demos.right.height = ARROWS_HEIGHT; s_demos.right.focuspic = ART_ARROWRIGHT; +#undef ART_ARROWS_X +#undef ART_ARROWS_Y s_demos.back.generic.type = MTYPE_BITMAP; s_demos.back.generic.name = ART_BACK0; diff --git a/source/q3_ui/ui_mem.c b/source/q3_ui/ui_mem.c index 18d0b98..a4fd45e 100644 --- a/source/q3_ui/ui_mem.c +++ b/source/q3_ui/ui_mem.c @@ -37,7 +37,7 @@ void *UI_AllocMem( int size ) char *endptr; int *ptr; - allocsize = ( size + sizeof(int) + ROUNDBITS ) & ~ROUNDBITS; // Round to 32-byte boundary + allocsize = ( size + sizeof(int) + ROUNDBITS ) & (unsigned long)~ROUNDBITS; // Round to 32-byte boundary ptr = NULL; smallest = NULL; diff --git a/source/q3_ui/ui_playermodel.c b/source/q3_ui/ui_playermodel.c index 3989b55..ab4f3de 100644 --- a/source/q3_ui/ui_playermodel.c +++ b/source/q3_ui/ui_playermodel.c @@ -188,7 +188,7 @@ static void PlayerModel_UpdateGrid( void ) { // model/skin portrait s_playermodel.pics[i].generic.name = s_playermodel.modelnames[j]; - s_playermodel.picbuttons[i].generic.flags &= ~QMF_INACTIVE; + s_playermodel.picbuttons[i].generic.flags &= (unsigned int)~QMF_INACTIVE; } else { @@ -197,7 +197,7 @@ static void PlayerModel_UpdateGrid( void ) s_playermodel.picbuttons[i].generic.flags |= QMF_INACTIVE; } - s_playermodel.pics[i].generic.flags &= ~QMF_HIGHLIGHT; + s_playermodel.pics[i].generic.flags &= (unsigned int)~QMF_HIGHLIGHT; s_playermodel.pics[i].shader = 0; s_playermodel.picbuttons[i].generic.flags |= QMF_PULSEIFFOCUS; } @@ -208,18 +208,18 @@ static void PlayerModel_UpdateGrid( void ) i = s_playermodel.selectedmodel % MAX_MODELSPERPAGE; s_playermodel.pics[i].generic.flags |= QMF_HIGHLIGHT; - s_playermodel.picbuttons[i].generic.flags &= ~QMF_PULSEIFFOCUS; + s_playermodel.picbuttons[i].generic.flags &= (unsigned int)~QMF_PULSEIFFOCUS; } if (s_playermodel.numpages > 1) { if (s_playermodel.modelpage > 0) - s_playermodel.left.generic.flags &= ~QMF_INACTIVE; + s_playermodel.left.generic.flags &= (unsigned int)~QMF_INACTIVE; else s_playermodel.left.generic.flags |= QMF_INACTIVE; if (s_playermodel.modelpage < s_playermodel.numpages-1) - s_playermodel.right.generic.flags &= ~QMF_INACTIVE; + s_playermodel.right.generic.flags &= (unsigned int)~QMF_INACTIVE; else s_playermodel.right.generic.flags |= QMF_INACTIVE; } @@ -514,14 +514,14 @@ static void PlayerModel_PicEvent( void* ptr, int event ) for (i=0; iid - ID_PLAYERPIC0; s_playermodel.pics[i].generic.flags |= QMF_HIGHLIGHT; - s_playermodel.picbuttons[i].generic.flags &= ~QMF_PULSEIFFOCUS; + s_playermodel.picbuttons[i].generic.flags &= (unsigned int)~QMF_PULSEIFFOCUS; // get model and strip icon_ modelnum = s_playermodel.modelpage*MAX_MODELSPERPAGE + i; diff --git a/source/q3_ui/ui_players.c b/source/q3_ui/ui_players.c index f0bbe1b..317f4dc 100644 --- a/source/q3_ui/ui_players.c +++ b/source/q3_ui/ui_players.c @@ -218,8 +218,6 @@ static void UI_TorsoSequencing( playerInfo_t *pi ) { currentAnim = pi->torsoAnim & ~ANIM_TOGGLEBIT; - // BFP doesn't use TORSO_DROP animation - if ( pi->weapon != pi->currentWeapon ) { if ( currentAnim != TORSO_ATTACK0_PREPARE ) { // BFP - before TORSO_DROP pi->torsoAnimationTimer = UI_TIMER_WEAPON_SWITCH; @@ -235,26 +233,6 @@ static void UI_TorsoSequencing( playerInfo_t *pi ) { UI_SetTorsoAnim( pi, TORSO_STAND ); return; } - - if( currentAnim == TORSO_ATTACK0_PREPARE || currentAnim == TORSO_ATTACK0_STRIKE ) { - UI_SetTorsoAnim( pi, TORSO_STAND ); - return; - } - - // BFP doesn't use these animations - /* - if ( currentAnim == TORSO_DROP ) { - UI_PlayerInfo_SetWeapon( pi, pi->weapon ); - pi->torsoAnimationTimer = UI_TIMER_WEAPON_SWITCH; - UI_ForceTorsoAnim( pi, TORSO_RAISE ); - return; - } - - if ( currentAnim == TORSO_RAISE ) { - UI_SetTorsoAnim( pi, TORSO_STAND ); - return; - } - */ } diff --git a/source/q3_ui/ui_qmenu.c b/source/q3_ui/ui_qmenu.c index 9328295..e8f2c1e 100644 --- a/source/q3_ui/ui_qmenu.c +++ b/source/q3_ui/ui_qmenu.c @@ -1273,7 +1273,7 @@ void Menu_AddItem( menuframework_s *menu, void *item ) menu->items[menu->nitems] = item; ((menucommon_s*)menu->items[menu->nitems])->parent = menu; ((menucommon_s*)menu->items[menu->nitems])->menuPosition = menu->nitems; - ((menucommon_s*)menu->items[menu->nitems])->flags &= ~QMF_HASMOUSEFOCUS; + ((menucommon_s*)menu->items[menu->nitems])->flags &= (unsigned int)~QMF_HASMOUSEFOCUS; // perform any item specific initializations itemptr = (menucommon_s*)item; diff --git a/source/q3_ui/ui_servers2.c b/source/q3_ui/ui_servers2.c index bdb7e1f..645ec9e 100644 --- a/source/q3_ui/ui_servers2.c +++ b/source/q3_ui/ui_servers2.c @@ -401,14 +401,14 @@ static void ArenaServers_UpdateMenu( void ) { } else { // all servers pinged - enable controls - g_arenaservers.master.generic.flags &= ~QMF_GRAYED; - g_arenaservers.gametype.generic.flags &= ~QMF_GRAYED; - g_arenaservers.sortkey.generic.flags &= ~QMF_GRAYED; - g_arenaservers.showempty.generic.flags &= ~QMF_GRAYED; - g_arenaservers.showfull.generic.flags &= ~QMF_GRAYED; - g_arenaservers.list.generic.flags &= ~QMF_GRAYED; - g_arenaservers.refresh.generic.flags &= ~QMF_GRAYED; - g_arenaservers.go.generic.flags &= ~QMF_GRAYED; + g_arenaservers.master.generic.flags &= (unsigned int)~QMF_GRAYED; + g_arenaservers.gametype.generic.flags &= (unsigned int)~QMF_GRAYED; + g_arenaservers.sortkey.generic.flags &= (unsigned int)~QMF_GRAYED; + g_arenaservers.showempty.generic.flags &= (unsigned int)~QMF_GRAYED; + g_arenaservers.showfull.generic.flags &= (unsigned int)~QMF_GRAYED; + g_arenaservers.list.generic.flags &= (unsigned int)~QMF_GRAYED; + g_arenaservers.refresh.generic.flags &= (unsigned int)~QMF_GRAYED; + g_arenaservers.go.generic.flags &= (unsigned int)~QMF_GRAYED; // update status bar if( g_servertype == AS_GLOBAL || g_servertype == AS_MPLAYER ) { @@ -453,13 +453,13 @@ static void ArenaServers_UpdateMenu( void ) { } // end of refresh - set control state - g_arenaservers.master.generic.flags &= ~QMF_GRAYED; - g_arenaservers.gametype.generic.flags &= ~QMF_GRAYED; - g_arenaservers.sortkey.generic.flags &= ~QMF_GRAYED; - g_arenaservers.showempty.generic.flags &= ~QMF_GRAYED; - g_arenaservers.showfull.generic.flags &= ~QMF_GRAYED; + g_arenaservers.master.generic.flags &= (unsigned int)~QMF_GRAYED; + g_arenaservers.gametype.generic.flags &= (unsigned int)~QMF_GRAYED; + g_arenaservers.sortkey.generic.flags &= (unsigned int)~QMF_GRAYED; + g_arenaservers.showempty.generic.flags &= (unsigned int)~QMF_GRAYED; + g_arenaservers.showfull.generic.flags &= (unsigned int)~QMF_GRAYED; g_arenaservers.list.generic.flags |= QMF_GRAYED; - g_arenaservers.refresh.generic.flags &= ~QMF_GRAYED; + g_arenaservers.refresh.generic.flags &= (unsigned int)~QMF_GRAYED; g_arenaservers.go.generic.flags |= QMF_GRAYED; } @@ -1152,7 +1152,7 @@ int ArenaServers_SetType( int type ) // BFP - Hacky way to get the correct serve break; case AS_FAVORITES: - g_arenaservers.remove.generic.flags &= ~(QMF_INACTIVE|QMF_HIDDEN); + g_arenaservers.remove.generic.flags &= (unsigned int)~(QMF_INACTIVE|QMF_HIDDEN); g_arenaservers.serverlist = g_favoriteserverlist; g_arenaservers.numservers = &g_numfavoriteservers; g_arenaservers.maxservers = MAX_FAVORITESERVERS; @@ -1496,8 +1496,8 @@ static void ArenaServers_MenuInit( void ) { g_arenaservers.remove.generic.id = ID_REMOVE; g_arenaservers.remove.generic.x = 450; g_arenaservers.remove.generic.y = 86; - g_arenaservers.remove.width = 96; // BFP - NOTE: Originally, DELETE button uses this value. It should be 80 - g_arenaservers.remove.height = 48; // BFP - NOTE: Originally, DELETE button uses this value. It should be 80 + g_arenaservers.remove.width = 80; + g_arenaservers.remove.height = 80; g_arenaservers.remove.focuspic = ART_REMOVE1; g_arenaservers.back.generic.type = MTYPE_BITMAP; diff --git a/source/q3_ui/ui_startserver.c b/source/q3_ui/ui_startserver.c index 721acaa..9a4e9a9 100644 --- a/source/q3_ui/ui_startserver.c +++ b/source/q3_ui/ui_startserver.c @@ -173,23 +173,23 @@ static void StartServer_Update( void ) { Com_sprintf( picname[i], sizeof(picname[i]), "levelshots/%s", s_startserver.maplist[top+i] ); - s_startserver.mappics[i].generic.flags &= ~QMF_HIGHLIGHT; + s_startserver.mappics[i].generic.flags &= (unsigned int)~QMF_HIGHLIGHT; s_startserver.mappics[i].generic.name = picname[i]; s_startserver.mappics[i].shader = 0; // reset s_startserver.mapbuttons[i].generic.flags |= QMF_PULSEIFFOCUS; - s_startserver.mapbuttons[i].generic.flags &= ~QMF_INACTIVE; + s_startserver.mapbuttons[i].generic.flags &= (unsigned int)~QMF_INACTIVE; } for (; i=0 && i < MAX_MAPSPERPAGE ) { s_startserver.mappics[i].generic.flags |= QMF_HIGHLIGHT; - s_startserver.mapbuttons[i].generic.flags &= ~QMF_PULSEIFFOCUS; + s_startserver.mapbuttons[i].generic.flags &= (unsigned int)~QMF_PULSEIFFOCUS; } // set the map name @@ -907,7 +907,7 @@ static void ServerOptions_SetPlayerItems( void ) { // names if( s_serveroptions.dedicated.curvalue == 0 ) { s_serveroptions.player0.string = "Human"; - s_serveroptions.playerName[0].generic.flags &= ~QMF_HIDDEN; + s_serveroptions.playerName[0].generic.flags &= (unsigned int)~QMF_HIDDEN; start = 1; } @@ -917,7 +917,7 @@ static void ServerOptions_SetPlayerItems( void ) { } for( n = start; n < PLAYER_SLOTS; n++ ) { if( s_serveroptions.playerType[n].curvalue == 1 ) { - s_serveroptions.playerName[n].generic.flags &= ~(QMF_INACTIVE|QMF_HIDDEN); + s_serveroptions.playerName[n].generic.flags &= (unsigned int)~(QMF_INACTIVE|QMF_HIDDEN); } else { s_serveroptions.playerName[n].generic.flags |= (QMF_INACTIVE|QMF_HIDDEN); @@ -933,7 +933,7 @@ static void ServerOptions_SetPlayerItems( void ) { s_serveroptions.playerTeam[n].generic.flags |= (QMF_INACTIVE|QMF_HIDDEN); } else { - s_serveroptions.playerTeam[n].generic.flags &= ~(QMF_INACTIVE|QMF_HIDDEN); + s_serveroptions.playerTeam[n].generic.flags &= (unsigned int)~(QMF_INACTIVE|QMF_HIDDEN); } } } @@ -1741,7 +1741,7 @@ static void UI_BotSelectMenu_UpdateGrid( void ) { botSelectInfo.picnames[i].color = color_white; #endif - botSelectInfo.picbuttons[i].generic.flags &= ~QMF_INACTIVE; + botSelectInfo.picbuttons[i].generic.flags &= (unsigned int)~QMF_INACTIVE; } else { // dead slot @@ -1750,7 +1750,7 @@ static void UI_BotSelectMenu_UpdateGrid( void ) { botSelectInfo.botnames[i][0] = 0; } - botSelectInfo.pics[i].generic.flags &= ~QMF_HIGHLIGHT; + botSelectInfo.pics[i].generic.flags &= (unsigned int)~QMF_HIGHLIGHT; botSelectInfo.pics[i].shader = 0; botSelectInfo.picbuttons[i].generic.flags |= QMF_PULSEIFFOCUS; } @@ -1758,18 +1758,18 @@ static void UI_BotSelectMenu_UpdateGrid( void ) { // set selected model i = botSelectInfo.selectedmodel % MAX_MODELSPERPAGE; botSelectInfo.pics[i].generic.flags |= QMF_HIGHLIGHT; - botSelectInfo.picbuttons[i].generic.flags &= ~QMF_PULSEIFFOCUS; + botSelectInfo.picbuttons[i].generic.flags &= (unsigned int)~QMF_PULSEIFFOCUS; if( botSelectInfo.numpages > 1 ) { if( botSelectInfo.modelpage > 0 ) { - botSelectInfo.left.generic.flags &= ~QMF_INACTIVE; + botSelectInfo.left.generic.flags &= (unsigned int)~QMF_INACTIVE; } else { botSelectInfo.left.generic.flags |= QMF_INACTIVE; } if( botSelectInfo.modelpage < (botSelectInfo.numpages - 1) ) { - botSelectInfo.right.generic.flags &= ~QMF_INACTIVE; + botSelectInfo.right.generic.flags &= (unsigned int)~QMF_INACTIVE; } else { botSelectInfo.right.generic.flags |= QMF_INACTIVE; @@ -1867,14 +1867,14 @@ static void UI_BotSelectMenu_BotEvent( void* ptr, int event ) { } for( i = 0; i < (PLAYERGRID_ROWS * PLAYERGRID_COLS); i++ ) { - botSelectInfo.pics[i].generic.flags &= ~QMF_HIGHLIGHT; + botSelectInfo.pics[i].generic.flags &= (unsigned int)~QMF_HIGHLIGHT; botSelectInfo.picbuttons[i].generic.flags |= QMF_PULSEIFFOCUS; } // set selected i = ((menucommon_s*)ptr)->id; botSelectInfo.pics[i].generic.flags |= QMF_HIGHLIGHT; - botSelectInfo.picbuttons[i].generic.flags &= ~QMF_PULSEIFFOCUS; + botSelectInfo.picbuttons[i].generic.flags &= (unsigned int)~QMF_PULSEIFFOCUS; botSelectInfo.selectedmodel = botSelectInfo.modelpage * MAX_MODELSPERPAGE + i; } diff --git a/source/q3_ui/ui_video.c b/source/q3_ui/ui_video.c index 496ad23..fc70e72 100644 --- a/source/q3_ui/ui_video.c +++ b/source/q3_ui/ui_video.c @@ -388,7 +388,7 @@ static void GraphicsOptions_UpdateMenuItems( void ) } else { - s_graphicsoptions.fs.generic.flags &= ~QMF_GRAYED; + s_graphicsoptions.fs.generic.flags &= (unsigned int)~QMF_GRAYED; } if ( s_graphicsoptions.fs.curvalue == 0 || s_graphicsoptions.driver.curvalue == 1 ) @@ -398,7 +398,7 @@ static void GraphicsOptions_UpdateMenuItems( void ) } else { - s_graphicsoptions.colordepth.generic.flags &= ~QMF_GRAYED; + s_graphicsoptions.colordepth.generic.flags &= (unsigned int)~QMF_GRAYED; } if ( s_graphicsoptions.allow_extensions.curvalue == 0 ) @@ -413,43 +413,43 @@ static void GraphicsOptions_UpdateMenuItems( void ) if ( s_ivo.mode != s_graphicsoptions.mode.curvalue ) { - s_graphicsoptions.apply.generic.flags &= ~(QMF_HIDDEN|QMF_INACTIVE); + s_graphicsoptions.apply.generic.flags &= (unsigned int)~(QMF_HIDDEN|QMF_INACTIVE); } if ( s_ivo.fullscreen != s_graphicsoptions.fs.curvalue ) { - s_graphicsoptions.apply.generic.flags &= ~(QMF_HIDDEN|QMF_INACTIVE); + s_graphicsoptions.apply.generic.flags &= (unsigned int)~(QMF_HIDDEN|QMF_INACTIVE); } if ( s_ivo.extensions != s_graphicsoptions.allow_extensions.curvalue ) { - s_graphicsoptions.apply.generic.flags &= ~(QMF_HIDDEN|QMF_INACTIVE); + s_graphicsoptions.apply.generic.flags &= (unsigned int)~(QMF_HIDDEN|QMF_INACTIVE); } if ( s_ivo.tq != s_graphicsoptions.tq.curvalue ) { - s_graphicsoptions.apply.generic.flags &= ~(QMF_HIDDEN|QMF_INACTIVE); + s_graphicsoptions.apply.generic.flags &= (unsigned int)~(QMF_HIDDEN|QMF_INACTIVE); } if ( s_ivo.lighting != s_graphicsoptions.lighting.curvalue ) { - s_graphicsoptions.apply.generic.flags &= ~(QMF_HIDDEN|QMF_INACTIVE); + s_graphicsoptions.apply.generic.flags &= (unsigned int)~(QMF_HIDDEN|QMF_INACTIVE); } if ( s_ivo.colordepth != s_graphicsoptions.colordepth.curvalue ) { - s_graphicsoptions.apply.generic.flags &= ~(QMF_HIDDEN|QMF_INACTIVE); + s_graphicsoptions.apply.generic.flags &= (unsigned int)~(QMF_HIDDEN|QMF_INACTIVE); } if ( s_ivo.driver != s_graphicsoptions.driver.curvalue ) { - s_graphicsoptions.apply.generic.flags &= ~(QMF_HIDDEN|QMF_INACTIVE); + s_graphicsoptions.apply.generic.flags &= (unsigned int)~(QMF_HIDDEN|QMF_INACTIVE); } if ( s_ivo.texturebits != s_graphicsoptions.texturebits.curvalue ) { - s_graphicsoptions.apply.generic.flags &= ~(QMF_HIDDEN|QMF_INACTIVE); + s_graphicsoptions.apply.generic.flags &= (unsigned int)~(QMF_HIDDEN|QMF_INACTIVE); } if ( s_ivo.geometry != s_graphicsoptions.geometry.curvalue ) { - s_graphicsoptions.apply.generic.flags &= ~(QMF_HIDDEN|QMF_INACTIVE); + s_graphicsoptions.apply.generic.flags &= (unsigned int)~(QMF_HIDDEN|QMF_INACTIVE); } if ( s_ivo.filter != s_graphicsoptions.filter.curvalue ) { - s_graphicsoptions.apply.generic.flags &= ~(QMF_HIDDEN|QMF_INACTIVE); + s_graphicsoptions.apply.generic.flags &= (unsigned int)~(QMF_HIDDEN|QMF_INACTIVE); } GraphicsOptions_CheckConfig(); From cc25d07a76f95d7dc1041c2aca16f3a9757bad3d Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 9 Sep 2024 02:00:29 +0200 Subject: [PATCH 094/374] q3_ui: Apply pagination on SERVER INFO menu and unhide info --- source/q3_ui/ui_serverinfo.c | 164 ++++++++++++++++++++++++++++++++--- 1 file changed, 151 insertions(+), 13 deletions(-) diff --git a/source/q3_ui/ui_serverinfo.c b/source/q3_ui/ui_serverinfo.c index 4ca1268..b10c5c4 100644 --- a/source/q3_ui/ui_serverinfo.c +++ b/source/q3_ui/ui_serverinfo.c @@ -29,16 +29,33 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define SERVERINFO_BACK0 "menu/art/back_0" #define SERVERINFO_BACK1 "menu/art/back_1" +// BFP - Arrows +#define ART_ARROWS "menu/art/gs_arrows_0" +#define ART_ARROWSL "menu/art/gs_arrows_l" +#define ART_ARROWSR "menu/art/gs_arrows_r" + static char* serverinfo_artlist[] = { SERVERINFO_BACK0, SERVERINFO_BACK1, + + // BFP - Add arrows inside that + ART_ARROWS, + ART_ARROWSL, + ART_ARROWSR, NULL }; #define ID_ADD 100 #define ID_BACK 101 +// BFP - ID for arrows +#define ID_NEXT 102 +#define ID_PREV 103 + +// BFP - Lines per page +#define LINES_PER_PAGE 15 + typedef struct { menuframework_s menu; @@ -49,6 +66,11 @@ typedef struct menutext_s add; char info[MAX_INFO_STRING]; int numlines; + int currentPage; + int totalPages; + menubitmap_s arrows; + menubitmap_s next; + menubitmap_s prev; } serverinfo_t; static serverinfo_t s_serverinfo; @@ -115,6 +137,27 @@ static void ServerInfo_Event( void* ptr, int event ) UI_PopMenu(); break; + + // BFP - Prev and next events + case ID_PREV: + if (event != QM_ACTIVATED) + break; + + if (s_serverinfo.currentPage > 0) { + s_serverinfo.currentPage--; + Menu_Draw( &s_serverinfo.menu ); + } + break; + + case ID_NEXT: + if (event != QM_ACTIVATED) + break; + + if (s_serverinfo.currentPage < s_serverinfo.totalPages - 1) { + s_serverinfo.currentPage++; + Menu_Draw( &s_serverinfo.menu ); + } + break; } } @@ -129,26 +172,79 @@ static void ServerInfo_MenuDraw( void ) char key[MAX_INFO_KEY]; char value[MAX_INFO_VALUE]; int y; + // BFP - For pagination + char pageIndicator[64]; + int startLine, endLine; + int lineIndex; + int len, wrappedLen, i, j; + char wrappedValue[MAX_INFO_VALUE]; +#define LIMIT_CHARACTERS 39 + + // BFP - NOTE: On original BFP, Menu_Draw is used at the end of the function, so hides completely the server info (·_·) + // To avoid the hidden info issue, the function needs to be called at the beginning, just here: + Menu_Draw( &s_serverinfo.menu ); - y = SCREEN_HEIGHT/2 - s_serverinfo.numlines*(SMALLCHAR_HEIGHT)/2 - 20; + // BFP - NOTE: Pagination is implemented here, also looks better when the user needs to see all info avoiding letters going off the screen + + startLine = s_serverinfo.currentPage * LINES_PER_PAGE; + endLine = startLine + LINES_PER_PAGE; + if ( endLine > s_serverinfo.numlines ) + endLine = s_serverinfo.numlines; + + y = SCREEN_HEIGHT/2 - ( endLine - startLine ) * ( SMALLCHAR_HEIGHT )/2 - 20; s = s_serverinfo.info; + lineIndex = 0; + while ( s ) { Info_NextPair( &s, key, value ); if ( !key[0] ) { break; } - Q_strcat( key, MAX_INFO_KEY, ":" ); - - UI_DrawString(SCREEN_WIDTH*0.50 - 8,y,key,UI_RIGHT|UI_SMALLFONT,color_white); // BFP - modified color - UI_DrawString(SCREEN_WIDTH*0.50 + 8,y,value,UI_LEFT|UI_SMALLFONT,text_color_normal); + // show only these lines in the page + if ( lineIndex >= startLine && lineIndex < endLine ) { + Q_strcat( key, MAX_INFO_KEY, ":" ); + + UI_DrawString( SCREEN_WIDTH*0.50 - 2, y, key, UI_RIGHT|UI_SMALLFONT, color_white ); + + // wrap the value if it exceeds the limit of characters + len = strlen( value ); + wrappedLen = 0; + while ( len > 0 ) { + if ( len > LIMIT_CHARACTERS ) { + // find the last occurrence of ".", ",", "-", "_", or " " within the limit + for ( i = LIMIT_CHARACTERS; i > 0; i-- ) { + if ( value[wrappedLen + i] == '.' || value[wrappedLen + i] == ',' + || value[wrappedLen + i] == '-' || value[wrappedLen + i] == '_' + || value[wrappedLen + i] == ' ' ) { + break; + } + } + if ( i == 0 ) { + i = LIMIT_CHARACTERS; // no delimiter found, use the limit + } + // include the delimiter in the first part + strncpy( wrappedValue, value + wrappedLen, i + 1 ); + wrappedValue[i + 1] = '\0'; + wrappedLen += i + 1; + len -= i + 1; + } else { + strcpy( wrappedValue, value + wrappedLen ); + len = 0; + } + UI_DrawString( SCREEN_WIDTH*0.50 + 2, y, wrappedValue, UI_LEFT|UI_SMALLFONT, text_color_normal ); + y += SMALLCHAR_HEIGHT; + } + } - y += SMALLCHAR_HEIGHT; + lineIndex++; } - - Menu_Draw( &s_serverinfo.menu ); + Com_sprintf( pageIndicator, sizeof(pageIndicator), "Page %d of %d", s_serverinfo.currentPage + 1, s_serverinfo.totalPages ); + UI_DrawString( 320, 420, pageIndicator, UI_CENTER|UI_SMALLFONT, color_white ); } + + /* ================= ServerInfo_MenuKey @@ -229,7 +325,7 @@ void UI_ServerInfoMenu( void ) s_serverinfo.add.generic.callback = ServerInfo_Event; s_serverinfo.add.generic.id = ID_ADD; s_serverinfo.add.generic.x = 320; - s_serverinfo.add.generic.y = 400; // BFP - modified ADD TO FAVORITES button y position + s_serverinfo.add.generic.y = 450; // BFP - (originally 400 on BFP) modified ADD TO FAVORITES button y position s_serverinfo.add.string = "ADD TO FAVORITES"; s_serverinfo.add.style = UI_CENTER|UI_SMALLFONT; s_serverinfo.add.color = color_white; // BFP - modified ADD TO FAVORITES button color @@ -248,6 +344,40 @@ void UI_ServerInfoMenu( void ) s_serverinfo.back.height = 80; // BFP - modified BACK button height s_serverinfo.back.focuspic = SERVERINFO_BACK1; + // BFP - Arrows to go prev or next +#define ART_ARROWS_X 260 +#define ART_ARROWS_Y 375 + s_serverinfo.arrows.generic.type = MTYPE_BITMAP; + s_serverinfo.arrows.generic.name = ART_ARROWS; + s_serverinfo.arrows.generic.flags = QMF_INACTIVE; + s_serverinfo.arrows.generic.x = ART_ARROWS_X; + s_serverinfo.arrows.generic.y = ART_ARROWS_Y; + s_serverinfo.arrows.width = 128; + s_serverinfo.arrows.height = 32; + + s_serverinfo.prev.generic.type = MTYPE_BITMAP; + s_serverinfo.prev.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS; + s_serverinfo.prev.generic.callback = ServerInfo_Event; + s_serverinfo.prev.generic.id = ID_PREV; + s_serverinfo.prev.generic.x = ART_ARROWS_X; + s_serverinfo.prev.generic.y = ART_ARROWS_Y; + s_serverinfo.prev.width = 64; + s_serverinfo.prev.height = 32; + s_serverinfo.prev.focuspic = ART_ARROWSL; + + s_serverinfo.next.generic.type = MTYPE_BITMAP; + s_serverinfo.next.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS; + s_serverinfo.next.generic.callback = ServerInfo_Event; + s_serverinfo.next.generic.id = ID_NEXT; + s_serverinfo.next.generic.x = ART_ARROWS_X+61; + s_serverinfo.next.generic.y = ART_ARROWS_Y; + s_serverinfo.next.width = 64; + s_serverinfo.next.height = 32; + s_serverinfo.next.focuspic = ART_ARROWSR; +#undef ART_ARROWS_X +#undef ART_ARROWS_Y + // BFP - End of arrows to go prev or next ^ + trap_GetConfigString( CS_SERVERINFO, s_serverinfo.info, MAX_INFO_STRING ); s_serverinfo.numlines = 0; @@ -260,15 +390,23 @@ void UI_ServerInfoMenu( void ) s_serverinfo.numlines++; } - if (s_serverinfo.numlines > 16) - s_serverinfo.numlines = 16; + // BFP - Handle total pages + s_serverinfo.totalPages = (s_serverinfo.numlines + LINES_PER_PAGE - 1) / LINES_PER_PAGE; - Menu_AddItem( &s_serverinfo.menu, (void*) &s_serverinfo.barlog ); // BFP - barlog - // BFP - NOTE: That also happens in original BFP. Adding the background, hides completely the server info, it would be advisable to find an alternative or... remove that background hidding info issue (·_·) Menu_AddItem( &s_serverinfo.menu, (void*) &s_serverinfo.menubg ); // BFP - Menu background + Menu_AddItem( &s_serverinfo.menu, (void*) &s_serverinfo.barlog ); // BFP - barlog Menu_AddItem( &s_serverinfo.menu, (void*) &s_serverinfo.banner ); Menu_AddItem( &s_serverinfo.menu, (void*) &s_serverinfo.add ); Menu_AddItem( &s_serverinfo.menu, (void*) &s_serverinfo.back ); + // BFP - Arrows to handle the pages + Menu_AddItem( &s_serverinfo.menu, (void*) &s_serverinfo.arrows ); + if ( s_serverinfo.totalPages > 1 ) { + Menu_AddItem( &s_serverinfo.menu, (void*) &s_serverinfo.next ); + Menu_AddItem( &s_serverinfo.menu, (void*) &s_serverinfo.prev ); + } + + // BFP - Initialize the current page to zero + s_serverinfo.currentPage = 0; UI_PushMenu( &s_serverinfo.menu ); } From 46b0f7d5d51ad40e5489992e91ac2b48af39d7c4 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 9 Sep 2024 02:25:01 +0200 Subject: [PATCH 095/374] q3_ui: Add aura type option for sprite aura on BFP OPTIONS menu and cleanup a bit --- source/q3_ui/ui_bfpoptions.c | 45 ++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/source/q3_ui/ui_bfpoptions.c b/source/q3_ui/ui_bfpoptions.c index 88061b0..6ffb4d9 100644 --- a/source/q3_ui/ui_bfpoptions.c +++ b/source/q3_ui/ui_bfpoptions.c @@ -26,7 +26,7 @@ BFP OPTIONS MENU #define ID_DYNEXPLOLIGHT 144 #define ID_KITRAILENGTH 145 #define ID_BEAMCMPXY 146 -#define ID_TRANSAURA 147 +#define ID_TRANSFORMATIONAURA 147 #define ID_SMALLAURA 148 #define ID_SSJGLOW 149 #define ID_ACCUCROSSHAIR 150 @@ -41,10 +41,11 @@ BFP OPTIONS MENU #define ID_BACK 159 // Macros to handle the cases in that order -#define SHADER_AURA 0 -#define LIGHTWEIGHT_AURA 1 -#define POLYGON_AURA 2 -#define HIGHPOLYCOUNT_AURA 3 +#define SPRITE_AURA 0 +#define SHADER_AURA 1 +#define LIGHTWEIGHT_AURA 2 +#define POLYGON_AURA 3 +#define HIGHPOLYCOUNT_AURA 4 #define WIMPY_EXPLO 0 #define WEAK_EXPLO 1 @@ -52,6 +53,7 @@ BFP OPTIONS MENU #define HARDCORE_EXPLO 3 static const char *auratype_items[] = { + "Sprite Aura", "Shader Aura", "Lightweight Aura", "Polygonal Aura", @@ -133,7 +135,8 @@ static void BFPOptions_SetMenuItems( void ) { #undef BFPOPTIONS_MENUITEM // Macros to look better the code -#define AURATYPE_SETUP(highpoly, poly, light) \ +#define AURATYPE_SETUP(sprite, highpoly, poly, light) \ + trap_Cvar_SetValue( "cg_spriteAura", sprite ); \ trap_Cvar_SetValue( "cg_highPolyAura", highpoly ); \ trap_Cvar_SetValue( "cg_polygonAura", poly ); \ trap_Cvar_SetValue( "cg_lightweightAuras", light ); @@ -160,20 +163,24 @@ static void BFPOptions_Event( void* ptr, int notification ) { case ID_AURATYPE: switch ( s_bfpoptions.auratype.curvalue ) { - case SHADER_AURA: // Shader Aura - AURATYPE_SETUP( 0, 0, 0 ) + case SPRITE_AURA: + AURATYPE_SETUP( 1, 0, 0, 0 ) break; - case LIGHTWEIGHT_AURA: // Lightweight Aura - AURATYPE_SETUP( 0, 0, 1 ) + case SHADER_AURA: + AURATYPE_SETUP( 0, 0, 0, 0 ) break; - case POLYGON_AURA: // Polygonal Aura - AURATYPE_SETUP( 0, 1, 0 ) + case LIGHTWEIGHT_AURA: + AURATYPE_SETUP( 0, 0, 0, 1 ) break; - case HIGHPOLYCOUNT_AURA: // High Polycount Aura - AURATYPE_SETUP( 1, 1, 0 ) + case POLYGON_AURA: + AURATYPE_SETUP( 0, 0, 1, 0 ) + break; + + case HIGHPOLYCOUNT_AURA: + AURATYPE_SETUP( 0, 1, 1, 0 ) break; } break; @@ -251,7 +258,7 @@ static void BFPOptions_Event( void* ptr, int notification ) { //-----------------------------------------------------------------------// - case ID_TRANSAURA: + case ID_TRANSFORMATIONAURA: trap_Cvar_SetValue( "cg_transformationAura", s_bfpoptions.transaura.curvalue ); break; @@ -311,7 +318,7 @@ static void BFPOptions_Event( void* ptr, int notification ) { static void BFPOptions_MenuInit( void ) { int y; - int highpolyaura, polygonalaura, lightweightaura; + int highpolyaura, polygonalaura, lightweightaura, spriteaura; int thirdperson, firstpersonvis; int explosionShell, explosionSmoke; int explosionring; @@ -441,7 +448,7 @@ static void BFPOptions_MenuInit( void ) { s_bfpoptions.transaura.generic.name = "Transformation Aura:"; s_bfpoptions.transaura.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; s_bfpoptions.transaura.generic.callback = BFPOptions_Event; - s_bfpoptions.transaura.generic.id = ID_TRANSAURA; + s_bfpoptions.transaura.generic.id = ID_TRANSFORMATIONAURA; s_bfpoptions.transaura.generic.x = BFPOPTIONS_X_POS; s_bfpoptions.transaura.generic.y = y; @@ -586,6 +593,7 @@ static void BFPOptions_MenuInit( void ) { highpolyaura = trap_Cvar_VariableValue( "cg_highPolyAura" ); polygonalaura = trap_Cvar_VariableValue( "cg_polygonAura" ); lightweightaura = trap_Cvar_VariableValue( "cg_lightweightAuras" ); + spriteaura = trap_Cvar_VariableValue( "cg_spriteAura" ); if ( highpolyaura >= 1 ) { s_bfpoptions.auratype.curvalue = HIGHPOLYCOUNT_AURA; @@ -593,6 +601,8 @@ static void BFPOptions_MenuInit( void ) { s_bfpoptions.auratype.curvalue = POLYGON_AURA; } else if ( lightweightaura >= 1 ) { s_bfpoptions.auratype.curvalue = LIGHTWEIGHT_AURA; + } else if ( spriteaura >= 1 ) { + s_bfpoptions.auratype.curvalue = SPRITE_AURA; } else { s_bfpoptions.auratype.curvalue = SHADER_AURA; } @@ -637,6 +647,7 @@ static void BFPOptions_MenuInit( void ) { BFPOptions_SetMenuItems(); } +#undef SPRITE_AURA #undef SHADER_AURA #undef LIGHTWEIGHT_AURA #undef POLYGON_AURA From 0f82f756b09c26cc57af645cc04ce8896579efd8 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 9 Sep 2024 02:25:02 +0200 Subject: [PATCH 096/374] Add info about differences from replica and original --- README.md | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/README.md b/README.md index 8ff2f4a..1b2c5ab 100644 --- a/README.md +++ b/README.md @@ -95,6 +95,7 @@ Click here to see the [Old PyroFragger dev journal (Markdown edition)](docs/pyro We're making a replica of the lost source code.
The highest priority goal is to copy and recreate the complete logical structure of the BFP game. It would be a game SDK that'll provide a structured and standardized way to modify the mod.
+You'll notice some differences that the original Bid For Power didn't have, such as some adjusted UI buttons, sprite aura type option in BFP options menu, server info menu has pagination and displays info, ...
Any fixes, improvements and contributions are welcome. But we can't accept secondary things and other stuff that don't reach the goals. ### References and clues to know how should be the game @@ -132,18 +133,6 @@ _**Click on some image to see it complete**._
-- When player receives a hit stun (`g_hitStun 1`): - -hit_stun_received - -
- -- When player is being ready to shot (holding a key): - -ready_to_attack - -
- - **cfg files**: A sample inside `models/players/player_name/default.cfg`: From bc6edc65e922e88a9d11d52aec2ee45b5951e3f7 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Fri, 13 Sep 2024 22:48:54 +0200 Subject: [PATCH 097/374] cgame: Implement particle aura and encapsulate sprite aura into a function --- source/cgame/cg_cvar.h | 1 + source/cgame/cg_local.h | 3 ++ source/cgame/cg_particles.c | 94 +++++++++++++++++++++++++++++++-- source/cgame/cg_players.c | 100 +++++++++++++++++++++++++----------- 4 files changed, 164 insertions(+), 34 deletions(-) diff --git a/source/cgame/cg_cvar.h b/source/cgame/cg_cvar.h index f7aa5ea..71d22cf 100644 --- a/source/cgame/cg_cvar.h +++ b/source/cgame/cg_cvar.h @@ -77,6 +77,7 @@ CG_CVAR( cg_drawOwnModel, "cg_drawOwnModel", "1", CVAR_ARCHIVE ) // BFP - toggle CG_CVAR( cg_drawKiWarning, "cg_drawKiWarning", "1", CVAR_ARCHIVE ) // BFP - Ki warning CG_CVAR( cg_stableCrosshair, "cg_stableCrosshair", "0", CVAR_ARCHIVE ) // BFP - Accurate crosshair CG_CVAR( cg_spriteAura, "cg_spriteAura", "0", CVAR_ARCHIVE ) // BFP - Sprite aura +CG_CVAR( cg_particleAura, "cg_particleAura", "0", CVAR_ARCHIVE ) // BFP - Particle aura CG_CVAR( cg_lightAuras, "cg_lightAuras", "1", CVAR_ARCHIVE ) // BFP - Light auras CG_CVAR( cg_smallOwnAura, "cg_smallOwnAura", "0", CVAR_ARCHIVE ) // BFP - Small own aura CG_CVAR( cg_lightweightAuras, "cg_lightweightAuras", "0", CVAR_ARCHIVE ) // BFP - Lightweight auras diff --git a/source/cgame/cg_local.h b/source/cgame/cg_local.h index d68e182..2ce28b0 100644 --- a/source/cgame/cg_local.h +++ b/source/cgame/cg_local.h @@ -1519,6 +1519,9 @@ void CG_ParticleDashSmoke (centity_t *cent, qhandle_t pshader, vec3_t origin); // BFP - Antigrav rock particles for charging void CG_ParticleAntigravRock (qhandle_t pshader, centity_t *cent, vec3_t origin); void CG_AntigravRockHandling (centity_t *cent); +// BFP - Particle aura +void CG_ParticleAura (centity_t *cent, int entityNum, qhandle_t pshader, vec3_t origin, vec3_t origin2, float range); +void CG_ParticleAuraHandling (centity_t *cent); // BFP - Unused particle stuff, saved for later :P #if 0 diff --git a/source/cgame/cg_particles.c b/source/cgame/cg_particles.c index ae4332f..08a3fd5 100644 --- a/source/cgame/cg_particles.c +++ b/source/cgame/cg_particles.c @@ -65,6 +65,9 @@ typedef struct particle_s int accumroll; + // BFP - Entity num + int entityNum; + } cparticle_t; typedef enum @@ -77,6 +80,7 @@ typedef enum P_SMOKE_IMPACT, P_BUBBLE, P_BUBBLE_TURBULENT, + P_AURA, // BFP - Particle aura P_SPRITE // BFP - Unused particle types, saved for later :P #if 0 @@ -315,7 +319,8 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) } else if (p->type == P_SMOKE || p->type == P_SMOKE_IMPACT || p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT // BFP - Bubble types moved here for better management - || p->type == P_ANTIGRAV_ROCK) // BFP - Added antigrav rock type + || p->type == P_ANTIGRAV_ROCK // BFP - Added antigrav rock type + || p->type == P_AURA) // BFP - Particle aura {// create a front rotating facing polygon // BFP - No smoke distance @@ -373,7 +378,8 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) width = p->width + ( ratio * ( p->endwidth - p->width) ); height = p->height + ( ratio * ( p->endheight - p->height) ); - if (p->type != P_SMOKE_IMPACT) + if (p->type != P_SMOKE_IMPACT + && p->type != P_AURA) // BFP - Don't apply for P_AURA particle position { vec3_t temp; @@ -775,7 +781,8 @@ void CG_AddParticles (void) || p->type == P_WEATHER_FLURRY || p->type == P_FLAT_SCALEUP_FADE #endif || p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT // BFP - Add P_BUBBLE types to remove particles - || p->type == P_ANTIGRAV_ROCK) // BFP - Add P_ANTIGRAV_ROCK to remove particles + || p->type == P_ANTIGRAV_ROCK // BFP - Add P_ANTIGRAV_ROCK to remove particles + || p->type == P_AURA) // BFP - Add P_AURA to remove particles { if (timenonscaled > p->endtime) { @@ -1118,6 +1125,87 @@ void CG_AntigravRockHandling (centity_t *cent) } } +// BFP - Particle aura +void CG_ParticleAura (centity_t *cent, int entityNum, qhandle_t pshader, vec3_t origin, vec3_t origin2, float range) +{ + cparticle_t *p; + + // if (!pshader) CG_Printf ("CG_ParticleAura pshader == ZERO!\n"); + + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + p->time = timenonscaled; + + // BFP - Keep entity number to identify who is using + p->entityNum = entityNum; + + // BFP - Add end time to remove particles, if there's no end time the particles will remain there + p->endtime = timenonscaled + 400; + p->startfade = timenonscaled + 200; + + p->color = 0; + p->alpha = 0.5; + p->alphavel = -0.075; + + // BFP - Apply to player's origin + p->start = cent->currentState.origin[2]; + p->end = cent->currentState.origin2[2]; + p->pshader = pshader; + p->height = p->width = 40; + + VectorCopy(origin, p->org); + + p->type = P_AURA; + + p->org[0] += (crandom() * range); + p->org[1] += (crandom() * range); + p->org[2] += (crandom() * 5); + + VectorSet( p->vel, + (rand() % 621) - 250, + (rand() % 621) - 250, + 100 ); + + // dispersion + VectorSet( p->accel, + crandom() * 20, + crandom() * 20, + 1200 ); + + p->link = qfalse; +} + +// BFP - To handle the client side visuals of aura particle +void CG_ParticleAuraHandling (centity_t *cent) +{ + cparticle_t *p, *next; + + for (p=active_particles ; p ; p=next) + { + next = p->next; + if ( p->type != P_AURA ) continue; + + if ( p->entityNum == cent->currentState.clientNum + && !( cent->currentState.eFlags & EF_DEAD ) + && !( cent->currentState.eFlags & EF_AURA ) ) + { + // BFP - Make each particle fall when there's no aura at this moment + if (!p->link) + { + p->alphavel = -0.03; + p->accel[0] = 0; + p->accel[1] = 0; + p->endtime = timenonscaled + 600; + p->link = qtrue; + } + } + } +} + void CG_ParticleSmoke (qhandle_t pshader, centity_t *cent) { diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index a1d03d3..d819002 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -2134,15 +2134,16 @@ void CG_AddRefEntityWithPowerups( refEntity_t ent, entityState_t *state, int tea if ( ( cg_lightweightAuras.integer > 0 || ( state->clientNum == cg.snap->ps.clientNum && cg_smallOwnAura.integer > 0 ) ) - && cg_spriteAura.integer <= 0 ) { + && cg_spriteAura.integer <= 0 + && cg_particleAura.integer <= 0 ) { trap_R_AddRefEntityToScene( &ent ); } // BFP - TODO: Shader aura if ( cg_lightweightAuras.integer <= 0 && cg_polygonAura.integer <= 0 - && cg_highPolyAura.integer <= 0 && cg_spriteAura.integer <= 0 + && cg_particleAura.integer <= 0 && ( state->clientNum == cg.snap->ps.clientNum && cg_smallOwnAura.integer <= 0 ) ) { MODEL_SIZE ( ent, 1.2f ) @@ -2151,6 +2152,43 @@ void CG_AddRefEntityWithPowerups( refEntity_t ent, entityState_t *state, int tea } } +/* +============ +CG_SpriteAura + +Adds sprite aura, just one quad +============ +*/ +static void CG_SpriteAura( refEntity_t aura ) { // BFP - Sprite aura + // BFP - NOTE: What shader was added?? Originally, BFP didn't finish the shader to attach or they forgot... + // That radius looks a bit big for an aura, maybe they thought to fit the texture that way or some circular aura? + // And... What the heck? This sprite view depends of pitch angle until some client connects? + // Also when cg_smallOwnAura cvar is enabled, it doesn't display any aura to the client itself. + // Moreover, the lights are disabled as mentioned previously in AURA_LIGHT macro comments + // In the future, the shader should be added, not sure what kind of aura is this... + float pitchView = cg.refdefViewAngles[PITCH]; + int i, connectedClients = 1; + + for ( i = 0; i < MAX_CLIENTS; i++ ) { + if ( cg_entities[i].currentValid ) { + connectedClients++; + } + } + aura.reType = RT_SPRITE; + aura.customShader = 0; + aura.radius = 75; + if ( connectedClients > 1 ) { + pitchView = -15; + } + aura.rotation = pitchView; + + aura.shaderRGBA[0] = 255; + aura.shaderRGBA[1] = 255; + aura.shaderRGBA[2] = 255; + aura.shaderRGBA[3] = 255; + trap_R_AddRefEntityToScene( &aura ); +} + /* ============ @@ -2201,7 +2239,7 @@ static void CG_Aura( centity_t *cent, int clientNum, clientInfo_t *ci, int rende // BFP - NOTE: Originally, if cg_spriteAura is on, the lights aren't displayed. // But that should be removed in the future and just keep cg_lightAuras conditional #define AURA_LIGHT(r, g, b) \ - if ( cg_lightAuras.integer > 0 && cg_spriteAura.integer <= 0 ) { \ + if ( cg_lightAuras.integer > 0 && cg_spriteAura.integer <= 0 && cg_particleAura.integer <= 0 ) { \ if ( clientNum == cg.snap->ps.clientNum && cg_smallOwnAura.integer > 0 ) { \ trap_R_AddLightToScene( cent->lerpOrigin, 200, r, g, b ); \ trap_R_AddLightToScene( cent->lerpOrigin, 200, r, g, b ); \ @@ -2338,45 +2376,42 @@ static void CG_Aura( centity_t *cent, int clientNum, clientInfo_t *ci, int rende // BFP - Sprite aura if ( ( cg_spriteAura.integer > 0 && cg_smallOwnAura.integer <= 0 ) || ( cg_spriteAura.integer > 0 && cg_smallOwnAura.integer > 0 && clientNum != cg.snap->ps.clientNum ) ) { - // BFP - NOTE: What shader was added?? Originally, BFP didn't finish the shader to attach or they forgot... - // That radius looks a bit big for an aura, maybe they thought to fit the texture that way or some circular aura? - // And... What the heck? This sprite view depends of pitch angle until some client connects? - // Also when cg_smallOwnAura cvar is enabled, it doesn't display any aura to the client itself. - // Moreover, the lights are disabled as mentioned previously in AURA_LIGHT macro comments - // In the future, the shader should be added, not sure what kind of aura is this... - float pitchView = cg.refdefViewAngles[PITCH]; - int i, connectedClients = 1; - - for ( i = 0; i < MAX_CLIENTS; i++ ) { - if ( cg_entities[i].currentValid ) { - connectedClients++; - } - } - aura.reType = RT_SPRITE; - aura.customShader = 0; - aura.radius = 75; - if ( connectedClients > 1 ) { - pitchView = -15; - } - aura.rotation = pitchView; + CG_SpriteAura( aura ); + return; + } - aura.shaderRGBA[0] = 255; - aura.shaderRGBA[1] = 255; - aura.shaderRGBA[2] = 255; - aura.shaderRGBA[3] = 255; - trap_R_AddRefEntityToScene( &aura ); + // BFP - Particle aura + if ( ( cg_particleAura.integer > 0 && cg_smallOwnAura.integer <= 0 ) + || ( cg_particleAura.integer > 0 && cg_smallOwnAura.integer > 0 && clientNum != cg.snap->ps.clientNum ) ) { + // BFP - NOTE: Particle aura wasn't fully implemented on original BFP. + // Originally, particle aura wasn't correctly placed on player's origin, it was zeroed and + // when the player moves up, the aura was moving to right, and when moves down, it was moving to left; + // moreover, spawns too many particles; also the shader uses bubble ones and the particle size is a bit big. + // It's unknown what they planned in their future. + // But this time, it's placed to player's origin like when being underwater, more fading is added, + // also it doesn't spawn too many particles. + // In the future, that should be tweaked, bubble shader doesn't seem to fit well. + vec3_t pAuraOrigin; + VectorCopy( legs.origin, pAuraOrigin ); + + pAuraOrigin[2] += -18; // put the origin a little below + + CG_ParticleAura( cent, clientNum, cgs.media.waterBubbleShader, pAuraOrigin, NULL, 20 ); + CG_ParticleAura( cent, clientNum, cgs.media.waterBubbleShader, pAuraOrigin, NULL, 20 ); return; } // BFP - Small own aura only can be shown to the one who enables it for themself, not everyone if ( clientNum != cg.snap->ps.clientNum || cg_smallOwnAura.integer <= 0 ) { // add aura - if ( cg_spriteAura.integer <= 0 && cg_polygonAura.integer > 0 && cg_lightweightAuras.integer <= 0 ) { + if ( cg_spriteAura.integer <= 0 && cg_particleAura.integer <= 0 + && cg_polygonAura.integer > 0 && cg_lightweightAuras.integer <= 0 ) { trap_R_AddRefEntityToScene( &aura ); } // add secondary aura to make look cooler, a bit bigger than the other - if ( cg_spriteAura.integer <= 0 && cg_polygonAura.integer > 0 && cg_highPolyAura.integer > 0 && cg_lightweightAuras.integer <= 0 ) { + if ( cg_spriteAura.integer <= 0 && cg_particleAura.integer <= 0 + && cg_polygonAura.integer > 0 && cg_highPolyAura.integer > 0 && cg_lightweightAuras.integer <= 0 ) { trap_R_AddRefEntityToScene( &aura2 ); } } @@ -2508,6 +2543,9 @@ void CG_Player( centity_t *cent ) { // BFP - Handle the antigrav rock particles when the player is charging CG_AntigravRockHandling( cent ); + // BFP - Handle particle aura + CG_ParticleAuraHandling( cent ); + // add a water splash if partially in and out of water CG_PlayerSplash( cent ); From 11a46dc1079f8b6dcc4d9c0de4f7f74e90e1c2d0 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Fri, 13 Sep 2024 23:14:09 +0200 Subject: [PATCH 098/374] q3_ui: Add Particle Aura type option and sort aura types correctly --- source/q3_ui/ui_bfpoptions.c | 42 ++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/source/q3_ui/ui_bfpoptions.c b/source/q3_ui/ui_bfpoptions.c index 6ffb4d9..bac99cb 100644 --- a/source/q3_ui/ui_bfpoptions.c +++ b/source/q3_ui/ui_bfpoptions.c @@ -42,10 +42,11 @@ BFP OPTIONS MENU // Macros to handle the cases in that order #define SPRITE_AURA 0 -#define SHADER_AURA 1 -#define LIGHTWEIGHT_AURA 2 -#define POLYGON_AURA 3 -#define HIGHPOLYCOUNT_AURA 4 +#define LIGHTWEIGHT_AURA 1 +#define POLYGON_AURA 2 +#define HIGHPOLYCOUNT_AURA 3 +#define PARTICLE_AURA 4 +#define SHADER_AURA 5 #define WIMPY_EXPLO 0 #define WEAK_EXPLO 1 @@ -54,10 +55,11 @@ BFP OPTIONS MENU static const char *auratype_items[] = { "Sprite Aura", - "Shader Aura", "Lightweight Aura", "Polygonal Aura", "High Polycount Aura", + "Particle Aura (Particle Effects only)", + "Shader Aura", NULL }; @@ -135,11 +137,12 @@ static void BFPOptions_SetMenuItems( void ) { #undef BFPOPTIONS_MENUITEM // Macros to look better the code -#define AURATYPE_SETUP(sprite, highpoly, poly, light) \ +#define AURATYPE_SETUP(sprite, highpoly, poly, light, particle) \ trap_Cvar_SetValue( "cg_spriteAura", sprite ); \ trap_Cvar_SetValue( "cg_highPolyAura", highpoly ); \ trap_Cvar_SetValue( "cg_polygonAura", poly ); \ - trap_Cvar_SetValue( "cg_lightweightAuras", light ); + trap_Cvar_SetValue( "cg_lightweightAuras", light );\ + trap_Cvar_SetValue( "cg_particleAura", particle ); #define VIEWPOINT_SETUP(tp, ownmodel) \ trap_Cvar_SetValue( "cg_thirdPerson", tp ); \ @@ -164,23 +167,27 @@ static void BFPOptions_Event( void* ptr, int notification ) { case ID_AURATYPE: switch ( s_bfpoptions.auratype.curvalue ) { case SPRITE_AURA: - AURATYPE_SETUP( 1, 0, 0, 0 ) - break; - - case SHADER_AURA: - AURATYPE_SETUP( 0, 0, 0, 0 ) + AURATYPE_SETUP( 1, 0, 0, 0, 0 ) break; case LIGHTWEIGHT_AURA: - AURATYPE_SETUP( 0, 0, 0, 1 ) + AURATYPE_SETUP( 0, 0, 0, 1, 0 ) break; case POLYGON_AURA: - AURATYPE_SETUP( 0, 0, 1, 0 ) + AURATYPE_SETUP( 0, 0, 1, 0, 0 ) break; case HIGHPOLYCOUNT_AURA: - AURATYPE_SETUP( 0, 1, 1, 0 ) + AURATYPE_SETUP( 0, 1, 1, 0, 0 ) + break; + + case PARTICLE_AURA: + AURATYPE_SETUP( 0, 0, 0, 0, 1 ) + break; + + case SHADER_AURA: + AURATYPE_SETUP( 0, 0, 0, 0, 0 ) break; } break; @@ -318,7 +325,7 @@ static void BFPOptions_Event( void* ptr, int notification ) { static void BFPOptions_MenuInit( void ) { int y; - int highpolyaura, polygonalaura, lightweightaura, spriteaura; + int highpolyaura, polygonalaura, lightweightaura, spriteaura, particleaura; int thirdperson, firstpersonvis; int explosionShell, explosionSmoke; int explosionring; @@ -594,6 +601,7 @@ static void BFPOptions_MenuInit( void ) { polygonalaura = trap_Cvar_VariableValue( "cg_polygonAura" ); lightweightaura = trap_Cvar_VariableValue( "cg_lightweightAuras" ); spriteaura = trap_Cvar_VariableValue( "cg_spriteAura" ); + particleaura = trap_Cvar_VariableValue( "cg_particleAura" ); if ( highpolyaura >= 1 ) { s_bfpoptions.auratype.curvalue = HIGHPOLYCOUNT_AURA; @@ -603,6 +611,8 @@ static void BFPOptions_MenuInit( void ) { s_bfpoptions.auratype.curvalue = LIGHTWEIGHT_AURA; } else if ( spriteaura >= 1 ) { s_bfpoptions.auratype.curvalue = SPRITE_AURA; + } else if ( particleaura >= 1 ) { + s_bfpoptions.auratype.curvalue = PARTICLE_AURA; } else { s_bfpoptions.auratype.curvalue = SHADER_AURA; } From b8e47c89bd11bac024ddab65c1075400adce7467 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Fri, 13 Sep 2024 23:14:09 +0200 Subject: [PATCH 099/374] Mark aura tasks as done --- README.md | 3 ++- docs/bfp_cvars_task.md | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1b2c5ab..5743aec 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,7 @@ A legendary 90s era Quake 3 Arena mod. - [x] ~~Breakable map entities ("func_breakable")~~ - [x] ~~Ki trails (use ki to move, cg_kiTrail >10 )~~ - [x] ~~Instant character model changing~~ +- [x] ~~Auras~~ - [ ] Make ki energy regeneration, ki use, attacks, charging balance indicated on old docs - [ ] Powerlevel and Power Tiers indicated on old docs - [x] ~~Hit Stun (makes player can't use ki, melee, block and charge)~~ @@ -95,7 +96,7 @@ Click here to see the [Old PyroFragger dev journal (Markdown edition)](docs/pyro We're making a replica of the lost source code.
The highest priority goal is to copy and recreate the complete logical structure of the BFP game. It would be a game SDK that'll provide a structured and standardized way to modify the mod.
-You'll notice some differences that the original Bid For Power didn't have, such as some adjusted UI buttons, sprite aura type option in BFP options menu, server info menu has pagination and displays info, ...
+You'll notice some differences that the original Bid For Power didn't have, such as some adjusted UI buttons, sprite and particle aura type options in BFP options menu, server info menu has pagination and displays info, particle aura is almost implemented, ...
Any fixes, improvements and contributions are welcome. But we can't accept secondary things and other stuff that don't reach the goals. ### References and clues to know how should be the game diff --git a/docs/bfp_cvars_task.md b/docs/bfp_cvars_task.md index 4f643fb..d820e4a 100644 --- a/docs/bfp_cvars_task.md +++ b/docs/bfp_cvars_task.md @@ -35,12 +35,11 @@ - cg_stfu [0/1]: disable character voices when firing attacks. - cg_lowpolysphere [0/1]: force the use of a lower polycount sphere. -- cg_lightexplosions [0/1]: turn on or off the explosion dynamic lights. +- cg_lightExplosions [0/1]: turn on or off the explosion dynamic lights. - cg_chargeupAlert [0/1]: turn on or off the "ready" message when charging attacks. - cg_explosionShell [0/1]: turn on or off the explosion shell. - cg_explosionSmoke [0/1]: turn on or off the explosion smoke. - cg_explosionRing [0/1]: turn on or off the explosion ring. -- cg_particles [0/1]: turn on or off particle effects. ## COMPLETED: @@ -57,11 +56,14 @@ - [x] ~~cg_crosshairHealth~~ - [x] ~~cg_flytilt~~ - [x] ~~cg_drawKiWarning~~ +- [x] ~~cg_particles~~ - [x] ~~cg_lightAuras~~ - [x] ~~cg_smallOwnAura~~ - [x] ~~cg_lightweightAuras~~ - [x] ~~cg_polygonAura~~ - [x] ~~cg_highPolyAura~~ +- [x] ~~cg_spriteAura~~ +- [x] ~~cg_particleAura~~ - [x] ~~cg_playHitSound~~ - [x] ~~g_noFlight (disables "fly" bind too, original BFP has a leak though)~~ - [x] ~~g_blockLength~~ From 2e614095c9a421d790a4b61c268a198a58675bb5 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sat, 14 Sep 2024 00:33:36 +0200 Subject: [PATCH 100/374] cgame: Fix antigrav rock particles when staying suspended in air after few bounces, now bounces are physically correct, apply entityNum check for antigrav rock particles and fix dash smoke particles aren't spawning when toggling ki boost --- source/cgame/cg_local.h | 2 +- source/cgame/cg_particles.c | 44 +++++++++++++++++-------------------- source/cgame/cg_players.c | 11 +++++----- 3 files changed, 26 insertions(+), 31 deletions(-) diff --git a/source/cgame/cg_local.h b/source/cgame/cg_local.h index 2ce28b0..cfc521f 100644 --- a/source/cgame/cg_local.h +++ b/source/cgame/cg_local.h @@ -1517,7 +1517,7 @@ void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_ // BFP - Dash smoke particle for ki boost when moving in the ground void CG_ParticleDashSmoke (centity_t *cent, qhandle_t pshader, vec3_t origin); // BFP - Antigrav rock particles for charging -void CG_ParticleAntigravRock (qhandle_t pshader, centity_t *cent, vec3_t origin); +void CG_ParticleAntigravRock (qhandle_t pshader, centity_t *cent, int entityNum, vec3_t origin); void CG_AntigravRockHandling (centity_t *cent); // BFP - Particle aura void CG_ParticleAura (centity_t *cent, int entityNum, qhandle_t pshader, vec3_t origin, vec3_t origin2, float range); diff --git a/source/cgame/cg_particles.c b/source/cgame/cg_particles.c index 08a3fd5..67152ec 100644 --- a/source/cgame/cg_particles.c +++ b/source/cgame/cg_particles.c @@ -418,8 +418,9 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) { // BFP - To detect if there is something solid trace_t trace; + vec3_t rockPos = {0, 0, -1}; // place a bit above // contents should be CONTENTS_SOLID, so the particles don't touch any entity like the player - CG_Trace( &trace, p->org, vec3_origin, vec3_origin, org, -1, CONTENTS_SOLID ); + CG_Trace( &trace, p->org, rockPos, rockPos, org, -1, CONTENTS_SOLID ); p->time = timenonscaled; p->snum = 1; // handle the p->snum when already entered in this phase for correction of client side visuals @@ -428,7 +429,7 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) p->accel[0] = 0; p->accel[1] = 0; // not hit anything or not a collider - if ( trace.fraction == 1.0f && p->roll > 0 ) + if ( trace.fraction == 1.0f ) { VectorCopy (org, p->org); p->vel[2] -= 50; @@ -436,15 +437,17 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) } else // bouncing { - // BFP - TODO: Temporary solution... Make bouncing more interactive when there's a mover moving // if the particle is touching a mover and moves down, so keep bouncing if ( trace.fraction <= 0 ) { - p->roll = 16; + p->roll = 6; } else { p->vel[2] = p->accel[2] = (p->roll > 0) ? 50 * p->roll : 0; p->roll--; // that decreases bounces } } + if ( p->roll <= 0 ) { // keep detecting the position + VectorCopy (trace.endpos, p->org); + } } // BFP - When reaching into this top, remove the particle! @@ -1027,7 +1030,7 @@ void CG_ParticleDashSmoke (centity_t *cent, qhandle_t pshader, vec3_t origin) } // BFP - Antigrav rock particles for ki charging status -void CG_ParticleAntigravRock (qhandle_t pshader, centity_t *cent, vec3_t origin) +void CG_ParticleAntigravRock (qhandle_t pshader, centity_t *cent, int entityNum, vec3_t origin) { cparticle_t *p; @@ -1052,6 +1055,9 @@ void CG_ParticleAntigravRock (qhandle_t pshader, centity_t *cent, vec3_t origin) active_particles = p; p->time = timenonscaled; + // BFP - Keep entity number to identify who is using + p->entityNum = entityNum; + p->endtime = timenonscaled + 450 + (crandom() * 20); p->color = 0; @@ -1099,27 +1105,17 @@ void CG_AntigravRockHandling (centity_t *cent) for (p=active_particles ; p ; p=next) { next = p->next; - if (p->type == P_ANTIGRAV_ROCK) + if ( p->type != P_ANTIGRAV_ROCK ) continue; + + if ( p->entityNum == cent->currentState.clientNum + && !( cent->currentState.eFlags & EF_DEAD ) + && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_CHARGE ) { - if ( cent->currentState.clientNum == cg.snap->ps.clientNum - && !( cent->currentState.eFlags & EF_DEAD ) - && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_CHARGE ) + // BFP - Make each particle fall when they aren't on ki charging status + if (!p->link) { - // BFP - Make each particle fall when they aren't on ki charging status - if (!p->link && !p->snum) // to handle the client side visuals - { - p->endtime = timenonscaled + 1650; - p->link = qtrue; - } - } - // if the player sees the other player doing that, the handling is different from itself, - // to correct the client side visuals in this case - if ( cent->currentState.clientNum != cg.snap->ps.clientNum - && ( cent->currentState.eFlags & EF_AURA ) - && !( cent->currentState.eFlags & EF_DEAD ) - && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_CHARGE - && !p->snum ) { // use p->snum to handle the client side visual of the other player - p->link = qfalse; // keep this way, otherwise the rocks fall + p->endtime = timenonscaled + 1650; + p->link = qtrue; } } } diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index d819002..6fee23b 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -1922,11 +1922,10 @@ static qboolean CG_PlayerShadow( centity_t *cent, float *shadowPlane ) { // BFP - Dash smoke and bubble particles when using ki boost on the ground or above the water contents = CG_PointContents( trace.endpos, -1 ); if ( cent->currentState.eFlags & EF_AURA ) { - if ( !( cent->currentState.powerups & ( 1 << PW_HASTE ) ) - && ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_RUN + if ( ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_RUN || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_BACK || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYA - || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYB ) ) { + || ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_FLYB ) { if ( !( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) && ( trace.fraction <= 0.70f // If the player is stepping a mover: @@ -1958,15 +1957,15 @@ static qboolean CG_PlayerShadow( centity_t *cent, float *shadowPlane ) { int shaderIndex = rand() % 3; switch ( shaderIndex ) { case 0: { - CG_ParticleAntigravRock( cgs.media.pebbleShader1, cent, trace.endpos ); + CG_ParticleAntigravRock( cgs.media.pebbleShader1, cent, cent->currentState.clientNum, trace.endpos ); break; } case 1: { - CG_ParticleAntigravRock( cgs.media.pebbleShader2, cent, trace.endpos ); + CG_ParticleAntigravRock( cgs.media.pebbleShader2, cent, cent->currentState.clientNum, trace.endpos ); break; } default: { - CG_ParticleAntigravRock( cgs.media.pebbleShader3, cent, trace.endpos ); + CG_ParticleAntigravRock( cgs.media.pebbleShader3, cent, cent->currentState.clientNum, trace.endpos ); } } } From adec9785b9bd19914be60fb2da11f7a6e7215802 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sat, 14 Sep 2024 22:50:54 +0200 Subject: [PATCH 101/374] cgame: Complete shader aura implementation and refactor aura shader variables for clarity in the code --- source/cgame/cg_local.h | 12 +++++++++--- source/cgame/cg_main.c | 12 +++++++++--- source/cgame/cg_players.c | 33 ++++++++++++++++++++++----------- 3 files changed, 40 insertions(+), 17 deletions(-) diff --git a/source/cgame/cg_local.h b/source/cgame/cg_local.h index cfc521f..10c2e81 100644 --- a/source/cgame/cg_local.h +++ b/source/cgame/cg_local.h @@ -781,9 +781,15 @@ typedef struct { qhandle_t flyauraModel; // BFP - Fly aura model qhandle_t runauraModel; // BFP - Run aura model // BFP - Aura shaders - qhandle_t auraRedShader; - qhandle_t auraBlueShader; - qhandle_t auraYellowShader; + qhandle_t auraRedTinyShader; + qhandle_t auraRedChargeShader; + qhandle_t auraRedUseShader; + qhandle_t auraBlueTinyShader; + qhandle_t auraBlueChargeShader; + qhandle_t auraBlueUseShader; + qhandle_t auraYellowTinyShader; + qhandle_t auraYellowChargeShader; + qhandle_t auraYellowUseShader; // BFP - Ki trail shaders qhandle_t kiTrailRedShader; diff --git a/source/cgame/cg_main.c b/source/cgame/cg_main.c index 387c171..6731727 100644 --- a/source/cgame/cg_main.c +++ b/source/cgame/cg_main.c @@ -639,9 +639,15 @@ static void CG_RegisterGraphics( void ) { cgs.media.runauraModel = trap_R_RegisterModel( "models/effects/runaura.md3" ); // BFP - Run aura model // BFP - Aura shaders - cgs.media.auraBlueShader = trap_R_RegisterShader( "powerups/bluetiny" ); - cgs.media.auraRedShader = trap_R_RegisterShader( "powerups/redtiny" ); - cgs.media.auraYellowShader = trap_R_RegisterShader( "powerups/yellowtiny" ); + cgs.media.auraBlueTinyShader = trap_R_RegisterShader( "powerups/bluetiny" ); + cgs.media.auraBlueChargeShader = trap_R_RegisterShader( "powerups/bluecharge" ); + cgs.media.auraBlueUseShader = trap_R_RegisterShader( "powerups/blueuse" ); + cgs.media.auraRedTinyShader = trap_R_RegisterShader( "powerups/redtiny" ); + cgs.media.auraRedChargeShader = trap_R_RegisterShader( "powerups/redcharge" ); + cgs.media.auraRedUseShader = trap_R_RegisterShader( "powerups/reduse" ); + cgs.media.auraYellowTinyShader = trap_R_RegisterShader( "powerups/yellowtiny" ); + cgs.media.auraYellowChargeShader = trap_R_RegisterShader( "powerups/yellowcharge" ); + cgs.media.auraYellowUseShader = trap_R_RegisterShader( "powerups/yellowuse" ); // BFP - Ki trail shaders cgs.media.kiTrailBlueShader = trap_R_RegisterShader( "powerups/bluekitrail" ); diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index 6fee23b..392a752 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -2108,24 +2108,24 @@ void CG_AddRefEntityWithPowerups( refEntity_t ent, entityState_t *state, int tea // render main model trap_R_AddRefEntityToScene( &ent ); - // BFP - TODO: If player is transformed: + // BFP - TODO: If player is transformed and powerlevel is more than 1 Mil: // render perma-glow when already transformed - /* ent.customShader = cgs.media.auraYellowShader; + /* ent.customShader = cgs.media.auraYellowTinyShader; if ( ( state->powerups & ( 1 << PW_TRANSFORMED ) ) && cg_permaglowUltimate.integer > 0 ) { trap_R_AddRefEntityToScene( &ent ); }*/ - ent.customShader = cgs.media.auraRedShader; + ent.customShader = cgs.media.auraRedTinyShader; if ( team == TEAM_BLUE ) { - ent.customShader = cgs.media.auraBlueShader; + ent.customShader = cgs.media.auraBlueTinyShader; } - // BFP - TODO: If player is transformed: + // BFP - TODO: If player is transformed and powerlevel is more than 1 Mil: // only on non-team gamemodes render when already transformed /*if ( ( state->powerups & ( 1 << PW_TRANSFORMED ) ) && cgs.gametype < GT_TEAM ) { - ent.customShader = cgs.media.auraYellowShader; + ent.customShader = cgs.media.auraYellowTinyShader; }*/ if ( state->eFlags & EF_AURA ) { @@ -2138,14 +2138,25 @@ void CG_AddRefEntityWithPowerups( refEntity_t ent, entityState_t *state, int tea trap_R_AddRefEntityToScene( &ent ); } - // BFP - TODO: Shader aura + // BFP - Shader aura if ( cg_lightweightAuras.integer <= 0 && cg_polygonAura.integer <= 0 && cg_spriteAura.integer <= 0 && cg_particleAura.integer <= 0 && ( state->clientNum == cg.snap->ps.clientNum && cg_smallOwnAura.integer <= 0 ) ) { - MODEL_SIZE ( ent, 1.2f ) + ent.customShader = cgs.media.auraRedChargeShader; + // BFP - TODO: If player is transformed and powerlevel is more than 1 Mil (same as the previous TODO notes) + if ( team == TEAM_BLUE ) { + ent.customShader = cgs.media.auraBlueChargeShader; + } + if ( ( state->legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_CHARGE ) { + ent.customShader = cgs.media.auraRedUseShader; + // BFP - TODO: If player is transformed and powerlevel is more than 1 Mil (same as the previous TODO notes) + if ( team == TEAM_BLUE ) { + ent.customShader = cgs.media.auraBlueUseShader; + } + } trap_R_AddRefEntityToScene( &ent ); } } @@ -2342,16 +2353,16 @@ static void CG_Aura( centity_t *cent, int clientNum, clientInfo_t *ci, int rende VectorCopy( legs.lightingOrigin, aura2.lightingOrigin ); // BFP - TODO: Add yellow aura only when the player is transformed, but don't override when playing a team gamemode - // aura.customShader = aura2.customShader = cgs.media.auraYellowShader; + // aura.customShader = aura2.customShader = cgs.media.auraYellowTinyShader; // Don't put this line of code here if transformed, just put outside the check EF_AURA conditional // trap_R_AddLightToScene( cent->lerpOrigin, 200 + (rand()&255), 1.0, 1.0, 0 ); // apply light blinking if ( ci->team == TEAM_BLUE ) { - aura.customShader = aura2.customShader = cgs.media.auraBlueShader; + aura.customShader = aura2.customShader = cgs.media.auraBlueTinyShader; AURA_LIGHT( 0.2f, 0.2f, 1.0 ) } else { - aura.customShader = aura2.customShader = cgs.media.auraRedShader; + aura.customShader = aura2.customShader = cgs.media.auraRedTinyShader; AURA_LIGHT( 1.0, 0.2f, 0.2f ) } From c5550e73d31e19414c41e7a8a394f7b42fbe83da Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sat, 14 Sep 2024 23:14:02 +0200 Subject: [PATCH 102/374] cgame: Implement debris particles (still not completed) and complete splash implementation --- source/cgame/cg_event.c | 25 +++++-- source/cgame/cg_local.h | 2 + source/cgame/cg_particles.c | 127 +++++++++++++++++++++++++++++------- 3 files changed, 126 insertions(+), 28 deletions(-) diff --git a/source/cgame/cg_event.c b/source/cgame/cg_event.c index 692d08d..5b24727 100644 --- a/source/cgame/cg_event.c +++ b/source/cgame/cg_event.c @@ -595,15 +595,28 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { trap_S_StartSound (NULL, es->number, CHAN_AUTO, cgs.media.watrUnSound ); // BFP - Bubble and splash particles when entering under water { - // BFP - TODO: Splash particles (that appears bubbles outside water but bouncing once) vec3_t end = {0, 0, 1}; + vec3_t splashOrigin; + + VectorCopy( cent->lerpOrigin, splashOrigin ); + splashOrigin[2] += 20; // place a bit above + + // Splash! + // BFP - NOTE: These are not debris :P + CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, qtrue ); + CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, qtrue ); + CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, qtrue ); + CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, qtrue ); + CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, qtrue ); + + splashOrigin[2] -= 25; // place a bit below // Blub, blub, blub... - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 700, 20 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 700, 20 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 700, 20 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 700, 20 ); - CG_ParticleBubble( cent, cgs.media.waterBubbleShader, cent->lerpOrigin, end, 700, 20 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, splashOrigin, end, 700, 20 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, splashOrigin, end, 700, 20 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, splashOrigin, end, 700, 20 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, splashOrigin, end, 700, 20 ); + CG_ParticleBubble( cent, cgs.media.waterBubbleShader, splashOrigin, end, 700, 20 ); } break; case EV_WATER_CLEAR: diff --git a/source/cgame/cg_local.h b/source/cgame/cg_local.h index 10c2e81..ae862bb 100644 --- a/source/cgame/cg_local.h +++ b/source/cgame/cg_local.h @@ -1528,6 +1528,8 @@ void CG_AntigravRockHandling (centity_t *cent); // BFP - Particle aura void CG_ParticleAura (centity_t *cent, int entityNum, qhandle_t pshader, vec3_t origin, vec3_t origin2, float range); void CG_ParticleAuraHandling (centity_t *cent); +// BFP - Debris particle +void CG_ParticleDebris (qhandle_t pshader, vec3_t origin, qboolean water); // BFP - Unused particle stuff, saved for later :P #if 0 diff --git a/source/cgame/cg_particles.c b/source/cgame/cg_particles.c index 67152ec..4613c78 100644 --- a/source/cgame/cg_particles.c +++ b/source/cgame/cg_particles.c @@ -77,6 +77,7 @@ typedef enum P_SMOKE, P_ANIM, // Ridah P_BLEED, + P_DEBRIS, // BFP - Debris P_SMOKE_IMPACT, P_BUBBLE, P_BUBBLE_TURBULENT, @@ -320,7 +321,8 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) else if (p->type == P_SMOKE || p->type == P_SMOKE_IMPACT || p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT // BFP - Bubble types moved here for better management || p->type == P_ANTIGRAV_ROCK // BFP - Added antigrav rock type - || p->type == P_AURA) // BFP - Particle aura + || p->type == P_AURA // BFP - Particle aura + || p->type == P_DEBRIS) // BFP - Debris type {// create a front rotating facing polygon // BFP - No smoke distance @@ -372,7 +374,7 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) else invratio = 1 * p->alpha; - if (invratio > 1 || p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT) // BFP - Don't disappear opaquely the bubbles + if (invratio > 1 || p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT || p->type == P_DEBRIS) // BFP - Don't disappear opaquely the bubbles even the debris invratio = 1; width = p->width + ( ratio * ( p->endwidth - p->width) ); @@ -457,6 +459,47 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) p->type = p->color = p->alpha = p->snum = 0; } } + else if (p->type == P_DEBRIS) // BFP - Debris type + { + // BFP - To detect if there is something solid + trace_t trace; + vec3_t debrisPos = {0, 0, -1}; // place a bit above + int contents; + // contents should be CONTENTS_SOLID, so the particles don't touch any entity like the player + CG_Trace( &trace, p->org, debrisPos, debrisPos, org, -1, CONTENTS_SOLID ); + + p->time = timenonscaled; + // not hit anything or not a collider + if ( trace.fraction == 1.0f ) + { + VectorCopy (org, p->org); + p->vel[2] -= 100; + p->accel[0] -= 1; + p->accel[1] -= 1; + p->accel[2] -= 10; + } + else // bouncing + { + if ( trace.fraction <= 0 ) { + p->roll = 6; + } else { + p->vel[2] = p->accel[2] = (p->roll > 0) ? 50 * p->roll : 0; + p->roll--; // that decreases bounces + } + } + if ( p->roll <= 0 ) { // keep detecting the position + VectorCopy (trace.endpos, p->org); + } + + // if it's assigned to water, then detect when going underwater and changing to P_BUBBLE type + contents = trap_CM_PointContents( trace.endpos, 0 ); + if ( p->snum > 0 && ( contents & CONTENTS_WATER ) ) { + p->type = P_BUBBLE_TURBULENT; + p->endtime = timenonscaled + 600; + VectorCopy (trace.endpos, p->org); + p->vel[2] = p->accel[2] = 0; + } + } if (p->rotate) { @@ -785,7 +828,8 @@ void CG_AddParticles (void) #endif || p->type == P_BUBBLE || p->type == P_BUBBLE_TURBULENT // BFP - Add P_BUBBLE types to remove particles || p->type == P_ANTIGRAV_ROCK // BFP - Add P_ANTIGRAV_ROCK to remove particles - || p->type == P_AURA) // BFP - Add P_AURA to remove particles + || p->type == P_AURA // BFP - Add P_AURA to remove particles + || p->type == P_DEBRIS) // BFP - Add P_DEBRIS to remove particles { if (timenonscaled > p->endtime) { @@ -1109,14 +1153,10 @@ void CG_AntigravRockHandling (centity_t *cent) if ( p->entityNum == cent->currentState.clientNum && !( cent->currentState.eFlags & EF_DEAD ) - && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_CHARGE ) - { - // BFP - Make each particle fall when they aren't on ki charging status - if (!p->link) - { - p->endtime = timenonscaled + 1650; - p->link = qtrue; - } + && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_CHARGE + && !p->link ) { // BFP - Make each particle fall when they aren't on ki charging status + p->endtime = timenonscaled + 1650; + p->link = qtrue; } } } @@ -1187,21 +1227,64 @@ void CG_ParticleAuraHandling (centity_t *cent) if ( p->entityNum == cent->currentState.clientNum && !( cent->currentState.eFlags & EF_DEAD ) - && !( cent->currentState.eFlags & EF_AURA ) ) - { - // BFP - Make each particle fall when there's no aura at this moment - if (!p->link) - { - p->alphavel = -0.03; - p->accel[0] = 0; - p->accel[1] = 0; - p->endtime = timenonscaled + 600; - p->link = qtrue; - } + && !( cent->currentState.eFlags & EF_AURA ) + && !p->link ) { // BFP - Make each particle fall when there's no aura at this moment + p->alphavel = -0.03; + p->accel[0] = 0; + p->accel[1] = 0; + p->endtime = timenonscaled + 600; + p->link = qtrue; } } } +// BFP - Debris particles for ki explosions and water splash +void CG_ParticleDebris (qhandle_t pshader, vec3_t origin, qboolean water) +{ + cparticle_t *p; + + // if (!pshader) CG_Printf ("CG_ParticleDebris == ZERO!\n"); + + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + p->time = timenonscaled; + + p->startfade = timenonscaled + 200; + p->endtime = timenonscaled + 2450 + (crandom() * 20); + + p->color = 0; + p->alpha = 1; + p->alphavel = 0; + p->pshader = pshader; + p->height = p->width = (water) + ? (rand() % 3) + 1 + : (rand() % 2) + 2; + + p->type = P_DEBRIS; + + VectorCopy( origin, p->org ); + + p->org[0] += (crandom() * 15); + p->org[1] += (crandom() * 15); + + p->start = origin[2]; + + p->vel[0] = (crandom() * 150); + p->vel[1] = (crandom() * 150); + p->vel[2] = 1050; + + p->accel[0] = (crandom() * 100); + p->accel[1] = (crandom() * 100); + p->accel[2] = 220; + + p->roll = 5; // used as bounce counter + p->link = qfalse; + p->snum = water; // if it's water, it'll stop above water +} void CG_ParticleSmoke (qhandle_t pshader, centity_t *cent) { From 6f67503c50a9cde3d585e765526d3e19f48f745b Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sun, 15 Sep 2024 11:44:40 +0200 Subject: [PATCH 103/374] cgame: Make bubbles stick at the surface after few milliseconds, remove when grazing something solid while underwater, apply entityNum to bubble particles and; when velocity and acceleration are very small, clamp them to zero --- source/cgame/cg_particles.c | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/source/cgame/cg_particles.c b/source/cgame/cg_particles.c index 4613c78..ff74106 100644 --- a/source/cgame/cg_particles.c +++ b/source/cgame/cg_particles.c @@ -403,7 +403,8 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) // BFP - Apply more end time to remove particles if the player stops charging if (p->type == P_BUBBLE) { - if ( ( cg.snap->ps.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_CHARGE + if ( p->entityNum == cg.snap->ps.clientNum + && ( cg.snap->ps.legsAnim & ~ANIM_TOGGLEBIT ) != LEGS_CHARGE && !p->link ) { p->endtime = timenonscaled + 2500 + (crandom() * 150); @@ -891,6 +892,9 @@ void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_ active_particles = p; p->time = timenonscaled; + // BFP - Keep entity number to identify who is using + p->entityNum = cent->currentState.number; + // BFP - Add end time to remove particles, if there's no end time the particles will remain there p->endtime = timenonscaled + 600; p->startfade = timenonscaled + 200; @@ -898,7 +902,7 @@ void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_ p->color = 0; p->alpha = 1; p->alphavel = 0; - // BFP - Apply to player's origin + // BFP - Apply to entity's origin p->start = cent->currentState.origin[2]; p->end = cent->currentState.origin2[2]; p->pshader = pshader; @@ -953,7 +957,7 @@ void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_ } p->snum = 3 - (crandom() * 6); // used to randomize where the bubbles stop when these touches the surface - p->link = qfalse; + p->link = qfalse; // used to handle the bubbles when touching the surface } // BFP - Handle bubble particles when reaching to the top @@ -971,14 +975,20 @@ void CG_BubblesWaterHandling( cparticle_t *p, vec3_t org ) { // decelerate for (i = 0; i < 2; ++i) { - if (fabs(p->vel[i]) > 0) { - p->vel[i] *= 0.99; + p->vel[i] *= 0.99; + + // if the velocity is very small, clamp it to zero + if (fabs(p->vel[i]) < 1) { + p->vel[i] = 0; } } for (i = 0; i < 2; ++i) { - if (fabs(p->accel[i]) > 0) { - p->accel[i] *= 0.99; + p->accel[i] *= 0.99; + + // if the acceleration is very small, clamp it to zero + if (fabs(p->accel[i]) < 1) { + p->accel[i] = 0; } } @@ -987,6 +997,11 @@ void CG_BubblesWaterHandling( cparticle_t *p, vec3_t org ) { // if the particle is touching something solid, it will skip instead stopping contents = trap_CM_PointContents( trace.endpos, 0 ); + if ( contents & CONTENTS_SOLID ) { // remove when grazing something solid + p->next = NULL; + p->type = p->color = p->alpha = 0; + return; + } if ( !( contents & CONTENTS_WATER ) ) { p->time = timenonscaled; VectorCopy (trace.endpos, p->org); @@ -1009,6 +1024,11 @@ void CG_BubblesWaterHandling( cparticle_t *p, vec3_t org ) { if ( p->type == P_BUBBLE ) { if ( p->vel[0] != 0 ) p->vel[0] *= 0.9; if ( p->vel[1] != 0 ) p->vel[1] *= 0.9; + // stop after few milliseconds + if ( p->link && p->time > p->endtime - 2250 ) { + p->vel[0] = 0; + p->vel[1] = 0; + } } else { if ( p->vel[0] != 0 ) p->vel[0] *= 0.97; if ( p->vel[1] != 0 ) p->vel[1] *= 0.97; From b9667d7632bc10f3fc363a7c378f8f66cd74b166 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sun, 15 Sep 2024 12:04:10 +0200 Subject: [PATCH 104/374] Add more notes and descriptions in the TODO list --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5743aec..5343948 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,8 @@ A legendary 90s era Quake 3 Arena mod. - [x] ~~Ki trails (use ki to move, cg_kiTrail >10 )~~ - [x] ~~Instant character model changing~~ - [x] ~~Auras~~ +- [ ] Player physics movements +- [ ] Remove some items like powerups and health pickups - [ ] Make ki energy regeneration, ki use, attacks, charging balance indicated on old docs - [ ] Powerlevel and Power Tiers indicated on old docs - [x] ~~Hit Stun (makes player can't use ki, melee, block and charge)~~ @@ -55,7 +57,7 @@ A legendary 90s era Quake 3 Arena mod. - [x] ~~Short-Range Teleport - Zanzoken (when pressing 2 times left or right)~~ - [ ] Transformations (related to Power Tiers) - [ ] Attacksets (configurable for cfgs) -- [ ] Skin Config File (explosionModel, explosionShader, missileRotation, missileShader, ... look old docs about that. "Custom plugin models") +- [ ] Skin Config File (explosionModel, explosionShader, missileRotation, missileShader, ... look old docs about that. ["Custom plugin models"](docs/Create_Custom_Models.md#the-skin-config-file)) - [x] ~~Playable third person mode and first person vis mode (add the options in the UI Setup menu)~~ - [ ] Cvars as described on old docs - [ ] Survival gametype (`g_gametype 3`) @@ -96,7 +98,7 @@ Click here to see the [Old PyroFragger dev journal (Markdown edition)](docs/pyro We're making a replica of the lost source code.
The highest priority goal is to copy and recreate the complete logical structure of the BFP game. It would be a game SDK that'll provide a structured and standardized way to modify the mod.
-You'll notice some differences that the original Bid For Power didn't have, such as some adjusted UI buttons, sprite and particle aura type options in BFP options menu, server info menu has pagination and displays info, particle aura is almost implemented, ...
+You'll notice some differences that the original Bid For Power didn't have, such as some adjusted UI buttons, sprite and particle aura type options in BFP options menu, server info menu has pagination and displays info, how particles move (e.g. bubbles are handled underwater and touching something solid vanishes to save performance), particle aura is almost implemented, ...
Any fixes, improvements and contributions are welcome. But we can't accept secondary things and other stuff that don't reach the goals. ### References and clues to know how should be the game From 3c8879a4d6eb28b2ff87eda3b6b30271d9b6df77 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 16 Sep 2024 03:16:40 +0200 Subject: [PATCH 105/374] q3_ui: Apply pagination on DRIVER INFO menu in EXTENSIONS section, limit of these strings in the UI are 64 --- source/q3_ui/ui_video.c | 208 ++++++++++++++++++++++++++++++++-------- 1 file changed, 170 insertions(+), 38 deletions(-) diff --git a/source/q3_ui/ui_video.c b/source/q3_ui/ui_video.c index fc70e72..e0a9847 100644 --- a/source/q3_ui/ui_video.c +++ b/source/q3_ui/ui_video.c @@ -38,6 +38,11 @@ DRIVER INFORMATION MENU #define DRIVERINFO_BACK0 "menu/art/back_0" #define DRIVERINFO_BACK1 "menu/art/back_1" +// BFP - Arrows +#define ART_ARROWS "menu/art/gs_arrows_0" +#define ART_ARROWSL "menu/art/gs_arrows_l" +#define ART_ARROWSR "menu/art/gs_arrows_r" + static char* driverinfo_artlist[] = { DRIVERINFO_BACK0, @@ -47,6 +52,16 @@ static char* driverinfo_artlist[] = #define ID_DRIVERINFOBACK 100 +// BFP - ID for arrows +#define ID_DRIVERINFOPREV 101 +#define ID_DRIVERINFONEXT 102 + +// BFP - Limit of extensions length and UI extension strings +// uis.glconfig.extensions_string length is 8192 +#define MAX_EXTENSIONS_STRING_LENGTH 2048 +// when surpassing 64 extension strings, UI starts to break crazily the next strings after 64 +#define MAX_UI_EXTENSION_STRINGS 64 + typedef struct { menuframework_s menu; @@ -54,9 +69,14 @@ typedef struct menubitmap_s menubg; // BFP - Menu background menubitmap_s barlog; // BFP - barlog menubitmap_s back; - char stringbuff[1024]; + char stringbuff[MAX_EXTENSIONS_STRING_LENGTH]; char* strings[64]; int numstrings; + // BFP - For pagination + int currentPage, totalPages, totalLines; + menubitmap_s arrows; + menubitmap_s next; + menubitmap_s prev; } driverinfo_t; static driverinfo_t s_driverinfo; @@ -71,11 +91,25 @@ static void DriverInfo_Event( void* ptr, int event ) if (event != QM_ACTIVATED) return; - switch (((menucommon_s*)ptr)->id) - { - case ID_DRIVERINFOBACK: - UI_PopMenu(); - break; + switch ( ((menucommon_s*)ptr)->id ) { + // BFP - Prev and next events + case ID_DRIVERINFOPREV: + if ( s_driverinfo.currentPage > 0 ) { + s_driverinfo.currentPage--; + Menu_Draw( &s_driverinfo.menu ); + } + break; + + case ID_DRIVERINFONEXT: + if ( s_driverinfo.currentPage < s_driverinfo.totalPages - 1 ) { + s_driverinfo.currentPage++; + Menu_Draw( &s_driverinfo.menu ); + } + break; + + case ID_DRIVERINFOBACK: + UI_PopMenu(); + break; } } @@ -88,28 +122,73 @@ static void DriverInfo_MenuDraw( void ) { int i; int y; + // BFP - For pagination + char pageIndicator[64]; + int startLine, endLine; + int lineIndex, len, wrappedLen, j; + char wrappedExtension[40]; // 39 characters + 1 null terminator +#define DRIVERINFO_LINES_PER_PAGE 20 +#define LIMIT_CHARACTERS 39 Menu_Draw( &s_driverinfo.menu ); - UI_DrawString( 320, 80, "VENDOR", UI_CENTER|UI_SMALLFONT, color_white ); // BFP - modified VENDOR title color - UI_DrawString( 320, 152, "PIXELFORMAT", UI_CENTER|UI_SMALLFONT, color_white ); // BFP - modified PIXELFORMAT title color - UI_DrawString( 320, 192, "EXTENSIONS", UI_CENTER|UI_SMALLFONT, color_white ); // BFP - modified EXTENSIONS title color - - UI_DrawString( 320, 80+16, uis.glconfig.vendor_string, UI_CENTER|UI_SMALLFONT, text_color_normal ); - UI_DrawString( 320, 96+16, uis.glconfig.version_string, UI_CENTER|UI_SMALLFONT, text_color_normal ); - UI_DrawString( 320, 112+16, uis.glconfig.renderer_string, UI_CENTER|UI_SMALLFONT, text_color_normal ); - UI_DrawString( 320, 152+16, va ("color(%d-bits) Z(%d-bits) stencil(%d-bits)", uis.glconfig.colorBits, uis.glconfig.depthBits, uis.glconfig.stencilBits), UI_CENTER|UI_SMALLFONT, text_color_normal ); - - // double column - y = 192+16; - for (i=0; i s_driverinfo.numstrings ) { + endLine = s_driverinfo.numstrings; } - if (s_driverinfo.numstrings & 1) - UI_DrawString( 320, y, s_driverinfo.strings[s_driverinfo.numstrings-1], UI_CENTER|UI_SMALLFONT, text_color_normal ); + // display paginated EXTENSIONS strings + y = 192 + 16; // start after the EXTENSIONS title + for ( i = startLine; i < endLine; i++ ) { + len = (int)strlen( s_driverinfo.strings[i] ); + wrappedLen = 0; + + while ( len > 0 ) { + if ( len > LIMIT_CHARACTERS ) { + if ( j == 0 ) { + j = LIMIT_CHARACTERS; // no delimiter found, use the limit + } + + // copy the first part of the string and wrap it + strncpy( wrappedExtension, s_driverinfo.strings[i] + wrappedLen, j + 1 ); + wrappedExtension[j + 1] = '\0'; + wrappedLen += j + 1; + len -= j + 1; + } else { + strcpy( wrappedExtension, s_driverinfo.strings[i] + wrappedLen ); + len = 0; + } + + // display strings in double columns + if ( i % 2 == 0 ) { + UI_DrawString( 320 - 4, y, wrappedExtension, UI_RIGHT | UI_SMALLFONT, text_color_normal ); + } else { + UI_DrawString( 320 + 4, y, wrappedExtension, UI_LEFT | UI_SMALLFONT, text_color_normal ); + y += SMALLCHAR_HEIGHT; + } + } + } + + // if odd number of strings, draw the last one centered + if ( s_driverinfo.numstrings & 1 && i == s_driverinfo.numstrings ) { + UI_DrawString( 320, y, s_driverinfo.strings[s_driverinfo.numstrings - 1], UI_CENTER | UI_SMALLFONT, text_color_normal ); + } + + Com_sprintf( pageIndicator, sizeof(pageIndicator), "EXTENSIONS - Page %d of %d", s_driverinfo.currentPage + 1, s_driverinfo.totalPages ); + UI_DrawString( 320, 445, pageIndicator, UI_CENTER | UI_SMALLFONT, color_white ); } /* @@ -138,7 +217,6 @@ UI_DriverInfo_Menu static void UI_DriverInfo_Menu( void ) { char* eptr; - int i; int len; // zero set all our globals @@ -185,40 +263,94 @@ static void UI_DriverInfo_Menu( void ) s_driverinfo.back.height = 80; // BFP - modified BACK button height s_driverinfo.back.focuspic = DRIVERINFO_BACK1; + // BFP - Arrows to go prev or next +#define ART_ARROWS_X 260 +#define ART_ARROWS_Y 400 + s_driverinfo.arrows.generic.type = MTYPE_BITMAP; + s_driverinfo.arrows.generic.name = ART_ARROWS; + s_driverinfo.arrows.generic.flags = QMF_INACTIVE; + s_driverinfo.arrows.generic.x = ART_ARROWS_X; + s_driverinfo.arrows.generic.y = ART_ARROWS_Y; + s_driverinfo.arrows.width = 128; + s_driverinfo.arrows.height = 32; + + s_driverinfo.prev.generic.type = MTYPE_BITMAP; + s_driverinfo.prev.generic.flags = QMF_LEFT_JUSTIFY | QMF_PULSEIFFOCUS; + s_driverinfo.prev.generic.callback = DriverInfo_Event; + s_driverinfo.prev.generic.id = ID_DRIVERINFOPREV; + s_driverinfo.prev.generic.x = ART_ARROWS_X; + s_driverinfo.prev.generic.y = ART_ARROWS_Y; + s_driverinfo.prev.width = 64; + s_driverinfo.prev.height = 32; + s_driverinfo.prev.focuspic = ART_ARROWSL; + + s_driverinfo.next.generic.type = MTYPE_BITMAP; + s_driverinfo.next.generic.flags = QMF_LEFT_JUSTIFY | QMF_PULSEIFFOCUS; + s_driverinfo.next.generic.callback = DriverInfo_Event; + s_driverinfo.next.generic.id = ID_DRIVERINFONEXT; + s_driverinfo.next.generic.x = ART_ARROWS_X+61; + s_driverinfo.next.generic.y = ART_ARROWS_Y; + s_driverinfo.next.width = 64; + s_driverinfo.next.height = 32; + s_driverinfo.next.focuspic = ART_ARROWSR; +#undef ART_ARROWS_X +#undef ART_ARROWS_Y + // BFP - End of arrows to go prev or next ^ + + + // BFP - The following stuff has been modified for pagination + // TTimo: overflow with particularly long GL extensions (such as the gf3) // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=399 // NOTE: could have pushed the size of stringbuff, but the list is already out of the screen // (no matter what your resolution) - Q_strncpyz(s_driverinfo.stringbuff, uis.glconfig.extensions_string, 1024); + Q_strncpyz(s_driverinfo.stringbuff, uis.glconfig.extensions_string, MAX_EXTENSIONS_STRING_LENGTH); // build null terminated extension strings eptr = s_driverinfo.stringbuff; - while ( s_driverinfo.numstrings<40 && *eptr ) + while ( s_driverinfo.numstrings < MAX_UI_EXTENSION_STRINGS && *eptr ) { - while ( *eptr && *eptr == ' ' ) - *eptr++ = '\0'; + // skip leading spaces + while ( *eptr == ' ' ) { + eptr++; + } + + // if we reach the end of the string, break + if ( *eptr == '\0' ) { + break; + } // track start of valid string - if (*eptr && *eptr != ' ') - s_driverinfo.strings[s_driverinfo.numstrings++] = eptr; + s_driverinfo.strings[s_driverinfo.numstrings] = eptr; - while ( *eptr && *eptr != ' ' ) + // find the end of the current extension string + while ( *eptr && *eptr != ' ' ) { eptr++; - } + } - // safety length strings for display - for (i=0; i 32) { - s_driverinfo.strings[i][len-1] = '>'; - s_driverinfo.strings[i][len] = '\0'; + // null-terminate the string + if ( *eptr != '\0' ) { + *eptr = '\0'; // null-terminate the current extension string + eptr++; // move past the null terminator } + + s_driverinfo.numstrings++; } + // BFP - Calculate total pages + s_driverinfo.totalLines = s_driverinfo.numstrings; + s_driverinfo.totalPages = (s_driverinfo.totalLines + DRIVERINFO_LINES_PER_PAGE - 1) / DRIVERINFO_LINES_PER_PAGE; + Menu_AddItem( &s_driverinfo.menu, &s_driverinfo.menubg ); // BFP - Menu background Menu_AddItem( &s_driverinfo.menu, &s_driverinfo.barlog ); // BFP - barlog Menu_AddItem( &s_driverinfo.menu, &s_driverinfo.banner ); Menu_AddItem( &s_driverinfo.menu, &s_driverinfo.back ); + // BFP - Arrows to handle the pages + Menu_AddItem( &s_driverinfo.menu, (void*) &s_driverinfo.arrows ); + if ( s_driverinfo.totalPages > 1 ) { + Menu_AddItem( &s_driverinfo.menu, (void*) &s_driverinfo.next ); + Menu_AddItem( &s_driverinfo.menu, (void*) &s_driverinfo.prev ); + } UI_PushMenu( &s_driverinfo.menu ); } From f7f0294bba13ffa867f15f8992fc6b629c99e680 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Wed, 18 Sep 2024 23:54:05 +0200 Subject: [PATCH 106/374] cgame: Implement and tweak debris particle physics, and tweak splash particles with CG_ParticleDebris function --- source/cgame/cg_event.c | 14 +++-- source/cgame/cg_local.h | 2 +- source/cgame/cg_particles.c | 102 +++++++++++++++++++++++------------- source/cgame/cg_weapons.c | 41 ++++++++++++--- 4 files changed, 109 insertions(+), 50 deletions(-) diff --git a/source/cgame/cg_event.c b/source/cgame/cg_event.c index 5b24727..c2d9f9a 100644 --- a/source/cgame/cg_event.c +++ b/source/cgame/cg_event.c @@ -601,13 +601,17 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { VectorCopy( cent->lerpOrigin, splashOrigin ); splashOrigin[2] += 20; // place a bit above + // that would be the range + splashOrigin[0] += (crandom() * 15); + splashOrigin[1] += (crandom() * 15); + // Splash! // BFP - NOTE: These are not debris :P - CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, qtrue ); - CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, qtrue ); - CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, qtrue ); - CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, qtrue ); - CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, qtrue ); + CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, NULL, qtrue ); + CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, NULL, qtrue ); + CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, NULL, qtrue ); + CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, NULL, qtrue ); + CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, NULL, qtrue ); splashOrigin[2] -= 25; // place a bit below diff --git a/source/cgame/cg_local.h b/source/cgame/cg_local.h index ae862bb..b4fbfa4 100644 --- a/source/cgame/cg_local.h +++ b/source/cgame/cg_local.h @@ -1529,7 +1529,7 @@ void CG_AntigravRockHandling (centity_t *cent); void CG_ParticleAura (centity_t *cent, int entityNum, qhandle_t pshader, vec3_t origin, vec3_t origin2, float range); void CG_ParticleAuraHandling (centity_t *cent); // BFP - Debris particle -void CG_ParticleDebris (qhandle_t pshader, vec3_t origin, qboolean water); +void CG_ParticleDebris (qhandle_t pshader, vec3_t origin, vec3_t vel, qboolean water); // BFP - Unused particle stuff, saved for later :P #if 0 diff --git a/source/cgame/cg_particles.c b/source/cgame/cg_particles.c index ff74106..45f48b9 100644 --- a/source/cgame/cg_particles.c +++ b/source/cgame/cg_particles.c @@ -421,9 +421,9 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) { // BFP - To detect if there is something solid trace_t trace; - vec3_t rockPos = {0, 0, -1}; // place a bit above + vec3_t rockMins = {0, 0, -1}; // place a bit above // contents should be CONTENTS_SOLID, so the particles don't touch any entity like the player - CG_Trace( &trace, p->org, rockPos, rockPos, org, -1, CONTENTS_SOLID ); + CG_Trace( &trace, p->org, rockMins, rockMins, org, -1, CONTENTS_SOLID ); p->time = timenonscaled; p->snum = 1; // handle the p->snum when already entered in this phase for correction of client side visuals @@ -464,42 +464,66 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) { // BFP - To detect if there is something solid trace_t trace; - vec3_t debrisPos = {0, 0, -1}; // place a bit above + vec3_t debrisMins = {0, 0, -1}; // place a bit above + vec3_t up = {0, 0, 1}; int contents; // contents should be CONTENTS_SOLID, so the particles don't touch any entity like the player - CG_Trace( &trace, p->org, debrisPos, debrisPos, org, -1, CONTENTS_SOLID ); + CG_Trace( &trace, p->org, debrisMins, debrisMins, org, -1, CONTENTS_SOLID ); + + // keep detecting the position, also helps to pass through map bounds + VectorCopy ( org, p->org ); p->time = timenonscaled; // not hit anything or not a collider + contents = trap_CM_PointContents( trace.endpos, 0 ); + if ( p->roll <= 0 && !p->link ) { // stop + VectorClear( p->accel ); + VectorClear( p->vel ); + } if ( trace.fraction == 1.0f ) { - VectorCopy (org, p->org); - p->vel[2] -= 100; - p->accel[0] -= 1; - p->accel[1] -= 1; - p->accel[2] -= 10; + p->vel[2] -= (p->link) ? 100 : 80; + p->accel[2] -= (p->link) ? 10 : 100; } else // bouncing { - if ( trace.fraction <= 0 ) { - p->roll = 6; + // if it's on a slope + if ( DotProduct( trace.plane.normal, up ) < 0.7 ) { + if ( fabs( p->vel[2] ) < 1 ) { + VectorClear( p->accel ); + VectorClear( p->vel ); + p->height = p->width *= 0.9; // make it tinier when that happens + } else { + p->vel[2] -= (p->link) ? 100 : 80; + p->accel[2] -= (p->link) ? 10 : 100; + } } else { - p->vel[2] = p->accel[2] = (p->roll > 0) ? 50 * p->roll : 0; - p->roll--; // that decreases bounces + if ( trace.fraction <= 0 ) { + p->roll = 4; + } else { + p->vel[2] = (p->roll > 0) ? 500 * p->roll : 0; + p->accel[2] = (p->roll > 0) ? 500 * p->roll : 0; + p->roll--; // decreases bounces + } } } - if ( p->roll <= 0 ) { // keep detecting the position - VectorCopy (trace.endpos, p->org); - } // if it's assigned to water, then detect when going underwater and changing to P_BUBBLE type - contents = trap_CM_PointContents( trace.endpos, 0 ); - if ( p->snum > 0 && ( contents & CONTENTS_WATER ) ) { + if ( p->link && ( contents & CONTENTS_WATER ) ) { p->type = P_BUBBLE_TURBULENT; p->endtime = timenonscaled + 600; VectorCopy (trace.endpos, p->org); p->vel[2] = p->accel[2] = 0; } + + // for a short time, the debris begin to get tinier + if ( p->time > p->endtime - 500 ) { + p->height = p->width *= 0.9; + } + if ( p->height <= 0.1 ) { + p->next = NULL; + p->type = p->color = p->alpha = 0; + } } if (p->rotate) @@ -1013,11 +1037,6 @@ void CG_BubblesWaterHandling( cparticle_t *p, vec3_t org ) { // trace again if the bubble went outside, then set it near to the surface contents = trap_CM_PointContents( p->org, 0 ); - if ( contents & CONTENTS_SOLID ) { // remove when grazing something solid - p->next = NULL; - p->type = p->color = p->alpha = 0; - return; - } if ( !( contents & CONTENTS_WATER ) ) { VectorCopy (trace.endpos, p->org); } @@ -1259,7 +1278,7 @@ void CG_ParticleAuraHandling (centity_t *cent) } // BFP - Debris particles for ki explosions and water splash -void CG_ParticleDebris (qhandle_t pshader, vec3_t origin, qboolean water) +void CG_ParticleDebris (qhandle_t pshader, vec3_t origin, vec3_t vel, qboolean water) { cparticle_t *p; @@ -1274,7 +1293,9 @@ void CG_ParticleDebris (qhandle_t pshader, vec3_t origin, qboolean water) p->time = timenonscaled; p->startfade = timenonscaled + 200; - p->endtime = timenonscaled + 2450 + (crandom() * 20); + p->endtime = (water) + ? timenonscaled + 2450 + (crandom() * 20) + : timenonscaled + 1200; p->color = 0; p->alpha = 1; @@ -1282,28 +1303,35 @@ void CG_ParticleDebris (qhandle_t pshader, vec3_t origin, qboolean water) p->pshader = pshader; p->height = p->width = (water) ? (rand() % 3) + 1 - : (rand() % 2) + 2; + : (rand() % 6) + 3; p->type = P_DEBRIS; VectorCopy( origin, p->org ); - p->org[0] += (crandom() * 15); - p->org[1] += (crandom() * 15); + if ( water ) { + p->org[0] += (crandom() * 15); + p->org[1] += (crandom() * 15); + } p->start = origin[2]; - p->vel[0] = (crandom() * 150); - p->vel[1] = (crandom() * 150); - p->vel[2] = 1050; + VectorCopy( vel, p->vel ); + + if ( water ) { + p->vel[0] = (crandom() * 150); + p->vel[1] = (crandom() * 150); + p->vel[2] = 1050; + } - p->accel[0] = (crandom() * 100); - p->accel[1] = (crandom() * 100); - p->accel[2] = 220; + p->accel[0] = (crandom() * 250); + p->accel[1] = (crandom() * 250); + p->accel[2] = 250 + (crandom() * 50); - p->roll = 5; // used as bounce counter - p->link = qfalse; - p->snum = water; // if it's water, it'll stop above water + p->roll = (water) // used as bounce counter + ? 0 + : 5; + p->link = water; // if it's water, it'll stop above water } void CG_ParticleSmoke (qhandle_t pshader, centity_t *cent) diff --git a/source/cgame/cg_weapons.c b/source/cgame/cg_weapons.c index fb2da8b..f05500b 100644 --- a/source/cgame/cg_weapons.c +++ b/source/cgame/cg_weapons.c @@ -1539,12 +1539,39 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im lightColor[0] = 1; lightColor[1] = 0.75; lightColor[2] = 0.0; - if (cg_oldRocket.integer == 0) { - // explosion sprite animation - VectorMA( origin, 24, dir, sprOrg ); - VectorScale( dir, 64, sprVel ); - - CG_ParticleExplosion( "explode1", sprOrg, sprVel, 1400, 20, 30 ); + // BFP - cg_oldRocket is unused on BFP, they forgot to remove + //if (cg_oldRocket.integer == 0) + { + int i; + for ( i = 0; i < 26; ++i ) { + // BFP - Spawn randomly the debris shaders with the particles + int shaderIndex = rand() % 3; + + // BFP - That would be the range for debris particles + VectorMA( origin, 24, dir, sprOrg ); + sprOrg[0] += (rand() % 24); + sprOrg[1] += (rand() % 24); + sprOrg[2] += (rand() % 24); + + VectorScale( dir, 1500 + (rand() % 1000), sprVel ); + sprVel[0] += (rand() % 2800) - 1500; + sprVel[1] += (rand() % 2800) - 1500; + sprVel[2] += (rand() % 2200) - 1000; + + switch ( shaderIndex ) { + case 0: { + CG_ParticleDebris( cgs.media.pebbleShader1, sprOrg, sprVel, qfalse ); + break; + } + case 1: { + CG_ParticleDebris( cgs.media.pebbleShader2, sprOrg, sprVel, qfalse ); + break; + } + default: { + CG_ParticleDebris( cgs.media.pebbleShader3, sprOrg, sprVel, qfalse ); + } + } + } } break; case WP_RAILGUN: @@ -1927,4 +1954,4 @@ void CG_Bullet( vec3_t end, int sourceEntityNum, vec3_t normal, qboolean flesh, CG_MissileHitWall( WP_MACHINEGUN, 0, end, normal, IMPACTSOUND_DEFAULT ); } -} \ No newline at end of file +} From 4aa6fb798937d749fc848f236df84906400fdc85 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Tue, 24 Sep 2024 23:47:36 +0200 Subject: [PATCH 107/374] cgame: Implement spark particles --- source/cgame/cg_local.h | 11 +-- source/cgame/cg_main.c | 2 + source/cgame/cg_particles.c | 138 ++++++++++++++++++++++-------------- source/cgame/cg_weapons.c | 31 +++++++- 4 files changed, 121 insertions(+), 61 deletions(-) diff --git a/source/cgame/cg_local.h b/source/cgame/cg_local.h index b4fbfa4..c0efd96 100644 --- a/source/cgame/cg_local.h +++ b/source/cgame/cg_local.h @@ -774,6 +774,8 @@ typedef struct { qhandle_t pebbleShader2; qhandle_t pebbleShader3; qhandle_t particleSmokeShader; + qhandle_t sparkShader1; + qhandle_t sparkShader2; // BFP - Aura models qhandle_t auraModel; // BFP - Normal aura model @@ -1514,7 +1516,6 @@ void CG_ClearParticles (void); void CG_AddParticles (void); void CG_ParticleSmoke (qhandle_t pshader, centity_t *cent); void CG_ParticleBulletDebris (vec3_t org, vec3_t vel, int duration); -void CG_ParticleSparks (vec3_t org, vec3_t vel, int duration, float x, float y, float speed); void CG_ParticleDust (centity_t *cent, vec3_t origin, vec3_t dir); void CG_ParticleMisc (qhandle_t pshader, vec3_t origin, int size, int duration, float alpha); void CG_ParticleExplosion (char *animStr, vec3_t origin, vec3_t vel, int duration, int sizeStart, int sizeEnd); @@ -1526,10 +1527,12 @@ void CG_ParticleDashSmoke (centity_t *cent, qhandle_t pshader, vec3_t origin); void CG_ParticleAntigravRock (qhandle_t pshader, centity_t *cent, int entityNum, vec3_t origin); void CG_AntigravRockHandling (centity_t *cent); // BFP - Particle aura -void CG_ParticleAura (centity_t *cent, int entityNum, qhandle_t pshader, vec3_t origin, vec3_t origin2, float range); -void CG_ParticleAuraHandling (centity_t *cent); +void CG_ParticleAura (centity_t *cent, int entityNum, qhandle_t pshader, vec3_t origin, vec3_t origin2, float range); +void CG_ParticleAuraHandling (centity_t *cent); // BFP - Debris particle -void CG_ParticleDebris (qhandle_t pshader, vec3_t origin, vec3_t vel, qboolean water); +void CG_ParticleDebris (qhandle_t pshader, vec3_t origin, vec3_t vel, qboolean water); +// BFP - Spark particle +void CG_ParticleSparks (qhandle_t pshader, vec3_t origin, vec3_t vel); // BFP - Unused particle stuff, saved for later :P #if 0 diff --git a/source/cgame/cg_main.c b/source/cgame/cg_main.c index 6731727..eee5ff0 100644 --- a/source/cgame/cg_main.c +++ b/source/cgame/cg_main.c @@ -681,6 +681,8 @@ static void CG_RegisterGraphics( void ) { cgs.media.pebbleShader2 = trap_R_RegisterShader( "pebbleShader2" ); // BFP - Rock particles for charging and explosion cgs.media.pebbleShader3 = trap_R_RegisterShader( "pebbleShader3" ); // BFP - Rock particles for charging and explosion cgs.media.particleSmokeShader = trap_R_RegisterShader( "particleSmokeShader" ); // BFP - Smoke particle when using ki boost in the ground and for the explosion + cgs.media.sparkShader1 = trap_R_RegisterShader( "sparkShader1" ); // BFP - Spark particle for explosion + cgs.media.sparkShader2 = trap_R_RegisterShader( "sparkShader2" ); // BFP - Spark particle for explosion // register the inline models cgs.numInlineModels = trap_CM_NumInlineModels(); diff --git a/source/cgame/cg_particles.c b/source/cgame/cg_particles.c index 45f48b9..f28aabe 100644 --- a/source/cgame/cg_particles.c +++ b/source/cgame/cg_particles.c @@ -476,34 +476,39 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) p->time = timenonscaled; // not hit anything or not a collider contents = trap_CM_PointContents( trace.endpos, 0 ); - if ( p->roll <= 0 && !p->link ) { // stop + if ( p->roll <= 0 && !p->link && p->snum <= 0 ) { // stop VectorClear( p->accel ); VectorClear( p->vel ); } - if ( trace.fraction == 1.0f ) - { - p->vel[2] -= (p->link) ? 100 : 80; - p->accel[2] -= (p->link) ? 10 : 100; - } - else // bouncing - { - // if it's on a slope - if ( DotProduct( trace.plane.normal, up ) < 0.7 ) { - if ( fabs( p->vel[2] ) < 1 ) { - VectorClear( p->accel ); - VectorClear( p->vel ); - p->height = p->width *= 0.9; // make it tinier when that happens - } else { - p->vel[2] -= (p->link) ? 100 : 80; - p->accel[2] -= (p->link) ? 10 : 100; - } - } else { - if ( trace.fraction <= 0 ) { - p->roll = 4; + + if ( p->snum > 0 ) { // for sparks + p->vel[2] -= 110; + p->accel[2] -= 150; + } else { + if ( trace.fraction == 1.0f ) { + p->vel[2] -= (p->link) ? 100 : 80; + p->accel[2] -= (p->link) ? 10 : 100; + } + else // bouncing + { + // if it's on a slope + if ( DotProduct( trace.plane.normal, up ) < 0.7 ) { + if ( fabs( p->vel[2] ) < 1 ) { + VectorClear( p->accel ); + VectorClear( p->vel ); + p->height = p->width *= 0.9; // make it tinier when that happens + } else { + p->vel[2] -= (p->link) ? 100 : 80; + p->accel[2] -= (p->link) ? 10 : 100; + } } else { - p->vel[2] = (p->roll > 0) ? 500 * p->roll : 0; - p->accel[2] = (p->roll > 0) ? 500 * p->roll : 0; - p->roll--; // decreases bounces + if ( trace.fraction <= 0 ) { + p->roll = 4; + } else { + p->vel[2] = (p->roll > 0) ? 500 * p->roll : 0; + p->accel[2] = (p->roll > 0) ? 500 * p->roll : 0; + p->roll--; // decreases bounces + } } } } @@ -520,12 +525,48 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) if ( p->time > p->endtime - 500 ) { p->height = p->width *= 0.9; } - if ( p->height <= 0.1 ) { + if ( p->width <= 0.1 ) { p->next = NULL; p->type = p->color = p->alpha = 0; } } + if (p->type == P_DEBRIS && p->snum > 0) { // render spark particles + vec3_t forward, right, endPoint; + float length; + + // direction of the particle + VectorNormalize2( p->vel, forward ); + + length = VectorLength( p->vel ) * 0.015f; // multiplier to tweak trail length + VectorMA( org, length, forward, endPoint ); + PerpendicularVector( right, forward ); + + // bottom-left + VectorMA( org, -p->width, right, verts[0].xyz ); + VectorArray2Set( verts[0].st, 0, 0 ); + Vector4Set( verts[0].modulate, 255, 255, 255, 255 * alpha ); + + // top-left + VectorMA( org, p->width, right, verts[1].xyz ); + VectorArray2Set( verts[1].st, 0, 1 ); + Vector4Set( verts[1].modulate, 255, 255, 255, 255 * alpha ); + + // top-right + VectorMA( endPoint, p->width * 0.2f, right, verts[2].xyz ); // make the tip narrower + VectorArray2Set( verts[2].st, 1, 1 ); + Vector4Set( verts[2].modulate, 255, 255, 255, 255 * alpha ); + + // bottom-right, but copied to top-right, making it similar to a triangle + VectorCopy( verts[2].xyz, verts[3].xyz ); + VectorArray2Set( verts[3].st, 1, 0 ); + Vector4Set( verts[3].modulate, 255, 255, 255, 255 * alpha ); + + trap_R_AddPolyToScene( p->pshader, 4, verts ); + return; + } + + if (p->rotate) { VectorMA (org, -height, rup2, point); @@ -1332,6 +1373,7 @@ void CG_ParticleDebris (qhandle_t pshader, vec3_t origin, vec3_t vel, qboolean w ? 0 : 5; p->link = water; // if it's water, it'll stop above water + p->snum = 0; } void CG_ParticleSmoke (qhandle_t pshader, centity_t *cent) @@ -1480,7 +1522,7 @@ void CG_ParticleExplosion (char *animStr, vec3_t origin, vec3_t vel, int duratio } -void CG_ParticleSparks (vec3_t org, vec3_t vel, int duration, float x, float y, float speed) +void CG_ParticleSparks (qhandle_t pshader, vec3_t origin, vec3_t vel) { cparticle_t *p; @@ -1491,41 +1533,29 @@ void CG_ParticleSparks (vec3_t org, vec3_t vel, int duration, float x, float y, p->next = active_particles; active_particles = p; p->time = timenonscaled; - - p->endtime = timenonscaled + duration; - p->startfade = timenonscaled + duration/2; - - p->color = EMISIVEFADE; - p->alpha = 0.4f; - p->alphavel = 0; - - p->height = 0.5; - p->width = 0.5; - p->endheight = 0.5; - p->endwidth = 0.5; + p->endtime = timenonscaled + 400; - p->pshader = cgs.media.tracerShader; + p->color = 0; + p->alpha = 1; + p->alphavel = 0; + p->pshader = pshader; + p->height = p->width = (rand() % 10) + 5; - p->type = P_SMOKE; - - VectorCopy(org, p->org); + p->type = P_DEBRIS; - p->org[0] += (crandom() * x); - p->org[1] += (crandom() * y); + VectorCopy( origin, p->org ); - p->vel[0] = vel[0]; - p->vel[1] = vel[1]; - p->vel[2] = vel[2]; + p->start = origin[2]; - p->accel[0] = p->accel[1] = p->accel[2] = 0; + VectorCopy( vel, p->vel ); - p->vel[0] += (crandom() * 4); - p->vel[1] += (crandom() * 4); - p->vel[2] += (20 + (crandom() * 10)) * speed; + p->accel[0] = (crandom() * 450); + p->accel[1] = (crandom() * 450); + p->accel[2] = 250 + (crandom() * 50); - p->accel[0] = crandom () * 4; - p->accel[1] = crandom () * 4; - + p->roll = 0; // no bounce + p->link = qfalse; + p->snum = 1; // treat it as non-solid } void CG_ParticleDust (centity_t *cent, vec3_t origin, vec3_t dir) diff --git a/source/cgame/cg_weapons.c b/source/cgame/cg_weapons.c index f05500b..a83bc80 100644 --- a/source/cgame/cg_weapons.c +++ b/source/cgame/cg_weapons.c @@ -1542,10 +1542,35 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im // BFP - cg_oldRocket is unused on BFP, they forgot to remove //if (cg_oldRocket.integer == 0) { - int i; + int i, j; + // BFP - Spawn randomly the shaders with the particles + int shaderIndex; + vec3_t sparkOrg, sparkVel; + for ( i = 0; i < 26; ++i ) { - // BFP - Spawn randomly the debris shaders with the particles - int shaderIndex = rand() % 3; + shaderIndex = (rand() % 100) < 50 ? 0 : 1; // if the random range was rand() % 2, it would repeat the pattern without randomize correctly + + VectorMA( origin, 10, dir, sparkOrg ); + + // move faster + VectorScale( dir, 1500 + (rand() % 1000), sparkVel ); + sparkVel[0] += 1.5 * (rand() % 3500) - 1500; + sparkVel[1] += 1.5 * (rand() % 3500) - 1500; + sparkVel[2] += 1.5 * (rand() % 2100) - 1000; + + switch ( shaderIndex ) { + case 0: { + CG_ParticleSparks( cgs.media.sparkShader1, sparkOrg, sparkVel ); + break; + } + default: { + CG_ParticleSparks( cgs.media.sparkShader2, sparkOrg, sparkVel ); + } + } + } + + for ( j = 0; j < 26; ++j ) { + shaderIndex = rand() % 3; // BFP - That would be the range for debris particles VectorMA( origin, 24, dir, sprOrg ); From 258c68010a9d9fe066a9b944118fbcd6a621ddf4 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Wed, 25 Sep 2024 00:22:32 +0200 Subject: [PATCH 108/374] cgame: Add crack mark shader and replace all other mark shaders --- source/cgame/cg_local.h | 5 +++++ source/cgame/cg_main.c | 3 +++ source/cgame/cg_weapons.c | 34 ++++------------------------------ 3 files changed, 12 insertions(+), 30 deletions(-) diff --git a/source/cgame/cg_local.h b/source/cgame/cg_local.h index c0efd96..531b73a 100644 --- a/source/cgame/cg_local.h +++ b/source/cgame/cg_local.h @@ -728,6 +728,8 @@ typedef struct { qhandle_t botSkillShaders[5]; + // BFP - NOTE: These mark shaders are unused, they didn't remove. Remove them in the future? + // wall mark shaders qhandle_t wakeMarkShader; qhandle_t bloodMarkShader; @@ -736,6 +738,9 @@ typedef struct { qhandle_t holeMarkShader; qhandle_t energyMarkShader; + // BFP - Crack mark shader + qhandle_t crackMarkShader; + // powerup shaders qhandle_t quadShader; qhandle_t redQuadShader; diff --git a/source/cgame/cg_main.c b/source/cgame/cg_main.c index eee5ff0..6f6191c 100644 --- a/source/cgame/cg_main.c +++ b/source/cgame/cg_main.c @@ -676,6 +676,9 @@ static void CG_RegisterGraphics( void ) { cgs.media.wakeMarkShader = trap_R_RegisterShader( "wake" ); cgs.media.bloodMarkShader = trap_R_RegisterShader( "bloodMark" ); + // BFP - Crack mark shader + cgs.media.crackMarkShader = trap_R_RegisterShader( "crackMarkShader" ); + // BFP - Particle shaders cgs.media.pebbleShader1 = trap_R_RegisterShader( "pebbleShader1" ); // BFP - Rock particles for charging and explosion cgs.media.pebbleShader2 = trap_R_RegisterShader( "pebbleShader2" ); // BFP - Rock particles for charging and explosion diff --git a/source/cgame/cg_weapons.c b/source/cgame/cg_weapons.c index a83bc80..a64f952 100644 --- a/source/cgame/cg_weapons.c +++ b/source/cgame/cg_weapons.c @@ -1475,7 +1475,6 @@ Caused by an EV_MISSILE_MISS event, or directly by local bullet tracing */ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, impactSound_t soundType ) { qhandle_t mod; - qhandle_t mark; qhandle_t shader; sfxHandle_t sfx; float radius; @@ -1483,14 +1482,14 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im vec3_t lightColor; localEntity_t *le; int r; - qboolean alphaFade; qboolean isSprite; int duration; vec3_t sprOrg; vec3_t sprVel; - mark = 0; - radius = 32; + // BFP - NOTE: Crack mark shader replaces all other mark shaders, the radius is the same (64), there's no alpha fade + + radius = 64; sfx = 0; mod = 0; shader = 0; @@ -1515,15 +1514,11 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im } else { sfx = cgs.media.sfx_lghit3; } - mark = cgs.media.holeMarkShader; - radius = 12; break; case WP_GRENADE_LAUNCHER: mod = cgs.media.dishFlashModel; shader = cgs.media.grenadeExplosionShader; sfx = cgs.media.sfx_rockexp; - mark = cgs.media.burnMarkShader; - radius = 64; light = 300; isSprite = qtrue; break; @@ -1531,8 +1526,6 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im mod = cgs.media.dishFlashModel; shader = cgs.media.rocketExplosionShader; sfx = cgs.media.sfx_rockexp; - mark = cgs.media.burnMarkShader; - radius = 64; light = 300; isSprite = qtrue; duration = 1000; @@ -1603,35 +1596,26 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im mod = cgs.media.ringFlashModel; shader = cgs.media.railExplosionShader; sfx = cgs.media.sfx_plasmaexp; - mark = cgs.media.energyMarkShader; - radius = 24; break; case WP_PLASMAGUN: mod = cgs.media.ringFlashModel; shader = cgs.media.plasmaExplosionShader; sfx = cgs.media.sfx_plasmaexp; - mark = cgs.media.energyMarkShader; - radius = 16; break; case WP_BFG: mod = cgs.media.dishFlashModel; shader = cgs.media.bfgExplosionShader; sfx = cgs.media.sfx_rockexp; - mark = cgs.media.burnMarkShader; - radius = 32; isSprite = qtrue; break; case WP_SHOTGUN: mod = cgs.media.bulletFlashModel; shader = cgs.media.bulletExplosionShader; - mark = cgs.media.bulletMarkShader; sfx = 0; - radius = 4; break; case WP_MACHINEGUN: mod = cgs.media.bulletFlashModel; shader = cgs.media.bulletExplosionShader; - mark = cgs.media.bulletMarkShader; r = rand() & 3; if ( r == 0 ) { @@ -1642,7 +1626,6 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im sfx = cgs.media.sfx_ric3; } - radius = 8; break; } @@ -1668,16 +1651,7 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im // // impact mark // - alphaFade = (mark == cgs.media.energyMarkShader); // plasma fades alpha, all others fade color - if ( weapon == WP_RAILGUN ) { - float *color; - - // colorize with client color - color = cgs.clientinfo[clientNum].color2; - CG_ImpactMark( mark, origin, dir, random()*360, color[0],color[1], color[2],1, alphaFade, radius, qfalse ); - } else { - CG_ImpactMark( mark, origin, dir, random()*360, 1,1,1,1, alphaFade, radius, qfalse ); - } + CG_ImpactMark( cgs.media.crackMarkShader, origin, dir, random()*360, 1,1,1,1, 0, radius, qfalse ); } From 6f727d4e521b57774d481f561db6a015b6f27048 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Wed, 25 Sep 2024 01:15:54 +0200 Subject: [PATCH 109/374] cgame: Encapsulate debris and spark particles explosions into functions and apply these correctly in some weapons --- source/cgame/cg_event.c | 14 ++++ source/cgame/cg_local.h | 4 ++ source/cgame/cg_weapons.c | 143 ++++++++++++++++++++++---------------- 3 files changed, 101 insertions(+), 60 deletions(-) diff --git a/source/cgame/cg_event.c b/source/cgame/cg_event.c index c2d9f9a..62b09e4 100644 --- a/source/cgame/cg_event.c +++ b/source/cgame/cg_event.c @@ -871,18 +871,28 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { DEBUGNAME("EV_MISSILE_HIT"); ByteToDir( es->eventParm, dir ); CG_MissileHitPlayer( es->weapon, position, dir, es->otherEntityNum ); + // BFP - Spark particles explosion + CG_SparksExplosion( position, dir ); break; case EV_MISSILE_MISS: DEBUGNAME("EV_MISSILE_MISS"); ByteToDir( es->eventParm, dir ); CG_MissileHitWall( es->weapon, 0, position, dir, IMPACTSOUND_DEFAULT ); + // BFP - Debris particles explosion + CG_DebrisExplosion( position, dir ); + // BFP - Spark particles explosion + CG_SparksExplosion( position, dir ); break; case EV_MISSILE_MISS_METAL: DEBUGNAME("EV_MISSILE_MISS_METAL"); ByteToDir( es->eventParm, dir ); CG_MissileHitWall( es->weapon, 0, position, dir, IMPACTSOUND_METAL ); + // BFP - Debris particles explosion + CG_DebrisExplosion( position, dir ); + // BFP - Spark particles explosion + CG_SparksExplosion( position, dir ); break; // BFP - TODO: Implement EV_MISSILE_DETONATE (it has been used on ki grenade bounces and ki disc, that happens when these explode after some time) @@ -898,6 +908,10 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { if ( es->eventParm != 255 ) { ByteToDir( es->eventParm, dir ); CG_MissileHitWall( es->weapon, es->clientNum, position, dir, IMPACTSOUND_DEFAULT ); + // BFP - Debris particles explosion + CG_DebrisExplosion( position, dir ); + // BFP - Spark particles explosion + CG_SparksExplosion( position, dir ); } break; diff --git a/source/cgame/cg_local.h b/source/cgame/cg_local.h index 531b73a..23955e5 100644 --- a/source/cgame/cg_local.h +++ b/source/cgame/cg_local.h @@ -1222,6 +1222,10 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im void CG_MissileHitPlayer( int weapon, vec3_t origin, vec3_t dir, int entityNum ); void CG_ShotgunFire( entityState_t *es ); void CG_Bullet( vec3_t origin, int sourceEntityNum, vec3_t normal, qboolean flesh, int fleshEntityNum ); +// BFP - Debris particles explosion +void CG_DebrisExplosion( vec3_t origin, vec3_t dir ); +// BFP - Spark particles explosion +void CG_SparksExplosion( vec3_t origin, vec3_t dir ); void CG_RailTrail( clientInfo_t *ci, vec3_t start, vec3_t end ); void CG_GrappleTrail( centity_t *ent, const weaponInfo_t *wi ); diff --git a/source/cgame/cg_weapons.c b/source/cgame/cg_weapons.c index a64f952..5c2aa80 100644 --- a/source/cgame/cg_weapons.c +++ b/source/cgame/cg_weapons.c @@ -1465,6 +1465,87 @@ void CG_FireWeapon( centity_t *cent ) { } } +/* +================= +CG_DebrisExplosion +================= +*/ +void CG_DebrisExplosion( vec3_t origin, vec3_t dir ) { // BFP - Debris particles explosion + int i; + // spawn randomly the shaders with the particles + int shaderIndex; + vec3_t sprOrg, sprVel; + + // BFP - NOTE: Debris particles shouldn't be used for bullet and disk weapon types + + for ( i = 0; i < 26; ++i ) { + shaderIndex = rand() % 3; + + // that would be the range for debris particles + VectorMA( origin, 24, dir, sprOrg ); + sprOrg[0] += (rand() % 24); + sprOrg[1] += (rand() % 24); + sprOrg[2] += (rand() % 24); + + VectorScale( dir, 1500 + (rand() % 1000), sprVel ); + sprVel[0] += (rand() % 2800) - 1500; + sprVel[1] += (rand() % 2800) - 1500; + sprVel[2] += (rand() % 2200) - 1000; + + switch ( shaderIndex ) { + case 0: { + CG_ParticleDebris( cgs.media.pebbleShader1, sprOrg, sprVel, qfalse ); + break; + } + case 1: { + CG_ParticleDebris( cgs.media.pebbleShader2, sprOrg, sprVel, qfalse ); + break; + } + default: { + CG_ParticleDebris( cgs.media.pebbleShader3, sprOrg, sprVel, qfalse ); + } + } + } +} + +/* +================= +CG_SparksExplosion +================= +*/ +void CG_SparksExplosion( vec3_t origin, vec3_t dir ) { // BFP - Spark particles explosion + int i; + // spawn randomly the shaders with the particles + int shaderIndex; + vec3_t sparkOrg, sparkVel; + + // BFP - NOTE: Spark particles shouldn't be used on bullet and disk weapon types + + // BFP - TODO: Apply calling this function for finger blast and these rail gun weapon types when hitting a player + + for ( i = 0; i < 26; ++i ) { + shaderIndex = (rand() % 100) < 50 ? 0 : 1; // if the random range was rand() % 2, it would repeat the pattern without randomize correctly + + VectorMA( origin, 10, dir, sparkOrg ); + + // move faster + VectorScale( dir, 1500 + (rand() % 1000), sparkVel ); + sparkVel[0] += 1.5 * (rand() % 3500) - 1500; + sparkVel[1] += 1.5 * (rand() % 3500) - 1500; + sparkVel[2] += 1.5 * (rand() % 2100) - 1000; + + switch ( shaderIndex ) { + case 0: { + CG_ParticleSparks( cgs.media.sparkShader1, sparkOrg, sparkVel ); + break; + } + default: { + CG_ParticleSparks( cgs.media.sparkShader2, sparkOrg, sparkVel ); + } + } + } +} + /* ================= @@ -1484,8 +1565,6 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im int r; qboolean isSprite; int duration; - vec3_t sprOrg; - vec3_t sprVel; // BFP - NOTE: Crack mark shader replaces all other mark shaders, the radius is the same (64), there's no alpha fade @@ -1533,64 +1612,7 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im lightColor[1] = 0.75; lightColor[2] = 0.0; // BFP - cg_oldRocket is unused on BFP, they forgot to remove - //if (cg_oldRocket.integer == 0) - { - int i, j; - // BFP - Spawn randomly the shaders with the particles - int shaderIndex; - vec3_t sparkOrg, sparkVel; - - for ( i = 0; i < 26; ++i ) { - shaderIndex = (rand() % 100) < 50 ? 0 : 1; // if the random range was rand() % 2, it would repeat the pattern without randomize correctly - - VectorMA( origin, 10, dir, sparkOrg ); - - // move faster - VectorScale( dir, 1500 + (rand() % 1000), sparkVel ); - sparkVel[0] += 1.5 * (rand() % 3500) - 1500; - sparkVel[1] += 1.5 * (rand() % 3500) - 1500; - sparkVel[2] += 1.5 * (rand() % 2100) - 1000; - - switch ( shaderIndex ) { - case 0: { - CG_ParticleSparks( cgs.media.sparkShader1, sparkOrg, sparkVel ); - break; - } - default: { - CG_ParticleSparks( cgs.media.sparkShader2, sparkOrg, sparkVel ); - } - } - } - - for ( j = 0; j < 26; ++j ) { - shaderIndex = rand() % 3; - - // BFP - That would be the range for debris particles - VectorMA( origin, 24, dir, sprOrg ); - sprOrg[0] += (rand() % 24); - sprOrg[1] += (rand() % 24); - sprOrg[2] += (rand() % 24); - - VectorScale( dir, 1500 + (rand() % 1000), sprVel ); - sprVel[0] += (rand() % 2800) - 1500; - sprVel[1] += (rand() % 2800) - 1500; - sprVel[2] += (rand() % 2200) - 1000; - - switch ( shaderIndex ) { - case 0: { - CG_ParticleDebris( cgs.media.pebbleShader1, sprOrg, sprVel, qfalse ); - break; - } - case 1: { - CG_ParticleDebris( cgs.media.pebbleShader2, sprOrg, sprVel, qfalse ); - break; - } - default: { - CG_ParticleDebris( cgs.media.pebbleShader3, sprOrg, sprVel, qfalse ); - } - } - } - } + //if (cg_oldRocket.integer == 0) {} break; case WP_RAILGUN: mod = cgs.media.ringFlashModel; @@ -1651,6 +1673,7 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im // // impact mark // + // BFP - TODO: Disk type weapons don't leave a mark, apply it CG_ImpactMark( cgs.media.crackMarkShader, origin, dir, random()*360, 1,1,1,1, 0, radius, qfalse ); } From daa1ba4ec1595290e60320727c6b7fc5cffa8354 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Thu, 26 Sep 2024 12:53:21 +0200 Subject: [PATCH 110/374] cgame: Refactor and optimize for loops on trails --- source/cgame/cg_local.h | 2 +- source/cgame/cg_main.c | 4 +-- source/cgame/cg_trails.c | 75 +++++++++++++++++++++------------------- 3 files changed, 43 insertions(+), 38 deletions(-) diff --git a/source/cgame/cg_local.h b/source/cgame/cg_local.h index 23955e5..77b3eac 100644 --- a/source/cgame/cg_local.h +++ b/source/cgame/cg_local.h @@ -1274,7 +1274,7 @@ void CG_ScorePlum( int client, vec3_t org, int score ); // // cg_trails.c // -void CG_InitKiTrails( void ); +void CG_InitTrails( void ); void CG_ResetKiTrail( int entityNum, vec3_t origin ); void CG_KiTrail( int entityNum, vec3_t origin, qboolean remove, qhandle_t hShader ); diff --git a/source/cgame/cg_main.c b/source/cgame/cg_main.c index 6f6191c..658a491 100644 --- a/source/cgame/cg_main.c +++ b/source/cgame/cg_main.c @@ -900,8 +900,8 @@ void CG_Init( int serverMessageNum, int serverCommandSequence, int clientNum ) { CG_InitMarkPolys(); - // BFP - Initialize ki trails - CG_InitKiTrails(); + // BFP - Initialize trails + CG_InitTrails(); // remove the last loading update cg.infoScreenText[0] = 0; diff --git a/source/cgame/cg_trails.c b/source/cgame/cg_trails.c index 1fba716..15242e8 100644 --- a/source/cgame/cg_trails.c +++ b/source/cgame/cg_trails.c @@ -1,25 +1,34 @@ +/* +=========================================================================== + +BFP TRAILS + +=========================================================================== +*/ + + #include "cg_local.h" -#define KI_TRAIL_SEGMENTS 99 -#define KI_TRAIL_WIDTH 15 +#define TRAIL_SEGMENTS 99 +#define TRAIL_WIDTH 15 typedef struct { - vec3_t segments[KI_TRAIL_SEGMENTS]; + vec3_t segments[TRAIL_SEGMENTS]; int numSegments; -} kiTrail_t; +} trail_t; -static kiTrail_t cg_kiTrails[MAX_GENTITIES]; +static trail_t cg_trails[MAX_GENTITIES]; /* =============== -CG_InitKiTrails +CG_InitTrails Initializes the array of trails for all centities. Should be called from CG_Init in cg_main.c =============== */ -void CG_InitKiTrails( void ) { - memset( &cg_kiTrails, 0, sizeof(cg_kiTrails) ); +void CG_InitTrails( void ) { + memset( &cg_trails, 0, sizeof(cg_trails) ); } /* @@ -36,10 +45,10 @@ origin: Point from where the trail should start. void CG_ResetKiTrail( int entityNum, vec3_t origin ) { int i; - for ( i = 0; i < KI_TRAIL_SEGMENTS; i++ ) { - VectorCopy( origin, cg_kiTrails[entityNum].segments[i] ); + for ( i = 0; i < TRAIL_SEGMENTS; ++i ) { + VectorCopy( origin, cg_trails[entityNum].segments[i] ); } - cg_kiTrails[entityNum].numSegments = 0; + cg_trails[entityNum].numSegments = 0; } /* @@ -58,63 +67,59 @@ void CG_KiTrail( int entityNum, vec3_t origin, qboolean remove, qhandle_t hShade } if ( remove ) { // removes every segment - cg_kiTrails[entityNum].numSegments--; + cg_trails[entityNum].numSegments--; } else { - if ( cg_kiTrails[entityNum].numSegments < KI_TRAIL_SEGMENTS ) { - cg_kiTrails[entityNum].numSegments++; + if ( cg_trails[entityNum].numSegments < TRAIL_SEGMENTS ) { + cg_trails[entityNum].numSegments++; } } // shift points down the buffer - for ( i = cg_kiTrails[entityNum].numSegments - 1; i > 0; i-- ) { - VectorCopy( cg_kiTrails[entityNum].segments[i - 1], cg_kiTrails[entityNum].segments[i] ); + for ( i = cg_trails[entityNum].numSegments - 1; i > 0; --i ) { + VectorCopy( cg_trails[entityNum].segments[i - 1], cg_trails[entityNum].segments[i] ); } // add the current position at the start - VectorCopy( origin, cg_kiTrails[entityNum].segments[0] ); + VectorCopy( origin, cg_trails[entityNum].segments[0] ); - for ( i = 0; i < cg_kiTrails[entityNum].numSegments - 1; i++ ) { + for ( i = 0; i < cg_trails[entityNum].numSegments - 1; ++i ) { // loop to render the segment 3 times - for ( j = 0; j < 3; j++ ) { + for ( j = 0; j < 3; ++j ) { vec3_t start, end, forward, right; - vec3_t viewAxis[3]; + vec3_t viewAxis; int kiTrailLength = cg_kiTrail.integer; - if ( kiTrailLength > KI_TRAIL_SEGMENTS ) { - kiTrailLength = KI_TRAIL_SEGMENTS; - } - - if ( i > kiTrailLength ) { - return; + if ( kiTrailLength > TRAIL_SEGMENTS ) { + kiTrailLength = TRAIL_SEGMENTS; } - if ( i + j >= cg_kiTrails[entityNum].numSegments - 1 ) { + if ( i + j >= cg_trails[entityNum].numSegments - 1 ) { return; } - VectorCopy( cg_kiTrails[entityNum].segments[i + j], start ); - VectorCopy( cg_kiTrails[entityNum].segments[i + j + 1], end ); + VectorCopy( cg_trails[entityNum].segments[i + j], start ); + VectorCopy( cg_trails[entityNum].segments[i + j + 1], end ); VectorSubtract( end, start, forward ); VectorNormalize( forward ); - VectorSubtract( cg.refdef.vieworg, start, viewAxis[0] ); - CrossProduct( viewAxis[0], forward, right ); + VectorSubtract( cg.refdef.vieworg, start, viewAxis ); + CrossProduct( viewAxis, forward, right ); VectorNormalize( right ); - VectorMA( end, KI_TRAIL_WIDTH, right, verts[0].xyz ); + VectorMA( end, TRAIL_WIDTH, right, verts[0].xyz ); VectorArray2Set( verts[0].st, 0, 1 ); Vector4Set( verts[0].modulate, 255, 255, 255, 255 ); - VectorMA( end, -KI_TRAIL_WIDTH, right, verts[1].xyz ); + VectorMA( end, -TRAIL_WIDTH, right, verts[1].xyz ); VectorArray2Set( verts[1].st, 1, 0 ); Vector4Set( verts[1].modulate, 255, 255, 255, 255 ); - VectorMA( start, -KI_TRAIL_WIDTH, right, verts[2].xyz ); + VectorMA( start, -TRAIL_WIDTH, right, verts[2].xyz ); VectorArray2Set( verts[2].st, 1, 0 ); Vector4Set( verts[2].modulate, 255, 255, 255, 255 ); - VectorMA( start, KI_TRAIL_WIDTH, right, verts[3].xyz ); + VectorMA( start, TRAIL_WIDTH, right, verts[3].xyz ); VectorArray2Set( verts[3].st, 0, 1 ); Vector4Set( verts[3].modulate, 255, 255, 255, 255 ); From c38ad0b33f271f656e8182ce2ae7420943ad7508 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 30 Sep 2024 16:21:05 +0200 Subject: [PATCH 111/374] q3_ui: On CREDITS menu, make black box header fade initially, make background shader macro empty by default (but with path commented), apply a logic conditional checks if the shader exists and refactor background shader variable --- source/q3_ui/ui_credits.c | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/source/q3_ui/ui_credits.c b/source/q3_ui/ui_credits.c index 9c7cefd..7e7919e 100644 --- a/source/q3_ui/ui_credits.c +++ b/source/q3_ui/ui_credits.c @@ -33,9 +33,7 @@ CREDITS #define ART_BFPLOGO "menu/art/bfp_logol" // BFP - Logo #define SCROLLSPEED 6.50 // The scrolling speed in pixels per second. Modify as appropriate for our credits -// uncomment this to use a background shader: -// #define BACKGROUND_SHADER -#define ART_MENUBG "menu/art/menubg" // BFP - Menu background +#define ART_MENUBG "" // "menu/art/menubg" // BFP - Menu background typedef struct { menuframework_s menu; @@ -47,13 +45,12 @@ static creditsmenu_t s_credits; int starttime; // game time at which credits are started float mvolume; // records the original music volume level, as we will. Modify it for the credits -qhandle_t BackgroundShader; // definition of the background shader pointer +qhandle_t backgroundShader; // definition of the background shader pointer -typedef struct -{ - char *string; - int style; - vec4_t *colour; +typedef struct { + char *string; + int style; + vec4_t *colour; } cr_line; // BFP - Macros for credits. This way is easier to add in the array @@ -206,9 +203,9 @@ Draws header. */ static void Credits_DrawHeader( void ) // BFP - Header { - // BFP - NOTE: It would be cool using a fading box or not. - // BFP vanilla uses a black box on it and pop ups when text alpha color is near to 0.90f -#define BLACK_BOX_FADE 0 + // BFP - NOTE: BFP vanilla uses a black box on it and pop ups when text alpha color is near to 0.90f + // But in that case, to make it better, black box fades initially +#define BLACK_BOX_FADE 1 float fadetime; vec4_t fadeBluecolour = { 0.00f, 0.00f, 1.00f, 0.00f }; #if BLACK_BOX_FADE @@ -275,9 +272,9 @@ static void ScrollingCredits_Draw( void ) // first, fill the background with the specified colour/shader // we are drawing a shader -#ifdef BACKGROUND_SHADER - UI_DrawHandlePic(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, BackgroundShader); -#endif + if ( backgroundShader ) { + UI_DrawHandlePic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, backgroundShader ); + } // let's draw the stuff // set initial y location @@ -353,9 +350,5 @@ void UI_CreditMenu( void ) { #endif // load the background shader -#ifdef BACKGROUND_SHADER - BackgroundShader = - trap_R_RegisterShaderNoMip( ART_MENUBG ); -#undef BACKGROUND_SHADER -#endif + backgroundShader = trap_R_RegisterShaderNoMip( ART_MENUBG ); } From 43370366a777cdaeded66bb46735101e48ff30b2 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Tue, 15 Oct 2024 03:35:28 +0200 Subject: [PATCH 112/374] cgame: Change(or revert) rail trail effect to Q3 SDK first version release --- source/cgame/cg_weapons.c | 130 +++++++++++++------------------------- 1 file changed, 44 insertions(+), 86 deletions(-) diff --git a/source/cgame/cg_weapons.c b/source/cgame/cg_weapons.c index 5c2aa80..f0ea029 100644 --- a/source/cgame/cg_weapons.c +++ b/source/cgame/cg_weapons.c @@ -177,46 +177,31 @@ static void CG_ShotgunEjectBrass( centity_t *cent ) { CG_RailTrail ========================== */ -void CG_RailTrail (clientInfo_t *ci, vec3_t start, vec3_t end) { - vec3_t axis[36], move, move2, next_move, vec, temp; - float len; - int i, j, skip; - +void CG_RailTrail ( clientInfo_t *ci, vec3_t start, vec3_t end ) { // BFP - BFP uses an old version of rail trail on Quake 3 Arena 1st version release localEntity_t *le; refEntity_t *re; - -#define RADIUS 4 -#define ROTATION 1 -#define SPACING 5 - - start[2] -= 4; - VectorCopy (start, move); - VectorSubtract (end, start, vec); - len = VectorNormalize (vec); - PerpendicularVector(temp, vec); - for (i = 0 ; i < 36; i++) { - RotatePointAroundVector(axis[i], vec, temp, i * 10);//banshee 2.4 was 10 - } - + + // + // rings + // le = CG_AllocLocalEntity(); re = &le->refEntity; - + le->leType = LE_FADE_RGB; le->startTime = cg.time; le->endTime = cg.time + cg_railTrailTime.value; - le->lifeRate = 1.0 / (le->endTime - le->startTime); - + le->lifeRate = 1.0 / ( le->endTime - le->startTime ); + re->shaderTime = cg.time / 1000.0f; - re->reType = RT_RAIL_CORE; - re->customShader = cgs.media.railCoreShader; - - VectorCopy(start, re->origin); - VectorCopy(end, re->oldorigin); - - re->shaderRGBA[0] = ci->color1[0] * 255; - re->shaderRGBA[1] = ci->color1[1] * 255; - re->shaderRGBA[2] = ci->color1[2] * 255; - re->shaderRGBA[3] = 255; + re->reType = RT_RAIL_RINGS; + re->customShader = cgs.media.railRingsShader; + + VectorCopy( start, re->origin ); + VectorCopy( end, re->oldorigin ); + + // nudge down a bit so it isn't exactly in center + re->origin[2] -= 8; + re->oldorigin[2] -= 8; le->color[0] = ci->color1[0] * 0.75; le->color[1] = ci->color1[1] * 0.75; @@ -224,62 +209,35 @@ void CG_RailTrail (clientInfo_t *ci, vec3_t start, vec3_t end) { le->color[3] = 1.0f; AxisClear( re->axis ); - - VectorMA(move, 20, vec, move); - VectorCopy(move, next_move); - VectorScale (vec, SPACING, vec); - - if (cg_oldRail.integer != 0) { - // nudge down a bit so it isn't exactly in center - re->origin[2] -= 8; - re->oldorigin[2] -= 8; - return; - } - skip = -1; - - j = 18; - for (i = 0; i < len; i += SPACING) { - if (i != skip) { - skip = i + SPACING; - le = CG_AllocLocalEntity(); - re = &le->refEntity; - le->leFlags = LEF_PUFF_DONT_SCALE; - le->leType = LE_MOVE_SCALE_FADE; - le->startTime = cg.time; - le->endTime = cg.time + (i>>1) + 600; - le->lifeRate = 1.0 / (le->endTime - le->startTime); - - re->shaderTime = cg.time / 1000.0f; - re->reType = RT_SPRITE; - re->radius = 1.1f; - re->customShader = cgs.media.railRingsShader; - - re->shaderRGBA[0] = ci->color2[0] * 255; - re->shaderRGBA[1] = ci->color2[1] * 255; - re->shaderRGBA[2] = ci->color2[2] * 255; - re->shaderRGBA[3] = 255; - - le->color[0] = ci->color2[0] * 0.75; - le->color[1] = ci->color2[1] * 0.75; - le->color[2] = ci->color2[2] * 0.75; - le->color[3] = 1.0f; - - le->pos.trType = TR_LINEAR; - le->pos.trTime = cg.time; - - VectorCopy( move, move2); - VectorMA(move2, RADIUS , axis[j], move2); - VectorCopy(move2, le->pos.trBase); - - le->pos.trDelta[0] = axis[j][0]*6; - le->pos.trDelta[1] = axis[j][1]*6; - le->pos.trDelta[2] = axis[j][2]*6; - } - VectorAdd (move, vec, move); + // + // core + // + le = CG_AllocLocalEntity(); + re = &le->refEntity; + + le->leType = LE_FADE_RGB; + le->startTime = cg.time; + le->endTime = cg.time + cg_railTrailTime.value; + le->lifeRate = 1.0 / ( le->endTime - le->startTime ); - j = j + ROTATION < 36 ? j + ROTATION : (j + ROTATION) % 36; - } + re->shaderTime = cg.time / 1000.0f; + re->reType = RT_RAIL_CORE; + re->customShader = cgs.media.railCoreShader; + + VectorCopy( start, re->origin ); + VectorCopy( end, re->oldorigin ); + + // nudge down a bit so it isn't exactly in center + re->origin[2] -= 8; + re->oldorigin[2] -= 8; + + le->color[0] = ci->color1[0] * 0.75; + le->color[1] = ci->color1[1] * 0.75; + le->color[2] = ci->color1[2] * 0.75; + le->color[3] = 1.0f; + + AxisClear( re->axis ); } /* From 38fe7bdd128af3c366fe2d17d4601502593b2a0f Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Tue, 15 Oct 2024 04:01:41 +0200 Subject: [PATCH 113/374] cgame: Implement explosions, dynamic explosion lights, big explosions and low sphere option. Not completed yet, so the skin config will be applied later. And low rock debris particles falling speed --- docs/bfp_cvars_task.md | 11 ++-- source/cgame/cg_cvar.h | 11 ++++ source/cgame/cg_effects.c | 42 +++++++++++++ source/cgame/cg_local.h | 31 +++++++--- source/cgame/cg_localents.c | 25 +++++++- source/cgame/cg_main.c | 11 ++++ source/cgame/cg_particles.c | 79 +++++++++++++++++++++++- source/cgame/cg_weapons.c | 116 +++++++++++++++++++++++++++--------- 8 files changed, 283 insertions(+), 43 deletions(-) diff --git a/docs/bfp_cvars_task.md b/docs/bfp_cvars_task.md index d820e4a..f5f42af 100644 --- a/docs/bfp_cvars_task.md +++ b/docs/bfp_cvars_task.md @@ -34,12 +34,7 @@ ## DONE BUT NOT IN CGAME: - cg_stfu [0/1]: disable character voices when firing attacks. -- cg_lowpolysphere [0/1]: force the use of a lower polycount sphere. -- cg_lightExplosions [0/1]: turn on or off the explosion dynamic lights. - cg_chargeupAlert [0/1]: turn on or off the "ready" message when charging attacks. -- cg_explosionShell [0/1]: turn on or off the explosion shell. -- cg_explosionSmoke [0/1]: turn on or off the explosion smoke. -- cg_explosionRing [0/1]: turn on or off the explosion ring. ## COMPLETED: @@ -75,6 +70,12 @@ - [x] ~~g_meleeRange~~ - [x] ~~g_meleeDiveRange~~ - [x] ~~g_meleeDamage~~ +- [x] ~~cg_lowpolysphere~~ +- [x] ~~cg_bigExplosions~~ +- [x] ~~cg_lightExplosions~~ +- [x] ~~cg_explosionShell~~ +- [x] ~~cg_explosionSmoke~~ +- [x] ~~cg_explosionRing~~ #### Cvar Gametypes: diff --git a/source/cgame/cg_cvar.h b/source/cgame/cg_cvar.h index 71d22cf..dfb88b5 100644 --- a/source/cgame/cg_cvar.h +++ b/source/cgame/cg_cvar.h @@ -66,6 +66,12 @@ CG_CVAR( cg_footsteps, "cg_footsteps", "1", CVAR_CHEAT ) CG_CVAR( cg_tracerChance, "cg_tracerchance", "0.4", CVAR_CHEAT ) CG_CVAR( cg_tracerWidth, "cg_tracerwidth", "1", CVAR_CHEAT ) CG_CVAR( cg_tracerLength, "cg_tracerlength", "100", CVAR_CHEAT ) +CG_CVAR( cg_lowpolysphere, "cg_lowpolysphere", "0", CVAR_ARCHIVE ) // BFP - Low poly sphere +CG_CVAR( cg_bigExplosions, "cg_bigExplosions", "1", CVAR_ARCHIVE ) // BFP - Big explosions +CG_CVAR( cg_explosionRing, "cg_explosionRing", "1", CVAR_ARCHIVE ) // BFP - Explosion ring +CG_CVAR( cg_explosionShell, "cg_explosionShell", "1", CVAR_ARCHIVE ) // BFP - Explosion shell +CG_CVAR( cg_explosionSmoke, "cg_explosionSmoke", "1", CVAR_ARCHIVE ) // BFP - Explosion smoke +CG_CVAR( cg_lightExplosions, "cg_lightExplosions", "1", CVAR_ARCHIVE ) // BFP - Dynamic explosion lights CG_CVAR( cg_flytilt, "cg_flytilt", "1", CVAR_ARCHIVE ) // BFP - Fly tilt CG_CVAR( cg_kiTrail, "cg_kiTrail", "50", CVAR_ARCHIVE ) // BFP - Ki trail length CG_CVAR( cg_playHitSound, "cg_playHitSound", "0", CVAR_ARCHIVE ) // BFP - Play hit sound @@ -120,10 +126,15 @@ CG_CVAR( cg_noTaunt, "cg_noTaunt", "0", CVAR_ARCHIVE ) CG_CVAR( cg_noProjectileTrail, "cg_noProjectileTrail", "0", CVAR_ARCHIVE ) CG_CVAR( cg_smallFont, "ui_smallFont", "0.25", CVAR_ARCHIVE ) CG_CVAR( cg_bigFont, "ui_bigFont", "0.4", CVAR_ARCHIVE ) + +/* +// BFP - Remove these unused cvars from the code in the future CG_CVAR( cg_oldRail, "cg_oldRail", "1", CVAR_ARCHIVE ) CG_CVAR( cg_oldRocket, "cg_oldRocket", "1", CVAR_ARCHIVE ) CG_CVAR( cg_oldPlasma, "cg_oldPlasma", "1", CVAR_ARCHIVE ) CG_CVAR( cg_trueLightning, "cg_trueLightning", "0.0", CVAR_ARCHIVE ) +*/ + //CG_CVAR( cg_pmove_fixed, "cg_pmove_fixed", "0", CVAR_USERINFO | CVAR_ARCHIVE ) #undef CG_CVAR diff --git a/source/cgame/cg_effects.c b/source/cgame/cg_effects.c index 73c6656..f058e97 100644 --- a/source/cgame/cg_effects.c +++ b/source/cgame/cg_effects.c @@ -294,6 +294,48 @@ localEntity_t *CG_MakeExplosion( vec3_t origin, vec3_t dir, return ex; } +/* +==================== +CG_SpawnExplosion +==================== +*/ +localEntity_t *CG_SpawnExplosion( vec3_t origin, vec3_t dir, leType_t type, qhandle_t hModel, qhandle_t shader, float duration ) { // BFP - Explosion sphere, shell and ring effect + localEntity_t *le; + vec3_t newOrigin; + + le = CG_AllocLocalEntity(); + + le->leType = type; + + le->refEntity.hModel = hModel; + le->refEntity.customShader = shader; + + VectorCopy( origin, newOrigin ); + + if ( !dir ) { + AxisClear( le->refEntity.axis ); + } else { + VectorCopy( dir, le->refEntity.axis[0] ); + RotateAroundDirection( le->refEntity.axis, 0 ); + } + + VectorCopy( origin, le->refEntity.origin ); + VectorCopy( newOrigin, le->refEntity.oldorigin ); + + le->refEntity.reType = RT_MODEL; + + le->color[0] = le->color[1] = le->color[2] = 1.0; + + le->startTime = cg.time - (rand() & 63); + le->lifeRate = duration; + le->endTime = le->startTime + le->lifeRate; + + // bias the time so all shader effects start correctly + le->refEntity.shaderTime = cg.time / 1000.0f; + + return le; +} + /* ================= diff --git a/source/cgame/cg_local.h b/source/cgame/cg_local.h index 77b3eac..c7d558b 100644 --- a/source/cgame/cg_local.h +++ b/source/cgame/cg_local.h @@ -211,6 +211,8 @@ typedef struct markPoly_s { typedef enum { LE_MARK, LE_EXPLOSION, + LE_EXPLOSION_RING, // BFP - Explosion ring + LE_EXPLOSION_SHELL, // BFP - Explosion shell LE_SPRITE_EXPLOSION, LE_FRAGMENT, LE_MOVE_SCALE_FADE, @@ -759,6 +761,15 @@ typedef struct { qhandle_t dishFlashModel; qhandle_t lightningExplosionModel; + // BFP - Explosion, projectile and beam models + qhandle_t nukeModel; + qhandle_t lowPolySphereModel; + qhandle_t highPolySphereModel; + qhandle_t beamModel; + + // BFP - Explosion shell shader + qhandle_t explosionShellShader; + // weapon effect shaders qhandle_t railExplosionShader; qhandle_t plasmaExplosionShader; @@ -1270,14 +1281,6 @@ void CG_BubbleTrail( vec3_t start, vec3_t end, float spacing ); void CG_SpawnEffect( vec3_t org ); void CG_ScorePlum( int client, vec3_t org, int score ); -// BFP - Ki trail -// -// cg_trails.c -// -void CG_InitTrails( void ); -void CG_ResetKiTrail( int entityNum, vec3_t origin ); -void CG_KiTrail( int entityNum, vec3_t origin, qboolean remove, qhandle_t hShader ); - void CG_GibPlayer( vec3_t playerOrigin ); void CG_BigExplode( vec3_t playerOrigin ); @@ -1286,6 +1289,16 @@ void CG_Bleed( vec3_t origin, int entityNum ); localEntity_t *CG_MakeExplosion( vec3_t origin, vec3_t dir, qhandle_t hModel, qhandle_t shader, int msec, qboolean isSprite ); +// BFP - Explosion effect +localEntity_t *CG_SpawnExplosion( vec3_t origin, vec3_t dir, leType_t type, qhandle_t hModel, qhandle_t shader, float duration ); + +// BFP - Ki trail +// +// cg_trails.c +// +void CG_InitTrails( void ); +void CG_ResetKiTrail( int entityNum, vec3_t origin ); +void CG_KiTrail( int entityNum, vec3_t origin, qboolean remove, qhandle_t hShader ); // // cg_snapshot.c @@ -1532,6 +1545,8 @@ void CG_ParticleExplosion (char *animStr, vec3_t origin, vec3_t vel, int duratio void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_t origin2, int turbtime, float range); // BFP - Dash smoke particle for ki boost when moving in the ground void CG_ParticleDashSmoke (centity_t *cent, qhandle_t pshader, vec3_t origin); +// BFP - Explosion smoke particle +void CG_ParticleExplosionSmoke (int radius, int lifetime, int speed, qhandle_t pshader, vec3_t origin); // BFP - Antigrav rock particles for charging void CG_ParticleAntigravRock (qhandle_t pshader, centity_t *cent, int entityNum, vec3_t origin); void CG_AntigravRockHandling (centity_t *cent); diff --git a/source/cgame/cg_localents.c b/source/cgame/cg_localents.c index 53ec373..3326d21 100644 --- a/source/cgame/cg_localents.c +++ b/source/cgame/cg_localents.c @@ -476,11 +476,32 @@ static void CG_AddExplosion( localEntity_t *ex ) { ent = &ex->refEntity; + if ( cg_bigExplosions.integer > 0 ) { // BFP - Big explosions + float scale = 1.04f; + float endTime = (float)( ex->endTime ) - (float)( ex->lifeRate * 0.5 ); + float endScale = (float)( ex->endTime - cg.time ) / (float)( ex->endTime - ex->startTime ); + + switch( ex->leType ) { + case LE_EXPLOSION: + if ( cg.time > endTime ) { + scale = 0.9f * ( endScale + 0.5f ); // decrease size + } + break; + case LE_EXPLOSION_SHELL: + scale = 1.12f; // scale faster than the explosion sphere + break; + } + + VectorScale( ent->axis[0], scale, ent->axis[0] ); + VectorScale( ent->axis[1], scale, ent->axis[1] ); + VectorScale( ent->axis[2], scale, ent->axis[2] ); + } + // add the entity trap_R_AddRefEntityToScene(ent); // add the dlight - if ( ex->light ) { + if ( cg_lightExplosions.integer > 0 ) { // BFP - Dynamic explosion lights float light; light = (float)( cg.time - ex->startTime ) / ( ex->endTime - ex->startTime ); @@ -661,6 +682,8 @@ void CG_AddLocalEntities( void ) { break; case LE_EXPLOSION: + case LE_EXPLOSION_RING: // BFP - Explosion ring + case LE_EXPLOSION_SHELL: // BFP - Explosion shell CG_AddExplosion( le ); break; diff --git a/source/cgame/cg_main.c b/source/cgame/cg_main.c index 658a491..51451b5 100644 --- a/source/cgame/cg_main.c +++ b/source/cgame/cg_main.c @@ -621,6 +621,17 @@ static void CG_RegisterGraphics( void ) { cgs.media.bulletFlashModel = trap_R_RegisterModel("models/weaphits/bullet.md3"); cgs.media.ringFlashModel = trap_R_RegisterModel("models/weaphits/ring02.md3"); cgs.media.dishFlashModel = trap_R_RegisterModel("models/weaphits/boom01.md3"); + // BFP - Explosion, projectile and beam models + cgs.media.nukeModel = trap_R_RegisterModel( "models/weaphits/nuke.md3" ); + cgs.media.lowPolySphereModel = trap_R_RegisterModel( "models/weaphits/sphere.md3" ); + cgs.media.highPolySphereModel = trap_R_RegisterModel( "models/weaphits/sphere_hi.md3" ); + cgs.media.beamModel = trap_R_RegisterModel( "models/weaphits/beam.md3" ); + + // BFP - Explosion shell shader + cgs.media.explosionShellShader = trap_R_RegisterShader( "explosionShellShader" ); + // BFP - Explosion ring shader (reused rail gun explosion) + cgs.media.railExplosionShader = trap_R_RegisterShader( "railExplosion" ); + cgs.media.teleportEffectModel = trap_R_RegisterModel( "models/misc/telep.md3" ); cgs.media.teleportEffectShader = trap_R_RegisterShader( "teleportEffect" ); diff --git a/source/cgame/cg_particles.c b/source/cgame/cg_particles.c index f28aabe..53f2143 100644 --- a/source/cgame/cg_particles.c +++ b/source/cgame/cg_particles.c @@ -503,7 +503,7 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) } } else { if ( trace.fraction <= 0 ) { - p->roll = 4; + p->roll = 3; } else { p->vel[2] = (p->roll > 0) ? 500 * p->roll : 0; p->accel[2] = (p->roll > 0) ? 500 * p->roll : 0; @@ -566,6 +566,28 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) return; } + if (p->type == P_SMOKE_IMPACT && p->link // BFP - Explosion smoke particle + && timenonscaled > p->endtime - p->end) { + int i; + // decelerate + for (i = 0; i < 2; ++i) { + p->vel[i] *= 0.99; + + // if the velocity is very small, clamp it to zero + if (fabs(p->vel[i]) < 1) { + p->vel[i] = 0; + } + } + + for (i = 0; i < 2; ++i) { + p->accel[i] *= 0.99; + + // if the acceleration is very small, clamp it to zero + if (fabs(p->accel[i]) < 1) { + p->accel[i] = 0; + } + } + } if (p->rotate) { @@ -934,6 +956,9 @@ void CG_AddParticles (void) org[0] = p->org[0] + p->vel[0]*time + p->accel[0]*time2; org[1] = p->org[1] + p->vel[1]*time + p->accel[1]*time2; org[2] = p->org[2] + p->vel[2]*time + p->accel[2]*time2; + if ( p->type == P_SMOKE_IMPACT && p->link ) { // BFP - Explosion smoke particle moving in a static way + org[2] = p->org[2] + p->vel[2]*time + p->accel[2]*time; + } type = p->type; @@ -1151,6 +1176,56 @@ void CG_ParticleDashSmoke (centity_t *cent, qhandle_t pshader, vec3_t origin) crandom() * 10, crandom() * 10, 1400 ); + + p->link = qfalse; // to distinguish the type of smoke +} + +// BFP - Particle for explosion smoke +void CG_ParticleExplosionSmoke (int radius, int lifetime, int speed, qhandle_t pshader, vec3_t origin) +{ + cparticle_t *p; + + // if (!pshader) CG_Printf ("CG_ParticleExplosionSmoke pshader == ZERO!\n"); + + if (!free_particles) + return; + + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->time = timenonscaled; + + p->alpha = 0.4; + p->alphavel = -0.01; + + p->pshader = pshader; + + p->endtime = timenonscaled + lifetime; + p->end = lifetime - 350; + + p->startfade = timenonscaled + lifetime; + + p->height = p->width = radius; + + p->endheight = p->height * 2; + p->endwidth = p->width * 2; + + p->type = P_SMOKE_IMPACT; + + VectorCopy( origin, p->org ); + p->org[2] += (crandom() * 25); + + VectorSet( p->vel, + (rand() % 701) - 200, + (rand() % 701) - 200, + speed ); + + p->accel[0] = p->accel[1] = 0; + p->accel[2] = 500; + + p->link = qtrue; // to distinguish the type of smoke } // BFP - Antigrav rock particles for ki charging status @@ -1371,7 +1446,7 @@ void CG_ParticleDebris (qhandle_t pshader, vec3_t origin, vec3_t vel, qboolean w p->roll = (water) // used as bounce counter ? 0 - : 5; + : 3; p->link = water; // if it's water, it'll stop above water p->snum = 0; } diff --git a/source/cgame/cg_weapons.c b/source/cgame/cg_weapons.c index f0ea029..088acf5 100644 --- a/source/cgame/cg_weapons.c +++ b/source/cgame/cg_weapons.c @@ -328,7 +328,7 @@ static void CG_PlasmaTrail( centity_t *cent, const weaponInfo_t *wi ) { float waterScale = 1.0f; - if ( cg_noProjectileTrail.integer || cg_oldPlasma.integer ) { + if ( cg_noProjectileTrail.integer ) { return; } @@ -806,6 +806,8 @@ static void CG_LightningBolt( centity_t *cent, vec3_t origin ) { memset( &beam, 0, sizeof( beam ) ); + // BFP - Unused true lightning logic effect, remove in the future +#if 0 // CPMA "true" lightning if ((cent->currentState.number == cg.predictedPlayerState.clientNum) && (cg_trueLightning.value != 0)) { vec3_t angle; @@ -832,7 +834,9 @@ static void CG_LightningBolt( centity_t *cent, vec3_t origin ) { AngleVectors(angle, forward, NULL, NULL ); VectorCopy(cent->lerpOrigin, muzzlePoint ); // VectorCopy(cg.refdef.vieworg, muzzlePoint ); - } else { + } else +#endif + { // !CPMA AngleVectors( cent->lerpAngles, forward, NULL, NULL ); VectorCopy(cent->lerpOrigin, muzzlePoint ); @@ -1433,10 +1437,13 @@ void CG_DebrisExplosion( vec3_t origin, vec3_t dir ) { // BFP - Debris particles // spawn randomly the shaders with the particles int shaderIndex; vec3_t sprOrg, sprVel; + int numRocks = 26; // BFP - NOTE: Debris particles shouldn't be used for bullet and disk weapon types - for ( i = 0; i < 26; ++i ) { + // BFP - TODO: Apply number of rocks as indicated on default.cfg file of some character: explosionRocks + + for ( i = 0; i < numRocks; ++i ) { shaderIndex = rand() % 3; // that would be the range for debris particles @@ -1476,15 +1483,18 @@ void CG_SparksExplosion( vec3_t origin, vec3_t dir ) { // BFP - Spark particles // spawn randomly the shaders with the particles int shaderIndex; vec3_t sparkOrg, sparkVel; + int numSparks = 26; // BFP - NOTE: Spark particles shouldn't be used on bullet and disk weapon types // BFP - TODO: Apply calling this function for finger blast and these rail gun weapon types when hitting a player - for ( i = 0; i < 26; ++i ) { + // BFP - TODO: Apply number of sparks as indicated on default.cfg file of some character: explosionSparks + + for ( i = 0; i < numSparks; ++i ) { shaderIndex = (rand() % 100) < 50 ? 0 : 1; // if the random range was rand() % 2, it would repeat the pattern without randomize correctly - VectorMA( origin, 10, dir, sparkOrg ); + VectorMA( origin, 0, dir, sparkOrg ); // move faster VectorScale( dir, 1500 + (rand() % 1000), sparkVel ); @@ -1517,8 +1527,6 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im qhandle_t shader; sfxHandle_t sfx; float radius; - float light; - vec3_t lightColor; localEntity_t *le; int r; qboolean isSprite; @@ -1530,10 +1538,6 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im sfx = 0; mod = 0; shader = 0; - light = 0; - lightColor[0] = 1; - lightColor[1] = 1; - lightColor[2] = 0; // set defaults isSprite = qfalse; @@ -1556,21 +1560,14 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im mod = cgs.media.dishFlashModel; shader = cgs.media.grenadeExplosionShader; sfx = cgs.media.sfx_rockexp; - light = 300; isSprite = qtrue; break; case WP_ROCKET_LAUNCHER: mod = cgs.media.dishFlashModel; shader = cgs.media.rocketExplosionShader; sfx = cgs.media.sfx_rockexp; - light = 300; isSprite = qtrue; duration = 1000; - lightColor[0] = 1; - lightColor[1] = 0.75; - lightColor[2] = 0.0; - // BFP - cg_oldRocket is unused on BFP, they forgot to remove - //if (cg_oldRocket.integer == 0) {} break; case WP_RAILGUN: mod = cgs.media.ringFlashModel; @@ -1616,16 +1613,81 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im // // create the explosion // - if ( mod ) { - le = CG_MakeExplosion( origin, dir, - mod, shader, - duration, isSprite ); - le->light = light; - VectorCopy( lightColor, le->lightColor ); - if ( weapon == WP_RAILGUN ) { - // colorize with client color - VectorCopy( cgs.clientinfo[clientNum].color1, le->color ); + { + // BFP - Low poly sphere + // BFP - TODO: Apply explosionModel from bfp attack config, bfgExplosionShader is just a test + qhandle_t sphereModel = ( cg_lowpolysphere.integer > 0 ) ? cgs.media.lowPolySphereModel : cgs.media.highPolySphereModel; + localEntity_t *leRing, *leShell; + + VectorMA( origin, 10, dir, origin ); + + // BFP - Explosion effects + // BFP - TODO: Apply explosionShader from bfp attack config, bfgExplosionShader is just a test + le = CG_SpawnExplosion( origin, dir, LE_EXPLOSION, sphereModel, cgs.media.bfgExplosionShader, 1000 ); + if ( cg_explosionShell.integer > 0 ) { // BFP - Explosion shell + leShell = CG_SpawnExplosion( origin, dir, LE_EXPLOSION_SHELL, sphereModel, cgs.media.explosionShellShader, 250 ); + } + if ( cg_explosionRing.integer > 0 ) { // BFP - Explosion ring + leRing = CG_SpawnExplosion( origin, dir, LE_EXPLOSION_RING, cgs.media.ringFlashModel, cgs.media.railExplosionShader, 500 ); + } + if ( cg_explosionSmoke.integer > 0 ) { // BFP - Explosion smoke + // BFP - TODO: Apply explosionSmoke as indicated on default.cfg file from some character: explosionSmoke + int i, numSmokes = 3; + int explosionSmokeRadius = 200; + int explosionSmokeLife = 1500; + int explosionSmokeSpeed = 10; + for ( i = 0; i < numSmokes; i++ ) { + // BFP - TODO: Apply explosionSmokeRadius as indicated on default.cfg file from some character: explosionSmokeRadius + // BFP - TODO: Apply explosionSmokeLife as indicated on default.cfg file from some character: explosionSmokeLife + // BFP - TODO: Apply explosionSmokeSpeed as indicated on default.cfg file from some character: explosionSmokeSpeed + CG_ParticleExplosionSmoke( explosionSmokeRadius, explosionSmokeLife, explosionSmokeSpeed, cgs.media.particleSmokeShader, origin ); + } } + + if ( cg_bigExplosions.integer > 0 ) { // BFP - Big explosions + const float MAX_SCALE = 25.0f, MAX_SCALEFACTOR = 6.0f; // limits to prevent too large scaling + float scale = 1; + int numPointsChargedOverMin = 1; // that means when reaching to 'READY!', it starts as 1 and if it's charging another charge point, adds 1 more + // BFP - TODO: Apply explosionScaleFactor as indicated on default.cfg file from some character: explosionScaleFactor + // BFP - TODO: Apply explosionScaleFactorChargeMult as indicated on default.cfg file from some character: explosionScaleFactorChargeMult + float explosionScaleFactor = 0.95, explosionScaleFactorChargeMult = 0; + // BFP - TODO: Apply explosionRingScaleFactor from default.cfg file from some character: explosionRingScaleFactor + // BFP - TODO: Apply explosionRingScaleFactorChargeMult from default.cfg file from some character: explosionRingScaleFactorChargeMult + float explosionRingScaleFactor = 0.95, explosionRingScaleFactorChargeMult = 0; + // BFP - TODO: Apply explosionShellScaleFactor from default.cfg file from some character: explosionShellScaleFactor + // BFP - TODO: Apply explosionShellScaleFactorChargeMult from default.cfg file from some character: explosionShellScaleFactorChargeMult + float explosionShellScaleFactor = 0.95, explosionShellScaleFactorChargeMult = 0; + + if ( explosionScaleFactor > MAX_SCALEFACTOR ) explosionScaleFactor = MAX_SCALEFACTOR; + if ( explosionScaleFactorChargeMult > MAX_SCALEFACTOR ) explosionScaleFactorChargeMult = MAX_SCALEFACTOR; + scale = explosionScaleFactor + explosionScaleFactorChargeMult * numPointsChargedOverMin; + if ( scale > MAX_SCALE ) scale = MAX_SCALE; + VectorScale( le->refEntity.axis[0], scale, le->refEntity.axis[0] ); + VectorScale( le->refEntity.axis[1], scale, le->refEntity.axis[1] ); + VectorScale( le->refEntity.axis[2], scale, le->refEntity.axis[2] ); + + if ( explosionRingScaleFactor > MAX_SCALEFACTOR ) explosionRingScaleFactor = MAX_SCALEFACTOR; + if ( explosionRingScaleFactorChargeMult > MAX_SCALEFACTOR ) explosionRingScaleFactorChargeMult = MAX_SCALEFACTOR; + scale = explosionRingScaleFactor + explosionRingScaleFactorChargeMult * numPointsChargedOverMin; + if ( scale > MAX_SCALE ) scale = MAX_SCALE; + VectorScale( leRing->refEntity.axis[0], scale, leRing->refEntity.axis[0] ); + VectorScale( leRing->refEntity.axis[1], scale, leRing->refEntity.axis[1] ); + VectorScale( leRing->refEntity.axis[2], scale, leRing->refEntity.axis[2] ); + + if ( explosionShellScaleFactor > MAX_SCALEFACTOR ) explosionShellScaleFactor = MAX_SCALEFACTOR; + if ( explosionShellScaleFactorChargeMult > MAX_SCALEFACTOR ) explosionShellScaleFactorChargeMult = MAX_SCALEFACTOR; + scale = explosionShellScaleFactor + explosionShellScaleFactorChargeMult * numPointsChargedOverMin; + if ( scale > MAX_SCALE ) scale = MAX_SCALE; + VectorScale( leShell->refEntity.axis[0], scale, leShell->refEntity.axis[0] ); + VectorScale( leShell->refEntity.axis[1], scale, leShell->refEntity.axis[1] ); + VectorScale( leShell->refEntity.axis[2], scale, leShell->refEntity.axis[2] ); + } + + // BFP - Apply dynamic explosion light values + le->light = 700; + le->lightColor[0] = 1; + le->lightColor[1] = 0.75; + le->lightColor[2] = 0.0; } // From c7314b16013e211e1dfa3770753afd4d5efe6e8d Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Tue, 15 Oct 2024 18:02:12 +0200 Subject: [PATCH 114/374] cgame: Move explosion smoke feature into local entities, that isn't a particle. Refactor explosion functions and place them into cg_effects.c for clarity --- source/cgame/cg_effects.c | 195 +++++++++++++++++++++++++++++++++++- source/cgame/cg_local.h | 17 ++-- source/cgame/cg_localents.c | 41 ++++++++ source/cgame/cg_particles.c | 75 +------------- source/cgame/cg_weapons.c | 166 +----------------------------- 5 files changed, 245 insertions(+), 249 deletions(-) diff --git a/source/cgame/cg_effects.c b/source/cgame/cg_effects.c index f058e97..c1afc75 100644 --- a/source/cgame/cg_effects.c +++ b/source/cgame/cg_effects.c @@ -296,10 +296,10 @@ localEntity_t *CG_MakeExplosion( vec3_t origin, vec3_t dir, /* ==================== -CG_SpawnExplosion +CG_SpawnExplosionModel ==================== */ -localEntity_t *CG_SpawnExplosion( vec3_t origin, vec3_t dir, leType_t type, qhandle_t hModel, qhandle_t shader, float duration ) { // BFP - Explosion sphere, shell and ring effect +localEntity_t *CG_SpawnExplosionModel( vec3_t origin, vec3_t dir, leType_t type, qhandle_t hModel, qhandle_t shader, float duration ) { // BFP - Explosion sphere, shell and ring effect localEntity_t *le; vec3_t newOrigin; @@ -567,3 +567,194 @@ void CG_BigExplode( vec3_t playerOrigin ) { CG_LaunchExplode( origin, velocity, cgs.media.smoke2 ); } + +/* +================= +CG_DebrisExplosion +================= +*/ +void CG_DebrisExplosion( vec3_t origin, vec3_t dir ) { // BFP - Debris particles explosion + int i; + // spawn randomly the shaders with the particles + int shaderIndex; + vec3_t sprOrg, sprVel; + int numRocks = 26; + + // BFP - NOTE: Debris particles shouldn't be used for bullet and disk weapon types + + // BFP - TODO: Apply number of rocks as indicated on default.cfg file of some character: explosionRocks + + for ( i = 0; i < numRocks; ++i ) { + shaderIndex = rand() % 3; + + // that would be the range for debris particles + VectorMA( origin, 24, dir, sprOrg ); + sprOrg[0] += (rand() % 24); + sprOrg[1] += (rand() % 24); + sprOrg[2] += (rand() % 24); + + VectorScale( dir, 1500 + (rand() % 1000), sprVel ); + sprVel[0] += (rand() % 2800) - 1500; + sprVel[1] += (rand() % 2800) - 1500; + sprVel[2] += (rand() % 2200) - 1000; + + switch ( shaderIndex ) { + case 0: { + CG_ParticleDebris( cgs.media.pebbleShader1, sprOrg, sprVel, qfalse ); + break; + } + case 1: { + CG_ParticleDebris( cgs.media.pebbleShader2, sprOrg, sprVel, qfalse ); + break; + } + default: { + CG_ParticleDebris( cgs.media.pebbleShader3, sprOrg, sprVel, qfalse ); + } + } + } +} + +/* +================= +CG_SparksExplosion +================= +*/ +void CG_SparksExplosion( vec3_t origin, vec3_t dir ) { // BFP - Spark particles explosion + int i; + // spawn randomly the shaders with the particles + int shaderIndex; + vec3_t sparkOrg, sparkVel; + int numSparks = 26; + + // BFP - NOTE: Spark particles shouldn't be used on bullet and disk weapon types + + // BFP - TODO: Apply calling this function for finger blast and these rail gun weapon types when hitting a player + + // BFP - TODO: Apply number of sparks as indicated on default.cfg file of some character: explosionSparks + + for ( i = 0; i < numSparks; ++i ) { + shaderIndex = (rand() % 100) < 50 ? 0 : 1; // if the random range was rand() % 2, it would repeat the pattern without randomize correctly + + VectorMA( origin, 0, dir, sparkOrg ); + + // move faster + VectorScale( dir, 1500 + (rand() % 1000), sparkVel ); + sparkVel[0] += 1.5 * (rand() % 3500) - 1500; + sparkVel[1] += 1.5 * (rand() % 3500) - 1500; + sparkVel[2] += 1.5 * (rand() % 2100) - 1000; + + switch ( shaderIndex ) { + case 0: { + CG_ParticleSparks( cgs.media.sparkShader1, sparkOrg, sparkVel ); + break; + } + default: { + CG_ParticleSparks( cgs.media.sparkShader2, sparkOrg, sparkVel ); + } + } + } +} + + +/* +================= +CG_ExplosionEffect +================= +*/ +void CG_ExplosionEffect( vec3_t origin, vec3_t dir ) { // BFP - Explosion effects + // BFP - Low poly sphere + // BFP - TODO: Apply explosionModel from bfp attack config, bfgExplosionShader is just a test + qhandle_t sphereModel = ( cg_lowpolysphere.integer > 0 ) ? cgs.media.lowPolySphereModel : cgs.media.highPolySphereModel; + localEntity_t *leSphere, *leRing, *leShell; + + VectorMA( origin, 10, dir, origin ); + + // BFP - TODO: Apply explosionShader from bfp attack config, bfgExplosionShader is just a test + leSphere = CG_SpawnExplosionModel( origin, dir, LE_EXPLOSION, sphereModel, cgs.media.bfgExplosionShader, 1000 ); + if ( cg_explosionShell.integer > 0 ) { // BFP - Explosion shell + leShell = CG_SpawnExplosionModel( origin, dir, LE_EXPLOSION_SHELL, sphereModel, cgs.media.explosionShellShader, 250 ); + } + if ( cg_explosionRing.integer > 0 ) { // BFP - Explosion ring + leRing = CG_SpawnExplosionModel( origin, dir, LE_EXPLOSION_RING, cgs.media.ringFlashModel, cgs.media.railExplosionShader, 500 ); + } + if ( cg_explosionSmoke.integer > 0 ) { // BFP - Explosion smoke + // BFP - TODO: Apply explosionSmoke as indicated on default.cfg file from some character: explosionSmoke + int i, numSmokes = 3; + // BFP - TODO: Apply explosionSmokeRadius as indicated on default.cfg file from some character: explosionSmokeRadius + int explosionSmokeRadius = 200; + // BFP - TODO: Apply explosionSmokeLife as indicated on default.cfg file from some character: explosionSmokeLife + int explosionSmokeLife = 1500; + // BFP - TODO: Apply explosionSmokeSpeed as indicated on default.cfg file from some character: explosionSmokeSpeed + int explosionSmokeSpeed = 10; + for ( i = 0; i < numSmokes; i++ ) { + localEntity_t *leSmoke; + vec3_t vel, smokeOrg; + static int timenonscaled; + + timenonscaled = trap_Milliseconds(); // BFP - That's what the variable makes non-timescaled + + VectorCopy( origin, smokeOrg ); + smokeOrg[0] += ( crandom() * 125 ); + smokeOrg[1] += ( crandom() * 125 ); + smokeOrg[2] += ( crandom() * 25 ); + + vel[0] = vel[1] = 0; + vel[2] = 50 * explosionSmokeSpeed; + + leSmoke = CG_SmokePuff( smokeOrg, vel, + explosionSmokeRadius, + 1, 1, 1, 0.33f, + explosionSmokeLife, + timenonscaled, 0, 0, + cgs.media.particleSmokeShader ); + + // change to this type, don't use the common smoke puff + leSmoke->leType = LE_MOVE_DONT_SCALE_FADE; + } + } + + if ( cg_bigExplosions.integer > 0 ) { // BFP - Big explosions + const float MAX_SCALE = 25.0f, MAX_SCALEFACTOR = 6.0f; // limits to prevent too large scaling + float scale = 1; + int numPointsChargedOverMin = 1; // that means when reaching to 'READY!', it starts as 1 and if it's charging another charge point, adds 1 more + // BFP - TODO: Apply explosionScaleFactor as indicated on default.cfg file from some character: explosionScaleFactor + // BFP - TODO: Apply explosionScaleFactorChargeMult as indicated on default.cfg file from some character: explosionScaleFactorChargeMult + float explosionScaleFactor = 0.95, explosionScaleFactorChargeMult = 0; + // BFP - TODO: Apply explosionRingScaleFactor from default.cfg file from some character: explosionRingScaleFactor + // BFP - TODO: Apply explosionRingScaleFactorChargeMult from default.cfg file from some character: explosionRingScaleFactorChargeMult + float explosionRingScaleFactor = 0.95, explosionRingScaleFactorChargeMult = 0; + // BFP - TODO: Apply explosionShellScaleFactor from default.cfg file from some character: explosionShellScaleFactor + // BFP - TODO: Apply explosionShellScaleFactorChargeMult from default.cfg file from some character: explosionShellScaleFactorChargeMult + float explosionShellScaleFactor = 0.95, explosionShellScaleFactorChargeMult = 0; + + if ( explosionScaleFactor > MAX_SCALEFACTOR ) explosionScaleFactor = MAX_SCALEFACTOR; + if ( explosionScaleFactorChargeMult > MAX_SCALEFACTOR ) explosionScaleFactorChargeMult = MAX_SCALEFACTOR; + scale = explosionScaleFactor + explosionScaleFactorChargeMult * numPointsChargedOverMin; + if ( scale > MAX_SCALE ) scale = MAX_SCALE; + VectorScale( leSphere->refEntity.axis[0], scale, leSphere->refEntity.axis[0] ); + VectorScale( leSphere->refEntity.axis[1], scale, leSphere->refEntity.axis[1] ); + VectorScale( leSphere->refEntity.axis[2], scale, leSphere->refEntity.axis[2] ); + + if ( explosionRingScaleFactor > MAX_SCALEFACTOR ) explosionRingScaleFactor = MAX_SCALEFACTOR; + if ( explosionRingScaleFactorChargeMult > MAX_SCALEFACTOR ) explosionRingScaleFactorChargeMult = MAX_SCALEFACTOR; + scale = explosionRingScaleFactor + explosionRingScaleFactorChargeMult * numPointsChargedOverMin; + if ( scale > MAX_SCALE ) scale = MAX_SCALE; + VectorScale( leRing->refEntity.axis[0], scale, leRing->refEntity.axis[0] ); + VectorScale( leRing->refEntity.axis[1], scale, leRing->refEntity.axis[1] ); + VectorScale( leRing->refEntity.axis[2], scale, leRing->refEntity.axis[2] ); + + if ( explosionShellScaleFactor > MAX_SCALEFACTOR ) explosionShellScaleFactor = MAX_SCALEFACTOR; + if ( explosionShellScaleFactorChargeMult > MAX_SCALEFACTOR ) explosionShellScaleFactorChargeMult = MAX_SCALEFACTOR; + scale = explosionShellScaleFactor + explosionShellScaleFactorChargeMult * numPointsChargedOverMin; + if ( scale > MAX_SCALE ) scale = MAX_SCALE; + VectorScale( leShell->refEntity.axis[0], scale, leShell->refEntity.axis[0] ); + VectorScale( leShell->refEntity.axis[1], scale, leShell->refEntity.axis[1] ); + VectorScale( leShell->refEntity.axis[2], scale, leShell->refEntity.axis[2] ); + } + + // BFP - Apply dynamic explosion light values + leSphere->light = 700; + leSphere->lightColor[0] = 1; + leSphere->lightColor[1] = 0.75; + leSphere->lightColor[2] = 0.0; +} diff --git a/source/cgame/cg_local.h b/source/cgame/cg_local.h index c7d558b..1fce989 100644 --- a/source/cgame/cg_local.h +++ b/source/cgame/cg_local.h @@ -216,6 +216,7 @@ typedef enum { LE_SPRITE_EXPLOSION, LE_FRAGMENT, LE_MOVE_SCALE_FADE, + LE_MOVE_DONT_SCALE_FADE, // BFP - Effect for explosion smoke LE_FALL_SCALE_FADE, LE_FADE_RGB, LE_SCALE_FADE, @@ -1233,10 +1234,6 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im void CG_MissileHitPlayer( int weapon, vec3_t origin, vec3_t dir, int entityNum ); void CG_ShotgunFire( entityState_t *es ); void CG_Bullet( vec3_t origin, int sourceEntityNum, vec3_t normal, qboolean flesh, int fleshEntityNum ); -// BFP - Debris particles explosion -void CG_DebrisExplosion( vec3_t origin, vec3_t dir ); -// BFP - Spark particles explosion -void CG_SparksExplosion( vec3_t origin, vec3_t dir ); void CG_RailTrail( clientInfo_t *ci, vec3_t start, vec3_t end ); void CG_GrappleTrail( centity_t *ent, const weaponInfo_t *wi ); @@ -1289,8 +1286,14 @@ void CG_Bleed( vec3_t origin, int entityNum ); localEntity_t *CG_MakeExplosion( vec3_t origin, vec3_t dir, qhandle_t hModel, qhandle_t shader, int msec, qboolean isSprite ); -// BFP - Explosion effect -localEntity_t *CG_SpawnExplosion( vec3_t origin, vec3_t dir, leType_t type, qhandle_t hModel, qhandle_t shader, float duration ); +// BFP - Explosion models +localEntity_t *CG_SpawnExplosionModel( vec3_t origin, vec3_t dir, leType_t type, qhandle_t hModel, qhandle_t shader, float duration ); +// BFP - Debris particles explosion +void CG_DebrisExplosion( vec3_t origin, vec3_t dir ); +// BFP - Spark particles explosion +void CG_SparksExplosion( vec3_t origin, vec3_t dir ); +// BFP - Explosion effects +void CG_ExplosionEffect( vec3_t origin, vec3_t dir ); // BFP - Ki trail // @@ -1545,8 +1548,6 @@ void CG_ParticleExplosion (char *animStr, vec3_t origin, vec3_t vel, int duratio void CG_ParticleBubble (centity_t *cent, qhandle_t pshader, vec3_t origin, vec3_t origin2, int turbtime, float range); // BFP - Dash smoke particle for ki boost when moving in the ground void CG_ParticleDashSmoke (centity_t *cent, qhandle_t pshader, vec3_t origin); -// BFP - Explosion smoke particle -void CG_ParticleExplosionSmoke (int radius, int lifetime, int speed, qhandle_t pshader, vec3_t origin); // BFP - Antigrav rock particles for charging void CG_ParticleAntigravRock (qhandle_t pshader, centity_t *cent, int entityNum, vec3_t origin); void CG_AntigravRockHandling (centity_t *cent); diff --git a/source/cgame/cg_localents.c b/source/cgame/cg_localents.c index 3326d21..f2505f3 100644 --- a/source/cgame/cg_localents.c +++ b/source/cgame/cg_localents.c @@ -389,6 +389,43 @@ static void CG_AddMoveScaleFade( localEntity_t *le ) { } +/* +================== +CG_AddMoveDontScaleFade +================== +*/ +static void CG_AddMoveDontScaleFade( localEntity_t *le ) { // BFP - For LE_MOVE_DONT_SCALE_FADE type, attention: it's a non-timescaled effect + refEntity_t *re; + float c; + // BFP - NOTE: Explosion effect use non-timescaled, to be timescaled by game, use cg.time + static int timenonscaled; + + timenonscaled = trap_Milliseconds(); // BFP - That's what the variable makes non-timescaled + + re = &le->refEntity; + + if ( le->fadeInTime > le->startTime && timenonscaled < le->fadeInTime ) { + // fade / grow time + c = 1.0 - (float) ( le->fadeInTime - timenonscaled ) / ( le->fadeInTime - le->startTime ); + } else { + // fade / grow time + c = ( le->endTime - timenonscaled ) * le->lifeRate; + } + + re->shaderRGBA[3] = 0xff * c * le->color[3]; + if ( re->shaderRGBA[3] <= 0 ) { // no alpha, disappear then + CG_FreeLocalEntity( le ); + return; + } + + re->radius = le->radius; + + BG_EvaluateTrajectory( &le->pos, timenonscaled, re->origin ); + + trap_R_AddRefEntityToScene( re ); +} + + /* =================== CG_AddScaleFade @@ -695,6 +732,10 @@ void CG_AddLocalEntities( void ) { CG_AddMoveScaleFade( le ); break; + case LE_MOVE_DONT_SCALE_FADE: // BFP - Effect for explosion smoke + CG_AddMoveDontScaleFade( le ); + break; + case LE_FADE_RGB: // teleporters, railtrails CG_AddFadeRGB( le ); break; diff --git a/source/cgame/cg_particles.c b/source/cgame/cg_particles.c index 53f2143..b24877f 100644 --- a/source/cgame/cg_particles.c +++ b/source/cgame/cg_particles.c @@ -566,29 +566,6 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) return; } - if (p->type == P_SMOKE_IMPACT && p->link // BFP - Explosion smoke particle - && timenonscaled > p->endtime - p->end) { - int i; - // decelerate - for (i = 0; i < 2; ++i) { - p->vel[i] *= 0.99; - - // if the velocity is very small, clamp it to zero - if (fabs(p->vel[i]) < 1) { - p->vel[i] = 0; - } - } - - for (i = 0; i < 2; ++i) { - p->accel[i] *= 0.99; - - // if the acceleration is very small, clamp it to zero - if (fabs(p->accel[i]) < 1) { - p->accel[i] = 0; - } - } - } - if (p->rotate) { VectorMA (org, -height, rup2, point); @@ -924,6 +901,7 @@ void CG_AddParticles (void) p->next = free_particles; free_particles = p; p->type = p->color = p->alpha = p->snum = 0; + p->height = p->width = p->endheight = p->endwidth = 0; continue; } } @@ -956,9 +934,6 @@ void CG_AddParticles (void) org[0] = p->org[0] + p->vel[0]*time + p->accel[0]*time2; org[1] = p->org[1] + p->vel[1]*time + p->accel[1]*time2; org[2] = p->org[2] + p->vel[2]*time + p->accel[2]*time2; - if ( p->type == P_SMOKE_IMPACT && p->link ) { // BFP - Explosion smoke particle moving in a static way - org[2] = p->org[2] + p->vel[2]*time + p->accel[2]*time; - } type = p->type; @@ -1180,54 +1155,6 @@ void CG_ParticleDashSmoke (centity_t *cent, qhandle_t pshader, vec3_t origin) p->link = qfalse; // to distinguish the type of smoke } -// BFP - Particle for explosion smoke -void CG_ParticleExplosionSmoke (int radius, int lifetime, int speed, qhandle_t pshader, vec3_t origin) -{ - cparticle_t *p; - - // if (!pshader) CG_Printf ("CG_ParticleExplosionSmoke pshader == ZERO!\n"); - - if (!free_particles) - return; - - p = free_particles; - free_particles = p->next; - p->next = active_particles; - active_particles = p; - - p->time = timenonscaled; - - p->alpha = 0.4; - p->alphavel = -0.01; - - p->pshader = pshader; - - p->endtime = timenonscaled + lifetime; - p->end = lifetime - 350; - - p->startfade = timenonscaled + lifetime; - - p->height = p->width = radius; - - p->endheight = p->height * 2; - p->endwidth = p->width * 2; - - p->type = P_SMOKE_IMPACT; - - VectorCopy( origin, p->org ); - p->org[2] += (crandom() * 25); - - VectorSet( p->vel, - (rand() % 701) - 200, - (rand() % 701) - 200, - speed ); - - p->accel[0] = p->accel[1] = 0; - p->accel[2] = 500; - - p->link = qtrue; // to distinguish the type of smoke -} - // BFP - Antigrav rock particles for ki charging status void CG_ParticleAntigravRock (qhandle_t pshader, centity_t *cent, int entityNum, vec3_t origin) { diff --git a/source/cgame/cg_weapons.c b/source/cgame/cg_weapons.c index 088acf5..ea715d6 100644 --- a/source/cgame/cg_weapons.c +++ b/source/cgame/cg_weapons.c @@ -1427,94 +1427,6 @@ void CG_FireWeapon( centity_t *cent ) { } } -/* -================= -CG_DebrisExplosion -================= -*/ -void CG_DebrisExplosion( vec3_t origin, vec3_t dir ) { // BFP - Debris particles explosion - int i; - // spawn randomly the shaders with the particles - int shaderIndex; - vec3_t sprOrg, sprVel; - int numRocks = 26; - - // BFP - NOTE: Debris particles shouldn't be used for bullet and disk weapon types - - // BFP - TODO: Apply number of rocks as indicated on default.cfg file of some character: explosionRocks - - for ( i = 0; i < numRocks; ++i ) { - shaderIndex = rand() % 3; - - // that would be the range for debris particles - VectorMA( origin, 24, dir, sprOrg ); - sprOrg[0] += (rand() % 24); - sprOrg[1] += (rand() % 24); - sprOrg[2] += (rand() % 24); - - VectorScale( dir, 1500 + (rand() % 1000), sprVel ); - sprVel[0] += (rand() % 2800) - 1500; - sprVel[1] += (rand() % 2800) - 1500; - sprVel[2] += (rand() % 2200) - 1000; - - switch ( shaderIndex ) { - case 0: { - CG_ParticleDebris( cgs.media.pebbleShader1, sprOrg, sprVel, qfalse ); - break; - } - case 1: { - CG_ParticleDebris( cgs.media.pebbleShader2, sprOrg, sprVel, qfalse ); - break; - } - default: { - CG_ParticleDebris( cgs.media.pebbleShader3, sprOrg, sprVel, qfalse ); - } - } - } -} - -/* -================= -CG_SparksExplosion -================= -*/ -void CG_SparksExplosion( vec3_t origin, vec3_t dir ) { // BFP - Spark particles explosion - int i; - // spawn randomly the shaders with the particles - int shaderIndex; - vec3_t sparkOrg, sparkVel; - int numSparks = 26; - - // BFP - NOTE: Spark particles shouldn't be used on bullet and disk weapon types - - // BFP - TODO: Apply calling this function for finger blast and these rail gun weapon types when hitting a player - - // BFP - TODO: Apply number of sparks as indicated on default.cfg file of some character: explosionSparks - - for ( i = 0; i < numSparks; ++i ) { - shaderIndex = (rand() % 100) < 50 ? 0 : 1; // if the random range was rand() % 2, it would repeat the pattern without randomize correctly - - VectorMA( origin, 0, dir, sparkOrg ); - - // move faster - VectorScale( dir, 1500 + (rand() % 1000), sparkVel ); - sparkVel[0] += 1.5 * (rand() % 3500) - 1500; - sparkVel[1] += 1.5 * (rand() % 3500) - 1500; - sparkVel[2] += 1.5 * (rand() % 2100) - 1000; - - switch ( shaderIndex ) { - case 0: { - CG_ParticleSparks( cgs.media.sparkShader1, sparkOrg, sparkVel ); - break; - } - default: { - CG_ParticleSparks( cgs.media.sparkShader2, sparkOrg, sparkVel ); - } - } - } -} - - /* ================= CG_MissileHitWall @@ -1527,7 +1439,6 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im qhandle_t shader; sfxHandle_t sfx; float radius; - localEntity_t *le; int r; qboolean isSprite; int duration; @@ -1613,82 +1524,7 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im // // create the explosion // - { - // BFP - Low poly sphere - // BFP - TODO: Apply explosionModel from bfp attack config, bfgExplosionShader is just a test - qhandle_t sphereModel = ( cg_lowpolysphere.integer > 0 ) ? cgs.media.lowPolySphereModel : cgs.media.highPolySphereModel; - localEntity_t *leRing, *leShell; - - VectorMA( origin, 10, dir, origin ); - - // BFP - Explosion effects - // BFP - TODO: Apply explosionShader from bfp attack config, bfgExplosionShader is just a test - le = CG_SpawnExplosion( origin, dir, LE_EXPLOSION, sphereModel, cgs.media.bfgExplosionShader, 1000 ); - if ( cg_explosionShell.integer > 0 ) { // BFP - Explosion shell - leShell = CG_SpawnExplosion( origin, dir, LE_EXPLOSION_SHELL, sphereModel, cgs.media.explosionShellShader, 250 ); - } - if ( cg_explosionRing.integer > 0 ) { // BFP - Explosion ring - leRing = CG_SpawnExplosion( origin, dir, LE_EXPLOSION_RING, cgs.media.ringFlashModel, cgs.media.railExplosionShader, 500 ); - } - if ( cg_explosionSmoke.integer > 0 ) { // BFP - Explosion smoke - // BFP - TODO: Apply explosionSmoke as indicated on default.cfg file from some character: explosionSmoke - int i, numSmokes = 3; - int explosionSmokeRadius = 200; - int explosionSmokeLife = 1500; - int explosionSmokeSpeed = 10; - for ( i = 0; i < numSmokes; i++ ) { - // BFP - TODO: Apply explosionSmokeRadius as indicated on default.cfg file from some character: explosionSmokeRadius - // BFP - TODO: Apply explosionSmokeLife as indicated on default.cfg file from some character: explosionSmokeLife - // BFP - TODO: Apply explosionSmokeSpeed as indicated on default.cfg file from some character: explosionSmokeSpeed - CG_ParticleExplosionSmoke( explosionSmokeRadius, explosionSmokeLife, explosionSmokeSpeed, cgs.media.particleSmokeShader, origin ); - } - } - - if ( cg_bigExplosions.integer > 0 ) { // BFP - Big explosions - const float MAX_SCALE = 25.0f, MAX_SCALEFACTOR = 6.0f; // limits to prevent too large scaling - float scale = 1; - int numPointsChargedOverMin = 1; // that means when reaching to 'READY!', it starts as 1 and if it's charging another charge point, adds 1 more - // BFP - TODO: Apply explosionScaleFactor as indicated on default.cfg file from some character: explosionScaleFactor - // BFP - TODO: Apply explosionScaleFactorChargeMult as indicated on default.cfg file from some character: explosionScaleFactorChargeMult - float explosionScaleFactor = 0.95, explosionScaleFactorChargeMult = 0; - // BFP - TODO: Apply explosionRingScaleFactor from default.cfg file from some character: explosionRingScaleFactor - // BFP - TODO: Apply explosionRingScaleFactorChargeMult from default.cfg file from some character: explosionRingScaleFactorChargeMult - float explosionRingScaleFactor = 0.95, explosionRingScaleFactorChargeMult = 0; - // BFP - TODO: Apply explosionShellScaleFactor from default.cfg file from some character: explosionShellScaleFactor - // BFP - TODO: Apply explosionShellScaleFactorChargeMult from default.cfg file from some character: explosionShellScaleFactorChargeMult - float explosionShellScaleFactor = 0.95, explosionShellScaleFactorChargeMult = 0; - - if ( explosionScaleFactor > MAX_SCALEFACTOR ) explosionScaleFactor = MAX_SCALEFACTOR; - if ( explosionScaleFactorChargeMult > MAX_SCALEFACTOR ) explosionScaleFactorChargeMult = MAX_SCALEFACTOR; - scale = explosionScaleFactor + explosionScaleFactorChargeMult * numPointsChargedOverMin; - if ( scale > MAX_SCALE ) scale = MAX_SCALE; - VectorScale( le->refEntity.axis[0], scale, le->refEntity.axis[0] ); - VectorScale( le->refEntity.axis[1], scale, le->refEntity.axis[1] ); - VectorScale( le->refEntity.axis[2], scale, le->refEntity.axis[2] ); - - if ( explosionRingScaleFactor > MAX_SCALEFACTOR ) explosionRingScaleFactor = MAX_SCALEFACTOR; - if ( explosionRingScaleFactorChargeMult > MAX_SCALEFACTOR ) explosionRingScaleFactorChargeMult = MAX_SCALEFACTOR; - scale = explosionRingScaleFactor + explosionRingScaleFactorChargeMult * numPointsChargedOverMin; - if ( scale > MAX_SCALE ) scale = MAX_SCALE; - VectorScale( leRing->refEntity.axis[0], scale, leRing->refEntity.axis[0] ); - VectorScale( leRing->refEntity.axis[1], scale, leRing->refEntity.axis[1] ); - VectorScale( leRing->refEntity.axis[2], scale, leRing->refEntity.axis[2] ); - - if ( explosionShellScaleFactor > MAX_SCALEFACTOR ) explosionShellScaleFactor = MAX_SCALEFACTOR; - if ( explosionShellScaleFactorChargeMult > MAX_SCALEFACTOR ) explosionShellScaleFactorChargeMult = MAX_SCALEFACTOR; - scale = explosionShellScaleFactor + explosionShellScaleFactorChargeMult * numPointsChargedOverMin; - if ( scale > MAX_SCALE ) scale = MAX_SCALE; - VectorScale( leShell->refEntity.axis[0], scale, leShell->refEntity.axis[0] ); - VectorScale( leShell->refEntity.axis[1], scale, leShell->refEntity.axis[1] ); - VectorScale( leShell->refEntity.axis[2], scale, leShell->refEntity.axis[2] ); - } - - // BFP - Apply dynamic explosion light values - le->light = 700; - le->lightColor[0] = 1; - le->lightColor[1] = 0.75; - le->lightColor[2] = 0.0; - } + CG_ExplosionEffect( origin, dir ); // BFP - Explosion effects // // impact mark From 5b7b26a676ea3fbf24d2295133bbb24703a818f9 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Wed, 16 Oct 2024 01:03:38 +0200 Subject: [PATCH 115/374] game: Remove spawning gibs when being hit with a big attack that surpasses health entering to death phase, just stay as corpse. And make railgun only hit one time instead passing through the target to the other point --- source/game/g_combat.c | 4 +++- source/game/g_weapon.c | 43 +++++++++++++++--------------------------- 2 files changed, 18 insertions(+), 29 deletions(-) diff --git a/source/game/g_combat.c b/source/game/g_combat.c index 5f85001..903bed7 100644 --- a/source/game/g_combat.c +++ b/source/game/g_combat.c @@ -509,7 +509,9 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int memset( self->client->ps.powerups, 0, sizeof(self->client->ps.powerups) ); // never gib in a nodrop - if ( (self->health <= GIB_HEALTH && !(contents & CONTENTS_NODROP) && g_blood.integer) || meansOfDeath == MOD_SUICIDE) { + // BFP - No gibs when being attacked and entering to death phase, just stay as corpse + // (self->health <= GIB_HEALTH && !(contents & CONTENTS_NODROP) && g_blood.integer) || + if (meansOfDeath == MOD_SUICIDE) { // gib death GibEntity( self, killer ); } else { diff --git a/source/game/g_weapon.c b/source/game/g_weapon.c index a4671db..62831c1 100644 --- a/source/game/g_weapon.c +++ b/source/game/g_weapon.c @@ -550,7 +550,6 @@ RAILGUN weapon_railgun_fire ================= */ -#define MAX_RAIL_HITS 4 void weapon_railgun_fire (gentity_t *ent) { vec3_t end; trace_t trace; @@ -559,42 +558,27 @@ void weapon_railgun_fire (gentity_t *ent) { int damage; int i; int hits; - int unlinked; int passent; - gentity_t *unlinkedEntities[MAX_RAIL_HITS]; damage = 100 * s_quadFactor; VectorMA (muzzle, 8192, forward, end); // trace only against the solids, so the railgun will go through people - unlinked = 0; hits = 0; passent = ent->s.number; - do { - trap_Trace (&trace, muzzle, NULL, NULL, end, passent, MASK_SHOT ); - if ( trace.entityNum >= ENTITYNUM_MAX_NORMAL ) { - break; - } + trap_Trace( &trace, muzzle, NULL, NULL, end, passent, MASK_SHOT ); + if ( trace.entityNum < ENTITYNUM_MAX_NORMAL ) { traceEnt = &g_entities[ trace.entityNum ]; if ( traceEnt->takedamage ) { - if( LogAccuracyHit( traceEnt, ent ) ) { - hits++; - } - G_Damage (traceEnt, ent, ent, forward, trace.endpos, damage, 0, MOD_RAILGUN); - } - if ( trace.contents & CONTENTS_SOLID ) { - break; // we hit something solid enough to stop the beam - } - // unlink this entity, so the next trace will go past it - trap_UnlinkEntity( traceEnt ); - unlinkedEntities[unlinked] = traceEnt; - unlinked++; - } while ( unlinked < MAX_RAIL_HITS ); + // BFP - Railgun events are also treated as a missile + tent = G_TempEntity( trace.endpos, EV_MISSILE_HIT ); - // link back in any entities we unlinked - for ( i = 0 ; i < unlinked ; i++ ) { - trap_LinkEntity( unlinkedEntities[i] ); + if ( LogAccuracyHit( traceEnt, ent ) ) { + hits++; + } + G_Damage( traceEnt, ent, ent, forward, trace.endpos, damage, 0, MOD_RAILGUN ); + } } // the final trace endpos will be the terminal point of the rail trail @@ -614,9 +598,12 @@ void weapon_railgun_fire (gentity_t *ent) { VectorMA( tent->s.origin2, -1, up, tent->s.origin2 ); // no explosion at end if SURF_NOIMPACT, but still make the trail - if ( trace.surfaceFlags & SURF_NOIMPACT ) { - tent->s.eventParm = 255; // don't make the explosion at the end - } else { + if ( !( trace.surfaceFlags & SURF_NOIMPACT ) ) { + // BFP - Railgun events are also treated as a missile + if ( traceEnt->s.eType != ET_PLAYER || traceEnt->physicsObject ) { + tent = G_TempEntity( trace.endpos, EV_MISSILE_MISS ); + } + // BFP - Sends dir vector variable to the event tent->s.eventParm = DirToByte( trace.plane.normal ); } tent->s.clientNum = ent->s.clientNum; From aadd8921c1796c2351d50bd008398cb5cb360b6a Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Wed, 16 Oct 2024 03:09:15 +0200 Subject: [PATCH 116/374] cgame: Add explosion sound effects when hitting, apply muzzle effects to machine gun and shotgun as testing weapon types, adjust effects when hitting to another player and remove brass models, these machine gun and shotgun ammo shells. Encapsulate smoke explosion effect to a function on, fix accidental NULL parameter set on splash water particle function causing crashes when using .dll/.so, place the splash particle a little towards the center of the player and fix debris type particles when the game is paused --- source/cgame/cg_effects.c | 73 +++++++++---- source/cgame/cg_event.c | 25 ++--- source/cgame/cg_local.h | 16 ++- source/cgame/cg_localents.c | 4 + source/cgame/cg_main.c | 11 +- source/cgame/cg_particles.c | 12 +- source/cgame/cg_weapons.c | 211 +++++++----------------------------- 7 files changed, 125 insertions(+), 227 deletions(-) diff --git a/source/cgame/cg_effects.c b/source/cgame/cg_effects.c index c1afc75..8b1e15d 100644 --- a/source/cgame/cg_effects.c +++ b/source/cgame/cg_effects.c @@ -575,8 +575,6 @@ CG_DebrisExplosion */ void CG_DebrisExplosion( vec3_t origin, vec3_t dir ) { // BFP - Debris particles explosion int i; - // spawn randomly the shaders with the particles - int shaderIndex; vec3_t sprOrg, sprVel; int numRocks = 26; @@ -585,7 +583,8 @@ void CG_DebrisExplosion( vec3_t origin, vec3_t dir ) { // BFP - Debris particles // BFP - TODO: Apply number of rocks as indicated on default.cfg file of some character: explosionRocks for ( i = 0; i < numRocks; ++i ) { - shaderIndex = rand() % 3; + // spawn randomly the shaders with the particles + int shaderIndex = rand() % 3; // that would be the range for debris particles VectorMA( origin, 24, dir, sprOrg ); @@ -655,29 +654,13 @@ void CG_SparksExplosion( vec3_t origin, vec3_t dir ) { // BFP - Spark particles } } - /* ================= -CG_ExplosionEffect +CG_SmokeExplosion ================= */ -void CG_ExplosionEffect( vec3_t origin, vec3_t dir ) { // BFP - Explosion effects - // BFP - Low poly sphere - // BFP - TODO: Apply explosionModel from bfp attack config, bfgExplosionShader is just a test - qhandle_t sphereModel = ( cg_lowpolysphere.integer > 0 ) ? cgs.media.lowPolySphereModel : cgs.media.highPolySphereModel; - localEntity_t *leSphere, *leRing, *leShell; - - VectorMA( origin, 10, dir, origin ); - - // BFP - TODO: Apply explosionShader from bfp attack config, bfgExplosionShader is just a test - leSphere = CG_SpawnExplosionModel( origin, dir, LE_EXPLOSION, sphereModel, cgs.media.bfgExplosionShader, 1000 ); - if ( cg_explosionShell.integer > 0 ) { // BFP - Explosion shell - leShell = CG_SpawnExplosionModel( origin, dir, LE_EXPLOSION_SHELL, sphereModel, cgs.media.explosionShellShader, 250 ); - } - if ( cg_explosionRing.integer > 0 ) { // BFP - Explosion ring - leRing = CG_SpawnExplosionModel( origin, dir, LE_EXPLOSION_RING, cgs.media.ringFlashModel, cgs.media.railExplosionShader, 500 ); - } - if ( cg_explosionSmoke.integer > 0 ) { // BFP - Explosion smoke +void CG_SmokeExplosion( vec3_t origin ) { // BFP - Explosion smoke + if ( cg_explosionSmoke.integer > 0 ) { // BFP - TODO: Apply explosionSmoke as indicated on default.cfg file from some character: explosionSmoke int i, numSmokes = 3; // BFP - TODO: Apply explosionSmokeRadius as indicated on default.cfg file from some character: explosionSmokeRadius @@ -686,7 +669,7 @@ void CG_ExplosionEffect( vec3_t origin, vec3_t dir ) { // BFP - Explosion effect int explosionSmokeLife = 1500; // BFP - TODO: Apply explosionSmokeSpeed as indicated on default.cfg file from some character: explosionSmokeSpeed int explosionSmokeSpeed = 10; - for ( i = 0; i < numSmokes; i++ ) { + for ( i = 0; i < numSmokes; ++i ) { localEntity_t *leSmoke; vec3_t vel, smokeOrg; static int timenonscaled; @@ -712,6 +695,50 @@ void CG_ExplosionEffect( vec3_t origin, vec3_t dir ) { // BFP - Explosion effect leSmoke->leType = LE_MOVE_DONT_SCALE_FADE; } } +} + + +/* +================= +CG_ExplosionSound +================= +*/ +void CG_ExplosionSound( vec3_t origin ) { // BFP - Explosion sounds + int i = rand() % 6; + + switch ( i ) { + case 0: trap_S_StartSound( origin, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.explosion1Sound ); break; + case 1: trap_S_StartSound( origin, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.explosion2Sound ); break; + case 2: trap_S_StartSound( origin, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.explosion3Sound ); break; + case 3: trap_S_StartSound( origin, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.explosion4Sound ); break; + case 4: trap_S_StartSound( origin, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.explosion5Sound ); break; + default: trap_S_StartSound( origin, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.explosion6Sound ); break; + } +} + + +/* +================= +CG_ExplosionEffect +================= +*/ +void CG_ExplosionEffect( vec3_t origin, vec3_t dir ) { // BFP - Explosion effects + // BFP - Low poly sphere + // BFP - TODO: Apply explosionModel from bfp attack config, highPolySphereModel is just a test + qhandle_t sphereModel = ( cg_lowpolysphere.integer > 0 ) ? cgs.media.lowPolySphereModel : cgs.media.highPolySphereModel; + localEntity_t *leSphere, *leRing, *leShell; + + VectorMA( origin, 10, dir, origin ); + + // BFP - TODO: Apply explosionShader from bfp attack config, bfgExplosionShader is just a test + leSphere = CG_SpawnExplosionModel( origin, dir, LE_EXPLOSION_SPHERE, sphereModel, cgs.media.bfgExplosionShader, 1000 ); + if ( cg_explosionShell.integer > 0 ) { // BFP - Explosion shell + leShell = CG_SpawnExplosionModel( origin, dir, LE_EXPLOSION_SHELL, sphereModel, cgs.media.explosionShellShader, 250 ); + } + if ( cg_explosionRing.integer > 0 ) { // BFP - Explosion ring + leRing = CG_SpawnExplosionModel( origin, dir, LE_EXPLOSION_RING, cgs.media.ringFlashModel, cgs.media.railExplosionShader, 500 ); + } + CG_SmokeExplosion( origin ); // BFP - Explosion smoke if ( cg_bigExplosions.integer > 0 ) { // BFP - Big explosions const float MAX_SCALE = 25.0f, MAX_SCALEFACTOR = 6.0f; // limits to prevent too large scaling diff --git a/source/cgame/cg_event.c b/source/cgame/cg_event.c index 62b09e4..54074cc 100644 --- a/source/cgame/cg_event.c +++ b/source/cgame/cg_event.c @@ -602,16 +602,16 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { splashOrigin[2] += 20; // place a bit above // that would be the range - splashOrigin[0] += (crandom() * 15); - splashOrigin[1] += (crandom() * 15); + splashOrigin[0] += (crandom() * 5); + splashOrigin[1] += (crandom() * 5); // Splash! // BFP - NOTE: These are not debris :P - CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, NULL, qtrue ); - CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, NULL, qtrue ); - CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, NULL, qtrue ); - CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, NULL, qtrue ); - CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, NULL, qtrue ); + CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, end, qtrue ); + CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, end, qtrue ); + CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, end, qtrue ); + CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, end, qtrue ); + CG_ParticleDebris( cgs.media.waterBubbleShader, splashOrigin, end, qtrue ); splashOrigin[2] -= 25; // place a bit below @@ -871,8 +871,6 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { DEBUGNAME("EV_MISSILE_HIT"); ByteToDir( es->eventParm, dir ); CG_MissileHitPlayer( es->weapon, position, dir, es->otherEntityNum ); - // BFP - Spark particles explosion - CG_SparksExplosion( position, dir ); break; case EV_MISSILE_MISS: @@ -905,14 +903,7 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) { cent->currentState.weapon = WP_RAILGUN; // if the end was on a nomark surface, don't make an explosion CG_RailTrail( ci, es->origin2, es->pos.trBase ); - if ( es->eventParm != 255 ) { - ByteToDir( es->eventParm, dir ); - CG_MissileHitWall( es->weapon, es->clientNum, position, dir, IMPACTSOUND_DEFAULT ); - // BFP - Debris particles explosion - CG_DebrisExplosion( position, dir ); - // BFP - Spark particles explosion - CG_SparksExplosion( position, dir ); - } + ByteToDir( es->eventParm, dir ); break; case EV_BULLET_HIT_WALL: diff --git a/source/cgame/cg_local.h b/source/cgame/cg_local.h index 1fce989..912619b 100644 --- a/source/cgame/cg_local.h +++ b/source/cgame/cg_local.h @@ -211,6 +211,7 @@ typedef struct markPoly_s { typedef enum { LE_MARK, LE_EXPLOSION, + LE_EXPLOSION_SPHERE, // BFP - Explosion sphere LE_EXPLOSION_RING, // BFP - Explosion ring LE_EXPLOSION_SHELL, // BFP - Explosion shell LE_SPRITE_EXPLOSION, @@ -694,9 +695,6 @@ typedef struct { qhandle_t smoke2; - qhandle_t machinegunBrassModel; - qhandle_t shotgunBrassModel; - qhandle_t railRingsShader; qhandle_t railCoreShader; @@ -945,6 +943,14 @@ typedef struct { sfxHandle_t wstbimpdSound; sfxHandle_t wstbactvSound; + // BFP - Explosion sounds + sfxHandle_t explosion1Sound; + sfxHandle_t explosion2Sound; + sfxHandle_t explosion3Sound; + sfxHandle_t explosion4Sound; + sfxHandle_t explosion5Sound; + sfxHandle_t explosion6Sound; + sfxHandle_t kiChargeSound; // BFP - Ki charge sound sfxHandle_t kiUseSound; // BFP - Ki use sound @@ -1292,6 +1298,10 @@ localEntity_t *CG_SpawnExplosionModel( vec3_t origin, vec3_t dir, leType_t type, void CG_DebrisExplosion( vec3_t origin, vec3_t dir ); // BFP - Spark particles explosion void CG_SparksExplosion( vec3_t origin, vec3_t dir ); +// BFP - Explosion smoke +void CG_SmokeExplosion( vec3_t origin ); +// BFP - Explosion sounds +void CG_ExplosionSound( vec3_t origin ); // BFP - Explosion effects void CG_ExplosionEffect( vec3_t origin, vec3_t dir ); diff --git a/source/cgame/cg_localents.c b/source/cgame/cg_localents.c index f2505f3..3833506 100644 --- a/source/cgame/cg_localents.c +++ b/source/cgame/cg_localents.c @@ -520,6 +520,9 @@ static void CG_AddExplosion( localEntity_t *ex ) { switch( ex->leType ) { case LE_EXPLOSION: + scale = 1.05f; // scale a bit faster to adjust + break; + case LE_EXPLOSION_SPHERE: if ( cg.time > endTime ) { scale = 0.9f * ( endScale + 0.5f ); // decrease size } @@ -719,6 +722,7 @@ void CG_AddLocalEntities( void ) { break; case LE_EXPLOSION: + case LE_EXPLOSION_SPHERE: // BFP - Explosion sphere case LE_EXPLOSION_RING: // BFP - Explosion ring case LE_EXPLOSION_SHELL: // BFP - Explosion shell CG_AddExplosion( le ); diff --git a/source/cgame/cg_main.c b/source/cgame/cg_main.c index 51451b5..e2465f4 100644 --- a/source/cgame/cg_main.c +++ b/source/cgame/cg_main.c @@ -472,6 +472,14 @@ static void CG_RegisterSounds( void ) { cgs.media.hgrenb1aSound = trap_S_RegisterSound("sound/weapons/grenade/hgrenb1a.wav", qfalse); cgs.media.hgrenb2aSound = trap_S_RegisterSound("sound/weapons/grenade/hgrenb2a.wav", qfalse); + // BFP - Explosion sounds + cgs.media.explosion1Sound = trap_S_RegisterSound("sound/bfp/explosion1.wav", qfalse); + cgs.media.explosion2Sound = trap_S_RegisterSound("sound/bfp/explosion2.wav", qfalse); + cgs.media.explosion3Sound = trap_S_RegisterSound("sound/bfp/explosion3.wav", qfalse); + cgs.media.explosion4Sound = trap_S_RegisterSound("sound/bfp/explosion4.wav", qfalse); + cgs.media.explosion5Sound = trap_S_RegisterSound("sound/bfp/explosion5.wav", qfalse); + cgs.media.explosion6Sound = trap_S_RegisterSound("sound/bfp/explosion6.wav", qfalse); + cgs.media.kiChargeSound = trap_S_RegisterSound("sound/bfp/kicharge1.wav", qfalse); // BFP - Ki charge sound cgs.media.kiUseSound = trap_S_RegisterSound("sound/bfp/kiuse1.wav", qfalse); // BFP - Ki use sound cgs.media.defaultKiChargingSound = trap_S_RegisterSound("sound/bfp/attackcharge1.wav", qfalse); // BFP - Default ki charging attack sound @@ -598,9 +606,6 @@ static void CG_RegisterGraphics( void ) { cgs.media.armorModel = trap_R_RegisterModel( "models/powerups/armor/armor_yel.md3" ); cgs.media.armorIcon = trap_R_RegisterShaderNoMip( "icons/iconr_yellow" ); - cgs.media.machinegunBrassModel = trap_R_RegisterModel( "models/weapons2/shells/m_shell.md3" ); - cgs.media.shotgunBrassModel = trap_R_RegisterModel( "models/weapons2/shells/s_shell.md3" ); - cgs.media.gibAbdomen = trap_R_RegisterModel( "models/gibs/abdomen.md3" ); cgs.media.gibArm = trap_R_RegisterModel( "models/gibs/arm.md3" ); cgs.media.gibChest = trap_R_RegisterModel( "models/gibs/chest.md3" ); diff --git a/source/cgame/cg_particles.c b/source/cgame/cg_particles.c index b24877f..00104f2 100644 --- a/source/cgame/cg_particles.c +++ b/source/cgame/cg_particles.c @@ -457,7 +457,7 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) if (org[2] > p->end) { p->next = NULL; - p->type = p->color = p->alpha = p->snum = 0; + p->color = p->alpha = 0; } } else if (p->type == P_DEBRIS) // BFP - Debris type @@ -525,10 +525,6 @@ void CG_AddParticleToScene (cparticle_t *p, vec3_t org, float alpha) if ( p->time > p->endtime - 500 ) { p->height = p->width *= 0.9; } - if ( p->width <= 0.1 ) { - p->next = NULL; - p->type = p->color = p->alpha = 0; - } } if (p->type == P_DEBRIS && p->snum > 0) { // render spark particles @@ -900,7 +896,7 @@ void CG_AddParticles (void) { p->next = free_particles; free_particles = p; - p->type = p->color = p->alpha = p->snum = 0; + p->color = p->alpha = 0; p->height = p->width = p->endheight = p->endwidth = 0; continue; } @@ -911,7 +907,7 @@ void CG_AddParticles (void) CG_AddParticleToScene (p, p->org, alpha); p->next = free_particles; free_particles = p; - p->type = p->color = p->alpha = 0; + p->color = p->alpha = 0; continue; } @@ -1064,7 +1060,7 @@ void CG_BubblesWaterHandling( cparticle_t *p, vec3_t org ) { contents = trap_CM_PointContents( trace.endpos, 0 ); if ( contents & CONTENTS_SOLID ) { // remove when grazing something solid p->next = NULL; - p->type = p->color = p->alpha = 0; + p->color = p->alpha = 0; return; } if ( !( contents & CONTENTS_WATER ) ) { diff --git a/source/cgame/cg_weapons.c b/source/cgame/cg_weapons.c index ea715d6..9468ebc 100644 --- a/source/cgame/cg_weapons.c +++ b/source/cgame/cg_weapons.c @@ -23,155 +23,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // cg_weapons.c -- events and effects dealing with weapons #include "cg_local.h" -/* -========================== -CG_MachineGunEjectBrass -========================== -*/ -static void CG_MachineGunEjectBrass( centity_t *cent ) { - localEntity_t *le; - refEntity_t *re; - vec3_t velocity, xvelocity; - vec3_t offset, xoffset; - float waterScale = 1.0f; - vec3_t v[3]; - - if ( cg_brassTime.integer <= 0 ) { - return; - } - - le = CG_AllocLocalEntity(); - re = &le->refEntity; - - velocity[0] = 0; - velocity[1] = -50 + 40 * crandom(); - velocity[2] = 100 + 50 * crandom(); - - le->leType = LE_FRAGMENT; - le->startTime = cg.time; - le->endTime = le->startTime + cg_brassTime.integer + ( cg_brassTime.integer / 4 ) * random(); - - le->pos.trType = TR_GRAVITY; - le->pos.trTime = cg.time - (rand()&15); - - AnglesToAxis( cent->lerpAngles, v ); - - offset[0] = 8; - offset[1] = -4; - offset[2] = 24; - - xoffset[0] = offset[0] * v[0][0] + offset[1] * v[1][0] + offset[2] * v[2][0]; - xoffset[1] = offset[0] * v[0][1] + offset[1] * v[1][1] + offset[2] * v[2][1]; - xoffset[2] = offset[0] * v[0][2] + offset[1] * v[1][2] + offset[2] * v[2][2]; - VectorAdd( cent->lerpOrigin, xoffset, re->origin ); - - VectorCopy( re->origin, le->pos.trBase ); - - if ( CG_PointContents( re->origin, -1 ) & CONTENTS_WATER ) { - waterScale = 0.10f; - } - - xvelocity[0] = velocity[0] * v[0][0] + velocity[1] * v[1][0] + velocity[2] * v[2][0]; - xvelocity[1] = velocity[0] * v[0][1] + velocity[1] * v[1][1] + velocity[2] * v[2][1]; - xvelocity[2] = velocity[0] * v[0][2] + velocity[1] * v[1][2] + velocity[2] * v[2][2]; - VectorScale( xvelocity, waterScale, le->pos.trDelta ); - - AxisCopy( axisDefault, re->axis ); - re->hModel = cgs.media.machinegunBrassModel; - - le->bounceFactor = 0.4 * waterScale; - - le->angles.trType = TR_LINEAR; - le->angles.trTime = cg.time; - le->angles.trBase[0] = rand()&31; - le->angles.trBase[1] = rand()&31; - le->angles.trBase[2] = rand()&31; - le->angles.trDelta[0] = 2; - le->angles.trDelta[1] = 1; - le->angles.trDelta[2] = 0; - - le->leFlags = LEF_TUMBLE; - le->leBounceSoundType = LEBS_BRASS; - le->leMarkType = LEMT_NONE; -} - -/* -========================== -CG_ShotgunEjectBrass -========================== -*/ -static void CG_ShotgunEjectBrass( centity_t *cent ) { - localEntity_t *le; - refEntity_t *re; - vec3_t velocity, xvelocity; - vec3_t offset, xoffset; - vec3_t v[3]; - int i; - - if ( cg_brassTime.integer <= 0 ) { - return; - } - - for ( i = 0; i < 2; i++ ) { - float waterScale = 1.0f; - - le = CG_AllocLocalEntity(); - re = &le->refEntity; - - velocity[0] = 60 + 60 * crandom(); - if ( i == 0 ) { - velocity[1] = 40 + 10 * crandom(); - } else { - velocity[1] = -40 + 10 * crandom(); - } - velocity[2] = 100 + 50 * crandom(); - - le->leType = LE_FRAGMENT; - le->startTime = cg.time; - le->endTime = le->startTime + cg_brassTime.integer*3 + cg_brassTime.integer * random(); - - le->pos.trType = TR_GRAVITY; - le->pos.trTime = cg.time; - - AnglesToAxis( cent->lerpAngles, v ); - - offset[0] = 8; - offset[1] = 0; - offset[2] = 24; - - xoffset[0] = offset[0] * v[0][0] + offset[1] * v[1][0] + offset[2] * v[2][0]; - xoffset[1] = offset[0] * v[0][1] + offset[1] * v[1][1] + offset[2] * v[2][1]; - xoffset[2] = offset[0] * v[0][2] + offset[1] * v[1][2] + offset[2] * v[2][2]; - VectorAdd( cent->lerpOrigin, xoffset, re->origin ); - VectorCopy( re->origin, le->pos.trBase ); - if ( CG_PointContents( re->origin, -1 ) & CONTENTS_WATER ) { - waterScale = 0.10f; - } - - xvelocity[0] = velocity[0] * v[0][0] + velocity[1] * v[1][0] + velocity[2] * v[2][0]; - xvelocity[1] = velocity[0] * v[0][1] + velocity[1] * v[1][1] + velocity[2] * v[2][1]; - xvelocity[2] = velocity[0] * v[0][2] + velocity[1] * v[1][2] + velocity[2] * v[2][2]; - VectorScale( xvelocity, waterScale, le->pos.trDelta ); - - AxisCopy( axisDefault, re->axis ); - re->hModel = cgs.media.shotgunBrassModel; - le->bounceFactor = 0.3f; - - le->angles.trType = TR_LINEAR; - le->angles.trTime = cg.time; - le->angles.trBase[0] = rand()&31; - le->angles.trBase[1] = rand()&31; - le->angles.trBase[2] = rand()&31; - le->angles.trDelta[0] = 1; - le->angles.trDelta[1] = 0.5; - le->angles.trDelta[2] = 0; - - le->leFlags = LEF_TUMBLE; - le->leBounceSoundType = LEBS_BRASS; - le->leMarkType = LEMT_NONE; - } -} - /* ========================== CG_RailTrail @@ -574,14 +425,12 @@ void CG_RegisterWeapon( int weaponNum ) { weaponInfo->flashSound[1] = trap_S_RegisterSound( "sound/weapons/machinegun/machgf2b.wav", qfalse ); weaponInfo->flashSound[2] = trap_S_RegisterSound( "sound/weapons/machinegun/machgf3b.wav", qfalse ); weaponInfo->flashSound[3] = trap_S_RegisterSound( "sound/weapons/machinegun/machgf4b.wav", qfalse ); - weaponInfo->ejectBrassFunc = CG_MachineGunEjectBrass; cgs.media.bulletExplosionShader = trap_R_RegisterShader( "bulletExplosion" ); break; case WP_SHOTGUN: MAKERGB( weaponInfo->flashDlightColor, 1, 1, 0 ); weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/shotgun/sshotf1b.wav", qfalse ); - weaponInfo->ejectBrassFunc = CG_ShotgunEjectBrass; break; case WP_ROCKET_LAUNCHER: @@ -1440,8 +1289,6 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im sfxHandle_t sfx; float radius; int r; - qboolean isSprite; - int duration; // BFP - NOTE: Crack mark shader replaces all other mark shaders, the radius is the same (64), there's no alpha fade @@ -1450,10 +1297,6 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im mod = 0; shader = 0; - // set defaults - isSprite = qfalse; - duration = 600; - switch ( weapon ) { default: case WP_LIGHTNING: @@ -1471,14 +1314,11 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im mod = cgs.media.dishFlashModel; shader = cgs.media.grenadeExplosionShader; sfx = cgs.media.sfx_rockexp; - isSprite = qtrue; break; case WP_ROCKET_LAUNCHER: mod = cgs.media.dishFlashModel; shader = cgs.media.rocketExplosionShader; sfx = cgs.media.sfx_rockexp; - isSprite = qtrue; - duration = 1000; break; case WP_RAILGUN: mod = cgs.media.ringFlashModel; @@ -1494,7 +1334,6 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im mod = cgs.media.dishFlashModel; shader = cgs.media.bfgExplosionShader; sfx = cgs.media.sfx_rockexp; - isSprite = qtrue; break; case WP_SHOTGUN: mod = cgs.media.bulletFlashModel; @@ -1517,14 +1356,25 @@ void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, im break; } - if ( sfx ) { + if ( sfx + && ( weapon == WP_MACHINEGUN || weapon == WP_SHOTGUN || weapon == WP_LIGHTNING ) ) { // BFP - TODO: Apply these weapon types into this sound trap_S_StartSound( origin, ENTITYNUM_WORLD, CHAN_AUTO, sfx ); + } else { // BFP - Explosion sounds + CG_ExplosionSound( origin ); } // // create the explosion // - CG_ExplosionEffect( origin, dir ); // BFP - Explosion effects + if ( weapon == WP_MACHINEGUN || weapon == WP_SHOTGUN ) { // BFP - TODO: Apply muzzle effects only to these weapon types (from default.cfg file from some character) + CG_MakeExplosion( origin, dir, + mod, shader, + 600, qfalse ); + } else if ( weapon == WP_LIGHTNING ) { // BFP - TODO: Just a test for lightning gun (eyebeam should have this behavior) + CG_SmokeExplosion( origin ); // BFP - Explosion smoke + } else { // BFP - Explosion effects + CG_ExplosionEffect( origin, dir ); + } // // impact mark @@ -1540,16 +1390,36 @@ CG_MissileHitPlayer ================= */ void CG_MissileHitPlayer( int weapon, vec3_t origin, vec3_t dir, int entityNum ) { - CG_Bleed( origin, entityNum ); + // BFP - Seems like a small redo from CG_MissileHitWall to adjust the needed effects + sfxHandle_t sfx = 0; + + // BFP - NOTE: Originally on BFP, players don't bleed, that's a friendly mod :P + // CG_Bleed( origin, entityNum ); // some weapons will make an explosion with the blood, while // others will just make the blood switch ( weapon ) { - case WP_GRENADE_LAUNCHER: - case WP_ROCKET_LAUNCHER: - CG_MissileHitWall( weapon, 0, origin, dir, IMPACTSOUND_FLESH ); + case WP_LIGHTNING: + break; + case WP_MACHINEGUN: + case WP_SHOTGUN: // BFP - TODO: Apply muzzle effects only to these weapon types (from default.cfg file from some character) + if ( weapon == WP_MACHINEGUN ) { + int r = rand() & 3; + switch ( r ) { + case 0: sfx = cgs.media.sfx_ric1; break; + case 1: sfx = cgs.media.sfx_ric2; break; + default: sfx = cgs.media.sfx_ric3; break; + } + } + trap_S_StartSound( origin, ENTITYNUM_WORLD, CHAN_AUTO, sfx ); + CG_MakeExplosion( origin, dir, + cgs.media.bulletFlashModel, cgs.media.bulletExplosionShader, + 600, qfalse ); break; default: + CG_ExplosionSound( origin ); // BFP - Explosion sounds + CG_SparksExplosion( origin, dir ); // BFP - Spark particles explosion + CG_ExplosionEffect( origin, dir ); // BFP - Explosion effects break; } } @@ -1826,10 +1696,5 @@ void CG_Bullet( vec3_t end, int sourceEntityNum, vec3_t normal, qboolean flesh, #endif // impact splash and mark - if ( flesh ) { - CG_Bleed( end, fleshEntityNum ); - } else { - CG_MissileHitWall( WP_MACHINEGUN, 0, end, normal, IMPACTSOUND_DEFAULT ); - } - + CG_MissileHitWall( WP_MACHINEGUN, 0, end, normal, IMPACTSOUND_DEFAULT ); } From 001aefd89568fc7e482bc9d975269b0059ba03ba Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Fri, 18 Oct 2024 00:21:33 +0200 Subject: [PATCH 117/374] game: Fix lightning gun weapon number zeroed when sending weapon info to EV_MISSILE_MISS event. A small detail forgotten by id Software --- source/game/g_weapon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/game/g_weapon.c b/source/game/g_weapon.c index 62831c1..07413d1 100644 --- a/source/game/g_weapon.c +++ b/source/game/g_weapon.c @@ -715,6 +715,7 @@ void Weapon_LightningFire( gentity_t *ent ) { } else if ( !( tr.surfaceFlags & SURF_NOIMPACT ) ) { tent = G_TempEntity( tr.endpos, EV_MISSILE_MISS ); tent->s.eventParm = DirToByte( tr.plane.normal ); + tent->s.weapon = ent->s.weapon; // BFP - Sends weapon info to the event } break; From f3b4c52fdbb27e8901ced5853ec77af983105536 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Fri, 18 Oct 2024 00:23:19 +0200 Subject: [PATCH 118/374] game: Fix memset on BuildShaderStateConfig function --- source/game/g_utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/game/g_utils.c b/source/game/g_utils.c index 8c6f35b..afc45b6 100644 --- a/source/game/g_utils.c +++ b/source/game/g_utils.c @@ -59,7 +59,7 @@ const char *BuildShaderStateConfig() { char out[(MAX_QPATH * 2) + 5]; int i; - memset(buff, 0, MAX_STRING_CHARS); + memset(buff, 0, sizeof(buff)); for (i = 0; i < remapCount; i++) { Com_sprintf(out, (MAX_QPATH * 2) + 5, "%s=%s:%5.2f@", remappedShaders[i].oldShader, remappedShaders[i].newShader, remappedShaders[i].timeOffset); Q_strcat( buff, sizeof( buff ), out); From 8a890e379f9c5b5d058c1f2e41baf580e12ac8dd Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Wed, 23 Oct 2024 02:54:00 +0200 Subject: [PATCH 119/374] game: Apply splash damage to railgun like BFP originally does, accuracy has been removed --- source/game/g_weapon.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/source/game/g_weapon.c b/source/game/g_weapon.c index 07413d1..b0ea9c5 100644 --- a/source/game/g_weapon.c +++ b/source/game/g_weapon.c @@ -559,6 +559,8 @@ void weapon_railgun_fire (gentity_t *ent) { int i; int hits; int passent; + // BFP - For splash damage + int splashRadius = 120; damage = 100 * s_quadFactor; @@ -573,11 +575,6 @@ void weapon_railgun_fire (gentity_t *ent) { if ( traceEnt->takedamage ) { // BFP - Railgun events are also treated as a missile tent = G_TempEntity( trace.endpos, EV_MISSILE_HIT ); - - if ( LogAccuracyHit( traceEnt, ent ) ) { - hits++; - } - G_Damage( traceEnt, ent, ent, forward, trace.endpos, damage, 0, MOD_RAILGUN ); } } @@ -586,6 +583,17 @@ void weapon_railgun_fire (gentity_t *ent) { // snap the endpos to integers to save net bandwidth, but nudged towards the line SnapVectorTowards( trace.endpos, muzzle ); + // BFP - Moved EV_MISSILE_MISS there + // no explosion at end if SURF_NOIMPACT, but still make the trail + if ( !( trace.surfaceFlags & SURF_NOIMPACT ) ) { + // BFP - Railgun events are also treated as a missile + if ( traceEnt->s.eType != ET_PLAYER || traceEnt->physicsObject ) { + tent = G_TempEntity( trace.endpos, EV_MISSILE_MISS ); + } + // BFP - Sends dir vector variable to the event + tent->s.eventParm = DirToByte( trace.plane.normal ); + } + // send railgun beam effect tent = G_TempEntity( trace.endpos, EV_RAILTRAIL ); @@ -597,16 +605,10 @@ void weapon_railgun_fire (gentity_t *ent) { VectorMA( tent->s.origin2, 4, right, tent->s.origin2 ); VectorMA( tent->s.origin2, -1, up, tent->s.origin2 ); - // no explosion at end if SURF_NOIMPACT, but still make the trail - if ( !( trace.surfaceFlags & SURF_NOIMPACT ) ) { - // BFP - Railgun events are also treated as a missile - if ( traceEnt->s.eType != ET_PLAYER || traceEnt->physicsObject ) { - tent = G_TempEntity( trace.endpos, EV_MISSILE_MISS ); - } - // BFP - Sends dir vector variable to the event - tent->s.eventParm = DirToByte( trace.plane.normal ); + // BFP - Finger blast splash damage + if ( G_RadiusDamage( trace.endpos, ent, damage, splashRadius, 0, MOD_RAILGUN ) ) { + hits++; } - tent->s.clientNum = ent->s.clientNum; // give the shooter a reward sound if they have made two railgun hits in a row if ( hits == 0 ) { From 479b1e842c3b5c539cc04f29c8544f3fadd7c6ab Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Wed, 23 Oct 2024 03:13:53 +0200 Subject: [PATCH 120/374] game: Fix for weapons like lightning gun spreading too much when adding weaponTime is out of control --- source/game/g_active.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/source/game/g_active.c b/source/game/g_active.c index 1eb6e29..5cc2a32 100644 --- a/source/game/g_active.c +++ b/source/game/g_active.c @@ -1049,7 +1049,9 @@ static void KiAttackWeaponHandling( gentity_t *ent, usercmd_t *ucmd, pmove_t *pm break; } - client->ps.weaponTime += addTime; + if ( client->ps.weaponTime <= 0 ) { + client->ps.weaponTime += addTime; + } } break; // BFP - NOTE: The beam is triggering until pressing the attack key again after holded, using ki charge or blocking @@ -1082,6 +1084,23 @@ static void KiAttackWeaponHandling( gentity_t *ent, usercmd_t *ucmd, pmove_t *pm case WEAPON_STUN: break; } + + // debug print about weapon states and weapon time +#if 0 + switch( client->ps.weaponstate ) { + case WEAPON_FIRING: Com_Printf( "WEAPON_FIRING\n" ); break; + case WEAPON_BEAMFIRING: Com_Printf( "WEAPON_BEAMFIRING\n" ); break; + case WEAPON_CHARGING: Com_Printf( "WEAPON_CHARGING\n" ); break; + case WEAPON_DIVIDINGKIBALLFIRING: Com_Printf( "WEAPON_DIVIDINGKIBALLFIRING\n" ); break; + case WEAPON_READY: Com_Printf( "WEAPON_READY\n" ); break; + case WEAPON_EXPLODING_KIBALLFIRING: Com_Printf( "WEAPON_EXPLODING_KIBALLFIRING\n" ); break; + case WEAPON_RAISING: Com_Printf( "WEAPON_RAISING\n" ); break; + case WEAPON_KIEXPLOSIONWAVE: Com_Printf( "WEAPON_KIEXPLOSIONWAVE\n" ); break; + case WEAPON_DROPPING: Com_Printf( "WEAPON_DROPPING\n" ); break; + case WEAPON_STUN: Com_Printf( "WEAPON_STUN\n" ); break; + } + Com_Printf( "weaponTime: %d\n", client->ps.weaponTime ); +#endif } #undef KI_CONSUME #undef CHARGE_KI_ATTACK_STATE @@ -1255,7 +1274,6 @@ void ClientThink_real( gentity_t *ent ) { if ( client->ps.powerups[PW_FLIGHT] > 0 ) { // BFP - Flight speed client->ps.speed *= 2; } - // BFP - TODO: When charging a ki attack like beam wave, consult FlyingThink and SpectatorThink if that's the case // BFP - Enable flight FlyingThink( ent, ucmd ); // prevents client-server side issues when there's other client in-game From dabacc87751b60553e7138db4b98e5e4608a28ea Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Wed, 23 Oct 2024 03:28:11 +0200 Subject: [PATCH 121/374] game: Add TODO notes about a ki attack that damages and pushes opponents, and correct finger beam confusion in railgun fire comments --- source/game/g_weapon.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/source/game/g_weapon.c b/source/game/g_weapon.c index b0ea9c5..6b91cd5 100644 --- a/source/game/g_weapon.c +++ b/source/game/g_weapon.c @@ -61,6 +61,9 @@ void Weapon_Gauntlet( gentity_t *ent ) { } +// BFP - TODO: There's a ki attack that acts like a shockwave to push opponents, +// maybe gauntlet attack can be modified adding punch attack distance and pushing opponents + // BFP - No check gauntlet attack #if 0 /* @@ -605,7 +608,7 @@ void weapon_railgun_fire (gentity_t *ent) { VectorMA( tent->s.origin2, 4, right, tent->s.origin2 ); VectorMA( tent->s.origin2, -1, up, tent->s.origin2 ); - // BFP - Finger blast splash damage + // BFP - Finger beam splash damage if ( G_RadiusDamage( trace.endpos, ent, damage, splashRadius, 0, MOD_RAILGUN ) ) { hits++; } From 85b5eaf43a488a0389b48c0dbf61e55c54957619 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Fri, 25 Oct 2024 16:09:00 +0200 Subject: [PATCH 122/374] Add Ansel, Anthony, Chris, Dash and Remisser dev jorunals, move all dev journals into a new folder inside docs called 'old_dev_journals' and organize some documenation on PyroFragger dev journal. Add more history explanation notes in the docs, add GitHub badges, organize README notes and TODO list is now above and divided between Pending and Done --- README.md | 198 +- docs/old_dev_journals/ansel_dev_journal.md | 71 + docs/old_dev_journals/anthony_dev_journal.md | 50 + docs/old_dev_journals/chris_dev_journal.md | 582 +++++ docs/old_dev_journals/dash_dev_journal.md | 256 +++ .../pyrofragger_dev_journal.md | 1453 ++++++------- docs/old_dev_journals/remisser_dev_journal.md | 502 +++++ .../rodney_dev_journal.md | 196 +- .../yrgol_dev_journal.md | 1900 ++++++++--------- 9 files changed, 3361 insertions(+), 1847 deletions(-) create mode 100644 docs/old_dev_journals/ansel_dev_journal.md create mode 100644 docs/old_dev_journals/anthony_dev_journal.md create mode 100644 docs/old_dev_journals/chris_dev_journal.md create mode 100644 docs/old_dev_journals/dash_dev_journal.md rename docs/{ => old_dev_journals}/pyrofragger_dev_journal.md (96%) create mode 100644 docs/old_dev_journals/remisser_dev_journal.md rename docs/{ => old_dev_journals}/rodney_dev_journal.md (97%) rename docs/{ => old_dev_journals}/yrgol_dev_journal.md (98%) diff --git a/README.md b/README.md index 5343948..ac8c5df 100644 --- a/README.md +++ b/README.md @@ -1,72 +1,82 @@ Bid For Power (BFP) source code =============================== +[![Stars](https://img.shields.io/github/stars/LegendaryGuard/BFP?style=for-the-badge)](https://github.com/LegendaryGuard/BFP/stargazers) +[![Issues](https://img.shields.io/github/issues/LegendaryGuard/BFP?style=for-the-badge)](https://github.com/LegendaryGuard/BFP/issues) +[![Forks](https://img.shields.io/github/forks/LegendaryGuard/BFP?style=for-the-badge)](https://github.com/LegendaryGuard/BFP/forks) +[![License](https://img.shields.io/github/license/LegendaryGuard/BFP?style=for-the-badge)](#legal) +[![Build actions](https://img.shields.io/github/actions/workflow/status/LegendaryGuard/BFP/build.yml?style=for-the-badge)](https://github.com/LegendaryGuard/BFP/actions) +
+![Visits](https://badges.pufler.dev/visits/LegendaryGuard/BFP?style=for-the-badge) + -A legendary 90s era Quake 3 Arena mod. +A legendary Quake 3 Arena mod from the late 90s to early 2000s.

-bfpq3logo + bfpq3logo

+# TODO list -## *WARNING!* UNDER CONSTRUCTION! - -### Table of contents -> 1. [TODO list](#todo-list) -> 2. [History](#history) -> 3. [About the repository](#about-the-repository) -> 4. [References and clues to know how should be the game](#references-and-clues-to-know-how-should-be-the-game) -> 5. [How to build](#how-to-build) -> > 5.1. [Introduction](#introduction)
-> > 5.2. [Windows](#windows) -> > > 5.2.1. [Building QVM (using .bat)](#building-qvm-using-bat)
-> > > 5.2.2. [Building QVM (mingw)](#building-qvm-mingw)
-> > > 5.2.3. [MSYS2 (mingw) (Building dynamic libraries (.dll))](#msys2-mingw-building-dynamic-libraries-dll)
-> > > 5.2.4. [Cygwin (mingw) (Building dynamic libraries (.dll))](#cygwin-mingw-building-dynamic-libraries-dll) -> > -> > 5.3. [Linux](#linux) -> > > 5.3.1. [Building QVM (make)](#building-qvm-make)
-> > > 5.3.2. [Building QVM (using .bat)](#building-qvm-using-bat-1)
-> > > 5.3.3. [Building shared libraries (.so)](#building-shared-libraries-so) -> > -> > 5.4. [Optional](#optional) -> 6. [Notes](#notes) -> 7. [Legal](#legal) -> 8. [Credits](#credits) +### Pending: -# TODO list: +- [ ] Attacksets (configurable for cfgs) +- [ ] Cvars as described on old docs +- [ ] Gametype: Survival (`g_gametype 3`) +- [ ] Gametype: Oozaru (`g_gametype 4`) +- [ ] Gametype: Last Man Standing (`g_gametype 6`) +- [ ] Make ki energy regeneration, ki use, attacks, charging balance indicated on old docs +- [ ] Player physics movements +- [ ] Power Struggles (when two beam attacks collide) +- [ ] Powerlevel and Power Tiers indicated on old docs +- [ ] Remove some items like powerups and health pickups +- [ ] Skin Config File (explosionModel, explosionShader, missileRotation, missileShader, … look old docs and cfgs about that: Custom plugin models) +- [ ] Transformations (related to Power Tiers) +- [ ] 21 different ki attacks including controllable, homing, and chargeable attacks (no guns) (can be referenced to some previous tasks) +- [ ] 6 different selectable characters, each with 5 attacks (can be referenced to some previous tasks) + +### Done: -- [x] ~~Toggeable flight (bind key). Hint: FLIGHT POWERUP~~ -- [x] ~~Melee feature~~ -- [x] ~~Remove weapon visuals (models and stuff)~~ - [x] ~~Animations as listed on the old docs~~ +- [x] ~~Auras~~ - [x] ~~Bind key to recover ki energy~~ - [x] ~~Bind key to toggle speed (ki boost). HINT: HASTE POWERUP~~ -- [x] ~~Replace ammo to ki energy stamina~~ -- [x] ~~Third person traceable crosshair~~ +- [x] ~~Blocking (consumes ki energy, transfers all damage to ki instead of health, deflect missile attacks, more info on old docs)~~ - [x] ~~Breakable map entities ("func_breakable")~~ -- [x] ~~Ki trails (use ki to move, cg_kiTrail >10 )~~ -- [x] ~~Instant character model changing~~ -- [x] ~~Auras~~ -- [ ] Player physics movements -- [ ] Remove some items like powerups and health pickups -- [ ] Make ki energy regeneration, ki use, attacks, charging balance indicated on old docs -- [ ] Powerlevel and Power Tiers indicated on old docs - [x] ~~Hit Stun (makes player can't use ki, melee, block and charge)~~ -- [ ] Power Struggles (when two beam attacks collide) -- [x] ~~Blocking (consumes ki energy, transfers all damage to ki instead of health, deflect missile attacks, more info on old docs)~~ +- [x] ~~Instant character model changing~~ +- [x] ~~Ki trails (use ki to move, cg_kiTrail >10 )~~ +- [x] ~~Melee feature~~ +- [x] ~~Playable third person mode and first person vis mode~~ +- [x] ~~Remove weapon visuals (models and stuff)~~ +- [x] ~~Replace ammo to ki energy stamina~~ - [x] ~~Short-Range Teleport - Zanzoken (when pressing 2 times left or right)~~ -- [ ] Transformations (related to Power Tiers) -- [ ] Attacksets (configurable for cfgs) -- [ ] Skin Config File (explosionModel, explosionShader, missileRotation, missileShader, ... look old docs about that. ["Custom plugin models"](docs/Create_Custom_Models.md#the-skin-config-file)) -- [x] ~~Playable third person mode and first person vis mode (add the options in the UI Setup menu)~~ -- [ ] Cvars as described on old docs -- [ ] Survival gametype (`g_gametype 3`) -- [ ] Oozaru gametype (`g_gametype 4`) -- [ ] Last Man Standing gametype (`g_gametype 6`) -- [ ] 6 different selectable characters, each with 5 attacks (can be referenced to some previous tasks) -- [ ] 21 different ki attacks including controllable, homing, and chargeable attacks (no guns) (can be referenced to some previous tasks) +- [x] ~~Third person traceable crosshair~~ +- [x] ~~Toggeable flight (bind key). Hint: FLIGHT POWERUP~~ + + +## Table of contents +> 1. [History](#history) +> 2. [About the repository](#about-the-repository) +> 3. [References and clues to know how should be the game](#references-and-clues-to-know-how-should-be-the-game) +> 4. [How to build](#how-to-build) +> > 4.1. [Introduction](#introduction)
+> > 4.2. [Windows](#windows) +> > > 4.2.1. [Building QVM (using .bat)](#building-qvm-using-bat)
+> > > 4.2.2. [Building QVM (mingw)](#building-qvm-mingw)
+> > > 4.2.3. [MSYS2 (mingw) (Building dynamic libraries (.dll))](#msys2-mingw-building-dynamic-libraries-dll)
+> > > 4.2.4. [Cygwin (mingw) (Building dynamic libraries (.dll))](#cygwin-mingw-building-dynamic-libraries-dll) +> > +> > 4.3. [Linux](#linux) +> > > 4.3.1. [Building QVM (make)](#building-qvm-make)
+> > > 4.3.2. [Building QVM (using .bat)](#building-qvm-using-bat-1)
+> > > 4.3.3. [Building shared libraries (.so)](#building-shared-libraries-so) +> > +> > 4.4. [Optional](#optional) +> 5. [Notes](#notes) +> 6. [Legal](#legal) +> 7. [Credits](#credits) -### History +# History ![BFP_ZEQ2_history](https://github-production-user-asset-6210df.s3.amazonaws.com/49716252/267147557-7954d397-3df4-4cf7-b9c3-d62e393658ab.png) @@ -75,33 +85,71 @@ Ended: 2002 Bid For Power is a total conversion for QuakeIII that plays nothing like the original game. Players take control of Ki-powered superheros and battle it out in a mostly aerial fight. The game is highlighted by the work of a great art team and an original style, and the gameplay is extremely fast paced. It can be difficult to keep up with until you get the hang of it. -The source code is said to have started from SDK version 1.17 after the release of Quake 3 Arena (December 2, 1999). It continued to be updated, including the addition of `cg_particles.c` in version 1.29, until version 1.31. +The source code is said to have started from SDK 1.17 point release after the release of Quake 3 Arena (December 2, 1999). It continued to be updated, including the addition of `cg_particles.c` in 1.29, until 1.31. More info can be found in [Quake 3 Arena changelog version history](https://discourse.ioquake.org/t/quake-3-changelog-version-history/375). The original source code appears to be lost, but the assets and some docs are available in various places. Nonetheless, not all sources are accessible. -#### Old dev journals (1999 - 2002) +### Old dev journals (1999 - 2002) -- Old Yrgol dev journal: https://web.archive.org/web/20020205150340/http://www.bidforpower.com/journals/yrgol.php +The original URLs can be slower to load, so it's recommended to use markdown edition ones. -Click here to see the [Old Yrgol dev journal (Markdown edition)](docs/yrgol_dev_journal.md) +NOTE: Some URLs and images within these contents may be broken or partially recovered. The final parts of Chris and Yrgol dev journals were found here:
+Chris: https://web.archive.org/web/20011202065630/http://bidforpower.com/
+Yrgol: https://web.archive.org/web/20020520060044/http://www.planetquake.com/Bidforpower/
+On markdown editions, the data log is complete. -- Old Rodney Olmos dev journal: https://web.archive.org/web/20011218204129/http://bidforpower.com/journals/rodney.php +- Chris dev journal: https://web.archive.org/web/20020210145200/http://bidforpower.com/journals/chris.php -Click here to see the [Old Rodney Olmos dev journal (Markdown edition)](docs/rodney_dev_journal.md) + * [Chris dev journal (Markdown edition)](docs/old_dev_journals/chris_dev_journal.md) -- Old PyroFragger dev journal: https://web.archive.org/web/20011218203246/http://bidforpower.com/journals/pyrofragger.php +- Yrgol dev journal: https://web.archive.org/web/20020205150340/http://www.bidforpower.com/journals/yrgol.php -Click here to see the [Old PyroFragger dev journal (Markdown edition)](docs/pyrofragger_dev_journal.md) + * [Yrgol dev journal (Markdown edition)](docs/old_dev_journals/yrgol_dev_journal.md) -### About the repository +- Ansel dev journal: https://web.archive.org/web/20011203063814/http://bidforpower.com/journals/ansel.php + + * [Ansel dev journal (Markdown edition)](docs/old_dev_journals/ansel_dev_journal.md) + +- Anthony dev journal: https://web.archive.org/web/20020210151755/http://bidforpower.com/journals/anthony.php + + * [Anthony dev journal (Markdown edition)](docs/old_dev_journals/anthony_dev_journal.md) + +- Dash dev journal: https://web.archive.org/web/20020223210411/http://www.bidforpower.com/journals/dash.php + + * [Dash dev journal (Markdown edition)](docs/old_dev_journals/dash_dev_journal.md) + +- Rodney Olmos dev journal: https://web.archive.org/web/20011218204129/http://bidforpower.com/journals/rodney.php + + * [Rodney Olmos dev journal (Markdown edition)](docs/old_dev_journals/rodney_dev_journal.md) + +- PyroFragger dev journal: https://web.archive.org/web/20011218203246/http://bidforpower.com/journals/pyrofragger.php + + * [PyroFragger dev journal (Markdown edition)](docs/old_dev_journals/pyrofragger_dev_journal.md) + +- Remisser dev journal: https://web.archive.org/web/20020210152114/http://bidforpower.com/journals/remisser.php + + * [Remisser dev journal (Markdown edition)](docs/old_dev_journals/remisser_dev_journal.md) + +... And more dev journals can be found [here](https://web.archive.org/web/20011202135731/http://bidforpower.com/journals/). + +# About the repository We're making a replica of the lost source code.
The highest priority goal is to copy and recreate the complete logical structure of the BFP game. It would be a game SDK that'll provide a structured and standardized way to modify the mod.
-You'll notice some differences that the original Bid For Power didn't have, such as some adjusted UI buttons, sprite and particle aura type options in BFP options menu, server info menu has pagination and displays info, how particles move (e.g. bubbles are handled underwater and touching something solid vanishes to save performance), particle aura is almost implemented, ...
+You'll notice some differences and things that the original Bid For Power didn't have/were forgotten, incomplete or poorly made such as: +- some adjusted UI buttons +- removed unused cvars +- sprite and particle aura type options in BFP options menu +- server info menu has pagination and displays info +- how particles move (e.g. bubbles are handled underwater and touching something solid vanishes to save performance) +- particle aura is almost implemented +- some cvars didn't save changed values after quitting the game that happened on original BFP (means that `CVAR_ARCHIVE` wasn't on them), but these are now applied on replica +- ... + Any fixes, improvements and contributions are welcome. But we can't accept secondary things and other stuff that don't reach the goals. -### References and clues to know how should be the game +# References and clues to know how should be the game Documentations, references and extracted stuff will give us clues to reach the goals.
@@ -164,11 +212,11 @@ Other q3 config: * [q3config.cfg](cfgs/q3config.cfg) -### How to build +# How to build -#### Introduction +### Introduction -*IMPORTANT NOTE TO THE DEVELOPMENT*: all source code files should be **UTF-8 without BOM** and **Unix (LF)**, otherwise, it will cause compiler errors when using MakefileQVM (most likely, syntax error will be displayed). +*IMPORTANT NOTE TO THE DEVELOPMENT*: all source code files must be **UTF-8 without BOM** and **Unix (LF)**, otherwise, it will cause compiler errors when using MakefileQVM (most likely, syntax error will be displayed). - `.map` file is a linker map file, which is generated by the linker when it links together multiple object files into an executable or shared library. It contains information about the symbols (such as functions and variables) defined in each object file, as well as their addresses in the final executable or library. The information in the map file can be useful for debugging and performance analysis. For example, it can help you identify which functions are taking the most time to execute, or which functions are being called from which parts of the code. @@ -362,7 +410,7 @@ The information in the map file can be useful for debugging and performance anal
-### Notes +# Notes **IMPORTANT NOTE**: This repository was initialized from https://github.com/marconett/q3a. @@ -394,9 +442,9 @@ The information in the map file can be useful for debugging and performance anal - ui_specifyleague.c - ui_spreset.c -### Legal +# Legal -The mod source code is GPLv3 licensed, the source code contents are based on Quake III Arena which is GPLv2 licensed. +The mod source code is [GPLv3 licensed](./COPYING), the source code contents are based on Quake III Arena which is [GPLv2 licensed](./GPL-2). The ancient abandoned MP3 decoder (`ui_mem.c`, `ui_mem.h`, `ui_mp3decoder.c` and `ui_mp3decoder.h`) is based on code from various contributors: - Copyright (C) 1993 Sun Microsystems @@ -404,22 +452,25 @@ The ancient abandoned MP3 decoder (`ui_mem.c`, `ui_mem.h`, `ui_mp3decoder.c` and - Copyright (C) 1999 Aaron Holtzman - Copyright (C) 2000-2001 Tim Angus -#### Bid For Power name +The images, screenshots, and URLs, even in the docs, included in this repository are used for reference purposes only and are not covered by the GPL license. They're sourced from various locations and are subject to their respective copyrights and terms of use. + +### Bid For Power name Nobody owns the "Bid For Power" name. Bid For Power was founded by Chris James and likely ended up in the palm of Yrgol's hand (although Yrgol doesn't own the assets). The owner, the maintainer and the contributors of the repository don't own this name.
This does not give any single person or a group of people to sell the name, basically it belongs to the original community.
The Bid For Power team may provide sufficient security against any claims or improper use of the name. -## Credits +# Credits Bid For Power is made by these staff members. We don't own materials such as art designs, maps and character models from their assets.
-#### Bid For Power Staff Members +### Bid For Power Staff Members +

Ansel
-Skin Artist
+Skin Artist

Anthony
2D Artist
@@ -462,4 +513,5 @@ Project Lead, Lead Programmer
::Additional Assistance::
Mooky, Perfect Chaos, Dakota, Bardock, DethAyngel, Ebola, Badhead, $onik, Gigatron, Timex & Nat. +

diff --git a/docs/old_dev_journals/ansel_dev_journal.md b/docs/old_dev_journals/ansel_dev_journal.md new file mode 100644 index 0000000..a1391ce --- /dev/null +++ b/docs/old_dev_journals/ansel_dev_journal.md @@ -0,0 +1,71 @@ +# Another character design - 11/14/2001 by Ansel + +Hey +I just finished texturing Pyrate a few weeks ago, so I thought I'd get some concept sketches going for another character. + +"Ryuujin - Stands for Dragon God in japanese. He is, obviously, a god who has spent the past 3 millenia training his mind and his body. He rarely speaks, and is rarely seen, but he always shows up when there is trouble. His ki is "different," kind of mysterious and very powerful. He wields two scerpent-dragon swords whose blades are made of the same ki as a kienzan." (taken from pyrofragger's devjournal) + +ryuujin_concept_art + +Sorry for the bad image quality, I don't have a scanner. + +This is not a final concept, and as always feedback is welcome. + +-Ansel + + + + +# Concept Drawings - 09/04/2001 by Ansel + +As you probably already know, BFP will be having original characters, so I went and did a few concept drawings. Here is my first concept- + +c1noname_pyrate + +If you have any questions or comments, please stop by the forums. + +-Ansel + + + + +# New Icons - 07/19/2001 by Ansel + +I finished all of the new attack icons for BFP. I won't show them all, but here is three more. You already saw the kamahameha icon in Chris' journal. + +

+ bakuhatsuha +
+ bigbang +
+ sbc +

+ +By the way, the attacks in order are: Bakuhatsuha, SBC, and Big Bang Attack. + +-Ansel + + + + +# What happend? Gohan happend - 04/03/2001 by Ansel + +We promised that we would show sceens of the new models, here is one. +Its a screen of Pyrofragger's new Gohan model, skinned. +The model is seperated in this shot though, we didn't have time to get a render of him put together. + +bfpgohan02 + + +Expect renders of gohan and krillin's new skins soon. + +Ansel + + + + +# First Update - 04/03/2001 by Ansel + +Just finshed the Gohan and Krillin skins for the new models, which means my phase 1 work is done.
+Ansel + diff --git a/docs/old_dev_journals/anthony_dev_journal.md b/docs/old_dev_journals/anthony_dev_journal.md new file mode 100644 index 0000000..d5d4b0c --- /dev/null +++ b/docs/old_dev_journals/anthony_dev_journal.md @@ -0,0 +1,50 @@ +# Old DBZ BFP art - 01/21/2002 by Anthony + +Hey guys, seeing as how some fan paks are gonna be released with DBZ stuff that works in BFP, I thought I'd post some of the old drawings I did for the original character select screen. So anyway, an example: + +c-freeza + + +To see the others, go here: + + +[Ant's DBZ Stash](https://web.archive.org/web/20020210151755/http://www.antsin3d.com/dbz/) + + +Hope ya enjoy it, it would have been a nice select screen ^_^ +Oh yeah, if you'd like to see some other neat stuff(just some 3d), see [HERE](https://web.archive.org/web/20020210151755/http://www.antsin3d.com/tempcg) + + + + +# Play it chill - 01/18/2002 by Anthony + +What's up guys? The launch is going over like either a movie premier or New Year's Eve, or a mix of both. Play it cool and you'll get it. I counted 2500 people in line over at Fileplanet, and everyone else is getting just as hammered. We know one thing: you won't have any problems finding opponents! I hope you guys all enjoy it, as I'm sure you will. Remember, take it easy and everyone will get the mod. Don't want anyone to get hurt ;] Have a BLAST! + + + + +# Stuff - 08/02/2001 by Anthony + +The box art image will be released shortly. On another note, I'd like to request that you not send any money to me in any way, be it capital, goods, or services. I'm not going to play off your gratitude and anxiousness for this mod by asking for such. I would consider doing so disgusting. Naturally it's not my place to judge the souls of others who may wish to.... +PS: Of course, Icey's now gone, as are his journal entries which I was referring to above. We'll have more info sometime late next week, probably another happy announcement. + + + + +# Art - 04/17/2001 by Anthony + +Just a little update, I finished the box art I was working on. You'll all get to see it in due course, a little closer to release. Of course, I can still tease you... + +bfpbox + +Anthony + + + + +# Cover / Promotional Art - 03/07/2001 by Anthony + +Hey guys. Since my old posts aren't here any longer, I'll remind you newbies who I am. I do stuff like the character select screen drawings, which I hope you all enjoy. Currently I'm working on cover and promotional art for BFP. Note that I am not in any way suggesting that BFP is going to be released outside of freeware on the Net-we just want to have plenty of graphics and titles that can be used to promote the best mod around, both for Phase 1 and the following products. Anyway, since it's all under the blanket until we see release, I won't be able to really describe my progress here-just suffice to say that progress is being made! + + diff --git a/docs/old_dev_journals/chris_dev_journal.md b/docs/old_dev_journals/chris_dev_journal.md new file mode 100644 index 0000000..3b75171 --- /dev/null +++ b/docs/old_dev_journals/chris_dev_journal.md @@ -0,0 +1,582 @@ +# BFP release time - 01/18/2002 by Chris + +We hope to have Bid For Power ready by 6 PM pacific time. + + + +# Still need mirrors - 01/18/2002 by Chris + +Now that Bid For Power has been released we need Mirrors now more then ever. If you have managed to fight through the lines and have gotten your hands on a copy of Bid For Power and would like to host is please email me at chris@bidforpower.com +We are getting some reports that windows XP users are having problems getting the .exe version of Bid For Power to work properly. If this occurs then rename the .exe version to .zip and it should work fine. + + + + +# Hold on... Almost there... - 01/18/2002 by Chris + +Bid For Power will be ready around 10 o'clock eastern time. Our ftp decided that it didnt like the bfp and ate it so we are re-uploading. + +

*update*

+ +We are getting some reports that windows XP users are having problems getting the .exe version of Bid For Power to work properly. If this occurs then rename the .exe version to .zip and it should work fine. + + + + +# Last minute mirrors - 01/18/2002 by Chris + +Hey guys. +Any gaming sites still interested in mirroring Bid For Power please send me an email to chris@bidforpower.com + +Please no tripod or geocities accounts. + +Thanks. + +We are getting some reports that windows XP users are having problems getting the .exe version of Bid For Power to work properly. If this occurs then rename the .exe version to .zip and it should work fine. + + + + +# Mirror, mirror, on the wall... - 01/11/2002 by Chris + +If there are any webmasters who be interested in mirroring Bid For Power please [email me](mailto:chris@gamethrust.com). All that we ask in return is that your site is capable of numbering the amount of downloads. +Thanks. + + + + +# Bid For Power - 12/27/2001 by Chris + +If you want to truly understand something, try to change it. + + + + +# Clouds composed of water vapor are up in the, you know, sky. - 12/17/2001 by Chris + +We're trying to get the last two models animated, skinned, prepped, etc... You name it, we're trying to get it done but progress is slow and delays are very fast. What I can say about the release is that it won't happen before Christmas. +Well now that the bad new is out of the way I can hint at the good news, as to wether we can get it out before New Year's is very much up in the air but the release will be soon. + + + + +# The Monday Update - Chris - 11/26/2001 + +Dash has been revising his Palace level and it's looking amazing. He has been working on improving the lighting, adding different floor textures, creating new details in different areas, and optimizing the building structure to make it run smoother. The screenshots speak for themselves though: + +

+ heaven_03 + heaven_04 +

+ +

+ heaven_05 + heaven_06 +

+ + + + +# The Monday Update - Chris - 11/20/2001 + +Another late Monday's Update but I think this one is worth it as we're showing off six new in-game screenshots and one brand new rendering. The six in-game screenshots show off our three completed characters, Kyah, Gothax, and Shilo all modeled and skinned by Rodney. These screenshots are taken from the new beta the team has been playing around with. The rendering is of, Ryuujin, Pyrofraggors new character he is woking on. + +

+ Ryuujin_InProgress +

+ + +

+ bfp_characters_beta_01 + bfp_characters_beta_02 + bfp_characters_beta_03 +

+ + +

+ bfp_characters_beta_05 + bfp_characters_beta_06 + bfp_characters_beta_07 +

+ +I also thought I'd go ahead and post some of the recent developer journals as they have quite a bit of good updates in them. + +- Yrgol's Developer Journal
+_"What we are currently working on is equivalent to beta 2 for most mods, or in bfp jargon phase 1. We had phase 1 completed for dbz quite a long time ago, and then the funimation/infogrames stuff happened. Most of the time since then has been used for converting bfp to not use dragonball z copyrights._ + +_Direct hit detection has been made more reliable. This makes the kienzan equivalent and the deathball easier to use._ + +_Explosion damage is no longer all or nothing. The damage decreases as distance from the explosion increases like in baseq3._ + +_Attack radius has been separated from explosion radius. The attack radius and explosion radius for each of the attacks have been tweaked._ + +_The knockback physics for attacks and explosions has been seriously tweaked. Attacks can now be used to rocket jump._ + +_Boost jumping has been toned down. It was simply too excessive before._ + +_Another total rebalance of all attacks happened."_ + +- Pyrofragger's Developer Journal +_"Sometime this week i'll have pictures of Ryuujin for you guys. The model is done and uv mapped, but i have to redo much of the physiquing and ansel still has to skin it. You'll see skinned renders in here soon as well as ingame shots on the mainpage."_ + + + + +# beta and a little extra - 11/18/2001 by Chris + +Yrgol uploaded a new beta for the team to test out. i've been playing it for awhile now and it really plays great. The overall balancings (mentioned in Yrgol's journal) really work nice now, the game has an awesome feel to it. +I noticed my comments concerning Nintendo marketing mainly to kiddies didn't go unheard as I got quite a few emails about the comments. The emails I got ranged in intelligence but overall a lot of people are really looking forward to the new resident evil games exclusively on the gamecube. But I still think gamecube is being marketed to kiddies. + +Also, a few journal entries back I mentioned putting up a signed copy of Half-Life, by the team at Valve Software, on [Ebay.com](https://web.archive.org/web/20020210145200/http://www.ebay.com/). Well I finally got around to it and you can now bid on a [first edition of Half-Life signed by the team at Valve Software](https://web.archive.org/web/20020102191742/http://cgi.ebay.com/aw-cgi/eBayISAPI.dll?ViewItem&item=1299439693). + + + + +# The Monday Update... On Friday - Chris - 11/10/2001 + +Sorry for the late update but I didn't get back from the Gamecube party till later then expected. As promised here are the brand new in-game screenshots of our new character Shilo, modeled by Rodney. Shilo has some strong anime influences and it really comes out in his shape, check it out: + +

+ bfp-shilo01 + bfp-shilo02 + bfp-shilo03 +

+ +

+ bfp-shilo04 + bfp-shilo05 + bfp-shilo06 +

+ +Here goes my rant about the Nintendo Gamecube for anyone interested. I had some high hopes for the Gamecube considering Nintendo's track record with it's releases. Usually with its releases it has some good launch titles and really makes good use of the system however the games I played (which were all on High Definition Panasonic Flat Screen TV's) seemed less then great. The graphics were good on the Star Wars game but other games like Luigi's Mansion, Waverace, and Star Fox were kind of bland, it seems like Gamecube is going in the "Kiddy Games" direction. I hope Nintendo starts to get more into realistic graphics, if they dont I could see them singling out a lot of people. + +If anyone knows of any launch parties for the Xbox in the Seattle area please email as I would be very interested in attending. Been dying to play an Xbox. + + + + +# The Monday Friday Update - 11/08/2001 by Chris + +On Friday we will be posting our Monday Update as things got a little hectic on Monday so we pushed it to this Friday. All is not lost as we will be showing off Shilo, the new model by Rodney, in-game. +In a semi-gaming related note, does anyone know if Xbox will be having a release party or anything similiar to Nintendo's Gamecube club where they basicly have parties where everyone can come and play the games? I found out Nintendo is having a Gamecube Club party in Seattle which is only about 20 minutes from where I live so this weekend I will be heading over there to check out some of their games. If anyone else in the seattle area is going as well drop me a line. + + + + +# Mondays update - 11/05/2001 by Chris + +Hi guys. +I'm a little backed up right now but hope to have mondays update later tonight. Until then I suggest you either download the second test version of wolfenstein or try and grab a copy of the star wars teaser though its difficult to find a good site to download it from. + + + + +# Monday Update - Chris - 10/29/2001 + +Some brand new in-game screenshots of three of our new characters; Kyah, Gothax, and Pyrate. The action takes place in the Triblecle Creek, an improved version of Dash's Namek level. Next update will include in-game screenshots of our newest character, Shilo. + +

+ ingame_01 + ingame_02 + ingame_03 +

+ +

+ ingame_04 + ingame_05 + ingame_06 +

+ +I also thought I would repost some info dug out from the recent Developer journal updates as some big stuff was mention; + +Yrgol's Dev Journal: + +- _"Per-skin config files have been added that allow things like attack names and voices to be defined by the skin. I have plans to move a lot of stuff into these config files, including attack shaders, sounds, and models. The individual models will never be able to define how the attacks operate, only how they are displayed to the user. "_ + +- _"I'm working on attack scripting for servers only. This will allow new attacks of any rough type that bfp already contains to be added to the game with little or no code. I have a script file set up and partially implemented that has like 30 variables for each of the attacks. This will not allow models to define new attacks, but it will allow team members to work on attacks without me, or mods of bfp. It also lets server ops who hate the game balance to tweak it significantly. "_ + +Remisser's Dev Journal: + +- _"I compiled the music... if anyone has any clue as to how to make these files smaller, tell me..."_ + +Chris Dev Journal: + +- _"Last time I updated I hinted at reworking our version of capture the flag and I've spent some time working different additions to it. Some new twists to classic game which add a lot more to it."_ + +- _"I spent sometime on designing a single-player/co-op gameplay mode which is definately a fast paced experience very similiar to something like... Dragonball Z. Keeping with our "new release/ new gameplay mode" idea I hope to have this be our first new gameplay mode release after our initial release."_ + + + + +# Gameplay additions - 10/24/2001 by Chris + +Last time I updated I hinted at reworking our version of capture the flag and I've spent some time working different additions to it. Some new twists to classic game which add a lot more to it. +I also spent sometime on designing a single-player/co-op gameplay mode which is definately a fast paced experience very similiar to something like... Dragonball Z. Keeping with our "new release/ new gameplay mode" idea I hope to have this be our first new gameplay mode release after our initial release. + +In other news, I've been thinking about starting an auction on [Ebay.com](https://web.archive.org/web/20020210145200/http://www.ebay.com/) (No, I wont be auctioning Bid For Power) of a first edition copy of Half-life I have which was signed by everyone from the original team at Valve Software. I got rid of all my game boxes and stumbled across Half-life, it's just been sitting on a shelf (unopened) for years now and thought someone else might appreciate it more. + + + + +# The Skies Above Heaven - Chris - 10/23/2001 + +Here are some new shots of the brand new skyline for Dash's Palace level. We will be updating with a new shot of Pyro's character just as soon as he gets everything finished on it, stay tuned. + +

+ palace_01 +

+ +

+ palace_02 +

+ + + + +# Midnight Update - 09/30/2001 by Chris + +It's midnight and I got finished looking through most of the posts on the forum so I thought I'd make an update to the dev journal. In a week from wednesday we will be having our internal due date for all the models going into the first release of Bid For Power (just so I dont get a lot of brainless posts on the forum, no this does not mean we are releasing in a week). +I was playing NilreMK's new model, pyrate, and it's an awesome piece of work, once it's fully skinned and animated we'll be sure to post shots of it on the main page along with Pyro's new model. + +I finally got DSL installed. I heard all those horror stories about having trouble getting the line to work and never thought it would happen to me. Well it did. Everything from having my line dropped, wrong equipment shipped, faulty NIC, secondary line problems, and pissed off tech support people who had me on hold for a total of 4 hours. + +Since I now have the luxury of playing games over the internet without having huge slowdowns I have been addicted to RTCW, especially having sniper only games. + + + + +# Status update - 09/14/2001 by Chris + +We've been working hard on getting the new Bid For Power ready and as Yrgol mentioned earlier our biggest competition is from ourselves. The new modelers in my opinion have outclassed our previous work that really shows the talent of our modelers. +As far as a release date is concerned were working hard to get everything ready but due to several things we haven’t been able to name a date nor will we till we are absolute. Apologizes if any previous updates had people thinking otherwise but I guess that’s the way it is when developing games. + +Our site has become riddled with advertisements which unless we’re in nascar don’t go together. We will likely be starting up a donation box similar to what planetnamek had which if we are successful we can remove all the advertisements (except for the banners at the top). + +Also, Computer Gaming Monthly ran a blurb about Bid For Power and I have been unable to find a copy of the magazine to check it out myself. If anyone has a copy of the article and can scan it and send it to me at chris@gamethrust.com it would be a big help. + +Thanks. + + + + +# Announcement - 08/05/2001 by Chris + +Expect the announcement to go up within the next hour. Thanks for your patience. + + + +# Updated features - 07/17/2001 by Chris + +Some new things to mention. +We've created some new Attack icons which look a lot more realistic then the current set of attack icons. Ansel has been working on this new set and they look great, here is an early version of the Kamehameha: + +

+ kamehameha_icon +

+ +Another thing to mention is the new interface we are planning. With the release of TA's code we can now implement a more advanced UI into Bid For Power. We're still working on the different looks but hopefully we can have something more solid to show next update. + +In Yrgol's previous update he mentioned the custom model support. We decided to branch out with this and add several different versions of Vegeta. Now instead of choosing between different skins you can now select different models of Vegeta. Here is what we have planned. + +Vegeta from the Freeza Saga +Vegeta from the Cell Saga +Vegeta from the Buu Saga + +Each model will range in size and shape and with three different modelers they will each have their own unique look. I should also note that we will still be keeping the existing set of skins for the models. + +Should have some good things to show off in the next update. + + + + +# Android #16 mirrors - 06/20/2001 by Chris + +We are low on mirror sites for Android #16 so if you have a site that is willing to host Android #16 please [email me](mailto:chris@gamethrust.com). + + + +# Life insurance pays off triple if you die on a business flight. - 06/18/2001 by Chris + +The site laucnh is going great and now we've pretty much got everything up and running as the image section will be ready soon enough. The dev journals, team section, faq, about, etc... are all doing great and if they haven't been updated yet will be later tonight. Android #16 should be ready for download tomorrow. We're packing him up right now and then sending him off to the good folks at fileplanet to be mirrored. The FAQ section will get a nice little update over the night and if you guys have any suggestions for new questions please post them in our [forum](https://web.archive.org/web/20020210145200/http://www.bidforpower.com/forum/showthread.php?s=83d20c406900acb34d0a60f904548094&threadid=6049). Expect some even cooler looking screenshots for tomorrow's update. + + + +# The martyrdom of Saint Me - 05/29/2001 by Chris + +Much has been happening but due to the new site we have been laying off on updating which is mainly my fault. It has been a busy couple of weeks and since the shadow of E3 has past us we can start to kick it into high gear again. +The ETA on the new site is still up in the air but the good news is that when we release the new site we will also release a playable Android #16 for Quake 3 Arena much like we did with our Vegeta model. + +We should have some more news soon. As far as other stuff I finally met Chuck Palahniuk at a recent reading for his new book, Choke. He is a very cool guy and now I will stop quoting Fight Club and start quoting other work by him. + + + + +# Where you going with this ikea boy? - 04/27/2001 by Chris + +Tomorrow I will finish up work on the in-game footage and should have something fairly nice to show off though it will take a little while for Fileplanet to begin mirroring the clips so they may not be officially posted till monday but they will be worth the wait. +Some sites have been emailing me asking if they can have some type of banner to use to link Bid For Power from their sites. About time I posted this banner, we should have a button available soon as well. + +

+ + bfp-banner01 + +

+ + + +# insert Fight Club saying here - 04/23/2001 by Chris + +I am doing a little video work and I was wondering if anyone here knows of a good program to extract both audio and video from quake 3. It is very important it records both audio and video, if you know where I can download a copy of a program like that please email me at chris@gamethrust.com +thanks. + + + + +# I am Jacks smirking revenge - 04/15/2001 by Chris + +The link submission is over as I collected way too many then I expected but thanks to everyone who submitted. We cant add everyone and most likely we will only add about six links. As for the ETA on the new site it will be about 2 weeks as we are waiting for some help from gamethrust to convert the site over to php3 format. +As you have noticed from some of the other members subtle hints work is closing on phase I. + +Anthony finished up work on the boxart for Bid For Power and it looks amazing, we are very eager to show it off. Very cool stuff. + +I managed to find some time over easter sunday to work on some levels for Half-life, take a peak: + + +

+ visions110000 +

+ +[Some other levels of mine](https://web.archive.org/web/20020215120703/http://www.bidforpower.com/chris/portfolio.htm) + + + + +# Link Submission - 04/13/2001 by Chris + +I am working on the link section to Bid For Power. If you are interested in having your site added please email me at chris@gamethrust.com Please no clan sites. +Please note that we are looking for sites that are either DBZ oriented, Quake 3 oriented, or Bid For Power oriented and not all that are submitted will be linked. + +As well as I am on the subject of updating the site, if there are any questions you think should be added to the FAQ email them to me and I will try and include them. + +And yes the new site will have a working image section... + + + + +# New Model Clips - 04/09/2001 by Chris + +The clips were hurting our bandwidth so I went and moved them to a new server. They will be posted on the main site in a little bit. +Just wanted to thank everyone that emailed me about mirroring the files. + + + + +# I am Jacks Late Fee - 03/26/2001 by Chris + +Looks like RC 3 did not go as planned. We will have it out the door by the end of the week. As for where our models stand the buff version of Freeza has been modeled and exported and now Rodney is working on the skin for him. +Pyro finished the models of gohan and krillin on sunday morning so Ansel is working on skinning both Krillin and Gohan. In case you were wondering krillin and gohan are modeled with their original Gi outfits. + +Later this week I can update with the body transformation of Freeza and the new models of Krillin and Gohan... who knows, maybe even an in-game movie. + + + + +# I am Jacks missing Skin Artist - 03/24/2001 by Chris + +Hi guys. +We are trying very hard to meet the monday deadline for RC III but we have run into a slight problem. We have three models which need to be skinned and currently our skin artists already have work or are discovering a life away from the computer for the weekend (could you blame them?) + +Being that we would really like to meet the monday deadline I am asking if any skin artist would like to give some temporary assistance and help with the skinning of our Krillin and Freeza models. + +The skin artist would have to be very good and have some prior experience to show plus he would have to work under the gun as we have about two days to get the skin done. + +If anyone would like to volunteer to skin our Krillin and Freeza models please email me at Chris@gamethrust.com with a link to some of your prior work. + +Thanks + + + + +# I am jacks update - 03/23/2001 by Chris + +Well I know the website hasnt been updated in awhile and thats partly my fault but dont worry we have kept ourselves busy. +Yrgol is working on a slight rebalance to phase I damages. Pyro has Krillin and Gohan done and Ansel should have the skins done this weekend meaning monday we will have a new gohan and krillin in game. + +NilreMK is working on exporting Tabouhs Freeza model(s) which should also be finished on monday, meaning monday will hopefully be a nice update of Gohan, Krillin, Freeza and also Kits new map and as a bonus Dashs updated namek waters. + + + + +# Without pain, without sacrifice, we would have nothing. - 03/09/2001 by Chris + +I would like to announce that for Phase II of Bid For Power (which will chronicle the android and cell sagas) we will be introducing an advanced melee system, rebalanced attack system, and several new RPG elements including "Unique Characteristic Traits" which will give each character their own special abilties. +An example of this will be that Piccolo will have the ability to regenerate health and Vegeta will have the ability to increase his power after experiencing an attack. Its getting pretty late so I will likely update tomorrow with a much more thurough explaination. + +Stay tuned... + + + + +# With a gun barrel stuck between your teeth, you only speak in vowels. - 03/08/2001 by Chris + +Announcement(s) postponed till tomorrow... + + + +# I am Jacks raging bile duct. - 03/07/2001 by Chris + + +Hi guys, +Sorry that I havent produced that video clip yet but I was holding off until I setup my new system. I did some talking with Yrgol and we are going to be adding even more effects to the power struggle so once those effects are in and my system is up to par I will post the video. + +Now on to even better news... Phase II news. We consider phase I our test run, our basic platform to build on. We are now planning some of the various new features for phase II and we may be adding a ton of new features including advanced melee system, new tier system, and an RPG edge to it all, very cool stuff. + +Tomorrow I should have some more interesting news about our phase II plans and maybe even some bigger news, all depends on how things work out. + +Almost forgot, I thought I would list some of the Bid For Power fan sites out there for people to check out: + +[Bid For Power World](https://web.archive.org/web/20020210145200/http://bfpworld.digitalnova.com/) + +[Bid For Power Online](https://web.archive.org/web/20010609020639/http://bfponline.4t.com/news.html) + +[PlanetBFP](https://web.archive.org/web/20010515205855/http://www.planetbfp.com/) + +[Bid For Power Clan League](https://web.archive.org/web/20010516202746/http://www.bfpcl.f2s.com/) + +[Bid For Power Net](https://web.archive.org/web/20020120230500/http://bfpnet.cjb.net/) + + + + +# I am Jacks cold sweat. - 02/19/2001 by Chris + +I have been tinkering on a new 30 second clip showing off a fight between some of the characters and unfortunately the movie of Piccolo fighting Krillin in the new Cell Tournament map feel to the cutting room floor but I thought I would atleast go ahead and post some screenshots of the now deceased video. +If I were to post a movie clip showing off a battle between two opponents who would you want the movie to have in it and at which map? [Post your answer in our forum](https://web.archive.org/web/20010407130034/http://www.bidforpower.com/forum/showthread.php?threadid=18016) + +

+ pic_vs_kril_01 +

+ +

+ pic_vs_kril_02 + pic_vs_kril_03 +

+ +

+ pic_vs_kril_04 + pic_vs_kril_05 +

+ + + + +# I am Jacks complete lack of surprise. - 02/18/2001 by Chris + +I was supposed to update with some screenshots of Cells Tournament but I decided to take it one step further and update with a vide clip from the map. I decided to create a clip of Gohan performing his Angry Gohan Attack but unfortunately the compression sucks and the 25 second clip runs out to be 17 megs. +And with our server I dont think we will be able to handle it so most likely by tonight I will be updating with a very compressed smaller version of the AGA. + + + + +# You have a kind of sick desperation in your laugh... - 02/13/2001 by Chris + +Gamethrust has posted a preview of Bid For Power :: RC 2. This is the first preview on RC 2 and most likely will be the only online preview of it and I suggest you all visit [Gamethrusts Preview of RC 2](https://web.archive.org/web/20010406214208/http://www.gamethrust.com/?page=game_preview&gameid=bidforpowerpc) . +We have some big plans for RC 2 but I wont be able to comment on those for atleast a few days until then though I suggest you call check out [Gamethrusts Preview of RC 2](https://web.archive.org/web/20010406214208/http://www.gamethrust.com/?page=game_preview&gameid=bidforpowerpc) . + + + + +# The things you own end up owning you. - 02/04/2001 by Chris + +Just a quick update before I start heavily updating the site over the weekday. I stumbled across this website and it really impressed me. The site is called [BidForPowerWorld](https://web.archive.org/web/20011202104243/http://bfpworld.n3.net/) and looks great. +From what I hear they are in need of some additional staff members so if you are interested I suggest you send them an email. + + + + +# Is Tyler my bad dream? Or am I Tylers? - 01/27/2001 by Chris + +I just thought I would update and tell everyone that both Planetquake and Quake3world have posted previews of Bid For Power +[Quake3worlds Bid For Power Preview](https://web.archive.org/web/20011224224432/http://www.quake3world.com/modifications/bfp.html) + +[Planetquakes Bid For Power Preview](https://web.archive.org/web/20020221094152/http://www.planetquake.com/features/articles/bidforpower_a.shtml) + +A big thanks to both those sites for doing the previews. In case your wondering if any other sites will be doing previews of Bid For Power in the near future the answer is yes. The GNN network will be doing a preview of Bid For Power and it should be ready soon. + +Since everyone on the forums have been wanting to see more shots of our newer maps I will be posting screenshots of each map on our site over the next week. + + + + +# Updates soon enough - 01/20/2001 by Chris + +We have been hard at work on Bid For Power and soon enough I will be updating the website with several shots from our new maps which include Northern Earth, Glacier Lands, The Cave, NamekXL, and the Cell Tournament map. +As far as news on models the standard animations for Krillin and Gohan have been completely redone so they play a lot more smoothly now. We are about to shift work to Phase II in the next week on our models. + +I will also be updating the site with some roll-over clips of all of our models and I will also post a video clip of our Oozaru model which is fully modeled and skinned. + +The big updates should start on monday. + + + + +# Hey its working again - 01/07/2001 by Chris + +As you can tell our Developer Journals are working once again. They were down quite awhile but now everything seems to be under control. +First off, as you can tell by Planetnameks preview we have a beta copy of Bid For Power floating around. You can expect another preview soon by a Quake 3 oriented website. +This beta was made only for websites to preview Bid For Power and we will not be releasing it publicly. There is a lot more to talk about but I'm a little tired right now so I need to get some sleep. + + + + +# Emails and the almighty FAQ - 12/16/2000 by Chris + +I just wanted to let everyone know before they decide to email me or post on the messageboard about a specific question they should check out our FAQ and About sections, they have tons of information and 9 times out of 10 they have the answers to what your looking for. +I get a lot of people emailing me asking about when bid for power will be released. The answer is and always has been "when its done" emailing me wont change this. + +Check out the FAQ and Abour section as they are a great resource of Bid For Power information. + + + + +# Dev Journal Shift and some video clips - 12/14/2000 by Chris + +Recently Eddie did some tweaking on the developer journals so now only the five most recent journals are displayed on the main section while the others are displayed in the Dev journal section. +It looks like I am going to have to push back the release of the in-game clip a little because we had some lower framerates when recording as well as a huge download. + +I will be working over the weekend of splicing together some cool action sequences from in-game and hopefully posting it sunday night. + + + + +# FYI - 12/09/2000 by Chris + +I just updated the site and I just wanted to let everyone know that the vegeta and freeza featured in that update are not finished. +I have an out of date version of vegeta so his skin is not the final version you will see in Bid For Power though if you check out the last image of vegeta at the bottom (in the pepper city map) you will see his final version. + +Last weekend Rodney finished up the animations and tweaks to our freeza model which is now a lot larger looking but the skin is not in its final form. It will be soon though. + +Should have a lot more updates coming soon. + + + + +# Website Stuff - 11/29/2000 by Chris + +It seems the Developer Journals are now displaying properly. It's time for me to do another "State of the BFP” update. +As you can see we moved servers and the reason for this is because the popularity of Bid For Power is increasing and our previous server was getting hit pretty hard so Gamethrust offered to host us on there server which is a lot faster. I just want to thank Eddie at Gamethrust who has worked his ass off programming the site and setting it up and without Eddie we wouldn’t be at this new server, so big thanks to Eddie. + +There are still one or two areas of the site that are offline but they will be online soon enough. Our forums are flowing with tons of activity and we have recently been leaking some really nice screenshots on to the forums so if you haven’t checked them out yet do so or your missing out on the eye candy. + +Right now some of the team is focusing on Battle For The Planet and incorporating both Brolly and Oozaru to the game play. As for whether or not Brolly will make it into the Phase I release of Bid For Power is still unclear, we should know by the end of the week. + +I’d also like to point out one of the cool little things of Bid For Power that has seemed to go unnoticed so far. In Bid For Power we allow the user to setup the visuals to his or her liking and by doing so we give the player a lot of options. For example our Auras, we allow the player to select between four different versions, this feature applies to a lot of the visuals in Bid For Power and I think the fans will be fairly impressed with it when Bid For Power is released. + +The past few updates are what I call “tech” updates which aren’t meant to show off game play as much as they are to show off various effects and features we have put into the current builds. I will be posting a few more tech updates followed by some in-game video clips (still bordering on tech updates) and from there hopefully I will post some game play shots. + + + + +# Website Craziness - 11/29/2000 by Chris + +As you can tell the website is a little off right now while we are implmenting the developer journals. Sorry for the problems but they should be fixed by the end of the night. diff --git a/docs/old_dev_journals/dash_dev_journal.md b/docs/old_dev_journals/dash_dev_journal.md new file mode 100644 index 0000000..49be83c --- /dev/null +++ b/docs/old_dev_journals/dash_dev_journal.md @@ -0,0 +1,256 @@ +# Wallpaper - 01/06/2002 by Dash + +I'm making some art, and using **Rodney**'s renders and one of **Ansel**'s Ryuujin draws, I've did this wallpaper for you guys. + +bfp_wallpaper + + + + +# The Rainbow under the Waterfall - 12/30/2001 by Dash + +Today I did some work on the Mystic Mountains Map; deathmatch version. Here are some new screenshots, featuring a Rainbow, generated by the waterfall. Enjoy + +mm_new3 + +mm_new1 + +mm_new2 + +mm_new4 + + + + +# Mystic Mountains New Pics - 12/29/2001 by Dash + +Here are some new pics of **Mystic Mountains**. I finished the terrain, I added some trees ( by Pyrofragger ), but Kit Carson will add the other details and will do the entity work. Anyways it will be ready to be included in BFP release. + +mm_2 + +mm_1 + + + +(old lost image: https://web.archive.org/web/20020611021434/http://bidforpower.com/dash/mm_3.jpg) + + + + +# Mystic Mountains - 12/28/2001 by Dash + +**Mystic Mountains**: this is the name of the **BFP CTF** map that me and kit are going to work on in the last days before the release. **Pyrofragger** is doing awesome trees models for it, and when they will be in there will be a lot of scale sense. I've updated the **POTW** with a screenshot of the waterfall in the map, wich isn't the final, but it show up a bit of its effect. + + + + +# CTF Maps - 12/26/2001 by Dash + +Now that I have some things to show I can say you Merry Christmas. Me and Pyrofragger yesterday have started to think a Bid For Power CTF map and I have already finished the Terrain for it. Just to tell you, this map can contain 20 times Tribecle Creek (Namek Waters) or more. Thanks to Kit Carson for his sky. Wait some days for the completed one (With Giant Waterfalls). By the way, I'm creating the terrain for another CTF map, and on this one me and Kit will do a Team work. +Here are some pics of the terrain. + + +dactf1 + +dactf2 + +dactf3 + + + + +# Planet YH-85 Finished - 12/16/2001 by Dash + +I finished my new map: **Planet YH-85**. Here's a screenshots, featuring **Pyrofragger's** awesome Meteor model. + +yh85_final + + + + +# Planet YH-85 | New BFP Map - 12/15/2001 by Dash + +Ok that's the story... I'm creating an Urban Terror map, and I created a Terrain for that. I decided to use that terrain, with a different lighting, and different things, to create a map for Bid for Power. The map is now almost complete, I think I'll add a Meteor map object in the crater, if **Pyrofragger** create it for this map. It's name is **Planet YH-85** a desert, very cold and ostile planet, in the Eastern Galaxy. +Yes, you can see well, you don't need goggles. It's the great Vegeta, and I'm using the Dragon Ball Z Fanpack with the new BFP Beta Test. +Here are some screenshots: + + +yh85_1 + + +yh85_2 + + + + +# Update - 12/14/2001 by Dash + +Just to update my Dev-J, here are 3 screenshots of **The Palace** level. Chris hasn't posted these on the main page, so I'm going to post'em here. And about the **Christmas Header**, yes I did it :) +Booyakayshaa ! + + +palace1 + +palace2 + +palace3 + + + + +# Dash Design Redesigned ! - 11/28/2001 by Dash + +I've redesigned Dash Design Go to check it ! There are some cool things to see... +Thanks + + + + +# What the new POTW is ? - 11/12/2001 by Dash + +Well, today I was working on a Gundam Universe map using EasyGen. But, I said, why don't I make a terrain to use into a Bid For Power map too ? +**A Rethorical Question.** + +So I did this thing using Tribecle Creek (Namek Waters) Textures, and some from Kit's NamekXL (The Ground). + +I have yet to add some trees of curse and more details. So I dunno if I'll finish it in time for the imminent relase of the game. + +Visit Dash Design !
+**WWW.PLANETQUAKE.COM/DASH** + + + + +# Wop, I'm back - 09/05/2001 by Dash + +I'm back and I've already made some new things for bfp... the new header of the site for instance. But, I have almost done the changing of the name of all the maps, and some are going to change a bit (lighting for instance) Now Im going to reveal the new names of the maps so pay attention: +**Kami's Lookout** will change into **The Palace** +**Namek Waters** will change into **A Strange Planet** + +**Abandoned Southern City** and **Northern Earth** will keep their names of curse. + +About [Dash Design](https://web.archive.org/web/20020223210411/http://www.planetquake.com/dash) my personal site, I will redesign it soon (I have the graphic done but I'm still converting the contenent) + +So stay tuned for updates. + + + + +# Update - 08/15/2001 by Dash + +Bah, that's all I have to say about the event wich are happening. By the way, I will by busy untill the 1st of september, because of internet connection problems that won't be resolved till that date. ( So don't expect to see me a lot online ) +And today it's my birthday, the 15th of August. Happy Birthday Dash ! + + + + +# Dacity Finished - 07/19/2001 by Dash + +Here are 2 screenshots of my Abandoned Southern City. Final Version. I hope to have some Deepest Canyon screenshots ready soon. + +dacityshot0004 + +dacityshot0006 + +[[**Dash Design**](https://web.archive.org/web/20020223210411/http://www.planetquake.com/dash)] + + + + +# The Deepest Canyon and other stuff... - 07/08/2001 by Dash + +Just a quick update today: here's a draw of my latest map The Deepest Canyon This map will be quite huge and eyecandy and it will contains those func_breakable entities from Yrgol. Stay tuned ! + +dacanyon + +[[**Dash Design**](https://web.archive.org/web/20020223210411/http://www.planetquake.com/dash)] + +Also Bid For Power Zone has got an interview of me. Check it out [here](https://web.archive.org/web/20020223210411/http://www.bfpzone.f2s.com/dash.shtml). + + + + +# Namek Waters Final3 - 06/28/2001 by Dash + +Namek Waters is finished, all the small bugs are fixed. Check [these](https://web.archive.org/web/20020223210411/http://www.planetquake.com/dash/mystuff/namekwaters3/page_01.htm) screenshots, showing in-game Goku and some cool things. +Note: Namek Waters Final3 is the same of Final2, only optimized. + +[[**Dash Design**](https://web.archive.org/web/20020223210411/http://www.planetquake.com/dash)] + + + + +# Kami's Fixed and other things - 06/26/2001 by Dash + +Here's a shot of the latest build of my Kami's Lookout map. Look at the new palms. + +finalkami + +Here are in detail the things I've added and fixed in these days: + + +**::Namek Waters FINAL3 Version:** + +- Added a Geiser +- New Waterfall Texture, +- New Particle Effect for the waterfalls' splashes, +- New Lighting, not overbrighted, +- Gridsize changed from 256 256 256 to 512 512 512. + +**::Kami's Lookout FINAL5 Version:** + +- New texture for the tiles outside, less repetitive and more small +like in the show, +- New Lighting, not overbrighted, +- Added a red carpet inside. +- New Palms, +- Sounds when you hit the palms + +[[**Dash Design**](https://web.archive.org/web/20020223210411/http://www.planetquake.com/dash)] + + + + +# Namek Waters 2nd Edition - 06/24/2001 by Dash + +Today I've compiled 2 maps. One is Dover Base for Gundam Universe and one is... **Namek Waters** -Super Special Edition. Here are some screenshots... Enjoy +[Click Here For The PICS](https://web.archive.org/web/20020223210411/http://www.planetquake.com/dash/mystuff/namekwaters2/page_01.htm) + + +[[**Dash Design**](https://web.archive.org/web/20020223210411/http://www.planetquake.com/dash)] + + + + +# Water Effects - 06/23/2001 by Dash + +It's time for the first update of Namek Waters. Here are my new effects for the water (waterfalls, sprays, geisers ). These shots are WITHOUT lighting, so expect tomorrow another update, showing the new nice lighting too. + +watereffect1 + +watereffect2 + + +Wait till tomorrow for a new update... [[**Dash Design**](https://web.archive.org/web/20020223210411/http://www.planetquake.com/dash)] + + + + +# Work that I've done and work in progress... - 06/22/2001 by Dash + +Wow, my first update in my super cool dev-journal. Here it is what I've done for Bid for Power. +- Northern Earth, +- Namek Waters, +- Kami's Lookout, +- Abandoned Southern City, +- All the textures for the maps above, +- Some minor things. + +Now I'm going to fix all my works. Kami's Lookout is finished and fixed, Northern Earth too. I'm going to recompile Namek Waters with a more contrast lighting and maybe make some fixes in Abandoned City. +Here are some nice in-game screenshots in the city: + +[Click Here](https://web.archive.org/web/20020223210411/http://www.planetquake.com/dash/mystuff/city1scr/page_01.htm) + +I'll upate with screenshots of the updated Namek Waters when I have it ready (Soon). HEY ! Don't forget to check my personal web page: + +[[**Dash Design**](https://web.archive.org/web/20020223210411/http://www.planetquake.com/dash)] diff --git a/docs/pyrofragger_dev_journal.md b/docs/old_dev_journals/pyrofragger_dev_journal.md similarity index 96% rename from docs/pyrofragger_dev_journal.md rename to docs/old_dev_journals/pyrofragger_dev_journal.md index 90efbfa..6cee84a 100644 --- a/docs/pyrofragger_dev_journal.md +++ b/docs/old_dev_journals/pyrofragger_dev_journal.md @@ -1,727 +1,728 @@ -# Meteor - 12/16/2001 by PyroFragger - -I spent a couple hours today helping dash with his new map by creating this meteor map object that rests in the crater. - -coolmeteor - -It looks 10x as cool ingame. - - - - - - -# Hehe, i bet you thought i forgot:) - 12/13/2001 by PyroFragger - - -Trying to be a little more faithful to my promises, spent the last 4 hours working on this: - -TetRender - -Excuse the slow load times of the bfp server. This is Tetsedah, one of the bfp character drawing contest winners. I sat down and reconstructed the mesh using my basemodel instead of Rodney's. Here's a picture of the sketch that Jeff aka Dark Cloud drew: - -contest3 - -Also, that awkward shadow on the collar of the jacket is just a rendering artifact, no idea what causes this but it's not part of the model so don't worry. - - - - - -# Arggg - 12/12/2001 by PyroFragger - - -My computer crashed and i lost some tweaking work i had done to the model. Not a problem, but i have to postpone the shots till tomorrow. Hopefully this won't happen once i have more RAM. Home stretch:) I aim to have both of the models ingame with temporary solid color skins by the end of this weekend, hopefully the skins will be done really soon. -/me hands Ansel more gatorade - -Go Go Go! - - - - - - -# Go baby Go - 12/12/2001 by PyroFragger - - -I can have Ryuujin INGAME the day after i get the skin from Ansel. In the mean time, i work on the second model. It\'s close to done, i\'ll show it off later tonight around 10 oclock pm EST. The finish line is in sight, cheer ansel on! -/me hands Ansel a gatorade - - - - - - - -# Ryuujin Model Finished - 12/04/2001 by PyroFragger - - -Finished all the stuff i need to do for Ryuujin and last weekend sent the maps to Ansel for skinning. Here's a pic: - -RyuujinRender - -It was gonna be in the monday update but there was no monday update so i'm posting it here. - - - - - - - -# Information - 11/22/2001 by PyroFragger - - -This isn't an eyecandy update, just an informational one. As yrgol said, we can release BFP around a week after he has all the models completed. I have ryuujin completed and ready to go ingame as soon as i get a skin from ansel (who's on vacation at the moment) and will have my second character completed sometime next week after i get another concept from ansel. By that time Pyrate will most likely be ingame, so we should be seeing a release very shortly. In my next update i'll have snazzy posed renders of Ryuujin and Komasurao, not saying when though because there's too much that can happen that can delay a date. - - - - - - -# Ryuujin Coming Soon - 11/17/2001 by PyroFragger - - -Sometime this week i'll have pictures of Ryuujin for you guys. The model is done and uv mapped, but i have to redo much of the physiquing and ansel still has to skin it. You'll see skinned renders in here soon as well as ingame shots on the mainpage. - - - - - - -# BaseModel Version 2.0 - 11/13/2001 by PyroFragger - - -For those who care, i reuploaded the BaseModel zip with fixed weighting on the ass. It was collapsing during some of the animations, fixed that right up. Version 2.0, same link as below. -Also, the biped is HIDDEN, not missing. Just go to the fifth tab and unhide all. - - - - - - - -# The Basemodel - 11/12/2001 by PyroFragger - -Here it is. It's fully UV Mapped and Physiqued , with all the tags correctly parented to the biped. For those of you without MAX, there is also the 3ds version that is simply uv mapped, you'll have to attach it to a skeleton in whatever program you use and parent the tags aswell. The uv mapping is done in such a way that all you need is ONE texture for the entire upper and lower body. The head has its own mapping (the head mapping is very very messy but it gets the job done, fix it if you feel like it). I recommend 1 128x128 texture for the head and a 512x512 for the body. -*!*!* UPDATE *!*!*!*! I've ported it to MAX 4. If you've downloaded it already and use MAX4, redownload now! - -Download It Here (broken link): https://web.archive.org/web/20011218203246/http://www.bidforpower.com/Pyro/BaseModel.zip - -Enjoy. Remember, ALL that i ask is for a little credit, and please, if you're going to edit it, edit it enough that its a new character, don't just change his hair to give him a mohawk and release it. I want to see quality character models made from this. - -EDIT: Also, if (for whatever reason) you've seen any bfp skins at all, you'll notice that the uv mapping is set up in the same way as Rodney's. Again, this is NOT Rodney's basemodel, you can check the uv wireframes as well as the actual geometry yourself if you're skeptical. - - - - - - - -# Homestead blows - 11/10/2001 by PyroFragger - - -Seems every time i use homestead to show pictures to you guys i exceed my monthly bandwidth in only one day, lol. If anyone has another free hosting site that allows img tagging (i.e. NOT GEOCITIES!), tell me. - - - - - - -# BAMMMMMMMMMM! - 11/09/2001 by PyroFragger - - -Heh, if you live in another timezone, sue me, its still 11 oclock over here. I still have some work to do on the model but i figure i'll show you what i have today. This is about 6 and a half hours worth of work: - -(old lost image: https://web.archive.org/web/20011218203246im_/http://alieninstinct.homestead.com/files/Base1.jpg) - -(old lost image: https://web.archive.org/web/20011218203246im_/http://alieninstinct.homestead.com/files/Base2.jpg) - -(old lost image: https://web.archive.org/web/20011218203246im_/http://alieninstinct.homestead.com/files/Base3.jpg) - -(old lost image: https://web.archive.org/web/20011218203246im_/http://alieninstinct.homestead.com/files/Base4.jpg) - -This isn't really Komosurao, just threw his head on the basemodel i'll be releasing later on (most likely tomorrow, i spent more time on the model than i thought i would, but it payed off). The more experienced MAX users on the editing forum should find this useful as either a guide or as a base for their own models. Enjoy. - - - - - - - - -# On Track - 11/08/2001 by PyroFragger - - -All's in order for tomorrow, tomorrow i will be releasing the following to the budding designers in our community: -A MAX file containing my new basemodel i am using to create my bfp characters. The model will be uv mapped and physiqued to a standard bfp skeleton - -A copy of the bfp animation list and an explanation for all of them - -I'll also have pics of my actual bfp models. - - - - - - - -# Friday Update - 11/06/2001 by PyroFragger - -Thank God i'm through with all this work, i'm home free for a bit. Look for an update friday with new stuff. - - - - - - -# Info - 11/01/2001 by PyroFragger - -I don't really spend much time here anymore obviously, mostly because schoolwork this year really picked up. As it stands, i have two exams tomorrow, and two large reports due tuesday and wednesday, followed by some more exams. I'd say after next week, i'll be in the clear for a bit, but until then its tough to say how much i'll be able to do. I MAY be able to squeeze a couple hours of work into Saturday. What i've decided to do is make my own base model for all my characters. Until now, i'd been using Rodney's because it had been determined that the new bfp would just be different skins and head models on the same body. Well we've obviously strayed away from that to give the finished product more variety, so i'd like to make my own basemodel instead of simply just edit other people's work. The same head models will stay though, since those are mine. Once my basemodel is done i'll be able to more easily invent new characters off of it, and i will release the finished, uvmapped, and physiqued basemodel to developers in the community in the form of a bfpsdk to base their own custom bfp models on, provided that in the readme you mention the basemodel came from me. -Most of you have probably already read yrgol's dev journal. That's exactly what i'll be doing with all of my custom models in the future. As he said, there's no way it will be in the first release (which is why i'll only be releasing one of my models for the first release), but eventually all models will have visually different attacks and auras. - -Here's some information on the characters that will eventually be in a future release of bfp: - -Komasurao - Decided to make him evil. He has a very dark, cruel energy. He's a very deceptive and ingenious fighter, he can trick other fighters with illusions and his attacks pack a punch. - -Ryuujin - Stands for Dragon God in japanese. He is, obviously, a god who has spent the past 3 millenia training his mind and his body. He rarely speaks, and is rarely seen, but he always shows up when there is trouble. His ki is "different," kind of mysterious and very powerful. He wields two scerpent-dragon swords whose blades are made of the same ki as a kienzan. - -Tetsedha - A very determined and confident, but not overconfident, fighter. He lives for the fight and trains continously. His ki is very cold and his attacks are slower than those of Taipan. He takes fighting very seriously and is easily a match for anyone. - -Taipan - A very aggressive, firey fighter who is easily ticked off and a force to be reckoned with. He is the rival of Tetsedha, and also lives for the fight. The only thing that keeps him going is the continous struggle to become better than him. This competition has made him a very talented and dangerous fighter. His ki is very firey and his attacks are quick. - -Drexx - As a teenager, he was very violent and irritable, so he was taken in by a master to try and turn his anger and rage into controllable energy. After 18 years of training, he has become one of the most elite fighters in the universe. He possesses a very electric ki, and he is scared of no one. - -Obviously i'm not the most reliable person in the world right now, so i can't make a prediction on when these will all be done, but i can they'll be done soon. I'll try and squeeze in time here and there inbetween working sessions. - - - - - - - -# ........ - 10/20/2001 by PyroFragger - - -Well i'm getting over this motivational slump i've been in for the past month. A lot of things been going on where i just either couldn't find the time for BFP, or just didn't feel like working on it. For those that have seen office space, you know what im talking about. There was about a 3 week period where i just didn't care. Anyways, i figure its best to just knock this out and get it over with. - - - - - - -# Stay away from teh light!!!111111 - 10/12/2001 by PyroFragger - - -Lol............... -The long story is: I was drinking my tea and eating my crumpets when gooey purple aliens teleported into my room. I was like, WTF? and they said: "Come with us, we will teach you many alien bondage techniques." I forget how it ends. - -The short story is: I lost my homestead account and was too tired to reg a new account. - - - - - - - -# LOL - 10/11/2001 by PyroFragger - - -Heh, got so busy yesterday completely forgot about yesterday's update. Anyways, later tonight, unless i forget again (j/k, i wont). - - - - - - -# BOOJAH! - 10/08/2001 by PyroFragger - - -K, im going to show you EVERYTHING ive done so far on wednesday. Unfortunately the contest winners and another 2 models i had going will not go into the initial release of BFP, i'm only allowed to have 1 go in as of now, due to the attack system. However, they will become available in a release sometime after the first release, sorry about that, but its out of my hands. So it'll either by the one i've already pimped on the forums or another model i made that you haven't seen yet, but none of the contest entries will go into the first release, not fair to the other winners. Anyways, check back on wednesday, i'll have some cool stuff. - - - - - - -# Yadda Yadda Yadda - 09/22/2001 by PyroFragger - - -No pics yet, sorry about that but if you've been following this project long enough you're probably used to it:) Anyways, other things have been occupying my time lately and i just haven't had much time/energy to sit there and work on the bfp models. We do have a deadline though, although i cant say what that is, and we are working towards it so the light at the end of the tunnel is within reach. Whenever i have pics ill show em here, not gonna say when because i dont like breaking promises and it'll be cooler as a surprise. --P - - - - - - - -# New Characters, Sneak Peek - 09/14/2001 by PyroFragger - - -These aren't finished, but i'm a little too burned out right now to continue modeling tonight, so for now you can see the bodies of the two male winners of the drawing contest. Tomorrow, i'll have the female winner as well as all three head models on, and sometime this upcoming week i'll have snazzy new renders of these three and 2 others of my own creation:) K, nuff stalling: - -(old lost image: https://web.archive.org/web/20011218203246im_/http://alieninstinct.homestead.com/files/Taipan_body.jpg) - -(old lost image: https://web.archive.org/web/20011218203246im_/http://alieninstinct.homestead.com/files/Tetsdeha_body.jpg) - -Enjoy. - - - - - - - -# The Winners!!!! - 09/07/2001 by PyroFragger - -Finally, I have sifted through all the contest winners, and here they are. First of all, let me thank everyone who set time aside for this contest. As an artist myself i know sometimes when you enter contests and don't win, it can be depressing, but I saw a lot of impressive drawings in that thread, a lot of you guys have a lot of talent, so keep at it. Without further adieu, here are the entries that made the first cut: - -- DR - page 1 http://darkbostudio.hypermart.net/gallery/darkrapsmall.jpg - -- Kyuusei - page 3 http://www.bidforpower.com/forum/attachment.php?s=&postid;=319192 - -- Kaku - page 3 http://yosefselim.homestead.com/files/Kaku.jpg - -- MITSUKAI - page 4 http://www.bidforpower.com/forum/attachment.php?s=&postid;=319373 - -- Gotrun - Page 8 http://www.bidforpower.com/forum/attachment.php?s=&postid;=321186 - -- God's Entry - Page 8 http://www.bidforpower.com/forum/attachment.php?s=&postid;=321522 - -- Zone - Page 8 http://zone-archive.com/temporary/zonebfp.jpg - -- Adult Chibi - Page 9 http://www.bidforpower.com/forum/attachment.php?s=&postid;=322672 - -- Asura - Page 10 http://www.bidforpower.com/forum/attachment.php?s=&postid;=323126 - -- Cpider's Entry - Page 11 http://www.bidforpower.com/forum/attachment.php?s=&postid;=323770 - -- SSJ-5-Dan's Entry - Page 11 http://www.bidforpower.com/forum/attachment.php?s=&postid;=323994 - -- Yutaka - Page 11 http://danznation.netfirms.com/scans/yutaka1.jpg - -- SSJ-5-Dan's Entry - Page 12 http://www.bidforpower.com/forum/attachment.php?s=&postid;=324903 - -- Taipan - Page 13 http://www.bidforpower.com/forum/attachment.php?s=&postid;=325435 - -- MutilatedPuppet's Entry - Page 14 http://www.bidforpower.com/forum/attachment.php?s=&postid;=326670 -http://www.bidforpower.com/forum/attachment.php?s=&postid;=327440 - -- SSJ-5-Dan's Entry - Page 15 http://www.bidforpower.com/forum/attachment.php?s=&postid;=327420 - -- Sakana - Page 15 http://members.aol.com/rikoblaze/images/sakana.jpg - -- Aenea - Page 15 http://www.bidforpower.com/forum/attachment.php?s=&postid;=327592 - -- UF's Friend Entry 1 - Page 17 http://www.bidforpower.com/forum/attachment.php?s=&postid;=328948 - -- UF's Friend Entry 2 - Page 17 http://www.bidforpower.com/forum/attachment.php?s=&postid;=328972 - -- Genesite Entry 1 - Page 18 http://www.bidforpower.com/forum/attachment.php?s=&postid;=329352 - -- Chinese Madman - Page 19 http://www.bidforpower.com/forum/attachment.php?s=&postid;=329793 - -- Demian - Page 20 http://www.bidforpower.com/forum/attachment.php?s=&postid;=330408 - -- Kuku247's Entry - Page 20 http://www.bidforpower.com/forum/attachment.php?s=&postid;=330494 - -- Reinako - Page 21 http://home.cfl.rr.com/kashi/reinako.jpg - -- Darkido - Page 22 http://www.bidforpower.com/forum/attachment.php?s=&postid;=330874 - -- Nomas - Page 22 http://www.bidforpower.com/forum/attachment.php?s=&postid;=331009 - -- Lee - Page 23 http://members.aol.com/thecabreras/images/lee.jpg - -- Ree - Page 23 http://members.aol.com/thecabreras/images/ree.jpg - -- Cauli - Page 23 http://www.bidforpower.com/forum/attachment.php?s=&postid;=331908 - -- Wylder - Page 28 http://www.bidforpower.com/forum/attachment.php?s=&postid;=332975 - -Those were the drawings that I felt, after sifting through all 28 pages of the thread, would be the best concept art to base models on. I made this first cut basically by how well thought out the drawing was. I tried to avoid typical drawings, such as characters in ordinary gi's, with ordinary face and ordinary everything else. - -Now, from this list, I narrowed it down even further to a list of 5 males and 5 females. Those are........ - -- Taipan -- UF's Friend Entry 2 -- Nomas -- Wylder -- Adult Chibi - -- Lee -- Ree -- Reinako -- Aenea -- Sakana - -I made these lists by basically picking out the drawings that best conformed to the style of BFP. If this had been an art contest, MutilatedPuppet would have won by far, his pen style artwork is incredible. Had this been a CG contest, Zone would have won by far with his awesome solid-color shading technique. Unfortunately though, neither of these fit the style of BFP, and several others like it also fell through at this point. Great drawings none the less. - -Now, on to the grading. - -Originality - Does this drawing borrow bits and pieces from dbz characters, or other anime characters, or is it unique? - -- Taipan - 9 (Boots like trunks) -- UF's Friend Entry 2 - 10 -- Nomas - 10 -- Wylder - 10 -- Adult Chibi - 8 (Piccolo's entire cape look) - -- Lee - 10 -- Ree - 10 -- Reinako - 10 -- Aenea - 8 (saiyan pads and boots) -- Sakana - 10 - -Not too much of a problem here, all pretty much original drawings for the most part. - -Design - Is the general design of the character executed well or is it plain? - -- Taipan - 10 -- UF's Friend Entry 2 - 10 -- Nomas - 9 -- Wylder - 9 -- Adult Chibi - 8 - -- Lee - 9 -- Ree - 10 -- Reinako - 9 -- Aenea - 8 -- Sakana - 10 - -Style - Does the character fit into the BFP/DBZ universe, or generally speaking, does it look good performing ki attacks and flying. - -- Taipan - 10 -- UF's Friend Entry 2 - 10 -- Nomas - 10 -- Wylder - 10 -- Adult Chibi - 10 - -- Lee - 7 -- Ree - 7 -- Reinako - 7 -- Aenea - 9 -- Sakana - 10 - -Effort - Is it evident that the person spent a lot of time on this drawing, or does it appear rushed. - -- Taipan - 10 -- UF's Friend Entry 2 - 10 -- Nomas - 9 -- Wylder - 10 -- Adult Chibi - 9 - -- Lee - 9 -- Ree - 10 -- Reinako - 10 -- Aenea - 9 -- Sakana - 9 - -EXTRA CREDIT - Not necessary, but rather a point extra added to the score for each thing i notice that grabs my eye about the drawing. - -- Taipan - Excellent work on the CG, +1 -- UF's Friend Entry 2 - -- Nomas -- Wylder -- Adult Chibi - Nice CG, +1 - -- Lee - -- Ree - -- Reinako - +1 for excellent CG work -- Aenea - Beautiful style, color +2 -- Sakana - Nice job with extra attack drawings, plus CG +2 - -FINAL SCORE - -- Taipan - 40 -- UF's Friend Entry 2 - 40 -- Nomas - 38 -- Wylder - 39 -- Adult Chibi - 36 - -- Lee - 35 -- Ree - 37 -- Reinako - 37 -- Aenea - 36 -- Sakana - 41 - -Now, since there is a tie in the male section, what i've decided to do is model BOTH, since each are extremely strong character designs and it'd be a waste to choose one over the other. That makes our winners Taipan, Unnamed(UF's friends entry 2), and Sakana. I will contact the winners tomorrow (a little late to do it tonight, dont you think, heh) and we'll work together to make the character like they envisioned it. Again, thanks to all who entered, it was a great contest and just because you didn't get picked is no reason to feel bad about your art, the only drawback of contests is there can only be so many winners. G'nite. - -nameless - -hotanimebabesdotcom_02 - -(old lost image: https://web.archive.org/web/20011218203246im_/http://members.aol.com/rikoblaze/images/sakana.jpg) - - --Pyro - - - - - - - - -# Komasurao - 09/04/2001 by PyroFragger - -Click Here: https://web.archive.org/web/20020106152249/http://alieninstinct.homestead.com/files/Komasurao.jpg -Its my first serious attempt at skinning an organic model. Hopefully i did ok. It doesn't have a face yet, yes i know, and the skin still needs touchups but atleast you can see what the character itself will look like. Give me suggestions. Komasurao is a combination of "ko"(great) and "masurao"(warrior). Im thinking of putting a japanese symbol on the back of his cape. - -BTW, im gonna send it to rodney so he can render it out like the others and make a character sheet for it, this is just a temporary render. - - - - - - - -# New Character Delay - 09/03/2001 by PyroFragger - - -K, i do have them done, but they are still being worked on and I refuse to rush them. Tomorrow I'll have atleast one finished, SKINNED model rendered in the style as the others. Drawings look good btw, keep it up. Remember, you have till friday. - - - - - - -# BFP Character Drawing Contest - 09/02/2001 by PyroFragger - -I'm sure most of you have seen this by now but if you haven't, for all you artistically inclined people, there's a drawing contest to determine the look of one new bfp character. Details can be found HERE: https://web.archive.org/web/20011031125532/http://www.thejasper.com/DBZ/CosDBZ.html -Good luck. - -PS: HUMAN/SAIYAN!!! IF YOUR CHARACTER IS NOT HUMAN/SAIYAN IT WILL NOT BE CONSIDERED!! NUFF SAID. - - - - - - - -# Take me, I'm yours. - 06/06/2001 by PyroFragger - -It's been decided, the music video will be a long one involving all characters, transitions between each, and a short intro at the beginning. The reason for these videos is to show off all 5 attacks for each characters, as well as melee action and the latest effects, animated, to some of your favorite tunes, not only because we are bored and need something to stall with while we keep pressing for release:) Look for these in the next week (still editing them to fit the music). -As of now, remisser (the music composer, for those that don't know) is finishing some ingame music and it is coming along really well. He'll have his own journal with the new layout, but for right now, he's sharing mine. Expect more from him soon. - --P - - - - - - - -# I stubbed my toenail and now it smells like monkey... - 05/20/2001 by PyroFragger - -I've been talking with a composer over the past couple of days and he is gonna do some music for bfp. I may be using some music from him to do some of the music videos. You can expect all of the music videos with our new layout, which will be coming soon. Thanks for your patience. -P.S. If you get bored or tired of waiting, go to www.newgrounds.com:) - - - - - - - -# The little engine that can - 05/09/2001 by PyroFragger - -I know its been awhile since you've seen an update with new material, but thats only because we are spending more time trying to get this out to you guys. After a long standstill, we are finally getting moving again and BFP will be out before you know it. All we ask for is a little more patience. As for the music videos, I got 185 emails from fans requesting songs. Obviously i couldnt look at them all so Im going to weed through the topics and find the most popular songs for each character. If you want to get your voice in, I suggest replying in one of those topics in the next 30 mins. Later. - - - - - - -# Look honey he plays hockey - 05/03/2001 by PyroFragger - -I just wanted to say this cause no one else is. A lot of people are probably frustrated that we haven't released yet. Well we are definately more anxious to release than any of you are. I can't go into details, but you have to believe that we are doing everything we can to get this out as soon as we can. Bare with us for a little bit. There are things preventing the release that cannot be publicly announced, but we are ready when it gets cleared up. -Anyways, I may do some music videos or something promotional featuring all the characters, all 5 of their attacks, and a transformation. I was going to do this before, but never got around to it. Any song requests for certain people. Krillin automatically gets "Smack my Bitch Up" by prodigy, so thats not an opetion:) But I need song ideas for the rest. - - - - - - - -# ...Ick, no pooh title for this one... - 04/27/2001 by PyroFragger - -My internet went down yesterday. Im on a cable modem, so when they work on the servers, my internet is running at 14,4 baud modem speed at best. Its awful. Well right after i said they would be up and that i still had time on the forums, the cable stopped working. I ran the test on the modem and the cable light was out. Now homestead wont let me on because they are upgrading the server or something, so until then, they arent up. I did have them done yesterday, I swear:) Anyways, hopefully later today i can get into my homestead account. For your information they are pics of Majin Dabura and Chibi Pan. - - - - - -# ...And most of all whinnie the pooh.. - 04/27/2001 by PyroFragger - -'Bout time. -(old lost image: https://web.archive.org/web/20011218203246/http://pyrofragger.homestead.com/files/p21.jpg) - -p22 - -Enjoy. Still to come: Cell form 1 and cell jr. - -Funny quote of the day: "If a blonde throws a grenade at you, pull the pin and throw it back. If a blonde throws a pin at you, run like hell, she's got the grenade in her mouth!" - - - - - - - -# ...there's rabbit..and piglet....and there's owl..... - 04/23/2001 by PyroFragger - -This has nothing to do with BFP at all (except for the little blurb at the bottom) but I took the time to learn MAX modeling over the past couple of days. All high poly stuff, but the princliple of making the initial mesh is still low poly, so I may transcend from Raydream to MAX, I just hope it improves my quality. Here's the thing i made, anyways. My first mesh completely modeled in MAX:) - - -BFP: -Im gonna go against what I said last time just this once so that you can look forward to the part 2 model selection on Thursday. - -Funny Quote of the Day: "Never call Victoria's Secret and ask if something comes in childrens size" - - - - - - - -# ...and Tigger, and little Roo..... - 04/14/2001 by PyroFragger - -*BIG* update: -First, I just want to say that the gi versions of Krillin and Gohan will not be part of the main download on account of some problems I was having with MAX (totally corrupted the file). They will be released later on as an addon. Im incredibly tired of physiquing and animating so today I took a break from all of that. Here is the result: - -checkthisout - -Hope that tides you over for a while. I also want to say that I am no longer giving out public release dates because things tend to happen that are not in my favor, and I always end up with a lot of disgruntled people on my case. - -You can expect more models sometime soon, but like i said, im not going to say when:) - -As for why I'm working on models that fit in phase 3, it is because most of our phase 2 models are done and I was just pretty bored and tired of animating. Now I have them done, and don't have to worry about them when the time comes. - -Check out all the losers wearing dbz costumes (sorry if you're one of them): https://web.archive.org/web/20011031125532/http://www.thejasper.com/DBZ/CosDBZ.html - -Peace - --P - - - - - - - - -# ...A donkey named Eyore is his friend... - 04/12/2001 by PyroFragger - -Good things and bad things. -Good: I found an easy way around the deformation problems the two models have been having so I can finally get them working right. As of now, they deform like hell, but that will all be fixed. If all goes well, I will have in-game shots of them tomorrow. - -Bad: I have put my website on hiatus so those bitching about it will have to chill. Things come up, I'll finish it when I have nothing at all to work on. In the mean time, you can read other tutorials, but mine's gonna take longer than I thought because I have to give the same steps for two different modeling packages, so it takes twice as long. Check back Saturday for a status report, I *may* be finished the tut by then, but don't hold me to that (and you wonder why we don't give release dates when we don't know if we can keep them:) I have other stuff to show off too on Saturday. Peace. - --P - - - - - - - -# ...For most of his childhood days... - 04/05/2001 by PyroFragger - -Check for the skins in Ansel's journal in the next few minutes. I gotta roll out, so I dont have time to upload a shot. The torso is going to be seperated from the legs because i dont have tags on them yet. Tomorrow I can work the kinks out and maybe have an ingame screen for each of them. --P - - - - - - - -# ..There lies an enchanted neighborhood - 04/03/2001 by PyroFragger - -I will be finished with everything relating to phase 1 by tomorrow, so my site will be finished soon. I had hoped to finish it much sooner but such is life. Check for screenshots either tomorrow or thursday of them skinned. - - - - - - -# ...where Christopher Robin plays... - 03/27/2001 by PyroFragger - -Those expecting the tutorial will have to wait. BFP work comes first, tut comes second. If you didnt already know we are finishing things and I have to of course get my models done really soon. They are already attached to skeletons and are animated, in the process of getting skinned, so they will be done soon. I may have the tut up by this weekend. Ive got more work to show later, not for phase 1. --P - - - - - - - -# Deep in the hundred acre woods..... - 03/16/2001 by PyroFragger - -Applied BFP standard animations and attack animations to the new krillin and gohan, ready for skinning soon. Also, I am designing a website for myself that will include shots of m bfp work and my first ever modeling tutorial that is nearing completion. --P - - - - - - - -# New Krillin and Gohan - 02/24/2001 by PyroFragger - -Two reasons for this: -1) tired of everyone telling me to change their outfits to Gi's (Your post clenched it Mr. Krillin ;) - -2) wasnt happy with the level of quality of the models compared to my newer models - -So......here they are, unskinned: - -Krillin: 790 polygons -Gohan: 892 polygons - -new_krillin_gohan - -FEEDBACK - - - - - - - -# Random Updates - 02/09/2001 by PyroFragger - -Been working on Cell perfect a tad bit more to get it ready for Roney's skin job. Cell form 1 is next. I also may be making a RoQ movie file for the ending of BFTP. Lastly, I've been working on a 32 person tourney/capture the dragonballs map. Until phase 2 is released, itll just be a big tourney map. Screenshots of that as well soon. Thats about it, later. - - - - - - -# One more update from me today - 02/09/2001 by PyroFragger - -As I said, I've been working on cell. This is the result, a more stylized, sleek, and muscular Cell: - -(old lost image: https://web.archive.org/web/20011218203246im_/http://pyrofragger.homestead.com/files/Final_Cell.jpg) - -Feedback. - - - - - - - -# First Update - 12/17/2000 by PyroFragger - -My first dev journal on the new site. As of now, im tweaking Gohan and Krillin while the others finish up. Work continues on Cell as well: - -(old lost image: https://web.archive.org/web/20011218203246im_/http://pyrofragger.homestead.com/files/p_cell.jpg) - -Anyways, i dont have much to do right now for phase 1, so I will probably be starting some giant tourney maps due to the 1.27 patch. - -My first dev journal on the new site. As of now, im tweaking Gohan and Krillin while the others finish up. Work continues on Cell as well: - -(old lost image: https://web.archive.org/web/20011218203246im_/http://pyrofragger.homestead.com/files/p_cell.jpg) - +# Meteor - 12/16/2001 by PyroFragger + +I spent a couple hours today helping dash with his new map by creating this meteor map object that rests in the crater. + +coolmeteor + +It looks 10x as cool ingame. + + + + + + +# Hehe, i bet you thought i forgot:) - 12/13/2001 by PyroFragger + + +Trying to be a little more faithful to my promises, spent the last 4 hours working on this: + +TetRender + +Excuse the slow load times of the bfp server. This is Tetsedah, one of the bfp character drawing contest winners. I sat down and reconstructed the mesh using my basemodel instead of Rodney's. Here's a picture of the sketch that Jeff aka Dark Cloud drew: + +contest3 + +Also, that awkward shadow on the collar of the jacket is just a rendering artifact, no idea what causes this but it's not part of the model so don't worry. + + + + + +# Arggg - 12/12/2001 by PyroFragger + + +My computer crashed and i lost some tweaking work i had done to the model. Not a problem, but i have to postpone the shots till tomorrow. Hopefully this won't happen once i have more RAM. Home stretch:) I aim to have both of the models ingame with temporary solid color skins by the end of this weekend, hopefully the skins will be done really soon. +/me hands Ansel more gatorade + +Go Go Go! + + + + + + +# Go baby Go - 12/12/2001 by PyroFragger + + +I can have Ryuujin INGAME the day after i get the skin from Ansel. In the mean time, i work on the second model. It\'s close to done, i\'ll show it off later tonight around 10 oclock pm EST. The finish line is in sight, cheer ansel on! +/me hands Ansel a gatorade + + + + + + + +# Ryuujin Model Finished - 12/04/2001 by PyroFragger + + +Finished all the stuff i need to do for Ryuujin and last weekend sent the maps to Ansel for skinning. Here's a pic: + +RyuujinRender + +It was gonna be in the monday update but there was no monday update so i'm posting it here. + + + + + + + +# Information - 11/22/2001 by PyroFragger + + +This isn't an eyecandy update, just an informational one. As yrgol said, we can release BFP around a week after he has all the models completed. I have ryuujin completed and ready to go ingame as soon as i get a skin from ansel (who's on vacation at the moment) and will have my second character completed sometime next week after i get another concept from ansel. By that time Pyrate will most likely be ingame, so we should be seeing a release very shortly. In my next update i'll have snazzy posed renders of Ryuujin and Komasurao, not saying when though because there's too much that can happen that can delay a date. + + + + + + +# Ryuujin Coming Soon - 11/17/2001 by PyroFragger + + +Sometime this week i'll have pictures of Ryuujin for you guys. The model is done and uv mapped, but i have to redo much of the physiquing and ansel still has to skin it. You'll see skinned renders in here soon as well as ingame shots on the mainpage. + + + + + + +# BaseModel Version 2.0 - 11/13/2001 by PyroFragger + + +For those who care, i reuploaded the BaseModel zip with fixed weighting on the ass. It was collapsing during some of the animations, fixed that right up. Version 2.0, same link as below. +Also, the biped is HIDDEN, not missing. Just go to the fifth tab and unhide all. + + + + + + + +# The Basemodel - 11/12/2001 by PyroFragger + +Here it is. It's fully UV Mapped and Physiqued , with all the tags correctly parented to the biped. For those of you without MAX, there is also the 3ds version that is simply uv mapped, you'll have to attach it to a skeleton in whatever program you use and parent the tags aswell. The uv mapping is done in such a way that all you need is ONE texture for the entire upper and lower body. The head has its own mapping (the head mapping is very very messy but it gets the job done, fix it if you feel like it). I recommend 1 128x128 texture for the head and a 512x512 for the body. +*!*!* UPDATE *!*!*!*! I've ported it to MAX 4. If you've downloaded it already and use MAX4, redownload now! + +Download It Here (broken link): https://web.archive.org/web/20011218203246/http://www.bidforpower.com/Pyro/BaseModel.zip + +Enjoy. Remember, ALL that i ask is for a little credit, and please, if you're going to edit it, edit it enough that its a new character, don't just change his hair to give him a mohawk and release it. I want to see quality character models made from this. + +EDIT: Also, if (for whatever reason) you've seen any bfp skins at all, you'll notice that the uv mapping is set up in the same way as Rodney's. Again, this is NOT Rodney's basemodel, you can check the uv wireframes as well as the actual geometry yourself if you're skeptical. + + + + + + + +# Homestead blows - 11/10/2001 by PyroFragger + + +Seems every time i use homestead to show pictures to you guys i exceed my monthly bandwidth in only one day, lol. If anyone has another free hosting site that allows img tagging (i.e. NOT GEOCITIES!), tell me. + + + + + + +# BAMMMMMMMMMM! - 11/09/2001 by PyroFragger + + +Heh, if you live in another timezone, sue me, its still 11 oclock over here. I still have some work to do on the model but i figure i'll show you what i have today. This is about 6 and a half hours worth of work: + +(old lost image: https://web.archive.org/web/20011218203246im_/http://alieninstinct.homestead.com/files/Base1.jpg) + +(old lost image: https://web.archive.org/web/20011218203246im_/http://alieninstinct.homestead.com/files/Base2.jpg) + +(old lost image: https://web.archive.org/web/20011218203246im_/http://alieninstinct.homestead.com/files/Base3.jpg) + +(old lost image: https://web.archive.org/web/20011218203246im_/http://alieninstinct.homestead.com/files/Base4.jpg) + +This isn't really Komosurao, just threw his head on the basemodel i'll be releasing later on (most likely tomorrow, i spent more time on the model than i thought i would, but it payed off). The more experienced MAX users on the editing forum should find this useful as either a guide or as a base for their own models. Enjoy. + + + + + + + + +# On Track - 11/08/2001 by PyroFragger + + +All's in order for tomorrow, tomorrow i will be releasing the following to the budding designers in our community: +A MAX file containing my new basemodel i am using to create my bfp characters. The model will be uv mapped and physiqued to a standard bfp skeleton + +A copy of the bfp animation list and an explanation for all of them + +I'll also have pics of my actual bfp models. + + + + + + + +# Friday Update - 11/06/2001 by PyroFragger + +Thank God i'm through with all this work, i'm home free for a bit. Look for an update friday with new stuff. + + + + + + +# Info - 11/01/2001 by PyroFragger + +I don't really spend much time here anymore obviously, mostly because schoolwork this year really picked up. As it stands, i have two exams tomorrow, and two large reports due tuesday and wednesday, followed by some more exams. I'd say after next week, i'll be in the clear for a bit, but until then its tough to say how much i'll be able to do. I MAY be able to squeeze a couple hours of work into Saturday. What i've decided to do is make my own base model for all my characters. Until now, i'd been using Rodney's because it had been determined that the new bfp would just be different skins and head models on the same body. Well we've obviously strayed away from that to give the finished product more variety, so i'd like to make my own basemodel instead of simply just edit other people's work. The same head models will stay though, since those are mine. Once my basemodel is done i'll be able to more easily invent new characters off of it, and i will release the finished, uvmapped, and physiqued basemodel to developers in the community in the form of a bfpsdk to base their own custom bfp models on, provided that in the readme you mention the basemodel came from me. +Most of you have probably already read yrgol's dev journal. That's exactly what i'll be doing with all of my custom models in the future. As he said, there's no way it will be in the first release (which is why i'll only be releasing one of my models for the first release), but eventually all models will have visually different attacks and auras. + +Here's some information on the characters that will eventually be in a future release of bfp: + +Komasurao - Decided to make him evil. He has a very dark, cruel energy. He's a very deceptive and ingenious fighter, he can trick other fighters with illusions and his attacks pack a punch. + +Ryuujin - Stands for Dragon God in japanese. He is, obviously, a god who has spent the past 3 millenia training his mind and his body. He rarely speaks, and is rarely seen, but he always shows up when there is trouble. His ki is "different," kind of mysterious and very powerful. He wields two scerpent-dragon swords whose blades are made of the same ki as a kienzan. + +Tetsedha - A very determined and confident, but not overconfident, fighter. He lives for the fight and trains continously. His ki is very cold and his attacks are slower than those of Taipan. He takes fighting very seriously and is easily a match for anyone. + +Taipan - A very aggressive, firey fighter who is easily ticked off and a force to be reckoned with. He is the rival of Tetsedha, and also lives for the fight. The only thing that keeps him going is the continous struggle to become better than him. This competition has made him a very talented and dangerous fighter. His ki is very firey and his attacks are quick. + +Drexx - As a teenager, he was very violent and irritable, so he was taken in by a master to try and turn his anger and rage into controllable energy. After 18 years of training, he has become one of the most elite fighters in the universe. He possesses a very electric ki, and he is scared of no one. + +Obviously i'm not the most reliable person in the world right now, so i can't make a prediction on when these will all be done, but i can they'll be done soon. I'll try and squeeze in time here and there inbetween working sessions. + + + + + + + +# ........ - 10/20/2001 by PyroFragger + + +Well i'm getting over this motivational slump i've been in for the past month. A lot of things been going on where i just either couldn't find the time for BFP, or just didn't feel like working on it. For those that have seen office space, you know what im talking about. There was about a 3 week period where i just didn't care. Anyways, i figure its best to just knock this out and get it over with. + + + + + + +# Stay away from teh light!!!111111 - 10/12/2001 by PyroFragger + + +Lol............... +The long story is: I was drinking my tea and eating my crumpets when gooey purple aliens teleported into my room. I was like, WTF? and they said: "Come with us, we will teach you many alien bondage techniques." I forget how it ends. + +The short story is: I lost my homestead account and was too tired to reg a new account. + + + + + + + +# LOL - 10/11/2001 by PyroFragger + + +Heh, got so busy yesterday completely forgot about yesterday's update. Anyways, later tonight, unless i forget again (j/k, i wont). + + + + + + +# BOOJAH! - 10/08/2001 by PyroFragger + + +K, im going to show you EVERYTHING ive done so far on wednesday. Unfortunately the contest winners and another 2 models i had going will not go into the initial release of BFP, i'm only allowed to have 1 go in as of now, due to the attack system. However, they will become available in a release sometime after the first release, sorry about that, but its out of my hands. So it'll either by the one i've already pimped on the forums or another model i made that you haven't seen yet, but none of the contest entries will go into the first release, not fair to the other winners. Anyways, check back on wednesday, i'll have some cool stuff. + + + + + + +# Yadda Yadda Yadda - 09/22/2001 by PyroFragger + + +No pics yet, sorry about that but if you've been following this project long enough you're probably used to it:) Anyways, other things have been occupying my time lately and i just haven't had much time/energy to sit there and work on the bfp models. We do have a deadline though, although i cant say what that is, and we are working towards it so the light at the end of the tunnel is within reach. Whenever i have pics ill show em here, not gonna say when because i dont like breaking promises and it'll be cooler as a surprise. +-P + + + + + + + +# New Characters, Sneak Peek - 09/14/2001 by PyroFragger + + +These aren't finished, but i'm a little too burned out right now to continue modeling tonight, so for now you can see the bodies of the two male winners of the drawing contest. Tomorrow, i'll have the female winner as well as all three head models on, and sometime this upcoming week i'll have snazzy new renders of these three and 2 others of my own creation:) K, nuff stalling: + +(old lost image: https://web.archive.org/web/20011218203246im_/http://alieninstinct.homestead.com/files/Taipan_body.jpg) + +(old lost image: https://web.archive.org/web/20011218203246im_/http://alieninstinct.homestead.com/files/Tetsdeha_body.jpg) + +Enjoy. + + + + + + + +# The Winners!!!! - 09/07/2001 by PyroFragger + +Finally, I have sifted through all the contest winners, and here they are. First of all, let me thank everyone who set time aside for this contest. As an artist myself i know sometimes when you enter contests and don't win, it can be depressing, but I saw a lot of impressive drawings in that thread, a lot of you guys have a lot of talent, so keep at it. Without further adieu, here are the entries that made the first cut: + +- DR - page 1 http://darkbostudio.hypermart.net/gallery/darkrapsmall.jpg + +- Kyuusei - page 3 http://www.bidforpower.com/forum/attachment.php?s=&postid;=319192 + +- Kaku - page 3 http://yosefselim.homestead.com/files/Kaku.jpg + +- MITSUKAI - page 4 http://www.bidforpower.com/forum/attachment.php?s=&postid;=319373 + +- Gotrun - Page 8 http://www.bidforpower.com/forum/attachment.php?s=&postid;=321186 + +- God's Entry - Page 8 http://www.bidforpower.com/forum/attachment.php?s=&postid;=321522 + +- Zone - Page 8 http://zone-archive.com/temporary/zonebfp.jpg + +- Adult Chibi - Page 9 http://www.bidforpower.com/forum/attachment.php?s=&postid;=322672 + +- Asura - Page 10 http://www.bidforpower.com/forum/attachment.php?s=&postid;=323126 + +- Cpider's Entry - Page 11 http://www.bidforpower.com/forum/attachment.php?s=&postid;=323770 + +- SSJ-5-Dan's Entry - Page 11 http://www.bidforpower.com/forum/attachment.php?s=&postid;=323994 + +- Yutaka - Page 11 http://danznation.netfirms.com/scans/yutaka1.jpg + +- SSJ-5-Dan's Entry - Page 12 http://www.bidforpower.com/forum/attachment.php?s=&postid;=324903 + +- Taipan - Page 13 http://www.bidforpower.com/forum/attachment.php?s=&postid;=325435 + +- MutilatedPuppet's Entry - Page 14 http://www.bidforpower.com/forum/attachment.php?s=&postid;=326670 +http://www.bidforpower.com/forum/attachment.php?s=&postid;=327440 + +- SSJ-5-Dan's Entry - Page 15 http://www.bidforpower.com/forum/attachment.php?s=&postid;=327420 + +- Sakana - Page 15 http://members.aol.com/rikoblaze/images/sakana.jpg + +- Aenea - Page 15 http://www.bidforpower.com/forum/attachment.php?s=&postid;=327592 + +- UF's Friend Entry 1 - Page 17 http://www.bidforpower.com/forum/attachment.php?s=&postid;=328948 + +- UF's Friend Entry 2 - Page 17 http://www.bidforpower.com/forum/attachment.php?s=&postid;=328972 + +- Genesite Entry 1 - Page 18 http://www.bidforpower.com/forum/attachment.php?s=&postid;=329352 + +- Chinese Madman - Page 19 http://www.bidforpower.com/forum/attachment.php?s=&postid;=329793 + +- Demian - Page 20 http://www.bidforpower.com/forum/attachment.php?s=&postid;=330408 + +- Kuku247's Entry - Page 20 http://www.bidforpower.com/forum/attachment.php?s=&postid;=330494 + +- Reinako - Page 21 http://home.cfl.rr.com/kashi/reinako.jpg + +- Darkido - Page 22 http://www.bidforpower.com/forum/attachment.php?s=&postid;=330874 + +- Nomas - Page 22 http://www.bidforpower.com/forum/attachment.php?s=&postid;=331009 + +- Lee - Page 23 http://members.aol.com/thecabreras/images/lee.jpg + +- Ree - Page 23 http://members.aol.com/thecabreras/images/ree.jpg + +- Cauli - Page 23 http://www.bidforpower.com/forum/attachment.php?s=&postid;=331908 + +- Wylder - Page 28 http://www.bidforpower.com/forum/attachment.php?s=&postid;=332975 + +Those were the drawings that I felt, after sifting through all 28 pages of the thread, would be the best concept art to base models on. I made this first cut basically by how well thought out the drawing was. I tried to avoid typical drawings, such as characters in ordinary gi's, with ordinary face and ordinary everything else. + +Now, from this list, I narrowed it down even further to a list of 5 males and 5 females. Those are........ + +- Taipan +- UF's Friend Entry 2 +- Nomas +- Wylder +- Adult Chibi + +- Lee +- Ree +- Reinako +- Aenea +- Sakana + +I made these lists by basically picking out the drawings that best conformed to the style of BFP. If this had been an art contest, MutilatedPuppet would have won by far, his pen style artwork is incredible. Had this been a CG contest, Zone would have won by far with his awesome solid-color shading technique. Unfortunately though, neither of these fit the style of BFP, and several others like it also fell through at this point. Great drawings none the less. + +Now, on to the grading. + +Originality - Does this drawing borrow bits and pieces from dbz characters, or other anime characters, or is it unique? + +- Taipan - 9 (Boots like trunks) +- UF's Friend Entry 2 - 10 +- Nomas - 10 +- Wylder - 10 +- Adult Chibi - 8 (Piccolo's entire cape look) + +- Lee - 10 +- Ree - 10 +- Reinako - 10 +- Aenea - 8 (saiyan pads and boots) +- Sakana - 10 + +Not too much of a problem here, all pretty much original drawings for the most part. + +Design - Is the general design of the character executed well or is it plain? + +- Taipan - 10 +- UF's Friend Entry 2 - 10 +- Nomas - 9 +- Wylder - 9 +- Adult Chibi - 8 + +- Lee - 9 +- Ree - 10 +- Reinako - 9 +- Aenea - 8 +- Sakana - 10 + +Style - Does the character fit into the BFP/DBZ universe, or generally speaking, does it look good performing ki attacks and flying. + +- Taipan - 10 +- UF's Friend Entry 2 - 10 +- Nomas - 10 +- Wylder - 10 +- Adult Chibi - 10 + +- Lee - 7 +- Ree - 7 +- Reinako - 7 +- Aenea - 9 +- Sakana - 10 + +Effort - Is it evident that the person spent a lot of time on this drawing, or does it appear rushed. + +- Taipan - 10 +- UF's Friend Entry 2 - 10 +- Nomas - 9 +- Wylder - 10 +- Adult Chibi - 9 + +- Lee - 9 +- Ree - 10 +- Reinako - 10 +- Aenea - 9 +- Sakana - 9 + +EXTRA CREDIT - Not necessary, but rather a point extra added to the score for each thing i notice that grabs my eye about the drawing. + +- Taipan - Excellent work on the CG, +1 +- UF's Friend Entry 2 - +- Nomas +- Wylder +- Adult Chibi - Nice CG, +1 + +- Lee - +- Ree - +- Reinako - +1 for excellent CG work +- Aenea - Beautiful style, color +2 +- Sakana - Nice job with extra attack drawings, plus CG +2 + +FINAL SCORE + +- Taipan - 40 +- UF's Friend Entry 2 - 40 +- Nomas - 38 +- Wylder - 39 +- Adult Chibi - 36 + +- Lee - 35 +- Ree - 37 +- Reinako - 37 +- Aenea - 36 +- Sakana - 41 + +Now, since there is a tie in the male section, what i've decided to do is model BOTH, since each are extremely strong character designs and it'd be a waste to choose one over the other. That makes our winners Taipan, Unnamed(UF's friends entry 2), and Sakana. I will contact the winners tomorrow (a little late to do it tonight, dont you think, heh) and we'll work together to make the character like they envisioned it. Again, thanks to all who entered, it was a great contest and just because you didn't get picked is no reason to feel bad about your art, the only drawback of contests is there can only be so many winners. G'nite. + +nameless + +hotanimebabesdotcom_02 + +(old lost image: https://web.archive.org/web/20011218203246im_/http://members.aol.com/rikoblaze/images/sakana.jpg) + + +-Pyro + + + + + + + + +# Komasurao - 09/04/2001 by PyroFragger + +Komasurao + +Its my first serious attempt at skinning an organic model. Hopefully i did ok. It doesn't have a face yet, yes i know, and the skin still needs touchups but atleast you can see what the character itself will look like. Give me suggestions. Komasurao is a combination of "ko"(great) and "masurao"(warrior). Im thinking of putting a japanese symbol on the back of his cape. + +BTW, im gonna send it to rodney so he can render it out like the others and make a character sheet for it, this is just a temporary render. + + + + + + + +# New Character Delay - 09/03/2001 by PyroFragger + + +K, i do have them done, but they are still being worked on and I refuse to rush them. Tomorrow I'll have atleast one finished, SKINNED model rendered in the style as the others. Drawings look good btw, keep it up. Remember, you have till friday. + + + + + + +# BFP Character Drawing Contest - 09/02/2001 by PyroFragger + +I'm sure most of you have seen this by now but if you haven't, for all you artistically inclined people, there's a drawing contest to determine the look of one new bfp character. Details can be found HERE: https://web.archive.org/web/20011031125532/http://www.thejasper.com/DBZ/CosDBZ.html
+Good luck. + +PS: HUMAN/SAIYAN!!! IF YOUR CHARACTER IS NOT HUMAN/SAIYAN IT WILL NOT BE CONSIDERED!! NUFF SAID. + + + + + + + +# Take me, I'm yours. - 06/06/2001 by PyroFragger + +It's been decided, the music video will be a long one involving all characters, transitions between each, and a short intro at the beginning. The reason for these videos is to show off all 5 attacks for each characters, as well as melee action and the latest effects, animated, to some of your favorite tunes, not only because we are bored and need something to stall with while we keep pressing for release:) Look for these in the next week (still editing them to fit the music). +As of now, remisser (the music composer, for those that don't know) is finishing some ingame music and it is coming along really well. He'll have his own journal with the new layout, but for right now, he's sharing mine. Expect more from him soon. + +-P + + + + + + + +# I stubbed my toenail and now it smells like monkey... - 05/20/2001 by PyroFragger + +I've been talking with a composer over the past couple of days and he is gonna do some music for bfp. I may be using some music from him to do some of the music videos. You can expect all of the music videos with our new layout, which will be coming soon. Thanks for your patience.
+P.S. If you get bored or tired of waiting, go to www.newgrounds.com:) + + + + + + + +# The little engine that can - 05/09/2001 by PyroFragger + +I know its been awhile since you've seen an update with new material, but thats only because we are spending more time trying to get this out to you guys. After a long standstill, we are finally getting moving again and BFP will be out before you know it. All we ask for is a little more patience. As for the music videos, I got 185 emails from fans requesting songs. Obviously i couldnt look at them all so Im going to weed through the topics and find the most popular songs for each character. If you want to get your voice in, I suggest replying in one of those topics in the next 30 mins. Later. + + + + + + +# Look honey he plays hockey - 05/03/2001 by PyroFragger + +I just wanted to say this cause no one else is. A lot of people are probably frustrated that we haven't released yet. Well we are definately more anxious to release than any of you are. I can't go into details, but you have to believe that we are doing everything we can to get this out as soon as we can. Bare with us for a little bit. There are things preventing the release that cannot be publicly announced, but we are ready when it gets cleared up.
+Anyways, I may do some music videos or something promotional featuring all the characters, all 5 of their attacks, and a transformation. I was going to do this before, but never got around to it. Any song requests for certain people. Krillin automatically gets "Smack my Bitch Up" by prodigy, so thats not an opetion:) But I need song ideas for the rest. + + + + + + + +# ...Ick, no pooh title for this one... - 04/27/2001 by PyroFragger + +My internet went down yesterday. Im on a cable modem, so when they work on the servers, my internet is running at 14,4 baud modem speed at best. Its awful. Well right after i said they would be up and that i still had time on the forums, the cable stopped working. I ran the test on the modem and the cable light was out. Now homestead wont let me on because they are upgrading the server or something, so until then, they arent up. I did have them done yesterday, I swear:) Anyways, hopefully later today i can get into my homestead account. For your information they are pics of Majin Dabura and Chibi Pan. + + + + + +# ...And most of all whinnie the pooh.. - 04/27/2001 by PyroFragger + +'Bout time.
+(old lost image: https://web.archive.org/web/20011218203246/http://pyrofragger.homestead.com/files/p21.jpg) + +p22 + +Enjoy. Still to come: Cell form 1 and cell jr. + +Funny quote of the day: "If a blonde throws a grenade at you, pull the pin and throw it back. If a blonde throws a pin at you, run like hell, she's got the grenade in her mouth!" + + + + + + + +# ...there's rabbit..and piglet....and there's owl..... - 04/23/2001 by PyroFragger + +This has nothing to do with BFP at all (except for the little blurb at the bottom) but I took the time to learn MAX modeling over the past couple of days. All high poly stuff, but the princliple of making the initial mesh is still low poly, so I may transcend from Raydream to MAX, I just hope it improves my quality. Here's the thing i made, anyways. My first mesh completely modeled in MAX:) + + +BFP: +Im gonna go against what I said last time just this once so that you can look forward to the part 2 model selection on Thursday. + +Funny Quote of the Day: "Never call Victoria's Secret and ask if something comes in childrens size" + + + + + + + +# ...and Tigger, and little Roo..... - 04/14/2001 by PyroFragger + +*BIG* update: +First, I just want to say that the gi versions of Krillin and Gohan will not be part of the main download on account of some problems I was having with MAX (totally corrupted the file). They will be released later on as an addon. Im incredibly tired of physiquing and animating so today I took a break from all of that. Here is the result: + +checkthisout + +Hope that tides you over for a while. I also want to say that I am no longer giving out public release dates because things tend to happen that are not in my favor, and I always end up with a lot of disgruntled people on my case. + +You can expect more models sometime soon, but like i said, im not going to say when:) + +As for why I'm working on models that fit in phase 3, it is because most of our phase 2 models are done and I was just pretty bored and tired of animating. Now I have them done, and don't have to worry about them when the time comes. + +Check out all the losers wearing dbz costumes (sorry if you're one of them): https://web.archive.org/web/20011031125532/http://www.thejasper.com/DBZ/CosDBZ.html + +Peace + +-P + + + + + + + + +# ...A donkey named Eyore is his friend... - 04/12/2001 by PyroFragger + +Good things and bad things. +Good: I found an easy way around the deformation problems the two models have been having so I can finally get them working right. As of now, they deform like hell, but that will all be fixed. If all goes well, I will have in-game shots of them tomorrow. + +Bad: I have put my website on hiatus so those bitching about it will have to chill. Things come up, I'll finish it when I have nothing at all to work on. In the mean time, you can read other tutorials, but mine's gonna take longer than I thought because I have to give the same steps for two different modeling packages, so it takes twice as long. Check back Saturday for a status report, I *may* be finished the tut by then, but don't hold me to that (and you wonder why we don't give release dates when we don't know if we can keep them:) I have other stuff to show off too on Saturday. Peace. + +-P + + + + + + + +# ...For most of his childhood days... - 04/05/2001 by PyroFragger + +Check for the skins in Ansel's journal in the next few minutes. I gotta roll out, so I dont have time to upload a shot. The torso is going to be seperated from the legs because i dont have tags on them yet. Tomorrow I can work the kinks out and maybe have an ingame screen for each of them. +-P + + + + + + + +# ..There lies an enchanted neighborhood - 04/03/2001 by PyroFragger + +I will be finished with everything relating to phase 1 by tomorrow, so my site will be finished soon. I had hoped to finish it much sooner but such is life. Check for screenshots either tomorrow or thursday of them skinned. + + + + + + +# ...where Christopher Robin plays... - 03/27/2001 by PyroFragger + +Those expecting the tutorial will have to wait. BFP work comes first, tut comes second. If you didnt already know we are finishing things and I have to of course get my models done really soon. They are already attached to skeletons and are animated, in the process of getting skinned, so they will be done soon. I may have the tut up by this weekend. Ive got more work to show later, not for phase 1. +-P + + + + + + + +# Deep in the hundred acre woods..... - 03/16/2001 by PyroFragger + +Applied BFP standard animations and attack animations to the new krillin and gohan, ready for skinning soon. Also, I am designing a website for myself that will include shots of m bfp work and my first ever modeling tutorial that is nearing completion. +-P + + + + + + + +# New Krillin and Gohan - 02/24/2001 by PyroFragger + +Two reasons for this: +1) tired of everyone telling me to change their outfits to Gi's (Your post clenched it Mr. Krillin ;) + +2) wasnt happy with the level of quality of the models compared to my newer models + +So......here they are, unskinned: + +Krillin: 790 polygons +Gohan: 892 polygons + +new_krillin_gohan + +FEEDBACK + + + + + + + +# Random Updates - 02/09/2001 by PyroFragger + +Been working on Cell perfect a tad bit more to get it ready for Roney's skin job. Cell form 1 is next. I also may be making a RoQ movie file for the ending of BFTP. Lastly, I've been working on a 32 person tourney/capture the dragonballs map. Until phase 2 is released, itll just be a big tourney map. Screenshots of that as well soon. Thats about it, later. + + + + + + +# One more update from me today - 02/09/2001 by PyroFragger + +As I said, I've been working on cell. This is the result, a more stylized, sleek, and muscular Cell: + +(old lost image: https://web.archive.org/web/20011218203246im_/http://pyrofragger.homestead.com/files/Final_Cell.jpg) + +Feedback. + + + + + + + +# First Update - 12/17/2000 by PyroFragger + +My first dev journal on the new site. As of now, im tweaking Gohan and Krillin while the others finish up. Work continues on Cell as well: + +(old lost image: https://web.archive.org/web/20011218203246im_/http://pyrofragger.homestead.com/files/p_cell.jpg) + +Anyways, i dont have much to do right now for phase 1, so I will probably be starting some giant tourney maps due to the 1.27 patch. + +My first dev journal on the new site. As of now, im tweaking Gohan and Krillin while the others finish up. Work continues on Cell as well: + +(old lost image: https://web.archive.org/web/20011218203246im_/http://pyrofragger.homestead.com/files/p_cell.jpg) + Anyways, i dont have much to do right now for phase 1, so I will probably be starting some giant tourney maps due to the 1.27 patch. \ No newline at end of file diff --git a/docs/old_dev_journals/remisser_dev_journal.md b/docs/old_dev_journals/remisser_dev_journal.md new file mode 100644 index 0000000..cc975c1 --- /dev/null +++ b/docs/old_dev_journals/remisser_dev_journal.md @@ -0,0 +1,502 @@ +# patience - 01/18/2002 by Remisser + +a lot of people are sending emails and other such things frantically asking about the release. Please have patience. It's coming. Chris never said the time was precise. Patience is a virtue. Don't go downloading the supposed leaks. There's a bug with the leaks, and the latest version was uploaded _last night_, by the amazing YRGOL. I recommend you start sending him complimentary notes of thanks for dealing with the tedious coding. :)
+pyrofragger on the other hand is a beligerent drunkard. :) + + + + +# to tide you over - 01/18/2002 by Remisser + +To keep you busy while you wait the next few hours out:
+[www.fark.com](https://web.archive.org/web/20020210152114/http://www.fark.com/) (fun news)
+[www.seanbaby.com](https://web.archive.org/web/20020123041221/http://seanbaby.com/) (funny stuff)
+[www.incisionstudios.com](https://web.archive.org/web/20011130114126/http://www.incisionstudios.com/) (good music - some from the next release of BFP [after this one coming out]) + + + + +# BFP CHAT - 01/18/2002 by Remisser + +So the game will be released today around 9PM EST (I say EST because so many people keep asking me because they can't convert pacific time) +Exciting? Yes. + +So you may want to chat about it. Go to www.mirc.com and download a chat client called MIRC. Then come on into irc.ENTERTHEGAME.com in the channel #FunTimes * and chat with us. (also, #HHMod is a fun channel. :)) +
+
+
+*not actual channel. + + + + +# d b z - 01/15/2002 by Remisser + +

+DBZ SUCKS!!!
+I'm glad this mod isn't tied to DBZ anymore. It'll be interesting when the side packs come out with the DBZ characters in it, but that cartoon is so tired now.
+
+
+---- +

+My music will unfortunately not be in the release this month due to miscommunication and time restraints. But hopefully with the next RC. It'll give you another reason to come back for more. :) + + + + +# merry - 12/25/2001 by Remisser + +Merry Christmas. I've been away for a bit from everything because of major problems, but I hope to fulfill all the commitments I had. This Sunday I will make all the music I have done for Bid For Power downloadable. Along with that I will have a journal entry that goes in depths explaining how I create music, with pointers, using example from the music that I've made for Bid For Power. People can always learn how to model, code, map and everything else quite easily, but it's always hard to get pointers on music without getting the runaround. I can't promise the music pointers by sunday, but I'll try.
+I also want to thank everyone for their dedication to the game. Do you want to know HOW dedicated some of you people are? [Click here to read a fanfic for Bid For Power/Ranma/Tenchi/Slayers/Project A-Ko/Sailor Moon/Dragon Ball Z](https://web.archive.org/web/20020811050438/http://www.cse.unl.edu/~jwessels/fanfics.html) - It's pretty cool, and is still under development. I found it while searching for sites about BFP. It uses the new characters (like Gothax and such) + +Also for your enjoyment:
+[A seasons greeting from Pancake Bunny.](https://web.archive.org/web/20011203120347/http://www.selfabort.com/) + +[My crappy life, as it unfolds.](https://web.archive.org/web/20011116022908/http://www.livejournal.com/users/missing/) + + + + +# update shmupdate - 11/29/2001 by Remisser + +So far I've gotten some good leads from coders (I still have more to email for a followup) and all is going well.
+Sometime this week (when I find that darn password) I will try to fix anything wrong with the PHP of the site. If any of you notice anything wrong with the php, email me so I can try to fix it. + +Lastly, I've been getting forwarded emails. One such email (which was sent to me by a few different people) was about how AOL and Microsoft were teaming up to beta test some new email software and if you forwarded it to one person you got $202 dollars, and more for each other person you sent it to. + +Now, I hate having to be the partypooper, but, the email is fake. First of all there is no way in the entire universe that they would be able to track all the mail sent around the internet from the numerous millions of people in the populace. Secondly, if they were even to ADMIT to being able to doing that, they would get sued for invasion of privacy. Thirdly, if they were to pay off every shmuck and loser who actually BELIEVED that it was possible, it would amount in the high TRILLIONS of dollars. So, yeah, right... AOL/Microsoft have this high spy secret software that can track any mail I send through an Apple IIe computer. Did I also mention they put a microchip in my brain and visit me at night through my aluminum foil thinking cap? It's true. I have to listen to Barney and Friends Super Duper CD just to stop their transmissions from coming in at night.
+Just because the devil forged an unholy alliance between Microsoft and AOL doesn't mean they have this ludicrous tracking power. You ever read those emails about how 'if you forward this, 3 cents will be donated to the cancer society of america' type emails? Guess what. They can't track it. Ever get 'sign this petition and forward it' emails? Guess what, those petitions, even IF they could track it and ORGANIZE it, it would be rejected because a computer could, just the same, scan a phonebook and come up with a random list of names for the petition. + +Chainmails are dumb. Don't send me any. I will not scroll to the bottom and make a wish. It won't come true unless I work for it. I will not be cursed if I don't forward an email. I just broke 15 mirrors, had 20 black cats cross my path, and I walk under ladders on a regular basis. If I'm going to die this gruesome death, I'll do it on my own terms. Think you've got this really funny email? Keep it to yourself, if I want humor I'll visit seanbaby.com, or fatchicksinpartyhats.com - I don't need your 'a priest and a rabbi' jokes that make your Moms and Dads laugh. + +I hate forwarded emails. + +-Trake Adams ( www.incisionstudios.com - I've got some BFP music on the radio station there :)) + +PS - Forward this journal entry. ;) + + + + +# code - 11/27/2001 by Remisser + +Anyone who can code well for Quake 3, send along a message to me. I need as much input as I can about quake 3 music related things. I'm trying to make a .pk file and... well, without the specifics, just send me an email if you're a good quake 3 coder.
+remisser@selfabort.com
+remisser@postmark.net + + + + +# darn dirty journal - 11/07/2001 by Remisser + +

+If you are good with FLASH sites and/or animations, read the end of this.
+---- +

+ +I had this wonderfully long journal entry I made. Opera made it disappear. Oh well. The basics of what I said was 'Problem solved with devenum.dll - I actually had to boot up in safe mode, then shell to DOS and delete the devenum.dll and replace it with the devenum.dll file I downloaded weeks ago. Thanks for all your responses, but none of you came up with that suggestion. :) You see, I had to shell to DOS because if I didn't, the /windows/system/ registry automatically replaces the devenum.dll file with an exact replica of the file, no matter if you DELETE IT, RENAME IT, OR EVEN TRY TO EDIT THE RAW CODE. Booting up in safe mode allows it so that 99% of your DLL's never get used, so therefore the registry has no reason to automatically replace them. Thank you for being patient with me, to-nite I'll be installing Windows 2000 Professional to get rid of some of my woes. I also plan on finishing up the projects I've been working on (BFP, GundamUniverse, Heroes in a Halfshell, et cetera.) Music for Bid For Power is done, on my part, and I'm pretty sure GPoodle is almost done with his music. As I stated with a problem early, the music will probably just be an addon pack unless I can find some way of making the music files smaller. I got a lot of people suggested converting to .mp3 format. Now, really... I'm a musician. If I knew a way of making a .pk file for quake 3 arena that allowed the playing of MP3's, I would use it, any person knows mp3 files are much smaller than wav files. And .ogg files as well. But I believe you can only .pk wave files. Correct me if I'm wrong. Well that's about it. Thanks for your patience and keep up the good work in helping us out.'
+^^^ That's basically what I said... + +Now as I began to mention at the top, I need a Flash person. I run www.selfabort.com - a site that currently will only be in regards to my music. I could use someone's help in designing a flash website (something dark and ominous) and in return I can either make some small bits of music for any projects you may have, or the sound effects, or I can give you a pag redirect. like www.selfabort.com/yournamehere/ -- Or you could just help me out of the kindness of your heart. If you have a friend that does flash, get HIM/HER to email me. :) They may not even be interested and I'd hate to go asking out of the blue. If you can include some urls or samples to your work,it'd be appreciated. I'm desperate. :) + +Thanks again,
+Remisser + + + + +# HELLLLLLLLLP!!! - 10/30/2001 by Remisser + +I need help!
+No matter what audio program I try to use I get the following error everytime: + +[Program name I'm using] has caused an error in
+DEVENUM.DLL
+[Program name] will now close. + +Email me at remisser@postmark.net + + + + +# [music] - 10/26/2001 by Remisser + +I compiled the music and it seems it takes up a lot of space... if anyone has any clue as to how to make these files smaller, tell me... .wav is large... + + + + +# [video] - 10/26/2001 by Remisser + +I'm going to see of a possibility of whether or not we can get a music video made with the new characters.
+Seeing as how things are moving along at a rapid pace though, the game would probably be done by the time we'd finish a video. + + + + +# [last entry] - 09/05/2001 by Remisser + +To clarify on my last joural entry: +1. I like GPoodles new song. +2. The sound quality of the mp3 download below this journal entry is a bit compromised.... + +Now for some news. For those concerned with the size of our ingame music will add to the actual BFP download size, we'll probably release the music as a seperate download. I'd rather it be combined, but for the sake of those with 2400 baud modems, I think it's for the better. + +remisser@postmark.net + + + + +# music / voices - 09/04/2001 by Remisser + +I gave Gpoodle a new music program, I hope he's using it. Apparently, he wants his music in the game too... while this is ultimately up to Yrgol and Chris, I might as well try and help him out and get better, right? Hey GP, if you're reading this, I have some plugins for fruityloops for yah! :)
+Moving along, I should have some music uploaded either tonight or tomorrow... the new characters inspired me. + +If you couldn't read Number 17's new journal, it basically said all his sound fx will be used, except for the DBZ voices (like the angry Gohan scream)... I'm going to see about actually implimenting some anime type screams and yells for the game, with my vast array of microphones and vocal effects modules. + +That's about it. Go to www.hhmod.com for my ninja turtles TC, if you're bored. :) We still need mappaers and such. + +REMISSER@SELFABORT.COM + + + + +# DOWNLOAD! W00t! - 09/04/2001 by Remisser + +remisser@postmark.net
+A download should be available (courtesy of Bandit- from [blink.net](https://web.archive.org/web/20020119214720/http://www.blinkk.net/) who graciously let me upload it) of a song in progress... the mp3 encoding is screwed up, so you'll hear little glorps and scratches... email me at remisser@postmark.net - maybe you can tell me some japanese phrases i should use to make a demo of new character voices for the team to hear. :) ANYHOW, [CLICK HERE TO DOWNLOAD](https://web.archive.org/web/20020210152114/http://www.blinkk.net/~remisser/sweetbfp.mp3) - I incorporated some of the stuff you people suggested (faster beats, more of a punch) - I collaborated on this song with a friend and I've added much more that will be uploaded later. + +I still need MAPPERS for my mod. :) [www.hhmod.com](https://web.archive.org/web/20020210152114/http://www.hhmod.com/) :) + + + + +# [c0ntr0v3rZy] - 08/17/2001 by Remisser + +My modem didn't fare well last night. So, I'm updating from work. No music will be available until I get my shiny new cable modem. This should be soon. +Moving on,
+Some people [who we will call 'minorities'] don't like my updates. They think they're useless. Other people [we'll call 'the majority'] like the fact that someone posts often. I do only what the MAJORITY cares for, not the MINORITIES. If you dislike my updates, ignore my journal. It's going to be the same drivel, basically.
+If you don't like the humor I display, or if you think I'm on some high-horse, then don't read this journal. Only strange people seem to get my humor, and strange is good. I'm not trying to appeal to a broad audience. I'm just trying to give what little info I have and give a smile. + +As for my public beratement of 'MikeGohan', it's dropped the negative mail I get drastically. It's my perrogative. Someone sent a link to a timeline and said I follow it, I don't. I've always been like this. And I am a rockstar, so excuse my rockstar attitude. I like DBZ, I hardly watch it (time constraints... and lots of La Blue Girl tapes I haven't seen yet) - but I know that this mod will be just as good without the trademarked characters. + +People who come up with timelines stating how standard other people are and how they follow the timeline they made are following another timeline: + +Join an interesting and popular community >> Make a website to add to that community >> Draw visitors by making fun of that very community you secretly admire >> Always be opposed to how things are run for the sake of having a differing opinion and getting the visitors who are sick of the site you bash + +I don't follow timelines. + +Sorry if this update seems ambiguous. + +I'll try to get the music up ASAP. + + + + +# Song - 08/16/2001 by Remisser + +Song download available tonight...
+crappy modem pending. :) + +
+
+
+ +Try to cut down on the IMing of me. :) #HHMod on irc.enterthegame.com is a better alternative than email and AIM, since I respond there. + + + + +# w00t w00t - 08/15/2001 by Remisser + +Well, I have a deadline of 'by this Friday' to have the music for BFP done.
+So... + +Don't know what that means... + +The music video I promised before could not be completed for the obvious trademark reasons... BUT... look forward to one soon with the new models (hopefully.) + +Here's a conversation I had online with that HTML hax0r:
+[http://www.selfabort.com/idiocy.htm](https://web.archive.org/web/20011204130005/http://www.selfabort.com/idiocy.htm) + +And, lastly, thank you for the unwarrented 'mod app' submissions... I do need help for the new one, but wasn't expecting people to pick that up from my last post. :) + + + + +# Mods / Posting / Updates - oh my - 08/14/2001 by Remisser + +Since people seem to like it when an update happens, I offer you this update:
+More common questions I get asked -
+Question: The links to your songs don't work. Why?
+Answer: Well, bfpta's site has moved, among other things... [http://www.bfpta.net/remsongs/](https://web.archive.org/web/20020416021046/http://www.bfpta.net/remsongs/) Go there, click on a song. + +Question: What other things are you working on?
+Answer: Numerous mods... Mainly sound effects for most of the side mods... Most of the mods are so secretive, I can't even tell you what they're about! The mod I'm running is taking up a lot of my time as I'm still looking for coders, mappers, skinners, et cetera... making it impossible for me to work on music at the moment. I am almost finished with the BFP music anyhow... Look for more downloads when my cable modem comes. + +Question: How long does it take you to make a song?
+Answer: It varies. Shortest time was one hour. Longest was 2 months.
+Question: I listened to your songs... they sound staticy and horrible in winamp... why's that?
+Answer: Winamp isn't that great... depending on the version you have... try using a different MP3 media... and don't listen to it on small $5 speakers made of tinfoil. The sound quality will be compromised... plug your headphones into your line in jack. That may help. + +Question: Who invented the cotton gin?
+Answer: African American slave Eli Whitney invented the cotton gin. + +There's five questions answered. Got a comment on any of them? Email me. remisser@postmark.net -- Can't promise I'll reply, but I will at least read it. + +remi ([also remisser@selfabort.com](mailto:remisser@selfabort.com)) + +=====EDIT!
+It appears many people were quick to point out the fallacy of my calling Eli Whitney an African American slave. While this was a joke meant to disillusion some people, I would not have edited this entry had user "Pat" not sent me this alluring photo of Mr. Whitney: +whitney2 + +Mr. Whitney is a SWM from the south who enjoys long leisurely walks along the beach, candle lit dinners, and water sports. Mr. Whitney is dynamite with the ladies and wants you to know how sexy you really are in your corset.
+Mr. Whitney is also in a band called "The Filibusters" and their new album "Rabblerousing" should be released posthaste... once vinyl records are invented. Mr. Whitney is quoted as saying his favorite pickup line is "Why dost thou not place your gluteous maximus upon my lap, so that we shall talk about the first thing that pops up." + + + + +# [The answers] - 08/12/2001 by Remisser + +Questions I've been getting recently:
+Question: When will Bid For Power be released?
+Answer: This is a direct quote from Chris off the main page "Bid For Power is close to being released (about a months time)" + +Question: What will the characters look like?
+Answer: I don't know. I do the music. They're going to release pictures as soon as possible... that's the whole FUN of going to a site... seeing new pictures... Being there when it first comes out... Will they look like DBZ characters? Well, a lot of anime tends to look similar... big eyes, small mouth, funky hair that could impale a normal human being. So, stay tuned. + +Question: What about the moves and the maps?
+Answer: Beats me. Though I think there should be a character that throws squirrels. I don't think Chris would like that... maybe we could change all the characters to Tyler Durden, Narrator, Bob, and Marla from Fight Club. Just turn it into boxing... hey, remember that mod for Doom II where it was called boxing, and they wanted it to be only boxing, but you got to start with the basic gun? Well, maybe that was just me and my friends... + +Anyways... + +I don't know about the moves and maps. I don't ask because it's more fun to wait... but I haven't gotten any requests for new sounds for new moves... so... hmmmm... + +Question: What do you use to make music?
+Answer: Lots of basic instruments (guitar, bass), and lots of computer programs. FruityLoops 3.0, Cool Edit Pro and 2000. Cubase when I'm frisky.
+Some free programs you might want to try: www.brambos.com Tuareg, excellent program for drumloops and random cuts. thrax.box.sk Thrax... an underground community, lists a lot of pay and free programs. Go there. + +Question: I love you remisser! Can I have your children?
+Answer: No. Chances are you're a guy. And you're only 14. That's sick. Stop following me. + + + + +# cornflower blue ties - 08/10/2001 by Remisser + +Just so you know, this is an email I got, and my public response:
+QUOTE:
+..what..you think ill fucking waste my time downloading bfp w/o the dbz charecters??fuck no..if i hear theres a person making a mod for the bfp mod..then maybe..im a big fan of dbz..dont tell us ..hype us on about something you said you were unsure of..AND 1 MORE THING...TAKE DOWN ANY AND ALL DBZ CHARECTER PICS ON YOUR SITE..ITS FALSE ADVERTISING AND WE CAN TAKE MONEY FROM YOU FOR THAT..hey look..a bfp site..ohh cool ..its a mod for q3..oh waite..no..its a fucked up..just maps and sound dbz game..ok..why the pics of the charecters..if there are non?..hmm.. "calls lawyer"..dont fuck with a dbz maniac..just get us the charecters..or have some one secertetly make them..then release a link to the download..not the offiacial download..well..you know..if im disapionted..i have your e-mail addy..and whats that..its a site e-mail addy??..then it will be nice to hack into that html..knowwhatimsayin + +^^^QUOTE ENDS... + +My Response:
+Really. REALLY now? I get these types of emails on a daily basis. On an hourly basis, even. What are you trying to do? Instill the fear of God into me? You know what I'm afraid of? That you'll breed. That people like you actually end up having children. But let's take a heartwarming look at your email. + +"it will be nice to hack into that html" - that is the most dumb thing I've heard all day. Hack into my html? What are you going to do, add a few A HREF and IMG SRC tags? How lame can you get? Maybe if you said 'hack into your servers', I might get scared, but I'm not. Y'see, you only know my postmark.net email address... I doubt you'd be able to 'hack' their 'html'. I have another email address, too. remisser@selfabort.com - but guess what, directnic.com owns that, and if you can 'hack' their 'html', you get a cookie! But, judging by your email address "Mikegohan07@aol.com", the only 'hacking' you know about are scripts you download. + +You don't even make them. + +That's what makes me sick. If you want to be known as a hacker, learn how to code, and say "here's a custom hack I made called Brute Force." If you want to put on a tinfoil hat and complain about the aliens, that doesn't make you a hacker. Sticking feathers up your butt does not make you a duck. + +Not only that you go on to try to force me, the one who makes the music, to take down 'any dbz likenesses', or, as you so elloquently put it: "TAKE DOWN ANY AND ALL DBZ CHARECTER PICS ON YOUR SITE..ITS FALSE ADVERTISING AND WE CAN TAKE MONEY FROM YOU FOR THAT.." -- AOL has a spell check. Have you seen this amazing utility? Maybe you can use it to better 'hack' into the 'html' of your email messages. But, as I was saying... False advertising? Take money from us? Tell me, how are you entitled to money when we are a free entity? What goods and services have you purchased from us? Nothing. You have about as much chance of getting money from me as the bum that holds open the doors of the 7-11 and asks for 'spare change on your way out'... and he probably has better breath than you! As for removing dbz likenesses? + +(old lost image: https://web.archive.org/web/20020210152114im_/http://venus.spaceports.com/~kakarot/images/sexykrillin.jpg) + +(old lost image: https://web.archive.org/web/20020210152114im_/http://venus.spaceports.com/~kakarot/images/sexychichi.gif) + + +How's that? We won't use DBZ characters... we'll use real people that look slightly like them. How's that? Huh?! HOW'S THAT? + +So, go ahead and call your lawyer on your bright red Tonka Toys Playhouse Happy Fun Fone that your mommie gave you, because you're wasting my time. + +[think before you speak] + +.remisser (missingfear on aim)
+Special thanks to Spaceports (http://venus.spaceports.com/~kakarot/special.htm) for my unlicensed use of their unlicensed use of licensed Dragonball Z characters. Hope you don't ge sued! + + + + +# oh, one more thing... - 08/09/2001 by Remisser + +an addition to what I said below, I'll try to get a new song for you to listen to within a few days... I'll be changing the name of the song "Destruction Of Namek" to "Obliteration Of Anime World unrelated to DBZ" + + + + +# What this all means - 08/09/2001 by Remisser + +This is the third day in a row I've written something, so, I'll try to make it somewhat daily... which will eventually fall through since I'll never have something to say every day... +So. A new revelation you are all in a quandy/uproar about. + +Bid For Power without the DBZ related/copywritten/prostituted characters. + +Well, it seemed bound to happen for a while now, and, while most of you are preaching doom/gloom, it's not as bad as you think. + +First off you've been given a release date of sorts - about a month from now. Maybe it'll come sooner. Who knows. + +Some people are as disappointed as I was when I found out they were lipsyncing, and look at the similarities: there are a lot of tongues wagging in BFP land, but not a lot of sound coming out. You're all getting worried over nothing. The members will be removing the dbz likenesses, but keeping the anime feel. I know what you're thinking... you're thinking "What if we decide to come out with an addon pack for BFP that had DBZ characters?" -- Hey, what you do when we release the game is in your hands... We're going to be legally clean... This just means I won't be starting that La Blue Girl mod after all. + +So, in closing, calm down, lighten up... it's not the end of the world. + +remisser@postmark.net + + + + +# Quick Note - 08/08/2001 by Remisser + +I'll make this as short and sweet as possible. +In response to some comments made about my last update: +First off, most of the leaks were .exe files. A sort of setup. .exe's aren't pure files. I don't care if you have a virus scanner endorsed by Billy Bob Thorton, or TV's "ALF", some virus' or trojans can get past your rinky-dink Norton. +Secondly, .pk files are as well UNPURE. A file must be pure to not be infected. DOC files can be infected with trojans just via macros alone. Don't dispute this with me, I really don't care what you think. No amount of self assurance will allow you to hide away from something that can and may destroy your computer. +Third, anyone know a good graphic artist? I can't come up with a logo for my site for crap. Blech. + +Thanks for all responses that were sent to remisser@postmark.net -- even if they were negative. + + + + +# Rebels, all of you... - 08/07/2001 by Remisser + +I'm guilty. I admit it. I've dealt warez and, quite frankly, I'm ashamed and apalled at myself. But those days are over now. I pay for my software. I am now an upstanding citizen of the United States of America. +Why am I saying all of this? The point, you ask? +The point is that once the Cease and Desist order (which, by the way, if it was a legal cease and desist order it would have to be mailed, not emailed, and drafted by a lawyer...) was issued to us, everyone scrambled, people leaked, tongues wagged, and 12 year olds across the globe decided to swamp Infogrames message boards with some ugly feeling of justice pumping through their prebubescent veins. Now, I said I USED to trade warez, I learned the err of my ways. Now, if Funimation claims it's illegal for US to distribute Bid For Power, what makes it right for those who did leak it, to do so? Rule of thumb says never download something not from the official site. If you have BFP on your computers, I say, delete it. Most of them are bound with Back Orafice, some of them have bastardized versions of Sub7 (still functional with the new settings) bound with the exe, and some have trojans and virus' with it. You may have, on your hard drive, the best DBZ game to date, but you may also have something that would allow your Gym Teacher to log remotely into your computer and access ANYTHING on your hard drive. Yes, even those hentai porn pics of Goku and Bulma doing the nasty. So delete it. Use your better judgement. Wait for Chris to peacefully resolve the matter. Have faith. Even if you don't think there's a virus on your computer and you somehow got BFP, delete it. Say to yourself "I don't have the final copy with Remisser's music." -- Say it deep in your throat and make it shout out at the top of your lungs "I'm mad as hell and I'm not going to download anymore!" +For those of you with patience, who didn't download a leak, congratulations. Greg Brady loves you. + +Now a note to funimation. Can't you buy see the potential for funimation sales of funimation merchandise products? I mean, with subliminal advertising alone, you could make an extra fortune. You'll have stacks of unmarked bills you an sit on. Think about it. Think of how well (not at all) the other dbz video games did. Now start to think "Gee... 6 million plus hits to this bfp site... that's about 5,999,998 more than an OFFICAL BFP video game site would get. Hmmm... is there any way we can capitalize on millions of page views?" + +And another thing I want you kind folks at Infogrames and Funi to know. Think this game will damage profits? Hardly. Anyone who wants BFP has to have Quake 3 Arena knowledge. They also have to purches Q3A before they can play the game. Also they have to have a computer capable of playing it. Let me tell you, anyone who was ever going to get q3a has already purchased it. We're not going to increase their revenue. And, not everyone wants to download a file as large as BFP. So, here are a few ideas and thoughts... 1) Your profits won't decrease, in fact, they might just get better because the forums here are a breeding ground for talk about the new video game you guys are making and how excited everyone is... it's adding to your sales. 2) I hate to say this, but, the game IS far superior to all the other dbz games made, and just gives a benchmark for your team of 'video game designers' to surpass. 3) Would you really sue us? Think of the costs (court, lawyers, otherwise) -- That'll cost about as much as you'll make from a below average DBZ game. At best you'll break even. And most of us are poor and on welfare. So if you sue us, you won't get money, and we'll get book deals and movie-of-the-week deals, and anytime there's a television show about video games, we'll get paid to tell how you molested us with your lawyers. + +Really, all we want is a middleground. Somewhere to meet and discuss the pros and cons. + +We're on your side. The fans are too. + +If you're a fan, take the time out to write to Funimation. Tell them you'll preorder the game. Tell them how good they look in a suit. Kind words go a long way. Stop downloading the virus filled warez bfp leak, stop flooding message boards with negativity, and send a good word or two. + +Oh... and I'm almost finished with the music for BFP. Downloads to come, weather pending. + +email: remisser@postmark.net + + + + +# invisible monster - 06/26/2001 by Remisser + +Within the next few weeks a music video should be available. And, you know, when I promise something it comes true. +The video will be about 2 minutes and 30 seconds in length. I have a song I've done for it and might make it available before the music video. If possible, I'll try to make the music video available with the next couple of days. This is unlikely, but is a possibility. + +Another thing, if you have a Bid For Power Fan or Clan site, I'm always curious and love to see new BFP related sites. For no particular reason... so email me at remisser@postmark.net with your site URL. + +Don't all these devjournal updates just get you giddy? + + + +# Your birth is a mistake you'll spend your whole life trying to correct. - 06/21/2001 by Remisser + +[Download the End Credits](https://web.archive.org/web/20020210152114/http://insite.i700.net/mp3/Remisser_-_End_Credits.mp3)
+Okay, so it's not that big of a download, but it's something to tide you over. Thanks again to bfpta for hosting this stuff. Thanks to people like Bid For Power Nation who are accepting applications for members who are essential to the fabric of the BFP reality, by updating faithfully, and, without thanks, mirroring files. It's people like axsdeny who made an Android 16 wallpaper that bring a tear to my eye, because it's all without thanks. But thank you, the fans. + +As far as everything else is concerned, I am throughly working on more and more level music. There will be about 5-7 songs (more than likely 7), so as to not add a crap load of megs to a future bfp download. So, don't complain. I hope to finish this all up soon, but keep voting (see prev. entry for the poll), and keep emailing. remisser@postmark.net + + + + +# bitch tits - 06/21/2001 by Remisser + + + + + + + + + + +
+
+ BFP Music Poll +
+
+
+ + + +
+ Which version do you like better? +





+ + + + + + + + + + + +
Destruction of Namek (fast)
Destruction Of Namek (normal)
+
+
+ +
+ + Results + +
+
+
+ +The above is the new poll for the two songs (which you can download and are linked below) for you to vote. Much more organized. + +Later tonight I will try to have another song up for download, and I will put up more questions and answers. Any questions regarding the music aspect of Bid For Power, please email them to remisser@postmark.net + + + + +# Nothing of me is original. I am the combined effort of everybody I've ever known. - 06/18/2001 by Remisser + +A few questions have arisen since my induction into the ranks of team member. Here are the most popular: + +_Who are you?_ + +I'm the new Bid For Power music composer/whipping boy. + +_Really? Cool! Can you put an MP3 player in the game?_ + +No. Good God, no. Go to winamp.com and get an mp3 player and use it in the background. I'm going through the hoops to bring you music, don't ask me how to mute it. + +_Put Slipknot music in the game! Put Rob Zombie music in the game! Please?_ + +OK. All the music for the ingame part of BFP will be original as to not incur the wrath of record companies, and, as well, not to be a proverbial legal landmine. Plus, nobody likes Slipknot. (Oh great, now I'm going to get 80 slipknot fans giving crap) + +Okay, I'm not trying to be vicious here, but these are the questions I've been getting. I love all of the input I've been receiving, but I've gotten enough for now... but I still need your help. You want to hear music being done for BFP at the moment? + +[The First Version of Destruction Of Namek](https://web.archive.org/web/20020210152114/http://insite.i700.net/mp3/Remisser_-_Destruction_Of_Namek_V1.mp3)
+This is the slower more anthemic version of a song I'm working on... + +[The Second Version of Destruction Of Namek (clip)](https://web.archive.org/web/20020210152114/http://insite.i700.net/mp3/Remisser_-_Destruction_Of_Namek_(fast).mp3)
+This is basically a clip that culminates previous fan suggestions... one of which was 'speed it up'. So it's +50 BPM faster than version one. + +DOWNLOADS were made available by the folks over at [BFPTA](https://web.archive.org/web/20020210152114/http://www.bfpta.cjb.net/). Bfpta is a website that in the very near future will showcase tips, tricks, tactics, and techniques designed to assist any and all Bid for power players with one goal: Victory. It will house a numerous amount of tips developed by themselves, and sent in by others, From Novice, to Nightmare. The general public can also comment on each tip, to show others what they think, and how it would/did benefit them. -- One of the many BFP sites that are growing on the web... I might feature more in the future, but if I mention them, it doesn't mean BFP endorses them in any manner. :) + +The next time I update, I should have viewer response on which version they liked best, and what direction I'll be going in. As well as what equipment I use, et cetera. (The only comments I want are which version you like better, I don't really need input on how to make music :)) + +Happy downloading. + + + + +# when did the future change from being a promise, to a threat? - 06/15/2001 by Remisser + +This being my first post in my journal, I'd like you all to
+know who I am. I am the new Bid For Power composer. I will be
+delivering some nice crafted songs for the ingame atmosphere. I will
+give you all links to clips of some of the songs in the next few days.
+I know I can't please all of you, but I'll try to please some of you. + +Any suggestions such as songs you think would be good to cover for
+the ingame part of BFP, please either suggest them to me in an email,
+or address the ideas in the forums... thank you, and have a nice day. diff --git a/docs/rodney_dev_journal.md b/docs/old_dev_journals/rodney_dev_journal.md similarity index 97% rename from docs/rodney_dev_journal.md rename to docs/old_dev_journals/rodney_dev_journal.md index c97bf18..e492608 100644 --- a/docs/rodney_dev_journal.md +++ b/docs/old_dev_journals/rodney_dev_journal.md @@ -1,99 +1,99 @@ -# Q3 models get ready to download - 11/13/2001 by Rodney - -my personal website is done, I haven't uploaded it yet, cuz Im trying to find someone to host it for a good deal, if you know of a good deals with unlimited bandwidth, or no charge for bandwidth that would be great. im shooting to get a host by this saturday, so expect the site up in about 2-3 weeks from now. The BFP models will not available yet, cuz of the new way the code is been implemented. So we have to wait til yrgol gives us the go =). -My site is gonna be at www.RodneyOlmos.com so you can try checking everynow and then and youll see junk poping in and out =). - - - - - - - -# Let me rephrase this - 10/05/2001 by Rodney - -Im also looking at the possibilities of making all the characters I made capable of including multiple animations built on the models so if other people want to use them for their mods or anything else related they will also be able to add them to their mod or game using the characters I built, with my permission or requests to use them, and you may not alter them and claim them yours. - - - - - - -# Sound Help - 10/01/2001 by Rodney - -Thanx to all the people that emailed me and offered their help on sound. Im going to be emailing a list of things that "need to be done", the peeps that emailed me, so we can get this ball rolling and get all the characters over with. -We have enough people helping with sounds now=), so thats good. and I think that might be enough - - - - - - - - -# Characters for Quake arena done - 09/26/2001 by Rodney - -Hey all, I update like once every 6 months =) -things that are new are this. -- I just finished paking all the characters for quake3 arena, this includes all the phase 2 characters, the extra dbz characters like yamcha, the chibis, ussj trunsk,etc, and the new bfp characters. In gonna be releasing them fairly soon or as soon as I get all the sounds for each one of the characters, I would really like a hand on sounds, If you would like to help on that please email me at nameck@networld.com the quake3 characters will get released on sets of 5 characters at the time. - -- New BFP characters are also getting paked for release, all the original DBZ phase 1 characters are pretty much done, and I will be releasing them a lil after BFP is released, it will be on paks of 6 characters at the time so you can add them to the new BFP. - -- The other dbz characters will also get released soon after the first pak. like tien yamcha the chibis ussj trunks, gohan and stuff. but when they get released they will be using some one else's attack. example, chibi goten will use goku's attack and such, yamcha will may be use krillins. - -Reasons for this is game balancing. so far there are 6 attack systems that yrgol coded and by adding new attacks for other characters might unbalance the game. hopefully after release we will get feedback from everybody on how the game plays so we can tweak it for balancing and may be adding more set of attacks for other characters, besides the dbz phase 2 needs to be tackled different since we are not gonna use dbz stuff any more. - - -Im also looking at the possibilities of making all the characters I made capable of including multiple animations built on the models so if other people want to use them for their mods or anything else related they will also be able to add them to their mod or game using the characters I built with my permission or request to use them.. - -for now thats it, Ill try to keep updating often til release. - -lates all - --Rodney -www.RodneyOlmos.com - - - - - - - -# .. Finallly Updating =) - 04/03/2001 by Rodney - -Ok.. since phase 1 is officially done, and there isn't much else to do on it, Im gonna update my journal, and proceed to do so this whole rest of the week,Im gonna post all the work I've ever done for BFP here. That includes the BFP logo, 2d menu art, characters and new upcoming characters and so on. -Here is a list of things of work that I've done and some images that should get posted during the week, - -- 16 -- Goku (3 dif versions of it) -- New Vegeta -- USSJ Trunks -- SSJ Gohan -- Piccolo -- Tien -- Freeza -- Yamcha? -- New Characters? -- Chibi Boys, Trunks and Goten -- Standard BFP Animations -- Logo -- 2d Menu art (buttons and such) -- Anthony did the cartoon renders -- Hud -- Avi Renders, Roll Animations - -I think thats it.... - -so I'll post all my work this week. - -c ya - - - - - - - - Test - 12/04/2000 by Rodney - -alright, my first dev update on this new webpage=) +# Q3 models get ready to download - 11/13/2001 by Rodney + +my personal website is done, I haven't uploaded it yet, cuz Im trying to find someone to host it for a good deal, if you know of a good deals with unlimited bandwidth, or no charge for bandwidth that would be great. im shooting to get a host by this saturday, so expect the site up in about 2-3 weeks from now. The BFP models will not available yet, cuz of the new way the code is been implemented. So we have to wait til yrgol gives us the go =). +My site is gonna be at www.RodneyOlmos.com so you can try checking everynow and then and youll see junk poping in and out =). + + + + + + + +# Let me rephrase this - 10/05/2001 by Rodney + +Im also looking at the possibilities of making all the characters I made capable of including multiple animations built on the models so if other people want to use them for their mods or anything else related they will also be able to add them to their mod or game using the characters I built, with my permission or requests to use them, and you may not alter them and claim them yours. + + + + + + +# Sound Help - 10/01/2001 by Rodney + +Thanx to all the people that emailed me and offered their help on sound. Im going to be emailing a list of things that "need to be done", the peeps that emailed me, so we can get this ball rolling and get all the characters over with. +We have enough people helping with sounds now=), so thats good. and I think that might be enough + + + + + + + + +# Characters for Quake arena done - 09/26/2001 by Rodney + +Hey all, I update like once every 6 months =) +things that are new are this. +- I just finished paking all the characters for quake3 arena, this includes all the phase 2 characters, the extra dbz characters like yamcha, the chibis, ussj trunsk,etc, and the new bfp characters. In gonna be releasing them fairly soon or as soon as I get all the sounds for each one of the characters, I would really like a hand on sounds, If you would like to help on that please email me at nameck@networld.com the quake3 characters will get released on sets of 5 characters at the time. + +- New BFP characters are also getting paked for release, all the original DBZ phase 1 characters are pretty much done, and I will be releasing them a lil after BFP is released, it will be on paks of 6 characters at the time so you can add them to the new BFP. + +- The other dbz characters will also get released soon after the first pak. like tien yamcha the chibis ussj trunks, gohan and stuff. but when they get released they will be using some one else's attack. example, chibi goten will use goku's attack and such, yamcha will may be use krillins. + +Reasons for this is game balancing. so far there are 6 attack systems that yrgol coded and by adding new attacks for other characters might unbalance the game. hopefully after release we will get feedback from everybody on how the game plays so we can tweak it for balancing and may be adding more set of attacks for other characters, besides the dbz phase 2 needs to be tackled different since we are not gonna use dbz stuff any more. + + +Im also looking at the possibilities of making all the characters I made capable of including multiple animations built on the models so if other people want to use them for their mods or anything else related they will also be able to add them to their mod or game using the characters I built with my permission or request to use them.. + +for now thats it, Ill try to keep updating often til release. + +lates all + +-Rodney
+www.RodneyOlmos.com + + + + + + + +# .. Finallly Updating =) - 04/03/2001 by Rodney + +Ok.. since phase 1 is officially done, and there isn't much else to do on it, Im gonna update my journal, and proceed to do so this whole rest of the week,Im gonna post all the work I've ever done for BFP here. That includes the BFP logo, 2d menu art, characters and new upcoming characters and so on. +Here is a list of things of work that I've done and some images that should get posted during the week, + +- 16 +- Goku (3 dif versions of it) +- New Vegeta +- USSJ Trunks +- SSJ Gohan +- Piccolo +- Tien +- Freeza +- Yamcha? +- New Characters? +- Chibi Boys, Trunks and Goten +- Standard BFP Animations +- Logo +- 2d Menu art (buttons and such) +- Anthony did the cartoon renders +- Hud +- Avi Renders, Roll Animations + +I think thats it.... + +so I'll post all my work this week. + +c ya + + + + + + + +# Test - 12/04/2000 by Rodney + +alright, my first dev update on this new webpage=) Ok lets see, characters are practically ready for phase1, I got new characters done, but they will not be out til phase 2 comes out The nice thing is once going through the whole learning process of phase1, phase 2 is gonna go by fast, I got 3 new versions of Goku with 3 dif outfits I wont show anything til the characters are done. Oh yea.. I talked to Chris, Im gonna get some renders done of each character so you can use as wallpapers, and also some character roll avis. And Ill just do that every time i get a character completely done. thats it for now. \ No newline at end of file diff --git a/docs/yrgol_dev_journal.md b/docs/old_dev_journals/yrgol_dev_journal.md similarity index 98% rename from docs/yrgol_dev_journal.md rename to docs/old_dev_journals/yrgol_dev_journal.md index 135f4bb..303e14a 100644 --- a/docs/yrgol_dev_journal.md +++ b/docs/old_dev_journals/yrgol_dev_journal.md @@ -1,950 +1,950 @@ - -# BFP MAKES YOU TALK IN CAPS - Yrgol - 05/12/2002 - -For those that were wondering who these guys are, the about section has been updated to include character descriptions and a little backstory for all the fighters. - - - -# 1.2 100,000 - Yrgol - 05/10/2002 - -Version 1.2 of Bid For Power has now been downloaded over 100,000 times. I'd like to give a big thanks out to everyone who stayed with us. - - - -# 1.2 Tourney - Yrgol - 05/08/2002 - -With the demise of the XSL there's another BFP tournament forming. They are having a 1v1, 2v2, and 3v3 tournament with signups going on now. -Visit their page at https://web.archive.org/web/20020810122128/http://bfp-allstars.us4n6.org/ - - - -# Its True, Its True! - Yrgol - 05/06/2002 - -1.2 is now ready for download. The files section of this page has been updated. I will be adding more links as the night goes on. - - - -# 28 hours until 1.2 - Yrgol - 05/05/2002 - -1.2 will be released tomorrow at around 9pm eastern. I added a few images to the action section. When the big fuzzy focus on planetquake gets updated they'll have another 8 screenshots which combined with the new images on this page will cover all the new attacks. - - - -# BFP 1.1 Update Information - 02/04/2002 by Yrgol - -The grand list of my updates to the latest build of Bid For Power. Enjoy. - -BFP 1.1 Changes - -features: - -* added a bfp_server.cfg file, which lets server ops control: - -- flight cost, boost cost, ki regen, and ki charge regen. - -* aura color is now forced to red or blue in team games depending on team. - -* new console. - -* tweaked attack shaders for lighting values. - -* new fingerblast look and sound. - -* lighter versions of the maps gptourney1 and gpctf1. - -* added cone of fire support to the attack scripting. - -balance: - -* lowered boost cost significantly - -* upped ki regen rate so that flying at max pl costs nothing. - -* fixed the extra knockback on attacks that use that feature. tornado blast uses this. - -* rebalance of most attacks. - -bugs: - -* fixed the 1v1 server crash. 1v1 servers should be as stable as the other game types now. - -* fixed handling of plugin player models on clients that don't have the model. - -* fixed a "weapon number out of range" message followed by a crash when playing with bots. - -* fixed the appearance of explosion spawn attacks (homing special multi-beam bug). - -* made suicide take away a kill. - -* fixed losses being assigned to the wrong player in 1v1 games. - -* ctf servers show up in 1.0 as lms servers. fixed. - -* survival servers show up in 1.0 as single player servers. fixed. - -* gametype in 1.0 gets cut off in the servers list. fixed. - -* fixed missing friend shader for team games. - -* added dummy player sounds for tetsedah, ryuujin, and pyrate to get rid of some warning messages. - -* fixed the small own aura setting. - -* switched the missile dlights of the two razor disks. - -* fixed tornado blast catching attacks that have higher priority. - -* fixed ki use toggle. - -* fixed position of sparks in power struggles. - - - - -# more stuff for the patch - 01/23/2002 by Yrgol - -* fixed the 1v1 server crash. 1v1 servers should be as stable as the other game types now. -* lowered boost cost significantly -* upped ki regen rate so that flying at max pl costs nothing. -* fixed a "weapon number out of range" message followed by a crash when playing with bots. -* fixed the extra knockback on attacks that use that feature. tornado blast uses this. -* fixed losses being assigned to the wrong player in 1v1 games. - - - -# bugs so far - 01/20/2002 by Yrgol - -I'm waiting for a decent amount of bugs to show themselves before doing a patch. - -fixed: -* added a bfp_server.cfg file, which lets server ops control: flight cost, boost cost, ki regen, and ki charge regen. -* fixed the appearance of explosion spawn attacks (homing special). -* aura color is now forced to red or blue in team games depending on team. -* ctf servers show up in 1.0 as lms servers. fixed. -* survival servers show up in 1.0 as single player servers. fixed. -* gametype in 1.0 gets cut off in the servers list. fixed. -* fixed missing friend shader for team games. -* added dummy player sounds for tetsedah, ryuujin, and pyrate to get rid of some warning messages. - -known and not fixed yet: -* there seems to be some stability issues with 1v1 servers. this mainly seems to happen on map changes. - - - - -# patch - 01/19/2002 by Yrgol - -The next thing released by bfp will be a dbz plugin media pack or two. This will be an optional download that includes the old models in plugin form and some new maps. - -After that, the next releae of bfp will be a patch that will arrive in about two weeks to a month or so from now. This patch will have a decently small filesize, and it's for fixing whatever bugs show up. If you encounter a bug, please visit the bugs forum to post a message so I can fix it. Once most of the bugs are gone I'll start working on new attacks with some real variety now that my hands aren't tied by dbz. - -The homing special has a graphical glitch. Once it spawns the multiple homing missiles, those missiles appear to each player as his own 4th tier attack instead of appearing as the attack that it is supposed to. This has no effect on how the attack actually operates and does damage, but it can get confusing. This is already fixed for the next version. - - - - -# Modding BFP - 12/13/2001 by Yrgol - -It is possible to modify bfp in a number of ways. Some of them are compatible with the base bfp, and others are destructive to the base bfp. The only type of bfp modding that I will support is the compatible type. -Multiple groups have tried to make their own versions of various hacked copies of bfp, so in order to prevent players from having to choose between versions, I'm posting a little guide on how to make mods of bfp coexist with each other. This is not supposed to be a comprehensive guide on how to mod bfp, just some dos and don'ts if you decide to modify it. - -Model and Map Packs:
-If you only want to create some new models that use existing attack sets, or new maps to play on, create model and map pk3s and release them together so the players can install them in their base bfp directory. These models and maps will be selectable in the menu just like any other model or map. BFP allows for a significant amount of variation in plugin models. - -Game Balance:
-If you are unhappy with the balance of the game and run a server, just modify the script file bfp_weapons.cfg to suit your tastes. You can then start up your server and people using the base bfp will be able to play there. I will be adding more ability to do this in the future, but what already exists is pretty significant. - -New Attacks or Attack Sets:
-If you wish to add new attacks or attack sets to the game, you will have to create a full mod of bfp. This is because otherwise, players will accidentally connect to your bfp mod using the base bfp, and their game is likely to crash. More importantly, I don't want players to have to randomly try bfp servers until they can find one that is compatible with the version they are using. - -The server-finding code in the game will find any server running any mod that lives in a directory that starts with "bfp", and display the full name of that mod. The official bfp files will be in the "bfpq3" directory. Unnoficial mods of bfp can go in directories like "bfpmyversion" or "bfpcool". Players will be able to see "bfpcool" or "bfpq3" in the menu, so that they can find a server compatible with the version of bfp they are running. - -Rule #1:
-Never add or remove anything to any file named similarly to bfp0.pk3 in the base bfp directory. This will invalidate sv_pure, and it will prevent me from patching the game! You can use quake 3's pk3 indexing to override files in bfp0.pk3 without touching that file. - -Rule #2:
-Nobody is getting ahold of my source code for quite a long time, so don't bother asking. If you wish to add new code to bfp, you will have to code the entire game from scratch. - -Rule #3:
-Do not include any official bfp model, map, or image files with your mod. Free game or not, enforcable or not, doing so is a violation of copyrights and is also totally unecessary. Make use of quake3's base mod ability. Quake 3 allows you to create a mod that uses files from another mod's directory. If you do not want your players to have to download the official bfp, you will have to create all new maps and models to use for your game. - - - - -# weapon limit - 12/07/2001 by Yrgol - -Quake3 has a limit of 16 different weapons. BFP used to have a limit of 31 total attacks, with 21 of those being used. Thanks to about 2000 lines of code changes, BFP now has a practically unlimited max number of attacks. -I currently have slots for 99 different attacks that can be added without any code, but I could easily double or triple that if bfp ever comes close to filling up all 99 attacks. - - - - -# mp3 support - 11/30/2001 by Yrgol - -I added Tim "Timbo" Angus' mp3 to wav converter into bfp. It can be found at http://tremulous.sourceforge.net/junk/cg_mp3decoder/ - -This will allow us to include more music in the download, since each music file will have a smaller filesize. - -This will not allow you to play your own mp3's. It is not an mp3 player, it is an in-game utility to convert mp3's into a q3-playable format. - - - - -# Client-side scripting - 11/29/2001 by Yrgol - -I've finished the client side weapon scripting, and I've posted a doc in the editing and modifications forum describing how to use the scripting in order to create plugin models for BFP.
-You can find the post here: -http://www.bidforpower.com/forum/showthread.php?s=dc60acd92fe3f101aff5ad112f78d25d&postid;=508160#post508160 - - - - -# 1.30 and bots - 11/19/2001 by Yrgol - -Oddly enough, the 1.30 point release fixed bot flight, which the 1.17 point release broke. The bots have no problem flying up or down anymore. The bots switch weapons now as well, and I added a few other bot tweaks. -Bfp bots are pretty good for deathmatch practice. They're working much better than I expected. I'm sending a big woot out to the 1.30 point release for q3. - - - - -# - 11/17/2001 by Yrgol - -What we are currently working on is equivalent to beta 2 for most mods, or in bfp jargon phase 1. We had phase 1 completed for dbz quite a long time ago, and then the funimation/infogrames stuff happened. Most of the time since then has been used for converting bfp to not use dragonball z copyrights. - -The code is ready to go, the ui images have been changed to be legal, and we have several non-dbz maps finished. I currently have 3 of the 6 necessary default models. When I have all 6 default models, I will create a full build for the team to test. If nothing horrible goes wrong we'll probably release about a week after that. - -I've been working on scripting much of bfp. When this is complete, new characters and attacks will not require any additional code. This will allow team members and the community to create new unique characters for future releases. There will be a second release which will likely include more maps and models, some more in-depth gameplay modes, more attacks, and a completed attack scripting system. I will also likely be replacing the melee system with something different. - -I've added much more powerful custom plugin model support. The old dbz models will be able to perform identical to what they did before, provided they are converted to the new format. I have repackaged the old bfp models and included the necessary script files for them to work. I will be working on making the support for customizations much more significant, but that will be for future releases. - -I added server side weapon scripting. It allows a large amount of control over the game balance by the server operators, and makes my job of balancing much easier. It can not yet be used to create new attacks, but it will eventually. While doing this I fixed up a few serious gameplay complaints. - -Direct hit detection has been made more reliable. This makes the kienzan equivalent and the deathball easier to use. - -Explosion damage is no longer all or nothing. The damage decreases as distance from the explosion increases like in baseq3. - -Attack radius has been separated from explosion radius. The attack radius and explosion radius for each of the attacks have been tweaked. - -The knockback physics for attacks and explosions has been seriously tweaked. Attacks can now be used to rocket jump. - -Boost jumping has been toned down. It was simply too excessive before. - -Another total rebalance of all attacks happened. - - - - -# scripting - 10/26/2001 by Yrgol - -There's no way I can get all of this done before release, but this is the direction I'm going in. - -I'm working on attack scripting for servers only. This will allow new attacks of any rough type that bfp already contains to be added to the game with little or no code. I have a script file set up and partially implemented that has like 30 variables for each of the attacks. This will not allow models to define new attacks, but it will allow team members to work on attacks without me, or mods of bfp. It also lets server ops who hate the game balance to tweak it significantly. - -I have plans to add a server script file to define what the attack sets are, and even how many different attack sets there are. This config file will make adding new attack sets for existing attacks a trivial task. The file will look something like this: - -``` -attackset 1 -attack1 15 -attack2 20 -attack3 21 -attack4 2 -attack5 30 -defaultmodel models/players/goku -``` - -Per-skin config files have been added that allow things like attack names and voices to be defined by the skin. I have plans to move a lot of stuff into these config files, including attack shaders, sounds, and models. The individual models will never be able to define how the attacks operate, only how they are displayed to the user. - -I will eventually create a separate server config file that defines all the ki costs for flight and things along those lines. - -I've been working on the server attack config scripting for about a week, and it's a huge job. I can not finish all of this in a reasonable time frame, but eventually bfp will be close to just being an engine with the game all defined by runtime scripts. Once that point is reached I'll no longer be the bottleneck for a lot of the future work, and I can concentrate on gametypes and random stuff. - -I do not expect much of this to be implemented enough to matter before we get to release though. I'd much rather release asap and then improve. - - - - -# Conversion - 09/10/2001 by Yrgol - -With the exception of the names, the attacks are not changing. Most of the maps are not changing either. -The new thrust of development for me is moving as many things as reasonable into the player models. Custom player models can be made for any of the sets of attacks, and I'm working on a way for skins to define the names of the attacks. I don't want to let each skin pick the attacks to use for balance, memory, and implementation reasons. The voices that get played when using certain attacks have been moved into the player model. - -The bfp leak is bfp's biggest competition right now. The release has to be better than the previous stuff. There are a few annoying bugs to work out, and some of the top tier attacks throw balance way off. - -My job has been sapping most of my time and motivation to program lately. - - - - -# HoverQ3 - 08/17/2001 by Yrgol - -I released a little mod called Hover Q3. It includes some art from Pyrofragger, Kit Carson, and Sole. You can find it at http://www.bidforpower.com/yrgol/hoverq3 - -It's a 3 meg download and is a lightweight but fun mod. Don't expect anything like bfp from this, but it's well worth checking out. - - - - -# destructable objects - 07/08/2001 by Yrgol - -Breakable map entities are in, with multiple stages of breaking. I havn't done anything fancy with particles and destructable objects yet. None of the maps currently use this feature. - - - -# stuff - 07/06/2001 by Yrgol - -custom models are fully supported now. if you create a hulk hogan model and put it in /models/players/vegetahogan/, then the hulk hogan model will show up in the ui as a selectable skin for vegeta, brotha. I'm gonna hit you with a final flash in a steel cage. - -beams are bendy now. beams are not guided missiles, they are a beam of energy that gets longer quickly. when you turn left while firing, the beam bends to the right briefly before straightening out again. - -other than that, some random bugfixes in the animation playing and 1.29 fixes. - - - - -# <-- that way - 06/21/2001 by Yrgol - -* fixed animation jitter caused by jump anims that shouldn't be played. -* made it play the run anim faster during boost run. -* fixed the bug that made the ki trail show up behind objects. -* gave the accurate third person crosshair some smoothing to prevent it jumping around. -* added a toggle to use a stable crosshair instead of the accurate one. -* fixed a bug that made killing yourself give you a PL boost. -* made renzoku cost a ki pctage to prevent link overflow -* fixed a cheat that let people get vegeta's attacks with a piccolo model. -* enabled custom player models. - -I have a real job, and right now it's very demanding. When I have time and energy for bfp, I'm trying to polish as much as I can. - -The custom player models are weakly supported. Just for example, if you wanted to make a gundam and put it in bfp with vegeta's attacks, you'd have to create a model and skin in models/players/vegetagundam. Once there, it acts as a vegeta skin, even though it's actually a skin and a model. If you were playing with someone who didn't have your gundam model, they'd see the default vegeta. - -I'll release a far more descriptive doc on how to make a custom bfp model later on when it matters. BFP uses a lot of animations. - - - - -# random update - 05/29/2001 by Yrgol - -had a somewhat productive week. bfp comes in spurts. - -updates: -* accurate 3rd person crosshair. -* particle dust trail for boost running or flying close to the ground. -* particle bubble effects that float to the surface and gather there. -* particle splash + bubbles for entering water. -* particle bubble trail for boost swimming: -particlebubble - -* particle bubble trail for boost flying close to water. -* particle bubble effects for charging underwater: -underwatercharge - -* fixed the waterdance bug. -* lowered zanzoken cost. -* added antigrav rock particles for charging: -groundcharge - -* the antigrav rocks fall to the ground when you stop charging. -* gave rock particles collision detection and bouncing properties - - - - -# survival mode - 04/08/2001 by Yrgol - -I added (past tense) survival mode to the game. This might morph into budokai mode when mappers and I both get some time. The name comes from the mode found in a lot of fighting games. - -Survival mode is basically 1v1 where if you die once, you go to the end of the line. The winner does not get healed in between matches, and people spawning in get power level based on the average like in FFA mode. Spectator scores are saved and visible. The winner is the first person to reach the frag limit. - -1v1 mode is meant for challenge matches. It only works well with about a 20 frag limit. Survival mode is intended to give a 1v1 option where you don't have to wait around for 20 minutes before playing. I hope it finds a home on some servers, because it's the mode I most want to play. - - - - -# sticky keys and fps dependencies - 04/07/2001 by Yrgol - -Melee, block, ki boost, and ki charge had a tendency to get "stuck" in online play when the wrong packet got lost. I changed these keys so that they communicate with the server in the same way firing a weapon does. They shouldn't get stuck anymore even when there's a lot of packet loss. This is a bug that's been present since build 1. I'm glad to be rid of it. -Flight speed was highly dependent on FPS as of rc2. Ki boost cost was highly dependent on FPS since build 1. Both of these are fixed now also. - - - - -# subject? - 04/02/2001 by Yrgol - -From memory since I havn't been keeping close logs lately. - -* got a new job -* moved from pittsburgh to boston -* added particle rocks and smoke to explosions. -* added a particle trail to the particle sparks. -* added particle bubbles to attacks underwater. -* added some particles to power struggles. -* redid the shaders so they don't get overbright. -* simplified the bfp options menu by making explosion effects have a selecter between 4 different levels of intensity. -* made kakusan fire a variable number of balls depending on the amount of time spent charging it. fires from 2 to 6 homing balls. slowed the charge time, fixed the angle of fire on the homing balls. -* made ki drain a percentage for eyebeam, shyogeki ha, and kiaho. -* made kiaho a constant fire attack. decreased the range massively. decreased the knockback somewhat. made it bounce all missile attacks except for deathball and kienzan. -* eyebeam is NOT underbalanced in the slightest in its current form. -* increased the speed of all beam attacks. -* made the menu look prettier. -* added 2 new maps, a giant sound pack from 17, a new console font from gp, a few random things from dash. -* fixed body transformations. -* tried out bfp at 640x480 with the options all turned up on a p3 450 running a TNT ONE 16 MEG VIDEO CARD and got 20-30 fps on danorthern against 3 bots. -* create an installer exe for bfp. - - - - -# particles - 02/16/2001 by Yrgol - -I added some particle effects to the game. I havn't really figured out what to do with them yet, but they are there. Just as a start I added the generic explosion sparks. As with every other effect, if you don't like it you can turn it off in the menu. - -bunch of renzokus fired at a wall - - - - -# Old style update - 02/08/2001 by Yrgol - -changes since the thing we sent to the news sites: -* lowered renzoku cost to 100 -* increased renzoku missile speed to 8000. -* increased renzoku radius to 120. -* lowered renzoku firing speed to 200ms. -* put in a 1 second delay before you can zanzoken out of stun. -* increased SBC radius to 150. -* increased SBC damage from 35%*mult to 40%*mult. -* increased mouthbeam damage from 20% to 30% (effective 60% vs same PL). -* lowered final flash damage from 40%*mult to 25%*mult. -* increased the angry gohan range from 500 to 1000. -* tweaked the angry gohan aura scaling. -* lowered angry gohan ki cost from 200 to 150. -* fixed a bug that made other people's charging flashes not show up. -* fixed the lagometer position -* made an exception so the death ball can compete with beams in collisions. -* fixed a bug that made third person extend into spectator free mode. -* fixed a horrible bug that made players not cycle in 1v1. -* tweaked some LMS code. -* fixed a bug that made the blocking anim play a bit too long. -* fixed the problem with the angry gohan shader. -* added basic power struggles. -* redid kiaiho. -__ -* took away boost speed bonus while _firing_ a beam. -* lowered kamehameha damage from 40%*mult to 30%*mult. -* upped final flash damage from 25%*mult to 30%*mult. -* made deathball work in power struggles. -* put the angry gohan cost back the way it was. -* lowered angry gohan range to 800 from 1000. -* slowed recharge time to 6 seconds. -__ -* added the new gohan and krillin. -* added some attack charge sounds. -* redid the timing on masenko and gave it a HA sound. -* fixed a bunch of post-death bugs. -* removed the generic flash sounds for kamehameha and masenko. -* added a new sprite for final flash. -__ -* added sprites for the big bang, sokidan, masenko, kamehameha, and renzoku. -* made oozaru picking more random. -* fixed the oozaru extendo penis. -* totally redid flight physics. -* changed up and down orientation while flying to be relative to the player's axis. -* added cg_flytilt for tilting the viewpoint when boost flying. -* fixed a bug with zanzoken going through clip brushes. -* increased the size of the smoke ring around explosions. -* added cg_explosionSmoke to turn off the smoke ring. -* redid jump. -* added wall jumps. -* added a short delay between jumps excluding wall jumps. avoiding people looking like bunnies. -* fixed the "slightly sticky ground" flight bug. -* added ctf, but it's not selectable from the menu. -* added more dramatic transformations. they are 5 seconds long and you are invuln during it. - - - - -# Random updates - 02/04/2001 by Yrgol - -Ansel's been making a lot of sprites to replace some of our attack models. Flight physics was totally redone to include momentum. - -CTF mode was added back in, but I don't know if it's going to be a fully supported mode or not. CTF is kinda goofy when you can fly fast, and we don't have any maps for it. CTF should not be confused with capture the dragonballs, which still isn't in phase 1. - - - - -# Power Struggles - 01/10/2001 by Yrgol - -Power struggles are in phase 1 now. Ki recharge time has been increased to 6 seconds for now, subject to change at any given moment. We had it take about 20-30 seconds a long time ago and it really killed the gameplay. Lots of attacks have gone through some rebalancing. - - - -# Yrgol’s Important Bid For Power Phase 1 README!!! - 01/10/2001 by Yrgol - -(complete with 3 different exclamation points!) -A wise man once said: “Those who do not read this document will suck at BFP.” - -What is Bid For Power? -Bid For Power (BFP) is a quake 3 total conversion. We have taken quake 3 and used it to create a new game. In order to play BFP, you will need the full retail version of Quake 3 Arena by ID Software, but once you have that, our game is a free downloadable add-on. - -In phase 1 of BFP, we place 6 of the fighters from the Freeza saga in an arena in order to fight. Power is gained over time, but the way to get power quickly is to kill other players. Obviously in the show, Krillin would not be able to fight Freeza, but if we followed that rule who would play Krillin? In BFP, the only difference between the characters is the set of attacks available. - -Features: -- 6 different selectable characters, each with 5 attacks. Goku, Piccolo, Vegeta, Freeza, Gohan, and Krillin. -- 21 different ki attacks including controllable attacks, homing attacks, and chargeable attacks (no guns!). -- Toggleable flight. -- offhand melee combat -- Re-"charge"able ki energy for ammo, flight, and speed/power boost. -- Power level determines the strength of attacks, speed of movement, max health, max ki, ki charge rate, and what attacks are available. -- 5 different game modes: FFA, 1v1, Team DM, Last Man Standing Team DM, and Oozaru mode. -- Numerous new player animations. -- Plenty of cool effects: head and full body transformations, selectable aura, ki trail, scalable attacks, big explosions, playable third person mode, first person vis mode. - -Installation (windows): -- Install the full retail version of Quake 3 Arena. The demo version will NOT work with BFP. -- Install the 1.27 point release for Quake 3 Arena, found at http://www.quake3world.com/files/patch127g.html -- Unzip the bfprc1.zip file into your quake 3 arena directory. Make sure to use folder names when extracting the files. -- The directory "bfp" will be created as a subdirectory of the quake 3 directory. -- To start the game, either use the "Mods" tab in quake 3, or start the game with command line args “+set fs_game bfp”. Creating a shortcut to quake 3 with that argument is the recommended way of starting BFP. - -Starting BFP:
-There are two ways to start BFP. The easiest way is to use the mods menu in Quake 3. From the main Quake 3 menu, click "mods". Then find "Dragon Ball Z: Bid For Power" on the list and highlight it. If you have a lot of mods installed, you may need to scroll the list in order to make BFP visible. Once you have BFP highlighted, click on the load button and BFP will start. - -The other way to start BFP is to use the command line arguments `+set fs_game bfp`. An easy way to do this under Windows is to create a shortcut. Highlight the quake3 icon in whatever directory you installed Quake 3 into, and press ctrl-c to copy the link. Press ctrl-v to create a shortcut to quake3. Right click on the new shortcut and go into the properties menu. Under the `shortcut` tab of the properties menu, change the target to `C:Quake 3 Arenaquake3.exe +set fs_game bfp` if you installed Quake 3 into C:Quake 3 Arena. Use this new shortcut to start BFP. - -BFP loads its own config file called 'bfp.cfg'. This allows either way of starting BFP to work without any config file problems. - -What is Phase 1? -Phase 1 is the first release of BFP. It covers important characters and places from the Freeza saga of DBZ. - -What is Phase 2? -Phase 2 will be the second major release of BFP. It will be released when it is done, and will cover important characters and places from the Android/Cell saga. Phase 2 will also likely have updated effects and game play. There will more than likely be a few patches between phase 1 and phase 2. - -How do I play a multi-player game? -This game is designed to be played multiplayer. From the main menu, click on the "multiplayer" button. BFP will scan all of the quake 3 arena servers and display any BFP servers that it finds. Once a BFP server is found, highlight it, click accept and the game will connect to the server. - -Is there a single-player game? -Just barely. This game is intended to be played multi-player. A single player game can be played with the bots, but we recommend playing against real people. - -Viewpoint -Viewpoint is how you see the game while you play it. You have your choice of 3 different viewpoints for playing BFP. To switch between the view, use the BFP Options menu. - -- Third Person: The model is seen from the outside. Unlike the standard quake 3 third person view, in BFP the crosshair is visible, and the angle is changed to create less blocking of the view. Cvars cg_thirdPersonAngle and cg_thirdPersonRange have had their cheat protection removed, and cg_thirdPersonHeight was added for additional customization. - -- First Person Vis: First person where your own model is drawn. Your viewpoint is positioned on the model's eyes, and you can see your own arms and legs while fighting. - -- First Person: The standard first person quake 3 view. - -Power Level - -Power level is how strong you are. Power level determines max health, max ki, movement speed, damage caused by attacks, and which attacks are available to use. The only way to get more power is to kill someone. When you die (in most game modes), your power level is reset to the average of all current power levels. When the game ends or the server restarts, the power level of the players is reset to the default. - -Power Tiers - -Power level is divided into tiers. While most power level effects are based on the power level itself, aura color and attacks available is determined by the tier. - -- Tier 1: < 100,000 PL. Blue aura, only one ki attack available. -- Tier 2: 100,000 - 250,000 PL. Red aura, two ki attacks selectable. -- Tier 3: 250,000 - 500,000 PL. Red aura, three ki attacks selectable. -- Tier 4: 500,000 - 999,000 PL. Red aura, four ki attacks selectable. -- Ultimate Tier: 1 mil PL. Yellow aura, all attacks selectable. - -Transformations - -At 1 million power level, the transformation happens. The aura color turns yellow, and if the character has a transformation it occurs. Saiyajin characters turn into Super Saiyajins. Other than the benefits from increased power level, there is no additional benefit of the transformation. - -Ki Energy - -Ki is your stamina. Ki is used as ammunition for the ki attacks. Additionally, ki can be used to increase power, speed, jumping height, and special attacks by using the boost key. Ki can be charged in order to replenish it at any time by holding down the charge key. Beware, while charging you can not move or attack, and are highly visible to other players. - -Flight - -BFP has a toggle able flight button. The default is "f" but it can be set in the controls menu. To begin flying, simply press f once, and once again to stop flying. While flying, you are able to move to wherever you look. The jump key will make you move up, and the crouch key will make you move down. Your ki drains at a steady rate. At low power levels you will need to limit your flight, while at high power levels you can fly all day. A large speed boost is gained by holding down the boost key. - -Melee Combat - -To engage in melee combat, hold down the melee key and put the crosshairs over your opponent. If you are close range, then you will start beating on him. If you are long range, you will dive at the bad guy for a strike. To add extra knock back and stun your opponent, hold down the boost key while melee fighting. - -Hit Stun - -While in hit stun, the player can not move, attack, block, or charge. 1 second of hit stun is added when the player runs out of ki. 3 seconds of hit stun is added when melee is used in combination with the boost key. Do not overlook this feature. Being able to knock people into hit stun with ki-boosted melee is one of the keys to being good at BFP. -*The melee stun can be avoided by holding melee while you are attacked. - -Zanzoken - -Zanzoken is a short, extremely fast movement. In BFP, zanzoken is a controlled short-range teleportation that is performed by double-tapping right or left movement keys. Zanzoken is useful for dodging attacks, and can be used to break out of hit stun after 1 second. - -Blocking - -Pressing block once grants the player between one and two seconds of blocking. Blocking drains ki quickly, but transfers all damage to ki instead of health. Blocking can also be used to deflect missile attacks. There is a one second delay between when the player stops blocking and when the player can block again. - -Ki Attacks - -Each character has 5 attacks. At the lowest power tier, the player only has one selectable attack. Each time the player advances to a new power tier, he gets a new selectable attack. By default, each of the numeric keys, 1-5, choose a different attack. Only one attack can be selected at a time, but switching between attacks is instant. - -- standard attacks: hold down fire and you fire. -- charge-up attacks: hold down fire to start charging the attack, release fire to fire. -- minimum charge-up attacks: same as charge-up attacks, but with a minimum charge-up time. The ball of ki will appear in the player's hands once he is prepared to fire. -- beam attacks: a type of charge-up attack. Can only fire one beam at a time. After firing, you can aim the attack by moving the mouse, or detonate it by hitting fire again. -- homing attacks: these attacks will home in on the nearest opponent. - -Attack Collisions - -Unlike quake 3 attacks, BFP attacks are more than just a trajectory. Attacks have actual dimensions, and will explode on contact with players. If an attack looks 50’ wide, it will hit any players who come within 25’ of the center of the attack. Mid-air attack collisions also happen. Two attacks that collide will damage each other, and the stronger attack will cause the other to explode. The exception is any beam attack, which will destroy any other attack that it makes contact with. - -Power Struggles - -When two beam attacks collide, a power struggle will happen. Instead of the stronger beam blowing up the weaker beam, the stronger beam will push back the weaker beam until it hits the other player. Ki boost can be used to up the power of your beam if you are losing a power struggle. The Death Ball is an exception among the missile attacks, and can be used in a power struggle. - -Krillin - -- Kikou: standard weak ki blast. Press or hold fire to fire a blast. -- Taiyoken: the solar flare. Hold down fire until charged, then release to blind people around you. -- Sokidan: homing ball. Hold down fire until charged, then release to fire. -- Kakusan: a missile that spawns 4 homing balls when detonated. Hold down fire until charged, and release to fire the missile. Press fire again to detonate the missile into 4 homing balls. -- Kienzan: the destructo disk. Hold down fire until charged, and release to fire. This attack goes through walls and does massive damage. - -Vegeta - -- Kikou: standard weak ki blast. Press or hold fire to fire a blast. -- Bakuhatsuha: larger ki blast. Press or hold fire to fire a blast. -- Renzoku Energy Dan: multiple fast-firing ki blasts. Hold down fire to attack. -- Big Bang Attack: a beam that has a massive explosion. Hold down fire until charged, release to fire. While firing, use the cursor to aim the attack. Press fire again to detonate into a massive big bang explosion. -- Final Flash: a large and powerful beam attack. Hold down fire until charged, release to fire. While firing, use the cursor to aim the attack. Press fire again to detonate the attack. - -Gohan - -- Kikou: standard weak ki blast. Press or hold fire to fire a blast. -- Sokidan: homing ball. Hold down fire until charged, then release to fire. -- Renzoku Energy Dan: multiple fast-firing ki blasts. Hold down fire to attack. -- Masenko: beam attack. Hold down fire until charged, release to fire. While firing, use the cursor to aim the attack. Press fire again to detonate the attack. -- Energy Dan (Angry Gohan Attack): Gohan creates a massive and continuous explosion around himself. Press and hold fire. After a few seconds the explosion will appear. Gohan can not move while performing this attack. - -Piccolo - -- Kikou: standard weak ki blast. Press or hold fire to fire a blast. -- Eye Beam: a continuous blast of power from the eyes. Press and hold fire. -- Renzoku Energy Dan: multiple fast-firing ki blasts. Hold down fire to attack. -- Chobakuretsumaha: a fast and powerful homing attack. Hold down fire until charged, and release to fire. -- Special Beam Cannon: a fast and narrow but extremely powerful spiraling beam. Hold down fire until charged, release to fire. While firing, use the cursor to aim the attack. Press fire again to detonate the attack. - -Goku - -- Kikou: standard weak ki blast. Press or hold fire to fire a blast. -- Kiaiho: An invisible blast of energy from the hands with a massive knockback. Press or hold fire to attack. -- Sokidan: homing ball. Hold down fire until charged, then release to fire. -- Renzoku Energy Dan: multiple fast-firing ki blasts. Hold down fire to attack. -- Kamehameha: beam attack. Hold down fire until charged, release to fire. While firing, use the cursor to aim the attack. Press fire again to detonate the attack. - -Freeza - -- Kikou: standard weak ki blast. Press or hold fire to fire a blast. -- Shyogeki Ha: fast firing, extremely fast moving ki blasts from the fingers. Hold fire to attack. -- Freeza Beam: an extremely fast ki attack fired from the finger. Press or hold fire to fire a blast. -- Tsuibi Kienzan: Freeza’s homing version of the kienzan. Hold down fire until charged, and release to fire. This attack goes through walls. -- Death Ball: a gigantic ball of ki. Hold down fire until charged, and release to fire. This attack is huge in size and does massive damage. - -Game Types: - -- Death Match: Players start at ~50,000 PL. Additional PL is gained for each kill. On death, the PL of the player resets to the average of all other PLs. -- Tourney: Same rules as DM, but with only two players at a time. -- Team DM: Same rules as DM, but with teams. -- Team LMS: Last Man Standing. If you’ve ever played clan arena you should know this mode. Players start at 1 mil PL, and players who die can not respawn until the next round. -- Oozaru: This game works as regular FFA, except one player is chosen to be the ~50’ tall Oozaru. The player who kills the Oozaru gets to be the Oozaru next. The Oozaru has extra power and speed, and is also a giant compared to the other players. - -CVARS: - -If you don't already know what a cvar is you should probably ignore this section. These can be used from the q3 console to access features. Most of these features can be set from within the menu. - -* g_basepl [1-999]: set the starting power level from one thousand to one mil. -* cg_kitrail [0-99]: set the length of the ki trail. 0 turns it off. -* cg_crosshairhealth [0/1]: turn on or off the feature that makes the crosshair turn red when you score a hit. -* cg_lightauras [0/1]: turn on or off the aura dynamic lights. -* cg_lightexplosions [0/1]: turn on or off the explosion dynamic lights. -* cg_drawKIWarning [0/1]: turn on or off the low ki warning. -* cg_chargeupAlert [0/1]: turn on or off the "ready" message when charging attacks. -* cg_stfu [0/1]: disable character voices when firing attacks. -* cg_lowpolysphere [0/1]: force the use of a lower polycount sphere. -* cg_explosionShell [0/1]: turn on or off the explosion shell. -* cg_drawOwnModel [0/1]: toggle first person between traditional and vis modes. - -Help my computer can’t handle BFP! - -With all of the graphics options turned on, BFP takes a much beefier system than standard Quake 3. If your computer sucks, don’t despair. We’re looking out for you. BFP is meant to push a p3 500 with 128 megs of memory and a GeForce video card, but it is designed to be able to run playably on a celeron 300 with 128 megs of memory and a TNT2. However, with a much weaker system than that, you are pushing your luck with BFP. - -Here are some things you can do to try to boost your performance. - -- The first thing to try is turning off dynamic lights in the game options menu. Quake 3 can be slow when it comes to handling dynamic lights, and there are a lot of them in BFP. -- Go into the BFP options menu and use the ki trail slider bar to lower the length of the ki trail. Few systems can handle the ki trail at its max length without framerate loss. With the slider bar all the way to the left, the ki trail will have 0 length. With the slider bar all the way to the right, the ki trail will almost stretch the length of our maps. -- Go under the systems setting menu and lower the resolution to 640x480. Don’t gag, most Quake 3 competition players seem to use this resolution. -- Go into the BFP options menu and set the aura type to “polygonal aura”. This is the least costly aura type. Using the BFP options menu, turn transformation aura off, dynamic aura lights off, dynamic explosion lights off, ki trail off, small own aura on, and ssj perma glow off. With these settings BFP should run about as well as quake 3 does on your computer. -- If you are really having trouble go into the video set-up menu and change the lighting from lightmap to vertex. Everything will look crappy, but the game will run faster. -- If your system is running low on memory, use the BFP options menu to turn Force Default Skins on. This is the BFP equivalent of cg_forceModels in Quake 3. Force Default Skins will disable all custom skins for the models. With this option on, there will only be one skin shared between all Vegetas. - -Who made this game, and why is it free? - -Bid For Power was made by a group of volunteers. We’re all DBZ fans and most of us have watched all or nearly all the Japanese episodes. I can’t speak for all the reasons of the individual team members, but we all thought the idea of a first person DragonBall Z game was cool enough to want to get involved. It’s free because we are not a company, and don’t have the money to pay off people like Id. This game was created by people, for fun, in their spare time. Everyone on the team contributed to the game design and art style. - -- Chris James: project lead, coordinator, original concept, PR. -- Yrgol: programming, game design. -- Rodney: Goku and Piccolo models, animation, additional model tweaking, 2d art, skins. -- Pyrofragger: Gohan, Krillin, and SSJ Goku models, animation, DNamek map, aura and attack models. -- NilreMK: Phase 2 and “secret character” models, animation, attack models, Q3 editing guru. -- Mooky: Vegeta and Freeza models. -- Ansel: lead skin artist, 2d art -- Dethayngel: skins. -- Ebola: skins. -- Anthony: 2d art, char select art. -- Badhead: attack and aura shaders. -- Number17: sounds. -- Yngwei: Snake Way map, skyboxes, performed all music used in BFP. -- GangstaPoodle: GPCity, GPNamek, GPCityDark, and GPCave maps and textures, 2d art. -- Kit Carson: Earth and NamekXL maps and textures. -- $onik: Kami’s Lookout map textures. -- Perfect Chaos: additional map textures. -- Nat: webmaster, additional programming. -- Disco Stu: web design - - - - -# zanzoken - 12/17/2000 by Yrgol - -Zanzoken is in now. I'm doing it as a short range controlled-direction teleport. Double tap right or left in combination with other movement in order to zanzoken. I don't want to get into specifics but yes there are restrictions and costs to prevent this from being used all the time. - - - -# stuff - 12/14/2000 by Yrgol - -As you can tell I'm still making the mod. The bots own now. If all that mattered were code, bfp would be ready to release. Everything that I said was going to be in phase 1 is in there now and then some, and the bugs are minimal. A few of our models still need some tweaking before the whole is releasable. - -Funimation did indeed send us a cease and decist letter within days of selling dbz game rights to Infogrames. However, they have decided to take a closer look at the situation. We did not want to jump the gun on being foxed, because things are still fairly up in the air. We did not want the slashdot post to happen. - -Bid For Power will be released. It will most likely have Dragon Ball Z characters in it when it is released. - -17-3 (not finished): -* made bots aim beams. -* made bots charge attacks randomly above the minimum. -* made bots melee. -* made bots act blind when hit with the taiyoken. -* made bots aware of splash damage on charge-up attacks. -* lowered shyogeki ha damage from 20 to 5. -* lowered shyogeki ha range from 8192 to 1200. -* lowered shyogeki ha spread. -* made homing attacks easier to dodge. -* lowered kiaiho range from 8192 to 1000. -* made kiaiho do a stable 20% damage. -* removed the damage boost for ki boosting. -* got rid of the character change messages because they never worked right. -* shrunk the pre-fire deathball a bit so it doesn't clip freeza's head. -* made blindness not last through death. -* got rid of the melee axehandle smash direction. -* fixed a bug in melee that caused a crash. -* lowered hit-stun time from 3 seconds to 2. -* capped self-splash at 20%. -* added in the separate kienzan attack shader. -* shrunk freeza's kienzan. -* fixed a bug that made the kienzans stay around far longer than they should. -* fixed a bug that made kienzans hit way too fast and too often. -* gave the kienzans a max number of hits, which fixes a memory leak. -* fixed a bug with the animation timers. -* fixed a bug with switching weapons while firing a beam. -* fixed a bug with switching weapons while charging up an attack. -* made charging only prevent intentional movement, not glue you in place. - -17-2: -* made bots be 100% agressive all the time. -* made bots fly a better. -* taught bots how to use charge-up attacks and beams. -* fixed bot aim. -* upped the charge time for the chobakuretsumaha and sokidan. -* scaled down the pre-fire flashes of most attacks. -* fixed the spelling and grammer in the bot files and fixed the error messages. - -17-1: -* redid third person view. -* got around the gimble lock for flight so you can go upside down. -* changed default cg_thirdpersonheight to -50. - - - - -# more sutff than you wanted - 11/29/2000 by Yrgol - -16-3/17: -* fixed the timing of the "ready" message with the kamehameha. -* made a bfp.cfg file so that bfp will work fine by using the mods menu. -* fixed a bug that caused untextured weapon flashes to appear. -* fixed a bug that caused attack voices to sometimes come out at the wrong time. -* added cg_stfu to turn the voices off. -* fixed a bug that made melee mess up charge-up attacks. -* fixed a bug that caused a lot of problems in the char select screen. -* fixed a bug that made melee screw up the weapon time and hit way too fast. -* fixed a bug that made the charge-o-meter misread the sokidan/chobakuretsumaha power. -* fixed another bug with the ready message. -* added cull disable to all the explosion shaders so they don't disappear when you get too close. -* added an explosion shell/shockwave. can be turned off with cg_explosionShell 0. -* added cg_lowpolysphere to toggle between a low and a high polycount sphere model. -* fixed the infamous death-spawn bug. -* fixed the sizing of the accept button in the video setup menu. -* seemingly accidentally fixed the problem of ki trails showing through walls. -* made cg_thirdpersonrange and cg_thirdpersonheight get saved in bfp.cfg. -* gave cg_thirdpersonheight a default of 20. -* increased freezabeam explosion radius. -16-2: -* added g_basePL with a slider in the server startup to define starting PL. -* gave the renzoku an alternating firing offset. -* cut chobakuretsumaha damage in half. -* upped the ki cost of the chobakuretsumaha. -* lowered freezabeam damage. -* made melee hit stun not happen when both people are holding melee. -* made homing missiles select a target based on angle instead of distance. -* refined homing angle selection somewhat. -* fixed the sbc spiral so it disappears less often. -* fixed jump (detection and animation). -* made the kienzan stop disappearing when it hits other missiles. -* added self splash damage back in. -* made blocking deflect missiles. -* added in 17's explosion sounds. -* added in character sounds for sbc, kamehameha, final flash, bb attack, masenko. -* hopefully fixed the ride me big boy bug. - -16-1: -* made the spiral not disappear when two people sbc at the same time -* made ki trails a little more robust -* forced r_railCoreWidth to 15 on startup. -* removed a bug with the ssjhead getting an aura when it shouldn't. -* fixed a bug that caused the char select screen to crash the game. -* resized images so they were powers of 2. -* got rid of "unknown gametype" when connecting to a oozaru or lms server. -* homing attacks don't turn all the way around anymore. -* homing attacks no longer lose their velocity when homing. -* tweaked the various homing missile speeds to account for the new code. -* made taiyoken based on FOV, meaning you have to see it to go blind. -* set the size of menu buttons to 80x80 and made those values -settable through one file instead of 30 different files. -* made the eyebeam visible from all perspectives. -* upped the eyebeam damage. -* made the eyebeam not draw when holding melee. -* fixed a rotation problem on the auras. -* fixed a problem with showing the wrong gametype name when starting a server. - -16: -* decreased melee dive range from 2000 to 700. -* hopefully fixed the problem of melee dive teleporting you into objects. -* new menu. -* new attack icons. -* new hud. -* new ki trail. -* fixed the servers menu to differentiate between bfp gametypes. -* removed the "impressive" for the freezabeam. -* lowered the ki cost of the freezabeam from 1000 to 500. -* made the freezabeam explode when it hits a player instead of going through them. -* gave the freezabeam explosion some damage. -* changed the sound played for the freezabeam. -* fixed a bug in the eyebeam that made the beam not show up. -* changed the name of the sbc to makankosappo. -* removed drowning. -* made the speed boost depend on PL instead of power tier. -* made cg_kitrail be a slider var from 0 to 99 for ki trail length. - -15-8: -* removed heals from spawning on maps. -* increased visual explosion size. -* made charging a lot more effective. -* cut damage in half. -* made melee dive a lot more solid. -* gave the melee hit sound an origin. - -15-7: -* made the chargeup alert display in third person -* moved the chargeup alert to the bottom of the screen. -* plays the pain sounds based on percent of max health. -* upped masenko damage. -* made the hud player counter not include dead people. -* removed gibs for killing someone. you can still gib a corpse. -* made the prepare anim play for kakusan. -* fixed the timing on at least some charge up attack anims. -* added a flash model to firing beams. -* added KamehamehaFlashShader etc for the beam attacks. -this shader needs to be opaque enough to hide the beam origin -* scaled down the pre-fire ball for beam attacks. -* removed the standard flash entirely. - -15-6: -* added a "ready to fire" message for charge-up attacks. -* added cg_chargeupAlert to turn off that message. -* fixed a bug that would let attacks get kienzan properties. -* upped kakusan damage some. -* lowered taiyoken damage to 1%. -* added a visibility check on taiyoken. only checks barriers, not direction. -* increased taiyoken chargeup time. -* shortened blindness time some. -* made the melee_axehandle animation run, but it's not very noticable. -* toned down the angry gohan. -* made the prepare anim play for the angry gohan. -* changed the scoreboard name of the angry gohan to the Angry Gohan Attack. -* fixed "the incredible eternal kienzan" bug. - -15-5: -* first person vis mode works. it works best with models that have tag_eyes (gohan/krillin). -* angry gohan no longer draws while meleeing or charging. -* took out the announcer sounds for player names. -* blindness no longer stays with you through death. -* took out the ring model for explosions on players. -* fixed a scaling problem in the explosion ring that made it go black. -* removed the eject brass option from the game options menu. -* individual score now survives death in LMS mode. -* following in LMS spectator mode no longer fucks the next round. -* got rid of some red in the menu. -* gave explosions and missiles dynamic lights. -* added cg_lightExplosions to turn off dynamic explosion lights. -* removed the chargeup anim for taiyoken. - -15-4: lost all code since 15, had to redo stuff. ---SHADERS-- -* added shaders for kamehameha and masenko. -* added separate beam shaders. -* added separate shaders for explosions. -* added a shader for the freezabeam explosion ---WEAPONS-- -* freeza's second attack no longer ejects brass. -* fixed manual beam detonation. -* missiles should collide with each other a bit better. -* fixed homing attack collisions. -* increased eye beam range. -* removed self-damage. -* gave deathball a min charge up time (it was supposed to have one). -* gave masenko a min charge up time (it was supposed to have one). -* decreased the chargeup speed of sokidan/chobakuretsumaha. -* made all weapons explode when they hit a player. -* put the BIG BANG in the BIG BANG attack -* pumped up the deathball. -* can't continue firing a beam while charging, blocking, -melee fighting, or in hit-stun. -* beam attacks use the sphere as the pre-fire flash. -* beams now trump missiles for mid-air collisions. -* lowered renzoku damage. -* made taiyoken work. -* gave the SBC a spiral trail. -* weapon firing sound plays while firing beams instead of -while charging them. -* made the freeza beam red and gave it an explosion. -* gave explosions a smoke ring. ---OTHER-- -* custom skins now work fine. if you use a custom -vegeta skin that I don't have, instead of showing -up as sarge you will show up as vegeta/default on -my screen. -* somewhat improved bots. -* cg_forceModel removed. -* added cg_forceSkin to force the default skin for each model. -* changed obituary messages. -* beam attacks no longer blind you in first person view. -* switched from the nuke model to the sphere model for explosions. -* tweaked explosions a lot. -* picking up a normal health after a mega health won't set -you back to 100% health anymore. -* no longer plays the melee sound for missiles. -* unfucked spectator mode. -* switching chars while in LMS mode causes a suicide like in -any other game mode. + +# BFP MAKES YOU TALK IN CAPS - Yrgol - 05/12/2002 + +For those that were wondering who these guys are, the about section has been updated to include character descriptions and a little backstory for all the fighters. + + + +# 1.2 100,000 - Yrgol - 05/10/2002 + +Version 1.2 of Bid For Power has now been downloaded over 100,000 times. I'd like to give a big thanks out to everyone who stayed with us. + + + +# 1.2 Tourney - Yrgol - 05/08/2002 + +With the demise of the XSL there's another BFP tournament forming. They are having a 1v1, 2v2, and 3v3 tournament with signups going on now. +Visit their page at https://web.archive.org/web/20020810122128/http://bfp-allstars.us4n6.org/ + + + +# Its True, Its True! - Yrgol - 05/06/2002 + +1.2 is now ready for download. The files section of this page has been updated. I will be adding more links as the night goes on. + + + +# 28 hours until 1.2 - Yrgol - 05/05/2002 + +1.2 will be released tomorrow at around 9pm eastern. I added a few images to the action section. When the big fuzzy focus on planetquake gets updated they'll have another 8 screenshots which combined with the new images on this page will cover all the new attacks. + + + +# BFP 1.1 Update Information - 02/04/2002 by Yrgol + +The grand list of my updates to the latest build of Bid For Power. Enjoy. + +BFP 1.1 Changes + +features: + +* added a bfp_server.cfg file, which lets server ops control: + +- flight cost, boost cost, ki regen, and ki charge regen. + +* aura color is now forced to red or blue in team games depending on team. + +* new console. + +* tweaked attack shaders for lighting values. + +* new fingerblast look and sound. + +* lighter versions of the maps gptourney1 and gpctf1. + +* added cone of fire support to the attack scripting. + +balance: + +* lowered boost cost significantly + +* upped ki regen rate so that flying at max pl costs nothing. + +* fixed the extra knockback on attacks that use that feature. tornado blast uses this. + +* rebalance of most attacks. + +bugs: + +* fixed the 1v1 server crash. 1v1 servers should be as stable as the other game types now. + +* fixed handling of plugin player models on clients that don't have the model. + +* fixed a "weapon number out of range" message followed by a crash when playing with bots. + +* fixed the appearance of explosion spawn attacks (homing special multi-beam bug). + +* made suicide take away a kill. + +* fixed losses being assigned to the wrong player in 1v1 games. + +* ctf servers show up in 1.0 as lms servers. fixed. + +* survival servers show up in 1.0 as single player servers. fixed. + +* gametype in 1.0 gets cut off in the servers list. fixed. + +* fixed missing friend shader for team games. + +* added dummy player sounds for tetsedah, ryuujin, and pyrate to get rid of some warning messages. + +* fixed the small own aura setting. + +* switched the missile dlights of the two razor disks. + +* fixed tornado blast catching attacks that have higher priority. + +* fixed ki use toggle. + +* fixed position of sparks in power struggles. + + + + +# more stuff for the patch - 01/23/2002 by Yrgol + +* fixed the 1v1 server crash. 1v1 servers should be as stable as the other game types now. +* lowered boost cost significantly +* upped ki regen rate so that flying at max pl costs nothing. +* fixed a "weapon number out of range" message followed by a crash when playing with bots. +* fixed the extra knockback on attacks that use that feature. tornado blast uses this. +* fixed losses being assigned to the wrong player in 1v1 games. + + + +# bugs so far - 01/20/2002 by Yrgol + +I'm waiting for a decent amount of bugs to show themselves before doing a patch. + +fixed: +* added a bfp_server.cfg file, which lets server ops control: flight cost, boost cost, ki regen, and ki charge regen. +* fixed the appearance of explosion spawn attacks (homing special). +* aura color is now forced to red or blue in team games depending on team. +* ctf servers show up in 1.0 as lms servers. fixed. +* survival servers show up in 1.0 as single player servers. fixed. +* gametype in 1.0 gets cut off in the servers list. fixed. +* fixed missing friend shader for team games. +* added dummy player sounds for tetsedah, ryuujin, and pyrate to get rid of some warning messages. + +known and not fixed yet: +* there seems to be some stability issues with 1v1 servers. this mainly seems to happen on map changes. + + + + +# patch - 01/19/2002 by Yrgol + +The next thing released by bfp will be a dbz plugin media pack or two. This will be an optional download that includes the old models in plugin form and some new maps. + +After that, the next releae of bfp will be a patch that will arrive in about two weeks to a month or so from now. This patch will have a decently small filesize, and it's for fixing whatever bugs show up. If you encounter a bug, please visit the bugs forum to post a message so I can fix it. Once most of the bugs are gone I'll start working on new attacks with some real variety now that my hands aren't tied by dbz. + +The homing special has a graphical glitch. Once it spawns the multiple homing missiles, those missiles appear to each player as his own 4th tier attack instead of appearing as the attack that it is supposed to. This has no effect on how the attack actually operates and does damage, but it can get confusing. This is already fixed for the next version. + + + + +# Modding BFP - 12/13/2001 by Yrgol + +It is possible to modify bfp in a number of ways. Some of them are compatible with the base bfp, and others are destructive to the base bfp. The only type of bfp modding that I will support is the compatible type. +Multiple groups have tried to make their own versions of various hacked copies of bfp, so in order to prevent players from having to choose between versions, I'm posting a little guide on how to make mods of bfp coexist with each other. This is not supposed to be a comprehensive guide on how to mod bfp, just some dos and don'ts if you decide to modify it. + +Model and Map Packs:
+If you only want to create some new models that use existing attack sets, or new maps to play on, create model and map pk3s and release them together so the players can install them in their base bfp directory. These models and maps will be selectable in the menu just like any other model or map. BFP allows for a significant amount of variation in plugin models. + +Game Balance:
+If you are unhappy with the balance of the game and run a server, just modify the script file bfp_weapons.cfg to suit your tastes. You can then start up your server and people using the base bfp will be able to play there. I will be adding more ability to do this in the future, but what already exists is pretty significant. + +New Attacks or Attack Sets:
+If you wish to add new attacks or attack sets to the game, you will have to create a full mod of bfp. This is because otherwise, players will accidentally connect to your bfp mod using the base bfp, and their game is likely to crash. More importantly, I don't want players to have to randomly try bfp servers until they can find one that is compatible with the version they are using. + +The server-finding code in the game will find any server running any mod that lives in a directory that starts with "bfp", and display the full name of that mod. The official bfp files will be in the "bfpq3" directory. Unnoficial mods of bfp can go in directories like "bfpmyversion" or "bfpcool". Players will be able to see "bfpcool" or "bfpq3" in the menu, so that they can find a server compatible with the version of bfp they are running. + +Rule #1:
+Never add or remove anything to any file named similarly to bfp0.pk3 in the base bfp directory. This will invalidate sv_pure, and it will prevent me from patching the game! You can use quake 3's pk3 indexing to override files in bfp0.pk3 without touching that file. + +Rule #2:
+Nobody is getting ahold of my source code for quite a long time, so don't bother asking. If you wish to add new code to bfp, you will have to code the entire game from scratch. + +Rule #3:
+Do not include any official bfp model, map, or image files with your mod. Free game or not, enforcable or not, doing so is a violation of copyrights and is also totally unecessary. Make use of quake3's base mod ability. Quake 3 allows you to create a mod that uses files from another mod's directory. If you do not want your players to have to download the official bfp, you will have to create all new maps and models to use for your game. + + + + +# weapon limit - 12/07/2001 by Yrgol + +Quake3 has a limit of 16 different weapons. BFP used to have a limit of 31 total attacks, with 21 of those being used. Thanks to about 2000 lines of code changes, BFP now has a practically unlimited max number of attacks. +I currently have slots for 99 different attacks that can be added without any code, but I could easily double or triple that if bfp ever comes close to filling up all 99 attacks. + + + + +# mp3 support - 11/30/2001 by Yrgol + +I added Tim "Timbo" Angus' mp3 to wav converter into bfp. It can be found at http://tremulous.sourceforge.net/junk/cg_mp3decoder/ + +This will allow us to include more music in the download, since each music file will have a smaller filesize. + +This will not allow you to play your own mp3's. It is not an mp3 player, it is an in-game utility to convert mp3's into a q3-playable format. + + + + +# Client-side scripting - 11/29/2001 by Yrgol + +I've finished the client side weapon scripting, and I've posted a doc in the editing and modifications forum describing how to use the scripting in order to create plugin models for BFP.
+You can find the post here: +http://www.bidforpower.com/forum/showthread.php?s=dc60acd92fe3f101aff5ad112f78d25d&postid;=508160#post508160 + + + + +# 1.30 and bots - 11/19/2001 by Yrgol + +Oddly enough, the 1.30 point release fixed bot flight, which the 1.17 point release broke. The bots have no problem flying up or down anymore. The bots switch weapons now as well, and I added a few other bot tweaks. +Bfp bots are pretty good for deathmatch practice. They're working much better than I expected. I'm sending a big woot out to the 1.30 point release for q3. + + + + +# - 11/17/2001 by Yrgol + +What we are currently working on is equivalent to beta 2 for most mods, or in bfp jargon phase 1. We had phase 1 completed for dbz quite a long time ago, and then the funimation/infogrames stuff happened. Most of the time since then has been used for converting bfp to not use dragonball z copyrights. + +The code is ready to go, the ui images have been changed to be legal, and we have several non-dbz maps finished. I currently have 3 of the 6 necessary default models. When I have all 6 default models, I will create a full build for the team to test. If nothing horrible goes wrong we'll probably release about a week after that. + +I've been working on scripting much of bfp. When this is complete, new characters and attacks will not require any additional code. This will allow team members and the community to create new unique characters for future releases. There will be a second release which will likely include more maps and models, some more in-depth gameplay modes, more attacks, and a completed attack scripting system. I will also likely be replacing the melee system with something different. + +I've added much more powerful custom plugin model support. The old dbz models will be able to perform identical to what they did before, provided they are converted to the new format. I have repackaged the old bfp models and included the necessary script files for them to work. I will be working on making the support for customizations much more significant, but that will be for future releases. + +I added server side weapon scripting. It allows a large amount of control over the game balance by the server operators, and makes my job of balancing much easier. It can not yet be used to create new attacks, but it will eventually. While doing this I fixed up a few serious gameplay complaints. + +Direct hit detection has been made more reliable. This makes the kienzan equivalent and the deathball easier to use. + +Explosion damage is no longer all or nothing. The damage decreases as distance from the explosion increases like in baseq3. + +Attack radius has been separated from explosion radius. The attack radius and explosion radius for each of the attacks have been tweaked. + +The knockback physics for attacks and explosions has been seriously tweaked. Attacks can now be used to rocket jump. + +Boost jumping has been toned down. It was simply too excessive before. + +Another total rebalance of all attacks happened. + + + + +# scripting - 10/26/2001 by Yrgol + +There's no way I can get all of this done before release, but this is the direction I'm going in. + +I'm working on attack scripting for servers only. This will allow new attacks of any rough type that bfp already contains to be added to the game with little or no code. I have a script file set up and partially implemented that has like 30 variables for each of the attacks. This will not allow models to define new attacks, but it will allow team members to work on attacks without me, or mods of bfp. It also lets server ops who hate the game balance to tweak it significantly. + +I have plans to add a server script file to define what the attack sets are, and even how many different attack sets there are. This config file will make adding new attack sets for existing attacks a trivial task. The file will look something like this: + +``` +attackset 1 +attack1 15 +attack2 20 +attack3 21 +attack4 2 +attack5 30 +defaultmodel models/players/goku +``` + +Per-skin config files have been added that allow things like attack names and voices to be defined by the skin. I have plans to move a lot of stuff into these config files, including attack shaders, sounds, and models. The individual models will never be able to define how the attacks operate, only how they are displayed to the user. + +I will eventually create a separate server config file that defines all the ki costs for flight and things along those lines. + +I've been working on the server attack config scripting for about a week, and it's a huge job. I can not finish all of this in a reasonable time frame, but eventually bfp will be close to just being an engine with the game all defined by runtime scripts. Once that point is reached I'll no longer be the bottleneck for a lot of the future work, and I can concentrate on gametypes and random stuff. + +I do not expect much of this to be implemented enough to matter before we get to release though. I'd much rather release asap and then improve. + + + + +# Conversion - 09/10/2001 by Yrgol + +With the exception of the names, the attacks are not changing. Most of the maps are not changing either. +The new thrust of development for me is moving as many things as reasonable into the player models. Custom player models can be made for any of the sets of attacks, and I'm working on a way for skins to define the names of the attacks. I don't want to let each skin pick the attacks to use for balance, memory, and implementation reasons. The voices that get played when using certain attacks have been moved into the player model. + +The bfp leak is bfp's biggest competition right now. The release has to be better than the previous stuff. There are a few annoying bugs to work out, and some of the top tier attacks throw balance way off. + +My job has been sapping most of my time and motivation to program lately. + + + + +# HoverQ3 - 08/17/2001 by Yrgol + +I released a little mod called Hover Q3. It includes some art from Pyrofragger, Kit Carson, and Sole. You can find it at http://www.bidforpower.com/yrgol/hoverq3 + +It's a 3 meg download and is a lightweight but fun mod. Don't expect anything like bfp from this, but it's well worth checking out. + + + + +# destructable objects - 07/08/2001 by Yrgol + +Breakable map entities are in, with multiple stages of breaking. I havn't done anything fancy with particles and destructable objects yet. None of the maps currently use this feature. + + + +# stuff - 07/06/2001 by Yrgol + +custom models are fully supported now. if you create a hulk hogan model and put it in /models/players/vegetahogan/, then the hulk hogan model will show up in the ui as a selectable skin for vegeta, brotha. I'm gonna hit you with a final flash in a steel cage. + +beams are bendy now. beams are not guided missiles, they are a beam of energy that gets longer quickly. when you turn left while firing, the beam bends to the right briefly before straightening out again. + +other than that, some random bugfixes in the animation playing and 1.29 fixes. + + + + +# <-- that way - 06/21/2001 by Yrgol + +* fixed animation jitter caused by jump anims that shouldn't be played. +* made it play the run anim faster during boost run. +* fixed the bug that made the ki trail show up behind objects. +* gave the accurate third person crosshair some smoothing to prevent it jumping around. +* added a toggle to use a stable crosshair instead of the accurate one. +* fixed a bug that made killing yourself give you a PL boost. +* made renzoku cost a ki pctage to prevent link overflow +* fixed a cheat that let people get vegeta's attacks with a piccolo model. +* enabled custom player models. + +I have a real job, and right now it's very demanding. When I have time and energy for bfp, I'm trying to polish as much as I can. + +The custom player models are weakly supported. Just for example, if you wanted to make a gundam and put it in bfp with vegeta's attacks, you'd have to create a model and skin in models/players/vegetagundam. Once there, it acts as a vegeta skin, even though it's actually a skin and a model. If you were playing with someone who didn't have your gundam model, they'd see the default vegeta. + +I'll release a far more descriptive doc on how to make a custom bfp model later on when it matters. BFP uses a lot of animations. + + + + +# random update - 05/29/2001 by Yrgol + +had a somewhat productive week. bfp comes in spurts. + +updates: +* accurate 3rd person crosshair. +* particle dust trail for boost running or flying close to the ground. +* particle bubble effects that float to the surface and gather there. +* particle splash + bubbles for entering water. +* particle bubble trail for boost swimming: +particlebubble + +* particle bubble trail for boost flying close to water. +* particle bubble effects for charging underwater: +underwatercharge + +* fixed the waterdance bug. +* lowered zanzoken cost. +* added antigrav rock particles for charging: +groundcharge + +* the antigrav rocks fall to the ground when you stop charging. +* gave rock particles collision detection and bouncing properties + + + + +# survival mode - 04/08/2001 by Yrgol + +I added (past tense) survival mode to the game. This might morph into budokai mode when mappers and I both get some time. The name comes from the mode found in a lot of fighting games. + +Survival mode is basically 1v1 where if you die once, you go to the end of the line. The winner does not get healed in between matches, and people spawning in get power level based on the average like in FFA mode. Spectator scores are saved and visible. The winner is the first person to reach the frag limit. + +1v1 mode is meant for challenge matches. It only works well with about a 20 frag limit. Survival mode is intended to give a 1v1 option where you don't have to wait around for 20 minutes before playing. I hope it finds a home on some servers, because it's the mode I most want to play. + + + + +# sticky keys and fps dependencies - 04/07/2001 by Yrgol + +Melee, block, ki boost, and ki charge had a tendency to get "stuck" in online play when the wrong packet got lost. I changed these keys so that they communicate with the server in the same way firing a weapon does. They shouldn't get stuck anymore even when there's a lot of packet loss. This is a bug that's been present since build 1. I'm glad to be rid of it. +Flight speed was highly dependent on FPS as of rc2. Ki boost cost was highly dependent on FPS since build 1. Both of these are fixed now also. + + + + +# subject? - 04/02/2001 by Yrgol + +From memory since I havn't been keeping close logs lately. + +* got a new job +* moved from pittsburgh to boston +* added particle rocks and smoke to explosions. +* added a particle trail to the particle sparks. +* added particle bubbles to attacks underwater. +* added some particles to power struggles. +* redid the shaders so they don't get overbright. +* simplified the bfp options menu by making explosion effects have a selecter between 4 different levels of intensity. +* made kakusan fire a variable number of balls depending on the amount of time spent charging it. fires from 2 to 6 homing balls. slowed the charge time, fixed the angle of fire on the homing balls. +* made ki drain a percentage for eyebeam, shyogeki ha, and kiaho. +* made kiaho a constant fire attack. decreased the range massively. decreased the knockback somewhat. made it bounce all missile attacks except for deathball and kienzan. +* eyebeam is NOT underbalanced in the slightest in its current form. +* increased the speed of all beam attacks. +* made the menu look prettier. +* added 2 new maps, a giant sound pack from 17, a new console font from gp, a few random things from dash. +* fixed body transformations. +* tried out bfp at 640x480 with the options all turned up on a p3 450 running a TNT ONE 16 MEG VIDEO CARD and got 20-30 fps on danorthern against 3 bots. +* create an installer exe for bfp. + + + + +# particles - 02/16/2001 by Yrgol + +I added some particle effects to the game. I havn't really figured out what to do with them yet, but they are there. Just as a start I added the generic explosion sparks. As with every other effect, if you don't like it you can turn it off in the menu. + +bunch of renzokus fired at a wall + + + + +# Old style update - 02/08/2001 by Yrgol + +changes since the thing we sent to the news sites: +* lowered renzoku cost to 100 +* increased renzoku missile speed to 8000. +* increased renzoku radius to 120. +* lowered renzoku firing speed to 200ms. +* put in a 1 second delay before you can zanzoken out of stun. +* increased SBC radius to 150. +* increased SBC damage from 35%*mult to 40%*mult. +* increased mouthbeam damage from 20% to 30% (effective 60% vs same PL). +* lowered final flash damage from 40%*mult to 25%*mult. +* increased the angry gohan range from 500 to 1000. +* tweaked the angry gohan aura scaling. +* lowered angry gohan ki cost from 200 to 150. +* fixed a bug that made other people's charging flashes not show up. +* fixed the lagometer position +* made an exception so the death ball can compete with beams in collisions. +* fixed a bug that made third person extend into spectator free mode. +* fixed a horrible bug that made players not cycle in 1v1. +* tweaked some LMS code. +* fixed a bug that made the blocking anim play a bit too long. +* fixed the problem with the angry gohan shader. +* added basic power struggles. +* redid kiaiho. +__ +* took away boost speed bonus while _firing_ a beam. +* lowered kamehameha damage from 40%*mult to 30%*mult. +* upped final flash damage from 25%*mult to 30%*mult. +* made deathball work in power struggles. +* put the angry gohan cost back the way it was. +* lowered angry gohan range to 800 from 1000. +* slowed recharge time to 6 seconds. +__ +* added the new gohan and krillin. +* added some attack charge sounds. +* redid the timing on masenko and gave it a HA sound. +* fixed a bunch of post-death bugs. +* removed the generic flash sounds for kamehameha and masenko. +* added a new sprite for final flash. +__ +* added sprites for the big bang, sokidan, masenko, kamehameha, and renzoku. +* made oozaru picking more random. +* fixed the oozaru extendo penis. +* totally redid flight physics. +* changed up and down orientation while flying to be relative to the player's axis. +* added cg_flytilt for tilting the viewpoint when boost flying. +* fixed a bug with zanzoken going through clip brushes. +* increased the size of the smoke ring around explosions. +* added cg_explosionSmoke to turn off the smoke ring. +* redid jump. +* added wall jumps. +* added a short delay between jumps excluding wall jumps. avoiding people looking like bunnies. +* fixed the "slightly sticky ground" flight bug. +* added ctf, but it's not selectable from the menu. +* added more dramatic transformations. they are 5 seconds long and you are invuln during it. + + + + +# Random updates - 02/04/2001 by Yrgol + +Ansel's been making a lot of sprites to replace some of our attack models. Flight physics was totally redone to include momentum. + +CTF mode was added back in, but I don't know if it's going to be a fully supported mode or not. CTF is kinda goofy when you can fly fast, and we don't have any maps for it. CTF should not be confused with capture the dragonballs, which still isn't in phase 1. + + + + +# Power Struggles - 01/10/2001 by Yrgol + +Power struggles are in phase 1 now. Ki recharge time has been increased to 6 seconds for now, subject to change at any given moment. We had it take about 20-30 seconds a long time ago and it really killed the gameplay. Lots of attacks have gone through some rebalancing. + + + +# Yrgol’s Important Bid For Power Phase 1 README!!! - 01/10/2001 by Yrgol + +(complete with 3 different exclamation points!) +A wise man once said: “Those who do not read this document will suck at BFP.” + +What is Bid For Power? +Bid For Power (BFP) is a quake 3 total conversion. We have taken quake 3 and used it to create a new game. In order to play BFP, you will need the full retail version of Quake 3 Arena by ID Software, but once you have that, our game is a free downloadable add-on. + +In phase 1 of BFP, we place 6 of the fighters from the Freeza saga in an arena in order to fight. Power is gained over time, but the way to get power quickly is to kill other players. Obviously in the show, Krillin would not be able to fight Freeza, but if we followed that rule who would play Krillin? In BFP, the only difference between the characters is the set of attacks available. + +Features: +- 6 different selectable characters, each with 5 attacks. Goku, Piccolo, Vegeta, Freeza, Gohan, and Krillin. +- 21 different ki attacks including controllable attacks, homing attacks, and chargeable attacks (no guns!). +- Toggleable flight. +- offhand melee combat +- Re-"charge"able ki energy for ammo, flight, and speed/power boost. +- Power level determines the strength of attacks, speed of movement, max health, max ki, ki charge rate, and what attacks are available. +- 5 different game modes: FFA, 1v1, Team DM, Last Man Standing Team DM, and Oozaru mode. +- Numerous new player animations. +- Plenty of cool effects: head and full body transformations, selectable aura, ki trail, scalable attacks, big explosions, playable third person mode, first person vis mode. + +Installation (windows): +- Install the full retail version of Quake 3 Arena. The demo version will NOT work with BFP. +- Install the 1.27 point release for Quake 3 Arena, found at http://www.quake3world.com/files/patch127g.html +- Unzip the bfprc1.zip file into your quake 3 arena directory. Make sure to use folder names when extracting the files. +- The directory "bfp" will be created as a subdirectory of the quake 3 directory. +- To start the game, either use the "Mods" tab in quake 3, or start the game with command line args “+set fs_game bfp”. Creating a shortcut to quake 3 with that argument is the recommended way of starting BFP. + +Starting BFP:
+There are two ways to start BFP. The easiest way is to use the mods menu in Quake 3. From the main Quake 3 menu, click "mods". Then find "Dragon Ball Z: Bid For Power" on the list and highlight it. If you have a lot of mods installed, you may need to scroll the list in order to make BFP visible. Once you have BFP highlighted, click on the load button and BFP will start. + +The other way to start BFP is to use the command line arguments `+set fs_game bfp`. An easy way to do this under Windows is to create a shortcut. Highlight the quake3 icon in whatever directory you installed Quake 3 into, and press ctrl-c to copy the link. Press ctrl-v to create a shortcut to quake3. Right click on the new shortcut and go into the properties menu. Under the `shortcut` tab of the properties menu, change the target to `C:Quake 3 Arenaquake3.exe +set fs_game bfp` if you installed Quake 3 into C:Quake 3 Arena. Use this new shortcut to start BFP. + +BFP loads its own config file called 'bfp.cfg'. This allows either way of starting BFP to work without any config file problems. + +What is Phase 1? +Phase 1 is the first release of BFP. It covers important characters and places from the Freeza saga of DBZ. + +What is Phase 2? +Phase 2 will be the second major release of BFP. It will be released when it is done, and will cover important characters and places from the Android/Cell saga. Phase 2 will also likely have updated effects and game play. There will more than likely be a few patches between phase 1 and phase 2. + +How do I play a multi-player game? +This game is designed to be played multiplayer. From the main menu, click on the "multiplayer" button. BFP will scan all of the quake 3 arena servers and display any BFP servers that it finds. Once a BFP server is found, highlight it, click accept and the game will connect to the server. + +Is there a single-player game? +Just barely. This game is intended to be played multi-player. A single player game can be played with the bots, but we recommend playing against real people. + +Viewpoint +Viewpoint is how you see the game while you play it. You have your choice of 3 different viewpoints for playing BFP. To switch between the view, use the BFP Options menu. + +- Third Person: The model is seen from the outside. Unlike the standard quake 3 third person view, in BFP the crosshair is visible, and the angle is changed to create less blocking of the view. Cvars cg_thirdPersonAngle and cg_thirdPersonRange have had their cheat protection removed, and cg_thirdPersonHeight was added for additional customization. + +- First Person Vis: First person where your own model is drawn. Your viewpoint is positioned on the model's eyes, and you can see your own arms and legs while fighting. + +- First Person: The standard first person quake 3 view. + +Power Level + +Power level is how strong you are. Power level determines max health, max ki, movement speed, damage caused by attacks, and which attacks are available to use. The only way to get more power is to kill someone. When you die (in most game modes), your power level is reset to the average of all current power levels. When the game ends or the server restarts, the power level of the players is reset to the default. + +Power Tiers + +Power level is divided into tiers. While most power level effects are based on the power level itself, aura color and attacks available is determined by the tier. + +- Tier 1: < 100,000 PL. Blue aura, only one ki attack available. +- Tier 2: 100,000 - 250,000 PL. Red aura, two ki attacks selectable. +- Tier 3: 250,000 - 500,000 PL. Red aura, three ki attacks selectable. +- Tier 4: 500,000 - 999,000 PL. Red aura, four ki attacks selectable. +- Ultimate Tier: 1 mil PL. Yellow aura, all attacks selectable. + +Transformations + +At 1 million power level, the transformation happens. The aura color turns yellow, and if the character has a transformation it occurs. Saiyajin characters turn into Super Saiyajins. Other than the benefits from increased power level, there is no additional benefit of the transformation. + +Ki Energy + +Ki is your stamina. Ki is used as ammunition for the ki attacks. Additionally, ki can be used to increase power, speed, jumping height, and special attacks by using the boost key. Ki can be charged in order to replenish it at any time by holding down the charge key. Beware, while charging you can not move or attack, and are highly visible to other players. + +Flight + +BFP has a toggle able flight button. The default is "f" but it can be set in the controls menu. To begin flying, simply press f once, and once again to stop flying. While flying, you are able to move to wherever you look. The jump key will make you move up, and the crouch key will make you move down. Your ki drains at a steady rate. At low power levels you will need to limit your flight, while at high power levels you can fly all day. A large speed boost is gained by holding down the boost key. + +Melee Combat + +To engage in melee combat, hold down the melee key and put the crosshairs over your opponent. If you are close range, then you will start beating on him. If you are long range, you will dive at the bad guy for a strike. To add extra knock back and stun your opponent, hold down the boost key while melee fighting. + +Hit Stun + +While in hit stun, the player can not move, attack, block, or charge. 1 second of hit stun is added when the player runs out of ki. 3 seconds of hit stun is added when melee is used in combination with the boost key. Do not overlook this feature. Being able to knock people into hit stun with ki-boosted melee is one of the keys to being good at BFP. +*The melee stun can be avoided by holding melee while you are attacked. + +Zanzoken + +Zanzoken is a short, extremely fast movement. In BFP, zanzoken is a controlled short-range teleportation that is performed by double-tapping right or left movement keys. Zanzoken is useful for dodging attacks, and can be used to break out of hit stun after 1 second. + +Blocking + +Pressing block once grants the player between one and two seconds of blocking. Blocking drains ki quickly, but transfers all damage to ki instead of health. Blocking can also be used to deflect missile attacks. There is a one second delay between when the player stops blocking and when the player can block again. + +Ki Attacks + +Each character has 5 attacks. At the lowest power tier, the player only has one selectable attack. Each time the player advances to a new power tier, he gets a new selectable attack. By default, each of the numeric keys, 1-5, choose a different attack. Only one attack can be selected at a time, but switching between attacks is instant. + +- standard attacks: hold down fire and you fire. +- charge-up attacks: hold down fire to start charging the attack, release fire to fire. +- minimum charge-up attacks: same as charge-up attacks, but with a minimum charge-up time. The ball of ki will appear in the player's hands once he is prepared to fire. +- beam attacks: a type of charge-up attack. Can only fire one beam at a time. After firing, you can aim the attack by moving the mouse, or detonate it by hitting fire again. +- homing attacks: these attacks will home in on the nearest opponent. + +Attack Collisions + +Unlike quake 3 attacks, BFP attacks are more than just a trajectory. Attacks have actual dimensions, and will explode on contact with players. If an attack looks 50’ wide, it will hit any players who come within 25’ of the center of the attack. Mid-air attack collisions also happen. Two attacks that collide will damage each other, and the stronger attack will cause the other to explode. The exception is any beam attack, which will destroy any other attack that it makes contact with. + +Power Struggles + +When two beam attacks collide, a power struggle will happen. Instead of the stronger beam blowing up the weaker beam, the stronger beam will push back the weaker beam until it hits the other player. Ki boost can be used to up the power of your beam if you are losing a power struggle. The Death Ball is an exception among the missile attacks, and can be used in a power struggle. + +Krillin + +- Kikou: standard weak ki blast. Press or hold fire to fire a blast. +- Taiyoken: the solar flare. Hold down fire until charged, then release to blind people around you. +- Sokidan: homing ball. Hold down fire until charged, then release to fire. +- Kakusan: a missile that spawns 4 homing balls when detonated. Hold down fire until charged, and release to fire the missile. Press fire again to detonate the missile into 4 homing balls. +- Kienzan: the destructo disk. Hold down fire until charged, and release to fire. This attack goes through walls and does massive damage. + +Vegeta + +- Kikou: standard weak ki blast. Press or hold fire to fire a blast. +- Bakuhatsuha: larger ki blast. Press or hold fire to fire a blast. +- Renzoku Energy Dan: multiple fast-firing ki blasts. Hold down fire to attack. +- Big Bang Attack: a beam that has a massive explosion. Hold down fire until charged, release to fire. While firing, use the cursor to aim the attack. Press fire again to detonate into a massive big bang explosion. +- Final Flash: a large and powerful beam attack. Hold down fire until charged, release to fire. While firing, use the cursor to aim the attack. Press fire again to detonate the attack. + +Gohan + +- Kikou: standard weak ki blast. Press or hold fire to fire a blast. +- Sokidan: homing ball. Hold down fire until charged, then release to fire. +- Renzoku Energy Dan: multiple fast-firing ki blasts. Hold down fire to attack. +- Masenko: beam attack. Hold down fire until charged, release to fire. While firing, use the cursor to aim the attack. Press fire again to detonate the attack. +- Energy Dan (Angry Gohan Attack): Gohan creates a massive and continuous explosion around himself. Press and hold fire. After a few seconds the explosion will appear. Gohan can not move while performing this attack. + +Piccolo + +- Kikou: standard weak ki blast. Press or hold fire to fire a blast. +- Eye Beam: a continuous blast of power from the eyes. Press and hold fire. +- Renzoku Energy Dan: multiple fast-firing ki blasts. Hold down fire to attack. +- Chobakuretsumaha: a fast and powerful homing attack. Hold down fire until charged, and release to fire. +- Special Beam Cannon: a fast and narrow but extremely powerful spiraling beam. Hold down fire until charged, release to fire. While firing, use the cursor to aim the attack. Press fire again to detonate the attack. + +Goku + +- Kikou: standard weak ki blast. Press or hold fire to fire a blast. +- Kiaiho: An invisible blast of energy from the hands with a massive knockback. Press or hold fire to attack. +- Sokidan: homing ball. Hold down fire until charged, then release to fire. +- Renzoku Energy Dan: multiple fast-firing ki blasts. Hold down fire to attack. +- Kamehameha: beam attack. Hold down fire until charged, release to fire. While firing, use the cursor to aim the attack. Press fire again to detonate the attack. + +Freeza + +- Kikou: standard weak ki blast. Press or hold fire to fire a blast. +- Shyogeki Ha: fast firing, extremely fast moving ki blasts from the fingers. Hold fire to attack. +- Freeza Beam: an extremely fast ki attack fired from the finger. Press or hold fire to fire a blast. +- Tsuibi Kienzan: Freeza’s homing version of the kienzan. Hold down fire until charged, and release to fire. This attack goes through walls. +- Death Ball: a gigantic ball of ki. Hold down fire until charged, and release to fire. This attack is huge in size and does massive damage. + +Game Types: + +- Death Match: Players start at ~50,000 PL. Additional PL is gained for each kill. On death, the PL of the player resets to the average of all other PLs. +- Tourney: Same rules as DM, but with only two players at a time. +- Team DM: Same rules as DM, but with teams. +- Team LMS: Last Man Standing. If you’ve ever played clan arena you should know this mode. Players start at 1 mil PL, and players who die can not respawn until the next round. +- Oozaru: This game works as regular FFA, except one player is chosen to be the ~50’ tall Oozaru. The player who kills the Oozaru gets to be the Oozaru next. The Oozaru has extra power and speed, and is also a giant compared to the other players. + +CVARS: + +If you don't already know what a cvar is you should probably ignore this section. These can be used from the q3 console to access features. Most of these features can be set from within the menu. + +* g_basepl [1-999]: set the starting power level from one thousand to one mil. +* cg_kitrail [0-99]: set the length of the ki trail. 0 turns it off. +* cg_crosshairhealth [0/1]: turn on or off the feature that makes the crosshair turn red when you score a hit. +* cg_lightauras [0/1]: turn on or off the aura dynamic lights. +* cg_lightexplosions [0/1]: turn on or off the explosion dynamic lights. +* cg_drawKIWarning [0/1]: turn on or off the low ki warning. +* cg_chargeupAlert [0/1]: turn on or off the "ready" message when charging attacks. +* cg_stfu [0/1]: disable character voices when firing attacks. +* cg_lowpolysphere [0/1]: force the use of a lower polycount sphere. +* cg_explosionShell [0/1]: turn on or off the explosion shell. +* cg_drawOwnModel [0/1]: toggle first person between traditional and vis modes. + +Help my computer can’t handle BFP! + +With all of the graphics options turned on, BFP takes a much beefier system than standard Quake 3. If your computer sucks, don’t despair. We’re looking out for you. BFP is meant to push a p3 500 with 128 megs of memory and a GeForce video card, but it is designed to be able to run playably on a celeron 300 with 128 megs of memory and a TNT2. However, with a much weaker system than that, you are pushing your luck with BFP. + +Here are some things you can do to try to boost your performance. + +- The first thing to try is turning off dynamic lights in the game options menu. Quake 3 can be slow when it comes to handling dynamic lights, and there are a lot of them in BFP. +- Go into the BFP options menu and use the ki trail slider bar to lower the length of the ki trail. Few systems can handle the ki trail at its max length without framerate loss. With the slider bar all the way to the left, the ki trail will have 0 length. With the slider bar all the way to the right, the ki trail will almost stretch the length of our maps. +- Go under the systems setting menu and lower the resolution to 640x480. Don’t gag, most Quake 3 competition players seem to use this resolution. +- Go into the BFP options menu and set the aura type to “polygonal aura”. This is the least costly aura type. Using the BFP options menu, turn transformation aura off, dynamic aura lights off, dynamic explosion lights off, ki trail off, small own aura on, and ssj perma glow off. With these settings BFP should run about as well as quake 3 does on your computer. +- If you are really having trouble go into the video set-up menu and change the lighting from lightmap to vertex. Everything will look crappy, but the game will run faster. +- If your system is running low on memory, use the BFP options menu to turn Force Default Skins on. This is the BFP equivalent of cg_forceModels in Quake 3. Force Default Skins will disable all custom skins for the models. With this option on, there will only be one skin shared between all Vegetas. + +Who made this game, and why is it free? + +Bid For Power was made by a group of volunteers. We’re all DBZ fans and most of us have watched all or nearly all the Japanese episodes. I can’t speak for all the reasons of the individual team members, but we all thought the idea of a first person DragonBall Z game was cool enough to want to get involved. It’s free because we are not a company, and don’t have the money to pay off people like Id. This game was created by people, for fun, in their spare time. Everyone on the team contributed to the game design and art style. + +- Chris James: project lead, coordinator, original concept, PR. +- Yrgol: programming, game design. +- Rodney: Goku and Piccolo models, animation, additional model tweaking, 2d art, skins. +- Pyrofragger: Gohan, Krillin, and SSJ Goku models, animation, DNamek map, aura and attack models. +- NilreMK: Phase 2 and “secret character” models, animation, attack models, Q3 editing guru. +- Mooky: Vegeta and Freeza models. +- Ansel: lead skin artist, 2d art +- Dethayngel: skins. +- Ebola: skins. +- Anthony: 2d art, char select art. +- Badhead: attack and aura shaders. +- Number17: sounds. +- Yngwei: Snake Way map, skyboxes, performed all music used in BFP. +- GangstaPoodle: GPCity, GPNamek, GPCityDark, and GPCave maps and textures, 2d art. +- Kit Carson: Earth and NamekXL maps and textures. +- $onik: Kami’s Lookout map textures. +- Perfect Chaos: additional map textures. +- Nat: webmaster, additional programming. +- Disco Stu: web design + + + + +# zanzoken - 12/17/2000 by Yrgol + +Zanzoken is in now. I'm doing it as a short range controlled-direction teleport. Double tap right or left in combination with other movement in order to zanzoken. I don't want to get into specifics but yes there are restrictions and costs to prevent this from being used all the time. + + + +# stuff - 12/14/2000 by Yrgol + +As you can tell I'm still making the mod. The bots own now. If all that mattered were code, bfp would be ready to release. Everything that I said was going to be in phase 1 is in there now and then some, and the bugs are minimal. A few of our models still need some tweaking before the whole is releasable. + +Funimation did indeed send us a cease and decist letter within days of selling dbz game rights to Infogrames. However, they have decided to take a closer look at the situation. We did not want to jump the gun on being foxed, because things are still fairly up in the air. We did not want the slashdot post to happen. + +Bid For Power will be released. It will most likely have Dragon Ball Z characters in it when it is released. + +17-3 (not finished): +* made bots aim beams. +* made bots charge attacks randomly above the minimum. +* made bots melee. +* made bots act blind when hit with the taiyoken. +* made bots aware of splash damage on charge-up attacks. +* lowered shyogeki ha damage from 20 to 5. +* lowered shyogeki ha range from 8192 to 1200. +* lowered shyogeki ha spread. +* made homing attacks easier to dodge. +* lowered kiaiho range from 8192 to 1000. +* made kiaiho do a stable 20% damage. +* removed the damage boost for ki boosting. +* got rid of the character change messages because they never worked right. +* shrunk the pre-fire deathball a bit so it doesn't clip freeza's head. +* made blindness not last through death. +* got rid of the melee axehandle smash direction. +* fixed a bug in melee that caused a crash. +* lowered hit-stun time from 3 seconds to 2. +* capped self-splash at 20%. +* added in the separate kienzan attack shader. +* shrunk freeza's kienzan. +* fixed a bug that made the kienzans stay around far longer than they should. +* fixed a bug that made kienzans hit way too fast and too often. +* gave the kienzans a max number of hits, which fixes a memory leak. +* fixed a bug with the animation timers. +* fixed a bug with switching weapons while firing a beam. +* fixed a bug with switching weapons while charging up an attack. +* made charging only prevent intentional movement, not glue you in place. + +17-2: +* made bots be 100% agressive all the time. +* made bots fly a better. +* taught bots how to use charge-up attacks and beams. +* fixed bot aim. +* upped the charge time for the chobakuretsumaha and sokidan. +* scaled down the pre-fire flashes of most attacks. +* fixed the spelling and grammer in the bot files and fixed the error messages. + +17-1: +* redid third person view. +* got around the gimble lock for flight so you can go upside down. +* changed default cg_thirdpersonheight to -50. + + + + +# more sutff than you wanted - 11/29/2000 by Yrgol + +16-3/17: +* fixed the timing of the "ready" message with the kamehameha. +* made a bfp.cfg file so that bfp will work fine by using the mods menu. +* fixed a bug that caused untextured weapon flashes to appear. +* fixed a bug that caused attack voices to sometimes come out at the wrong time. +* added cg_stfu to turn the voices off. +* fixed a bug that made melee mess up charge-up attacks. +* fixed a bug that caused a lot of problems in the char select screen. +* fixed a bug that made melee screw up the weapon time and hit way too fast. +* fixed a bug that made the charge-o-meter misread the sokidan/chobakuretsumaha power. +* fixed another bug with the ready message. +* added cull disable to all the explosion shaders so they don't disappear when you get too close. +* added an explosion shell/shockwave. can be turned off with cg_explosionShell 0. +* added cg_lowpolysphere to toggle between a low and a high polycount sphere model. +* fixed the infamous death-spawn bug. +* fixed the sizing of the accept button in the video setup menu. +* seemingly accidentally fixed the problem of ki trails showing through walls. +* made cg_thirdpersonrange and cg_thirdpersonheight get saved in bfp.cfg. +* gave cg_thirdpersonheight a default of 20. +* increased freezabeam explosion radius. +16-2: +* added g_basePL with a slider in the server startup to define starting PL. +* gave the renzoku an alternating firing offset. +* cut chobakuretsumaha damage in half. +* upped the ki cost of the chobakuretsumaha. +* lowered freezabeam damage. +* made melee hit stun not happen when both people are holding melee. +* made homing missiles select a target based on angle instead of distance. +* refined homing angle selection somewhat. +* fixed the sbc spiral so it disappears less often. +* fixed jump (detection and animation). +* made the kienzan stop disappearing when it hits other missiles. +* added self splash damage back in. +* made blocking deflect missiles. +* added in 17's explosion sounds. +* added in character sounds for sbc, kamehameha, final flash, bb attack, masenko. +* hopefully fixed the ride me big boy bug. + +16-1: +* made the spiral not disappear when two people sbc at the same time +* made ki trails a little more robust +* forced r_railCoreWidth to 15 on startup. +* removed a bug with the ssjhead getting an aura when it shouldn't. +* fixed a bug that caused the char select screen to crash the game. +* resized images so they were powers of 2. +* got rid of "unknown gametype" when connecting to a oozaru or lms server. +* homing attacks don't turn all the way around anymore. +* homing attacks no longer lose their velocity when homing. +* tweaked the various homing missile speeds to account for the new code. +* made taiyoken based on FOV, meaning you have to see it to go blind. +* set the size of menu buttons to 80x80 and made those values +settable through one file instead of 30 different files. +* made the eyebeam visible from all perspectives. +* upped the eyebeam damage. +* made the eyebeam not draw when holding melee. +* fixed a rotation problem on the auras. +* fixed a problem with showing the wrong gametype name when starting a server. + +16: +* decreased melee dive range from 2000 to 700. +* hopefully fixed the problem of melee dive teleporting you into objects. +* new menu. +* new attack icons. +* new hud. +* new ki trail. +* fixed the servers menu to differentiate between bfp gametypes. +* removed the "impressive" for the freezabeam. +* lowered the ki cost of the freezabeam from 1000 to 500. +* made the freezabeam explode when it hits a player instead of going through them. +* gave the freezabeam explosion some damage. +* changed the sound played for the freezabeam. +* fixed a bug in the eyebeam that made the beam not show up. +* changed the name of the sbc to makankosappo. +* removed drowning. +* made the speed boost depend on PL instead of power tier. +* made cg_kitrail be a slider var from 0 to 99 for ki trail length. + +15-8: +* removed heals from spawning on maps. +* increased visual explosion size. +* made charging a lot more effective. +* cut damage in half. +* made melee dive a lot more solid. +* gave the melee hit sound an origin. + +15-7: +* made the chargeup alert display in third person +* moved the chargeup alert to the bottom of the screen. +* plays the pain sounds based on percent of max health. +* upped masenko damage. +* made the hud player counter not include dead people. +* removed gibs for killing someone. you can still gib a corpse. +* made the prepare anim play for kakusan. +* fixed the timing on at least some charge up attack anims. +* added a flash model to firing beams. +* added KamehamehaFlashShader etc for the beam attacks. +this shader needs to be opaque enough to hide the beam origin +* scaled down the pre-fire ball for beam attacks. +* removed the standard flash entirely. + +15-6: +* added a "ready to fire" message for charge-up attacks. +* added cg_chargeupAlert to turn off that message. +* fixed a bug that would let attacks get kienzan properties. +* upped kakusan damage some. +* lowered taiyoken damage to 1%. +* added a visibility check on taiyoken. only checks barriers, not direction. +* increased taiyoken chargeup time. +* shortened blindness time some. +* made the melee_axehandle animation run, but it's not very noticable. +* toned down the angry gohan. +* made the prepare anim play for the angry gohan. +* changed the scoreboard name of the angry gohan to the Angry Gohan Attack. +* fixed "the incredible eternal kienzan" bug. + +15-5: +* first person vis mode works. it works best with models that have tag_eyes (gohan/krillin). +* angry gohan no longer draws while meleeing or charging. +* took out the announcer sounds for player names. +* blindness no longer stays with you through death. +* took out the ring model for explosions on players. +* fixed a scaling problem in the explosion ring that made it go black. +* removed the eject brass option from the game options menu. +* individual score now survives death in LMS mode. +* following in LMS spectator mode no longer fucks the next round. +* got rid of some red in the menu. +* gave explosions and missiles dynamic lights. +* added cg_lightExplosions to turn off dynamic explosion lights. +* removed the chargeup anim for taiyoken. + +15-4: lost all code since 15, had to redo stuff. +--SHADERS-- +* added shaders for kamehameha and masenko. +* added separate beam shaders. +* added separate shaders for explosions. +* added a shader for the freezabeam explosion +--WEAPONS-- +* freeza's second attack no longer ejects brass. +* fixed manual beam detonation. +* missiles should collide with each other a bit better. +* fixed homing attack collisions. +* increased eye beam range. +* removed self-damage. +* gave deathball a min charge up time (it was supposed to have one). +* gave masenko a min charge up time (it was supposed to have one). +* decreased the chargeup speed of sokidan/chobakuretsumaha. +* made all weapons explode when they hit a player. +* put the BIG BANG in the BIG BANG attack +* pumped up the deathball. +* can't continue firing a beam while charging, blocking, +melee fighting, or in hit-stun. +* beam attacks use the sphere as the pre-fire flash. +* beams now trump missiles for mid-air collisions. +* lowered renzoku damage. +* made taiyoken work. +* gave the SBC a spiral trail. +* weapon firing sound plays while firing beams instead of +while charging them. +* made the freeza beam red and gave it an explosion. +* gave explosions a smoke ring. +--OTHER-- +* custom skins now work fine. if you use a custom +vegeta skin that I don't have, instead of showing +up as sarge you will show up as vegeta/default on +my screen. +* somewhat improved bots. +* cg_forceModel removed. +* added cg_forceSkin to force the default skin for each model. +* changed obituary messages. +* beam attacks no longer blind you in first person view. +* switched from the nuke model to the sphere model for explosions. +* tweaked explosions a lot. +* picking up a normal health after a mega health won't set +you back to 100% health anymore. +* no longer plays the melee sound for missiles. +* unfucked spectator mode. +* switching chars while in LMS mode causes a suicide like in +any other game mode. From f2578ce053cf766e7a533dcd5febd96144a6b3a0 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sat, 26 Oct 2024 02:16:04 +0200 Subject: [PATCH 123/374] cgame: Fix when shell and ring explosions are disabled and their effects are NULL --- source/cgame/cg_effects.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/source/cgame/cg_effects.c b/source/cgame/cg_effects.c index 8b1e15d..a646910 100644 --- a/source/cgame/cg_effects.c +++ b/source/cgame/cg_effects.c @@ -762,21 +762,25 @@ void CG_ExplosionEffect( vec3_t origin, vec3_t dir ) { // BFP - Explosion effect VectorScale( leSphere->refEntity.axis[1], scale, leSphere->refEntity.axis[1] ); VectorScale( leSphere->refEntity.axis[2], scale, leSphere->refEntity.axis[2] ); - if ( explosionRingScaleFactor > MAX_SCALEFACTOR ) explosionRingScaleFactor = MAX_SCALEFACTOR; - if ( explosionRingScaleFactorChargeMult > MAX_SCALEFACTOR ) explosionRingScaleFactorChargeMult = MAX_SCALEFACTOR; - scale = explosionRingScaleFactor + explosionRingScaleFactorChargeMult * numPointsChargedOverMin; - if ( scale > MAX_SCALE ) scale = MAX_SCALE; - VectorScale( leRing->refEntity.axis[0], scale, leRing->refEntity.axis[0] ); - VectorScale( leRing->refEntity.axis[1], scale, leRing->refEntity.axis[1] ); - VectorScale( leRing->refEntity.axis[2], scale, leRing->refEntity.axis[2] ); + if ( cg_explosionRing.integer > 0 ) { + if ( explosionRingScaleFactor > MAX_SCALEFACTOR ) explosionRingScaleFactor = MAX_SCALEFACTOR; + if ( explosionRingScaleFactorChargeMult > MAX_SCALEFACTOR ) explosionRingScaleFactorChargeMult = MAX_SCALEFACTOR; + scale = explosionRingScaleFactor + explosionRingScaleFactorChargeMult * numPointsChargedOverMin; + if ( scale > MAX_SCALE ) scale = MAX_SCALE; + VectorScale( leRing->refEntity.axis[0], scale, leRing->refEntity.axis[0] ); + VectorScale( leRing->refEntity.axis[1], scale, leRing->refEntity.axis[1] ); + VectorScale( leRing->refEntity.axis[2], scale, leRing->refEntity.axis[2] ); + } - if ( explosionShellScaleFactor > MAX_SCALEFACTOR ) explosionShellScaleFactor = MAX_SCALEFACTOR; - if ( explosionShellScaleFactorChargeMult > MAX_SCALEFACTOR ) explosionShellScaleFactorChargeMult = MAX_SCALEFACTOR; - scale = explosionShellScaleFactor + explosionShellScaleFactorChargeMult * numPointsChargedOverMin; - if ( scale > MAX_SCALE ) scale = MAX_SCALE; - VectorScale( leShell->refEntity.axis[0], scale, leShell->refEntity.axis[0] ); - VectorScale( leShell->refEntity.axis[1], scale, leShell->refEntity.axis[1] ); - VectorScale( leShell->refEntity.axis[2], scale, leShell->refEntity.axis[2] ); + if ( cg_explosionShell.integer > 0 ) { + if ( explosionShellScaleFactor > MAX_SCALEFACTOR ) explosionShellScaleFactor = MAX_SCALEFACTOR; + if ( explosionShellScaleFactorChargeMult > MAX_SCALEFACTOR ) explosionShellScaleFactorChargeMult = MAX_SCALEFACTOR; + scale = explosionShellScaleFactor + explosionShellScaleFactorChargeMult * numPointsChargedOverMin; + if ( scale > MAX_SCALE ) scale = MAX_SCALE; + VectorScale( leShell->refEntity.axis[0], scale, leShell->refEntity.axis[0] ); + VectorScale( leShell->refEntity.axis[1], scale, leShell->refEntity.axis[1] ); + VectorScale( leShell->refEntity.axis[2], scale, leShell->refEntity.axis[2] ); + } } // BFP - Apply dynamic explosion light values From 685a9234284c7290c0917af467b73dc48960d9be Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sun, 27 Oct 2024 00:21:37 +0200 Subject: [PATCH 124/374] q3_ui: Remove redundant code on g_servertype check inside ArenaServers_SetType function --- source/q3_ui/ui_servers2.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/source/q3_ui/ui_servers2.c b/source/q3_ui/ui_servers2.c index 645ec9e..260af1f 100644 --- a/source/q3_ui/ui_servers2.c +++ b/source/q3_ui/ui_servers2.c @@ -1124,14 +1124,11 @@ ArenaServers_SetType int ArenaServers_SetType( int type ) // BFP - Hacky way to get the correct server type :P { int value; // BFP - Return the correct value in order to select server type -#if ENABLE_MPLAYER - g_servertype = value = type; // BFP - Let's go! value, you too! -#else // Q3 default +#if ( !ENABLE_MPLAYER ) /* Q3 default */ if (g_servertype == type) return type; - - g_servertype = value = type; // BFP - Let's go! value, you too! #endif + g_servertype = value = type; // BFP - Let's go! value, you too! switch( type ) { default: From 6126b05b67783e4d0e18eab2f434f9ddb4616542 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Sun, 27 Oct 2024 00:22:40 +0200 Subject: [PATCH 125/374] q3_ui: Add Big Explosions and explosion shell options (these existed on RC/beta versions), add explosion smoke and ring options and upgrade BFP OPTIONS menu by dividing it into 3 sections to prevent options from going off the screen --- source/q3_ui/ui_bfpoptions.c | 609 ++++++++++++++++++++++++----------- 1 file changed, 413 insertions(+), 196 deletions(-) diff --git a/source/q3_ui/ui_bfpoptions.c b/source/q3_ui/ui_bfpoptions.c index bac99cb..c79e2a4 100644 --- a/source/q3_ui/ui_bfpoptions.c +++ b/source/q3_ui/ui_bfpoptions.c @@ -15,7 +15,8 @@ BFP OPTIONS MENU #define ART_MENUBG "menu/art/menubg" #define ART_BARLOG "menu/art/cap_barlog" -#define BFPOPTIONS_X_POS 360 +#define BFPOPTIONS_X_POS 450 +#define BFPOPTIONS_SECTION_Y (BIGCHAR_HEIGHT * 2) #define ID_AURATYPE 138 #define ID_EXPLOTYPE 139 @@ -38,7 +39,14 @@ BFP OPTIONS MENU #define ID_DEFAULTSKINS 156 #define ID_STFU 157 #define ID_LOWPOLYSPHERE 158 -#define ID_BACK 159 +#define ID_BIGEXPLOSIONS 159 +#define ID_EXPLOSIONSHELL 160 +#define ID_EXPLOSIONSMOKE 161 +#define ID_EXPLOSIONRING 162 +#define ID_BACK 163 +#define ID_AURASCONFIG 164 +#define ID_EXPLOSIONSCONFIG 165 +#define ID_VIEWEFFSNDCONFIG 166 // Macros to handle the cases in that order #define SPRITE_AURA 0 @@ -84,6 +92,10 @@ typedef struct { menubitmap_s barlog; menutext_s banner; + menutext_s aurasButton; + menutext_s explosionsButton; + menutext_s viewEffectsSoundsButton; + menulist_s auratype; menulist_s explotype; menulist_s viewpoint; @@ -92,6 +104,10 @@ typedef struct { menuradiobutton_s dynauralight; menuradiobutton_s dynamiclights; menuradiobutton_s dynexplolights; + menuradiobutton_s bigexplosions; + menuradiobutton_s explosionshell; + menuradiobutton_s explosionsmoke; + menuradiobutton_s explosionring; menuslider_s kitrailength; menuslider_s beamcmpxy; menuradiobutton_s transaura; @@ -107,11 +123,16 @@ typedef struct { menuradiobutton_s stfu; menuradiobutton_s lowpolysphere; menubitmap_s back; - } bfpoptions_t; static bfpoptions_t s_bfpoptions; +static int menuBarOption = ID_AURASCONFIG; + +void BFPAuraOptions_MenuInit( void ); +void BFPExplosionsOptions_MenuInit( void ); +void BFPViewEffSndsOptions_MenuInit( void ); + // A macro to look better the code #define BFPOPTIONS_MENUITEM( menu_item_curvalue, cvar ) \ menu_item_curvalue = trap_Cvar_VariableValue( cvar ) != 0; @@ -121,6 +142,10 @@ static void BFPOptions_SetMenuItems( void ) { BFPOPTIONS_MENUITEM( s_bfpoptions.particlesfx.curvalue, "cg_particles" ) BFPOPTIONS_MENUITEM( s_bfpoptions.dynauralight.curvalue, "cg_lightAuras" ) BFPOPTIONS_MENUITEM( s_bfpoptions.dynexplolights.curvalue, "cg_lightExplosions" ) + BFPOPTIONS_MENUITEM( s_bfpoptions.bigexplosions.curvalue, "cg_bigExplosions" ) + BFPOPTIONS_MENUITEM( s_bfpoptions.explosionshell.curvalue, "cg_explosionShell" ) + BFPOPTIONS_MENUITEM( s_bfpoptions.explosionsmoke.curvalue, "cg_explosionSmoke" ) + BFPOPTIONS_MENUITEM( s_bfpoptions.explosionring.curvalue, "cg_explosionRing" ) BFPOPTIONS_MENUITEM( s_bfpoptions.transaura.curvalue, "cg_transformationAura" ) BFPOPTIONS_MENUITEM( s_bfpoptions.smallaura.curvalue, "cg_smallOwnAura" ) BFPOPTIONS_MENUITEM( s_bfpoptions.ssjglow.curvalue, "cg_permaglowUltimate" ) @@ -151,16 +176,60 @@ static void BFPOptions_SetMenuItems( void ) { #define EXPLOTYPE_SETUP(expShell, expSmoke, particles, expRing ) \ trap_Cvar_SetValue( "cg_explosionShell", expShell ); \ trap_Cvar_SetValue( "cg_explosionSmoke", expSmoke ); \ - trap_Cvar_SetValue( "cg_particles", particles ); \ trap_Cvar_SetValue( "cg_explosionRing", expRing ); \ + trap_Cvar_SetValue( "cg_particles", particles ); \ + s_bfpoptions.explosionshell.curvalue = expShell; \ + s_bfpoptions.explosionsmoke.curvalue = expSmoke; \ + s_bfpoptions.explosionring.curvalue = expRing; \ s_bfpoptions.particlesfx.curvalue = particles; +static void BFPOptions_ExplosionsTypeCheck( void ) { + int particles = s_bfpoptions.particlesfx.curvalue; + int explosionSmoke = s_bfpoptions.explosionsmoke.curvalue; + int explosionShell = s_bfpoptions.explosionshell.curvalue; + int explosionRing = s_bfpoptions.explosionring.curvalue; + + if ( particles <= 0 && explosionSmoke <= 0 && explosionShell <= 0 && explosionRing <= 0 ) { + s_bfpoptions.explotype.curvalue = WIMPY_EXPLO; + } + if ( particles <= 0 && explosionSmoke <= 0 && explosionShell >= 1 && explosionRing >= 1 ) { + s_bfpoptions.explotype.curvalue = WEAK_EXPLO; + } + if ( particles >= 1 && explosionSmoke <= 0 && explosionShell >= 1 && explosionRing >= 1 ) { + s_bfpoptions.explotype.curvalue = SO_SO_EXPLO; + } + if ( particles >= 1 && explosionSmoke >= 1 && explosionShell >= 1 && explosionRing >= 1 ) { + s_bfpoptions.explotype.curvalue = HARDCORE_EXPLO; + } +} + static void BFPOptions_Event( void* ptr, int notification ) { if ( notification != QM_ACTIVATED ) { return; } switch ( ((menucommon_s*)ptr)->id ) { + //---------------------------Show options---------------------------------// + case ID_AURASCONFIG: + if ( menuBarOption != ID_AURASCONFIG ) { + menuBarOption = ID_AURASCONFIG; + BFPAuraOptions_MenuInit(); + } + break; + + case ID_EXPLOSIONSCONFIG: + if ( menuBarOption != ID_EXPLOSIONSCONFIG ) { + menuBarOption = ID_EXPLOSIONSCONFIG; + BFPExplosionsOptions_MenuInit(); + } + break; + + case ID_VIEWEFFSNDCONFIG: + if ( menuBarOption != ID_VIEWEFFSNDCONFIG ) { + menuBarOption = ID_VIEWEFFSNDCONFIG; + BFPViewEffSndsOptions_MenuInit(); + } + break; //-----------------------------Aura list---------------------------------// @@ -240,6 +309,7 @@ static void BFPOptions_Event( void* ptr, int notification ) { case ID_PARTICLESFX: trap_Cvar_SetValue( "cg_particles", s_bfpoptions.particlesfx.curvalue ); + BFPOptions_ExplosionsTypeCheck(); break; case ID_DYNAURALIGHT: @@ -250,6 +320,25 @@ static void BFPOptions_Event( void* ptr, int notification ) { trap_Cvar_SetValue( "cg_lightExplosions", s_bfpoptions.dynexplolights.curvalue ); break; + case ID_BIGEXPLOSIONS: + trap_Cvar_SetValue( "cg_bigExplosions", s_bfpoptions.bigexplosions.curvalue ); + break; + + case ID_EXPLOSIONSHELL: + trap_Cvar_SetValue( "cg_explosionShell", s_bfpoptions.explosionshell.curvalue ); + BFPOptions_ExplosionsTypeCheck(); + break; + + case ID_EXPLOSIONSMOKE: + trap_Cvar_SetValue( "cg_explosionSmoke", s_bfpoptions.explosionsmoke.curvalue ); + BFPOptions_ExplosionsTypeCheck(); + break; + + case ID_EXPLOSIONRING: + trap_Cvar_SetValue( "cg_explosionRing", s_bfpoptions.explosionring.curvalue ); + BFPOptions_ExplosionsTypeCheck(); + break; + //----------------------------Sliders------------------------------------// @@ -318,26 +407,9 @@ static void BFPOptions_Event( void* ptr, int notification ) { break; } } -#undef AURATYPE_SETUP -#undef VIEWPOINT_SETUP -#undef EXPLOTYPE_SETUP - - -static void BFPOptions_MenuInit( void ) { - int y; - int highpolyaura, polygonalaura, lightweightaura, spriteaura, particleaura; - int thirdperson, firstpersonvis; - int explosionShell, explosionSmoke; - int explosionring; - int particles; - - memset( &s_bfpoptions, 0, sizeof(bfpoptions_t) ); - BFPOptions_Cache(); - - s_bfpoptions.menu.wrapAround = qtrue; - s_bfpoptions.menu.fullscreen = qtrue; +static void BFPBarBackground_MenuSet( void ) { s_bfpoptions.menubg.generic.type = MTYPE_BITMAP; s_bfpoptions.menubg.generic.name = ART_MENUBG; s_bfpoptions.menubg.generic.flags = QMF_LEFT_JUSTIFY|QMF_INACTIVE; @@ -362,33 +434,289 @@ static void BFPOptions_MenuInit( void ) { s_bfpoptions.banner.color = color_white; s_bfpoptions.banner.style = UI_CENTER|UI_BIGFONT; - y = 90; + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.menubg ); + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.barlog ); + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.banner ); +} + +static void BFPButtonOptions_MenuSet( void ) { + BFPBarBackground_MenuSet(); + + s_bfpoptions.aurasButton.generic.type = MTYPE_PTEXT; + s_bfpoptions.aurasButton.generic.flags = ( menuBarOption == ID_AURASCONFIG ) ? QMF_RIGHT_JUSTIFY : (QMF_RIGHT_JUSTIFY|QMF_PULSEIFFOCUS); + s_bfpoptions.aurasButton.generic.id = ID_AURASCONFIG; + s_bfpoptions.aurasButton.generic.callback = BFPOptions_Event; + s_bfpoptions.aurasButton.generic.x = 216; + s_bfpoptions.aurasButton.generic.y = 240 - 2 * PROP_HEIGHT; + s_bfpoptions.aurasButton.string = "AURAS"; + s_bfpoptions.aurasButton.style = UI_RIGHT; + s_bfpoptions.aurasButton.color = color_white; + + s_bfpoptions.explosionsButton.generic.type = MTYPE_PTEXT; + s_bfpoptions.explosionsButton.generic.flags = ( menuBarOption == ID_EXPLOSIONSCONFIG ) ? QMF_RIGHT_JUSTIFY : (QMF_RIGHT_JUSTIFY|QMF_PULSEIFFOCUS); + s_bfpoptions.explosionsButton.generic.id = ID_EXPLOSIONSCONFIG; + s_bfpoptions.explosionsButton.generic.callback = BFPOptions_Event; + s_bfpoptions.explosionsButton.generic.x = 216; + s_bfpoptions.explosionsButton.generic.y = 240 - PROP_HEIGHT; + s_bfpoptions.explosionsButton.string = "EXPLOSIONS"; + s_bfpoptions.explosionsButton.style = UI_RIGHT; + s_bfpoptions.explosionsButton.color = color_white; + + s_bfpoptions.viewEffectsSoundsButton.generic.type = MTYPE_PTEXT; + s_bfpoptions.viewEffectsSoundsButton.generic.flags = ( menuBarOption == ID_VIEWEFFSNDCONFIG ) ? QMF_RIGHT_JUSTIFY : (QMF_RIGHT_JUSTIFY|QMF_PULSEIFFOCUS); + s_bfpoptions.viewEffectsSoundsButton.generic.id = ID_VIEWEFFSNDCONFIG; + s_bfpoptions.viewEffectsSoundsButton.generic.callback = BFPOptions_Event; + s_bfpoptions.viewEffectsSoundsButton.generic.x = 216; + s_bfpoptions.viewEffectsSoundsButton.generic.y = 240; + s_bfpoptions.viewEffectsSoundsButton.string = "VIEW & FX"; + s_bfpoptions.viewEffectsSoundsButton.style = UI_RIGHT; + s_bfpoptions.viewEffectsSoundsButton.color = color_white; + + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.aurasButton ); + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.explosionsButton ); + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.viewEffectsSoundsButton ); +} + + +void BFPAuraOptions_MenuInit( void ) { + int y; + int highpolyaura, polygonalaura, lightweightaura, spriteaura, particleaura; + + memset( &s_bfpoptions, 0, sizeof(bfpoptions_t) ); + + BFPOptions_Cache(); + + s_bfpoptions.menu.wrapAround = qtrue; + s_bfpoptions.menu.fullscreen = qtrue; + + y = 240 - 3 * (BIGCHAR_HEIGHT+2); s_bfpoptions.auratype.generic.type = MTYPE_SPINCONTROL; s_bfpoptions.auratype.generic.name = "Aura Type:"; s_bfpoptions.auratype.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; s_bfpoptions.auratype.generic.callback = BFPOptions_Event; s_bfpoptions.auratype.generic.id = ID_AURATYPE; - s_bfpoptions.auratype.generic.x = 320; + s_bfpoptions.auratype.generic.x = BFPOPTIONS_X_POS-130; s_bfpoptions.auratype.generic.y = y; s_bfpoptions.auratype.itemnames = auratype_items; y += BIGCHAR_HEIGHT + 2; + s_bfpoptions.dynauralight.generic.type = MTYPE_RADIOBUTTON; + s_bfpoptions.dynauralight.generic.name = "Dynamic Aura Lights:"; + s_bfpoptions.dynauralight.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; + s_bfpoptions.dynauralight.generic.callback = BFPOptions_Event; + s_bfpoptions.dynauralight.generic.id = ID_DYNAURALIGHT; + s_bfpoptions.dynauralight.generic.x = BFPOPTIONS_X_POS; + s_bfpoptions.dynauralight.generic.y = y; + + y += BIGCHAR_HEIGHT + 2; + s_bfpoptions.transaura.generic.type = MTYPE_RADIOBUTTON; + s_bfpoptions.transaura.generic.name = "Transformation Aura:"; + s_bfpoptions.transaura.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; + s_bfpoptions.transaura.generic.callback = BFPOptions_Event; + s_bfpoptions.transaura.generic.id = ID_TRANSFORMATIONAURA; + s_bfpoptions.transaura.generic.x = BFPOPTIONS_X_POS; + s_bfpoptions.transaura.generic.y = y; + + y += BIGCHAR_HEIGHT + 2; + s_bfpoptions.smallaura.generic.type = MTYPE_RADIOBUTTON; + s_bfpoptions.smallaura.generic.name = "Small Own Aura:"; + s_bfpoptions.smallaura.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; + s_bfpoptions.smallaura.generic.callback = BFPOptions_Event; + s_bfpoptions.smallaura.generic.id = ID_SMALLAURA; + s_bfpoptions.smallaura.generic.x = BFPOPTIONS_X_POS; + s_bfpoptions.smallaura.generic.y = y; + + y += BIGCHAR_HEIGHT + 2; + s_bfpoptions.ssjglow.generic.type = MTYPE_RADIOBUTTON; + s_bfpoptions.ssjglow.generic.name = "SSJ Perma-Glow:"; + s_bfpoptions.ssjglow.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; + s_bfpoptions.ssjglow.generic.callback = BFPOptions_Event; + s_bfpoptions.ssjglow.generic.id = ID_SSJGLOW; + s_bfpoptions.ssjglow.generic.x = BFPOPTIONS_X_POS; + s_bfpoptions.ssjglow.generic.y = y; + + s_bfpoptions.back.generic.type = MTYPE_BITMAP; + s_bfpoptions.back.generic.name = ART_BACK0; + s_bfpoptions.back.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS; + s_bfpoptions.back.generic.callback = BFPOptions_Event; + s_bfpoptions.back.generic.id = ID_BACK; + s_bfpoptions.back.generic.x = 0; + s_bfpoptions.back.generic.y = 480-80; + s_bfpoptions.back.width = 80; + s_bfpoptions.back.height = 80; + s_bfpoptions.back.focuspic = ART_BACK1; + + BFPButtonOptions_MenuSet(); + + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.auratype ); + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.dynauralight ); + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.transaura ); + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.smallaura ); + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.ssjglow ); + + highpolyaura = trap_Cvar_VariableValue( "cg_highPolyAura" ); + polygonalaura = trap_Cvar_VariableValue( "cg_polygonAura" ); + lightweightaura = trap_Cvar_VariableValue( "cg_lightweightAuras" ); + spriteaura = trap_Cvar_VariableValue( "cg_spriteAura" ); + particleaura = trap_Cvar_VariableValue( "cg_particleAura" ); + + if ( highpolyaura >= 1 ) { + s_bfpoptions.auratype.curvalue = HIGHPOLYCOUNT_AURA; + } else if ( polygonalaura >= 1 ) { + s_bfpoptions.auratype.curvalue = POLYGON_AURA; + } else if ( lightweightaura >= 1 ) { + s_bfpoptions.auratype.curvalue = LIGHTWEIGHT_AURA; + } else if ( spriteaura >= 1 ) { + s_bfpoptions.auratype.curvalue = SPRITE_AURA; + } else if ( particleaura >= 1 ) { + s_bfpoptions.auratype.curvalue = PARTICLE_AURA; + } else { + s_bfpoptions.auratype.curvalue = SHADER_AURA; + } + + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.back ); + + BFPOptions_SetMenuItems(); +} + + +void BFPExplosionsOptions_MenuInit( void ) { + int y; + int explosionRing, explosionShell, explosionSmoke; + int particles; + + memset( &s_bfpoptions, 0, sizeof(bfpoptions_t) ); + + BFPOptions_Cache(); + + s_bfpoptions.menu.wrapAround = qtrue; + s_bfpoptions.menu.fullscreen = qtrue; + + y = 240 - 4 * (BIGCHAR_HEIGHT+2); s_bfpoptions.explotype.generic.type = MTYPE_SPINCONTROL; s_bfpoptions.explotype.generic.name = "Explosion Type:"; s_bfpoptions.explotype.generic.flags = QMF_PULSEIFFOCUS | QMF_SMALLFONT; s_bfpoptions.explotype.generic.callback = BFPOptions_Event; s_bfpoptions.explotype.generic.id = ID_EXPLOTYPE; - s_bfpoptions.explotype.generic.x = 320; + s_bfpoptions.explotype.generic.x = BFPOPTIONS_X_POS; s_bfpoptions.explotype.generic.y = y; s_bfpoptions.explotype.itemnames = explotype_items; y += BIGCHAR_HEIGHT + 2; + s_bfpoptions.bigexplosions.generic.type = MTYPE_RADIOBUTTON; + s_bfpoptions.bigexplosions.generic.name = "Big Explosions:"; + s_bfpoptions.bigexplosions.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; + s_bfpoptions.bigexplosions.generic.callback = BFPOptions_Event; + s_bfpoptions.bigexplosions.generic.id = ID_BIGEXPLOSIONS; + s_bfpoptions.bigexplosions.generic.x = BFPOPTIONS_X_POS; + s_bfpoptions.bigexplosions.generic.y = y; + + y += BIGCHAR_HEIGHT + 2; + s_bfpoptions.dynexplolights.generic.type = MTYPE_RADIOBUTTON; + s_bfpoptions.dynexplolights.generic.name = "Dynamic Explosion Lights:"; + s_bfpoptions.dynexplolights.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; + s_bfpoptions.dynexplolights.generic.callback = BFPOptions_Event; + s_bfpoptions.dynexplolights.generic.id = ID_DYNEXPLOLIGHT; + s_bfpoptions.dynexplolights.generic.x = BFPOPTIONS_X_POS; + s_bfpoptions.dynexplolights.generic.y = y; + + y += BIGCHAR_HEIGHT + 2; + s_bfpoptions.lowpolysphere.generic.type = MTYPE_RADIOBUTTON; + s_bfpoptions.lowpolysphere.generic.name = "Low Polycount Sphere:"; + s_bfpoptions.lowpolysphere.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; + s_bfpoptions.lowpolysphere.generic.callback = BFPOptions_Event; + s_bfpoptions.lowpolysphere.generic.id = ID_LOWPOLYSPHERE; + s_bfpoptions.lowpolysphere.generic.x = BFPOPTIONS_X_POS; + s_bfpoptions.lowpolysphere.generic.y = y; + + y += BFPOPTIONS_SECTION_Y; + s_bfpoptions.explosionsmoke.generic.type = MTYPE_RADIOBUTTON; + s_bfpoptions.explosionsmoke.generic.name = "Smoke:"; + s_bfpoptions.explosionsmoke.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; + s_bfpoptions.explosionsmoke.generic.callback = BFPOptions_Event; + s_bfpoptions.explosionsmoke.generic.id = ID_EXPLOSIONSMOKE; + s_bfpoptions.explosionsmoke.generic.x = BFPOPTIONS_X_POS; + s_bfpoptions.explosionsmoke.generic.y = y; + + y += BIGCHAR_HEIGHT + 2; + s_bfpoptions.explosionshell.generic.type = MTYPE_RADIOBUTTON; + s_bfpoptions.explosionshell.generic.name = "Shell:"; + s_bfpoptions.explosionshell.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; + s_bfpoptions.explosionshell.generic.callback = BFPOptions_Event; + s_bfpoptions.explosionshell.generic.id = ID_EXPLOSIONSHELL; + s_bfpoptions.explosionshell.generic.x = BFPOPTIONS_X_POS; + s_bfpoptions.explosionshell.generic.y = y; + + y += BIGCHAR_HEIGHT + 2; + s_bfpoptions.explosionring.generic.type = MTYPE_RADIOBUTTON; + s_bfpoptions.explosionring.generic.name = "Ring:"; + s_bfpoptions.explosionring.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; + s_bfpoptions.explosionring.generic.callback = BFPOptions_Event; + s_bfpoptions.explosionring.generic.id = ID_EXPLOSIONRING; + s_bfpoptions.explosionring.generic.x = BFPOPTIONS_X_POS; + s_bfpoptions.explosionring.generic.y = y; + + s_bfpoptions.back.generic.type = MTYPE_BITMAP; + s_bfpoptions.back.generic.name = ART_BACK0; + s_bfpoptions.back.generic.flags = QMF_LEFT_JUSTIFY|QMF_PULSEIFFOCUS; + s_bfpoptions.back.generic.callback = BFPOptions_Event; + s_bfpoptions.back.generic.id = ID_BACK; + s_bfpoptions.back.generic.x = 0; + s_bfpoptions.back.generic.y = 480-80; + s_bfpoptions.back.width = 80; + s_bfpoptions.back.height = 80; + s_bfpoptions.back.focuspic = ART_BACK1; + + BFPButtonOptions_MenuSet(); + + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.explotype ); + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.bigexplosions ); + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.dynexplolights ); + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.lowpolysphere ); + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.explosionsmoke ); + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.explosionshell ); + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.explosionring ); + + explosionSmoke = trap_Cvar_VariableValue( "cg_explosionSmoke" ); + explosionShell = trap_Cvar_VariableValue( "cg_explosionShell" ); + explosionRing = trap_Cvar_VariableValue( "cg_explosionRing" ); + particles = trap_Cvar_VariableValue( "cg_particles" ); + + s_bfpoptions.bigexplosions.curvalue = trap_Cvar_VariableValue( "cg_bigExplosions" ); + s_bfpoptions.explosionsmoke.curvalue = explosionSmoke; + s_bfpoptions.explosionshell.curvalue = explosionShell; + s_bfpoptions.explosionring.curvalue = explosionRing; + + s_bfpoptions.particlesfx.curvalue = particles; + + BFPOptions_ExplosionsTypeCheck(); + + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.back ); + + BFPOptions_SetMenuItems(); +} + + +void BFPViewEffSndsOptions_MenuInit( void ) { + int y; + int thirdperson, firstpersonvis; + int particles; + + memset( &s_bfpoptions, 0, sizeof(bfpoptions_t) ); + + BFPOptions_Cache(); + + s_bfpoptions.menu.wrapAround = qtrue; + s_bfpoptions.menu.fullscreen = qtrue; + + // -------------------------------View & HUD--------------------------------- + y = 240 - 7 * (BIGCHAR_HEIGHT+2); s_bfpoptions.viewpoint.generic.type = MTYPE_SPINCONTROL; s_bfpoptions.viewpoint.generic.name = "Viewpoint:"; s_bfpoptions.viewpoint.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; s_bfpoptions.viewpoint.generic.callback = BFPOptions_Event; s_bfpoptions.viewpoint.generic.id = ID_VIEWPOINT; - s_bfpoptions.viewpoint.generic.x = 320; + s_bfpoptions.viewpoint.generic.x = BFPOPTIONS_X_POS; s_bfpoptions.viewpoint.generic.y = y; s_bfpoptions.viewpoint.itemnames = viewpoint_items; @@ -402,6 +730,35 @@ static void BFPOptions_MenuInit( void ) { s_bfpoptions.fix3person.generic.y = y; y += BIGCHAR_HEIGHT + 2; + s_bfpoptions.simplehud.generic.type = MTYPE_RADIOBUTTON; + s_bfpoptions.simplehud.generic.name = "Simple HUD:"; + s_bfpoptions.simplehud.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; + s_bfpoptions.simplehud.generic.callback = BFPOptions_Event; + s_bfpoptions.simplehud.generic.id = ID_SIMPLEHUD; + s_bfpoptions.simplehud.generic.x = BFPOPTIONS_X_POS; + s_bfpoptions.simplehud.generic.y = y; + + y += BIGCHAR_HEIGHT + 2; + s_bfpoptions.flightilt.generic.type = MTYPE_RADIOBUTTON; + s_bfpoptions.flightilt.generic.name = "Flight Tilt:"; + s_bfpoptions.flightilt.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; + s_bfpoptions.flightilt.generic.callback = BFPOptions_Event; + s_bfpoptions.flightilt.generic.id = ID_FLIGHTILT; + s_bfpoptions.flightilt.generic.x = BFPOPTIONS_X_POS; + s_bfpoptions.flightilt.generic.y = y; + + y += BIGCHAR_HEIGHT + 2; + s_bfpoptions.accucrosshair.generic.type = MTYPE_RADIOBUTTON; + s_bfpoptions.accucrosshair.generic.name = "Accurate Crosshair:"; + s_bfpoptions.accucrosshair.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; + s_bfpoptions.accucrosshair.generic.callback = BFPOptions_Event; + s_bfpoptions.accucrosshair.generic.id = ID_ACCUCROSSHAIR; + s_bfpoptions.accucrosshair.generic.x = BFPOPTIONS_X_POS; + s_bfpoptions.accucrosshair.generic.y = y; + + + // -------------------------------Effects--------------------------------- + y += BFPOPTIONS_SECTION_Y; s_bfpoptions.particlesfx.generic.type = MTYPE_RADIOBUTTON; s_bfpoptions.particlesfx.generic.name = "Particle Effects:"; s_bfpoptions.particlesfx.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; @@ -410,24 +767,6 @@ static void BFPOptions_MenuInit( void ) { s_bfpoptions.particlesfx.generic.x = BFPOPTIONS_X_POS; s_bfpoptions.particlesfx.generic.y = y; - y += BIGCHAR_HEIGHT + 2; - s_bfpoptions.dynauralight.generic.type = MTYPE_RADIOBUTTON; - s_bfpoptions.dynauralight.generic.name = "Dynamic Aura Lights:"; - s_bfpoptions.dynauralight.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; - s_bfpoptions.dynauralight.generic.callback = BFPOptions_Event; - s_bfpoptions.dynauralight.generic.id = ID_DYNAURALIGHT; - s_bfpoptions.dynauralight.generic.x = BFPOPTIONS_X_POS; - s_bfpoptions.dynauralight.generic.y = y; - - y += BIGCHAR_HEIGHT + 2; - s_bfpoptions.dynexplolights.generic.type = MTYPE_RADIOBUTTON; - s_bfpoptions.dynexplolights.generic.name = "Dynamic Explosion Lights:"; - s_bfpoptions.dynexplolights.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; - s_bfpoptions.dynexplolights.generic.callback = BFPOptions_Event; - s_bfpoptions.dynexplolights.generic.id = ID_DYNEXPLOLIGHT; - s_bfpoptions.dynexplolights.generic.x = BFPOPTIONS_X_POS; - s_bfpoptions.dynexplolights.generic.y = y; - y += BIGCHAR_HEIGHT + 2; s_bfpoptions.kitrailength.generic.type = MTYPE_SLIDER; s_bfpoptions.kitrailength.generic.name = "Ki Trail Length:"; @@ -450,78 +789,6 @@ static void BFPOptions_MenuInit( void ) { s_bfpoptions.beamcmpxy.minvalue = 0; s_bfpoptions.beamcmpxy.maxvalue = 100; - y += BIGCHAR_HEIGHT + 2; - s_bfpoptions.transaura.generic.type = MTYPE_RADIOBUTTON; - s_bfpoptions.transaura.generic.name = "Transformation Aura:"; - s_bfpoptions.transaura.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; - s_bfpoptions.transaura.generic.callback = BFPOptions_Event; - s_bfpoptions.transaura.generic.id = ID_TRANSFORMATIONAURA; - s_bfpoptions.transaura.generic.x = BFPOPTIONS_X_POS; - s_bfpoptions.transaura.generic.y = y; - - y += BIGCHAR_HEIGHT + 2; - s_bfpoptions.smallaura.generic.type = MTYPE_RADIOBUTTON; - s_bfpoptions.smallaura.generic.name = "Small Own Aura:"; - s_bfpoptions.smallaura.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; - s_bfpoptions.smallaura.generic.callback = BFPOptions_Event; - s_bfpoptions.smallaura.generic.id = ID_SMALLAURA; - s_bfpoptions.smallaura.generic.x = BFPOPTIONS_X_POS; - s_bfpoptions.smallaura.generic.y = y; - - y += BIGCHAR_HEIGHT + 2; - s_bfpoptions.ssjglow.generic.type = MTYPE_RADIOBUTTON; - s_bfpoptions.ssjglow.generic.name = "SSJ Perma-Glow:"; - s_bfpoptions.ssjglow.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; - s_bfpoptions.ssjglow.generic.callback = BFPOptions_Event; - s_bfpoptions.ssjglow.generic.id = ID_SSJGLOW; - s_bfpoptions.ssjglow.generic.x = BFPOPTIONS_X_POS; - s_bfpoptions.ssjglow.generic.y = y; - - y += BIGCHAR_HEIGHT + 2; - s_bfpoptions.accucrosshair.generic.type = MTYPE_RADIOBUTTON; - s_bfpoptions.accucrosshair.generic.name = "Accurate Crosshair:"; - s_bfpoptions.accucrosshair.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; - s_bfpoptions.accucrosshair.generic.callback = BFPOptions_Event; - s_bfpoptions.accucrosshair.generic.id = ID_ACCUCROSSHAIR; - s_bfpoptions.accucrosshair.generic.x = BFPOPTIONS_X_POS; - s_bfpoptions.accucrosshair.generic.y = y; - - y += BIGCHAR_HEIGHT + 2; - s_bfpoptions.simplehud.generic.type = MTYPE_RADIOBUTTON; - s_bfpoptions.simplehud.generic.name = "Simple HUD:"; - s_bfpoptions.simplehud.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; - s_bfpoptions.simplehud.generic.callback = BFPOptions_Event; - s_bfpoptions.simplehud.generic.id = ID_SIMPLEHUD; - s_bfpoptions.simplehud.generic.x = BFPOPTIONS_X_POS; - s_bfpoptions.simplehud.generic.y = y; - - y += BIGCHAR_HEIGHT + 2; - s_bfpoptions.chargealert.generic.type = MTYPE_RADIOBUTTON; - s_bfpoptions.chargealert.generic.name = "Chargeup Alerts:"; - s_bfpoptions.chargealert.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; - s_bfpoptions.chargealert.generic.callback = BFPOptions_Event; - s_bfpoptions.chargealert.generic.id = ID_CHARGEALERT; - s_bfpoptions.chargealert.generic.x = BFPOPTIONS_X_POS; - s_bfpoptions.chargealert.generic.y = y; - - y += BIGCHAR_HEIGHT + 2; - s_bfpoptions.q3hitsfx.generic.type = MTYPE_RADIOBUTTON; - s_bfpoptions.q3hitsfx.generic.name = "Q3 Hit Sound:"; - s_bfpoptions.q3hitsfx.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; - s_bfpoptions.q3hitsfx.generic.callback = BFPOptions_Event; - s_bfpoptions.q3hitsfx.generic.id = ID_Q3HITSFX; - s_bfpoptions.q3hitsfx.generic.x = BFPOPTIONS_X_POS; - s_bfpoptions.q3hitsfx.generic.y = y; - - y += BIGCHAR_HEIGHT + 2; - s_bfpoptions.flightilt.generic.type = MTYPE_RADIOBUTTON; - s_bfpoptions.flightilt.generic.name = "Flight Tilt:"; - s_bfpoptions.flightilt.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; - s_bfpoptions.flightilt.generic.callback = BFPOptions_Event; - s_bfpoptions.flightilt.generic.id = ID_FLIGHTILT; - s_bfpoptions.flightilt.generic.x = BFPOPTIONS_X_POS; - s_bfpoptions.flightilt.generic.y = y; - y += BIGCHAR_HEIGHT + 2; s_bfpoptions.bigheads.generic.type = MTYPE_RADIOBUTTON; s_bfpoptions.bigheads.generic.name = "Superdeformed Heads:"; @@ -540,7 +807,9 @@ static void BFPOptions_MenuInit( void ) { s_bfpoptions.defaultskins.generic.x = BFPOPTIONS_X_POS; s_bfpoptions.defaultskins.generic.y = y; - y += BIGCHAR_HEIGHT + 2; + + // -------------------------------Sounds--------------------------------- + y += BFPOPTIONS_SECTION_Y; s_bfpoptions.stfu.generic.type = MTYPE_RADIOBUTTON; s_bfpoptions.stfu.generic.name = "Disable Voices:"; s_bfpoptions.stfu.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; @@ -550,13 +819,22 @@ static void BFPOptions_MenuInit( void ) { s_bfpoptions.stfu.generic.y = y; y += BIGCHAR_HEIGHT + 2; - s_bfpoptions.lowpolysphere.generic.type = MTYPE_RADIOBUTTON; - s_bfpoptions.lowpolysphere.generic.name = "Low Polycount Sphere:"; - s_bfpoptions.lowpolysphere.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; - s_bfpoptions.lowpolysphere.generic.callback = BFPOptions_Event; - s_bfpoptions.lowpolysphere.generic.id = ID_LOWPOLYSPHERE; - s_bfpoptions.lowpolysphere.generic.x = BFPOPTIONS_X_POS; - s_bfpoptions.lowpolysphere.generic.y = y; + s_bfpoptions.chargealert.generic.type = MTYPE_RADIOBUTTON; + s_bfpoptions.chargealert.generic.name = "Chargeup Alerts:"; + s_bfpoptions.chargealert.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; + s_bfpoptions.chargealert.generic.callback = BFPOptions_Event; + s_bfpoptions.chargealert.generic.id = ID_CHARGEALERT; + s_bfpoptions.chargealert.generic.x = BFPOPTIONS_X_POS; + s_bfpoptions.chargealert.generic.y = y; + + y += BIGCHAR_HEIGHT + 2; + s_bfpoptions.q3hitsfx.generic.type = MTYPE_RADIOBUTTON; + s_bfpoptions.q3hitsfx.generic.name = "Q3 Hit Sound:"; + s_bfpoptions.q3hitsfx.generic.flags = QMF_PULSEIFFOCUS|QMF_SMALLFONT; + s_bfpoptions.q3hitsfx.generic.callback = BFPOptions_Event; + s_bfpoptions.q3hitsfx.generic.id = ID_Q3HITSFX; + s_bfpoptions.q3hitsfx.generic.x = BFPOPTIONS_X_POS; + s_bfpoptions.q3hitsfx.generic.y = y; s_bfpoptions.back.generic.type = MTYPE_BITMAP; s_bfpoptions.back.generic.name = ART_BACK0; @@ -569,74 +847,23 @@ static void BFPOptions_MenuInit( void ) { s_bfpoptions.back.height = 80; s_bfpoptions.back.focuspic = ART_BACK1; - Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.menubg ); - Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.barlog ); - Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.banner ); + BFPButtonOptions_MenuSet(); - Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.auratype ); - Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.explotype); Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.viewpoint ); Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.fix3person ); - Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.particlesfx ); - Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.dynauralight ); - Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.dynexplolights); - Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.kitrailength); - Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.beamcmpxy); - Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.transaura ); - Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.smallaura ); - Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.ssjglow ); - Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.accucrosshair ); Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.simplehud ); - Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.chargealert ); - Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.q3hitsfx ); Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.flightilt ); + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.accucrosshair ); + + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.particlesfx ); + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.kitrailength ); + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.beamcmpxy ); Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.bigheads ); Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.defaultskins ); - Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.stfu ); - Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.lowpolysphere ); -//----------------------------Auras-------------------------------------// - - highpolyaura = trap_Cvar_VariableValue( "cg_highPolyAura" ); - polygonalaura = trap_Cvar_VariableValue( "cg_polygonAura" ); - lightweightaura = trap_Cvar_VariableValue( "cg_lightweightAuras" ); - spriteaura = trap_Cvar_VariableValue( "cg_spriteAura" ); - particleaura = trap_Cvar_VariableValue( "cg_particleAura" ); - - if ( highpolyaura >= 1 ) { - s_bfpoptions.auratype.curvalue = HIGHPOLYCOUNT_AURA; - } else if ( polygonalaura >= 1 ) { - s_bfpoptions.auratype.curvalue = POLYGON_AURA; - } else if ( lightweightaura >= 1 ) { - s_bfpoptions.auratype.curvalue = LIGHTWEIGHT_AURA; - } else if ( spriteaura >= 1 ) { - s_bfpoptions.auratype.curvalue = SPRITE_AURA; - } else if ( particleaura >= 1 ) { - s_bfpoptions.auratype.curvalue = PARTICLE_AURA; - } else { - s_bfpoptions.auratype.curvalue = SHADER_AURA; - } - -//----------------------------Explosions-------------------------------------// - - explosionSmoke = trap_Cvar_VariableValue( "cg_explosionSmoke" ); - explosionShell = trap_Cvar_VariableValue( "cg_explosionShell" ); - particles = trap_Cvar_VariableValue( "cg_particles" ); - explosionring = trap_Cvar_VariableValue( "cg_explosionRing" ); - - if ( explosionSmoke <= 0 && explosionShell <= 0 && explosionring <= 0 ) { - s_bfpoptions.explotype.curvalue = WIMPY_EXPLO; - } else if ( explosionSmoke >= 1 && explosionring >= 1 ) { - s_bfpoptions.explotype.curvalue = WEAK_EXPLO; - } else if ( explosionSmoke >= 1 && particles >= 1 && explosionring >= 1 ) { - s_bfpoptions.explotype.curvalue = SO_SO_EXPLO; - } else if ( explosionSmoke >= 1 && explosionShell >= 1 && particles >= 1 && explosionring >= 1 ) { - s_bfpoptions.explotype.curvalue = HARDCORE_EXPLO; - } else { - s_bfpoptions.explotype.curvalue = WIMPY_EXPLO; - } - -//----------------------------Camera-------------------------------------// + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.chargealert ); + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.q3hitsfx ); + Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.stfu ); thirdperson = trap_Cvar_VariableValue( "cg_thirdPerson" ); firstpersonvis = trap_Cvar_VariableValue( "cg_drawOwnModel" ); @@ -649,23 +876,12 @@ static void BFPOptions_MenuInit( void ) { s_bfpoptions.viewpoint.curvalue = 1; } -//-----------------------------------------------------------------------// - s_bfpoptions.kitrailength.curvalue = trap_Cvar_VariableValue( "cg_kiTrail" ); s_bfpoptions.beamcmpxy.curvalue = trap_Cvar_VariableValue( "cg_beamTrail" ); Menu_AddItem( &s_bfpoptions.menu, &s_bfpoptions.back ); BFPOptions_SetMenuItems(); } -#undef SPRITE_AURA -#undef SHADER_AURA -#undef LIGHTWEIGHT_AURA -#undef POLYGON_AURA -#undef HIGHPOLYCOUNT_AURA -#undef WIMPY_EXPLO -#undef WEAK_EXPLO -#undef SO_SO_EXPLO -#undef HARDCORE_EXPLO /* @@ -687,6 +903,7 @@ UI_BFPOptionsMenu =============== */ void UI_BFPOptionsMenu( void ) { - BFPOptions_MenuInit(); + menuBarOption = ID_AURASCONFIG; + BFPAuraOptions_MenuInit(); UI_PushMenu( &s_bfpoptions.menu ); } From 9db8343265e02a7f8b1b7a44959972d253be8ef4 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 28 Oct 2024 02:18:26 +0100 Subject: [PATCH 126/374] cgame: Apply fly tilt correctly, clean up third person camera code and some tweaks. Prevent player's head from tilting when that happens --- source/cgame/cg_players.c | 3 ++ source/cgame/cg_view.c | 103 ++++++-------------------------------- 2 files changed, 18 insertions(+), 88 deletions(-) diff --git a/source/cgame/cg_players.c b/source/cgame/cg_players.c index 392a752..4243e63 100644 --- a/source/cgame/cg_players.c +++ b/source/cgame/cg_players.c @@ -1472,6 +1472,9 @@ static void CG_PlayerAngles( centity_t *cent, vec3_t legs[3], vec3_t torso[3], v // --------- roll ------------- + // BFP - Prevent the player's head from tilting + headAngles[ROLL] = 0; + // lean towards the direction of travel VectorCopy( cent->currentState.pos.trDelta, velocity ); speed = VectorNormalize( velocity ); diff --git a/source/cgame/cg_view.c b/source/cgame/cg_view.c index 497c77e..b1e9b90 100644 --- a/source/cgame/cg_view.c +++ b/source/cgame/cg_view.c @@ -225,18 +225,10 @@ static void CG_OffsetThirdPersonView( void ) { trace_t trace; static vec3_t mins = { -4, -4, -4 }; static vec3_t maxs = { 4, 4, 4 }; - // vec3_t focusPoint; // BFP - unused - // float focusDist; // BFP - unused float forwardScale, sideScale; // BFP - Camera setup variables vec3_t overrideOrg; float camAngle, camHeight, camRange; - // BFP - Fly tilt - int cmdNum; - usercmd_t cmd; - // BFP - Last angled for fly tilt angle to move smoothly similar to BFP vanilla - static float lastAngled = 0.0f, lastRightAngled = 0.0f, lastUpAngled = 0.0f; - float rightAngled, upAngled; // BFP - Camera setup camAngle = cg_thirdPersonAngle.value; @@ -249,8 +241,6 @@ static void CG_OffsetThirdPersonView( void ) { } VectorCopy( cg.refdef.vieworg, overrideOrg ); - // cg.refdef.vieworg[2] += cg.predictedPlayerState.viewheight; // BFP - BFP camera position doesn't use that to move to player's height - VectorCopy( cg.refdefViewAngles, focusAngles ); // if dead, look at killer @@ -259,23 +249,10 @@ static void CG_OffsetThirdPersonView( void ) { cg.refdefViewAngles[YAW] = cg.predictedPlayerState.stats[STAT_DEAD_YAW]; } -// BFP - unused check -#if 0 - if ( focusAngles[PITCH] > 45 ) { - focusAngles[PITCH] = 45; // don't go too far overhead - } -#endif - AngleVectors( focusAngles, forward, NULL, NULL ); - // VectorMA( cg.refdef.vieworg, FOCUS_DISTANCE, forward, focusPoint ); // BFP - unused - VectorCopy( cg.refdef.vieworg, view ); - // view[2] += 8; // // BFP - unused Q3 default view height value - - // cg.refdefViewAngles[PITCH] *= 0.5; // BFP - unused - AngleVectors( cg.refdefViewAngles, forward, right, up ); // BFP - Camera height setup @@ -284,23 +261,15 @@ static void CG_OffsetThirdPersonView( void ) { forwardScale = cos( camAngle / 180 * M_PI ); sideScale = sin( camAngle / 180 * M_PI ); -// BFP - unused -#if 0 - VectorMA( view, -camRange * forwardScale, forward, view ); - VectorMA( view, -camRange * sideScale, right, view ); -#endif - - // trace a ray from the origin to the viewpoint to make sure the view isn't - // in a solid block. Use an 8 by 8 block to prevent the view from near clipping anything - // BFP - cg_cameraMode cvar to detect if it's disabled doesn't exist // BFP - NOTE: Originally, BFP uses MASK_SOLID for tracing and it might not be a good solution, so use MASK_PLAYERSOLID for all traces here instead in the future // That traces the camera pivot + // trace a ray from the origin to the viewpoint to make sure the view isn't + // in a solid block. Use an 8 by 8 block to prevent the view from near clipping anything CG_Trace( &trace, cg.refdef.vieworg, mins, maxs, view, cg.predictedPlayerState.clientNum, MASK_SOLID ); if ( trace.fraction != 1.0 ) { - // BFP - Use the vector scale to trace something solid and add endpos + // BFP - Use the vector scale to trace something solid VectorScale( trace.plane.normal, camRange, view ); - VectorAdd( trace.endpos, view, cg.refdef.vieworg ); view[2] += (1.0 - trace.fraction) * 32; // try another trace to this position, because a tunnel may have the ceiling @@ -310,61 +279,15 @@ static void CG_OffsetThirdPersonView( void ) { VectorCopy( trace.endpos, view ); } -// BFP - unused -#if 0 - VectorCopy( view, cg.refdef.vieworg ); - - // select pitch to look at focus point from vieword - VectorSubtract( focusPoint, cg.refdef.vieworg, focusPoint ); - focusDist = sqrt( focusPoint[0] * focusPoint[0] + focusPoint[1] * focusPoint[1] ); - if ( focusDist < 1 ) { - focusDist = 1; // should never happen - } - - cg.refdefViewAngles[PITCH] = -180 / M_PI * atan2( focusPoint[2], focusDist ); - cg.refdefViewAngles[YAW] -= cg_thirdPersonAngle.value; -#endif - // BFP - Camera setup focusAngles[YAW] -= camAngle; - // BFP - Fly tilt - // Get the pressed keys to move left or right - cmdNum = trap_GetCurrentCmdNumber(); - trap_GetUserCmd( cmdNum, &cmd ); - - // BFP - TODO: If cg_thirdPersonAngle is changed, the roll rotation should be moved like in 0º (or fixed) - - focusAngles[ROLL] = LERP( lastAngled, 0.0f, (float)(cg.frametime / 1000.00f) * 20.0f ); - rightAngled = LERP( lastRightAngled, 0.0f, (float)(cg.frametime / 1000.00f) * 20.0f ); - upAngled = LERP( lastUpAngled, 0.0f, (float)(cg.frametime / 1000.00f) * 20.0f ); - - if ( cg_flytilt.integer > 0 - && ( cg.predictedPlayerState.eFlags & EF_AURA ) - && cg.predictedPlayerState.powerups[PW_FLIGHT] > 0 - && !( cg.predictedPlayerState.pm_flags & PMF_KI_CHARGE ) ) { - if ( cmd.rightmove < 0 ) { // Left - focusAngles[ROLL] = LERP( lastAngled, -20.0f, (float)(cg.frametime / 1000.00f) * 15.0f ); - rightAngled = LERP( lastRightAngled, focusAngles[ROLL] - 0.55f, (float)(cg.frametime / 1000.00f) * 15.0f ); - upAngled = LERP( lastUpAngled, -acos( focusAngles[ROLL] / 180 * M_PI ) - 1.7f, (float)(cg.frametime / 1000.00f) * 15.0f ); - } else if ( cmd.rightmove > 0 ) { // Right - focusAngles[ROLL] = LERP( lastAngled, 20.0f, (float)(cg.frametime / 1000.00f) * 15.0f ); - rightAngled = LERP( lastRightAngled, focusAngles[ROLL] - 0.55f, (float)(cg.frametime / 1000.00f) * 15.0f ); - upAngled = LERP( lastUpAngled, -acos( focusAngles[ROLL] / 180 * M_PI ) - 1.7f, (float)(cg.frametime / 1000.00f) * 15.0f ); - } - } - // Last roll where it was "lerped" - lastAngled = focusAngles[ROLL]; - lastRightAngled = rightAngled; - lastUpAngled = upAngled; - VectorCopy( focusAngles, cg.refdefViewAngles ); // VectorCopy( focusAngles, cg.predictedPlayerState.viewangles ); // For player model, doesn't make sense though :P - // BFP - NOTE: Applying angles to height and slide (up and right vectors), while rolling with fly tilt, is an odd case, BFP has something that handles up and right vectors (· ·') *curiosity sweat* - VectorMA( overrideOrg, -camRange * sideScale + rightAngled, right, cg.refdef.vieworg ); + VectorMA( overrideOrg, -camRange * sideScale, right, cg.refdef.vieworg ); VectorMA( cg.refdef.vieworg, -camRange * forwardScale, forward, cg.refdef.vieworg ); - VectorMA( cg.refdef.vieworg, upAngled, up, cg.refdef.vieworg ); + VectorMA( cg.refdef.vieworg, 0, up, cg.refdef.vieworg ); // BFP - Trace the camera position when being near to something solid CG_Trace( &trace, view, mins, maxs, cg.refdef.vieworg, cg.predictedPlayerState.clientNum, MASK_SOLID ); @@ -389,11 +312,8 @@ Returns false if out of view. qboolean CG_WorldCoordToScreenCoordFloat( vec3_t worldCoord, float *x, float *y ) { // BFP - Crosshair functionality float xcenter, ycenter; vec3_t local, transformed; - vec3_t vforward; - vec3_t vright; - vec3_t vup; - float xzi; - float yzi; + vec3_t vforward, vright, vup; + float xzi, yzi; xcenter = 640.0f / 2.0f; // gives screen coords in virtual 640x480, to be adjusted when drawn ycenter = 480.0f / 2.0f; // gives screen coords in virtual 640x480, to be adjusted when drawn @@ -784,7 +704,14 @@ static int CG_CalcViewValues( void ) { VectorCopy( ps->origin, cg.refdef.vieworg ); - VectorCopy( ps->viewangles, cg.refdefViewAngles ); + + // BFP - Fly tilt + if ( cg_flytilt.integer > 0 ) { + VectorCopy( ps->viewangles, cg.refdefViewAngles ); + } else { + ps->viewangles[ROLL] = 0; // that removes tilt + VectorCopy( ps->viewangles, cg.refdefViewAngles ); + } if (cg_cameraOrbit.integer) { if (cg.time > cg.nextOrbitTime) { From 84ea02f9ac5aa4e0e2f851df0013a4ca693648b8 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Mon, 28 Oct 2024 02:39:58 +0100 Subject: [PATCH 127/374] game: Lot of changes happened on pmove: - Apply braking when flying to prevent slow friction movement - Handle flight and ki boost jumping from the ground correctly to avoid jittering - Increase jump velocity to 600 (from 270, Q3 default) and ki boost jumping speed to 1100 (same as original BFP) - Apply left and right water jumping movements (still needs tweaking) - Apply fly tilt on ki boost in viewangles roll and make move a bit down - Apply ki boost speed on PM_AirMove, PM_WalkMove, and PM_FlyMove instead of pm->ps->speed from g_active.c - Avoid displaying shooting effects (from lightning weapon) - Apply near ground tracing value at -95 to match original BFP - Fix jittering issues when starting to fly from the ground and using ki boost - Fix ki explosion wave weapon state when it's still on while changing weapon - Add WP_GAUNTLET in weapon states for testing purposes - Handle attack preparation when respawning - Disable trap_SnapVector when timescale is less than 0 to prevent continuous movement without braking --- source/game/bg_local.h | 2 +- source/game/bg_pmove.c | 225 +++++++++++++++++++++++++++++++---------- source/game/g_active.c | 9 +- 3 files changed, 172 insertions(+), 64 deletions(-) diff --git a/source/game/bg_local.h b/source/game/bg_local.h index 1142535..0e42ac0 100644 --- a/source/game/bg_local.h +++ b/source/game/bg_local.h @@ -26,7 +26,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define STEPSIZE 18 -#define JUMP_VELOCITY 270 +#define JUMP_VELOCITY 600 // BFP - Before 270 #define TIMER_LAND 130 #define TIMER_GESTURE (34*66+50) diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index 611a6e3..cf8576e 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -298,6 +298,11 @@ static void PM_Friction( void ) { vel[0] = 0; vel[1] = 0; // allow sinking underwater // FIXME: still have z friction underwater? + + // BFP - Brake when flying at that speed rate, otherwise the friction continues + if ( pm->ps->powerups[PW_FLIGHT] > 0 ) { + vel[2] = 0; + } return; } @@ -495,8 +500,9 @@ static qboolean PM_CheckJump( void ) { pm->ps->groundEntityNum = ENTITYNUM_NONE; pm->ps->velocity[2] = JUMP_VELOCITY; // BFP - Double jump velocity when using ki boost - if ( pm->ps->powerups[PW_HASTE] > 0 ) { - pm->ps->velocity[2] *= 2; + if ( pm->ps->powerups[PW_HASTE] > 0 + || ( pm->cmd.buttons & BUTTON_KI_USE ) ) { // BFP - Handle the ki boost button if it's being pressed, that avoids jittering movements + pm->ps->velocity[2] = 1100; } PM_AddEvent( EV_JUMP ); @@ -515,12 +521,11 @@ PM_CheckWaterJump ============= */ static qboolean PM_CheckWaterJump( void ) { - // BFP - Apply for backwards too, Q3 doesn't have that - vec3_t spot, backwardSpot; + vec3_t spot; int cont; - vec3_t flatforward, flatbackward; -#define WATER_JUMP_HORIZONTAL_VELOCITY 200 -#define WATER_JUMP_VERTICAL_VELOCITY 250 + // BFP - Apply for backwards, left and right too, Q3 doesn't have that + vec3_t flatforward, flatbackward, flatleft, flatright; + const int WATER_JUMP_HORIZONTAL_VELOCITY = 200, WATER_JUMP_VERTICAL_VELOCITY = 250; if (pm->ps->pm_time) { return qfalse; @@ -542,6 +547,18 @@ static qboolean PM_CheckWaterJump( void ) { flatbackward[2] = 0; VectorNormalize( flatbackward ); + // left direction + flatleft[0] = -pml.right[0]; + flatleft[1] = -pml.right[1]; + flatleft[2] = 0; + VectorNormalize( flatleft ); + + // right direction + flatright[0] = pml.right[0]; + flatright[1] = pml.right[1]; + flatright[2] = 0; + VectorNormalize( flatright ); + // check forward VectorMA ( pm->ps->origin, 30, flatforward, spot ); spot[2] += 4; @@ -570,10 +587,36 @@ static qboolean PM_CheckWaterJump( void ) { } } + // check left + VectorMA( pm->ps->origin, 30, flatleft, spot ); + spot[2] += 4; + cont = pm->pointcontents( spot, pm->ps->clientNum ); + if ( cont & CONTENTS_SOLID ) { + spot[2] += 16; + cont = pm->pointcontents( spot, pm->ps->clientNum ); + if ( !cont ) { + VectorScale( pml.right, -WATER_JUMP_HORIZONTAL_VELOCITY, pm->ps->velocity ); + pm->ps->velocity[2] = WATER_JUMP_VERTICAL_VELOCITY; + return qtrue; + } + } + + // check right + VectorMA( pm->ps->origin, 30, flatright, spot ); + spot[2] += 4; + cont = pm->pointcontents( spot, pm->ps->clientNum ); + if ( cont & CONTENTS_SOLID ) { + spot[2] += 16; + cont = pm->pointcontents( spot, pm->ps->clientNum ); + if ( !cont ) { + VectorScale( pml.right, WATER_JUMP_HORIZONTAL_VELOCITY, pm->ps->velocity ); + pm->ps->velocity[2] = WATER_JUMP_VERTICAL_VELOCITY; + return qtrue; + } + } + return qfalse; } -#undef WATER_JUMP_HORIZONTAL_VELOCITY -#undef WATER_JUMP_VERTICAL_VELOCITY //============================================================================ @@ -626,13 +669,20 @@ static void PM_WaterMove( void ) { PM_WaterJumpMove(); return; } + + // BFP - Water animation handling, uses flying animation in that case + CONTINUEFLY_ANIM_HANDLING() + + // BFP - Melee strike legs animation + CONTINUEMELEESTRIKE_LEGS_ANIM_HANDLING( 1 ) + #if 0 // jump = head for surface if ( pm->cmd.upmove >= 10 ) { if (pm->ps->velocity[2] > -300) { - if ( pm->watertype == CONTENTS_WATER ) { + if ( pm->watertype & CONTENTS_WATER ) { pm->ps->velocity[2] = 100; - } else if (pm->watertype == CONTENTS_SLIME) { + } else if ( pm->watertype & CONTENTS_SLIME ) { pm->ps->velocity[2] = 80; } else { pm->ps->velocity[2] = 50; @@ -677,12 +727,6 @@ static void PM_WaterMove( void ) { VectorScale(pm->ps->velocity, vel, pm->ps->velocity); } - // BFP - Water animation handling, uses flying animation in that case - CONTINUEFLY_ANIM_HANDLING() - - // BFP - Melee strike legs animation - CONTINUEMELEESTRIKE_LEGS_ANIM_HANDLING( 1 ) - PM_SlideMove( qfalse ); } @@ -700,6 +744,11 @@ static void PM_FlyMove( void ) { vec3_t wishdir; float scale; + // BFP - Fly tilt variables + static float currentRollAngle = 0; + short targetRollAngle = 0; + float lerpSpeed = 2.5; + // normal slowdown PM_Friction (); @@ -717,11 +766,28 @@ static void PM_FlyMove( void ) { VectorCopy (wishvel, wishdir); wishspeed = VectorNormalize(wishdir); + wishspeed *= scale; // add speed + if ( !( pm->ps->pm_flags & PMF_BLOCK ) // BFP - Don't increase the speed when blocking && ( pm->ps->powerups[PW_HASTE] > 0 || ( pm->cmd.buttons & BUTTON_KI_USE ) ) ) { - wishspeed *= scale; + wishspeed *= (scale + 2); // increase the speed a bit + + // determine the target roll angle based on rightmove + targetRollAngle = 0; + if ( pm->cmd.rightmove > 0 ) { + targetRollAngle = 20; + pm->ps->velocity[2] -= 5; // move a bit down + } else if ( pm->cmd.rightmove < 0 ) { + targetRollAngle = -20; + pm->ps->velocity[2] -= 5; // move a bit down + } } + // lerp the current roll angle towards the target roll angle + currentRollAngle += ( targetRollAngle - currentRollAngle ) * lerpSpeed * pml.frametime; + + pm->ps->viewangles[ROLL] = currentRollAngle; + PM_Accelerate (wishdir, wishspeed, pm_flyaccelerate); PM_StepSlideMove( qfalse ); @@ -769,6 +835,11 @@ static void PM_AirMove( void ) { wishspeed = VectorNormalize(wishdir); wishspeed *= scale; + if ( !( pm->ps->pm_flags & PMF_BLOCK ) // BFP - Don't increase the speed when blocking + && ( pm->ps->powerups[PW_HASTE] > 0 || ( pm->cmd.buttons & BUTTON_KI_USE ) ) ) { + wishspeed *= scale; + } + // not on ground, so little effect on velocity PM_Accelerate (wishdir, wishspeed, pm_airaccelerate); @@ -792,6 +863,12 @@ static void PM_AirMove( void ) { TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ); PM_StepSlideMove ( qtrue ); + // BFP - TODO: Handle gravity, make the player heavier + /*if ( !( pm->ps->pm_flags & PMF_STOP_AIR_FLY ) ) { + PM_SlideMove ( qtrue ); + } else { + pm->ps->velocity[2] -= pm->ps->gravity * pml.frametime; + }*/ } // BFP - no hook @@ -907,6 +984,11 @@ static void PM_WalkMove( void ) { } } + if ( !( pm->ps->pm_flags & PMF_BLOCK ) // BFP - Don't increase the speed when blocking + && ( pm->ps->powerups[PW_HASTE] > 0 || ( pm->cmd.buttons & BUTTON_KI_USE ) ) ) { + wishspeed *= scale; + } + // when a player gets hit, they temporarily lose // full control, which allows them to be moved a bit if ( ( pml.groundTrace.surfaceFlags & SURF_SLICK ) ) { // BFP - No handling PMF_TIME_KNOCKBACK, before: || pm->ps->pm_flags & PMF_TIME_KNOCKBACK ) { @@ -1301,38 +1383,6 @@ static void PM_GroundTrace( void ) { pm->ps->pm_flags &= ~PMF_NEARGROUND; } - // BFP - If the player is in the ground, then jump! - // And make sure to handle the PMF flag when the player isn't flying and falling - if ( pm->ps->powerups[PW_FLIGHT] > 0 - && ( pm->ps->pm_flags & PMF_FALLING ) - && !( pm->ps->pm_flags & PMF_NEARGROUND ) ) { - if ( pml.groundTrace.contents & MASK_PLAYERSOLID ) { - // do a smooth jump animation like BFP does - if ( !( pm->cmd.buttons & BUTTON_KI_CHARGE ) - && pm->ps->weaponstate != WEAPON_KIEXPLOSIONWAVE - && pm->ps->weaponstate != WEAPON_STUN ) { - pm->ps->pm_time = 550; - pm->ps->velocity[2] = JUMP_VELOCITY; - if ( !( pm->ps->pm_flags & PMF_KI_ATTACK ) - && !( pm->ps->pm_flags & PMF_MELEE ) ) { - if ( pm->cmd.forwardmove > 0 ) { - TORSOSTATUS_ANIM_HANDLING( TORSO_FLYA ); - } else if ( pm->cmd.forwardmove < 0 ) { - TORSOSTATUS_ANIM_HANDLING( TORSO_FLYB ); - } else { - TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ); - } - } - PM_ForceLegsAnim( LEGS_JUMP ); - } - pml.groundPlane = qfalse; // jumping away - pml.walking = qfalse; - } - pm->ps->pm_flags &= ~PMF_FALLING; - pm->ps->groundEntityNum = ENTITYNUM_NONE; - return; - } - // slopes that are too steep will not be considered onground if ( trace.plane.normal[2] < MIN_WALK_NORMAL ) { if ( pm->debugLevel ) { @@ -1583,6 +1633,7 @@ static void PM_Footsteps( void ) { // BFP - Avoid when charging if ( pm->ps->pm_flags & PMF_KI_CHARGE ) { + pm->ps->eFlags &= ~EF_FIRING; // don't display shooting effects return; } @@ -1817,7 +1868,7 @@ static void PM_TorsoAnimation( void ) { } VectorCopy( pm->ps->origin, point ); - point[2] -= 128; // BFP - Put more down, obviously it was 64, but BFP does that + point[2] -= 95; // BFP - Put more down, obviously it was 64, but BFP does that pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask); pml.groundTrace = trace; @@ -1868,6 +1919,56 @@ static void PM_TorsoAnimation( void ) { #endif } +/* +============== +PM_FlightStart +============== +*/ +static void PM_FlightStart( void ) { // BFP - Start flight handling + vec3_t point; + trace_t trace; + + point[0] = pm->ps->origin[0]; + point[1] = pm->ps->origin[1]; + point[2] = pm->ps->origin[2] - 0.25; + + pm->trace ( &trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask ); + pml.groundTrace = trace; + + // must wait for flight key to be released + if ( pm->ps->pm_flags & PMF_JUMP_HELD ) { // avoid when the flight key is being pressed all time + return; + } + + // BFP - If the player is in the ground, then jump! + // And make sure to handle the PMF flag when the player isn't flying and falling + if ( ( pm->ps->powerups[PW_FLIGHT] > 0 || ( pm->cmd.buttons & BUTTON_ENABLEFLIGHT ) ) // Handle the ki boost button if it's being pressed, that avoids jittering + && ( pm->ps->pm_flags & PMF_FALLING ) + && !( pm->ps->pm_flags & PMF_NEARGROUND ) ) { + if ( pml.groundTrace.contents & MASK_PLAYERSOLID ) { + // do a smooth jump animation like BFP does + if ( !( pm->cmd.buttons & BUTTON_KI_CHARGE ) + && pm->ps->weaponstate != WEAPON_KIEXPLOSIONWAVE + && pm->ps->weaponstate != WEAPON_STUN ) { + pm->ps->pm_time = 550; + pm->ps->velocity[2] = JUMP_VELOCITY - 200; + if ( !( pm->ps->pm_flags & PMF_KI_ATTACK ) + && !( pm->ps->pm_flags & PMF_MELEE ) ) { + if ( pm->cmd.forwardmove > 0 ) { + TORSOSTATUS_ANIM_HANDLING( TORSO_FLYA ); + } else if ( pm->cmd.forwardmove < 0 ) { + TORSOSTATUS_ANIM_HANDLING( TORSO_FLYB ); + } else { + TORSOSTATUS_ANIM_HANDLING( TORSO_STAND ); + } + } + PM_ForceLegsAnim( LEGS_JUMP ); + } + } + pm->ps->pm_flags &= ~PMF_FALLING; + } +} + /* ============== PM_FlightAnimation @@ -1946,6 +2047,7 @@ static void PM_KiChargeAnimation( void ) { // BFP - Ki Charge if ( pm->cmd.buttons & BUTTON_KI_CHARGE ) { pm->ps->powerups[PW_HASTE] = 0; + pm->ps->eFlags &= ~EF_FIRING; // don't display shooting effects pm->ps->pm_flags |= PMF_KI_CHARGE; PM_ContinueTorsoAnim( TORSO_CHARGE ); PM_ContinueLegsAnim( LEGS_CHARGE ); @@ -1997,6 +2099,7 @@ static void PM_Melee( void ) { // BFP - Melee // Don't allow pressing ki attack and block buttons when melee is being used if ( ( pm->ps->pm_flags & PMF_MELEE ) || ( pm->cmd.buttons & BUTTON_MELEE ) ) { + pm->ps->eFlags &= ~EF_FIRING; // don't display shooting effects pm->cmd.buttons &= ~( BUTTON_ATTACK | BUTTON_BLOCK ); } } @@ -2091,6 +2194,7 @@ static void PM_Weapon( void ) { // can't change if weapon is firing, but can change // again if lowering or raising if ( pm->ps->weaponstate != WEAPON_BEAMFIRING // BFP - Avoid if the beam is still firing + && pm->ps->weaponstate != WEAPON_KIEXPLOSIONWAVE // BFP - Avoid if ki explosion wave is still on && pm->ps->weaponstate != WEAPON_STUN // BFP - Avoid when being stunned && ( pm->ps->weaponTime <= 0 || pm->ps->weaponstate != WEAPON_FIRING ) ) { if ( pm->ps->weapon != pm->cmd.weapon ) { @@ -2205,6 +2309,7 @@ static void PM_Weapon( void ) { pm->ps->pm_flags |= PMF_KI_ATTACK; //PM_AddEvent( EV_FIRE_WEAPON ); break; + case WP_GAUNTLET: case WP_LIGHTNING: pm->ps->pm_flags |= PMF_KI_ATTACK; } @@ -2246,7 +2351,8 @@ static void PM_Weapon( void ) { } } if ( !( pm->cmd.buttons & BUTTON_ATTACK ) - || ( pm->cmd.buttons & BUTTON_MELEE ) ) { + || ( pm->cmd.buttons & BUTTON_MELEE ) + || pm->ps->weapon != pm->cmd.weapon ) { // avoid when changing weapon pm->ps->weaponTime = 1000; pm->ps->weaponstate = WEAPON_STUN; } @@ -2490,9 +2596,10 @@ void PmoveSingle (pmove_t *pmove) { pm->ps->eFlags &= ~EF_TALK; } - // BFP - Handling the PMF flag when stepping the ground + // BFP - Handling the PMF flag when stepping the ground and when preparing to attack if ( pm->ps->pm_flags & PMF_RESPAWNED ) { pm->ps->pm_flags |= PMF_FALLING; + pm->cmd.buttons &= ~BUTTON_ATTACK; } // set the firing flag for continuous beam weapons @@ -2546,7 +2653,13 @@ void PmoveSingle (pmove_t *pmove) { AngleVectors (pm->ps->viewangles, pml.forward, pml.right, pml.up); - if ( pm->cmd.upmove < 10 ) { + // BFP - Avoid when the flight key is being pressed all time + if ( pm->ps->groundEntityNum == ENTITYNUM_NONE && ( pm->cmd.buttons & BUTTON_ENABLEFLIGHT ) ) { + pm->ps->pm_flags |= PMF_JUMP_HELD; + } + + if ( pm->cmd.upmove < 10 + && !( pm->cmd.buttons & BUTTON_ENABLEFLIGHT ) ) { // BFP - Don't use for jumping // not holding jump pm->ps->pm_flags &= ~PMF_JUMP_HELD; } @@ -2622,6 +2735,7 @@ void PmoveSingle (pmove_t *pmove) { // set mins, maxs, and viewheight PM_CheckDuck (); + PM_FlightStart(); // set groundentity PM_GroundTrace(); @@ -2694,8 +2808,9 @@ void PmoveSingle (pmove_t *pmove) { // entering / leaving water splashes PM_WaterEvents(); + // BFP - BFP disabled that because the velocity calcualtions aren't correct when timescale is less than 1 // snap some parts of playerstate to save network bandwidth - trap_SnapVector( pm->ps->velocity ); + // trap_SnapVector( pm->ps->velocity ); } diff --git a/source/game/g_active.c b/source/game/g_active.c index 5cc2a32..f605316 100644 --- a/source/game/g_active.c +++ b/source/game/g_active.c @@ -1050,7 +1050,7 @@ static void KiAttackWeaponHandling( gentity_t *ent, usercmd_t *ucmd, pmove_t *pm } if ( client->ps.weaponTime <= 0 ) { - client->ps.weaponTime += addTime; + client->ps.weaponTime = addTime; } } break; @@ -1241,9 +1241,6 @@ void ClientThink_real( gentity_t *ent ) { || client->ps.powerups[PW_HASTE] > 0 ) // BFP - When "kiusetoggle" is binded, enables/disables && ( client->ps.weaponstate != WEAPON_KIEXPLOSIONWAVE && client->ps.weaponstate != WEAPON_STUN ) ) { - if ( client->ps.powerups[PW_FLIGHT] <= 0 ) { - client->ps.speed *= 2.5; - } client->ps.powerups[PW_HASTE] = 1; // Handle ki boost status client->ps.eFlags |= EF_AURA; } else { @@ -1271,10 +1268,6 @@ void ClientThink_real( gentity_t *ent ) { client->ps.eFlags |= EF_AURA; } - if ( client->ps.powerups[PW_FLIGHT] > 0 ) { // BFP - Flight speed - client->ps.speed *= 2; - } - // BFP - Enable flight FlyingThink( ent, ucmd ); // prevents client-server side issues when there's other client in-game } From af805cf342956a0c6c40465bd44280ecf502ffa7 Mon Sep 17 00:00:00 2001 From: LegendaryGuard Date: Tue, 29 Oct 2024 00:54:30 +0100 Subject: [PATCH 128/374] cgame - game: Apply g_noFlight and g_meleeOnly in pmove avoiding entering on these statuses or pressing the buttons if these are enabled, apply NO FLIGHT and MELEE ONLY messages on loading map info and add them in the vote commands --- source/cgame/cg_info.c | 16 ++++++++++++++++ source/game/bg_local.h | 1 + source/game/bg_misc.c | 2 -- source/game/bg_pmove.c | 19 +++++++++++++++++++ source/game/g_cmds.c | 7 ++++++- 5 files changed, 42 insertions(+), 3 deletions(-) diff --git a/source/cgame/cg_info.c b/source/cgame/cg_info.c index 1e1dd9c..91d8c0d 100644 --- a/source/cgame/cg_info.c +++ b/source/cgame/cg_info.c @@ -233,6 +233,22 @@ void CG_DrawInformation( void ) { y += PROP_HEIGHT; } + // BFP - Melee only + trap_Cvar_VariableStringBuffer( "g_meleeOnly", buf, sizeof( buf ) ); + if ( atoi( buf ) ) { + UI_DrawProportionalString( 320, y, "MELEE ONLY", + UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite ); + y += PROP_HEIGHT; + } + + // BFP - No flight + trap_Cvar_VariableStringBuffer( "g_noFlight", buf, sizeof( buf ) ); + if ( atoi( buf ) ) { + UI_DrawProportionalString( 320, y, "NO FLIGHT", + UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite ); + y += PROP_HEIGHT; + } + // game type switch ( cgs.gametype ) { case GT_FFA: diff --git a/source/game/bg_local.h b/source/game/bg_local.h index 0e42ac0..a6dbd9d 100644 --- a/source/game/bg_local.h +++ b/source/game/bg_local.h @@ -79,4 +79,5 @@ void PM_AddEvent( int newEvent ); qboolean PM_SlideMove( qboolean gravity ); void PM_StepSlideMove( qboolean gravity ); +void trap_Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize ); diff --git a/source/game/bg_misc.c b/source/game/bg_misc.c index 2fc9eb9..d317dfb 100644 --- a/source/game/bg_misc.c +++ b/source/game/bg_misc.c @@ -1046,8 +1046,6 @@ Handles the sequence numbers =============== */ -void trap_Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize ); - void BG_AddPredictableEventToPlayerstate( int newEvent, int eventParm, playerState_t *ps ) { #ifdef _DEBUG diff --git a/source/game/bg_pmove.c b/source/game/bg_pmove.c index cf8576e..5ea94e2 100644 --- a/source/game/bg_pmove.c +++ b/source/game/bg_pmove.c @@ -1927,6 +1927,8 @@ PM_FlightStart static void PM_FlightStart( void ) { // BFP - Start flight handling vec3_t point; trace_t trace; + // BFP - For no flight + char buf[1024]; point[0] = pm->ps->origin[0]; point[1] = pm->ps->origin[1]; @@ -1940,6 +1942,12 @@ static void PM_FlightStart( void ) { // BFP - Start flight handling return; } + // BFP - No flight + trap_Cvar_VariableStringBuffer( "g_noFlight", buf, sizeof( buf ) ); + if ( atoi( buf ) ) { + return; + } + // BFP - If the player is in the ground, then jump! // And make sure to handle the PMF flag when the player isn't flying and falling if ( ( pm->ps->powerups[PW_FLIGHT] > 0 || ( pm->cmd.buttons & BUTTON_ENABLEFLIGHT ) ) // Handle the ki boost button if it's being pressed, that avoids jittering @@ -2602,6 +2610,17 @@ void PmoveSingle (pmove_t *pmove) { pm->cmd.buttons &= ~BUTTON_ATTACK; } + // BFP - Melee only + { + char buf[1024]; + trap_Cvar_VariableStringBuffer( "g_meleeOnly", buf, sizeof( buf ) ); + if ( atoi( buf ) ) { + pm->cmd.buttons &= ~BUTTON_ATTACK; + pm->ps->pm_flags &= ~PMF_KI_ATTACK; + pm->ps->eFlags &= ~EF_FIRING; + } + } + // set the firing flag for continuous beam weapons if ( !(pm->ps->pm_flags & PMF_RESPAWNED) && pm->ps->pm_type != PM_INTERMISSION && ( pm->cmd.buttons & BUTTON_ATTACK ) && pm->ps->ammo[ pm->ps->weapon ] ) { diff --git a/source/game/g_cmds.c b/source/game/g_cmds.c index 09f2b4a..2447337 100644 --- a/source/game/g_cmds.c +++ b/source/game/g_cmds.c @@ -1253,9 +1253,14 @@ void Cmd_CallVote_f( gentity_t *ent ) { } else if ( !Q_stricmp( arg1, "g_doWarmup" ) ) { } else if ( !Q_stricmp( arg1, "timelimit" ) ) { } else if ( !Q_stricmp( arg1, "fraglimit" ) ) { + // } else if ( !Q_stricmp( arg1, "g_basePL" ) ) { // BFP - TODO: Base powerlevel + } else if ( !Q_stricmp( arg1, "g_hitStun" ) ) { // BFP - Hit stun + // } else if ( !Q_stricmp( arg1, "g_allowSpectatorChat" ) ) { // BFP - TODO: Allow spectator chat + } else if ( !Q_stricmp( arg1, "g_meleeOnly" ) ) { // BFP - Melee only + } else if ( !Q_stricmp( arg1, "g_noFlight" ) ) { // BFP - No flight } else { trap_SendServerCommand( ent-g_entities, "print \"Invalid vote string.\n\"" ); - trap_SendServerCommand( ent-g_entities, "print \"Vote commands are: map_restart, nextmap, map , g_gametype , kick , clientkick , g_doWarmup, timelimit