]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/g_damage.qc
Impulses: migration pathway
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / g_damage.qc
index b5d87eed172cb27eafd02cec6d4af64a6dfd440e..dfabd9d3dc9758b24fbbe9b0a843c581685bfe4c 100644 (file)
@@ -1,65 +1,27 @@
 #include "g_damage.qh"
-#include "_all.qh"
 
+#include "bot/bot.qh"
 #include "g_hook.qh"
-#include "mutators/mutators_include.qh"
+#include "mutators/all.qh"
 #include "scores.qh"
 #include "spawnpoints.qh"
 #include "t_items.qh"
 #include "../common/vehicles/all.qh"
+#include "../common/items/all.qc"
+#include "../common/mutators/mutator/waypoints/waypointsprites.qh"
 #include "weapons/accuracy.qh"
 #include "weapons/csqcprojectile.qh"
 #include "weapons/selection.qh"
-#include "../common/buffs.qh"
 #include "../common/constants.qh"
-#include "../common/deathtypes.qh"
+#include "../common/deathtypes/all.qh"
 #include "../common/notifications.qh"
 #include "../common/movetypes/movetypes.qh"
 #include "../common/playerstats.qh"
 #include "../common/teams.qh"
 #include "../common/util.qh"
 #include "../common/weapons/all.qh"
-#include "../csqcmodellib/sv_model.qh"
-#include "../warpzonelib/common.qh"
-
-float Damage_DamageInfo_SendEntity(entity to, int sf)
-{SELFPARAM();
-       WriteByte(MSG_ENTITY, ENT_CLIENT_DAMAGEINFO);
-       WriteShort(MSG_ENTITY, self.projectiledeathtype);
-       WriteCoord(MSG_ENTITY, floor(self.origin.x));
-       WriteCoord(MSG_ENTITY, floor(self.origin.y));
-       WriteCoord(MSG_ENTITY, floor(self.origin.z));
-       WriteByte(MSG_ENTITY, bound(1, self.dmg, 255));
-       WriteByte(MSG_ENTITY, bound(0, self.dmg_radius, 255));
-       WriteByte(MSG_ENTITY, bound(1, self.dmg_edge, 255));
-       WriteShort(MSG_ENTITY, self.oldorigin.x);
-       WriteByte(MSG_ENTITY, self.species);
-       return true;
-}
-
-void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad, vector force, int deathtype, float bloodtype, entity dmgowner)
-{
-       // TODO maybe call this from non-edgedamage too?
-       // TODO maybe make the client do the particle effects for the weapons and the impact sounds using this info?
-
-       entity e;
-
-       if(!sound_allowed(MSG_BROADCAST, dmgowner))
-               deathtype |= 0x8000;
-
-       e = spawn();
-       setorigin(e, org);
-       e.projectiledeathtype = deathtype;
-       e.dmg = coredamage;
-       e.dmg_edge = edgedamage;
-       e.dmg_radius = rad;
-       e.dmg_force = vlen(force);
-       e.velocity = force;
-       e.oldorigin_x = compressShortVector(e.velocity);
-       e.species = bloodtype;
-
-       Net_LinkEntity(e, false, 0.2, Damage_DamageInfo_SendEntity);
-}
+#include "../lib/csqcmodel/sv_model.qh"
+#include "../lib/warpzone/common.qh"
 
 void UpdateFrags(entity player, float f)
 {
@@ -98,14 +60,11 @@ void GiveFrags (entity attacker, entity targ, float f, int deathtype)
        if(g_weaponarena_random)
        {
                // 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)
-                       culprit = attacker.weapon;
-               else if(!(attacker.weapons & WepSet_FromWeapon(culprit)))
-                       culprit = attacker.weapon;
-
-               if(g_weaponarena_random_with_blaster && culprit == WEP_BLASTER.m_id) // WEAPONTODO: Shouldn't this be in a mutator?
+               Weapon culprit = DEATH_WEAPONOF(deathtype);
+               if(!culprit) culprit = Weapons_from(attacker.weapon);
+               else if(!(attacker.weapons & (culprit.m_wepset))) culprit = Weapons_from(attacker.weapon);
+
+               if(g_weaponarena_random_with_blaster && culprit == WEP_BLASTER) // WEAPONTODO: Shouldn't this be in a mutator?
                {
                        // no exchange
                }
@@ -113,8 +72,7 @@ void GiveFrags (entity attacker, entity targ, float f, int deathtype)
                {
                        if(!GiveFrags_randomweapons)
                        {
-                               GiveFrags_randomweapons = spawn();
-                               GiveFrags_randomweapons.classname = "GiveFrags_randomweapons";
+                               GiveFrags_randomweapons = new(GiveFrags_randomweapons);
                        }
 
                        if(warmup_stage)
@@ -124,7 +82,7 @@ void GiveFrags (entity attacker, entity targ, float f, int deathtype)
 
                        // all others (including the culprit): remove
                        GiveFrags_randomweapons.weapons &= ~attacker.weapons;
-                       GiveFrags_randomweapons.weapons &= ~WepSet_FromWeapon(culprit);
+                       GiveFrags_randomweapons.weapons &= ~(culprit.m_wepset);
 
                        // among the remaining ones, choose one by random
                        W_RandomWeapons(GiveFrags_randomweapons, 1);
@@ -132,12 +90,12 @@ void GiveFrags (entity attacker, entity targ, float f, int deathtype)
                        if(GiveFrags_randomweapons.weapons)
                        {
                                attacker.weapons |= GiveFrags_randomweapons.weapons;
-                               attacker.weapons &= ~WepSet_FromWeapon(culprit);
+                               attacker.weapons &= ~(culprit.m_wepset);
                        }
                }
 
                // after a frag, choose another random weapon set
-               if (!(attacker.weapons & WepSet_FromWeapon(attacker.weapon)))
+               if (!(attacker.weapons & WepSet_FromWeapon(Weapons_from(attacker.weapon))))
                        W_SwitchWeapon_Force(attacker, w_getbestweapon(attacker));
        }
 
@@ -203,7 +161,7 @@ void Obituary_SpecialDeath(
 {
        if(DEATH_ISSPECIAL(deathtype))
        {
-               entity deathent = deathtypes[(deathtype - DT_FIRST)];
+               entity deathent = Deathtypes_from(deathtype - DT_FIRST);
                if (!deathent) { backtrace("Obituary_SpecialDeath: Could not find deathtype entity!\n"); return; }
 
                if(murder)
@@ -261,11 +219,11 @@ float Obituary_WeaponDeath(
        string s1, string s2, string s3,
        float f1, float f2)
 {
-       float death_weapon = DEATH_WEAPONOF(deathtype);
-       if(death_weapon)
+       Weapon death_weapon = DEATH_WEAPONOF(deathtype);
+       if (death_weapon != WEP_Null)
        {
                w_deathtype = deathtype;
-               int death_message = WEP_ACTION(death_weapon, ((murder) ? WR_KILLMESSAGE : WR_SUICIDEMESSAGE));
+               int death_message = ((murder) ? death_weapon.wr_killmessage(death_weapon) : death_weapon.wr_suicidemessage(death_weapon));
                w_deathtype = false;
 
                if (death_message)
@@ -301,6 +259,8 @@ float Obituary_WeaponDeath(
        return false;
 }
 
+.int buffs = _STAT(BUFFS); // TODO: remove
+
 void Obituary(entity attacker, entity inflictor, entity targ, int deathtype)
 {
        // Sanity check
@@ -335,13 +295,13 @@ void Obituary(entity attacker, entity inflictor, entity targ, int deathtype)
        {
                if(DEATH_ISSPECIAL(deathtype))
                {
-                       if(deathtype == DEATH_TEAMCHANGE || deathtype == DEATH_AUTOTEAMCHANGE)
+                       if(deathtype == DEATH_TEAMCHANGE.m_id || deathtype == DEATH_AUTOTEAMCHANGE.m_id)
                        {
                                Obituary_SpecialDeath(targ, false, deathtype, targ.netname, deathlocation, "", targ.team, 0, 0);
                        }
                        else
                        {
-                               switch(deathtype)
+                               switch(DEATH_ENT(deathtype))
                                {
                                        case DEATH_MIRRORDAMAGE:
                                        {
@@ -472,7 +432,7 @@ void Obituary(entity attacker, entity inflictor, entity targ, int deathtype)
                        }
 
                        float f3 = 0;
-                       if(deathtype == DEATH_BUFF)
+                       if(deathtype == DEATH_BUFF.m_id)
                                f3 = attacker.buffs;
 
                        if (!Obituary_WeaponDeath(targ, true, deathtype, targ.netname, attacker.netname, deathlocation, targ.killcount, kill_count_to_attacker))
@@ -485,7 +445,7 @@ void Obituary(entity attacker, entity inflictor, entity targ, int deathtype)
        // =============
        else
        {
-               switch(deathtype)
+               switch(DEATH_ENT(deathtype))
                {
                        // For now, we're just forcing HURTTRIGGER to behave as "DEATH_VOID" and giving it no special options...
                        // Later on you will only be able to make custom messages using DEATH_CUSTOM,
@@ -560,11 +520,10 @@ void Freeze (entity targ, float freeze_time, float frozen_type, float show_waypo
        targ.revive_progress = ((frozen_type == 3) ? 1 : 0);
        targ.health = ((frozen_type == 3) ? targ_maxhealth : 1);
        targ.revive_speed = freeze_time;
+       self.bot_attack = false;
 
-       entity ice, head;
-       ice = spawn();
+       entity ice = new(ice);
        ice.owner = targ;
-       ice.classname = "ice";
        ice.scale = targ.scale;
        ice.think = Ice_Think;
        ice.nextthink = time;
@@ -580,6 +539,7 @@ void Freeze (entity targ, float freeze_time, float frozen_type, float show_waypo
 
        RemoveGrapplingHook(targ);
 
+       entity head;
        FOR_EACH_PLAYER(head)
        if(head.hook.aiment == targ)
                RemoveGrapplingHook(head);
@@ -591,6 +551,9 @@ void Freeze (entity targ, float freeze_time, float frozen_type, float show_waypo
 
 void Unfreeze (entity targ)
 {
+       if(!targ.frozen)
+               return;
+
        if(targ.frozen && targ.frozen != 3) // only reset health if target was frozen
                targ.health = ((IS_PLAYER(targ)) ? start_health : targ.max_health);
 
@@ -598,6 +561,7 @@ void Unfreeze (entity targ)
        targ.frozen = 0;
        targ.revive_progress = 0;
        targ.revival_time = time;
+       self.bot_attack = true;
 
        WaypointSprite_Kill(targ.waypointsprite_attached);
 
@@ -620,7 +584,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d
        mirrordamage = 0;
        mirrorforce = 0;
 
-       if (gameover || targ.killcount == -666)
+       if (gameover || targ.killcount == FRAGS_SPECTATOR)
                return;
 
        setself(targ);
@@ -636,7 +600,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d
                                        RemoveGrapplingHook(targ); // STOP THAT, you parasite!
 
        // special rule: gravity bomb does not hit team mates (other than for disconnecting the hook)
-       if(DEATH_ISWEAPON(deathtype, WEP_HOOK.m_id) || DEATH_ISWEAPON(deathtype, WEP_TUBA.m_id))
+       if(DEATH_ISWEAPON(deathtype, WEP_HOOK) || DEATH_ISWEAPON(deathtype, WEP_TUBA))
        {
                if(IS_PLAYER(targ))
                        if(SAME_TEAM(targ, attacker))
@@ -646,7 +610,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d
                        }
        }
 
-       if(deathtype == DEATH_KILL || deathtype == DEATH_TEAMCHANGE || deathtype == DEATH_AUTOTEAMCHANGE)
+       if(deathtype == DEATH_KILL.m_id || deathtype == DEATH_TEAMCHANGE.m_id || deathtype == DEATH_AUTOTEAMCHANGE.m_id)
        {
                // exit the vehicle before killing (fixes a crash)
                if(IS_PLAYER(targ) && targ.vehicle)
@@ -661,14 +625,14 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d
                targ.flags -= targ.flags & FL_GODMODE;
                damage = 100000;
        }
-       else if(deathtype == DEATH_MIRRORDAMAGE || deathtype == DEATH_NOAMMO)
+       else if(deathtype == DEATH_MIRRORDAMAGE.m_id || deathtype == DEATH_NOAMMO.m_id)
        {
                // no processing
        }
        else
        {
                // nullify damage if teamplay is on
-               if(deathtype != DEATH_TELEFRAG)
+               if(deathtype != DEATH_TELEFRAG.m_id)
                if(IS_PLAYER(attacker))
                {
                        if(IS_PLAYER(targ) && targ != attacker && (IS_INDEPENDENT_PLAYER(attacker) || IS_INDEPENDENT_PLAYER(targ)))
@@ -740,24 +704,24 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d
                force = frag_force;
 
                if(targ.frozen)
-               if(deathtype != DEATH_HURTTRIGGER && deathtype != DEATH_TEAMCHANGE && deathtype != DEATH_AUTOTEAMCHANGE)
+               if(deathtype != DEATH_HURTTRIGGER.m_id && deathtype != DEATH_TEAMCHANGE.m_id && deathtype != DEATH_AUTOTEAMCHANGE.m_id)
                {
-                       if(autocvar_g_freezetag_revive_falldamage > 0)
-                       if(deathtype == DEATH_FALL)
-                       if(damage >= autocvar_g_freezetag_revive_falldamage)
+                       if(autocvar_g_frozen_revive_falldamage > 0)
+                       if(deathtype == DEATH_FALL.m_id)
+                       if(damage >= autocvar_g_frozen_revive_falldamage)
                        {
                                Unfreeze(targ);
-                               targ.health = autocvar_g_freezetag_revive_falldamage_health;
+                               targ.health = autocvar_g_frozen_revive_falldamage_health;
                                Send_Effect(EFFECT_ICEORGLASS, targ.origin, '0 0 0', 3);
                                Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_FREEZETAG_REVIVED_FALL, targ.netname);
                                Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_FREEZETAG_REVIVE_SELF);
                        }
 
                        damage = 0;
-                       force *= autocvar_g_freezetag_frozen_force;
+                       force *= autocvar_g_frozen_force;
                }
 
-               if(targ.frozen && deathtype == DEATH_HURTTRIGGER && !autocvar_g_freezetag_frozen_damage_trigger)
+               if(targ.frozen && deathtype == DEATH_HURTTRIGGER.m_id && !autocvar_g_frozen_damage_trigger)
                {
                        Send_Effect(EFFECT_TELEPORT, targ.origin, '0 0 0', 1);
 
@@ -822,7 +786,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d
                // count the damage
                if(attacker)
                if(!targ.deadflag)
-               if(deathtype != DEATH_BUFF)
+               if(deathtype != DEATH_BUFF.m_id)
                if(targ.takedamage == DAMAGE_AIM)
                if(targ != attacker)
                {
@@ -838,7 +802,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d
                                {
                                        if(damage > 0)
                                        {
-                                               if(deathtype != DEATH_FIRE)
+                                               if(deathtype != DEATH_FIRE.m_id)
                                                {
                                                        if(victim.BUTTON_CHAT)
                                                                attacker.typehitsound += 1;
@@ -859,7 +823,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d
                                }
                                else
                                {
-                                       if(deathtype != DEATH_FIRE)
+                                       if(deathtype != DEATH_FIRE.m_id)
                                        {
                                                attacker.typehitsound += 1;
                                        }
@@ -883,9 +847,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d
                vector farce = damage_explosion_calcpush(self.damageforcescale * force, self.velocity, autocvar_g_balance_damagepush_speedfactor);
                if(self.movetype == MOVETYPE_PHYSICS)
                {
-                       entity farcent;
-                       farcent = spawn();
-                       farcent.classname = "farce";
+                       entity farcent = new(farce);
                        farcent.enemy = self;
                        farcent.movedir = farce * 10;
                        if(self.mass)
@@ -893,7 +855,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d
                        farcent.origin = hitloc;
                        farcent.forcetype = FORCETYPE_FORCEATPOS;
                        farcent.nextthink = time + 0.1;
-                       farcent.think = SUB_Remove;
+                       farcent.think = SUB_Remove_self;
                }
                else
                {
@@ -916,7 +878,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d
                attacker = attacker_save;
 
                force = normalize(attacker.origin + attacker.view_ofs - hitloc) * mirrorforce;
-               Damage(attacker, inflictor, attacker, mirrordamage, DEATH_MIRRORDAMAGE, attacker.origin, force);
+               Damage(attacker, inflictor, attacker, mirrordamage, DEATH_MIRRORDAMAGE.m_id, attacker.origin, force);
        }
 }
 
@@ -946,7 +908,7 @@ float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector in
        total_damage_to_creatures = 0;
 
        if(deathtype != (WEP_HOOK.m_id | HITTYPE_SECONDARY | HITTYPE_BOUNCE)) // only send gravity bomb damage once
-               if(DEATH_WEAPONOF(deathtype) != WEP_TUBA.m_id) // do not send tuba damage (bandwidth hog)
+               if(DEATH_WEAPONOF(deathtype) != WEP_TUBA) // do not send tuba damage (bandwidth hog)
                {
                        force = inflictorvelocity;
                        if(vlen(force) == 0)
@@ -1104,7 +1066,7 @@ 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).m_id, 0, min(coredamage, stat_damagedone));
 
        return total_damage_to_creatures;
 }
@@ -1134,8 +1096,7 @@ float Fire_AddDamage(entity e, entity o, float d, float t, float dt)
                if(!e.fire_burner)
                {
                        // print("adding a fire burner to ", e.classname, "\n");
-                       e.fire_burner = spawn();
-                       e.fire_burner.classname = "fireburner";
+                       e.fire_burner = new(fireburner);
                        e.fire_burner.think = fireburner_think;
                        e.fire_burner.nextthink = time;
                        e.fire_burner.owner = e;
@@ -1220,7 +1181,7 @@ float Fire_AddDamage(entity e, entity o, float d, float t, float dt)
                                }
                        }
                        if(accuracy_isgooddamage(o, e))
-                               accuracy_add(o, DEATH_WEAPONOF(dt), 0, max(0, totaldamage - mindamage));
+                               accuracy_add(o, DEATH_WEAPONOF(dt).m_id, 0, max(0, totaldamage - mindamage));
                        return max(0, totaldamage - mindamage); // can never be negative, but to make sure
                }
                else
@@ -1234,7 +1195,7 @@ float Fire_AddDamage(entity e, entity o, float d, float t, float dt)
                e.fire_owner = o;
                e.fire_hitsound = false;
                if(accuracy_isgooddamage(o, e))
-                       accuracy_add(o, DEATH_WEAPONOF(dt), 0, d);
+                       accuracy_add(o, DEATH_WEAPONOF(dt).m_id, 0, d);
                return d;
        }
 }
@@ -1284,7 +1245,7 @@ void Fire_ApplyDamage(entity e)
                {
                        t = autocvar_g_balance_firetransfer_time * (e.fire_endtime - time);
                        d = autocvar_g_balance_firetransfer_damage * e.fire_damagepersec * t;
-                       Fire_AddDamage(other, o, d, t, DEATH_FIRE);
+                       Fire_AddDamage(other, o, d, t, DEATH_FIRE.m_id);
                }
        }
 }