]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/monsters/sv_monsters.qc
Use STAT(FROZEN, e) instead of e.frozen
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / monsters / sv_monsters.qc
index 73e6d9060ea80d89205d7cbc48de61ee36582632..f0c8c083329865574ee615a60936bf8ec9c70fe8 100644 (file)
@@ -1,29 +1,28 @@
 #if defined(CSQC)
 #elif defined(MENUQC)
 #elif defined(SVQC)
-       #include "../../dpdefs/progsdefs.qh"
-    #include "../../dpdefs/dpextensions.qh"
-    #include "../../warpzonelib/common.qh"
+    #include <lib/warpzone/common.qh>
     #include "../constants.qh"
     #include "../teams.qh"
     #include "../util.qh"
     #include "all.qh"
     #include "sv_monsters.qh"
+       #include "../physics/movelib.qh"
     #include "../weapons/all.qh"
-    #include "../../server/autocvars.qh"
-    #include "../../server/defs.qh"
-    #include "../deathtypes.qh"
-    #include "../../server/mutators/mutators_include.qh"
-       #include "../../server/steerlib.qh"
+    #include <server/autocvars.qh>
+    #include <server/defs.qh>
+    #include "../deathtypes/all.qh"
+    #include <server/mutators/all.qh>
+       #include <server/steerlib.qh>
        #include "../turrets/sv_turrets.qh"
        #include "../turrets/util.qh"
     #include "../vehicles/all.qh"
-    #include "../../server/campaign.qh"
-    #include "../../server/command/common.qh"
-    #include "../../server/command/cmd.qh"
+    #include <server/campaign.qh>
+    #include <server/command/common.qh>
+    #include <server/command/cmd.qh>
        #include "../triggers/triggers.qh"
-    #include "../../csqcmodellib/sv_model.qh"
-    #include "../../server/round_handler.qh"
+    #include <lib/csqcmodel/sv_model.qh>
+    #include <server/round_handler.qh>
 #endif
 
 void monsters_setstatus()
@@ -38,7 +37,8 @@ void monster_dropitem()
                return;
 
        vector org = self.origin + ((self.mins + self.maxs) * 0.5);
-       entity e = spawn();
+       entity e = new(droppedweapon); // use weapon handling to remove it on touch
+       e.spawnfunc_checked = true;
 
        e.monster_loot = self.monster_loot;
 
@@ -49,14 +49,13 @@ void monster_dropitem()
        {
                setself(e);
                e.noalign = true;
-               e.monster_loot();
+               e.monster_loot(e);
                e.gravity = 1;
                e.movetype = MOVETYPE_TOSS;
                e.reset = SUB_Remove;
                setorigin(e, org);
                e.velocity = randomvec() * 175 + '0 0 325';
                e.item_spawnshieldtime = time + 0.7;
-               e.classname = "droppedweapon"; // use weapon handling to remove it on touch
                SUB_SetFade(e, time + autocvar_g_monsters_drop_time, 1);
                setself(this);
        }
@@ -92,12 +91,12 @@ bool Monster_ValidTarget(entity mon, entity player)
        || (player.takedamage == DAMAGE_NO)
        || (player.items & IT_INVISIBILITY)
        || (IS_SPEC(player) || IS_OBSERVER(player)) // don't attack spectators
-       || (!IS_VEHICLE(player) && (player.deadflag != DEAD_NO || mon.deadflag != DEAD_NO || player.health <= 0 || mon.health <= 0))
+       || (!IS_VEHICLE(player) && (IS_DEAD(player) || IS_DEAD(mon) || player.health <= 0 || mon.health <= 0))
        || (mon.monster_follow == player || player.monster_follow == mon)
        || (!IS_VEHICLE(player) && (player.flags & FL_NOTARGET))
        || (!autocvar_g_monsters_typefrag && player.BUTTON_CHAT)
        || (SAME_TEAM(player, mon))
-       || (player.frozen)
+       || (STAT(FROZEN, player))
        || (player.alpha != 0 && player.alpha < 0.5)
        )
        {
@@ -118,7 +117,7 @@ bool Monster_ValidTarget(entity mon, entity player)
                makevectors (mon.angles);
                dot = normalize (player.origin - mon.origin) * v_forward;
 
-               if(dot <= 0.3) { return false; }
+               if(dot <= autocvar_g_monsters_target_infront_range) { return false; }
        }
 
        return true; // this target is valid!
@@ -209,7 +208,7 @@ void Monster_Delay_Action()
        }
        else
        {
-               oldself.think = SUB_Remove;
+               oldself.think = SUB_Remove_self;
                oldself.nextthink = time;
        }
 }
@@ -267,7 +266,7 @@ void Monster_Sound_Precache(string f)
 
 void Monster_Sounds_Precache()
 {SELFPARAM();
-       string m = (get_monsterinfo(self.monsterid)).model;
+       string m = (get_monsterinfo(self.monsterid)).m_model.model_str();
        float globhandle, n, i;
        string f;
 
@@ -348,7 +347,7 @@ void Monster_Sound(.string samplefield, float sound_delay, float delaytoo, float
        if(delaytoo)
        if(time < self.msound_delay)
                return; // too early
-       GlobalSound(self.(samplefield), chan, VOICETYPE_PLAYERSOUND);
+       GlobalSound_string(self, self.(samplefield), chan, VOICETYPE_PLAYERSOUND);
 
        self.msound_delay = time + sound_delay;
 }
@@ -365,9 +364,9 @@ float Monster_Attack_Melee(entity targ, float damg, vector anim, float er, float
        setanim(self, anim, false, true, false);
 
        if(self.animstate_endtime > time && (self.flags & FL_MONSTER))
-               self.attack_finished_single = self.anim_finished = self.animstate_endtime;
+               self.attack_finished_single[0] = self.anim_finished = self.animstate_endtime;
        else
-               self.attack_finished_single = self.anim_finished = time + animtime;
+               self.attack_finished_single[0] = self.anim_finished = time + animtime;
 
        monster_makevectors(targ);
 
@@ -383,11 +382,11 @@ float Monster_Attack_Leap_Check(vector vel)
 {SELFPARAM();
        if(self.state && (self.flags & FL_MONSTER))
                return false; // already attacking
-       if(!(self.flags & FL_ONGROUND))
+       if(!(IS_ONGROUND(self)))
                return false; // not on the ground
        if(self.health <= 0)
                return false; // called when dead?
-       if(time < self.attack_finished_single)
+       if(time < self.attack_finished_single[0])
                return false; // still attacking
 
        vector old = self.velocity;
@@ -409,16 +408,16 @@ bool Monster_Attack_Leap(vector anm, void() touchfunc, vector vel, float animtim
        setanim(self, anm, false, true, false);
 
        if(self.animstate_endtime > time && (self.flags & FL_MONSTER))
-               self.attack_finished_single = self.anim_finished = self.animstate_endtime;
+               self.attack_finished_single[0] = self.anim_finished = self.animstate_endtime;
        else
-               self.attack_finished_single = self.anim_finished = time + animtime;
+               self.attack_finished_single[0] = self.anim_finished = time + animtime;
 
        if(self.flags & FL_MONSTER)
                self.state = MONSTER_ATTACK_RANGED;
        self.touch = touchfunc;
        self.origin_z += 1;
        self.velocity = vel;
-       self.flags &= ~FL_ONGROUND;
+       UNSET_ONGROUND(self);
 
        return true;
 }
@@ -427,14 +426,14 @@ void Monster_Attack_Check(entity e, entity targ)
 {
        if((e == world || targ == world)
        || (!e.monster_attackfunc)
-       || (time < e.attack_finished_single)
+       || (time < e.attack_finished_single[0])
        ) { return; }
 
        float targ_vlen = vlen(targ.origin - e.origin);
 
        if(targ_vlen <= e.attack_range)
        {
-               float attack_success = e.monster_attackfunc(MONSTER_ATTACK_MELEE);
+               float attack_success = e.monster_attackfunc(MONSTER_ATTACK_MELEE, targ);
                if(attack_success == 1)
                        Monster_Sound(monstersound_melee, 0, false, CH_VOICE);
                else if(attack_success > 0)
@@ -443,7 +442,7 @@ void Monster_Attack_Check(entity e, entity targ)
 
        if(targ_vlen > e.attack_range)
        {
-               float attack_success = e.monster_attackfunc(MONSTER_ATTACK_RANGED);
+               float attack_success = e.monster_attackfunc(MONSTER_ATTACK_RANGED, targ);
                if(attack_success == 1)
                        Monster_Sound(monstersound_melee, 0, false, CH_VOICE);
                else if(attack_success > 0)
@@ -471,7 +470,8 @@ void Monster_UpdateModel()
        self.anim_die2   = animfixfps(self, '9 1 0.01', '0 0 0');*/
 
        // then get the real values
-       MON_ACTION(self.monsterid, MR_ANIM);
+       Monster mon = get_monsterinfo(self.monsterid);
+       mon.mr_anim(mon);
 }
 
 void Monster_Touch()
@@ -564,14 +564,13 @@ vector Monster_Move_Target(entity targ)
                WarpZone_TraceLine(self.origin, targ_origin, MOVE_NOMONSTERS, self);
 
                if((self.enemy == world)
-                       || (self.enemy.deadflag != DEAD_NO || self.enemy.health < 1)
-                       || (self.enemy.frozen)
+                       || (IS_DEAD(self.enemy) || self.enemy.health < 1)
+                       || (STAT(FROZEN, self.enemy))
                        || (self.enemy.flags & FL_NOTARGET)
                        || (self.enemy.alpha < 0.5 && self.enemy.alpha != 0)
                        || (self.enemy.takedamage == DAMAGE_NO)
                        || (vlen(self.origin - targ_origin) > self.target_range)
                        || ((trace_fraction < 1) && (trace_ent != self.enemy)))
-                       //|| (time > self.ctf_droptime + autocvar_g_ctf_pass_timelimit)) // TODO: chase timelimit?
                {
                        self.enemy = world;
                        self.pass_distance = 0;
@@ -703,7 +702,7 @@ void Monster_Move(float runspeed, float walkspeed, float stpspeed)
 
        entity targ;
 
-       if(self.frozen == 2)
+       if(STAT(FROZEN, self) == 2)
        {
                self.revive_progress = bound(0, self.revive_progress + self.ticrate * self.revive_speed, 1);
                self.health = max(1, self.revive_progress * self.max_health);
@@ -712,7 +711,7 @@ void Monster_Move(float runspeed, float walkspeed, float stpspeed)
                if(!(self.spawnflags & MONSTERFLAG_INVINCIBLE) && self.sprite)
                        WaypointSprite_UpdateHealth(self.sprite, self.health);
 
-               movelib_beak_simple(stpspeed);
+               movelib_brake_simple(stpspeed);
                setanim(self, self.anim_idle, true, false, false);
 
                self.enemy = world;
@@ -723,7 +722,7 @@ void Monster_Move(float runspeed, float walkspeed, float stpspeed)
 
                return;
        }
-       else if(self.frozen == 3)
+       else if(STAT(FROZEN, self) == 3)
        {
                self.revive_progress = bound(0, self.revive_progress - self.ticrate * self.revive_speed, 1);
                self.health = max(0, autocvar_g_nades_ice_health + (self.max_health-autocvar_g_nades_ice_health) * self.revive_progress );
@@ -731,7 +730,7 @@ void Monster_Move(float runspeed, float walkspeed, float stpspeed)
                if(!(self.spawnflags & MONSTERFLAG_INVINCIBLE) && self.sprite)
                        WaypointSprite_UpdateHealth(self.sprite, self.health);
 
-               movelib_beak_simple(stpspeed);
+               movelib_brake_simple(stpspeed);
                setanim(self, self.anim_idle, true, false, false);
 
                self.enemy = world;
@@ -742,7 +741,7 @@ void Monster_Move(float runspeed, float walkspeed, float stpspeed)
                        Unfreeze(self);
                        self.health = 0;
                        if(self.event_damage)
-                               self.event_damage(self, self.frozen_by, 1, DEATH_NADE_ICE_FREEZE, self.origin, '0 0 0');
+                               self.event_damage(self, self.frozen_by, 1, DEATH_NADE_ICE_FREEZE.m_id, self.origin, '0 0 0');
                }
 
                else if ( self.revive_progress <= 0 )
@@ -759,7 +758,7 @@ void Monster_Move(float runspeed, float walkspeed, float stpspeed)
                        {
                                self.last_trace = time + 0.4;
 
-                               Damage (self, world, world, 2, DEATH_DROWN, self.origin, '0 0 0');
+                               Damage (self, world, world, 2, DEATH_DROWN.m_id, self.origin, '0 0 0');
                                self.angles = '90 90 0';
                                if(random() < 0.5)
                                {
@@ -800,7 +799,7 @@ void Monster_Move(float runspeed, float walkspeed, float stpspeed)
                runspeed = walkspeed = 0;
                if(time >= self.spawn_time)
                        setanim(self, self.anim_idle, true, false, false);
-               movelib_beak_simple(stpspeed);
+               movelib_brake_simple(stpspeed);
                return;
        }
 
@@ -808,12 +807,6 @@ void Monster_Move(float runspeed, float walkspeed, float stpspeed)
        runspeed = bound(0, monster_speed_run * MONSTER_SKILLMOD(self), runspeed * 2.5); // limit maxspeed to prevent craziness
        walkspeed = bound(0, monster_speed_walk * MONSTER_SKILLMOD(self), walkspeed * 2.5); // limit maxspeed to prevent craziness
 
-       if(time < self.spider_slowness)
-       {
-               runspeed *= 0.5;
-               walkspeed *= 0.5;
-       }
-
        if(teamplay)
        if(autocvar_g_monsters_teams)
        if(DIFF_TEAM(self.monster_follow, self))
@@ -840,13 +833,13 @@ void Monster_Move(float runspeed, float walkspeed, float stpspeed)
                self.last_enemycheck = time + 1; // check for enemies every second
        }
 
-       if(self.state == MONSTER_ATTACK_RANGED && (self.flags & FL_ONGROUND))
+       if(self.state == MONSTER_ATTACK_RANGED && (IS_ONGROUND(self)))
        {
                self.state = 0;
                self.touch = Monster_Touch;
        }
 
-       if(self.state && time >= self.attack_finished_single)
+       if(self.state && time >= self.attack_finished_single[0])
                self.state = 0; // attack is over
 
        if(self.state != MONSTER_ATTACK_MELEE) // don't move if set
@@ -868,7 +861,7 @@ void Monster_Move(float runspeed, float walkspeed, float stpspeed)
        if(vlen(self.origin - self.moveto) > 100)
        {
                float do_run = (self.enemy || self.monster_moveto);
-               if((self.flags & FL_ONGROUND) || ((self.flags & FL_FLY) || (self.flags & FL_SWIM)))
+               if((IS_ONGROUND(self)) || ((self.flags & FL_FLY) || (self.flags & FL_SWIM)))
                        Monster_CalculateVelocity(self, self.moveto, self.origin, true, ((do_run) ? runspeed : walkspeed));
 
                if(time > self.pain_finished) // TODO: use anim_finished instead!
@@ -887,7 +880,7 @@ void Monster_Move(float runspeed, float walkspeed, float stpspeed)
                else if(e.target)
                        self.target2 = e.target;
 
-               movelib_beak_simple(stpspeed);
+               movelib_brake_simple(stpspeed);
                if(time > self.anim_finished)
                if(time > self.pain_finished)
                if(!self.state)
@@ -912,12 +905,13 @@ void Monster_Move(float runspeed, float walkspeed, float stpspeed)
 
 void Monster_Remove(entity mon)
 {
+       .entity weaponentity = weaponentities[0];
        if(!mon) { return; }
 
        if(!MUTATOR_CALLHOOK(MonsterRemove, mon))
                Send_Effect(EFFECT_ITEM_PICKUP, mon.origin, '0 0 0', 1);
 
-       if(mon.weaponentity) { remove(mon.weaponentity); }
+       if(mon.(weaponentity)) { remove(mon.(weaponentity)); }
        if(mon.iceblock) { remove(mon.iceblock); }
        WaypointSprite_Kill(mon.sprite);
        remove(mon);
@@ -956,19 +950,19 @@ float Monster_Appear_Check(entity ent, float monster_id)
        return true;
 }
 
-void Monster_Reset()
-{SELFPARAM();
-       setorigin(self, self.pos1);
-       self.angles = self.pos2;
+void Monster_Reset(entity this)
+{
+       setorigin(this, this.pos1);
+       this.angles = this.pos2;
 
-       Unfreeze(self); // remove any icy remains
+       Unfreeze(this); // remove any icy remains
 
-       self.health = self.max_health;
-       self.velocity = '0 0 0';
-       self.enemy = world;
-       self.goalentity = world;
-       self.attack_finished_single = 0;
-       self.moveto = self.origin;
+       this.health = this.max_health;
+       this.velocity = '0 0 0';
+       this.enemy = world;
+       this.goalentity = world;
+       this.attack_finished_single[0] = 0;
+       this.moveto = this.origin;
 }
 
 void Monster_Dead_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
@@ -984,7 +978,7 @@ void Monster_Dead_Damage(entity inflictor, entity attacker, float damage, int de
                // number of monsters spawned with mobspawn command
                totalspawned -= 1;
 
-               self.think = SUB_Remove;
+               self.think = SUB_Remove_self;
                self.nextthink = time + 0.1;
                self.event_damage = func_null;
        }
@@ -996,7 +990,7 @@ void Monster_Dead(entity attacker, float gibbed)
        self.nextthink = time;
        self.monster_lifetime = time + 5;
 
-       if(self.frozen)
+       if(STAT(FROZEN, self))
        {
                Unfreeze(self); // remove any icy remains
                self.health = 0; // reset by Unfreeze
@@ -1029,15 +1023,16 @@ void Monster_Dead(entity attacker, float gibbed)
        self.touch                      = Monster_Touch; // reset incase monster was pouncing
        self.reset                      = func_null;
        self.state                      = 0;
-       self.attack_finished_single = 0;
+       self.attack_finished_single[0] = 0;
        self.effects = 0;
 
        if(!((self.flags & FL_FLY) || (self.flags & FL_SWIM)))
                self.velocity = '0 0 0';
 
-       CSQCModel_UnlinkEntity();
+       CSQCModel_UnlinkEntity(self);
 
-       MON_ACTION(self.monsterid, MR_DEATH);
+       Monster mon = get_monsterinfo(self.monsterid);
+       mon.mr_death(mon);
 
        if(self.candrop && self.weapon)
                W_ThrowNewWeapon(self, self.weapon, 0, self.origin, randomvec() * 150 + '0 0 325');
@@ -1045,19 +1040,19 @@ void Monster_Dead(entity attacker, float gibbed)
 
 void Monster_Damage(entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force)
 {SELFPARAM();
-       if((self.spawnflags & MONSTERFLAG_INVINCIBLE) && deathtype != DEATH_KILL)
+       if((self.spawnflags & MONSTERFLAG_INVINCIBLE) && deathtype != DEATH_KILL.m_id && !ITEM_DAMAGE_NEEDKILL(deathtype))
                return;
 
-       if(self.frozen && deathtype != DEATH_KILL && deathtype != DEATH_NADE_ICE_FREEZE)
+       if(STAT(FROZEN, self) && deathtype != DEATH_KILL.m_id && deathtype != DEATH_NADE_ICE_FREEZE.m_id)
                return;
 
-       //if(time < self.pain_finished && deathtype != DEATH_KILL)
+       //if(time < self.pain_finished && deathtype != DEATH_KILL.m_id)
                //return;
 
-       if(time < self.spawnshieldtime && deathtype != DEATH_KILL)
+       if(time < self.spawnshieldtime && deathtype != DEATH_KILL.m_id)
                return;
 
-       if(deathtype == DEATH_FALL && self.draggedby != world)
+       if(deathtype == DEATH_FALL.m_id && self.draggedby != world)
                return;
 
        vector v;
@@ -1070,7 +1065,8 @@ void Monster_Damage(entity inflictor, entity attacker, float damage, int deathty
        damage_take = take;
        frag_attacker = attacker;
        frag_deathtype = deathtype;
-       MON_ACTION(self.monsterid, MR_PAIN);
+       Monster mon = get_monsterinfo(self.monsterid);
+       mon.mr_pain(mon);
        take = damage_take;
 
        if(take)
@@ -1084,12 +1080,12 @@ void Monster_Damage(entity inflictor, entity attacker, float damage, int deathty
 
        self.dmg_time = time;
 
-       if(sound_allowed(MSG_BROADCAST, attacker) && deathtype != DEATH_DROWN)
+       if(sound_allowed(MSG_BROADCAST, attacker) && deathtype != DEATH_DROWN.m_id)
                spamsound (self, CH_PAIN, SND(BODYIMPACT1), VOL_BASE, ATTEN_NORM);  // FIXME: PLACEHOLDER
 
        self.velocity += force * self.damageforcescale;
 
-       if(deathtype != DEATH_DROWN && take)
+       if(deathtype != DEATH_DROWN.m_id && take)
        {
                Violence_GibSplash_At(hitloc, force, 2, bound(0, take, 200) / 16, self, attacker);
                if (take > 50)
@@ -1100,7 +1096,7 @@ void Monster_Damage(entity inflictor, entity attacker, float damage, int deathty
 
        if(self.health <= 0)
        {
-               if(deathtype == DEATH_KILL)
+               if(deathtype == DEATH_KILL.m_id)
                        self.candrop = false; // killed by mobkill command
 
                // TODO: fix this?
@@ -1109,18 +1105,18 @@ void Monster_Damage(entity inflictor, entity attacker, float damage, int deathty
                SUB_UseTargets();
                self.target2 = self.oldtarget2; // reset to original target on death, incase we respawn
 
-               Monster_Dead(attacker, (self.health <= -100 || deathtype == DEATH_KILL));
+               Monster_Dead(attacker, (self.health <= -100 || deathtype == DEATH_KILL.m_id));
 
                WaypointSprite_Kill(self.sprite);
 
                frag_target = self;
                MUTATOR_CALLHOOK(MonsterDies, attacker);
 
-               if(self.health <= -100 || deathtype == DEATH_KILL) // check if we're already gibbed
+               if(self.health <= -100 || deathtype == DEATH_KILL.m_id) // check if we're already gibbed
                {
                        Violence_GibSplash(self, 1, 0.5, attacker);
 
-                       self.think = SUB_Remove;
+                       self.think = SUB_Remove_self;
                        self.nextthink = time + 0.1;
                }
        }
@@ -1134,11 +1130,11 @@ void Monster_Move_2D(float mspeed, float allow_jumpoff)
                mspeed = 0;
                if(time >= self.spawn_time)
                        setanim(self, self.anim_idle, true, false, false);
-               movelib_beak_simple(0.6);
+               movelib_brake_simple(0.6);
                return;
        }
 
-       float reverse = FALSE;
+       float reverse = false;
        vector a, b;
 
        makevectors(self.angles);
@@ -1149,11 +1145,11 @@ void Monster_Move_2D(float mspeed, float allow_jumpoff)
 
        if(trace_fraction != 1.0)
        {
-               reverse = TRUE;
+               reverse = true;
 
                if(trace_ent)
                if(IS_PLAYER(trace_ent) && !(trace_ent.items & IT_STRENGTH))
-                       reverse = FALSE;
+                       reverse = false;
        }
 
        // TODO: fix this... tracing is broken if the floor is thin
@@ -1163,7 +1159,7 @@ void Monster_Move_2D(float mspeed, float allow_jumpoff)
                a = b - '0 0 32';
                traceline(b, a, MOVE_WORLDONLY, self);
                if(trace_fraction == 1.0)
-                       reverse = TRUE;
+                       reverse = true;
        } */
 
        if(reverse)
@@ -1175,7 +1171,7 @@ void Monster_Move_2D(float mspeed, float allow_jumpoff)
        movelib_move_simple_gravity(v_forward, mspeed, 1);
 
        if(time > self.pain_finished)
-       if(time > self.attack_finished_single)
+       if(time > self.attack_finished_single[0])
        if(vlen(self.velocity) > 10)
                setanim(self, self.anim_walk, true, false, false);
        else
@@ -1202,12 +1198,12 @@ void Monster_Anim()
                deadbits = 0;
        }
        int animbits = deadbits;
-       if(self.frozen)
+       if(STAT(FROZEN, self))
                animbits |= ANIMSTATE_FROZEN;
        if(self.crouch)
                animbits |= ANIMSTATE_DUCK; // not that monsters can crouch currently...
        animdecide_setstate(self, animbits, false);
-       animdecide_setimplicitstate(self, (self.flags & FL_ONGROUND));
+       animdecide_setimplicitstate(self, (IS_ONGROUND(self)));
 
        /* // weapon entities for monsters?
        if (self.weaponentity)
@@ -1227,11 +1223,12 @@ void Monster_Think()
        if(self.monster_lifetime)
        if(time >= self.monster_lifetime)
        {
-               Damage(self, self, self, self.health + self.max_health, DEATH_KILL, self.origin, self.origin);
+               Damage(self, self, self, self.health + self.max_health, DEATH_KILL.m_id, self.origin, self.origin);
                return;
        }
 
-       if(MON_ACTION(self.monsterid, MR_THINK))
+       Monster mon = get_monsterinfo(self.monsterid);
+       if(mon.mr_think(mon))
                Monster_Move(self.speed2, self.speed, self.stopspeed);
 
        Monster_Anim();
@@ -1241,7 +1238,8 @@ void Monster_Think()
 
 float Monster_Spawn_Setup()
 {SELFPARAM();
-       MON_ACTION(self.monsterid, MR_SETUP);
+       Monster mon = get_monsterinfo(self.monsterid);
+       mon.mr_setup(mon);
 
        // ensure some basic needs are met
        if(!self.health) { self.health = 100; }
@@ -1307,7 +1305,6 @@ bool Monster_Spawn(int mon_id)
 
        if(!autocvar_g_monsters) { Monster_Remove(self); return false; }
 
-       self.mdl = mon.model;
        if(Monster_Appear_Check(self, mon_id)) { return true; } // return true so the monster isn't removed
 
        if(!self.monster_skill)
@@ -1325,7 +1322,7 @@ bool Monster_Spawn(int mon_id)
        if(!(self.spawnflags & MONSTERFLAG_RESPAWNED)) // don't count re-spawning monsters either
                monsters_total += 1;
 
-       _setmodel(self, self.mdl);
+       setmodel(self, mon.m_model);
        self.flags                              = FL_MONSTER;
        self.classname                  = "monster";
        self.takedamage                 = DAMAGE_AIM;
@@ -1356,7 +1353,6 @@ bool Monster_Spawn(int mon_id)
        self.deadflag                   = DEAD_NO;
        self.noalign                    = ((mon.spawnflags & MONSTER_TYPE_FLY) || (mon.spawnflags & MONSTER_TYPE_SWIM));
        self.spawn_time                 = time;
-       self.spider_slowness    = 0;
        self.gravity                    = 1;
        self.monster_moveto             = '0 0 0';
        self.monster_face               = '0 0 0';
@@ -1374,9 +1370,15 @@ bool Monster_Spawn(int mon_id)
                self.movetype = MOVETYPE_FLY;
        }
 
-       if(mon.spawnflags & MONSTER_SIZE_BROKEN)
        if(!(self.spawnflags & MONSTERFLAG_RESPAWNED))
-               self.scale *= 1.3;
+       {
+               if(mon.spawnflags & MONSTER_SIZE_BROKEN)
+                       self.scale *= 1.3;
+
+               if(mon.spawnflags & MONSTER_SIZE_QUAKE)
+               if(autocvar_g_monsters_quake_resize)
+                       self.scale *= 1.3;
+       }
 
        setsize(self, mon.mins * self.scale, mon.maxs * self.scale);