-
Notifications
You must be signed in to change notification settings - Fork 7
Description
Hi there.
Lines 1961 to 2171 in 8fe7081
| void Bullet_Fire_Extended(gentity_t* source, gentity_t* attacker, vec3_t start, vec3_t end, float spread, int damage) { | |
| trace_t tr; | |
| vec3_t initial_start; | |
| gentity_t* tent; | |
| gentity_t* traceEnt; | |
| gentity_t* head = NULL; | |
| // since start is overwritten halfway through this function. | |
| VectorCopy(start, initial_start); | |
| damage *= s_quadFactor; | |
| // (SA) changed so player could shoot his own dynamite. | |
| // (SA) whoops, but that broke bullets going through explosives... | |
| trap_Trace(&tr, start, NULL, NULL, end, source->s.number, MASK_SHOT); | |
| // trap_Trace (&tr, start, NULL, NULL, end, ENTITYNUM_NONE, MASK_SHOT); | |
| traceEnt = &g_entities[tr.entityNum]; | |
| if (traceEnt->is_head) { | |
| head = traceEnt; | |
| traceEnt = head->parent; | |
| } | |
| if (LogAccuracyShot(traceEnt, source) && g_gamestate.integer == GS_PLAYING) | |
| { | |
| source->client->pers.life_acc_shots++; | |
| source->client->sess.acc_shots++; | |
| } | |
| // DHM - Nerve :: only in single player | |
| if (g_gametype.integer == GT_SINGLE_PLAYER) | |
| AICast_ProcessBullet(attacker, start, tr.endpos); | |
| // bullet debugging using Q3A's railtrail | |
| if (g_debugBullets.integer & 1) { | |
| tent = G_TempEntity(start, EV_RAILTRAIL); | |
| VectorCopy(tr.endpos, tent->s.origin2); | |
| tent->s.otherEntityNum2 = attacker->s.number; | |
| } | |
| //----(SA) commented out | |
| // if ( tr.surfaceFlags & SURF_NOIMPACT ) { | |
| // if (attacker->s.weapon == WP_MAUSER && attacker->r.svFlags & SVF_CASTAI) | |
| // SniperSoundEFX (tr.endpos); | |
| // | |
| // return; | |
| // } | |
| //----(SA) end | |
| RubbleFlagCheck(attacker, tr); | |
| EmitterCheck(traceEnt, attacker, &tr); | |
| // snap the endpos to integers, but nudged towards the line | |
| SnapVectorTowards(tr.endpos, start); | |
| //----(SA) commented out | |
| // if (attacker->s.weapon == WP_MAUSER && attacker->r.svFlags & SVF_CASTAI) | |
| // { | |
| // SniperSoundEFX (tr.endpos); | |
| // } | |
| //----(SA) end | |
| // send bullet impact | |
| if (traceEnt->takedamage && (traceEnt->client) && !(traceEnt->flags & FL_DEFENSE_GUARD)) { | |
| tent = G_TempEntity(tr.endpos, EV_BULLET_HIT_FLESH); | |
| tent->s.eventParm = traceEnt->s.number; | |
| if (LogAccuracyHit(traceEnt, attacker) && g_gamestate.integer == GS_PLAYING) { | |
| attacker->client->ps.persistant[PERS_ACCURACY_HITS]++; | |
| // L0 - Stats | |
| attacker->client->pers.life_acc_hits++; | |
| attacker->client->sess.acc_hits++; | |
| } | |
| //----(SA) added | |
| if (g_debugBullets.integer >= 2) { // show hit player bb | |
| gentity_t* bboxEnt; | |
| vec3_t b1, b2; | |
| VectorCopy(traceEnt->r.currentOrigin, b1); | |
| VectorCopy(traceEnt->r.currentOrigin, b2); | |
| VectorAdd(b1, traceEnt->r.mins, b1); | |
| VectorAdd(b2, traceEnt->r.maxs, b2); | |
| bboxEnt = G_TempEntity(b1, EV_RAILTRAIL); | |
| VectorCopy(b2, bboxEnt->s.origin2); | |
| bboxEnt->s.dmgFlags = 1; // ("type") | |
| bboxEnt->s.otherEntityNum2 = attacker->s.number; | |
| } | |
| //----(SA) end | |
| } | |
| else if (traceEnt->takedamage && traceEnt->s.eType == ET_BAT) { | |
| tent = G_TempEntity(tr.endpos, EV_BULLET_HIT_FLESH); | |
| tent->s.eventParm = traceEnt->s.number; | |
| } | |
| else { | |
| // Ridah, bullet impact should reflect off surface | |
| vec3_t reflect; | |
| float dot; | |
| if (g_debugBullets.integer >= 4) { // show hit thing bb | |
| gentity_t* bboxEnt; | |
| vec3_t b1, b2; | |
| VectorCopy(traceEnt->r.currentOrigin, b1); | |
| VectorCopy(traceEnt->r.currentOrigin, b2); | |
| VectorAdd(b1, traceEnt->r.mins, b1); | |
| VectorAdd(b2, traceEnt->r.maxs, b2); | |
| bboxEnt = G_TempEntity(b1, EV_RAILTRAIL); | |
| VectorCopy(b2, bboxEnt->s.origin2); | |
| bboxEnt->s.dmgFlags = 1; // ("type") | |
| bboxEnt->s.otherEntityNum2 = attacker->s.number; | |
| } | |
| if (traceEnt->flags & FL_DEFENSE_GUARD) { | |
| // reflect off sheild | |
| VectorSubtract(tr.endpos, traceEnt->r.currentOrigin, reflect); | |
| VectorNormalize(reflect); | |
| VectorMA(traceEnt->r.currentOrigin, 15, reflect, reflect); | |
| tent = G_TempEntity(reflect, EV_BULLET_HIT_WALL); | |
| } | |
| else { | |
| tent = G_TempEntity(tr.endpos, EV_BULLET_HIT_WALL); | |
| } | |
| dot = DotProduct(forward, tr.plane.normal); | |
| VectorMA(forward, -2 * dot, tr.plane.normal, reflect); | |
| VectorNormalize(reflect); | |
| tent->s.eventParm = DirToByte(reflect); | |
| if (traceEnt->flags & FL_DEFENSE_GUARD) { | |
| tent->s.otherEntityNum2 = traceEnt->s.number; // force sparks | |
| } | |
| else { | |
| tent->s.otherEntityNum2 = ENTITYNUM_NONE; | |
| } | |
| // done. | |
| } | |
| tent->s.otherEntityNum = attacker->s.number; | |
| if (traceEnt->takedamage) { | |
| qboolean reflectBool = qfalse; | |
| vec3_t trDir; | |
| if (traceEnt->flags & FL_DEFENSE_GUARD) { | |
| // if we are facing the direction the bullet came from, then reflect it | |
| AngleVectors(traceEnt->s.apos.trBase, trDir, NULL, NULL); | |
| if (DotProduct(forward, trDir) < 0.6) { | |
| reflectBool = qtrue; | |
| } | |
| } | |
| if (reflectBool) { | |
| vec3_t reflect_end; | |
| // reflect this bullet | |
| G_AddEvent(traceEnt, EV_GENERAL_SOUND, level.bulletRicochetSound); | |
| CalcMuzzlePoints(traceEnt, traceEnt->s.weapon); | |
| //----(SA) modified to use extended version so attacker would pass through | |
| // Bullet_Fire( traceEnt, 1000, damage ); | |
| Bullet_Endpos(traceEnt, spread, &reflect_end); | |
| Bullet_Fire_Extended(traceEnt, attacker, muzzleTrace, reflect_end, spread, damage); | |
| //----(SA) end | |
| } | |
| else { | |
| vec3_t backwards; | |
| // Ridah, don't hurt team-mates | |
| // DHM - Nerve :: Only in single player | |
| if (attacker->client && traceEnt->client && g_gametype.integer == GT_SINGLE_PLAYER && (traceEnt->r.svFlags & SVF_CASTAI) && (attacker->r.svFlags & SVF_CASTAI) && AICast_SameTeam(AICast_GetCastState(attacker->s.number), traceEnt->s.number)) { | |
| // AI's don't hurt members of their own team | |
| return; | |
| } | |
| // done. | |
| VectorSubtract(initial_start, tr.endpos, backwards); | |
| VectorNormalize(backwards); | |
| VectorMA(tr.endpos, 1, backwards, initial_start); | |
| traceEnt->headshot = IsHeadshot(traceEnt, &head, initial_start, forward, ammoTable[attacker->s.weapon].mod); | |
| if (head && g_debugBullets.integer >= 3) // show hit player head bb | |
| { | |
| gentity_t* bboxEnt; | |
| vec3_t b1, b2; | |
| VectorCopy(head->r.currentOrigin, b1); | |
| VectorCopy(head->r.currentOrigin, b2); | |
| VectorAdd(b1, head->r.mins, b1); | |
| VectorAdd(b2, head->r.maxs, b2); | |
| bboxEnt = G_TempEntity(b1, EV_RAILTRAIL); | |
| VectorCopy(b2, bboxEnt->s.origin2); | |
| bboxEnt->s.dmgFlags = 1; | |
| bboxEnt->s.otherEntityNum2 = attacker->s.number; | |
| } | |
| G_Damage(traceEnt, attacker, attacker, forward, tr.endpos, damage, 0, ammoTable[attacker->s.weapon].mod); | |
| traceEnt->headshot = qfalse; | |
| // allow bullets to "pass through" func_explosives if they break by taking another simultanious shot | |
| if (Q_stricmp(traceEnt->classname, "func_explosive") == 0) { | |
| if (traceEnt->health <= damage) { | |
| // start new bullet at position this hit the bmodel and continue to the end position (ignoring shot-through bmodel in next trace) | |
| // spread = 0 as this is an extension of an already spread shot | |
| Bullet_Fire_Extended(traceEnt, attacker, tr.endpos, end, 0, damage); | |
| } | |
| } | |
| } | |
| } | |
| } |
I've been trying to look into the shotgunning effect as is something reported by many, noticed more in a close range/slow movement fights.
Looking at bullet fire extended I don't think there is a check to detect if a bullet already hit X entity, probably makes no sense as the times moves forward yes, I know but involving lag compensation, bullet traces calc, overlapping hitboxes, applied spread, laggy moments, combined with sv_40fps there is a chance that bullet hitscan detection, which might not be perfect, a single bullet hits a target twice? Hard to explain as the time moves but somehow can see it happining, everything is possible.
Any chance to add into debug bullet to see if this attacker/bullet has hit this entity already and logs warning? Or by frame.
Entity has been hit by X attacker this frame | Might mess with explosions damage.
Entity has been hit by X bullet from this X attacker this frame | Might work better but probably harder to track.
If for any reason it happens would explain "shotgunning" and can be "easily" corrected (at that point the same check would just before G_Damage)
Correct me is this has been already issued somewhere else or makes no sense at all.
I'll be glad to chat about it more or attempt to help
-Elver