]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/mutators/mutator_buffs.qc
Fix some cases of division by 0
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / mutator_buffs.qc
index 09b50442b423eb21244d22bc6a3d5faa3701360f..bafa28c9c88dbc86cfbf24718ea4e8be018eb66a 100644 (file)
@@ -1,10 +1,16 @@
 float buffs_BuffModel_Customize()
 {
-       float same_team = (SAME_TEAM(other, self.owner) || (IS_SPEC(other) && SAME_TEAM(other.enemy, self.owner)));
-       if(self.owner.alpha <= 0.5 && !same_team && self.owner.alpha != 0)
+       entity player, myowner;
+       float same_team;
+
+       player = WaypointSprite_getviewentity(other);
+       myowner = self.owner;
+       same_team = (SAME_TEAM(player, myowner) || SAME_TEAM(player, myowner));
+
+       if(myowner.alpha <= 0.5 && !same_team && myowner.alpha != 0)
                return FALSE;
-               
-       if(other == self.owner || (IS_SPEC(other) && other.enemy == self.owner))
+
+       if(player == myowner || (IS_SPEC(other) && other.enemy == myowner))
        {
                // somewhat hide the model, but keep the glow
                self.effects = 0;
@@ -23,7 +29,7 @@ float buff_Waypoint_visible_for_player(entity plr)
 {
     if(!self.owner.buff_active && !self.owner.buff_activetime)
         return FALSE;
-               
+
        if(plr.buffs)
        {
                if(plr.cvar_cl_buffs_autoreplace)
@@ -40,7 +46,7 @@ float buff_Waypoint_visible_for_player(entity plr)
 
 void buff_Waypoint_Spawn(entity e)
 {
-    WaypointSprite_Spawn(Buff_PrettyName(e.buffs), 0, autocvar_g_buffs_waypoint_distance, e, '0 0 1' * e.maxs_z, world, e.team, e, buff_waypoint, TRUE, RADARICON_POWERUP, e.glowmod);
+    WaypointSprite_Spawn(Buff_Sprite(e.buffs), 0, autocvar_g_buffs_waypoint_distance, e, '0 0 1' * e.maxs_z, world, e.team, e, buff_waypoint, TRUE, RADARICON_POWERUP, e.glowmod);
     WaypointSprite_UpdateTeamRadar(e.buff_waypoint, RADARICON_POWERUP, e.glowmod);
     e.buff_waypoint.waypointsprite_visible_for_player = buff_Waypoint_visible_for_player;
 }
@@ -66,10 +72,16 @@ void buff_Respawn(entity ent)
        if(!MoveToRandomMapLocation(ent, DPCONTENTS_SOLID | DPCONTENTS_CORPSE | DPCONTENTS_PLAYERCLIP, DPCONTENTS_SLIME | DPCONTENTS_LAVA | DPCONTENTS_SKY | DPCONTENTS_BODY | DPCONTENTS_DONOTENTER, Q3SURFACEFLAG_SKY, ((autocvar_g_buffs_random_location_attempts > 0) ? autocvar_g_buffs_random_location_attempts : 10), 1024, 256))
        {
                entity spot = SelectSpawnPoint(TRUE);
-               setorigin(self, (spot.origin + '0 0 200') + (randomvec() * 300));
-               self.angles = spot.angles;
+               setorigin(ent, ((spot.origin + '0 0 200') + (randomvec() * 300)));
+               ent.angles = spot.angles;
        }
        
+       tracebox(ent.origin, ent.mins * 1.5, self.maxs * 1.5, ent.origin, MOVE_NOMONSTERS, ent);
+       
+       setorigin(ent, trace_endpos); // attempt to unstick
+       
+       ent.movetype = MOVETYPE_TOSS;
+       
        makevectors(ent.angles);
        ent.velocity = '0 0 200';
        ent.angles = '0 0 0';
@@ -288,6 +300,9 @@ void buff_Init(entity ent)
        buff_SetCooldown(autocvar_g_buffs_cooldown_activate + game_starttime);
        self.buff_active = !self.buff_activetime;
        self.pflags = PFLAGS_FULLDYNAMIC;
+       
+       if(self.noalign)
+               self.movetype = MOVETYPE_NONE; // reset by random location
 
        setmodel(self, "models/relics/relic.md3");
        setsize(self, BUFF_MIN, BUFF_MAX);
@@ -334,6 +349,15 @@ MUTATOR_HOOKFUNCTION(buffs_PlayerDamage_SplitHealthArmor)
        return FALSE;
 }
 
+void buff_Vengeance_DelayedDamage()
+{
+       if(self.enemy)
+               Damage(self.enemy, self.owner, self.owner, self.dmg, DEATH_BUFF_VENGEANCE, self.enemy.origin, '0 0 0');
+       
+       remove(self);
+       return;
+}
+
 MUTATOR_HOOKFUNCTION(buffs_PlayerDamage_Calculate)
 {
        if(frag_deathtype == DEATH_BUFF_VENGEANCE) { return FALSE; } // oh no you don't
@@ -347,6 +371,7 @@ MUTATOR_HOOKFUNCTION(buffs_PlayerDamage_Calculate)
        if(!ITEM_DAMAGE_NEEDKILL(frag_deathtype))
        if(frag_attacker)
        if(random() <= autocvar_g_buffs_medic_survive_chance)
+       if(frag_target.health - autocvar_g_buffs_medic_survive_health > 0) // not if the final result would be less than 0, medic must get health
                frag_damage = frag_target.health - autocvar_g_buffs_medic_survive_health;
                
        if(frag_target.buffs & BUFF_VENGEANCE)
@@ -354,9 +379,13 @@ MUTATOR_HOOKFUNCTION(buffs_PlayerDamage_Calculate)
        if(frag_attacker != frag_target)
        if(!ITEM_DAMAGE_NEEDKILL(frag_deathtype))
        {
-               vector v = healtharmor_applydamage(frag_attacker.armorvalue, autocvar_g_balance_armor_blockpercent, DEATH_BUFF_VENGEANCE, frag_damage * autocvar_g_buffs_vengeance_damage_multiplier);
-               float take = v_x;
-               Damage(frag_attacker, frag_target, frag_target, take, DEATH_BUFF_VENGEANCE, frag_attacker.origin, '0 0 0');
+               entity dmgent = spawn();
+
+               dmgent.dmg = frag_damage * autocvar_g_buffs_vengeance_damage_multiplier;
+               dmgent.enemy = frag_attacker;
+               dmgent.owner = frag_target;
+               dmgent.think = buff_Vengeance_DelayedDamage;
+               dmgent.nextthink = time + 0.1;
        }
 
        if(frag_target.buffs & BUFF_BASH)
@@ -427,7 +456,7 @@ MUTATOR_HOOKFUNCTION(buffs_PlayerPhysics)
 MUTATOR_HOOKFUNCTION(buffs_PlayerJump)
 {
        if(self.buffs & BUFF_JUMP)
-               player_jumpheight = autocvar_g_buffs_jump_height;
+               player_jumpheight = max(autocvar_g_buffs_jump_height, player_jumpheight);
 
        return FALSE;
 }
@@ -489,6 +518,19 @@ MUTATOR_HOOKFUNCTION(buffs_RemovePlayer)
        return FALSE;
 }
 
+MUTATOR_HOOKFUNCTION(buffs_CustomizeWaypoint)
+{
+       entity e = WaypointSprite_getviewentity(other);
+
+       // if you have the invisibility powerup, sprites ALWAYS are restricted to your team
+       // but only apply this to real players, not to spectators
+       if((self.owner.flags & FL_CLIENT) && (self.owner.buffs & BUFF_INVISIBLE) && (e == other))
+       if(DIFF_TEAM(self.owner, e))
+               return TRUE;
+
+       return FALSE;
+}
+
 MUTATOR_HOOKFUNCTION(buffs_OnEntityPreSpawn)
 {
        if(autocvar_g_buffs_replace_powerups)
@@ -508,9 +550,11 @@ MUTATOR_HOOKFUNCTION(buffs_OnEntityPreSpawn)
 MUTATOR_HOOKFUNCTION(buffs_WeaponRate)
 {
        if(self.buffs & BUFF_SPEED)
+       if(autocvar_g_buffs_speed_rate > 0)
                weapon_rate *= autocvar_g_buffs_speed_rate;
                
        if(time < self.buff_disability_time)
+       if(autocvar_g_buffs_disability_rate > 0)
                weapon_rate *= autocvar_g_buffs_disability_rate;
        
        return FALSE;
@@ -724,7 +768,7 @@ void buffs_Initialize()
 MUTATOR_DEFINITION(mutator_buffs)
 {
        MUTATOR_HOOK(PlayerDamage_SplitHealthArmor, buffs_PlayerDamage_SplitHealthArmor, CBC_ORDER_ANY);
-       MUTATOR_HOOK(PlayerDamage_Calculate, buffs_PlayerDamage_Calculate, CBC_ORDER_LAST);
+       MUTATOR_HOOK(PlayerDamage_Calculate, buffs_PlayerDamage_Calculate, CBC_ORDER_ANY);
        MUTATOR_HOOK(PlayerSpawn, buffs_PlayerSpawn, CBC_ORDER_ANY);
        MUTATOR_HOOK(PlayerPhysics, buffs_PlayerPhysics, CBC_ORDER_ANY);
        MUTATOR_HOOK(PlayerJump, buffs_PlayerJump, CBC_ORDER_ANY);
@@ -738,6 +782,7 @@ MUTATOR_DEFINITION(mutator_buffs)
        MUTATOR_HOOK(MakePlayerObserver, buffs_RemovePlayer, CBC_ORDER_ANY);
        MUTATOR_HOOK(ClientDisconnect, buffs_RemovePlayer, CBC_ORDER_ANY);
        MUTATOR_HOOK(OnEntityPreSpawn, buffs_OnEntityPreSpawn, CBC_ORDER_ANY);
+       MUTATOR_HOOK(CustomizeWaypoint, buffs_CustomizeWaypoint, CBC_ORDER_ANY);
        MUTATOR_HOOK(WeaponRateFactor, buffs_WeaponRate, CBC_ORDER_ANY);
        MUTATOR_HOOK(PlayerPreThink, buffs_PlayerThink, CBC_ORDER_ANY);
        MUTATOR_HOOK(GetCvars, buffs_GetCvars, CBC_ORDER_ANY);