diff --git a/reaction/game/bg_misc.c b/reaction/game/bg_misc.c index 1efc227f..5d41c685 100644 --- a/reaction/game/bg_misc.c +++ b/reaction/game/bg_misc.c @@ -21,8 +21,7 @@ An item fires all of its targets when it is picked up. If the toucher can't car "count" override quantity or duration on most items. */ - -gitem_t bg_itemlist[] = +gitem_t bg_itemlist[] = { { NULL, @@ -44,7 +43,7 @@ gitem_t bg_itemlist[] = // // - // WEAPONS + // WEAPONS // @@ -68,7 +67,7 @@ gitem_t bg_itemlist[] = { "weapon_pistol", "sound/weapons/mk23/mk23slide.wav", - { "models/weapons2/mk23/mk23.md3", + { "models/weapons2/mk23/mk23.md3", 0, 0, 0}, /* icon */ "icons/iconw_mk23", /* pickup */ RQ3_PISTOL_NAME, @@ -83,7 +82,7 @@ gitem_t bg_itemlist[] = { "weapon_m4", "sound/weapons/m4/m4slide.wav", - { "models/weapons2/m4/m4.md3", + { "models/weapons2/m4/m4.md3", 0, 0, 0}, /* icon */ "icons/iconw_m4", /* pickup */ RQ3_M4_NAME, @@ -98,7 +97,7 @@ gitem_t bg_itemlist[] = { "weapon_ssg3000", "sound/weapons/ssg3000/ssgin.wav", - { "models/weapons2/ssg3000/ssg3000.md3", + { "models/weapons2/ssg3000/ssg3000.md3", 0, 0, 0}, /* icon */ "icons/iconw_ssg", /* pickup */ RQ3_SSG3000_NAME, @@ -113,7 +112,7 @@ gitem_t bg_itemlist[] = { "weapon_mp5", "sound/weapons/mp5/mp5slide.wav", - { "models/weapons2/mp5/mp5.md3", + { "models/weapons2/mp5/mp5.md3", 0, 0, 0}, /* icon */ "icons/iconw_mp5", /* pickup */ RQ3_MP5_NAME, @@ -128,7 +127,7 @@ gitem_t bg_itemlist[] = { "weapon_handcannon", "sound/weapons/handcannon/hcopen.wav", - { "models/weapons2/handcannon/handcannon.md3", + { "models/weapons2/handcannon/handcannon.md3", 0, 0, 0}, /* icon */ "icons/iconw_sawedoff", /* pickup */ RQ3_HANDCANNON_NAME, @@ -143,7 +142,7 @@ gitem_t bg_itemlist[] = { "weapon_m3", "sound/weapons/m3/m3in.wav", - { "models/weapons2/m3/m3.md3", + { "models/weapons2/m3/m3.md3", 0, 0, 0}, /* icon */ "icons/iconw_m3", /* pickup */ RQ3_M3_NAME, @@ -158,7 +157,7 @@ gitem_t bg_itemlist[] = { "weapon_akimbo", "sound/weapons/mk23/mk23slide.wav", - { "models/weapons2/akimbo/akimbo.md3", + { "models/weapons2/akimbo/akimbo.md3", 0, 0, 0}, /* icon */ "icons/iconw_akimbo", /* pickup */ RQ3_AKIMBO_NAME, @@ -175,7 +174,7 @@ gitem_t bg_itemlist[] = "weapon_grenade", //"sound/grenade/tink2.wav", "sound/misc/am_pkup.wav", - { "models/weapons2/grenade/grenade.md3", + { "models/weapons2/grenade/grenade.md3", 0, 0, 0}, /* icon */ "icons/iconw_gren", /* pickup */ RQ3_GRENADE_NAME, @@ -207,7 +206,7 @@ gitem_t bg_itemlist[] = { "pistol_1st", NULL, - { "models/weapons2/mk23/mk23_1st.md3", + { "models/weapons2/mk23/mk23_1st.md3", 0, 0, 0}, "icons/iconw_mk23", RQ3_PISTOL_NAME, @@ -222,7 +221,7 @@ gitem_t bg_itemlist[] = { "m4_1st", NULL, - { "models/weapons2/m4/m4_1st.md3", + { "models/weapons2/m4/m4_1st.md3", 0, 0, 0}, "icons/iconw_m4", RQ3_M4_NAME, @@ -237,7 +236,7 @@ gitem_t bg_itemlist[] = { "ssg3000_1st", NULL, - { "models/weapons2/ssg3000/ssg3000_1st.md3", + { "models/weapons2/ssg3000/ssg3000_1st.md3", 0, 0, 0}, "icons/iconw_ssg", RQ3_SSG3000_NAME, @@ -252,7 +251,7 @@ gitem_t bg_itemlist[] = { "mp5_1st", NULL, - { "models/weapons2/mp5/mp5_1st.md3", + { "models/weapons2/mp5/mp5_1st.md3", 0, 0, 0}, "icons/iconw_mp5", RQ3_MP5_NAME, @@ -267,7 +266,7 @@ gitem_t bg_itemlist[] = { "handcannon_1st", NULL, - { "models/weapons2/handcannon/handcannon_1st.md3", + { "models/weapons2/handcannon/handcannon_1st.md3", 0, 0, 0}, "icons/iconw_sawedoff", RQ3_HANDCANNON_NAME, @@ -282,7 +281,7 @@ gitem_t bg_itemlist[] = { "m3_1st", NULL, - { "models/weapons2/m3/m3_1st.md3", + { "models/weapons2/m3/m3_1st.md3", 0, 0, 0}, "icons/iconw_m3", RQ3_M3_NAME, @@ -297,7 +296,7 @@ gitem_t bg_itemlist[] = { "akimbo_1st", NULL, - { "models/weapons2/akimbo/akimbo_1st.md3", + { "models/weapons2/akimbo/akimbo_1st.md3", 0, 0, 0}, "icons/iconw_akimbo", RQ3_AKIMBO_NAME, @@ -313,7 +312,7 @@ gitem_t bg_itemlist[] = { "grenade_1st", NULL, - { "models/weapons2/grenade/grenade_1st.md3", + { "models/weapons2/grenade/grenade_1st.md3", 0, 0, 0}, "icons/iconw_gren", RQ3_GRENADE_NAME, @@ -334,7 +333,7 @@ gitem_t bg_itemlist[] = { "ammo_mk23", "sound/misc/am_pkup.wav", - { "models/ammo/mk23.md3", + { "models/ammo/mk23.md3", 0, 0, 0}, /* icon */ "icons/icona_mk23clip", /* pickup */ "MK23 Clip", @@ -351,7 +350,7 @@ gitem_t bg_itemlist[] = { "ammo_shells", "sound/misc/am_pkup.wav", - { "models/ammo/m3.md3", + { "models/ammo/m3.md3", 0, 0, 0}, /* icon */ "icons/icona_shells", /* pickup */ "Shotgun Shells", @@ -369,7 +368,7 @@ gitem_t bg_itemlist[] = { "ammo_ssg3000", "sound/misc/am_pkup.wav", - { "models/ammo/ssg3000.md3", + { "models/ammo/ssg3000.md3", 0, 0, 0}, /* icon */ "icons/icona_ssgammo", /* pickup */ "AP Sniper Ammo", @@ -386,7 +385,7 @@ gitem_t bg_itemlist[] = { "ammo_mp5", "sound/misc/am_pkup.wav", - { "models/ammo/mp5.md3", + { "models/ammo/mp5.md3", 0, 0, 0}, /* icon */ "icons/icona_mp5clip", /* pickup */ "MP5 Clip", @@ -404,7 +403,7 @@ gitem_t bg_itemlist[] = // { // "ammo_lightning", // "sound/misc/am_pkup.wav", -// { "models/powerups/ammo/lightningam.md3", +// { "models/powerups/ammo/lightningam.md3", // 0, 0, 0}, /* icon */// "icons/icona_lightning", /* pickup */// "Shotgun Shells", @@ -421,7 +420,7 @@ gitem_t bg_itemlist[] = { "ammo_m4", "sound/misc/am_pkup.wav", - { "models/ammo/m4.md3", + { "models/ammo/m4.md3", 0, 0, 0}, /* icon */ "icons/icona_m4clip", /* pickup */ "M4 Clip", @@ -544,9 +543,9 @@ Only in CTF games /*QUAKED holdable_kamikaze (.3 .3 1) (-16 -16 -16) (16 16 16) suspended */ { - "holdable_kamikaze", + "holdable_kamikaze", "sound/items/holdable.wav", - { "models/powerups/kamikazi.md3", + { "models/powerups/kamikazi.md3", 0, 0, 0}, /* icon */ "icons/kamikaze", /* pickup */ "Kamikaze", @@ -560,7 +559,7 @@ Only in CTF games /*QUAKED holdable_portal (.3 .3 1) (-16 -16 -16) (16 16 16) suspended */ { - "holdable_portal", + "holdable_portal", "sound/items/holdable.wav", { "models/powerups/holdable/porter.md3", 0, 0, 0}, @@ -576,9 +575,9 @@ Only in CTF games /*QUAKED holdable_invulnerability (.3 .3 1) (-16 -16 -16) (16 16 16) suspended */ { - "holdable_invulnerability", + "holdable_invulnerability", "sound/items/holdable.wav", - { "models/powerups/holdable/invulnerability.md3", + { "models/powerups/holdable/invulnerability.md3", 0, 0, 0}, /* icon */ "icons/invulnerability", /* pickup */ "Invulnerability", @@ -594,7 +593,7 @@ Only in CTF games { "ammo_nails", "sound/misc/am_pkup.wav", - { "models/powerups/ammo/nailgunam.md3", + { "models/powerups/ammo/nailgunam.md3", 0, 0, 0}, /* icon */ "icons/icona_nailgun", /* pickup */ "Nails", @@ -610,7 +609,7 @@ Only in CTF games { "ammo_mines", "sound/misc/am_pkup.wav", - { "models/powerups/ammo/proxmineam.md3", + { "models/powerups/ammo/proxmineam.md3", 0, 0, 0}, /* icon */ "icons/icona_proxlauncher", /* pickup */ "Proximity Mines", @@ -626,7 +625,7 @@ Only in CTF games { "ammo_belt", "sound/misc/am_pkup.wav", - { "models/powerups/ammo/chaingunam.md3", + { "models/powerups/ammo/chaingunam.md3", 0, 0, 0}, /* icon */ "icons/icona_chaingun", /* pickup */ "Chaingun Belt", @@ -645,7 +644,7 @@ Only in CTF games { "item_scout", "sound/items/scout.wav", - { "models/powerups/scout.md3", + { "models/powerups/scout.md3", 0, 0, 0 }, /* icon */ "icons/scout", /* pickup */ "Scout", @@ -661,7 +660,7 @@ Only in CTF games { "item_guard", "sound/items/guard.wav", - { "models/powerups/guard.md3", + { "models/powerups/guard.md3", 0, 0, 0 }, /* icon */ "icons/guard", /* pickup */ "Guard", @@ -677,7 +676,7 @@ Only in CTF games { "item_doubler", "sound/items/doubler.wav", - { "models/powerups/doubler.md3", + { "models/powerups/doubler.md3", 0, 0, 0 }, /* icon */ "icons/doubler", /* pickup */ "Doubler", @@ -751,9 +750,9 @@ Only in One Flag CTF games /*QUAKED weapon_nailgun (.3 .3 1) (-16 -16 -16) (16 16 16) suspended */ { - "weapon_nailgun", + "weapon_nailgun", "sound/misc/w_pkup.wav", - { "models/weapons/nailgun/nailgun.md3", + { "models/weapons/nailgun/nailgun.md3", 0, 0, 0}, /* icon */ "icons/iconw_nailgun", /* pickup */ "Nailgun", @@ -767,9 +766,9 @@ Only in One Flag CTF games /*QUAKED weapon_prox_launcher (.3 .3 1) (-16 -16 -16) (16 16 16) suspended */ { - "weapon_prox_launcher", + "weapon_prox_launcher", "sound/misc/w_pkup.wav", - { "models/weapons/proxmine/proxmine.md3", + { "models/weapons/proxmine/proxmine.md3", 0, 0, 0}, /* icon */ "icons/iconw_proxlauncher", /* pickup */ "Prox Launcher", @@ -789,9 +788,9 @@ Only in One Flag CTF games /*QUAKED weapon_chaingun (.3 .3 1) (-16 -16 -16) (16 16 16) suspended */ { - "weapon_chaingun", + "weapon_chaingun", "sound/misc/w_pkup.wav", - { "models/weapons/vulcan/vulcan.md3", + { "models/weapons/vulcan/vulcan.md3", 0, 0, 0}, /* icon */ "icons/iconw_chaingun", /* pickup */ "Chaingun", @@ -819,9 +818,9 @@ gitem_t *BG_FindItemForPowerup( powerup_t pw ) { int i; for ( i = 0 ; i < bg_numItems ; i++ ) { - if ( (bg_itemlist[i].giType == IT_POWERUP || + if ( (bg_itemlist[i].giType == IT_POWERUP || bg_itemlist[i].giType == IT_TEAM || - bg_itemlist[i].giType == IT_PERSISTANT_POWERUP) && + bg_itemlist[i].giType == IT_PERSISTANT_POWERUP) && bg_itemlist[i].giTag == pw ) { return &bg_itemlist[i]; } @@ -859,7 +858,7 @@ BG_FindItemForWeapon */ gitem_t *BG_FindItemForWeapon( weapon_t weapon ) { gitem_t *it; - + for ( it = bg_itemlist + 1 ; it->classname ; it++) { if ( it->giType == IT_WEAPON && it->giTag == weapon ) { return it; @@ -878,7 +877,7 @@ BG_FindItem */ gitem_t *BG_FindItem( const char *pickupName ) { gitem_t *it; - + for ( it = bg_itemlist + 1 ; it->classname ; it++ ) { if ( !Q_stricmp( it->pickup_name, pickupName ) ) return it; @@ -1024,7 +1023,7 @@ qboolean BG_CanItemBeGrabbed( int gametype, const entityState_t *ent, const play //return qfalse; //else return qtrue; // weapons are always picked up - + case IT_AMMO: //Blaze: pick up all ammo @@ -1103,7 +1102,7 @@ qboolean BG_CanItemBeGrabbed( int gametype, const entityState_t *ent, const play #endif case IT_TEAM: // team items, such as flags -#ifdef MISSIONPACK +#ifdef MISSIONPACK if( gametype == GT_1FCTF ) { // neutral flag can always be picked up if( item->giTag == PW_NEUTRALFLAG ) { @@ -1440,6 +1439,7 @@ void BG_TouchJumpPad( playerState_t *ps, entityState_t *jumppad ) { // then don't play the event sound again if we are in a fat trigger if ( ps->jumppad_ent != jumppad->number ) { + /* vectoangles( jumppad->origin2, angles); p = fabs( AngleNormalize180( angles[PITCH] ) ); if( p < 45 ) { @@ -1447,6 +1447,9 @@ void BG_TouchJumpPad( playerState_t *ps, entityState_t *jumppad ) { } else { effectNum = 1; } + */ + // NiceAss: For cutsom sounds... + effectNum = jumppad->generic1; BG_AddPredictableEventToPlayerstate( EV_JUMP_PAD, effectNum, ps ); } // remember hitting this jumppad this frame diff --git a/reaction/game/bg_pmove.c b/reaction/game/bg_pmove.c index 213ac76c..a6375c5d 100644 --- a/reaction/game/bg_pmove.c +++ b/reaction/game/bg_pmove.c @@ -1922,7 +1922,7 @@ static void PM_BeginWeaponChange( int weapon ) { PM_StartWeaponAnim(WP_ANIM_DISARM); else */ - if (pm->ps->weapon == WP_KNIFE && !(pm->ps->persistant[PERS_WEAPONMODES] & RQ3_KNIFEMODE)) + if ( pm->ps->weapon == WP_KNIFE && !(pm->ps->persistant[PERS_WEAPONMODES] & RQ3_KNIFEMODE) ) PM_StartWeaponAnim(WP_ANIM_THROWDISARM); else { PM_StartWeaponAnim(WP_ANIM_DISARM); @@ -1939,14 +1939,18 @@ static void PM_BeginWeaponChange( int weapon ) { // Elder: cancel burst shots pm->ps->stats[STAT_BURST] = 0; - pm->ps->weaponstate = WEAPON_DROPPING; - - // NiceAss: Added this. Is it a hack? - if (pm->ps->weapon == WP_GRENADE && pm->ps->ammo[pm->ps->weapon] == 0) { + // NiceAss: Added this as a fix for knifes and grenades when you throw the last one. + if ( ( (pm->ps->weapon == WP_GRENADE || pm->ps->weapon == WP_KNIFE) && pm->ps->ammo[pm->ps->weapon] == 0) && + pm->ps->weaponstate != WEAPON_FIRING ) + { + pm->ps->weaponstate = WEAPON_DROPPING; pm->ps->weaponTime = 0; return; } + pm->ps->weaponstate = WEAPON_DROPPING; + + //Elder: temp hack /* if (pm->ps->weapon == WP_PISTOL || @@ -1989,10 +1993,11 @@ static void PM_FinishWeaponChange( void ) { weapon = WP_NONE; } - //Remove grenade if out of ammo - if (weapon == WP_GRENADE && pm->ps->ammo[WP_GRENADE] == 0) + //Remove grenade/knife if out of ammo + if ( (weapon == WP_GRENADE || weapon == WP_KNIFE) && pm->ps->ammo[weapon] == 0) { - pm->ps->stats[STAT_WEAPONS] &= ~(1 << WP_GRENADE); + if (weapon == WP_GRENADE) pm->ps->stats[STAT_WEAPONS] &= ~(1 << WP_GRENADE); + if (weapon == WP_KNIFE) pm->ps->stats[STAT_WEAPONS] &= ~(1 << WP_KNIFE); weapon = WP_PISTOL; } @@ -2049,14 +2054,12 @@ static void PM_FinishWeaponChange( void ) { PM_StartWeaponAnim(WP_ANIM_ACTIVATE); */ /*else*/ - if (pm->ps->weapon == WP_KNIFE && !(pm->ps->persistant[PERS_WEAPONMODES] & RQ3_KNIFEMODE)) PM_StartWeaponAnim(WP_ANIM_THROWACTIVATE); else PM_StartWeaponAnim(WP_ANIM_ACTIVATE); PM_StartTorsoAnim( TORSO_RAISE ); - } @@ -2360,8 +2363,9 @@ static void PM_Reload( void ) pm->ps->ammo[WP_AKIMBO] = RQ3_AKIMBO_AMMO; } - if ( !(pm->ps->stats[STAT_RQ3] & RQ3_LOCKRELOADS) ) + if ( !(pm->ps->stats[STAT_RQ3] & RQ3_LOCKRELOADS) ) { pm->ps->ammo[pm->ps->weapon] = ammotoadd; + } // handle continuous fast-reloads if ((pm->ps->weapon == WP_M3 || pm->ps->weapon == WP_SSG3000) && @@ -2516,6 +2520,23 @@ static void PM_Weapon( void ) { pm->cmd.buttons |= BUTTON_ATTACK; } + //agt: Knife stupidity + //I'll hijack STAT_BURST for this one + if( pm->ps->weapon == WP_KNIFE && (pm->ps->persistant[PERS_WEAPONMODES] & RQ3_KNIFEMODE) ) { + if (pm->cmd.buttons & BUTTON_ATTACK && + pm->ps->stats[STAT_BURST] >= 0 && pm->ps->stats[STAT_BURST] < 5) + { + pm->cmd.buttons |= BUTTON_ATTACK; + } + else if (pm->ps->stats[STAT_BURST] > 4) { + pm->ps->stats[STAT_BURST] = 0; + pm->ps->weaponTime += 650; // NiceAss note: 30ms * 5 attacks = 150 ms + 650ms = 800ms. + } + else if (pm->ps->stats[STAT_BURST] > 0) { + pm->cmd.buttons |= BUTTON_ATTACK; + } + } + //Elder: New semi-auto code if ( pm->ps->weapon == WP_PISTOL && (pm->ps->persistant[PERS_WEAPONMODES] & RQ3_MK23MODE) == RQ3_MK23MODE) @@ -2581,6 +2602,11 @@ static void PM_Weapon( void ) { } */ + // NiceAss: Sorta a hack, but it looks better. +/* if ( pm->ps->weapon == WP_PISTOL && pm->ps->ammo[WP_PISTOL] == 0 && pm->ps->weaponTime < RQ3_PISTOL_DELAY*.3 ) { + PM_StartWeaponAnim( WP_ANIM_EMPTY ); + }*/ + // make weapon function if ( pm->ps->weaponTime > 0 ) { pm->ps->weaponTime -= pml.msec; @@ -2605,7 +2631,7 @@ static void PM_Weapon( void ) { if ( pm->ps->weapon == WP_GRENADE && pm->ps->weaponstate == WEAPON_COCKED) { pm->ps->weaponstate = WEAPON_FIRING; pm->cmd.buttons &= ~BUTTON_ATTACK; - PM_AddEvent( EV_FIRE_WEAPON ); + PM_AddEvent2( EV_FIRE_WEAPON, RQ3_WPMOD_GRENADEDROP ); pm->ps->ammo[WP_GRENADE]--; } PM_BeginWeaponChange( pm->cmd.weapon ); @@ -2669,7 +2695,30 @@ static void PM_Weapon( void ) { return; } - if ( pm->ps->weaponstate == WEAPON_RAISING ) { + //NiceAss: Attempt to have the knife/grenade "activate" after a throw if you have another one of them + if ( pm->ps->weaponstate == WEAPON_FIRING && pm->ps->ammo[pm->ps->weapon] > 0 && + (pm->ps->weapon == WP_KNIFE || pm->ps->weapon == WP_GRENADE) ) { + + if (pm->ps->weapon == WP_KNIFE && !(pm->ps->persistant[PERS_WEAPONMODES] & RQ3_KNIFEMODE)) + { + pm->ps->weaponTime = RQ3_KNIFE_ACTIVATE_DELAY; + PM_StartWeaponAnim(WP_ANIM_THROWACTIVATE); + pm->ps->weaponstate = WEAPON_RAISING; + PM_StartTorsoAnim( TORSO_RAISE ); + return; + } + if (pm->ps->weapon == WP_GRENADE) + { + pm->ps->weaponTime = RQ3_GRENADE_DELAY; + PM_StartWeaponAnim(WP_ANIM_ACTIVATE); + pm->ps->weaponstate = WEAPON_RAISING; + PM_StartTorsoAnim( TORSO_RAISE ); + return; + } + } + + if ( pm->ps->weaponstate == WEAPON_RAISING && + !( ( pm->ps->persistant[PERS_WEAPONMODES] & RQ3_KNIFEMODE) && pm->ps->stats[STAT_BURST]) ) { pm->ps->weaponstate = WEAPON_READY; if ( pm->ps->weapon == WP_KNIFE ) { PM_StartTorsoAnim( TORSO_STAND2 ); @@ -2699,9 +2748,15 @@ static void PM_Weapon( void ) { PM_StartWeaponAnim( WP_ANIM_THROWIDLE ); else PM_StartWeaponAnim( WP_ANIM_IDLE ); + return; } + // NiceAss: Added for knife animation switch. + // At the moment, this is only used for changing knife-throw modes. + if ( pm->ps->weaponstate == WEAPON_MODECHANGE ) { + if ( pm->ps->weapon == WP_KNIFE) pm->ps->weaponstate = WEAPON_READY; + } // Elder: fire on release - based on code from inolen // check for fire @@ -2719,15 +2774,15 @@ static void PM_Weapon( void ) { PM_ContinueWeaponAnim(WP_ANIM_EXTRA1); return; } - // NiceAss: Fix for the double-grenade bug (pm->ps->weaponstate == WEAPON_FIRING) - else if ( pm->ps->weaponstate == WEAPON_COCKED || pm->ps->weaponstate == WEAPON_FIRING) + else if ( pm->ps->weaponstate == WEAPON_COCKED ) return; } // Elder: stall the thrown knife action else if ( pm->ps->weapon == WP_KNIFE && pm->ps->weaponstate != WEAPON_STALL && pm->ps->stats[STAT_WEAPONSTALLTIME] <= 0 && - !(pm->ps->persistant[PERS_WEAPONMODES] & RQ3_KNIFEMODE) ) + !(pm->ps->persistant[PERS_WEAPONMODES] & RQ3_KNIFEMODE) && + pm->ps->ammo[pm->ps->weapon]) { pm->ps->weaponstate = WEAPON_STALL; pm->ps->stats[STAT_WEAPONSTALLTIME] = 200; @@ -2829,7 +2884,13 @@ static void PM_Weapon( void ) { // check for out of ammo if ( ! pm->ps->ammo[ pm->ps->weapon ]) { PM_AddEvent( EV_NOAMMO ); - pm->ps->weaponTime += 500; + //NiceAss: Dirty hack: + if (pm->ps->weapon == WP_KNIFE || pm->ps->weapon == WP_GRENADE) + //PM_FinishWeaponChange(); + pm->ps->weaponstate = WEAPON_DROPPING; + else + pm->ps->weaponTime += 500; + return; } @@ -2856,7 +2917,8 @@ static void PM_Weapon( void ) { */ if ( pm->ps->weapon == WP_KNIFE && (pm->ps->persistant[PERS_WEAPONMODES] & RQ3_KNIFEMODE) ) - PM_StartWeaponAnim( WP_ANIM_FIRE ); + // Modified by agt for slash "bursting" + if(!pm->ps->stats[STAT_BURST]) PM_StartWeaponAnim( WP_ANIM_FIRE ); PM_StartTorsoAnim( TORSO_ATTACK2 ); } else { @@ -2885,10 +2947,15 @@ static void PM_Weapon( void ) { pm->ps->weapon == WP_M4 || pm->ps->weapon == WP_MP5 || pm->ps->weapon == WP_GRENADE) */ - PM_StartWeaponAnim( WP_ANIM_FIRE ); + //if ( pm->ps->ammo[pm->ps->weapon] > 1 ) + PM_StartWeaponAnim( WP_ANIM_FIRE ); + //else + // PM_StartWeaponAnim( WP_ANIM_EMPTY ); } } + //NiceAss: Hack of the week!!!! + if (pm->ps->weaponstate == WEAPON_FIRING && pm->ps->weapon == WP_GRENADE) return; pm->ps->weaponstate = WEAPON_FIRING; @@ -2902,7 +2969,9 @@ static void PM_Weapon( void ) { (pm->ps->weapon == WP_MP5 && (pm->ps->persistant[PERS_WEAPONMODES] & RQ3_MP5MODE) == RQ3_MP5MODE) || (pm->ps->weapon == WP_PISTOL && - (pm->ps->persistant[PERS_WEAPONMODES] & RQ3_MK23MODE) == RQ3_MK23MODE)) + (pm->ps->persistant[PERS_WEAPONMODES] & RQ3_MK23MODE) == RQ3_MK23MODE) || + (pm->ps->weapon == WP_KNIFE && + (pm->ps->persistant[PERS_WEAPONMODES] & RQ3_KNIFEMODE) == RQ3_KNIFEMODE) ) { pm->ps->stats[STAT_BURST]++; } @@ -2970,10 +3039,15 @@ static void PM_Weapon( void ) { if (bg_itemlist[pm->ps->stats[STAT_HOLDABLE_ITEM]].giTag == HI_SILENCER && (pm->ps->weapon == WP_PISTOL || pm->ps->weapon == WP_MP5 || - pm->ps->weapon == WP_SSG3000)) - { + pm->ps->weapon == WP_SSG3000)) { PM_AddEvent2( EV_FIRE_WEAPON, RQ3_WPMOD_SILENCER ); } + else if (pm->ps->stats[STAT_BURST] > 1 && pm->ps->weapon == WP_KNIFE && + (pm->ps->persistant[PERS_WEAPONMODES] & RQ3_KNIFEMODE) == RQ3_KNIFEMODE) + { + // NiceAss: Prevent the client from doing stuff after the first "slash". + PM_AddEvent2( EV_FIRE_WEAPON, RQ3_WPMOD_KNIFENOMARK); + } else PM_AddEvent( EV_FIRE_WEAPON ); @@ -2995,7 +3069,14 @@ static void PM_Weapon( void ) { case WP_KNIFE: if ( (pm->ps->persistant[PERS_WEAPONMODES] & RQ3_KNIFEMODE) == RQ3_KNIFEMODE) { //knife slash - addTime = RQ3_KNIFE_DELAY; + //agt: hacking it up a little. The alternate time value should be + //a constant, but I have a headache and I'm tired of screwing around + //with the knives. [NiceAss: I'll do it for you!] + if(pm->ps->stats[STAT_BURST]) { + addTime = RQ3_KNIFE_SLASH_BURST; //NiceAss: Not really a burst, but it fits with everything else =D + } else { + addTime = RQ3_KNIFE_DELAY; + } } else { //knife throw diff --git a/reaction/game/bg_public.h b/reaction/game/bg_public.h index ff76f945..dfd4ddd1 100644 --- a/reaction/game/bg_public.h +++ b/reaction/game/bg_public.h @@ -222,8 +222,9 @@ typedef enum { #define RQ3_AKIMBO_DELAY 100 #define RQ3_AKIMBO_DELAY2 300 #define RQ3_KNIFE_DELAY 800 -#define RQ3_THROW_DELAY 800 -#define RQ3_GRENADE_DELAY 750 // Elder: I made this up +#define RQ3_THROW_DELAY 300 // NiceAss: Was 800, but much too slow. +#define RQ3_KNIFE_SLASH_BURST 30 // NiceAss: For slashing every 30 ms. (Agt's arbitrary number of the day =)) +#define RQ3_GRENADE_DELAY 300 // NiceAss: Was 750, but much too slow. //Elder: reload delays //Also kinda "derived" from the AQ2 source @@ -251,7 +252,7 @@ typedef enum { //Elder: each weapon also has a different weapon switch up delay... ugh bloody hell #define RQ3_PISTOL_ACTIVATE_DELAY 900 #define RQ3_M3_ACTIVATE_DELAY 700 -#define RQ3_M4_ACTIVATE_DELAY 1000 +#define RQ3_M4_ACTIVATE_DELAY 700 // 1000 #define RQ3_MP5_ACTIVATE_DELAY 1000 #define RQ3_HANDCANNON_ACTIVATE_DELAY 600 #define RQ3_SSG3000_ACTIVATE_DELAY 800 @@ -287,6 +288,11 @@ typedef enum { //Elder: weapon modifications #define RQ3_WPMOD_SILENCER 1 #define RQ3_WPMOD_KNIFESLASH 2 +// NiceAss: Used after the first "slash" of the knife. +// A bit misleading in its name. It also means there will be no sound. +#define RQ3_WPMOD_KNIFENOMARK 3 +// Niceass: If you are switching weapons, the grenade is dropped rather than thrown. +#define RQ3_WPMOD_GRENADEDROP 4 // // config strings are a general means of communicating variable length strings @@ -376,7 +382,9 @@ typedef enum { WEAPON_DROPPING, //sync with WP_ANIM_DISARM WEAPON_FIRING, //sync with WP_ANIM_FIRE WEAPON_RELOADING, //sync with WP_ANIM_RELOAD - WEAPON_STALL //for delaying weapon fires (knife, grenade) + WEAPON_STALL, //for delaying weapon fires (knife, grenade) + WEAPON_MODECHANGE, // NiceAss: sync with WP_ANIM_EXTRA1 & WP_ANIM_EXTRA2 for knife. + WEAPON_BANDAGING // NiceAss: Added to follow AQ2 and fix a bug. } weaponstate_t; //Blaze: for the weapon animation states @@ -841,7 +849,7 @@ typedef enum { EV_GLOBAL_SOUND, // no attenuation EV_GLOBAL_TEAM_SOUND, EV_RQ3_SOUND, // Elder: play local sounds - intended for kick - + EV_DMREWARD, // Duffman: To display expotional reward messages. EV_BULLET_HIT_FLESH, diff --git a/reaction/game/g_active.c b/reaction/game/g_active.c index 472728ad..a5d32a27 100644 --- a/reaction/game/g_active.c +++ b/reaction/game/g_active.c @@ -2,6 +2,10 @@ // #include "g_local.h" +#ifdef __ZCAM__ +#include "zcam.h" +#endif /* __ZCAM__ */ + //Elder: got rid of these //extern float s_quadFactor; @@ -339,7 +343,7 @@ void ClientImpacts( gentity_t *ent, pmove_t *pm ) { G_TouchTriggers Find all trigger entities that ent's current position touches. -Spectators will only interact with teleporters. +Spectators will only interact with teleporters (and door triggers for spectators) ============ */ void G_TouchTriggers( gentity_t *ent ) { @@ -417,11 +421,17 @@ void G_TouchTriggers( gentity_t *ent ) { ent->client->ps.jumppad_frame = 0; ent->client->ps.jumppad_ent = 0; } + + if (ent->client->openDoor == 2) { + ent->client->openDoor = qfalse; + ent->client->openDoorTime = 0; + } } /* ================= SpectatorThink +NiceAss: Heavy modifications will be here for AQ2-like spectator mode and zcam!? ================= */ void SpectatorThink( gentity_t *ent, usercmd_t *ucmd ) { @@ -430,6 +440,24 @@ void SpectatorThink( gentity_t *ent, usercmd_t *ucmd ) { client = ent->client; + + client->oldbuttons = client->buttons; + client->buttons = ucmd->buttons; + + // attack button cycles through spectators + if ( ( client->buttons & BUTTON_ATTACK ) && ! ( client->oldbuttons & BUTTON_ATTACK ) ) { + Cmd_FollowCycle_f( ent, 1 ); + } + +#ifdef __ZCAM__ + if ( client->sess.spectatorState == SPECTATOR_CAMERA_FLIC && + client->sess.spectatorState == SPECTATOR_CAMERA_SWING ) + { + camera_think(ent); + return; + } +#endif + if ( client->sess.spectatorState != SPECTATOR_FOLLOW ) { client->ps.pm_type = PM_SPECTATOR; client->ps.speed = 400; // faster than normal @@ -450,14 +478,6 @@ void SpectatorThink( gentity_t *ent, usercmd_t *ucmd ) { G_TouchTriggers( ent ); trap_UnlinkEntity( ent ); } - - client->oldbuttons = client->buttons; - client->buttons = ucmd->buttons; - - // attack button cycles through spectators - if ( ( client->buttons & BUTTON_ATTACK ) && ! ( client->oldbuttons & BUTTON_ATTACK ) ) { - Cmd_FollowCycle_f( ent, 1 ); - } } @@ -585,7 +605,6 @@ void ClientTimerActions( gentity_t *ent, int msec ) { ent->client->ps.stats[STAT_RQ3] &= ~RQ3_BANDAGE_WORK; //Elder: moved from somewhere - err, g_cmds.c I think ent->client->ps.stats[STAT_RQ3] &= ~RQ3_LEGDAMAGE; - // ent->client->ps.weaponstate = WEAPON_RAISING; // ent->client->ps.torsoAnim = ( ( ent->client->ps.torsoAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | TORSO_RAISE; // NiceAss: clear last player to hit you. @@ -1397,14 +1416,29 @@ void ClientThink( int clientNum ) { // phone jack if they don't get any for a while ent->client->lastCmdTime = level.time; - if ( !(ent->r.svFlags & SVF_BOT) && !g_synchronousClients.integer ) { + if ( !(ent->r.svFlags & SVF_BOT) && !g_synchronousClients.integer +#ifdef __ZCAM__ + /* camera jitter fix (server side) */ + && (ent->client->sess.sessionTeam != TEAM_SPECTATOR + || (ent->client->sess.sessionTeam == TEAM_SPECTATOR + && ent->client->sess.spectatorState == SPECTATOR_FOLLOW)) +#endif /* __ZCAM__ */ + ) { ClientThink_real( ent ); } } void G_RunClient( gentity_t *ent ) { - if ( !(ent->r.svFlags & SVF_BOT) && !g_synchronousClients.integer ) { + if ( !(ent->r.svFlags & SVF_BOT) && !g_synchronousClients.integer + #ifdef __ZCAM__ + /* camera jitter fix (server side) */ + && (ent->client->sess.sessionTeam != TEAM_SPECTATOR + || (ent->client->sess.sessionTeam == TEAM_SPECTATOR + && ent->client->sess.spectatorState == SPECTATOR_FOLLOW)) + #endif /* __ZCAM__ */ + ) + { return; } ent->client->pers.cmd.serverTime = level.time; diff --git a/reaction/game/g_client.c b/reaction/game/g_client.c index 5c2ceb77..e942b5c0 100644 --- a/reaction/game/g_client.c +++ b/reaction/game/g_client.c @@ -1,6 +1,9 @@ // Copyright (C) 1999-2000 Id Software, Inc. // #include "g_local.h" +#ifdef __ZCAM__ +#include "zcam.h" +#endif /* __ZCAM__ */ #define RQ3_NONAMEPLAYER "Nameless" @@ -693,6 +696,8 @@ void ClientUserinfoChanged( int clientNum ) { char redTeam[MAX_INFO_STRING]; char blueTeam[MAX_INFO_STRING]; char userinfo[MAX_INFO_STRING]; + // NiceAss: Added the following. Needed to prevent all models but "grunt" + char *skin2, model2[MAX_STRING_CHARS]; ent = g_entities + clientNum; client = ent->client; @@ -761,10 +766,26 @@ void ClientUserinfoChanged( int clientNum ) { Q_strncpyz( model, Info_ValueForKey (userinfo, "team_model"), sizeof( model ) ); Q_strncpyz( headModel, Info_ValueForKey (userinfo, "team_headmodel"), sizeof( headModel ) ); } else { - Q_strncpyz( model, Info_ValueForKey (userinfo, "model"), sizeof( model ) ); + Q_strncpyz( model, Info_ValueForKey (userinfo, "model"), sizeof( model ) ); Q_strncpyz( headModel, Info_ValueForKey (userinfo, "headmodel"), sizeof( headModel ) ); } + // NiceAss: temporary hack to prevent non-grunt models: + Q_strncpyz(model2, model, sizeof(model)); + skin2 = Q_strrchr( model2, '/' ); + if ( skin2 ) { + *skin2++ = '\0'; + } else { + skin2 = "default"; + } + + if ( Q_stricmpn(model2, "grunt", sizeof(model2) ) ) { + trap_SendServerCommand( ent-g_entities, va("print \"Illegal player model. Forcing change on server.\n\"")); + Q_strncpyz(model, "grunt/resdog", sizeof("grunt/resdog")); + Q_strncpyz(headModel, "grunt/resdog", sizeof("grunt/resdog")); + } + // End of temporary hack. + // bots set their team a few frames later if (g_gametype.integer >= GT_TEAM && g_entities[clientNum].r.svFlags & SVF_BOT) { s = Info_ValueForKey( userinfo, "team" ); @@ -881,6 +902,8 @@ int G_SendCheatVars(int clientNum) char cheatVar[40], cl_cheatvar[128]; float lowval, highval; + //NiceAss: Added so /devmap will not have the client check cvars. Lie to the server that it loaded fine =) + if (g_cheats.integer) return qtrue; // load the file len = trap_FS_FOpenFile( filename, &f, FS_READ ); @@ -1262,6 +1285,11 @@ void ClientSpawn(gentity_t *ent) { VectorCopy (playerMaxs, ent->r.maxs); client->ps.clientNum = index; + +#ifdef __ZCAM__ + camera_begin (ent); +#endif /* __ZCAM__ */ + //Blaze: changed WP_MACHINEGUN to WP_PISTOL, makes the base weapon you start with the pistol client->ps.stats[STAT_WEAPONS] = ( 1 << WP_PISTOL ); //Blaze: Set starting amo for the machine gun, different in teamplay and dm, we can remove this @@ -1431,6 +1459,10 @@ void ClientDisconnect( int clientNum ) { } } +#ifdef __ZCAM__ + camera_disconnect (ent); +#endif /* __ZCAM__ */ + // send effect if they were completely connected if ( ent->client->pers.connected == CON_CONNECTED && ent->client->sess.sessionTeam != TEAM_SPECTATOR ) { diff --git a/reaction/game/g_cmds.c b/reaction/game/g_cmds.c index 0c55aa9f..24863de5 100644 --- a/reaction/game/g_cmds.c +++ b/reaction/game/g_cmds.c @@ -1,6 +1,9 @@ // Copyright (C) 1999-2000 Id Software, Inc. // #include "g_local.h" +#ifdef __ZCAM__ +#include "zcam.h" +#endif /* __ZACM__ */ //Blaze: was there a extra ../ here? #include "../ui/menudef.h" // for the voice chats @@ -1695,7 +1698,7 @@ void Cmd_Bandage (gentity_t *ent) ^ ANIM_TOGGLEBIT ) | WP_ANIM_DISARM; } else */ - if (ent->client->ps.weapon == WP_KNIFE && (ent->client->ps.persistant[PERS_WEAPONMODES] & RQ3_KNIFEMODE)) + if (ent->client->ps.weapon == WP_KNIFE && !(ent->client->ps.persistant[PERS_WEAPONMODES] & RQ3_KNIFEMODE)) { ent->client->ps.generic1 = ( ( ent->client->ps.generic1 & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | WP_ANIM_THROWDISARM; @@ -2257,18 +2260,29 @@ void Cmd_Weapon(gentity_t *ent) } break; case WP_KNIFE: + // NiceAss: weapon animation/state check before the mode switch. + if ( ent->client->ps.weaponstate != WEAPON_READY ) break; + // toggle throwing/slashing - if ((ent->client->ps.persistant[PERS_WEAPONMODES] & RQ3_KNIFEMODE) == RQ3_KNIFEMODE) + if ( (ent->client->ps.persistant[PERS_WEAPONMODES] & RQ3_KNIFEMODE) == RQ3_KNIFEMODE) { //Elder: added ent->client->ps.persistant[PERS_WEAPONMODES] &= ~RQ3_KNIFEMODE; trap_SendServerCommand( ent-g_entities, va("print \"Switched to throwing.\n\"")); + // Niceass: Animations added + ent->client->ps.weaponstate = WEAPON_MODECHANGE; + ent->client->ps.weaponTime = 550; + ent->client->ps.generic1 = ( ( ent->client->ps.generic1 & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | WP_ANIM_EXTRA1; } else { //Elder: we're gonna use this to flag throw or slash with the knife ent->client->ps.persistant[PERS_WEAPONMODES] |= RQ3_KNIFEMODE; trap_SendServerCommand( ent-g_entities, va("print \"Switched to slashing.\n\"")); + // Niceass: Animations added + ent->client->ps.weaponstate = WEAPON_MODECHANGE; + ent->client->ps.weaponTime = 550; + ent->client->ps.generic1 = ( ( ent->client->ps.generic1 & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | WP_ANIM_EXTRA2; } break; case WP_HANDCANNON: @@ -2563,6 +2577,11 @@ void ClientCommand( int clientNum ) { //Elder: stuff for dropping items else if (Q_stricmp (cmd, "dropitem") == 0) Cmd_DropItem_f( ent ); +#ifdef __ZCAM__ + // NiceAss: removed + //else if (Q_stricmp (cmd, "camera") == 0) + // camera_cmd ( ent ); +#endif /* __ZCAM__ */ else if (Q_stricmp (cmd, "playerstats") == 0) { Cmd_PlayerStats_f( ent ); diff --git a/reaction/game/g_combat.c b/reaction/game/g_combat.c index 8635ca31..83b731e4 100644 --- a/reaction/game/g_combat.c +++ b/reaction/game/g_combat.c @@ -16,6 +16,7 @@ void ScorePlum( gentity_t *ent, vec3_t origin, int score ) { plum = G_TempEntity( origin, EV_SCOREPLUM ); // only send this temp entity to a single client plum->r.svFlags |= SVF_SINGLECLIENT; + plum->r.singleClient = ent->s.number; // plum->s.otherEntityNum = ent->s.number; @@ -1496,6 +1497,66 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, } } + // NiceAss: Make sure it hit the player before doing this stuff. + // This was added when the possibility of missing was added from spherical head detection. + // We don't want someone flying back from a sniper to the head when it actually missed! + if ( G_HitPlayer ( targ, dir, point ) ) { + // figure momentum add, even if the damage won't be taken + if ( knockback && targ->client ) { + vec3_t kvel, flydir; + float mass; + + if ( mod != MOD_FALLING ) + { + VectorCopy(dir, flydir); + flydir[2] += 0.4f; + } + + mass = 200; + + //Elder: Q2 uses a hardcoded value of 500 for non-rocket jumps + //Q3 uses g_knockback.value ... default 1000 + //AQ2: + //VectorScale (flydir, 500.0 * (float)knockback / mass, kvel); + //RQ3: + //VectorScale (dir, g_knockback.value * (float)knockback / mass, kvel); + if (targ->client && attacker == targ) + VectorScale (flydir, 1600.0 * (float)knockback / mass, kvel); + else + VectorScale (flydir, 500.0 * (float)knockback / mass, kvel); + VectorAdd (targ->client->ps.velocity, kvel, targ->client->ps.velocity); + + // set the timer so that the other client can't cancel + // out the movement immediately + if ( !targ->client->ps.pm_time ) { + int t; + + t = knockback * 2; + if ( t < 50 ) { + t = 50; + } + if ( t > 200 ) { + t = 200; + } + targ->client->ps.pm_time = t; + targ->client->ps.pm_flags |= PMF_TIME_KNOCKBACK; + } + } + + // NiceAss: This was moved too + // 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) + { + if ( OnSameTeam( targ, attacker ) ) { + attacker->client->ps.persistant[PERS_HITS]--; + } else { + attacker->client->ps.persistant[PERS_HITS]++; + } + attacker->client->ps.persistant[PERS_ATTACKEE_ARMOR] = (targ->health<<8)|(client->ps.stats[STAT_ARMOR]); + } + } // check for completely getting out of the damage if ( !(dflags & DAMAGE_NO_PROTECTION) ) { @@ -1865,62 +1926,6 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, // End Duffman } - // NiceAss: This whole "if" statement was moved down so it wouldn't happen if you missed the head. (spherical hit detection stuff) - // figure momentum add, even if the damage won't be taken - if ( knockback && targ->client ) { - vec3_t kvel, flydir; - float mass; - - if ( mod != MOD_FALLING ) - { - VectorCopy(dir, flydir); - flydir[2] += 0.4f; - } - - mass = 200; - - //Elder: Q2 uses a hardcoded value of 500 for non-rocket jumps - //Q3 uses g_knockback.value ... default 1000 - //AQ2: - //VectorScale (flydir, 500.0 * (float)knockback / mass, kvel); - //RQ3: - //VectorScale (dir, g_knockback.value * (float)knockback / mass, kvel); - if (targ->client && attacker == targ) - VectorScale (flydir, 1600.0 * (float)knockback / mass, kvel); - else - VectorScale (flydir, 500.0 * (float)knockback / mass, kvel); - VectorAdd (targ->client->ps.velocity, kvel, targ->client->ps.velocity); - - // set the timer so that the other client can't cancel - // out the movement immediately - if ( !targ->client->ps.pm_time ) { - int t; - - t = knockback * 2; - if ( t < 50 ) { - t = 50; - } - if ( t > 200 ) { - t = 200; - } - targ->client->ps.pm_time = t; - targ->client->ps.pm_flags |= PMF_TIME_KNOCKBACK; - } - } - - // NiceAss: This was moved too - // 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) { - if ( OnSameTeam( targ, attacker ) ) { - attacker->client->ps.persistant[PERS_HITS]--; - } else { - attacker->client->ps.persistant[PERS_HITS]++; - } - attacker->client->ps.persistant[PERS_ATTACKEE_ARMOR] = (targ->health<<8)|(client->ps.stats[STAT_ARMOR]); - } - // 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 @@ -1948,7 +1953,7 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker, // G_Printf("(%d) taken as damage\n",take); if (instant_dam) { - //G_Printf("(%d) instant damage\n",take); + // G_Printf("(%d) instant damage\n",take); targ->health = targ->health - take; } if ( targ->client ) { @@ -2060,6 +2065,8 @@ CanDamage Returns qtrue if the inflictor can directly damage the target. Used for explosions and melee attacks. + +NICEASS TODO: Impliment G_HitPlayer in this func for clients. ============ */ qboolean CanDamage (gentity_t *targ, vec3_t origin) { @@ -2074,6 +2081,7 @@ qboolean CanDamage (gentity_t *targ, vec3_t origin) { VectorCopy (midpoint, dest); trap_Trace ( &tr, origin, vec3_origin, vec3_origin, dest, ENTITYNUM_NONE, MASK_SOLID); + if (tr.fraction == 1.0 || tr.entityNum == targ->s.number) return qtrue; diff --git a/reaction/game/g_items.c b/reaction/game/g_items.c index 68e1a3de..b2389f59 100644 --- a/reaction/game/g_items.c +++ b/reaction/game/g_items.c @@ -1031,6 +1031,7 @@ gentity_t *dropWeapon( gentity_t *ent, gitem_t *item, float angle, int xr_flags VectorSet (maxs, ITEM_RADIUS, ITEM_RADIUS, ITEM_RADIUS); // NiceAss: Check if the new location starts in a solid. + // FIXME: Use trap_point or whatever? trap_Trace( &tr, origin, mins, maxs, origin, ent->s.number, MASK_SOLID ); if (tr.startsolid == qtrue) VectorMA( origin, -7, velocity, origin ); // -5 won't work (hint: it should work). Only -7 or less will.. @@ -1381,7 +1382,9 @@ void G_BounceItem( gentity_t *ent, trace_t *trace ) { VectorScale( ent->s.pos.trDelta, ent->physicsBounce, ent->s.pos.trDelta ); // check for stop - if ( trace->plane.normal[2] > 0 && ent->s.pos.trDelta[2] < 40 ) { + + if ( ( trace->plane.normal[2] > 0 && ent->s.pos.trDelta[2] < 40 ) || + ( trace->plane.normal[2] > .7 ) ) { trace->endpos[2] += 1.0; // make sure it is off ground SnapVector( trace->endpos ); G_SetOrigin( ent, trace->endpos ); @@ -1389,6 +1392,7 @@ void G_BounceItem( gentity_t *ent, trace_t *trace ) { return; } + VectorAdd( ent->r.currentOrigin, trace->plane.normal, ent->r.currentOrigin); VectorCopy( ent->r.currentOrigin, ent->s.pos.trBase ); ent->s.pos.trTime = level.time; diff --git a/reaction/game/g_local.h b/reaction/game/g_local.h index e383a82a..4b104b89 100644 --- a/reaction/game/g_local.h +++ b/reaction/game/g_local.h @@ -11,6 +11,9 @@ // the "gameversion" client command will print this plus compile date #define GAMEVERSION "reaction" +// NiceAss: Took it out until later. +// #define __ZCAM__ + #define BODY_QUEUE_SIZE 8 // Blaze: How long someone bleeds for @@ -207,6 +210,10 @@ typedef enum { SPECTATOR_NOT, SPECTATOR_FREE, SPECTATOR_FOLLOW, +#ifdef __ZCAM__ + SPECTATOR_CAMERA_FLIC, + SPECTATOR_CAMERA_SWING, +#endif SPECTATOR_SCOREBOARD } spectatorState_t; @@ -284,6 +291,9 @@ typedef struct { int records[REC_NUM_RECORDS]; // Elder: for our statistics tracking } clientPersistant_t; +#ifdef __ZCAM__ +struct camera_s; +#endif /* __ZCAM__ */ // Elder: spam prevention defaults /* @@ -395,7 +405,7 @@ struct gclient_s { // End Duffman int weaponCount[WP_NUM_WEAPONS]; // Elder: for duplicate unique weapon tracking - qboolean openDoor; //Blaze: used to hold if someone has hit opendoor key + int openDoor; //Blaze: used to hold if someone has hit opendoor key int openDoorTime; // timeResidual is used to handle events that happen every second @@ -437,7 +447,7 @@ struct gclient_s { int uniqueItems; int killStreak; // Elder: replaces the old STAT_STREAK qboolean kevlarHit; // Elder: kevlar hit -- FIXME: poor implementation - + int knife_sound; // NiceAss: What did the player hit while slashing? #ifdef MISSIONPACK gentity_t *persistantPowerup; @@ -447,6 +457,9 @@ struct gclient_s { #endif char *areabits; +#ifdef __ZCAM__ + struct camera_s *camera; +#endif /* __ZCAM__ */ }; diff --git a/reaction/game/g_main.c b/reaction/game/g_main.c index 3f9c9983..1e8e39da 100644 --- a/reaction/game/g_main.c +++ b/reaction/game/g_main.c @@ -2,6 +2,9 @@ // #include "g_local.h" +#ifdef __ZCAM__ +#include "zcam.h" +#endif /* __ZCAM__ */ level_locals_t level; @@ -327,11 +330,11 @@ void G_RemapTeamShaders() { char string[1024]; float f = level.time * 0.001; Com_sprintf( string, sizeof(string), "team_icon/%s_red", g_redteam.string ); - AddRemap("textures/ctf2/redteam01", string, f); - AddRemap("textures/ctf2/redteam02", string, f); + AddRemap("textures/ctf2/redteam01", string, f); + AddRemap("textures/ctf2/redteam02", string, f); Com_sprintf( string, sizeof(string), "team_icon/%s_blue", g_blueteam.string ); - AddRemap("textures/ctf2/blueteam01", string, f); - AddRemap("textures/ctf2/blueteam02", string, f); + AddRemap("textures/ctf2/blueteam01", string, f); + AddRemap("textures/ctf2/blueteam02", string, f); trap_SetConfigstring(CS_SHADERSTATE, BuildShaderStateConfig()); #endif } @@ -389,7 +392,7 @@ void G_UpdateCvars( void ) { cv->modificationCount = cv->vmCvar->modificationCount; if ( cv->trackChange ) { - trap_SendServerCommand( -1, va("print \"Server: %s changed to %s\n\"", + trap_SendServerCommand( -1, va("print \"Server: %s changed to %s\n\"", cv->cvarName, cv->vmCvar->string ) ); } @@ -469,13 +472,17 @@ void G_InitGame( int levelTime, int randomSeed, int restart ) { g_entities[i].client = level.clients + i; } +#ifdef __ZCAM__ + camera_init (); +#endif /* __ZCAM__ */ + // always leave room for the max number of clients, // even if they aren't all used, so numbers inside that // range are NEVER anything but clients level.num_entities = MAX_CLIENTS; // let the server system know where the entites are - trap_LocateGameData( level.gentities, level.num_entities, sizeof( gentity_t ), + trap_LocateGameData( level.gentities, level.num_entities, sizeof( gentity_t ), &level.clients[0].ps, sizeof( level.clients[0] ) ); // reserve some spots for dead player bodies @@ -542,6 +549,10 @@ void G_ShutdownGame( int restart ) { trap_FS_FCloseFile( level.logFile ); } +#ifdef __ZCAM__ + camera_shutdown (); +#endif /* __ZCAM__ */ + // write all the client session data so we can get it back G_WriteSessionData(); @@ -622,7 +633,7 @@ void AddTournamentPlayer( void ) { continue; } // never select the dedicated follow or scoreboard clients - if ( client->sess.spectatorState == SPECTATOR_SCOREBOARD || + if ( client->sess.spectatorState == SPECTATOR_SCOREBOARD || client->sess.spectatorClient < 0 ) { continue; } @@ -800,7 +811,7 @@ void CalculateRanks( void ) { if ( level.clients[i].sess.sessionTeam != TEAM_SPECTATOR ) { level.numNonSpectatorClients++; - + // decide if this should be auto-followed if ( level.clients[i].pers.connected == CON_CONNECTED ) { level.numPlayingClients++; @@ -821,7 +832,7 @@ void CalculateRanks( void ) { } } - qsort( level.sortedClients, level.numConnectedClients, + qsort( level.sortedClients, level.numConnectedClients, sizeof(level.sortedClients[0]), SortRanks ); // set the rank value for all clients that are connected and not spectators @@ -837,7 +848,7 @@ void CalculateRanks( void ) { cl->ps.persistant[PERS_RANK] = 1; } } - } else { + } else { rank = -1; score = 0; for ( i = 0; i < level.numPlayingClients; i++ ) { @@ -1032,7 +1043,7 @@ void BeginIntermission( void ) { ExitLevel When the intermission has been exited, the server is either killed -or moved to a new level based on the "nextmap" cvar +or moved to a new level based on the "nextmap" cvar ============= */ @@ -1053,7 +1064,7 @@ void ExitLevel (void) { level.changemap = NULL; level.intermissiontime = 0; } - return; + return; } @@ -1341,7 +1352,7 @@ qboolean ScoreIsTied( void ) { if ( level.numPlayingClients < 2 ) { return qfalse; } - + if ( g_gametype.integer >= GT_TEAM ) { return level.teamScores[TEAM_RED] == level.teamScores[TEAM_BLUE]; } @@ -1387,7 +1398,7 @@ void CheckExitRules( void ) { return; } - // check for sudden death + // check for sudden death if ( ScoreIsTied() ) { // always wait for sudden death return; @@ -1766,7 +1777,7 @@ void G_RunThink (gentity_t *ent) { if (thinktime > level.time) { return; } - + ent->nextthink = 0; if (!ent->think) { G_Error ( "NULL ent->think"); @@ -1836,8 +1847,8 @@ start = trap_Milliseconds(); //Elder: removed //xr_drop= dropWeapon( ent, xr_item, 0, FL_THROWN_ITEM );//FL_DROPPED_ITEM | xr_drop = LaunchItem(xr_item, ent->s.pos.trBase, 0, FL_THROWN_KNIFE); - - + + G_FreeEntity( ent ); */ //} @@ -1952,22 +1963,22 @@ void RQ3_StartUniqueItems ( void ) angle += 30; rq3_item = BG_FindItemForHoldable( HI_KEVLAR ); - rq3_temp = (gentity_t*)SelectRandomDeathmatchSpawnPoint(); + rq3_temp = (gentity_t*)SelectRandomDeathmatchSpawnPoint(); Drop_Item (rq3_temp, rq3_item, angle); angle += 30; rq3_item = BG_FindItemForHoldable( HI_SILENCER ); - rq3_temp = (gentity_t*)SelectRandomDeathmatchSpawnPoint(); + rq3_temp = (gentity_t*)SelectRandomDeathmatchSpawnPoint(); Drop_Item (rq3_temp, rq3_item, angle); angle += 30; rq3_item = BG_FindItemForHoldable( HI_BANDOLIER ); - rq3_temp = (gentity_t*)SelectRandomDeathmatchSpawnPoint(); + rq3_temp = (gentity_t*)SelectRandomDeathmatchSpawnPoint(); Drop_Item (rq3_temp, rq3_item, angle); angle += 30; rq3_item = BG_FindItemForHoldable( HI_LASER ); - rq3_temp = (gentity_t*)SelectRandomDeathmatchSpawnPoint(); + rq3_temp = (gentity_t*)SelectRandomDeathmatchSpawnPoint(); Drop_Item (rq3_temp, rq3_item, angle); angle += 30; } diff --git a/reaction/game/g_misc.c b/reaction/game/g_misc.c index a3086319..fc0a1c11 100644 --- a/reaction/game/g_misc.c +++ b/reaction/game/g_misc.c @@ -518,7 +518,7 @@ void G_BreakGlass( gentity_t *ent, vec3_t point, int mod ) //Elder: for the bit-shifting int eParm; int shiftCount = 0; - + //Elder: //eventParm can only transmit as a byte (8-bits/255) //So if we receive a huge one, we can knock it down (shift-op) diff --git a/reaction/game/g_missile.c b/reaction/game/g_missile.c index 5c4bacef..bf6052ae 100644 --- a/reaction/game/g_missile.c +++ b/reaction/game/g_missile.c @@ -424,7 +424,6 @@ void G_MissileImpact( gentity_t *ent, trace_t *trace ) { // one, rather than changing the missile into the explosion? //Elder: I don't know but that's what we did for the knife - if ( other->takedamage && other->client ) { G_AddEvent( ent, EV_MISSILE_HIT, DirToByte( trace->plane.normal ) ); ent->s.otherEntityNum = other->s.number; @@ -454,17 +453,19 @@ void G_MissileImpact( gentity_t *ent, trace_t *trace ) { BG_EvaluateTrajectoryDelta(&ent->s.pos, level.time, knifeVelocity); if (other->s.eType == ET_BREAKABLE) { - VectorScale(knifeVelocity, -0.25, knifeVelocity); + //VectorScale(knifeVelocity, -0.25, knifeVelocity); //Blaze: Moved from above, now deal the damage to the glass, and let the knife drop if ( ent->s.weapon == WP_KNIFE && other->s.eType == ET_BREAKABLE ) { BG_EvaluateTrajectory( &ent->s.pos, level.time, origin); - velocity[0] = 0; - velocity[1] = 0; - velocity[2] = 0; + //velocity[0] = 0; + //velocity[1] = 0; + //velocity[2] = 0; G_Damage (other, ent, &g_entities[ent->r.ownerNum], velocity, origin, THROW_DAMAGE, 0, MOD_KNIFE_THROWN); } - - + // NiceAss: Cut its velocity in half. + VectorScale( ent->s.pos.trDelta, .6, ent->s.pos.trDelta); + return; +/* //breakable "hit"; make it fall to the ground xr_drop = LaunchItem(xr_item, trace->endpos, velocity, FL_DROPPED_ITEM); @@ -480,6 +481,7 @@ void G_MissileImpact( gentity_t *ent, trace_t *trace ) { VectorAdd(xr_drop->s.origin, knifeOffset, xr_drop->s.origin); VectorCopy(xr_drop->s.origin, xr_drop->r.currentOrigin); + */ } else { //leave embedded in the wall @@ -753,9 +755,10 @@ gentity_t *fire_grenade (gentity_t *self, vec3_t start, vec3_t dir) { if ( self->client) { // Elder: Statistics tracking self->client->pers.records[REC_GRENADESHOTS]++; - if ( self->client->ps.stats[STAT_HEALTH] <= 0 || - (self->client->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK) { + (self->client->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK || + // NiceAss: Should catch any case of switching weapons with a grenade "cocked" + self->client->ps.weaponstate == WEAPON_DROPPING ) { //Always drop close range if dead or about to bandage speed = GRENADE_SHORT_SPEED / 2; } @@ -829,7 +832,7 @@ gentity_t *fire_knife (gentity_t *self, vec3_t start, vec3_t dir) self->client->pers.records[REC_KNIFETHROWSHOTS]++; } - bolt->s.pos.trDelta[2] *= .85; + // bolt->s.pos.trDelta[2] *= .85; //Elder: not needed anymore //Saving stuff for Makro's knife equations diff --git a/reaction/game/g_mover.c b/reaction/game/g_mover.c index 5282861e..36cfefcc 100644 --- a/reaction/game/g_mover.c +++ b/reaction/game/g_mover.c @@ -1151,12 +1151,12 @@ void Touch_DoorTrigger( gentity_t *ent, gentity_t *other, trace_t *trace ) { //else { //Blaze's broken open door code //Elder: not as broken as you think :) - if (other->client->openDoor == qtrue || + if (other->client->openDoor || (ent->parent->spawnflags & SP_AUTOOPEN) == SP_AUTOOPEN) { //G_Printf("Using a door\n"); Use_BinaryMover( ent->parent, ent, other ); - other->client->openDoor = qfalse; - other->client->openDoorTime = 0; + // NiceAss: Hackish, but oh well. Done so you can trigger multipul doors in an area. + other->client->openDoor = 2; } //} } @@ -1196,8 +1196,18 @@ void Think_SpawnNewDoorTrigger( gentity_t *ent ) { best = i; } } - maxs[best] += 120; - mins[best] -= 120; + // expand + maxs[best] += 60; + mins[best] -= 60; + // NiceAss: AQ2 Style. Above is Q3 style. + if (best != 0) { + maxs[0] += 60; + mins[0] -= 60; + } + if (best != 1) { + maxs[1] += 60; + mins[1] -= 60; + } // NiceAss: This trigger will be for players // create a trigger with this size @@ -1213,9 +1223,20 @@ void Think_SpawnNewDoorTrigger( gentity_t *ent ) { trap_LinkEntity (other); // NiceAss: This trigger will be for spectators - // NiceAss: Undo most of the stretched box size so it is only a little bigger than the door - maxs[best] -= 110; - mins[best] += 110; + // NiceAss: Undo the stretched box size + // expand + maxs[best] -= 60; + mins[best] += 60; + // NiceAss: AQ2 Style. Above is Q3 style. + if (best != 0) { + maxs[0] -= 60; + mins[0] += 60; + } + if (best != 1) { + maxs[1] -= 60; + mins[1] += 60; + } + other = G_Spawn (); other->classname = "door_trigger_spectator"; VectorCopy (mins, other->r.mins); diff --git a/reaction/game/g_trigger.c b/reaction/game/g_trigger.c index 83e13c8a..97250d4b 100644 --- a/reaction/game/g_trigger.c +++ b/reaction/game/g_trigger.c @@ -177,15 +177,16 @@ Must point at a target_position, which will be the apex of the leap. This will be client side predicted, unlike target_push */ void SP_trigger_push( gentity_t *self ) { + char *sound; InitTrigger (self); // unlike other triggers, we need to send this one to the client + // NiceAss: Added for custom push sounds. Default is none. Q3 is "sounds/world/bouncepad.wav" + if (G_SpawnString( "noise", "", &sound )) {; + self->s.generic1 = G_SoundIndex( sound ); + } + self->r.svFlags &= ~SVF_NOCLIENT; - - // make sure the client precaches this sound - //Elder: edited for now TODO: let mappers use a key pair - //G_SoundIndex("sound/world/jumppad.wav"); - self->s.eType = ET_PUSH_TRIGGER; self->touch = trigger_push_touch; self->think = AimAtTarget; diff --git a/reaction/game/g_weapon.c b/reaction/game/g_weapon.c index 870c0e26..d2a795ed 100644 --- a/reaction/game/g_weapon.c +++ b/reaction/game/g_weapon.c @@ -347,18 +347,18 @@ void Bullet_Fire (gentity_t *ent, float spread, int damage, int MOD ) { { switch (MOD) { - case MOD_PISTOL: - ent->client->pers.records[REC_MK23SHOTS]++; - break; - case MOD_M4: - ent->client->pers.records[REC_M4SHOTS]++; - break; - case MOD_MP5: - ent->client->pers.records[REC_MP5SHOTS]++; - break; - case MOD_AKIMBO: - ent->client->pers.records[REC_AKIMBOSHOTS]++; - break; + case MOD_PISTOL: + ent->client->pers.records[REC_MK23SHOTS]++; + break; + case MOD_M4: + ent->client->pers.records[REC_M4SHOTS]++; + break; + case MOD_MP5: + ent->client->pers.records[REC_MP5SHOTS]++; + break; + case MOD_AKIMBO: + ent->client->pers.records[REC_AKIMBOSHOTS]++; + break; } } @@ -366,26 +366,26 @@ void Bullet_Fire (gentity_t *ent, float spread, int damage, int MOD ) { //damage *= s_quadFactor; /* Original AQ2 code - vectoangles (aimdir, dir); - AngleVectors (dir, forward, right, up); + vectoangles (aimdir, dir); + AngleVectors (dir, forward, right, up); - r = crandom()*hspread; - u = crandom()*vspread; - VectorMA (start, 8192, forward, end); - VectorMA (end, r, right, end); - VectorMA (end, u, up, end); + r = crandom()*hspread; + u = crandom()*vspread; + VectorMA (start, 8192, forward, end); + VectorMA (end, r, right, end); + VectorMA (end, u, up, end); */ /* More AQ2 code to implement - // change bullet's course when it enters water - VectorSubtract (end, start, dir); - vectoangles (dir, dir); - AngleVectors (dir, forward, right, up); - r = crandom()*hspread*2; - u = crandom()*vspread*2; - VectorMA (water_start, 8192, forward, end); - VectorMA (end, r, right, end); - VectorMA (end, u, up, end); + // change bullet's course when it enters water + VectorSubtract (end, start, dir); + vectoangles (dir, dir); + AngleVectors (dir, forward, right, up); + r = crandom()*hspread*2; + u = crandom()*vspread*2; + VectorMA (water_start, 8192, forward, end); + VectorMA (end, r, right, end); + VectorMA (end, u, up, end); */ //Elder: original Q3 code -- note the first line and its use to reduce spread @@ -436,31 +436,30 @@ void Bullet_Fire (gentity_t *ent, float spread, int damage, int MOD ) { // Elder: Statistics tracking switch (MOD) { - case MOD_PISTOL: - ent->client->pers.records[REC_MK23HITS]++; - //ent->client->mk23Hits++; - break; - case MOD_M4: - ent->client->pers.records[REC_M4HITS]++; - //ent->client->m4Hits++; - break; - case MOD_MP5: - ent->client->pers.records[REC_MP5HITS]++; - //ent->client->mp5Hits++; - break; - case MOD_AKIMBO: - ent->client->pers.records[REC_AKIMBOHITS]++; - //ent->client->akimboHits++; - break; + case MOD_PISTOL: + ent->client->pers.records[REC_MK23HITS]++; + //ent->client->mk23Hits++; + break; + case MOD_M4: + ent->client->pers.records[REC_M4HITS]++; + //ent->client->m4Hits++; + break; + case MOD_MP5: + ent->client->pers.records[REC_MP5HITS]++; + //ent->client->mp5Hits++; + break; + case MOD_AKIMBO: + ent->client->pers.records[REC_AKIMBOHITS]++; + //ent->client->akimboHits++; + break; } } - //Elder: *******************TEST CODE ***************** - //} else if ( tr.surfaceFlags & SURF_GRASS ) { + //Elder: *******************TEST CODE ***************** + //} else if ( tr.surfaceFlags & SURF_GRASS ) { //tent = G_TempEntity( tr.endpos, EV_BULLET_HIT_FLESH); //tent->s.eventParm = DirToByte( tr.plane.normal ); - } else if ( (tr.surfaceFlags & SURF_METALSTEPS) || - (tr.surfaceFlags & SURF_METAL2) ) { + } else if ( (tr.surfaceFlags & SURF_METALSTEPS) || (tr.surfaceFlags & SURF_METAL2) ) { tent = G_TempEntity( tr.endpos, EV_BULLET_HIT_METAL ); tent->s.eventParm = DirToByte( tr.plane.normal ); tent->s.otherEntityNum = ent->s.number; @@ -477,22 +476,6 @@ void Bullet_Fire (gentity_t *ent, float spread, int damage, int MOD ) { //G_Printf("Surfaceflags: %d\n", tr.surfaceFlags); if ( traceEnt->takedamage) { -#ifdef MISSIONPACK - if ( traceEnt->client && traceEnt->client->invulnerabilityTime > level.time ) { - if (G_InvulnerabilityEffect( traceEnt, forward, tr.endpos, impactpoint, bouncedir )) { - G_BounceProjectile( muzzle, impactpoint, bouncedir, end ); - VectorCopy( impactpoint, muzzle ); - // the player can hit him/herself with the bounced rail - passent = ENTITYNUM_NONE; - } - else { - VectorCopy( tr.endpos, muzzle ); - passent = traceEnt->s.number; - } - continue; - } - else { -#endif G_Damage( traceEnt, ent, ent, forward, tr.endpos, damage, 0, MOD); // FIXME: poor implementation @@ -505,15 +488,19 @@ void Bullet_Fire (gentity_t *ent, float spread, int damage, int MOD ) { // Need this? tent2->s.otherEntityNum = ent->s.number; } - else - traceEnt->client->kevlarHit = qfalse; } -#ifdef MISSIONPACK + // NiceAss: Added so the M4 will shoot through bodies + if (MOD == MOD_M4 && traceEnt->client && + traceEnt->client->kevlarHit == qfalse) + { + VectorCopy (tr.endpos, muzzle); + passent = tr.entityNum; + continue; + } + if (traceEnt->client) traceEnt->client->kevlarHit = qfalse; } -#endif - } - break; + break; } } @@ -1129,23 +1116,32 @@ void Knife_Attack ( gentity_t *self, int damage) { //Elder: no knock-back on knife slashes G_Damage (hitent, self, self, forward, tr.endpos, damage, DAMAGE_NO_KNOCKBACK, MOD_KNIFE ); - if (hitent->client) - { - tent = G_TempEntity(tr.endpos, EV_RQ3_SOUND); - tent->s.eventParm = RQ3_SOUND_KNIFEHIT; - if (self->client) - self->client->pers.records[REC_KNIFESLASHHITS]++; - } + if (hitent->client) self->client->knife_sound = -2; } else - { - //Elder TODO: take into account surface flags for clank - tent = G_TempEntity(tr.endpos, EV_KNIFE_MISS); - tent->s.eventParm = DirToByte(tr.plane.normal); - tent->s.weapon = WP_KNIFE; - } + self->client->knife_sound = -1; } } + + // NiceAss: Play appropriate sound on 5th slash + if (self->client->ps.stats[STAT_BURST] > 4) { + if (self->client->knife_sound == 0) { // Missed + // TODO: Miss sound should be here, like in AQ2 + } + else if (self->client->knife_sound == -1) { // Hit wall + //Elder TODO: take into account surface flags for clank + tent = G_TempEntity(tr.endpos, EV_KNIFE_MISS); + tent->s.eventParm = DirToByte(tr.plane.normal); + tent->s.weapon = WP_KNIFE; + } + else if (self->client->knife_sound == -2) { // Hit player + tent = G_TempEntity(tr.endpos, EV_RQ3_SOUND); + tent->s.eventParm = RQ3_SOUND_KNIFEHIT; + if (self->client) + self->client->pers.records[REC_KNIFESLASHHITS]++; + } + self->client->knife_sound = 0; + } } //static int knives = 0; @@ -1438,6 +1434,8 @@ void Weapon_SSG3000_FireOld(gentity_t *ent) RQ3_SaveZoomLevel(ent); } + + /* ================= Elder: @@ -1700,7 +1698,7 @@ void Weapon_MP5_Fire(gentity_t *ent) if ( (ent->client->ps.persistant[PERS_WEAPONMODES] & RQ3_MP5MODE) == RQ3_MP5MODE ) { spread = MP5_SPREAD * 0.7; - //ent->client->ps.stats[STAT_BURST]++; + //ent->client->ps.stats[STAT_BURST]++; } else { @@ -2365,9 +2363,12 @@ void Laser_Gen( gentity_t *ent, qboolean enabled ) { void Laser_Think( gentity_t *self ) { vec3_t end, start, forward, up; - trace_t tr; + trace_t tr, tr2; int l=0, passent; gentity_t *traceEnt; + // NiceAss: For fog: + gentity_t *tent; + vec3_t fogStart; //If the player dies, is spectator, or wrong weapon, kill the dot if (self->parent->client->ps.pm_type == PM_DEAD || @@ -2387,6 +2388,9 @@ void Laser_Think( gentity_t *self ) CalcMuzzlePoint(self->parent, forward, right, up, start); passent = self->parent->s.number; + + self->s.eFlags &= ~EF_FIRING; + // Keep tracing if it hits glass. for (l = 0; l < 10; l++) { @@ -2394,6 +2398,7 @@ void Laser_Think( gentity_t *self ) //Trace Position trap_Trace (&tr, start, NULL, NULL, end, passent, MASK_SHOT); + //trap_Trace (&tr2, start, NULL, NULL, end, passent, MASK_SHOT|CONTENTS_FOG); traceEnt = &g_entities[ tr.entityNum ]; //Did you not hit anything? @@ -2403,16 +2408,25 @@ void Laser_Think( gentity_t *self ) return; } - VectorMA(tr.endpos, 10, forward, start); // Nudge it forward a little bit - // It "hit" a player, but actually missed (thanks to new headshot code!) - if ( traceEnt->takedamage && traceEnt->client && G_HitPlayer(traceEnt, forward, tr.endpos) == qfalse ) { + if ( ( traceEnt->takedamage && traceEnt->client && G_HitPlayer(traceEnt, forward, tr.endpos) == qfalse ) ) { passent = tr.entityNum; continue; } + + // We hit fog... + /* + if (!VectorCompare(tr.endpos, tr2.endpos)) { + VectorCopy(tr2.endpos, tr.endpos); + self->s.eFlags |= EF_FIRING; + self->s.otherEntityNum = self->parent->client->ps.clientNum;//self->parent->s.number; // ->s.clientNum ??? + break; + } +*/ if (!(tr.surfaceFlags & SURF_GLASS)) break; + VectorMA(tr.endpos, 10, forward, start); // Nudge it forward a little bit } - + //Move you forward to keep you visible if (tr.fraction != 1) VectorMA(tr.endpos,-4,forward,tr.endpos);