mirror of
https://github.com/ReactionQuake3/reaction.git
synced 2024-11-13 00:24:29 +00:00
Elder:
Fixes a serious sniper rifle shot crash
This commit is contained in:
parent
fc11d6fe2e
commit
316a3ae002
3 changed files with 84 additions and 30 deletions
|
@ -1496,19 +1496,21 @@ void ClientEndFrame( gentity_t *ent ) {
|
||||||
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_BANDAGE_WORK;
|
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_BANDAGE_WORK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//Elder: M4 ride-up/kick -- condition for non-burst and ammo only
|
//Elder: M4 ride-up/kick -- condition for non-burst and ammo only
|
||||||
if ( ent->client->ps.weapon == WP_M4 && ent->client->ps.ammo[WP_M4] > 0 &&
|
if ( ent->client->ps.weapon == WP_M4 && ent->client->ps.ammo[WP_M4] > 0 &&
|
||||||
(ent->client->ps.persistant[PERS_WEAPONMODES] & RQ3_M4MODE) != RQ3_M4MODE &&
|
(ent->client->ps.persistant[PERS_WEAPONMODES] & RQ3_M4MODE) != RQ3_M4MODE &&
|
||||||
(ent->client->buttons & BUTTON_ATTACK) == BUTTON_ATTACK)
|
(ent->client->buttons & BUTTON_ATTACK) == BUTTON_ATTACK)
|
||||||
{
|
{
|
||||||
//G_Printf("bullets: %d, viewangle: %f\n", ent->client->consecutiveShots, ent->client->ps.viewangles[0]);
|
//G_Printf("bullets: %d, viewangle: %f\n", ent->client->consecutiveShots, ent->client->ps.viewangles[0]);
|
||||||
ent->client->ps.delta_angles[0] = ANGLE2SHORT(ent->client->consecutiveShots * -0.7);
|
ent->client->ps.delta_angles[0] = ANGLE2SHORT(SHORT2ANGLE(ent->client->ps.delta_angles[0]) - 0.7);
|
||||||
}
|
}
|
||||||
else
|
else if (ent->client->consecutiveShots)
|
||||||
{
|
{
|
||||||
ent->client->ps.delta_angles[0] = 0;
|
//Restore view after shots
|
||||||
|
ent->client->ps.delta_angles[0] = ANGLE2SHORT(SHORT2ANGLE(ent->client->ps.delta_angles[0]) - ent->client->consecutiveShots * -0.7);
|
||||||
ent->client->consecutiveShots = 0;
|
ent->client->consecutiveShots = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
G_SetClientSound (ent);
|
G_SetClientSound (ent);
|
||||||
|
|
|
@ -2039,8 +2039,8 @@ void Cmd_OpenDoor(gentity_t *ent)
|
||||||
//Use_BinaryMover( ent->parent, ent, other );
|
//Use_BinaryMover( ent->parent, ent, other );
|
||||||
gentity_t *door = NULL;
|
gentity_t *door = NULL;
|
||||||
|
|
||||||
//Don't open doors if intermission or dead
|
//Don't open doors if dead
|
||||||
if (level.intermissiontime || ent->client->ps.stats[STAT_HEALTH] <= 0)
|
if (ent->client->ps.stats[STAT_HEALTH] <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while ((door = findradius(door,ent->r.currentOrigin,100)) != NULL)
|
while ((door = findradius(door,ent->r.currentOrigin,100)) != NULL)
|
||||||
|
|
|
@ -1043,71 +1043,121 @@ void Weapon_SSG3000_FireOld(gentity_t *ent)
|
||||||
/*
|
/*
|
||||||
=================
|
=================
|
||||||
Elder:
|
Elder:
|
||||||
This is based on the railgun code
|
This is a triple-hybrid bastard child of
|
||||||
|
railgun_fire, old SSG, and bullet_fire code
|
||||||
|
|
||||||
weapon_ssg3000_fire
|
weapon_ssg3000_fire
|
||||||
=================
|
=================
|
||||||
*/
|
*/
|
||||||
#define MAX_SSG3000_HITS 5
|
#define MAX_SSG3000_HITS 4
|
||||||
void Weapon_SSG3000_Fire (gentity_t *ent) {
|
void Weapon_SSG3000_Fire (gentity_t *ent) {
|
||||||
vec3_t end;
|
vec3_t end;
|
||||||
trace_t trace;
|
trace_t trace;
|
||||||
gentity_t *tent;
|
gentity_t *tent[MAX_SSG3000_HITS];
|
||||||
|
gentity_t *tentWall;
|
||||||
gentity_t *traceEnt;
|
gentity_t *traceEnt;
|
||||||
int damage;
|
int damage;
|
||||||
int i;
|
int i;
|
||||||
int hits;
|
int hits;
|
||||||
int unlinked;
|
int unlinked;
|
||||||
int passent;
|
int passent;
|
||||||
qboolean hitBreakable;
|
|
||||||
gentity_t *unlinkedEntities[MAX_SSG3000_HITS];
|
gentity_t *unlinkedEntities[MAX_SSG3000_HITS];
|
||||||
|
|
||||||
|
qboolean hitBreakable;
|
||||||
|
float r;
|
||||||
|
float u;
|
||||||
|
float spread;
|
||||||
|
|
||||||
|
|
||||||
|
VectorMA (muzzle, 8192*16, forward, end);
|
||||||
|
|
||||||
|
//Elder: added to assist in zoom crap
|
||||||
|
if (RQ3_isZoomed(ent)) {
|
||||||
|
spread = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
spread = RQ3Spread(ent, SNIPER_SPREAD);
|
||||||
|
r = random() * M_PI * 2.0f;
|
||||||
|
u = sin(r) * crandom() * spread * 16;
|
||||||
|
r = cos(r) * crandom() * spread * 16;
|
||||||
|
VectorMA (end, r, right, end);
|
||||||
|
VectorMA (end, u, up, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//damage = 100 * s_quadFactor;
|
//damage = 100 * s_quadFactor;
|
||||||
damage = SNIPER_DAMAGE;
|
damage = SNIPER_DAMAGE;
|
||||||
|
|
||||||
VectorMA (muzzle, 8192, forward, end);
|
//VectorMA (muzzle, 8192*16, forward, end);
|
||||||
|
|
||||||
// trace only against the solids, so the SSG3000 will go through people
|
// trace only against the solids, so the SSG3000 will go through people
|
||||||
unlinked = 0;
|
unlinked = 0;
|
||||||
hits = 0;
|
hits = 0;
|
||||||
passent = ent->s.number;
|
passent = ent->s.number;
|
||||||
G_Printf("NewSSG3000: Start\n");
|
//G_Printf("(%d) SSG: Begin loop\n", level.time);
|
||||||
do {
|
do {
|
||||||
//Elder: need to store this flag because
|
//Elder: need to store this flag because
|
||||||
//the entity may get wiped out in G_Damage
|
//the entity may get wiped out in G_Damage
|
||||||
hitBreakable = qfalse;
|
hitBreakable = qfalse;
|
||||||
|
|
||||||
|
//G_Printf("(%d) SSG: Trapping trace\n", level.time);
|
||||||
|
|
||||||
trap_Trace (&trace, muzzle, NULL, NULL, end, passent, MASK_SHOT );
|
trap_Trace (&trace, muzzle, NULL, NULL, end, passent, MASK_SHOT );
|
||||||
if ( trace.entityNum >= ENTITYNUM_MAX_NORMAL ) {
|
if ( trace.entityNum >= ENTITYNUM_MAX_NORMAL ) {
|
||||||
|
//G_Printf("(%d) SSG: OOB Entity: exiting loop\n", level.time);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
traceEnt = &g_entities[ trace.entityNum ];
|
traceEnt = &g_entities[ trace.entityNum ];
|
||||||
|
|
||||||
if ( traceEnt->takedamage ) {
|
if ( traceEnt->takedamage ) {
|
||||||
|
//G_Printf("(%d) SSG: hit damagable entity\n", level.time);
|
||||||
|
|
||||||
//flag hitBreakable - bullets go through even
|
//flag hitBreakable - bullets go through even
|
||||||
//if it doesn't "shatter" - but that's usually
|
//if it doesn't "shatter" - but that's usually
|
||||||
//not the case
|
//not the case
|
||||||
if ( traceEnt->s.eType == ET_BREAKABLE ) {
|
if ( traceEnt->s.eType == ET_BREAKABLE ) {
|
||||||
|
//G_Printf("(%d) SSG: Hit a breakable\n", level.time);
|
||||||
hitBreakable = qtrue;
|
hitBreakable = qtrue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// send impacts
|
||||||
|
if ( traceEnt->client )
|
||||||
|
{
|
||||||
|
tent[unlinked] = G_TempEntity( trace.endpos, EV_BULLET_HIT_FLESH );
|
||||||
|
tent[unlinked]->s.eventParm = traceEnt->s.number;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tent[unlinked] = G_TempEntity( trace.endpos, EV_BULLET_HIT_WALL );
|
||||||
|
tent[unlinked]->s.eventParm = DirToByte( trace.plane.normal );
|
||||||
|
}
|
||||||
|
tent[unlinked]->s.otherEntityNum = ent->s.number;
|
||||||
|
|
||||||
if( LogAccuracyHit( traceEnt, ent ) ) {
|
if( LogAccuracyHit( traceEnt, ent ) ) {
|
||||||
hits++;
|
hits++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//G_Printf("(%d) SSG: Doing damage to target\n", level.time);
|
||||||
G_Damage (traceEnt, ent, ent, forward, trace.endpos, damage, 0, MOD_SNIPER);
|
G_Damage (traceEnt, ent, ent, forward, trace.endpos, damage, 0, MOD_SNIPER);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Elder: go through non-solids and breakables
|
//Elder: go through non-solids and breakables
|
||||||
//If we ever wanted to "shoot through walls" we'd do stuff here
|
//If we ever wanted to "shoot through walls" we'd do stuff here
|
||||||
if ( hitBreakable == qfalse && (trace.contents & CONTENTS_SOLID)) {
|
if ( hitBreakable == qfalse && (trace.contents & CONTENTS_SOLID)) {
|
||||||
|
//G_Printf("(%d) SSG: did not hit breakable and hit solid, exiting loop\n", level.time);
|
||||||
break; // we hit something solid enough to stop the beam
|
break; // we hit something solid enough to stop the beam
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//G_Printf("(%d) SSG: Unlinking trace entity\n", level.time);
|
||||||
// unlink this entity, so the next trace will go past it
|
// unlink this entity, so the next trace will go past it
|
||||||
trap_UnlinkEntity( traceEnt );
|
trap_UnlinkEntity( traceEnt );
|
||||||
unlinkedEntities[unlinked] = traceEnt;
|
unlinkedEntities[unlinked] = traceEnt;
|
||||||
unlinked++;
|
unlinked++;
|
||||||
|
//G_Printf("(%d) SSG: Unlinked count: %d\n", level.time, unlinked);
|
||||||
} while ( unlinked < MAX_SSG3000_HITS );
|
} while ( unlinked < MAX_SSG3000_HITS );
|
||||||
|
|
||||||
|
//G_Printf("(%d) SSG: Relinking unlinked entities\n", level.time);
|
||||||
// link back in any entities we unlinked
|
// link back in any entities we unlinked
|
||||||
for ( i = 0 ; i < unlinked ; i++ ) {
|
for ( i = 0 ; i < unlinked ; i++ ) {
|
||||||
trap_LinkEntity( unlinkedEntities[i] );
|
trap_LinkEntity( unlinkedEntities[i] );
|
||||||
|
@ -1118,20 +1168,16 @@ void Weapon_SSG3000_Fire (gentity_t *ent) {
|
||||||
// snap the endpos to integers to save net bandwidth, but nudged towards the line
|
// snap the endpos to integers to save net bandwidth, but nudged towards the line
|
||||||
SnapVectorTowards( trace.endpos, muzzle );
|
SnapVectorTowards( trace.endpos, muzzle );
|
||||||
|
|
||||||
// send bullet impact
|
//G_Printf("(%d) SSG: Sending bullet impact event\n", level.time);
|
||||||
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 wall bullet impact
|
||||||
|
// no explosion at end if SURF_NOIMPACT
|
||||||
|
if ( !(trace.surfaceFlags & SURF_NOIMPACT) )
|
||||||
|
{
|
||||||
|
tentWall = G_TempEntity( trace.endpos, EV_BULLET_HIT_WALL );
|
||||||
|
tentWall->s.eventParm = DirToByte( trace.plane.normal );
|
||||||
|
tentWall->s.otherEntityNum = ent->s.number;
|
||||||
|
}
|
||||||
|
|
||||||
// send railgun beam effect
|
// send railgun beam effect
|
||||||
//tent = G_TempEntity( trace.endpos, EV_RAILTRAIL );
|
//tent = G_TempEntity( trace.endpos, EV_RAILTRAIL );
|
||||||
|
@ -1152,6 +1198,8 @@ void Weapon_SSG3000_Fire (gentity_t *ent) {
|
||||||
//}
|
//}
|
||||||
//tent->s.clientNum = ent->s.clientNum;
|
//tent->s.clientNum = ent->s.clientNum;
|
||||||
|
|
||||||
|
//G_Printf("(%d) SSG: Shooter reward\n", level.time);
|
||||||
|
|
||||||
// give the shooter a reward sound if they have made two railgun hits in a row
|
// give the shooter a reward sound if they have made two railgun hits in a row
|
||||||
if ( hits == 0 ) {
|
if ( hits == 0 ) {
|
||||||
// complete miss
|
// complete miss
|
||||||
|
@ -1172,6 +1220,9 @@ void Weapon_SSG3000_Fire (gentity_t *ent) {
|
||||||
ent->client->accuracy_hits++;
|
ent->client->accuracy_hits++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Elder: bolt action plus save last zoom
|
||||||
|
ent->client->weaponfireNextTime = level.time + RQ3_SSG3000_BOLT_DELAY;
|
||||||
|
RQ3_SaveZoomLevel(ent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1482,6 +1533,7 @@ void FireWeapon( gentity_t *ent ) {
|
||||||
Weapon_M4_Fire ( ent );
|
Weapon_M4_Fire ( ent );
|
||||||
break;
|
break;
|
||||||
case WP_SSG3000:
|
case WP_SSG3000:
|
||||||
|
//Weapon_SSG3000_FireOld( ent );
|
||||||
Weapon_SSG3000_Fire ( ent );
|
Weapon_SSG3000_Fire ( ent );
|
||||||
break;
|
break;
|
||||||
case WP_MP5:
|
case WP_MP5:
|
||||||
|
|
Loading…
Reference in a new issue