Major changes from the the alpha pak release on June 8th
I have it documented in my worklog
This commit is contained in:
Victor Chow 2001-06-10 06:46:06 +00:00
parent 85a0dece4b
commit 9092878c49
15 changed files with 535 additions and 142 deletions

View file

@ -462,6 +462,7 @@ localEntity_t *CG_MakeExplosion( vec3_t origin, vec3_t dir,
}
//Elder: we need one that sprays blood
/*
=================
CG_Bleed
@ -692,13 +693,16 @@ void CG_BigExplode( vec3_t playerOrigin ) {
CG_LaunchExplode( origin, velocity, cgs.media.smoke2 );
}
#define GLASS_VELOCITY 175
#define GLASS_JUMP 125
/*
==================
CG_LaunchGlass
==================
*/
//Elder: might want to rotate the model randomly or do it in break glass
void CG_LaunchGlass( vec3_t origin, vec3_t velocity, qhandle_t hModel ) {
void CG_LaunchGlass( vec3_t origin, vec3_t velocity, vec3_t rotation, qhandle_t hModel ) {
localEntity_t *le;
refEntity_t *re;
@ -719,6 +723,13 @@ void CG_BigExplode( vec3_t playerOrigin ) {
VectorCopy( velocity, le->pos.trDelta );
le->pos.trTime = cg.time;
//Elder: added
//VectorCopy( origin, le->angles.trBase );
VectorCopy( velocity, le->angles.trBase );
le->angles.trBase[2] = le->angles.trBase[2] - GLASS_JUMP;
VectorCopy( rotation, le->angles.trDelta );
le->angles.trTime = cg.time;
le->bounceFactor = 0.3f;
le->leFlags = LEF_TUMBLE;
@ -733,10 +744,9 @@ void CG_BigExplode( vec3_t playerOrigin ) {
Generated a bunch of glass shards launching out from the glass location
===================
*/
#define GLASS_VELOCITY 175
#define GLASS_JUMP 125
void CG_BreakGlass( vec3_t playerOrigin, int glassParm ) {
vec3_t origin, velocity;
vec3_t origin, velocity, rotation;
int value;
int count = 40; // How many shards to generate
int states[] = {1,2,3}; // The array of possible numbers
@ -801,20 +811,23 @@ void CG_BreakGlass( vec3_t playerOrigin, int glassParm ) {
// number every time a piece of glass is broken.
value = states[rand()%numstates];
VectorCopy( playerOrigin, origin );
velocity[0] = crandom()*GLASS_VELOCITY;
velocity[1] = crandom()*GLASS_VELOCITY;
velocity[2] = GLASS_JUMP + crandom()*GLASS_VELOCITY;
velocity[0] = crandom() * GLASS_VELOCITY;
velocity[1] = crandom() * GLASS_VELOCITY;
velocity[2] = GLASS_JUMP + crandom() * GLASS_VELOCITY;
//Elder: added
rotation[0] = crandom() * GLASS_VELOCITY;
rotation[1] = crandom() * GLASS_VELOCITY;
rotation[2] = crandom() * GLASS_VELOCITY;
switch (value) {
case 1:
// If our random number was 1, generate the 1st shard piece
CG_LaunchGlass( origin, velocity, debris1 );
CG_LaunchGlass( origin, velocity, rotation, debris1 );
break;
case 2:
CG_LaunchGlass( origin, velocity, debris2 );
CG_LaunchGlass( origin, velocity, rotation, debris2 );
break;
case 3:
CG_LaunchGlass( origin, velocity, debris3 );
CG_LaunchGlass( origin, velocity, rotation, debris3 );
break;
}
}

View file

@ -1002,10 +1002,25 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) {
case EV_RQ3_SOUND:
DEBUGNAME("EV_RQ3_SOUND");
//CG_Printf("EV_RQ3_SOUND\n");
if (es->eventParm == 0) {
//CG_Printf("EV_RQ3_SOUND: Kick\n");
trap_S_StartSound( NULL, es->number, CHAN_VOICE, cgs.media.kickSound);
//CG_Printf("EV_RQ3_SOUND: %d\n", es->eventParm);
switch (es->eventParm) {
case RQ3_SOUND_KICK:
//CG_Printf("EV_RQ3_SOUND: Kick\n");
trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.kickSound);
break;
case RQ3_SOUND_HEADSHOT:
//CG_Printf("EV_RQ3_SOUND: Headshot\n");
//Elder: extra blood - synched with sound
//CG_Bleed( position, es->number );
trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.headshotSound);
break;
case RQ3_SOUND_LCA:
//CG_Printf("EV_RQ3_SOUND: Lights, Camera, Action\n");
//Global sound
trap_S_StartSound( NULL, cg.snap->ps.clientNum, CHAN_AUTO, cgs.media.lcaSound);
break;
default:
break;
}
break;
@ -1128,7 +1143,11 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) {
case EV_PAIN:
// local player sounds are triggered in CG_CheckLocalSounds,
// so ignore events on the player
DEBUGNAME("EV_PAIN");
DEBUGNAME("EV_PAIN");/*
if ( es->eventParm == -99999 ) {
CG_Printf("EV_PAIN: Headshot\n");
trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.headshotSound);
}*/
if ( cent->currentState.number != cg.snap->ps.clientNum ) {
CG_PainEvent( cent, es->eventParm );
}

View file

@ -826,6 +826,9 @@ typedef struct {
// sounds
sfxHandle_t kickSound; //Elder: kick sound
sfxHandle_t headshotSound; //Elder: splat
sfxHandle_t lcaSound; //Elder: lights, camera, action!
sfxHandle_t lensSound; //Elder: sniper lens zoom
sfxHandle_t quadSound;
sfxHandle_t tracerSound;
sfxHandle_t selectSound;

View file

@ -612,8 +612,12 @@ static void CG_RegisterSounds( void ) {
cgs.media.gibBounce2Sound = trap_S_RegisterSound( "sound/player/gibimp2.wav", qfalse );
cgs.media.gibBounce3Sound = trap_S_RegisterSound( "sound/player/gibimp3.wav", qfalse );
//Elder: kick sound
//Elder: RQ3 sounds
cgs.media.kickSound = trap_S_RegisterSound( "sound/misc/kick.wav", qfalse);
cgs.media.lensSound = trap_S_RegisterSound( "sound/misc/lens.wav", qfalse);
cgs.media.headshotSound = trap_S_RegisterSound( "sound/misc/headshot.wav", qfalse);
cgs.media.lcaSound = trap_S_RegisterSound( "sound/misc/lca.wav", qfalse);
#ifdef MISSIONPACK
cgs.media.useInvulnerabilitySound = trap_S_RegisterSound( "sound/items/invul_activate.wav", qfalse );

View file

@ -433,7 +433,8 @@ CG_GrenadeTrail
==========================
*/
static void CG_GrenadeTrail( centity_t *ent, const weaponInfo_t *wi ) {
CG_RocketTrail( ent, wi );
//Elder: removed smoke trail
//CG_RocketTrail( ent, wi );
}
@ -1724,6 +1725,8 @@ void CG_Weapon_f( void ) {
if ( trap_Argc() == 1 ) {
//Elder: if SSG, use local zooming THEN forward to server for stats
if (cg.snap->ps.weapon == WP_SSG3000) {
//trap_S_StartSound( NULL, cg.snap->ps.clientNum, CHAN_ITEM, cgs.media.lensSound);
trap_S_StartLocalSound( cgs.media.lensSound, CHAN_ITEM);
CG_RXN_Zoom();
}

View file

@ -1548,6 +1548,7 @@ static void PM_FinishWeaponChange( void ) {
int weapon;
weapon = pm->cmd.weapon;
if ( weapon < WP_NONE || weapon >= WP_NUM_WEAPONS ) {
weapon = WP_NONE;
}
@ -1688,7 +1689,7 @@ static void PM_Weapon( void ) {
PM_StartTorsoAnim( TORSO_ATTACK );
}
//Elder: works great server side, but client needs to predict it
// Elder: the client side portion is in
// Homer: if weapon can set to be burst mode, check for burst value
// M4
if ( pm->ps->weapon == WP_M4 && pm->ps->stats[STAT_BURST] > 2 ) {
@ -1717,10 +1718,11 @@ static void PM_Weapon( void ) {
// take an ammo away if not infinite
if ( pm->ps->ammo[ pm->ps->weapon ] != -1 ) {
//Blaze: Dont remove ammo for knife
//Elder: can't access throwKnife?
//if ( pm->ps->weapon != WP_KNIFE)
//Elder: don't remove ammo if slashing knife
if ( !(pm->ps->weapon == WP_KNIFE && pm->ps->stats[STAT_KNIFE] == RQ3_KNIFE_SLASH) ) {
//G_Printf("Taking away ammo\n");
pm->ps->ammo[ pm->ps->weapon ]--;
}
//Elder: remove one more bullet/shell if handcannon/akimbo
if (pm->ps->weapon == WP_HANDCANNON || pm->ps->weapon == WP_AKIMBO) {
pm->ps->ammo[ pm->ps->weapon ]--;

View file

@ -94,6 +94,34 @@
//Elder: confused?
//Elder: used for STAT_KNIFE ...
#define RQ3_KNIFE_SLASH 0
#define RQ3_KNIFE_THROW 1
//Elder: from Action source, but changed defined names a bit
#define RQ3_PISTOL_NAME "MK23 Pistol"
#define RQ3_MP5_NAME "MP5/10 Submachinegun"
#define RQ3_M4_NAME "M4 Assault Rifle"
#define RQ3_M3_NAME "M3 Super 90 Assault Shotgun"
#define RQ3_HANDCANNON_NAME "Handcannon"
#define RQ3_SSG3000_NAME "Sniper Rifle"
#define RQ3_AKIMBO_NAME "Dual MK23 Pistols"
#define RQ3_KNIFE_NAME "Combat Knife"
#define RQ3_GRENADE_NAME "M26 Fragmentation Grenade"
#define RQ3_SILENCER_NAME "Silencer"
#define RQ3_SLIPPERS_NAME "Stealth Slippers"
#define RQ3_BANDOLIER_NAME "Bandolier"
#define RQ3_KEVLAR_NAME "Kevlar Vest"
#define RQ3_LASER_NAME "Lasersight"
//Elder: sound events for EV_RQ3_SOUND
#define RQ3_SOUND_KICK 0
#define RQ3_SOUND_HEADSHOT 1
#define RQ3_SOUND_KNIFEDEATH 2
#define RQ3_SOUND_LCA 3 //lights, camera, action!
//
// config strings are a general means of communicating variable length strings
@ -251,7 +279,7 @@ typedef enum {
STAT_PERSISTANT_POWERUP,
#endif
STAT_WEAPONS, // 16 bit fields
STAT_ARMOR,
STAT_ARMOR, // Elder: technically we don't need this anymore - maybe for vest
STAT_DEAD_YAW, // look this direction when dead (FIXME: get rid of?)
// Begin Duffman
STAT_CLIPS, // Num Clips player currently has
@ -264,6 +292,7 @@ typedef enum {
STAT_UNIQUEWEAPONS,
STAT_FALLDAMAGE,
STAT_BANDAGE, //Elder: holds bandage need
STAT_KNIFE, //Elder: knife throwing -- wasteful? then later rename STAT_RQ3 or something and use bits
} statIndex_t;

View file

@ -102,7 +102,7 @@ qboolean JumpKick( gentity_t *ent )
damage, DAMAGE_NO_LOCATIONAL, MOD_KICK );
//Elder: Our set of locally called sounds
G_AddEvent ( ent, EV_RQ3_SOUND, 0);
G_AddEvent ( ent, EV_RQ3_SOUND, RQ3_SOUND_KICK);
return qtrue;
}
@ -151,10 +151,30 @@ void P_DamageFeedback( gentity_t *player ) {
client->ps.damageYaw = angles[YAW]/360.0 * 256;
}
// play an apropriate pain sound
/*
G_Printf("Lasthurt: %d, Head: %d, Face: %d, And-Op: %d\n",
client->lasthurt_location,
LOCATION_HEAD, LOCATION_FACE,
client->lasthurt_location & ~(LOCATION_BACK | LOCATION_LEFT | LOCATION_RIGHT | LOCATION_FRONT) );
*/
// play an appropriate pain sound
if ( (level.time > player->pain_debounce_time) && !(player->flags & FL_GODMODE) ) {
player->pain_debounce_time = level.time + 700;
G_AddEvent( player, EV_PAIN, player->health );
switch ( client->lasthurt_location &
~(LOCATION_BACK | LOCATION_LEFT | LOCATION_RIGHT | LOCATION_FRONT) ) {
//Elder: headshot sound
case LOCATION_HEAD:
case LOCATION_FACE:
G_AddEvent ( player, EV_RQ3_SOUND, RQ3_SOUND_HEADSHOT);
break;
default:
G_AddEvent( player, EV_PAIN, player->health );
break;
}
client->ps.damageEvent++;
}
@ -559,6 +579,8 @@ void ClientTimerActions( gentity_t *ent, int msec ) {
ent->client->bleed_remain = 0;
ent->client->bleeding = 0;
ent->client->bleedtick = 0;
//Elder: added
ent->client->isBandaging = qfalse;
// ent->client->ps.weaponTime += 2500;
// ent->client->ps.weaponstate = WEAPON_RAISING;
// ent->client->ps.torsoAnim = ( ( ent->client->ps.torsoAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | TORSO_RAISE;
@ -840,25 +862,40 @@ void ThrowWeapon( gentity_t *ent )
//if( client->ps.weapon == WP_KNIFE || client->ps.weapon == WP_PISTOL || client->ps.weapon == WP_GRENADE || ( ucmd->buttons & BUTTON_ATTACK ))
// return;
//Elder: better change conditional to include bandaging case... re: "You are too busy bandaging..."
if (ucmd->buttons & BUTTON_ATTACK) return;
weap=0;
//Still firing
if (ucmd->buttons & BUTTON_ATTACK) {
return;
}
//Elder: Bandaging case
else if (client->isBandaging) {
trap_SendServerCommand( ent-g_entities, va("print \"You are too busy bandaging...\n\""));
return;
}
weap = 0;
if (client->ps.stats[STAT_UNIQUEWEAPONS] > 0)
{
weap = client->ps.stats[STAT_WEAPONS];
if ((client->ps.stats[STAT_WEAPONS] & (1 << WP_M4) )== (1 << WP_M4)) weap = WP_M4;
if ((client->ps.stats[STAT_WEAPONS] & (1 << WP_M3) )== (1 << WP_M3)) weap = WP_M3;
if ((client->ps.stats[STAT_WEAPONS] & (1 << WP_MP5) )== (1 << WP_MP5)) weap = WP_MP5;
if ((client->ps.stats[STAT_WEAPONS] & (1 << WP_HANDCANNON) )== (1 << WP_HANDCANNON)) weap = WP_HANDCANNON;
if ((client->ps.stats[STAT_WEAPONS] & (1 << WP_SSG3000) )== (1 << WP_SSG3000)) weap = WP_SSG3000;
if ((client->ps.stats[STAT_WEAPONS] & (1 << WP_M4) ) == (1 << WP_M4))
weap = WP_M4;
if ((client->ps.stats[STAT_WEAPONS] & (1 << WP_M3) ) == (1 << WP_M3))
weap = WP_M3;
if ((client->ps.stats[STAT_WEAPONS] & (1 << WP_MP5) ) == (1 << WP_MP5))
weap = WP_MP5;
if ((client->ps.stats[STAT_WEAPONS] & (1 << WP_HANDCANNON) ) == (1 << WP_HANDCANNON))
weap = WP_HANDCANNON;
if ((client->ps.stats[STAT_WEAPONS] & (1 << WP_SSG3000) ) == (1 << WP_SSG3000))
weap = WP_SSG3000;
if (weap == 0 ) return;
xr_item = BG_FindItemForWeapon( weap );
//Elder: do you really want to do this?
client->ps.ammo[ weap ] = 0;
client->ps.stats[STAT_WEAPONS] &= ~( 1 << weap);
//Elder: moved up
client->ps.weapon = WP_PISTOL;
client->ps.ammo[ weap ] = 0;
client->ps.stats[STAT_WEAPONS] &= ~( 1 << weap);
//client->ps.weapon = WP_PISTOL;
xr_drop= dropWeapon( ent, xr_item, 0, FL_DROPPED_ITEM | FL_THROWN_ITEM );
xr_drop->count= -1; // XRAY FMJ 0 is already taken, -1 means no ammo
client->ps.stats[STAT_UNIQUEWEAPONS]--;

View file

@ -1222,6 +1222,11 @@ void ClientSpawn(gentity_t *ent) {
// Hawkins reset zoomed flag
client->zoomed=0;
//Elder: knife reset/initialize
client->ps.stats[STAT_KNIFE] = RQ3_KNIFE_SLASH;
//Elder: reset isBandaging flag
client->isBandaging = qfalse;
// set default animations
client->ps.torsoAnim = TORSO_STAND;

View file

@ -1603,6 +1603,8 @@ void Cmd_Bandage (gentity_t *ent)
ent->client->ps.weaponTime += 6000;
ent->client->bleedtick = 4;
//Elder: added
ent->client->isBandaging = qtrue;
}
else
{
@ -1625,6 +1627,12 @@ void Cmd_Reload( gentity_t *ent ) {
int weapon;
int ammotoadd;
int delay;
//Elder: added
if (ent->client->isBandaging) {
trap_SendServerCommand( ent-g_entities, va("print \"You are too busy bandaging...\n\""));
return;
}
weapon = ent->client->ps.weapon;
//Elder: changed to new function
@ -1892,10 +1900,16 @@ void Cmd_Weapon(gentity_t *ent)
case WP_KNIFE:
// toggle throwing/slashing
ent->client->throwKnife = !(ent->client->throwKnife);
if (ent->client->throwKnife)
if (ent->client->throwKnife) {
//Elder: added
ent->client->ps.stats[STAT_KNIFE] = RQ3_KNIFE_THROW;
trap_SendServerCommand( ent-g_entities, va("print \"Switched to throwing.\n\""));
else
}
else {
//Elder: we're gonna use this to flag throw or slash with the knife
ent->client->ps.stats[STAT_KNIFE] = RQ3_KNIFE_SLASH;
trap_SendServerCommand( ent-g_entities, va("print \"Switched to slashing.\n\""));
}
break;
case WP_HANDCANNON:
// nothing

View file

@ -59,6 +59,8 @@ void TossClientItems( gentity_t *self ) {
float angle;
int i;
gentity_t *drop;
//Elder: added
int weaponInventory;
// drop the weapon if not a gauntlet or machinegun
weapon = self->s.weapon;
@ -78,14 +80,60 @@ void TossClientItems( gentity_t *self ) {
}
}
*/
//Blaze: dont need this check as we will be droping everyhing, but just changed WP_MACHINEGUN to WP_PISTOL just in case, also removed grappling hook check
if ( weapon > WP_PISTOL && self->client->ps.ammo[ weapon ] ) {
//Blaze: dont need this check as we will be dropping everyhing, but just changed WP_MACHINEGUN to WP_PISTOL just in case, also removed grappling hook check
//Elder:
//don't drop akimbos (maybe drop another pistol), knives, or grenades
//and don't drop knife - that's handled later
//Maybe we should check the player's weapon inventory instead
/*
if ( weapon != WP_GRENADE && weapon != WP_AKIMBO &&
weapon != WP_KNIFE && weapon > WP_PISTOL && self->client->ps.ammo[ weapon ] ) {
// find the item type for this weapon
item = BG_FindItemForWeapon( weapon );
// spawn the item
Drop_Item( self, item, 0 );
}
*/
//Elder: run through player STAT_WEAPONS and drop any unique weapons
//That way, we can also account for the bandolier automatically
//BTW, that means no cheating to get all weapons or it'll spawn mad!!
weaponInventory = self->client->ps.stats[STAT_WEAPONS];
if ( (weaponInventory & (1 << WP_M3) ) == (1 << WP_M3) ) {
item = BG_FindItemForWeapon( WP_M3 );
Drop_Item( self, item, 0);
}
if ( (weaponInventory & (1 << WP_M4) ) == (1 << WP_M4) ) {
item = BG_FindItemForWeapon( WP_M4 );
Drop_Item( self, item, 0);
}
if ( (weaponInventory & (1 << WP_MP5) ) == (1 << WP_MP5) ) {
item = BG_FindItemForWeapon( WP_MP5 );
Drop_Item( self, item, 0);
}
if ( (weaponInventory & (1 << WP_HANDCANNON) ) == (1 << WP_HANDCANNON) ) {
item = BG_FindItemForWeapon( WP_HANDCANNON );
Drop_Item( self, item, 0);
}
if ( (weaponInventory & (1 << WP_SSG3000) ) == (1 << WP_SSG3000) ) {
item = BG_FindItemForWeapon( WP_SSG3000 );
Drop_Item( self, item, 0);
}
//Elder: Always drop the pistol
item = BG_FindItemForWeapon( WP_PISTOL );
Drop_Item (self, item, 0);
//Elder: drop a knife if player has at least one
if ( self->client->ps.ammo[ WP_KNIFE ] > 0) {
item = BG_FindItemForWeapon( WP_KNIFE );
Drop_Item (self, item, 0);
}
// drop all the powerups if not in teamplay
if ( g_gametype.integer != GT_TEAM ) {
@ -450,6 +498,8 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
self->client->bleeding = 0;
//targ->client->bleedcount = 0;
self->client->bleed_remain = 0;
//Elder: added;
self->client->isBandaging = qfalse;
}
if ( self->client->ps.pm_type == PM_DEAD ) {
return;
@ -991,6 +1041,9 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
vec3_t bulletAngle;
//Elder: added for M3 and Pistols
vec_t dist;
vec3_t line;
int clientHeight;
int clientFeetZ;
@ -1021,6 +1074,7 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
}
}
#endif
if ( !inflictor ) {
inflictor = &g_entities[ENTITYNUM_WORLD];
}
@ -1043,6 +1097,34 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
return;
}
//Elder: from action source
// damage reduction for shotgun and mk23/akimbo
// if far away, reduce it to original action levels
//Note: doesn't handle shots on non-clients (e.g. breakables)
if (targ->client && inflictor->client) {
if ( mod == MOD_M3) {
VectorSubtract(targ->client->ps.origin, inflictor->client->ps.origin, line );
dist = VectorLength( line );
if ( dist > 450.0 ) {
damage = damage - 2;
}
}
else if ( mod == MOD_PISTOL || mod == MOD_AKIMBO ) {
VectorSubtract(targ->client->ps.origin, inflictor->client->ps.origin, line );
dist = VectorLength( line );
// G_Printf("Distance from target: %f\n", dist);
if ( dist > 600.0 && dist < 1400.0 ) {
// G_Printf("Damage reduced to 2/3\n");
damage = (int)(damage * 2/3);
}
//Elder: added >= ... 1400.0 is a magic number for perfect shots if not in :)
else if ( dist >= 1400.0 ) {
// G_Printf("Damage reduced to 1/2\n");
damage = (int)(damage * 1/2);
}
}
}
//Blaze: If we shot a breakable item subtract the damage from its health and try to break it
if ( targ->s.eType == ET_BREAKABLE ) {
targ->health -= damage;
@ -1080,6 +1162,7 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
VectorNormalize(dir);
}
//Elder: this is a simplifed knockback calc - Action has a radically different one.
knockback = damage;
if ( knockback > 200 ) {
knockback = 200;
@ -1104,6 +1187,8 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
mass = 200;
//Elder: Q2 uses a hardcoded value of 500 for non-rocket jumps
//Q3 uses g_knockback.value ... default 1000
VectorScale (dir, g_knockback.value * (float)knockback / mass, kvel);
VectorAdd (targ->client->ps.velocity, kvel, targ->client->ps.velocity);
@ -1330,6 +1415,11 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
{
trap_SendServerCommand( attacker-g_entities, va("print \"You hit %s^7 in the head.\n\"", targ->client->pers.netname));
trap_SendServerCommand( targ-g_entities, va("print \"Head Damage.\n\""));
//Elder: headshot sound moved to g_active.c
//if ( mod != MOD_KNIFE && mod != MOD_KNIFE_THROWN ) {
//G_Printf("play headshot sound\n");
//G_AddEvent ( targ, EV_RQ3_SOUND, RQ3_SOUND_HEADSHOT);
//}
take *= 1.8; //+ 1;
break;
}
@ -1337,6 +1427,11 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
{
trap_SendServerCommand( attacker-g_entities, va("print \"You hit %s^7 in the head.\n\"", targ->client->pers.netname));
trap_SendServerCommand( targ-g_entities, va("print \"Head Damage.\n\""));
//Elder: headshot sound - no events here
//if ( mod != MOD_KNIFE && mod != MOD_KNIFE_THROWN ) {
//G_Printf("play headshot sound\n");
//G_AddEvent ( targ, EV_RQ3_SOUND, RQ3_SOUND_HEADSHOT);
//}
take *= 1.8; //+ 1;
break;
}
@ -1409,12 +1504,13 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
}
if ( targ->health <= 0 ) {
if ( client )
targ->flags |= FL_NO_KNOCKBACK;
if (targ->health < -999)
//Elder: removed so we can play with bodies :)
//if ( client ) {
//targ->flags |= FL_NO_KNOCKBACK;
//}
if (targ->health < -999) {
targ->health = -999;
}
targ->enemy = attacker;
targ->die (targ, inflictor, attacker, take, mod);
return;

View file

@ -321,7 +321,8 @@ int Pickup_Weapon (gentity_t *ent, gentity_t *other) {
//Someone can optimize this code later, but for now, it works.
if ( !(other->client->ps.stats[STAT_WEAPONS] & (1 << WP_AKIMBO) ) ) {
//give akimbo
G_Printf("Dual MK23 pistols\n");
//G_Printf("Dual MK23 pistols\n");
trap_SendServerCommand( other-g_entities, va("print \"%s^7\n\"", RQ3_AKIMBO_NAME) );
other->client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_AKIMBO );
other->client->ps.ammo[WP_AKIMBO] = other->client->ps.ammo[WP_PISTOL] + RQ3_PISTOL_AMMO;
ammotoadd = other->client->ps.ammo[WP_PISTOL];
@ -329,7 +330,8 @@ int Pickup_Weapon (gentity_t *ent, gentity_t *other) {
//Elder: Already have akimbo - technically should have pistol
else if (other->client->numClips[ WP_PISTOL ] < 2) {
//give an extra clip - make < 2 + 2 * hasBandolier(0/1) or something for bando when it's in
G_Printf("Picked up an extra clip\n");
//G_Printf("Picked up an extra clip\n");
trap_SendServerCommand( other-g_entities, va("print \"Picked up an extra clip^7\n\"" ) );
other->client->numClips[ WP_PISTOL ]++;
other->client->numClips[ WP_AKIMBO ]++;
ammotoadd = other->client->ps.ammo[WP_PISTOL];
@ -565,6 +567,9 @@ void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) {
predict = other->client->pers.predictItemPickup;
//Elder: should check if the item was recently thrown ... if it was, then
//don't allow it to be picked up ... or something like that
// call the item-specific pickup function
switch( ent->item->giType ) {
case IT_WEAPON:
@ -623,10 +628,10 @@ void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) {
break;
}
//Blaze: Check and see if it's a unique weapon, and if so make sure they dont have too many already
if (ent->item->giTag == WP_MP5 || ent->item->giTag == WP_M4 || ent->item->giTag == WP_M3 || ent->item->giTag == WP_HANDCANNON || ent->item->giTag == WP_SSG3000)
{
if (other->client->ps.stats[STAT_UNIQUEWEAPONS] >= g_rxn_maxweapons.integer)
{
if (ent->item->giTag == WP_MP5 || ent->item->giTag == WP_M4 ||
ent->item->giTag == WP_M3 || ent->item->giTag == WP_HANDCANNON ||
ent->item->giTag == WP_SSG3000) {
if (other->client->ps.stats[STAT_UNIQUEWEAPONS] >= g_rxn_maxweapons.integer) {
return;
}
}
@ -634,7 +639,8 @@ void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) {
respawn = Pickup_Weapon(ent, other);
respawn = -1; //Dont respawn weapons
if (ent->item->giTag == WP_GRENADE)
//Elder: added pistol condition
if (ent->item->giTag == WP_GRENADE || ent->item->giTag == WP_PISTOL)
{
// G_Printf("Grenade Pickedup (%d)\n",respawn);
respawn = 30;
@ -814,6 +820,7 @@ gentity_t *LaunchItem( gitem_t *item, vec3_t origin, vec3_t velocity, int xr_fla
G_SetOrigin( dropped, origin );
dropped->s.pos.trType = TR_GRAVITY;
dropped->s.pos.trTime = level.time;
//Elder: should change to a constant velocity for weapons
VectorCopy( velocity, dropped->s.pos.trDelta );
dropped->s.eFlags |= EF_BOUNCE_HALF;
@ -825,7 +832,19 @@ gentity_t *LaunchItem( gitem_t *item, vec3_t origin, vec3_t velocity, int xr_fla
dropped->think = Team_DroppedFlagThink;
dropped->nextthink = level.time + 30000;
Team_CheckDroppedItem( dropped );
} else { // auto-remove after 30 seconds
}
//Elder: Reaction Unique Weapons in deathmatch - respawn in 30 seconds
//Don't forget to condition it when we get teamplay in
else if ( item->giType == IT_WEAPON &&
item->giTag != WP_GRENADE && item->giTag != WP_PISTOL &&
item->giTag != WP_AKIMBO && item->giTag != WP_KNIFE ) {
dropped->think = RQ3_DroppedWeaponThink;
//Elder: don't want to wait forever while testing :)
dropped->nextthink = level.time + RQ3_RESPAWNTIME_DEFAULT;
}
else { // auto-remove after 30 seconds
dropped->think = G_FreeEntity;
dropped->nextthink = level.time + 30000;
}
@ -1275,3 +1294,115 @@ void G_RunItem( gentity_t *ent ) {
G_BounceItem( ent, &tr );
}
/*
==============
Added by Elder
RQ3_DroppedWeaponThink
Get the item name from the entity and forward
it to RQ3_ResetWeapon to find and respawn
This is like respawning CTF flags in baseq3
==============
*/
void RQ3_DroppedWeaponThink(gentity_t *ent) {
int weaponNum = WP_NONE;
switch (ent->item->giTag) {
case WP_MP5:
case WP_M4:
case WP_M3:
case WP_HANDCANNON:
case WP_SSG3000:
weaponNum = ent->item->giTag;
break;
case WP_PISTOL:
case WP_KNIFE:
case WP_AKIMBO:
case WP_GRENADE:
default:
//Elder: shouldn't have to come here
G_Printf("DroppedWeaponThink: Out of range weapon %d\n", ent->item->giTag);
return;
break;
}
//Elder: flag the item we want to remove
ent->flags |= FL_RQ3_JUNKITEM;
RQ3_ResetWeapon( weaponNum );
// Reset Weapon will delete this entity
}
/*
==============
Added by Elder
RQ3_ResetWeapon
Respawn a unique weapon
Similar to CTF Flag reset
A little quirky - maybe someone can fine-tune this!
Bugs:
The weapon may not return to its original location if there is
more than one of the type. It just finds the closest empty spot
and respawns it.
==============
*/
void RQ3_ResetWeapon( int weapon ) {
char *c;
gentity_t *ent; //, *rent = NULL;
int numRespawned = 0;
int numRemoved = 0;
switch (weapon) {
case WP_M3:
c = "weapon_m3";
break;
case WP_M4:
c = "weapon_m4";
break;
case WP_MP5:
c = "weapon_mp5";
break;
case WP_SSG3000:
c = "weapon_ssg3000";
break;
case WP_HANDCANNON:
c = "weapon_handcannon";
break;
default:
//Elder: shouldn't be here
G_Printf("RQ3_ResetWeapon: Received bad weapon: %d\n", weapon);
break;
}
ent = NULL;
//Elder: here's the solution and another problem to RQ3 weapon respawns
while ((ent = G_Find (ent, FOFS(classname), c)) != NULL) {
//if it's a dropped copy, free it
//if (ent->flags & FL_DROPPED_ITEM) {
//Elder: only release if it's past the
//default respawn time and is flagged
if (numRemoved < 1 &&
(ent->flags & FL_DROPPED_ITEM) == FL_DROPPED_ITEM &&
(ent->flags & FL_RQ3_JUNKITEM) == FL_RQ3_JUNKITEM &&
level.time - ent->timestamp >= RQ3_RESPAWNTIME_DEFAULT) {
G_FreeEntity(ent);
numRemoved++;
}
else {
//rent = ent;
//Elder: only respawn if it's a "taken" item
//It won't necessarily respawn the gun in its original spot if there's
//more than one, but it will put it in an empty location... good enough?
if ( (ent->r.svFlags & SVF_NOCLIENT) == SVF_NOCLIENT &&
(ent->s.eFlags & EF_NODRAW) == EF_NODRAW &&
ent->r.contents == 0 && numRespawned < 1) {
RespawnItem(ent);
numRespawned++;
}
}
}
//return rent;
}

View file

@ -43,6 +43,7 @@
//Elder: err - this looks funny... should it be 0x00010000 ?
//#define FL_THROWN_ITEM 0x00016000 // XRAY FMJ weapon throwing
#define FL_THROWN_ITEM 0x00010000 // XRAY FMJ weapon throwing
#define FL_RQ3_JUNKITEM 0x00020000 // Elder: the item we want to remove
// movers are things like doors, plats, buttons, etc
typedef enum {
@ -60,6 +61,8 @@ typedef enum {
#define SP_PODIUM_MODEL "models/mapobjects/podium/podium4.md3"
#define RQ3_RESPAWNTIME_DEFAULT 30000 // Elder: time for weapons to respawn
//============================================================================
typedef struct gentity_s gentity_t;
@ -327,8 +330,8 @@ struct gclient_s {
int bleedloc; //Blaze: Where are we bleeding
vec3_t bleedloc_offset;// Blaze: location of bleeding (from origin)
vec3_t bleednorm;
//qboolean isbleeding;//Blaze: is client bleeding
int legDamage;//Blaze: Client has leg damage
//qboolean isBleeding;//Blaze: is client bleeding
int legDamage;//Blaze: Client has leg damage - holds number of hits too
int bleedtick;//Blaze: Holds # of seconds till bleeding stops.
//Elder: server only needs to know for sniper spread - ARGH
int zoomed; // Hawkins (SSG zoom)
@ -341,6 +344,7 @@ struct gclient_s {
int m4_3rb; // M4 to 3rb
int grenRange; // range to throw grenade (short/medium/long)
int throwKnife; // knife to throwing
qboolean isBandaging; //Elder: player in the process of bandaging
// end Homer
#ifdef MISSIONPACK
gentity_t *persistantPowerup;
@ -503,6 +507,11 @@ void ClearRegisteredItems( void );
void RegisterItem( gitem_t *item );
void SaveRegisteredItems( void );
//Elder: added
void RQ3_DroppedWeaponThink(gentity_t *ent);
void RQ3_ResetWeapon( int weapon );
//
// g_utils.c
//

View file

@ -67,7 +67,8 @@ void G_ExplodeMissile( gentity_t *ent ) {
g_entities[ent->r.ownerNum].client->accuracy_hits++;
}
}
G_Printf("exploding knife\n");
//Elder: huhh?
//G_Printf("exploding knife\n");
trap_LinkEntity( ent );
}
@ -255,14 +256,25 @@ void G_MissileImpact( gentity_t *ent, trace_t *trace ) {
#endif
other = &g_entities[trace->entityNum];
// check for bounce
if ( !other->takedamage &&
//Elder: no grenade explosion on impact
if ( ent->s.weapon == WP_GRENADE &&
( ent->s.eFlags & ( EF_BOUNCE | EF_BOUNCE_HALF ) ) ) {
G_BounceMissile( ent, trace );
G_AddEvent( ent, EV_GRENADE_BOUNCE, 0 );
return;
}
//Elder: regular Q3 grenades
// check for bounce
/*
if ( !other->takedamage &&
( ent->s.eFlags & ( EF_BOUNCE | EF_BOUNCE_HALF ) ) ) {
G_BounceMissile( ent, trace );
G_AddEvent( ent, EV_GRENADE_BOUNCE, 0 );
return;
}
*/
#ifdef MISSIONPACK
if ( other->takedamage ) {
if ( ent->s.weapon != WP_PROX_LAUNCHER ) {

View file

@ -5,6 +5,27 @@
#include "g_local.h"
//Blaze: reaction weapon damage ratings & weapon spreads
//Elder: moved to the top
#define PISTOL_DAMAGE 90
#define MP5_DAMAGE 55
#define M4_DAMAGE 90
#define M3_DAMAGE 17
//Elder: wrong name
//#define SHOTGUN_DAMAGE 17
#define HANDCANNON_DAMAGE 20
#define SNIPER_DAMAGE 250
#define AKIMBO_DAMAGE 90
#define SLASH_DAMAGE 200//Shashing knife damage
#define THROW_DAMAGE 250//Throwing Knife damage
#define PISTOL_SPREAD 140
#define MP5_SPREAD 250
#define M4_SPREAD 300
#define SNIPER_SPREAD 425
#define AKIMBO_SPREAD 300
static float s_quadFactor;
static vec3_t forward, right, up;
static vec3_t muzzle;
@ -135,23 +156,7 @@ void SnapVectorTowards( vec3_t v, vec3_t to ) {
#define MACHINEGUN_SPREAD 200
#define MACHINEGUN_DAMAGE 7
#define MACHINEGUN_TEAM_DAMAGE 5 // wimpier MG in teamplay
//Blaze: reaction weapon damage ratings & weapon spreads
#define PISTOL_DAMAGE 90
#define MP5_DAMAGE 55
#define M4_DAMAGE 90
#define SHOTGUN_DAMAGE 17
#define HANDCANNON_DAMAGE 20
#define SNIPER_DAMAGE 250
#define AKIMBO_DAMAGE 90
#define SLASH_DAMAGE 200//Shashing knife damage
#define THROW_DAMAGE 250//Throwing Knife damage
#define PISTOL_SPREAD 140
#define MP5_SPREAD 250
#define M4_SPREAD 300
#define SNIPER_SPREAD 425
#define AKIMBO_SPREAD 300
void Bullet_Fire (gentity_t *ent, float spread, int damage, int MOD ) {
trace_t tr;
@ -283,7 +288,18 @@ qboolean ShotgunPellet( vec3_t start, vec3_t end, gentity_t *ent ) {
}
if ( traceEnt->takedamage) {
damage = DEFAULT_SHOTGUN_DAMAGE; // * s_quadFactor;
//Elder: added to discern handcannon and m3 damage
if (ent->client && ent->client->ps.weapon == WP_HANDCANNON ) {
//G_Printf("Firing handcannon\n");
damage = HANDCANNON_DAMAGE;
G_Damage( traceEnt, ent, ent, forward, tr.endpos, damage, 0, MOD_HANDCANNON);
}
else {
//G_Printf("Firing M3\n");
damage = M3_DAMAGE;
G_Damage( traceEnt, ent, ent, forward, tr.endpos, damage, 0, MOD_M3);
}
//damage = DEFAULT_SHOTGUN_DAMAGE; // * s_quadFactor;
#ifdef MISSIONPACK
if ( traceEnt->client && traceEnt->client->invulnerabilityTime > level.time ) {
if (G_InvulnerabilityEffect( traceEnt, forward, tr.endpos, impactpoint, bouncedir )) {
@ -306,7 +322,8 @@ qboolean ShotgunPellet( vec3_t start, vec3_t end, gentity_t *ent ) {
}
}
#else
G_Damage( traceEnt, ent, ent, forward, tr.endpos, damage, 0, MOD_SHOTGUN);
//Elder: moved into if conditional above
//G_Damage( traceEnt, ent, ent, forward, tr.endpos, damage, 0, MOD_SHOTGUN);
if( LogAccuracyHit( traceEnt, ent ) ) {
return qtrue;
}
@ -793,80 +810,77 @@ static int knives = 0;
void knife_touch (gentity_t *ent, gentity_t *other,trace_t *trace)
{
vec3_t origin;
gitem_t *xr_item;
gentity_t *xr_drop;
vec3_t origin;
gitem_t *xr_item;
gentity_t *xr_drop;
G_Printf("Knife Touched Something\n");
if (other == ent->parent)
return;
if (other == ent->parent)
return;
if (trace && (trace->surfaceFlags & SURF_SKY))
{
//Blaze: Get rid of the knife if it hits the sky
if (trace && (trace->surfaceFlags & SURF_SKY)) {
//Blaze: Get rid of the knife if it hits the sky
// G_FreeEdict (ent);
return;
}
//Elder: I think you want this
G_FreeEntity(ent);
return;
}
if (ent->parent->client)
{
//Blaze: Play the clank hit noise
// gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/clank.wav"), 1, ATTN_NORM, 0);
// PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT);
}
if (ent->parent->client) {
//Blaze: Play the clank hit noise
// gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/clank.wav"), 1, ATTN_NORM, 0);
// PlayerNoise(ent->owner, ent->s.origin, PNOISE_IMPACT);
}
// calculate position for the explosion entity
// calculate position for the explosion entity
VectorMA (ent->s.origin, -0.02, ent->s.origin2, origin);
VectorMA (ent->s.origin, -0.02, ent->s.origin2, origin);
//glass fx
if (0 == Q_stricmp(other->classname, "func_explosive"))
{
// ignore it, so it can bounce
return;
}
else
if (0 == Q_stricmp(other->classname, "func_explosive")) {
// ignore it, so it can bounce
return;
}
else
// ---
if (other->takedamage)
{
G_Damage (other, ent, ent, ent->s.origin2, ent->s.origin, THROW_DAMAGE, 0, MOD_KNIFE_THROWN);
}
else
{
if (other->takedamage) {
G_Damage (other, ent, ent, ent->s.origin2, ent->s.origin, THROW_DAMAGE, 0, MOD_KNIFE_THROWN);
}
else {
// code to manage excess knives in the game, guarantees that
// no more than knifelimit knives will be stuck in walls.
// if knifelimit == 0 then it won't be in effect and it can
// start removing knives even when less than the limit are
// out there.
/* if ( g_rxn_knifelimit.value != 0 )
{
knives++;
if (knives > g_rxn_knifelimit.value)
knives = 1;
knife = FindEdictByClassnum ("weapon_Knife", knives);
if (knife)
{
knife->nextthink = level.time + .1;
}
} */
// code to manage excess knives in the game, guarantees that
// no more than knifelimit knives will be stuck in walls.
// if knifelimit == 0 then it won't be in effect and it can
// start removing knives even when less than the limit are
// out there.
/* if ( g_rxn_knifelimit.value != 0 )
{
knives++;
if (knives > g_rxn_knifelimit.value)
knives = 1;
knife = FindEdictByClassnum ("weapon_Knife", knives);
if (knife)
{
knife->nextthink = level.time + .1;
}
} */
xr_item = BG_FindItemForWeapon( WP_KNIFE );
//spawn a knife in the object
//Elder: todo - rotate the knife model so it's collinear with trajectory
//and eliminate the jittering
xr_item = BG_FindItemForWeapon( WP_KNIFE );
//xr_drop = dropWeapon( ent, xr_item, 0, FL_DROPPED_ITEM | FL_THROWN_ITEM );
xr_drop = dropWeapon( ent, xr_item, 0, FL_DROPPED_ITEM);
xr_drop->count = 1;
}
xr_drop= dropWeapon( ent, xr_item, 0, FL_DROPPED_ITEM | FL_THROWN_ITEM );
xr_drop->count =1;
}
G_FreeEntity (ent);
G_FreeEntity (ent);
}
//gentity_t *Knife_Throw (gentity_t *self,vec3_t start, vec3_t dir, int damage, int speed )
@ -933,12 +947,16 @@ void Weapon_Knife_Fire(gentity_t *ent)
gentity_t *m;
// Homer: if client is supposed to be slashing, go to that function instead
if ( !ent->client->throwKnife )
{
if ( !ent->client->throwKnife ) {
//Elder: added
ent->client->ps.stats[STAT_KNIFE] = RQ3_KNIFE_SLASH;
Knife_Attack(ent,SLASH_DAMAGE);
return;
}
//Elder: added
ent->client->ps.stats[STAT_KNIFE] = RQ3_KNIFE_THROW;
// extra vertical velocity
forward[2] += 0.2f;
@ -950,8 +968,6 @@ void Weapon_Knife_Fire(gentity_t *ent)
// m->splashDamage *= s_quadFactor;
// ^^^^ Homer: got quad?
}
/*