]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/damage.qc
Transifex autosync
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / damage.qc
index 3cbc07c57d3dddb989bd6b954ad58df86e6186f0..d5a9a20c760d352a7d6631ed2530eba9cf2faad4 100644 (file)
@@ -245,8 +245,10 @@ void Obituary(entity attacker, entity inflictor, entity targ, int deathtype, .en
        if (MUTATOR_CALLHOOK(ClientObituary, inflictor, attacker, targ, deathtype, attacker.(weaponentity))) { CS(targ).killcount = 0; return; }
        notif_anonymous = M_ARGV(5, bool);
 
+       // TODO: Replace "???" with a translatable "Anonymous player" string
+       // https://gitlab.com/xonotic/xonotic-data.pk3dir/-/issues/2839
        if(notif_anonymous)
-               attacker_name = "Anonymous player";
+               attacker_name = "???";
 
        #ifdef NOTIFICATIONS_DEBUG
        Debug_Notification(
@@ -531,11 +533,11 @@ void Freeze(entity targ, float revivespeed, int frozen_type, bool show_waypoint)
        FOREACH_CLIENT(IS_PLAYER(it),
        {
                for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
-           {
-               .entity weaponentity = weaponentities[slot];
-               if(it.(weaponentity).hook.aiment == targ)
-                       RemoveHook(it.(weaponentity).hook);
-           }
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       if(it.(weaponentity).hook.aiment == targ)
+                               RemoveHook(it.(weaponentity).hook);
+               }
        });
 
        // add waypoint
@@ -565,11 +567,11 @@ void Unfreeze(entity targ, bool reset_health)
        FOREACH_CLIENT(IS_PLAYER(it),
        {
                for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
-           {
-               .entity weaponentity = weaponentities[slot];
-               if(it.(weaponentity).hook.aiment == targ)
-                       RemoveHook(it.(weaponentity).hook);
-           }
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       if(it.(weaponentity).hook.aiment == targ)
+                               RemoveHook(it.(weaponentity).hook);
+               }
        });
 
        // remove the ice block
@@ -608,7 +610,7 @@ void Damage(entity targ, entity inflictor, entity attacker, float damage, int de
 
                // These are ALWAYS lethal
                // No damage modification here
-               // Instead, prepare the victim for his death...
+               // Instead, prepare the victim for their death...
                if(deathtype == DEATH_TEAMCHANGE.m_id || deathtype == DEATH_AUTOTEAMCHANGE.m_id)
                {
                        SetResourceExplicit(targ, RES_ARMOR, 0);
@@ -710,11 +712,11 @@ void Damage(entity targ, entity inflictor, entity attacker, float damage, int de
                if(IS_PLAYER(targ) && damage > 0 && attacker)
                {
                        for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
-                   {
-                       .entity went = weaponentities[slot];
-                       if(targ.(went).hook && targ.(went).hook.aiment == attacker)
-                               RemoveHook(targ.(went).hook);
-                   }
+                       {
+                               .entity went = weaponentities[slot];
+                               if(targ.(went).hook && targ.(went).hook.aiment == attacker)
+                                       RemoveHook(targ.(went).hook);
+                       }
                }
 
                if(STAT(FROZEN, targ) && !ITEM_DAMAGE_NEEDKILL(deathtype)
@@ -917,13 +919,17 @@ float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector in
                if (((cantbe != targ) && !mustbe) || (mustbe == targ))
                if (targ.takedamage)
                {
-                       // measure distance from nearest point on target (not origin)
-                       // to nearest point on inflictor (not origin)
+                       // calculate distance from nearest point on target to nearest point on inflictor
+                       // instead of origin to ensure full damage on impacts
+
                        vector nearest = targ.WarpZone_findradius_nearest;
+
+                       // optimize code by getting inflictororigin_wz from WarpZone_FindRadius calculations instead of
+                       //vector inflictororigin_wz = WarpZone_TransformOrigin(targ, inflictororigin);
+
+                       vector inflictororigin_wz = targ.WarpZone_findradius_nearest + targ.WarpZone_findradius_dist;
                        vector inflictornearest = NearestPointOnBoundingBox(
-                               inflictororigin - (inflictor.maxs - inflictor.mins) * 0.5,
-                               inflictororigin + (inflictor.maxs - inflictor.mins) * 0.5,
-                               nearest);
+                               inflictororigin_wz + inflictor.mins, inflictororigin_wz + inflictor.maxs, nearest);
                        vector diff = inflictornearest - nearest;
 
                        // round up a little on the damage to ensure full damage on impacts
@@ -931,26 +937,68 @@ float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector in
                        float dist = max(0, vlen(diff) - bound(MIN_DAMAGEEXTRARADIUS, targ.damageextraradius, MAX_DAMAGEEXTRARADIUS));
                        if (dist <= rad)
                        {
-                               float power = 1;
-                               if (rad > 0)
-                                       power -= (dist / rad);
-                               // at this point power can't be < 0 or > 1
-                               float finaldmg = coredamage * power + edgedamage * (1 - power);
+                               float f = (rad > 0) ? 1 - (dist / rad) : 1;
+                               // at this point f can't be < 0 or > 1
+                               float finaldmg = coredamage * f + edgedamage * (1 - f);
                                if (finaldmg > 0)
                                {
                                        float a;
                                        float c;
                                        vector hitloc;
-                                       vector myblastorigin;
-                                       vector center;
-
-                                       myblastorigin = WarpZone_TransformOrigin(targ, inflictororigin);
 
                                        // if it's a player, use the view origin as reference
-                                       center = CENTER_OR_VIEWOFS(targ);
+                                       vector center = CENTER_OR_VIEWOFS(targ);
+
+                                       if (autocvar_g_player_damageplayercenter)
+                                       {
+                                               if (targ != attacker)
+                                               {
+                                                       // always use target's bbox centerpoint
+                                                       center = targ.origin + ((targ.mins + targ.maxs) * 0.5);
+                                               }
+                                               else // targ == attacker
+                                               {
+                                               #if 0
+                                                       // code stolen from W_SetupShot_Dir_ProjectileSize_Range()
+                                                       vector md = targ.(weaponentity).movedir;
+                                                       vector dv = v_right * -md.y + v_up * md.z;
+                                                       vector mi = '0 0 0', ma = '0 0 0';
+
+                                                       if(IS_CLIENT(targ)) // no antilag for non-clients!
+                                                       {
+                                                               if(CS(targ).antilag_debug)
+                                                                       tracebox_antilag(targ, center, mi, ma, center + dv, MOVE_NORMAL, targ, CS(targ).antilag_debug);
+                                                               else
+                                                                       tracebox_antilag(targ, center, mi, ma, center + dv, MOVE_NORMAL, targ, ANTILAG_LATENCY(targ));
+                                                       }
+                                                       else
+                                                               tracebox(center, mi, ma, center + dv, MOVE_NORMAL, targ);
+
+                                                       center.z = trace_endpos.z;
+                                               #else
+                                                       // very cheap way but it skips move into solid checks which is fine most of the time for now AFAIK
+                                                       // this should only really be an issue with some rare edge cases where
+                                                       // shot origin was prevented from going into a ceiling but it still explodes at the ceiling
+                                                       // shot origin wasn't raised as high as possible and the shooter gets upwards knockback
+                                                       // TL;DR: no bugs if vertical shot origin is always within player bbox
+                                                       center.z = center.z + targ.(weaponentity).movedir.z;
+                                               #endif
+                                               }
+                                       }
 
-                                       force = normalize(center - myblastorigin);
-                                       force = force * (finaldmg / coredamage) * forceintensity;
+                                       /* debug prints
+                                       print(sprintf("origin  vec %v\n", targ.origin));
+                                       print(sprintf("movedir vec %v\n", targ.(weaponentity).movedir));
+                                       print(sprintf("old def vec %v\n", CENTER_OR_VIEWOFS(targ)));
+                                       print(sprintf("origin+vofs %v\n", targ.origin + targ.view_ofs));
+                                       print(sprintf("bbox center %v\n", (targ.origin + ((targ.mins + targ.maxs) * 0.5))));
+                                       print(sprintf("center  vec %v\n", center));
+                                       print(sprintf("shotorg vec %v\n", w_shotorg));
+                                       print("\n");
+                                       */
+
+                                       force = normalize(center - inflictororigin_wz);
+                                       force = force * (finaldmg / max(coredamage, edgedamage)) * forceintensity;
                                        hitloc = nearest;
 
                                        // apply special scaling along the z axis if set
@@ -1020,14 +1068,15 @@ float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector in
 
                                                if(autocvar_g_throughfloor_debug)
                                                        LOG_INFOF(" D=%f F=%f", finaldmg, vlen(force));
+
+                                               /*if (targ == attacker)
+                                               {
+                                                       print("hits ", ftos(hits), " / ", ftos(total));
+                                                       print(" finaldmg ", ftos(finaldmg), " force ", ftos(vlen(force)));
+                                                       print(" (", vtos(force), ") (", ftos(a), ")\n");
+                                               }*/
                                        }
 
-                                       //if (targ == attacker)
-                                       //{
-                                       //      print("hits ", ftos(hits), " / ", ftos(total));
-                                       //      print(" finaldmg ", ftos(finaldmg), " force ", vtos(force));
-                                       //      print(" (", ftos(a), ")\n");
-                                       //}
                                        if(finaldmg || force)
                                        {
                                                if(targ.iscreature)
@@ -1052,14 +1101,14 @@ float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector in
        RadiusDamage_running = 0;
 
        if(!DEATH_ISSPECIAL(deathtype))
-               accuracy_add(attacker, DEATH_WEAPONOF(deathtype), 0, min(coredamage, stat_damagedone));
+               accuracy_add(attacker, DEATH_WEAPONOF(deathtype), 0, min(max(coredamage, edgedamage), stat_damagedone));
 
        return total_damage_to_creatures;
 }
 
 float RadiusDamage(entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype, .entity weaponentity, entity directhitentity)
 {
-       return RadiusDamageForSource(inflictor, (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5), inflictor.velocity, attacker, coredamage, edgedamage, rad, 
+       return RadiusDamageForSource(inflictor, (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5), inflictor.velocity, attacker, coredamage, edgedamage, rad,
                                                                        cantbe, mustbe, false, forceintensity, 1, deathtype, weaponentity, directhitentity);
 }