Several fixes, some new additions
This commit is contained in:
Victor Chow 2001-07-01 05:11:12 +00:00
parent a59035f44b
commit fc11d6fe2e
10 changed files with 310 additions and 12 deletions

View file

@ -91,7 +91,7 @@ static void CG_Bandage_f (void) {
//Elder: added to prevent bandaging while reloading or firing
//Moved below "already-bandaging" case and removed message
if ( cg.snap->ps.weaponTime > 0 ) {
if ( cg.snap->ps.weaponTime > 0 || cg.snap->ps.weaponstate == WEAPON_COCKED) {
//CG_Printf("You are too busy with your weapon!\n");
return;
}
@ -560,6 +560,7 @@ static consoleCommand_t commands[] = {
{ "dropweapon", CG_DropWeapon_f }, // Elder: added to reset zoom then goto server
{ "bandage", CG_Bandage_f }, // Elder: added to reset zoom then goto server
{ "reload", CG_Reload_f }, // Elder: added to reset zoom then goto server
{ "specialweapon", CG_SpecialWeapon_f }, // Elder: select special weapon
{ "tell_target", CG_TellTarget_f },
{ "tell_attacker", CG_TellAttacker_f },
{ "vtell_target", CG_VoiceTellTarget_f },
@ -674,4 +675,5 @@ void CG_InitConsoleCommands( void ) {
trap_AddCommand ("dropweapon");
//Elder: try this
trap_AddCommand ("weapon");
trap_AddCommand ("specialweapon");
}

View file

@ -1365,6 +1365,7 @@ void CG_NextWeapon_f( void );
//Elder: added?
void CG_Weapon_f( void );
void CG_PrevWeapon_f( void );
void CG_SpecialWeapon_f ( void );
void CG_RegisterWeapon( int weaponNum );
void CG_RegisterItemVisuals( int itemNum );

View file

@ -1563,10 +1563,15 @@ CG_WeaponSelectable
===============
*/
static qboolean CG_WeaponSelectable( int i ) {
//Blaze: Check the amount of clips too for the weapon rotate code
if ( !cg.snap->ps.ammo[i] && !cg.snap->ps.stats[STAT_CLIPS] ) {
//Elder: never switch to empty grenades/knives
if ( !cg.snap->ps.ammo[i] && (i == WP_GRENADE || i == WP_KNIFE) ) {
return qfalse;
}
//Blaze: Check the amount of clips too for the weapon rotate code
//Elder: this won't work plus AQ2 lets you select empty weapons
//if ( !cg.snap->ps.ammo[i] && !cg.snap->ps.stats[STAT_CLIPS] ) {
//return qfalse;
//}
if ( ! (cg.snap->ps.stats[ STAT_WEAPONS ] & ( 1 << i ) ) ) {
return qfalse;
}
@ -1590,6 +1595,11 @@ void CG_NextWeapon_f( void ) {
return;
}
// if we are going into the intermission, don't do anything
if ( cg.intermissionStarted ) {
return;
}
//Elder: added
if ( (cg.snap->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK) {
CG_Printf("You are too busy bandaging...\n");
@ -1597,7 +1607,9 @@ void CG_NextWeapon_f( void ) {
}
//Elder: in the middle of firing, reloading or weapon-switching
if (cg.snap->ps.weaponTime > 0) {
//cg.snap->ps.weaponstate == WEAPON_RELOADING when it's in
if (cg.snap->ps.weaponstate == WEAPON_DROPPING && cg.snap->ps.weaponTime > 0) {
//if (cg.snap->ps.weaponTime > 0) {
return;
}
@ -1624,6 +1636,9 @@ void CG_NextWeapon_f( void ) {
if ( i == 16 ) {
cg.weaponSelect = original;
}
else {
trap_SendClientCommand("unzoom");
}
}
/*
@ -1642,6 +1657,11 @@ void CG_PrevWeapon_f( void ) {
return;
}
// if we are going into the intermission, don't do anything
if ( cg.intermissionStarted ) {
return;
}
//Elder: added
if ( (cg.snap->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK) {
CG_Printf("You are too busy bandaging...\n");
@ -1649,7 +1669,8 @@ void CG_PrevWeapon_f( void ) {
}
//Elder: in the middle of firing, reloading or weapon-switching
if (cg.snap->ps.weaponTime > 0) {
//cg.snap->ps.weaponstate == WEAPON_RELOADING when it's in
if (cg.snap->ps.weaponstate == WEAPON_DROPPING && cg.snap->ps.weaponTime > 0) {
return;
}
@ -1676,8 +1697,77 @@ void CG_PrevWeapon_f( void ) {
if ( i == 16 ) {
cg.weaponSelect = original;
}
else {
trap_SendClientCommand("unzoom");
}
}
/*
===============
Added by Elder
CG_SpecialWeapon_f
===============
*/
void CG_SpecialWeapon_f( void ) {
int i;
int original;
if ( !cg.snap ) {
return;
}
if ( cg.snap->ps.pm_flags & PMF_FOLLOW ) {
return;
}
// if we are going into the intermission, don't do anything
if ( cg.intermissionStarted ) {
return;
}
//Elder: added
if ( (cg.snap->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK) {
CG_Printf("You are too busy bandaging...\n");
return;
}
//Elder: in the middle of firing, reloading or weapon-switching
//cg.snap->ps.weaponstate == WEAPON_RELOADING when it's in
if (cg.snap->ps.weaponstate == WEAPON_DROPPING && cg.snap->ps.weaponTime > 0) {
return;
}
cg.weaponSelectTime = cg.time;
original = cg.weaponSelect;
for ( i = 0 ; i < 16 ; i++ ) {
cg.weaponSelect++;
if ( cg.weaponSelect == 16 ) {
cg.weaponSelect = 0;
}
//Skip normal weapons
switch (cg.weaponSelect) {
case WP_PISTOL:
case WP_KNIFE:
case WP_GRENADE:
continue;
}
if ( CG_WeaponSelectable( cg.weaponSelect ) ) {
break;
}
}
if ( i == 16 ) {
cg.weaponSelect = original;
}
else {
trap_SendClientCommand("unzoom");
}
}
//Elder: for returning to the zoom state in ps stats
void CG_RQ3_QuickZoom ( void ) {
//cg.zoomLevel = lastzoom;

View file

@ -1598,6 +1598,7 @@ static void PM_Footsteps( void ) {
// if we just crossed a cycle boundary, play an apropriate footstep event
if ( ( ( old + 64 ) ^ ( pm->ps->bobCycle + 64 ) ) & 128 ) {
if ( pm->waterlevel == 0 ) {
//Elder: we can check for slippers here!
// on ground will only play sounds if running
if ( footstep && !pm->noFootsteps ) {
PM_AddEvent( PM_FootstepForSurface() );
@ -1855,6 +1856,14 @@ static void PM_Weapon( void ) {
// again if lowering or raising
if ( pm->ps->weaponTime <= 0 || pm->ps->weaponstate != WEAPON_FIRING ) {
if ( pm->ps->weapon != pm->cmd.weapon ) {
//Elder TODO: if switching weapons, fire off the grenade "instantly"
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->ps->ammo[WP_GRENADE]--;
}
PM_BeginWeaponChange( pm->cmd.weapon );
}
}
@ -1879,7 +1888,37 @@ static void PM_Weapon( void ) {
return;
}
// Elder: fire on release - based on code from inolen
// check for fire
// if they are pressing attack and their current weapon is the railgun
if ((pm->cmd.buttons & 1) && (pm->ps->weapon == WP_GRENADE) ) {
pm->ps->weaponTime = 0;
// put it in the "cocked" position
pm->ps->weaponstate = WEAPON_COCKED;
return;
}
// check for fire release
// if they aren't pressing attack
if (!(pm->cmd.buttons & 1)) {
// if we had them cocked and then they aren't pressing it then
// that means they released it
if (pm->ps->weaponstate == WEAPON_COCKED) {
// set to be able to fire
pm->ps->weaponstate = WEAPON_READY;
}
else
{
// else if they arn't pressing attack, then they just are running around
pm->ps->weaponTime = 0;
pm->ps->weaponstate = WEAPON_READY;
pm->ps->stats[STAT_BURST] = 0;
return;
}
}
/*
if ( ! (pm->cmd.buttons & BUTTON_ATTACK) ) {
pm->ps->weaponTime = 0;
pm->ps->weaponstate = WEAPON_READY;
@ -1893,7 +1932,7 @@ static void PM_Weapon( void ) {
//pm->ps->stats[STAT_BURST] = 0;
//}
return;
}
}*/
//Elder: custom fire animations go here
// start the animation even if out of ammo

View file

@ -59,6 +59,12 @@
#define RQ3_DEBRIS_CONCRETE 0x00000400
//#define RQ3_DEBRIS_POPCAN 0x00000800
//Elder: debris variations
#define RQ3_DEBRIS_VAR0 0x00001000
#define RQ3_DEBRIS_VAR1 0x00002000
#define RQ3_DEBRIS_VAR2 0x00004000
#define RQ3_DEBRIS_VAR3 0x00008000
//Elder: to stop some of the hardcoding
//This is some ammo amounts per clip/item pick up
#define RQ3_SSG3000_CLIP 6
@ -326,7 +332,8 @@ typedef enum {
} pmtype_t;
typedef enum {
WEAPON_READY,
WEAPON_READY,
WEAPON_COCKED,
WEAPON_RAISING,
WEAPON_DROPPING,
WEAPON_FIRING//,

View file

@ -2038,6 +2038,11 @@ void Cmd_OpenDoor(gentity_t *ent)
{
//Use_BinaryMover( ent->parent, ent, other );
gentity_t *door = NULL;
//Don't open doors if intermission or dead
if (level.intermissiontime || ent->client->ps.stats[STAT_HEALTH] <= 0)
return;
while ((door = findradius(door,ent->r.currentOrigin,100)) != NULL)
{
if (Q_stricmp (door->classname, "func_door_rotating") == 0) {
@ -2116,8 +2121,8 @@ void Cmd_Weapon(gentity_t *ent)
//Elder: don't print - will broadcast to server
//G_Printf("zoomlevel = %d\n",ent->client->zoomed);
//G_AddEvent(ent,EV_ZOOM,ent->client->zoomed);
break;
case WP_PISTOL:
// semiauto toggle (increase accuracy)
@ -2220,7 +2225,6 @@ void Cmd_Weapon(gentity_t *ent)
break;
}
}
@ -2230,7 +2234,7 @@ void Cmd_Unzoom(gentity_t *ent){
//Elder: added
//if (ent->client->isBandaging == qtrue) {
if ( (ent->client->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK) {
trap_SendServerCommand( ent-g_entities, va("print \"You'll get to your weapon when you are finished bandaging!\n\""));
//trap_SendServerCommand( ent-g_entities, va("print \"You'll get to your weapon when you are finished bandaging!\n\""));
return;
}
else {

View file

@ -513,6 +513,11 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
//Blaze: Stop bleeding when dead
if ( self->client )
{
//Elder: drop the primed grenade
if (self->client->ps.weapon == WP_GRENADE &&
self->client->ps.weaponstate == WEAPON_COCKED) {
FireWeapon(self);
}
// Hawkins put spread back and zoom out
//Elder: this wouldn't happen if you copy and paste carefully

View file

@ -394,10 +394,21 @@ void G_BreakGlass(gentity_t *ent, vec3_t point, int mod) {
VectorScale(size, 0.5, size);
VectorAdd(ent->r.mins, size, center);
//Elder:
//eventParm can only hold a byte (8-bits/255)
//So if we receive a huge one, we can knock it down (and-op)
//and count the number of times
//Once it's below 255, we can send a more appropriate event
//This way, the mappers can use a single func_breakable
//while we process it on the server-side.
//Besides, any bit-op is fast.
//Places to stuff: eventParm, generic1
// If the glass has no more life, BREAK IT
if( ent->health <= 0 ) {
//Elder: using event param to specify debris type
eParm = ent->s.eventParm;
G_Printf("eParm: %d\n", eParm);
//Elder: free it after the eventParm assignment
G_FreeEntity( ent );

View file

@ -695,7 +695,11 @@ gentity_t *fire_grenade (gentity_t *self, vec3_t start, vec3_t dir) {
//Elder: grenade toggle distances/speeds
if ( self->client) {
if ( (self->client->ps.persistant[PERS_WEAPONMODES] & RQ3_GRENSHORT) == RQ3_GRENSHORT &&
if (self->client->ps.stats[STAT_HEALTH] <= 0) {
//Always drop close range if dead
speed = GRENADE_SHORT_SPEED / 2;
}
else if ( (self->client->ps.persistant[PERS_WEAPONMODES] & RQ3_GRENSHORT) == RQ3_GRENSHORT &&
(self->client->ps.persistant[PERS_WEAPONMODES] & RQ3_GRENMED) == RQ3_GRENMED) {
//Long range throw
speed = GRENADE_LONG_SPEED;

View file

@ -1018,7 +1018,7 @@ void Weapon_MK23_Fire(gentity_t *ent)
SSG3000 Attack
============
*/
void Weapon_SSG3000_Fire(gentity_t *ent)
void Weapon_SSG3000_FireOld(gentity_t *ent)
{
float spread;
//Elder: Don't print - will broadcast to server
@ -1040,6 +1040,141 @@ void Weapon_SSG3000_Fire(gentity_t *ent)
RQ3_SaveZoomLevel(ent);
}
/*
=================
Elder:
This is based on the railgun code
weapon_ssg3000_fire
=================
*/
#define MAX_SSG3000_HITS 5
void Weapon_SSG3000_Fire (gentity_t *ent) {
vec3_t end;
trace_t trace;
gentity_t *tent;
gentity_t *traceEnt;
int damage;
int i;
int hits;
int unlinked;
int passent;
qboolean hitBreakable;
gentity_t *unlinkedEntities[MAX_SSG3000_HITS];
//damage = 100 * s_quadFactor;
damage = SNIPER_DAMAGE;
VectorMA (muzzle, 8192, forward, end);
// trace only against the solids, so the SSG3000 will go through people
unlinked = 0;
hits = 0;
passent = ent->s.number;
G_Printf("NewSSG3000: Start\n");
do {
//Elder: need to store this flag because
//the entity may get wiped out in G_Damage
hitBreakable = qfalse;
trap_Trace (&trace, muzzle, NULL, NULL, end, passent, MASK_SHOT );
if ( trace.entityNum >= ENTITYNUM_MAX_NORMAL ) {
break;
}
traceEnt = &g_entities[ trace.entityNum ];
if ( traceEnt->takedamage ) {
//flag hitBreakable - bullets go through even
//if it doesn't "shatter" - but that's usually
//not the case
if ( traceEnt->s.eType == ET_BREAKABLE ) {
hitBreakable = qtrue;
}
if( LogAccuracyHit( traceEnt, ent ) ) {
hits++;
}
G_Damage (traceEnt, ent, ent, forward, trace.endpos, damage, 0, MOD_SNIPER);
}
//Elder: go through non-solids and breakables
//If we ever wanted to "shoot through walls" we'd do stuff here
if ( hitBreakable == qfalse && (trace.contents & CONTENTS_SOLID)) {
break; // we hit something solid enough to stop the beam
}
// unlink this entity, so the next trace will go past it
trap_UnlinkEntity( traceEnt );
unlinkedEntities[unlinked] = traceEnt;
unlinked++;
} while ( unlinked < MAX_SSG3000_HITS );
// link back in any entities we unlinked
for ( i = 0 ; i < unlinked ; i++ ) {
trap_LinkEntity( unlinkedEntities[i] );
}
// the final trace endpos will be the terminal point of the rail trail
// snap the endpos to integers to save net bandwidth, but nudged towards the line
SnapVectorTowards( trace.endpos, muzzle );
// send bullet impact
if ( traceEnt->takedamage && traceEnt->client ) {
//Elder: should probably change to something more spectacular
tent = G_TempEntity( trace.endpos, EV_BULLET_HIT_FLESH );
tent->s.eventParm = traceEnt->s.number;
if( LogAccuracyHit( traceEnt, ent ) ) {
ent->client->accuracy_hits++;
}
} else {
tent = G_TempEntity( trace.endpos, EV_BULLET_HIT_WALL );
tent->s.eventParm = DirToByte( trace.plane.normal );
}
tent->s.otherEntityNum = ent->s.number;
// send railgun beam effect
//tent = G_TempEntity( trace.endpos, EV_RAILTRAIL );
// set player number for custom colors on the railtrail
//tent->s.clientNum = ent->s.clientNum;
//VectorCopy( muzzle, tent->s.origin2 );
// move origin a bit to come closer to the drawn gun muzzle
//VectorMA( tent->s.origin2, 4, right, tent->s.origin2 );
//VectorMA( tent->s.origin2, -1, up, tent->s.origin2 );
// no explosion at end if SURF_NOIMPACT, but still make the trail
//if ( trace.surfaceFlags & SURF_NOIMPACT ) {
//tent->s.eventParm = 255; // don't make the explosion at the end
//} else {
//tent->s.eventParm = DirToByte( trace.plane.normal );
//}
//tent->s.clientNum = ent->s.clientNum;
// give the shooter a reward sound if they have made two railgun hits in a row
if ( hits == 0 ) {
// complete miss
ent->client->accurateCount = 0;
} else {
// check for "impressive" reward sound
ent->client->accurateCount += hits;
if ( ent->client->accurateCount >= 3 ) {
ent->client->accurateCount -= 3;
//Blaze: Removed because it uses the persistant stats stuff
//ent->client->ps.persistant[PERS_IMPRESSIVE_COUNT]++;
// add the sprite over the player's head
ent->client->ps.eFlags &= ~(EF_AWARD_IMPRESSIVE | EF_AWARD_EXCELLENT | EF_AWARD_GAUNTLET | EF_AWARD_ASSIST | EF_AWARD_DEFEND | EF_AWARD_CAP );
ent->client->ps.eFlags |= EF_AWARD_IMPRESSIVE;
ent->client->rewardTime = level.time + REWARD_SPRITE_TIME;
}
ent->client->accuracy_hits++;
}
}
/*
============
MP5 Attack