]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/g_damage.qc
Merge remote branch 'origin/master' into fruitiex/panelhud
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / g_damage.qc
index 9d7a4974070ce200c52ff4f2ad8328eb5ff766cd..2ad648e5d7e429c6efefaeff83f81029a0f9579f 100644 (file)
@@ -102,7 +102,7 @@ void UpdateFrags(entity player, float f)
 
 // NOTE: f=0 means still count as a (positive) kill, but count no frags for it
 void W_SwitchWeapon_Force(entity e, float w);
-void GiveFrags (entity attacker, entity targ, float f)
+void GiveFrags (entity attacker, entity targ, float f, float deathtype)
 {
        float w;
 
@@ -139,19 +139,36 @@ void GiveFrags (entity attacker, entity targ, float f)
        if(targ != attacker) // not for suicides
        if(g_weaponarena_random)
        {
-               // after a frag, choose another random weapon set
-               if(inWarmupStage)
-                       w = warmup_start_weapons;
-               else
-                       w = start_weapons;
+               // after a frag, exchange the current weapon (or the culprit, if detectable) by a new random weapon
+               float culprit;
+               culprit = DEATH_WEAPONOF(deathtype);
+               if(!culprit || !(attacker.weapons & W_WeaponBit(culprit)))
+                       culprit = attacker.weapon;
 
-               attacker.weapons = randombits(w - (w & W_WeaponBit(attacker.weapon)), g_weaponarena_random, TRUE);
-               if(attacker.weapons < 0)
+               if(g_weaponarena_random_with_laser && culprit == WEPBIT_LASER)
+               {
+                       // no exchange
+               }
+               else
                {
-                       // error from randombits: no weapon available
-                       // this means we can just give ALL weapons
-                       attacker.weapons = w;
+                       if(inWarmupStage)
+                               w = warmup_start_weapons;
+                       else
+                               w = start_weapons;
+
+                       // all others (including the culprit): remove
+                       w &~= attacker.weapons;
+
+                       // among the remaining ones, choose one by random
+                       w = randombits(w, 1, FALSE);
+                       if(w)
+                       {
+                               attacker.weapons |= w;
+                               attacker.weapons &~= W_WeaponBit(culprit);
+                       }
                }
+
+               // after a frag, choose another random weapon set
                if not(attacker.weapons & W_WeaponBit(attacker.weapon))
                        W_SwitchWeapon_Force(attacker, w_getbestweapon(attacker));
        }
@@ -301,7 +318,7 @@ void Obituary (entity attacker, entity inflictor, entity targ, float deathtype)
                        if(deathtype != DEATH_TEAMCHANGE && deathtype != DEATH_QUIET)
                        {
                                LogDeath("suicide", deathtype, targ, targ);
-                               GiveFrags(attacker, targ, -1);
+                               GiveFrags(attacker, targ, -1, deathtype);
                        }
 
                        if (targ.killcount > 2)
@@ -325,7 +342,7 @@ void Obituary (entity attacker, entity inflictor, entity targ, float deathtype)
                                else
                                        type = KILL_TEAM_BLUE;
 
-                               GiveFrags(attacker, targ, -1);
+                               GiveFrags(attacker, targ, -1, deathtype);
 
                                Send_CSQC_Centerprint(attacker, s, "", type, MSG_KILL);
 
@@ -379,10 +396,10 @@ void Obituary (entity attacker, entity inflictor, entity targ, float deathtype)
                                {
                                        UpdateFrags(attacker, ctf_score_value("score_kill"));
                                        PlayerScore_Add(attacker, SP_CTF_FCKILLS, 1);
-                                       GiveFrags(attacker, targ, 0); // for logging
+                                       GiveFrags(attacker, targ, 0, deathtype); // for logging
                                }
                                else
-                                       GiveFrags(attacker, targ, 1);
+                                       GiveFrags(attacker, targ, 1, deathtype);
 
                                if (targ.killcount > 2) {
                                        Send_KillNotification(s, ftos(targ.killcount), a, KILL_END_SPREE, MSG_SPREE);
@@ -441,7 +458,7 @@ void Obituary (entity attacker, entity inflictor, entity targ, float deathtype)
                        if(strstrofs(msg, "%", 0) < 0)
                                msg = strcat("%s ", msg);
 
-                       GiveFrags(targ, targ, -1);
+                       GiveFrags(targ, targ, -1, deathtype);
                        if(PlayerScore_Add(targ, SP_SCORE, 0) == -5) {
                                AnnounceTo(targ, "botlike");
                        }
@@ -565,6 +582,28 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float
                                                        else
                                                                damage = autocvar_g_friendlyfire * damage;
                                                        // mirrordamage will be used LATER
+
+                                                       if(autocvar_g_mirrordamage_virtual)
+                                                       {
+                                                               vector v;
+                                                               v = healtharmor_applydamage(attacker.armorvalue, autocvar_g_balance_armor_blockpercent, mirrordamage);
+                                                               attacker.dmg_take += v_x;
+                                                               attacker.dmg_save += v_y;
+                                                               attacker.dmg_inflictor = inflictor;
+                                                               mirrordamage = 0;
+                                                               mirrorforce = 0;
+                                                       }
+
+                                                       if(autocvar_g_friendlyfire_virtual)
+                                                       {
+                                                               vector v;
+                                                               v = healtharmor_applydamage(targ.armorvalue, autocvar_g_balance_armor_blockpercent, damage);
+                                                               targ.dmg_take += v_x;
+                                                               targ.dmg_save += v_y;
+                                                               targ.dmg_inflictor = inflictor;
+                                                               damage = 0;
+                                                               force = '0 0 0';
+                                                       }
                                                }
                                                else
                                                        damage = 0;
@@ -606,12 +645,11 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float
                        if (DEATH_ISWEAPON(deathtype, WEP_LASER))
                        {
                                damage = 0;
+                               mirrordamage = 0;
                                if (targ != attacker)
                                {
                                        if ((targ.health >= 1) && (targ.classname == "player"))
                                                centerprint(attacker, strcat(DAMAGE_CENTERPRINT_SPACER, "Secondary fire inflicts no damage!"));
-                                       damage = 0;
-                                       mirrordamage = 0;
                                        force = '0 0 0';
                                        // keep mirrorforce
                                        attacker = targ;
@@ -841,31 +879,20 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float
        {
                attacker = attacker_save;
                if(g_minstagib)
-                       if(mirrordamage > 0)
+               if(mirrordamage > 0)
+               {
+                       // just lose extra LIVES, don't kill the player for mirror damage
+                       if(attacker.armorvalue > 0)
                        {
-                               // just lose extra LIVES, don't kill the player for mirror damage
-                               if(attacker.armorvalue > 0)
-                               {
-                                       attacker.armorvalue = attacker.armorvalue - 1;
-                                       centerprint(attacker, strcat(DAMAGE_CENTERPRINT_SPACER, "^3Remaining extra lives: ",ftos(attacker.armorvalue)));
-                                       attacker.hitsound += 1;
-                               }
-                               mirrordamage = 0;
+                               attacker.armorvalue = attacker.armorvalue - 1;
+                               centerprint(attacker, strcat(DAMAGE_CENTERPRINT_SPACER, "^3Remaining extra lives: ",ftos(attacker.armorvalue)));
+                               attacker.hitsound += 1;
                        }
-
-               if(autocvar_g_mirrordamage_virtual)
-               {
-                       vector v;
-                       v = healtharmor_applydamage(attacker.armorvalue, autocvar_g_balance_armor_blockpercent, mirrordamage);
-                       attacker.dmg_take += v_x;
-                       attacker.dmg_save += v_y;
-                       attacker.dmg_inflictor = inflictor;
-               }
-               else
-               {
-                       force = normalize(attacker.origin + attacker.view_ofs - hitloc) * mirrorforce;
-                       Damage(attacker, inflictor, attacker, mirrordamage, DEATH_MIRRORDAMAGE, attacker.origin, force);
+                       mirrordamage = 0;
                }
+
+               force = normalize(attacker.origin + attacker.view_ofs - hitloc) * mirrorforce;
+               Damage(attacker, inflictor, attacker, mirrordamage, DEATH_MIRRORDAMAGE, attacker.origin, force);
        }
 }