Release 25 Game

This commit is contained in:
Bryce Hutchings 2001-12-17 15:08:34 +00:00
parent 1520497f0b
commit 7568fda611
15 changed files with 537 additions and 285 deletions

View file

@ -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

View file

@ -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

View file

@ -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,

View file

@ -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;

View file

@ -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 ) {

View file

@ -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 );

View file

@ -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;

View file

@ -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;

View file

@ -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__ */
};

View file

@ -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;
}

View file

@ -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)

View file

@ -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

View file

@ -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);

View file

@ -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;

View file

@ -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);