]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/monsters/sv_monsters.qc
Purge self from the damage/death mutator hooks
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / monsters / sv_monsters.qc
index e95e3d1dea3ed0fddda349db2c98dd692478eb78..f641d7944fce06f77fee7f12bd296853274397c5 100644 (file)
@@ -31,7 +31,7 @@ void monsters_setstatus(entity this)
        this.stat_monsters_killed = monsters_killed;
 }
 
-void monster_dropitem(entity this)
+void monster_dropitem(entity this, entity attacker)
 {
        if(!this.candrop || !this.monster_loot)
                return;
@@ -42,13 +42,13 @@ void monster_dropitem(entity this)
 
        e.monster_loot = this.monster_loot;
 
-       MUTATOR_CALLHOOK(MonsterDropItem, e);
-       e = other;
+       MUTATOR_CALLHOOK(MonsterDropItem, this, e, attacker);
+       e = M_ARGV(1, entity);
 
        if(e && e.monster_loot)
        {
                e.noalign = true;
-               WITH(entity, self, e, e.monster_loot(e));
+               WITHSELF(e, e.monster_loot(e));
                e.gravity = 1;
                e.movetype = MOVETYPE_TOSS;
                e.reset = SUB_Remove;
@@ -90,7 +90,7 @@ bool Monster_ValidTarget(entity this, entity targ)
        || (!IS_VEHICLE(targ) && (IS_DEAD(targ) || IS_DEAD(this) || targ.health <= 0 || this.health <= 0))
        || (this.monster_follow == targ || targ.monster_follow == this)
        || (!IS_VEHICLE(targ) && (targ.flags & FL_NOTARGET))
-       || (!autocvar_g_monsters_typefrag && targ.BUTTON_CHAT)
+       || (!autocvar_g_monsters_typefrag && PHYS_INPUT_BUTTON_CHAT(targ))
        || (SAME_TEAM(targ, this))
        || (STAT(FROZEN, targ))
        || (targ.alpha != 0 && targ.alpha < 0.5)
@@ -138,7 +138,7 @@ entity Monster_FindTarget(entity mon)
                        if(closest_target)
                        {
                                vector closest_target_center = CENTER_OR_VIEWOFS(closest_target);
-                               if(vlen(ent_center - head_center) < vlen(ent_center - closest_target_center))
+                               if(vlen2(ent_center - head_center) < vlen2(ent_center - closest_target_center))
                                        { closest_target = head; }
                        }
                        else { closest_target = head; }
@@ -191,7 +191,6 @@ void monster_changeteam(entity ent, float newteam)
 }
 
 .void(entity) monster_delayedfunc;
-void Monster_Delay_Action_self();
 void Monster_Delay_Action(entity this)
 {
        if(Monster_ValidTarget(this.owner, this.owner.enemy)) { this.monster_delayedfunc(this.owner); }
@@ -199,27 +198,22 @@ void Monster_Delay_Action(entity this)
        if(this.cnt > 1)
        {
                this.cnt -= 1;
-               this.think = Monster_Delay_Action_self;
+               setthink(this, Monster_Delay_Action);
                this.nextthink = time + this.count;
        }
        else
        {
-               this.think = SUB_Remove_self;
+               setthink(this, SUB_Remove);
                this.nextthink = time;
        }
 }
 
-void Monster_Delay_Action_self()
-{
-       Monster_Delay_Action(self);
-}
-
 void Monster_Delay(entity this, int repeat_count, float defer_amnt, void(entity) func)
 {
        // deferred attacking, checks if monster is still alive and target is still valid before attacking
        entity e = spawn();
 
-       e.think = Monster_Delay_Action_self;
+       setthink(e, Monster_Delay_Action);
        e.nextthink = time + defer_amnt;
        e.count = defer_amnt;
        e.owner = this;
@@ -400,7 +394,7 @@ bool Monster_Attack_Leap_Check(entity this, vector vel)
        return true;
 }
 
-bool Monster_Attack_Leap(entity this, vector anm, void() touchfunc, vector vel, float animtime)
+bool Monster_Attack_Leap(entity this, vector anm, void(entity this) touchfunc, vector vel, float animtime)
 {
        if(!Monster_Attack_Leap_Check(this, vel))
                return false;
@@ -414,7 +408,7 @@ bool Monster_Attack_Leap(entity this, vector anm, void() touchfunc, vector vel,
 
        if(this.flags & FL_MONSTER)
                this.state = MONSTER_ATTACK_RANGED;
-       this.touch = touchfunc;
+       settouch(this, touchfunc);
        this.origin_z += 1;
        this.velocity = vel;
        UNSET_ONGROUND(this);
@@ -429,9 +423,7 @@ void Monster_Attack_Check(entity this, entity targ)
        || (time < this.attack_finished_single[0])
        ) { return; }
 
-       float targ_vlen = vlen(targ.origin - this.origin);
-
-       if(targ_vlen <= this.attack_range)
+       if(vdist(targ.origin - this.origin, <=, this.attack_range))
        {
                bool attack_success = this.monster_attackfunc(MONSTER_ATTACK_MELEE, this, targ);
                if(attack_success == 1)
@@ -440,7 +432,7 @@ void Monster_Attack_Check(entity this, entity targ)
                        return;
        }
 
-       if(targ_vlen > this.attack_range)
+       if(vdist(targ.origin - this.origin, >, this.attack_range))
        {
                float attack_success = this.monster_attackfunc(MONSTER_ATTACK_RANGED, this, targ);
                if(attack_success == 1)
@@ -474,15 +466,15 @@ void Monster_UpdateModel(entity this)
        mon.mr_anim(mon, this);
 }
 
-void Monster_Touch()
-{SELFPARAM();
+void Monster_Touch(entity this)
+{
        if(other == world) { return; }
 
        if(other.monster_attack)
-       if(self.enemy != other)
+       if(this.enemy != other)
        if(!IS_MONSTER(other))
-       if(Monster_ValidTarget(self, other))
-               self.enemy = other;
+       if(Monster_ValidTarget(this, other))
+               this.enemy = other;
 }
 
 void Monster_Miniboss_Check(entity this)
@@ -517,14 +509,14 @@ bool Monster_Respawn_Check(entity this)
        return true;
 }
 
-void Monster_Respawn() { SELFPARAM(); Monster_Spawn(self, self.monsterid); }
+void Monster_Respawn(entity this) { Monster_Spawn(this, this.monsterid); }
 
 void Monster_Dead_Fade(entity this)
 {
        if(Monster_Respawn_Check(this))
        {
                this.spawnflags |= MONSTERFLAG_RESPAWNED;
-               this.think = Monster_Respawn;
+               setthink(this, Monster_Respawn);
                this.nextthink = time + this.respawntime;
                this.monster_lifetime = 0;
                this.deadflag = DEAD_RESPAWNING;
@@ -549,9 +541,9 @@ void Monster_Dead_Fade(entity this)
        }
 }
 
-void Monster_Use()
-{SELFPARAM();
-       if(Monster_ValidTarget(self, activator)) { self.enemy = activator; }
+void Monster_Use(entity this, entity actor, entity trigger)
+{
+       if(Monster_ValidTarget(this, actor)) { this.enemy = actor; }
 }
 
 vector Monster_Move_Target(entity this, entity targ)
@@ -569,7 +561,7 @@ vector Monster_Move_Target(entity this, entity targ)
                        || (this.enemy.flags & FL_NOTARGET)
                        || (this.enemy.alpha < 0.5 && this.enemy.alpha != 0)
                        || (this.enemy.takedamage == DAMAGE_NO)
-                       || (vlen(this.origin - targ_origin) > this.target_range)
+                       || (vdist(this.origin - targ_origin, >, this.target_range))
                        || ((trace_fraction < 1) && (trace_ent != this.enemy)))
                {
                        this.enemy = world;
@@ -741,7 +733,7 @@ void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed)
                        Unfreeze(this);
                        this.health = 0;
                        if(this.event_damage)
-                               this.event_damage(this, this.frozen_by, 1, DEATH_NADE_ICE_FREEZE.m_id, this.origin, '0 0 0');
+                               this.event_damage(this, this, this.frozen_by, 1, DEATH_NADE_ICE_FREEZE.m_id, this.origin, '0 0 0');
                }
 
                else if ( this.revive_progress <= 0 )
@@ -836,7 +828,7 @@ void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed)
        if(this.state == MONSTER_ATTACK_RANGED && IS_ONGROUND(this))
        {
                this.state = 0;
-               this.touch = Monster_Touch;
+               settouch(this, Monster_Touch);
        }
 
        if(this.state && time >= this.attack_finished_single[0])
@@ -858,7 +850,7 @@ void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed)
        if(!(this.spawnflags & MONSTERFLAG_FLY_VERTICAL) && !(this.flags & FL_SWIM))
                this.moveto_z = this.origin_z;
 
-       if(vlen(this.origin - this.moveto) > 100)
+       if(vdist(this.origin - this.moveto, >, 100))
        {
                float do_run = (this.enemy || this.monster_moveto);
                if(IS_ONGROUND(this) || ((this.flags & FL_FLY) || (this.flags & FL_SWIM)))
@@ -867,7 +859,7 @@ void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed)
                if(time > this.pain_finished) // TODO: use anim_finished instead!
                if(!this.state)
                if(time > this.anim_finished)
-               if(vlen(this.velocity) > 10)
+               if(vdist(this.velocity, >, 10))
                        setanim(this, ((do_run) ? this.anim_run : this.anim_walk), true, false, false);
                else
                        setanim(this, this.anim_idle, true, false, false);
@@ -884,7 +876,7 @@ void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed)
                if(time > this.anim_finished)
                if(time > this.pain_finished)
                if(!this.state)
-               if(vlen(this.velocity) <= 30)
+               if(vdist(this.velocity, <=, 30))
                        setanim(this, this.anim_idle, true, false, false);
        }
 
@@ -905,6 +897,9 @@ void Monster_Move(entity this, float runspeed, float walkspeed, float stpspeed)
 
 void Monster_Remove(entity this)
 {
+       if(IS_CLIENT(this))
+               return; // don't remove it?
+
        .entity weaponentity = weaponentities[0];
        if(!this) { return; }
 
@@ -917,23 +912,23 @@ void Monster_Remove(entity this)
        remove(this);
 }
 
-void Monster_Dead_Think()
-{SELFPARAM();
-       self.nextthink = time + self.ticrate;
+void Monster_Dead_Think(entity this)
+{
+       this.nextthink = time + this.ticrate;
 
-       if(self.monster_lifetime != 0)
-       if(time >= self.monster_lifetime)
+       if(this.monster_lifetime != 0)
+       if(time >= this.monster_lifetime)
        {
-               Monster_Dead_Fade(self);
+               Monster_Dead_Fade(this);
                return;
        }
 }
 
-void Monster_Appear()
-{SELFPARAM();
-       self.enemy = activator;
-       self.spawnflags &= ~MONSTERFLAG_APPEAR; // otherwise, we get an endless loop
-       Monster_Spawn(self, self.monsterid);
+void Monster_Appear(entity this, entity actor, entity trigger)
+{
+       this.enemy = actor;
+       this.spawnflags &= ~MONSTERFLAG_APPEAR; // otherwise, we get an endless loop
+       Monster_Spawn(this, this.monsterid);
 }
 
 bool Monster_Appear_Check(entity this, int monster_id)
@@ -941,7 +936,7 @@ bool Monster_Appear_Check(entity this, int monster_id)
        if(!(this.spawnflags & MONSTERFLAG_APPEAR))
                return false;
 
-       this.think = func_null;
+       setthink(this, func_null);
        this.monsterid = monster_id; // set so this monster is properly registered (otherwise, normal initialization is used)
        this.nextthink = 0;
        this.use = Monster_Appear;
@@ -965,28 +960,28 @@ void Monster_Reset(entity this)
        this.moveto = this.origin;
 }
 
-void Monster_Dead_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{SELFPARAM();
-       self.health -= damage;
+void Monster_Dead_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+{
+       this.health -= damage;
 
-       Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);
+       Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, this, attacker);
 
-       if(self.health <= -100) // 100 health until gone?
+       if(this.health <= -50) // 100 health until gone?
        {
-               Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);
+               Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, this, attacker);
 
                // number of monsters spawned with mobspawn command
                totalspawned -= 1;
 
-               self.think = SUB_Remove_self;
-               self.nextthink = time + 0.1;
-               self.event_damage = func_null;
+               setthink(this, SUB_Remove);
+               this.nextthink = time + 0.1;
+               this.event_damage = func_null;
        }
 }
 
 void Monster_Dead(entity this, entity attacker, float gibbed)
 {
-       this.think = Monster_Dead_Think;
+       setthink(this, Monster_Dead_Think);
        this.nextthink = time;
        this.monster_lifetime = time + 5;
 
@@ -996,7 +991,7 @@ void Monster_Dead(entity this, entity attacker, float gibbed)
                this.health = 0; // reset by Unfreeze
        }
 
-       monster_dropitem(this);
+       monster_dropitem(this, attacker);
 
        Monster_Sound(this, monstersound_death, 0, false, CH_VOICE);
 
@@ -1020,7 +1015,7 @@ void Monster_Dead(entity this, entity attacker, float gibbed)
        this.enemy                      = world;
        this.movetype           = MOVETYPE_TOSS;
        this.moveto                     = this.origin;
-       this.touch                      = Monster_Touch; // reset incase monster was pouncing
+       settouch(this, Monster_Touch); // reset incase monster was pouncing
        this.reset                      = func_null;
        this.state                      = 0;
        this.attack_finished_single[0] = 0;
@@ -1038,86 +1033,79 @@ void Monster_Dead(entity this, entity attacker, float gibbed)
                W_ThrowNewWeapon(this, this.weapon, 0, this.origin, randomvec() * 150 + '0 0 325');
 }
 
-void Monster_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
-{SELFPARAM();
-       if((self.spawnflags & MONSTERFLAG_INVINCIBLE) && deathtype != DEATH_KILL.m_id && !ITEM_DAMAGE_NEEDKILL(deathtype))
+void Monster_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
+{
+       if((this.spawnflags & MONSTERFLAG_INVINCIBLE) && deathtype != DEATH_KILL.m_id && !ITEM_DAMAGE_NEEDKILL(deathtype))
                return;
 
-       if(STAT(FROZEN, self) && deathtype != DEATH_KILL.m_id && deathtype != DEATH_NADE_ICE_FREEZE.m_id)
+       if(STAT(FROZEN, this) && deathtype != DEATH_KILL.m_id && deathtype != DEATH_NADE_ICE_FREEZE.m_id)
                return;
 
-       //if(time < self.pain_finished && deathtype != DEATH_KILL.m_id)
+       //if(time < this.pain_finished && deathtype != DEATH_KILL.m_id)
                //return;
 
-       if(time < self.spawnshieldtime && deathtype != DEATH_KILL.m_id)
+       if(time < this.spawnshieldtime && deathtype != DEATH_KILL.m_id)
                return;
 
-       if(deathtype == DEATH_FALL.m_id && self.draggedby != world)
+       if(deathtype == DEATH_FALL.m_id && this.draggedby != world)
                return;
 
        vector v;
        float take, save;
 
-       v = healtharmor_applydamage(100, self.armorvalue / 100, deathtype, damage);
+       v = healtharmor_applydamage(100, this.armorvalue / 100, deathtype, damage);
        take = v_x;
        save = v_y;
 
-       damage_take = take;
-       frag_attacker = attacker;
-       frag_deathtype = deathtype;
-       Monster mon = get_monsterinfo(self.monsterid);
-       mon.mr_pain(mon, self);
-       take = damage_take;
+       Monster mon = get_monsterinfo(this.monsterid);
+       take = mon.mr_pain(mon, this, take, attacker, deathtype);
 
        if(take)
        {
-               self.health -= take;
-               Monster_Sound(self, monstersound_pain, 1.2, true, CH_PAIN);
+               this.health -= take;
+               Monster_Sound(this, monstersound_pain, 1.2, true, CH_PAIN);
        }
 
-       if(self.sprite)
-               WaypointSprite_UpdateHealth(self.sprite, self.health);
+       if(this.sprite)
+               WaypointSprite_UpdateHealth(this.sprite, this.health);
 
-       self.dmg_time = time;
+       this.dmg_time = time;
 
        if(sound_allowed(MSG_BROADCAST, attacker) && deathtype != DEATH_DROWN.m_id)
-               spamsound (self, CH_PAIN, SND(BODYIMPACT1), VOL_BASE, ATTEN_NORM);  // FIXME: PLACEHOLDER
+               spamsound (this, CH_PAIN, SND(BODYIMPACT1), VOL_BASE, ATTEN_NORM);  // FIXME: PLACEHOLDER
 
-       self.velocity += force * self.damageforcescale;
+       this.velocity += force * this.damageforcescale;
 
        if(deathtype != DEATH_DROWN.m_id && take)
        {
-               Violence_GibSplash_At(hitloc, force, 2, bound(0, take, 200) / 16, self, attacker);
+               Violence_GibSplash_At(hitloc, force, 2, bound(0, take, 200) / 16, this, attacker);
                if (take > 50)
-                       Violence_GibSplash_At(hitloc, force * -0.1, 3, 1, self, attacker);
+                       Violence_GibSplash_At(hitloc, force * -0.1, 3, 1, this, attacker);
                if (take > 100)
-                       Violence_GibSplash_At(hitloc, force * -0.2, 3, 1, self, attacker);
+                       Violence_GibSplash_At(hitloc, force * -0.2, 3, 1, this, attacker);
        }
 
-       if(self.health <= 0)
+       if(this.health <= 0)
        {
                if(deathtype == DEATH_KILL.m_id)
-                       self.candrop = false; // killed by mobkill command
+                       this.candrop = false; // killed by mobkill command
 
                // TODO: fix this?
-               activator = attacker;
-               other = self.enemy;
-               SUB_UseTargets();
-               self.target2 = self.oldtarget2; // reset to original target on death, incase we respawn
+               SUB_UseTargets(this, attacker, this.enemy);
+               this.target2 = this.oldtarget2; // reset to original target on death, incase we respawn
 
-               Monster_Dead(self, attacker, (self.health <= -100 || deathtype == DEATH_KILL.m_id));
+               Monster_Dead(this, attacker, (this.health <= -100 || deathtype == DEATH_KILL.m_id));
 
-               WaypointSprite_Kill(self.sprite);
+               WaypointSprite_Kill(this.sprite);
 
-               frag_target = self;
-               MUTATOR_CALLHOOK(MonsterDies, attacker);
+               MUTATOR_CALLHOOK(MonsterDies, this, attacker, deathtype);
 
-               if(self.health <= -100 || deathtype == DEATH_KILL.m_id) // check if we're already gibbed
+               if(this.health <= -100 || deathtype == DEATH_KILL.m_id) // check if we're already gibbed
                {
-                       Violence_GibSplash(self, 1, 0.5, attacker);
+                       Violence_GibSplash(this, 1, 0.5, attacker);
 
-                       self.think = SUB_Remove_self;
-                       self.nextthink = time + 0.1;
+                       setthink(this, SUB_Remove);
+                       this.nextthink = time + 0.1;
                }
        }
 }
@@ -1172,7 +1160,7 @@ void Monster_Move_2D(entity this, float mspeed, bool allow_jumpoff)
 
        if(time > this.pain_finished)
        if(time > this.attack_finished_single[0])
-       if(vlen(this.velocity) > 10)
+       if(vdist(this.velocity, >, 10))
                setanim(this, this.anim_walk, true, false, false);
        else
                setanim(this, this.anim_idle, true, false, false);
@@ -1215,25 +1203,25 @@ void Monster_Anim(entity this)
        */
 }
 
-void Monster_Think()
-{SELFPARAM();
-       self.think = Monster_Think;
-       self.nextthink = self.ticrate;
+void Monster_Think(entity this)
+{
+       setthink(this, Monster_Think);
+       this.nextthink = this.ticrate;
 
-       if(self.monster_lifetime)
-       if(time >= self.monster_lifetime)
+       if(this.monster_lifetime)
+       if(time >= this.monster_lifetime)
        {
-               Damage(self, self, self, self.health + self.max_health, DEATH_KILL.m_id, self.origin, self.origin);
+               Damage(this, this, this, this.health + this.max_health, DEATH_KILL.m_id, this.origin, this.origin);
                return;
        }
 
-       Monster mon = get_monsterinfo(self.monsterid);
-       if(mon.mr_think(mon, self))
-               Monster_Move(self, self.speed2, self.speed, self.stopspeed);
+       Monster mon = get_monsterinfo(this.monsterid);
+       if(mon.mr_think(mon, this))
+               Monster_Move(this, this.speed2, this.speed, this.stopspeed);
 
-       Monster_Anim(self);
+       Monster_Anim(this);
 
-       CSQCMODEL_AUTOUPDATE(self);
+       CSQCMODEL_AUTOUPDATE(this);
 }
 
 bool Monster_Spawn_Setup(entity this)
@@ -1288,7 +1276,7 @@ bool Monster_Spawn_Setup(entity this)
                }
        }
 
-       this.think = Monster_Think;
+       setthink(this, Monster_Think);
        this.nextthink = time + this.ticrate;
 
        if(MUTATOR_CALLHOOK(MonsterSpawn, this))
@@ -1332,7 +1320,7 @@ bool Monster_Spawn(entity this, int mon_id)
        this.damagedbycontents  = true;
        this.monsterid                  = mon_id;
        this.event_damage               = Monster_Damage;
-       this.touch                              = Monster_Touch;
+       settouch(this, Monster_Touch);
        this.use                                = Monster_Use;
        this.solid                              = SOLID_BBOX;
        this.movetype                   = MOVETYPE_WALK;
@@ -1364,6 +1352,9 @@ bool Monster_Spawn(entity this, int mon_id)
        if(autocvar_g_nodepthtestplayers) { this.effects |= EF_NODEPTHTEST; }
        if(mon.spawnflags & MONSTER_TYPE_SWIM) { this.flags |= FL_SWIM; }
 
+       if(autocvar_g_playerclip_collisions)
+               this.dphitcontentsmask |= DPCONTENTS_PLAYERCLIP;
+
        if(mon.spawnflags & MONSTER_TYPE_FLY)
        {
                this.flags |= FL_FLY;