X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fw_common.qc;h=2e0c1e8f02bbcd466773894e43e3da4df52104f5;hb=6b188d663fd973615bd71b58cfd2d7b1b2df0ca9;hp=3343fa7c3f5f24d9977e41b05e4da32a498bc0ac;hpb=c6466f683b8270a7a56305fbf0e8cc785df8356d;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/w_common.qc b/qcsrc/server/w_common.qc index 3343fa7c3..2e0c1e8f0 100644 --- a/qcsrc/server/w_common.qc +++ b/qcsrc/server/w_common.qc @@ -1,5 +1,5 @@ -void W_GiveWeapon (entity e, float wep, string name) +void W_GiveWeapon (entity e, float wep) { entity oldself; @@ -12,12 +12,8 @@ void W_GiveWeapon (entity e, float wep, string name) self = e; if not(g_minstagib) - if (other.classname == "player") - { - sprint (other, "You got the ^2"); - sprint (other, name); - sprint (other, "\n"); - } + if(other.classname == "player") + { Send_Notification(NOTIF_ONE, other, MSG_MULTI, ITEM_WEAPON_GOT, wep); } self = oldself; } @@ -38,6 +34,8 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f entity pseudoprojectile; float f, ffs; + pseudoprojectile = world; + railgun_start = start; railgun_end = end; @@ -165,10 +163,10 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f trace_dphitq3surfaceflags = endq3surfaceflags; } -.float dmg_edge; .float dmg_force; .float dmg_radius; .float dmg_total; +//.float last_yoda; void W_BallisticBullet_Hit (void) { float f, q, g; @@ -183,24 +181,17 @@ void W_BallisticBullet_Hit (void) { endzcurveparticles(); - headshot = 0; yoda = 0; - damage_headshotbonus = self.dmg_edge * f; railgun_start = self.origin - 2 * frametime * self.velocity; railgun_end = self.origin + 2 * frametime * self.velocity; g = accuracy_isgooddamage(self.realowner, other); Damage(other, self, self.realowner, self.dmg * f, self.projectiledeathtype, self.origin, self.dmg_force * normalize(self.velocity) * f); - damage_headshotbonus = 0; - if(headshot) - f *= q; - if(self.dmg_edge > 0) + /*if(yoda && (time > (self.last_yoda + 5))) { - if(headshot) - AnnounceTo(self.realowner, "headshot"); - if(yoda) - AnnounceTo(self.realowner, "awesome"); - } + Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_YODA); + self.last_yoda = time; + }*/ // calculate hits for ballistic weapons if(g) @@ -227,7 +218,7 @@ void W_BallisticBullet_LeaveSolid_think() self.think = self.W_BallisticBullet_LeaveSolid_think_save; self.nextthink = max(time, self.W_BallisticBullet_LeaveSolid_nextthink_save); - self.W_BallisticBullet_LeaveSolid_think_save = SUB_Null; + self.W_BallisticBullet_LeaveSolid_think_save = func_null; self.flags &~= FL_ONGROUND; @@ -241,31 +232,58 @@ void W_BallisticBullet_LeaveSolid_think() UpdateCSQCProjectile(self); } -float W_BallisticBullet_LeaveSolid(entity e, vector vel, float constant) +float W_BallisticBullet_LeaveSolid(float eff) { // move the entity along its velocity until it's out of solid, then let it resume - + vector vel = self.velocity; float dt, dst, velfactor, v0, vs; float maxdist; float E0_m, Es_m; + float constant = self.dmg_radius * (other.ballistics_density ? other.ballistics_density : 1); // outside the world? forget it if(self.origin_x > world.maxs_x || self.origin_y > world.maxs_y || self.origin_z > world.maxs_z || self.origin_x < world.mins_x || self.origin_y < world.mins_y || self.origin_z < world.mins_z) return 0; + // special case for zero density and zero bullet constant: + + if(self.dmg_radius == 0) + { + if(other.ballistics_density < 0) + constant = 0; // infinite travel distance + else + return 0; // no penetration + } + else + { + if(other.ballistics_density < 0) + constant = 0; // infinite travel distance + else if(other.ballistics_density == 0) + constant = self.dmg_radius; + else + constant = self.dmg_radius * other.ballistics_density; + } + // E(s) = E0 - constant * s, constant = area of bullet circle * material constant / mass v0 = vlen(vel); E0_m = 0.5 * v0 * v0; - maxdist = E0_m / constant; - // maxdist = 0.5 * v0 * v0 / constant - // dprint("max dist = ", ftos(maxdist), "\n"); - if(maxdist <= autocvar_g_ballistics_mindistance) - return 0; + if(constant) + { + maxdist = E0_m / constant; + // maxdist = 0.5 * v0 * v0 / constant + // dprint("max dist = ", ftos(maxdist), "\n"); - traceline_inverted (self.origin, self.origin + normalize(vel) * maxdist, MOVE_NORMAL, self); + if(maxdist <= autocvar_g_ballistics_mindistance) + return 0; + } + else + { + maxdist = vlen(other.maxs - other.mins) + 1; // any distance, as long as we leave the entity + } + traceline_inverted (self.origin, self.origin + normalize(vel) * maxdist, MOVE_NORMAL, self, TRUE); if(trace_fraction == 1) // 1: we never got out of solid return 0; @@ -298,12 +316,19 @@ float W_BallisticBullet_LeaveSolid(entity e, vector vel, float constant) self.flags |= FL_ONGROUND; // prevent moving self.W_BallisticBullet_LeaveSolid_velocity = vel; + if(eff >= 0) + if(vlen(trace_endpos - self.origin) > 4) + { + endzcurveparticles(); + trailparticles(self, eff, self.origin, trace_endpos); + } + return 1; } void W_BallisticBullet_Touch (void) { - float density; + //float density; if(self.think == W_BallisticBullet_LeaveSolid_think) // skip this! return; @@ -311,6 +336,12 @@ void W_BallisticBullet_Touch (void) PROJECTILE_TOUCH; W_BallisticBullet_Hit (); + if(self.dmg_radius < 0) // these NEVER penetrate solid + { + remove(self); + return; + } + // if we hit "weapclip", bail out // // rationale of this check: @@ -331,12 +362,8 @@ void W_BallisticBullet_Touch (void) return; } - density = other.ballistics_density; - if(density == 0) - density = 1; - // go through solid! - if(!W_BallisticBullet_LeaveSolid(self, self.velocity, self.dmg_radius * density)) + if(!W_BallisticBullet_LeaveSolid(-1)) { remove(self); return; @@ -360,9 +387,9 @@ void fireBallisticBullet_trace_callback(vector start, vector hit, vector end) self.owner = world; } -void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, float lifetime, float damage, float headshotbonus, float force, float dtype, float tracereffects, float gravityfactor, float bulletconstant) +void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, float lifetime, float damage, float force, float dtype, float tracereffects, float gravityfactor, float bulletconstant) { - float lag, dt, savetime, density; + float lag, dt, savetime; //, density; entity pl, oldself; float antilagging; @@ -384,14 +411,18 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f proj.nextthink = time + lifetime; // min(pLifetime, vlen(world.maxs - world.mins) / pSpeed); W_SetupProjectileVelocityEx(proj, dir, v_up, pSpeed, 0, 0, spread, antilagging); proj.angles = vectoangles(proj.velocity); - proj.dmg_radius = autocvar_g_ballistics_materialconstant / bulletconstant; + if(bulletconstant > 0) + proj.dmg_radius = autocvar_g_ballistics_materialconstant / bulletconstant; + else if(bulletconstant == 0) + proj.dmg_radius = 0; + else + proj.dmg_radius = -1; // so: bulletconstant = bullet mass / area of bullet circle setorigin(proj, start); proj.flags = FL_PROJECTILE; proj.touch = W_BallisticBullet_Touch; proj.dmg = damage; - proj.dmg_edge = headshotbonus; proj.dmg_force = force; proj.projectiledeathtype = dtype; @@ -468,6 +499,9 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f W_BallisticBullet_Hit(); } + if(proj.dmg_radius < 0) // these NEVER penetrate solid + break; + // if we hit "weapclip", bail out // // rationale of this check: @@ -485,15 +519,13 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f if not(trace_dphitcontents & DPCONTENTS_OPAQUE) break; - density = other.ballistics_density; - if(density == 0) - density = 1; - // go through solid! - if(!W_BallisticBullet_LeaveSolid(self, self.velocity, self.dmg_radius * density)) + if(!W_BallisticBullet_LeaveSolid((other && (other.solid != SOLID_BSP)) ? eff : -1)) break; W_BallisticBullet_LeaveSolid_think(); + + self.projectiledeathtype |= HITTYPE_BOUNCE; } frametime = savetime; self = oldself; @@ -584,10 +616,14 @@ float W_CheckProjectileDamage(entity inflictor, entity projowner, float deathtyp void W_PrepareExplosionByDamage(entity attacker, void() explode) { self.takedamage = DAMAGE_NO; - self.event_damage = SUB_Null; - self.owner = attacker; - self.realowner = attacker; - + self.event_damage = func_null; + + if((attacker.flags & FL_CLIENT) && !autocvar_g_projectiles_keep_owner) + { + self.owner = attacker; + self.realowner = attacker; + } + // do not explode NOW but in the NEXT FRAME! // because recursive calls to RadiusDamage are not allowed self.nextthink = time;