Git Repos / fte_dogmode / qc / monsters / zombie.qc
Last update to this file was on 2025-08-13 at 05:20.
Show zombie.qc
//==============================================================================
// ZOMBIES!.qc - Version 1.1
// by Ace_Dave
// http://www.trenton.edu/~weiden/quake
// Weiden@Trenton.EDU
//==============================================================================
//======================================================================
// Constants
//======================================================================
#ifdef SSQC
//----------------------------------------------------------------------
// monster zombie spawnflags -- CEV
//----------------------------------------------------------------------
typedef enumflags
{
        SPAWNFLAG_MONSTER_ZOMBIE_CRUCIFIED = 1, // animated dead
        SPAWNFLAG_MONSTER_ZOMBIE_DEAD_CRUCIFIED = 4, // motionless dead
        // SPAWN_DEAD = 4,              // from Zer src, for reference
        // SPAWN_DEAD_CRUCIFIED = 8,    // from Zer src again for reference
        // SPAWNFLAG_MONSTER_TELEWAIT = 8, // teleport-wait enemy
        SPAWNFLAG_MONSTER_ZOMBIE_SLEEPING = 16 // Zer default was 2
        // SPAWNFLAG_MONSTER_NO_SIGHT_SOUND = 32, // see base_monster.qc -- CEV
        // SPAWNFLAG_MONSTER_PASSIVE_UNTIL_ATTACKED = 64,
        // SPAWNFLAG_MONSTER_PASSIVE_ALWAYS = 128,
        // SPAWNFLAG_NOT_ON_EASY = 256, // see base_entities.qc -- CEV
        // SPAWNFLAG_NOT_ON_NORMAL = 512, // see base_entities.qc -- CEV
        // SPAWNFLAG_NOT_ON_HARD_OR_NIGHTMARE = 1024, // base_entities.qc -- CEV
        // SPAWNFLAG_NOT_IN_DEATHMATCH = 2048, // see base_entities.qc -- CEV
        // SPAWNFLAG_NOT_IN_COOP = 4096, // see base_entities.qc -- CEV
        // SPAWNFLAG_NOT_IN_SP = 8192, // see base_entities.qc -- CEV
        // SPAWNFLAG_NOT_ON_SKILL2 = 32768, // see base_entities.qc -- CEV
        // SPAWNFLAG_NOT_ON_SKILL3 = 65536, // see base_entities.qc -- CEV
        // SPAWNFLAG_CENTERPRINTALL = 131072 // see base_entities.qc -- CEV
        // SPAWNFLAG_MONSTER_SILENT = 262144, // suppress the teleport-in sound
        // SPAWNFLAG_MONSTER_TURRET = 524288, // dumptruck_ds
        // SPAWNFLAG_MONSTER_SPAWNED = 1048576, // MG1 SPAWNED flag
        // SPAWNFLAG_MONSTER_ANGRY = 2097152, // monster spawns in angry -- CEV
        // SPAWNFLAG_MONSTER_WAITWALK = 4194304 // MG1 WAITWALK flag
} monster_zombie_spawnflags;
#endif
#ifdef SSQC
const float ZOMBIE_HEALTH = 61;         // pd3 61
#endif
#if defined(CSQC) || defined(SSQC)
const vector ZOMBIE_MINS = '-16 -16 -24';
const vector ZOMBIE_MAXS = '16 16 40';
#endif
//======================================================================
// forward declarations
//======================================================================
// monster_zombie
#ifdef CSQC
void(float isnew) monster_zombie_netreceive;
#endif
#ifdef SSQC
void() monster_zombie_sightsound;       // AI & attacks
void() monster_zombie_attack_missile;
void() monster_zombie_attack_turretmissile;
// F()                                  // macro to set FRAME netflag -- CEV
void() zom_dead_cruc1;                  // animation & thinking
void() zom_cruc1; void() zom_cruc2; void() zom_cruc3; void() zom_cruc4;
void() zom_cruc5; void() zom_cruc6;
void() zom_stand1; void() zom_stand2;
void() zom_alt_stand1; void() zom_alt_stand2; void() zom_stand3;
void() zom_stand4; void() zom_stand5; void() zom_stand6; void() zom_stand7;
void() zom_stand8; void() zom_stand9; void() zom_stand10; void() zom_stand11;
void() zom_stand12; void() zom_stand13; void() zom_stand14; void() zom_stand15;
void() zom_walk1; void() zom_walk2; void() zom_walk3; void() zom_walk4;
void() zom_walk5; void() zom_walk6; void() zom_walk7; void() zom_walk8;
void() zom_walk9; void() zom_walk10; void() zom_walk11; void() zom_walk12;
void() zom_walk13; void() zom_walk14; void() zom_walk15; void() zom_walk16;
void() zom_walk17; void() zom_walk18; void() zom_walk19;
void() zom_run1; void() zom_run2; void() zom_run3; void() zom_run4;
void() zom_run5; void() zom_run6; void() zom_run7; void() zom_run8;
void() zom_run9; void() zom_run10; void() zom_run11; void() zom_run12;
void() zom_run13; void() zom_run14; void() zom_run15; void() zom_run16;
void() zom_run17; void() zom_run18;
void() zom_atka1; void() zom_atka2; void() zom_atka3; void() zom_atka4;
void() zom_atka5; void() zom_atka6; void() zom_atka7; void() zom_atka8;
void() zom_atka9; void() zom_atka10; void() zom_atka11; void() zom_atka12;
void() zom_atka13;
void() zom_atkb1; void() zom_atkb2; void() zom_atkb3; void() zom_atkb4;
void() zom_atkb5; void() zom_atkb6; void() zom_atkb7; void() zom_atkb8;
void() zom_atkb9; void() zom_atkb10; void() zom_atkb11; void() zom_atkb12;
void() zom_atkb13; void() zom_atkb14;
void() zom_atkc1; void() zom_atkc2; void() zom_atkc3; void() zom_atkc4;
void() zom_atkc5; void() zom_atkc6; void() zom_atkc7; void() zom_atkc8;
void() zom_atkc9; void() zom_atkc10; void() zom_atkc11; void() zom_atkc12;
void() zom_tur_atka1; void() zom_tur_atka2; void() zom_tur_atka3;
void() zom_tur_atka4; void() zom_tur_atka5; void() zom_tur_atka6;
void() zom_tur_atka7; void() zom_tur_atka8; void() zom_tur_atka9;
void() zom_tur_atka10; void() zom_tur_atka11; void() zom_tur_atka12;
void() zom_tur_atka13;
void() zom_tur_atkb1; void() zom_tur_atkb2; void() zom_tur_atkb3;
void() zom_tur_atkb4; void() zom_tur_atkb5; void() zom_tur_atkb6;
void() zom_tur_atkb7; void() zom_tur_atkb8; void() zom_tur_atkb9;
void() zom_tur_atkb10; void() zom_tur_atkb11; void() zom_tur_atkb12;
void() zom_tur_atkb13; void() zom_tur_atkb14;
void() zom_tur_atkc1; void() zom_tur_atkc2; void() zom_tur_atkc3;
void() zom_tur_atkc4; void() zom_tur_atkc5; void() zom_tur_atkc6;
void() zom_tur_atkc7; void() zom_tur_atkc8; void() zom_tur_atkc9;
void() zom_tur_atkc10; void() zom_tur_atkc11; void() zom_tur_atkc12;
void() zom_alt_seek1; void() zom_alt_seek2; void() zom_seek3; void() zom_seek4;
void() zom_seek5; void() zom_seek6; void() zom_seek7; void() zom_seek8;
void() zom_seek9; void() zom_seek10; void() zom_seek11; void() zom_seek12;
void() zom_seek13; void() zom_seek14; void() zom_seek15;
void() zom_paina1; void() zom_paina2; void() zom_paina3; void() zom_paina4;
void() zom_paina5; void() zom_paina6; void() zom_paina7; void() zom_paina8;
void() zom_paina9; void() zom_paina10; void() zom_paina11; void() zom_paina12;
void() zom_painb1; void() zom_painb2; void() zom_painb3; void() zom_painb4;
void() zom_painb5; void() zom_painb6; void() zom_painb7; void() zom_painb8;
void() zom_painb9; void() zom_painb10; void() zom_painb11; void() zom_painb12;
void() zom_painb13; void() zom_painb14; void() zom_painb15; void() zom_painb16;
void() zom_painb17; void() zom_painb18; void() zom_painb19; void() zom_painb20;
void() zom_painb21; void() zom_painb22; void() zom_painb23; void() zom_painb24;
void() zom_painb25; void() zom_painb26; void() zom_painb27; void() zom_painb28;
void() zom_painc1; void() zom_painc2; void() zom_painc3; void() zom_painc4;
void() zom_painc5; void() zom_painc6; void() zom_painc7; void() zom_painc8;
void() zom_painc9; void() zom_painc10; void() zom_painc11; void() zom_painc12;
void() zom_painc13; void() zom_painc14; void() zom_painc15; void() zom_painc16;
void() zom_painc17; void() zom_painc18;
void() zom_paind1; void() zom_paind2; void() zom_paind3; void() zom_paind4;
void() zom_paind5; void() zom_paind6; void() zom_paind7; void() zom_paind8;
void() zom_paind9; void() zom_paind10; void() zom_paind11; void() zom_paind12;
void() zom_paind13;
void() zom_paine1; void() zom_paine2; void() zom_paine3; void() zom_paine4;
void() zom_paine5; void() zom_paine6; void() zom_paine7; void() zom_paine8;
void() zom_paine9; void() zom_paine10; void() zom_paine11; void() zom_paine12;
void() zom_paine13; void() zom_paine14; void() zom_paine15; void() zom_paine16;
void() zom_paine17; void() zom_paine18; void() zom_paine19; void() zom_paine20;
void() zom_paine21; void() zom_paine22; void() zom_paine23; void() zom_paine24;
void() zom_paine25; void() zom_paine26; void() zom_paine27; void() zom_paine28;
void() zom_paine29; void() zom_paine30;
void(entity attacker, float take) monster_zombie_pain; // interaction
void(vector dir) monster_zombie_destroy;
void() monster_zombie_use;
void() monster_zombie_decide;           // initialization
void() monster_zombie_start;
entity(vector org, vector ang, float sflags, float yaw)
        spawn_monster_zombie;
#endif
#if defined(CSQC) || defined(SSQC)
void(entity e) monster_zombie_init;
#endif
#ifdef SSQC
void() monster_zombie;
#endif
//======================================================================
// frame macros
//======================================================================
#ifdef SSQC
$cd /raid/quake/id1/models/zombie
$origin 0 0 24
$base base
$skin skin
$frame stand1 stand2 stand3 stand4 stand5 stand6 stand7 stand8
$frame stand9 stand10 stand11 stand12 stand13 stand14 stand15
$frame walk1 walk2 walk3 walk4 walk5 walk6 walk7 walk8 walk9 walk10 walk11
$frame walk12 walk13 walk14 walk15 walk16 walk17 walk18 walk19
$frame run1 run2 run3 run4 run5 run6 run7 run8 run9 run10 run11 run12
$frame run13 run14 run15 run16 run17 run18
$frame atta1 atta2 atta3 atta4 atta5 atta6 atta7 atta8 atta9 atta10 atta11
$frame atta12 atta13
$frame attb1 attb2 attb3 attb4 attb5 attb6 attb7 attb8 attb9 attb10 attb11
$frame attb12 attb13 attb14
$frame attc1 attc2 attc3 attc4 attc5 attc6 attc7 attc8 attc9 attc10 attc11
$frame attc12
$frame paina1 paina2 paina3 paina4 paina5 paina6 paina7 paina8 paina9 paina10
$frame paina11 paina12
$frame painb1 painb2 painb3 painb4 painb5 painb6 painb7 painb8 painb9 painb10
$frame painb11 painb12 painb13 painb14 painb15 painb16 painb17 painb18 painb19
$frame painb20 painb21 painb22 painb23 painb24 painb25 painb26 painb27 painb28
$frame painc1 painc2 painc3 painc4 painc5 painc6 painc7 painc8 painc9 painc10
$frame painc11 painc12 painc13 painc14 painc15 painc16 painc17 painc18
$frame paind1 paind2 paind3 paind4 paind5 paind6 paind7 paind8 paind9 paind10
$frame paind11 paind12 paind13
$frame paine1 paine2 paine3 paine4 paine5 paine6 paine7 paine8 paine9 paine10
$frame paine11 paine12 paine13 paine14 paine15 paine16 paine17 paine18 paine19
$frame paine20 paine21 paine22 paine23 paine24 paine25 paine26 paine27 paine28
$frame paine29 paine30
$frame cruc_1 cruc_2 cruc_3 cruc_4 cruc_5 cruc_6
#endif
//------------------------------------------------------------------------------
/*QUAKED monster_zombie (1 0 0) (-16 -16 -24) (16 16 32) CRUCIFIED AMBUSH CRUCIFIED_MOTIONLESS TRIGGER_SPAWNED SPAWN_SLEEPING X X X NOT_ON_EASY NOT_ON_NORMAL NOT_ON_HARD_OR_NIGHTMARE NOT_IN_DEATHMATCH NOT_IN_COOP NOT_IN_SINGLEPLAYER X NOT_ON_HARD_ONLY NOT_ON_NIGHTMARE_ONLY
{
        model ( {{ spawnflags & 1 -> { "path" : "progs/zombie.mdl", "frame" : 192 }, "progs/zombie.mdl" }} );
}
If crucified, stick the bounding box 12 pixels back into a wall to look right.
Default health = 60
If SPAWN_SLEEPING is used there must be a targetname set. The zombie will stand up when targeted. Crucified motionless zombies are silent and do not animate." //dumptruck_ds
mdl_head(string) : "Path to custom head model"
mdl_body(string) : "Path to custom body model"
mdl_proj(string) : "Path to custom projectile model"
skin_head(float) : "Skin index of custom head model"
skin_proj(float) : "Skin index of custom projectile model"
mdl_gib1(string) : "Path to custom 1st gib model"
mdl_gib2(string) : "Path to custom 2nd gib model"
mdl_gib3(string) : "Path to custom 3rd gib model"
effects(choices) : "Add a visual effect to an entity"
0 : "None (Default)"
1 : "Brightfield (yellow particles)"
4 : "Bright light"
8 : "Dim light"
berserk(choices) "Skips certain pain animations similar to skill 3 (Makes a semi-nightmare monster!)"
0 : "Off (Default)"
1 : "Berserk (skip pain animations)"
delay(float) : "Delay spawn in for this amount of time"
wait(choices) : "Play an effect when trigger spawned?"
0 : "Teleport Effects (Default)"
1 : "Spawn Silently"
spawn_angry(Choices)
0 : "Only when trigger spawned, default behavior - not angry"
1 : "Only when trigger spawned, set to 1 to spawn angry at player"
infight_mode(Choices)
0 : "Default behavior, only with different classnames"
1 : "Infight with monsters with the same classname but a different mdl_body"
2 : "Infight with monsters with the same classname and model but a different skin"
3 : "Infight no matter what"
health(integer) : "Set this to a custom health amount"
pain_target(string) : "Fire this target when pain_threshold is reached"
pain_threshold(integer) : "Fire pain_target when health drops below this amount"
sight_trigger(integer) : "1 = Fire target upon seeing the player instead of death"
skin(integer) : "Skin index (default 0) Use this when your custom model has more than one skin to select"
spawnflags(Flags) =
1 : "Crucified"
2 : "Ambush"
4 : "Crucified motionless"
16 : "Spawn Sleeping"
*/
//----------------------------------------------------------------------
// class monster_zombie: base_monster
// {
#ifdef CSQC
        //--------------------------------------------------------------
        void(float isnew) monster_zombie_netreceive =
        {
                // creates the newframe and netflags variables -- CEV
                BASE_MONSTER_NETRECEIVE (monster_zombie_init,
                        ZOMBIE_MINS, ZOMBIE_MAXS)
                if (isnew)
                        base_entity_que_add (self, QUE_TYPE_ACTOR);
        };
#endif
#ifdef SSQC
        //--------------------------------------------------------------
        void() monster_zombie_sightsound =
        {
                SOUND (self, snd_zombie_idle_01)
        };
        //--------------------------------------------------------------
        void() monster_zombie_attack_missile =
        {
                local float r;
                r = random ();
                if (r < 0.3)
                        zom_atka1 ();
                else if (r < 0.6)
                        zom_atkb1 ();
                else
                        zom_atkc1 ();
        };
        //--------------------------------------------------------------
        void() monster_zombie_attack_turretmissile =
        {
                local float r;
                r = random ();
                if (r < 0.3)
                        zom_tur_atkb1 ();
                else if (r < 0.6)
                        zom_tur_atka1 ();
                else
                        zom_tur_atkc1 ();
        };
        //--------------------------------------------------------------
        #define F() \
        /* { */ \
                if (!(self.SendFlags & NETFLAG_BASE_ENTITY_FRAME)) \
                { \
                        self.SendFlags |= NETFLAG_BASE_ENTITY_FRAME; \
                } \
        /* } */
        //--------------------------------------------------------------
        // motionless crucified zombie
        //--------------------------------------------------------------
        void() zom_dead_cruc1 = [$cruc_1, zom_dead_cruc1]
        {
                self.nextthink = time + 1;
                F ()
        };
        //--------------------------------------------------------------
        // crucified zombie
        //--------------------------------------------------------------
        void() zom_cruc1 = [$cruc_1, zom_cruc2]
        {
                if (random() < 0.1)
                {
                        SOUND (self, snd_zombie_idle_03)
                }
                F ()
        };
        void() zom_cruc2 = [$cruc_2, zom_cruc3]
        {
                self.nextthink = time + 0.1 + random() * 0.1;
                F ()
        };
        void() zom_cruc3 = [$cruc_3, zom_cruc4]
        {
                self.nextthink = time + 0.1 + random() * 0.1;
                F ()
        };
        void() zom_cruc4 = [$cruc_4, zom_cruc5]
        {
                self.nextthink = time + 0.1 + random() * 0.1;
                F ()
        };
        void() zom_cruc5 = [$cruc_5, zom_cruc6]
        {
                self.nextthink = time + 0.1 + random() * 0.1;
                F ()
        };
        void() zom_cruc6 = [$cruc_6, zom_cruc1]
        {
                self.nextthink = time + 0.1 + random() * 0.1;
                F ()
        };
        //--------------------------------------------------------------
        // new "stand" - for sleeping zombies
        //--------------------------------------------------------------
        void() zom_stand1 = [$paine11, zom_stand2]
        {
                self.solid = SOLID_NOT;
                // dumptruck_ds -- count value > 0 to leave the zombie
                // sleeping until triggered!
                if (self.count == 0)
                        ai_stand ();
                self.SendFlags |= NETFLAG_BASE_ENTITY_FRAME |
                        NETFLAG_BASE_ENTITY_SOLID;
        };
        void() zom_stand2 = [$paine11, zom_stand1]
        {
                if (self.count == 0)
                        ai_stand ();
                F ()
        };
        //--------------------------------------------------------------
        // old "stand" - called when standing only
        //--------------------------------------------------------------
        void() zom_alt_stand1 = [$stand1, zom_alt_stand2]
        {
                self.health = ZOMBIE_HEALTH - 1;
                ai_stand ();
                F ()
        };
        void() zom_alt_stand2 = [$stand2, zom_stand3] { ai_stand (); F () };
        void() zom_stand3 = [$stand3, zom_stand4] { ai_stand (); F () };
        void() zom_stand4 = [$stand4, zom_stand5] { ai_stand (); F () };
        void() zom_stand5 = [$stand5, zom_stand6] { ai_stand (); F () };
        void() zom_stand6 = [$stand6, zom_stand7] { ai_stand (); F () };
        void() zom_stand7 = [$stand7, zom_stand8] { ai_stand (); F () };
        void() zom_stand8 = [$stand8, zom_stand9] { ai_stand (); F () };
        void() zom_stand9 = [$stand9, zom_stand10] { ai_stand (); F () };
        void() zom_stand10 = [$stand10, zom_stand11] { ai_stand (); F () };
        void() zom_stand11 = [$stand11, zom_stand12] { ai_stand (); F () };
        void() zom_stand12 = [$stand12, zom_stand13] { ai_stand (); F () };
        void() zom_stand13 = [$stand13, zom_stand14] { ai_stand (); F () };
        void() zom_stand14 = [$stand14, zom_stand15] { ai_stand (); F () };
        void() zom_stand15 = [$stand15, zom_alt_stand1] { ai_stand (); F () };
        //--------------------------------------------------------------
        // Zombie walk (shamble? shuffle?) functions
        //--------------------------------------------------------------
        void() zom_walk1 = [$walk1, zom_walk2]
        {
                self.solid = SOLID_SLIDEBOX;
                // so he doesn't fall
                self.health = ZOMBIE_HEALTH - 1;
                ai_walk (0);
                self.SendFlags |= NETFLAG_BASE_ENTITY_FRAME |
                        NETFLAG_BASE_ENTITY_SOLID;
        };
        void() zom_walk2 = [$walk2, zom_walk3] { ai_walk (2); F () };
        void() zom_walk3 = [$walk3, zom_walk4] { ai_walk (3); F () };
        void() zom_walk4 = [$walk4, zom_walk5] { ai_walk (2); F () };
        void() zom_walk5 = [$walk5, zom_walk6] { ai_walk (1); F () };
        void() zom_walk6 = [$walk6, zom_walk7] { ai_walk (0); F () };
        void() zom_walk7 = [$walk7, zom_walk8] { ai_walk (0); F () };
        void() zom_walk8 = [$walk8, zom_walk9] { ai_walk (0); F () };
        void() zom_walk9 = [$walk9, zom_walk10] { ai_walk (0); F () };
        void() zom_walk10 = [$walk10, zom_walk11] { ai_walk (0); F () };
        void() zom_walk11 = [$walk11, zom_walk12] { ai_walk (2); F () };
        void() zom_walk12 = [$walk12, zom_walk13] { ai_walk (2); F () };
        void() zom_walk13 = [$walk13, zom_walk14] { ai_walk (1); F () };
        void() zom_walk14 = [$walk14, zom_walk15] { ai_walk (0); F () };
        void() zom_walk15 = [$walk15, zom_walk16] { ai_walk (0); F () };
        void() zom_walk16 = [$walk16, zom_walk17] { ai_walk (0); F () };
        void() zom_walk17 = [$walk17, zom_walk18] { ai_walk (0); F () };
        void() zom_walk18 = [$walk18, zom_walk19] { ai_walk (0); F () };
        void() zom_walk19 = [$walk19, zom_walk1]
        {
                ai_walk (0);
                if (random() < 0.2)
                {
                        SOUND (self, snd_zombie_idle_01)
                }
                F ()
        };
        //--------------------------------------------------------------
        // Zombie run functions
        //--------------------------------------------------------------
        void() zom_run1 = [$run1, zom_run2]
        {
                if (self.spawnflags & SPAWNFLAG_MONSTER_ZOMBIE_SLEEPING)
                {
                        // sloppy hack, but it fixes the illusionary zombie bug
                        // custom_mdls dumptruck_ds
                        setmodel (self, "progs/zombie.mdl");
                        // setmodel (self, "progs/zombie.mdl");
                        setsize (self, '-16 -16 -24', '16 16 40');
                }
                ai_run (1);
                // self.inpain = 0;
                self.speed2 = 0;
                F ()
        };
        void() zom_run2 = [$run2, zom_run3] { ai_run (1); F () };
        void() zom_run3 = [$run3, zom_run4] { ai_run (0); F () };
        void() zom_run4 = [$run4, zom_run5] { ai_run (1); F () };
        void() zom_run5 = [$run5, zom_run6] { ai_run (2); F () };
        void() zom_run6 = [$run6, zom_run7] { ai_run (3); F () };
        void() zom_run7 = [$run7, zom_run8] { ai_run (4); F () };
        void() zom_run8 = [$run8, zom_run9] { ai_run (4); F () };
        void() zom_run9 = [$run9, zom_run10] { ai_run (2); F () };
        void() zom_run10 = [$run10, zom_run11] { ai_run (0); F () };
        void() zom_run11 = [$run11, zom_run12] { ai_run (0); F () };
        void() zom_run12 = [$run12, zom_run13] { ai_run (0); F () };
        void() zom_run13 = [$run13, zom_run14] { ai_run (2); F () };
        void() zom_run14 = [$run14, zom_run15] { ai_run (4); F () };
        void() zom_run15 = [$run15, zom_run16] { ai_run (6); F () };
        void() zom_run16 = [$run16, zom_run17] { ai_run (7); F () };
        void() zom_run17 = [$run17, zom_run18] { ai_run (3); F () };
        void() zom_run18 = [$run18, zom_run1]
        {
                ai_run (8);
                if (random() < 0.2)
                {
                        SOUND (self, snd_zombie_idle_01)
                }
                else if (random() > 0.8)
                {
                        SOUND (self, snd_zombie_idle_02)
                }
                F ()
        };
        //--------------------------------------------------------------
        // Zombie Attack A
        //--------------------------------------------------------------
        void() zom_atka1 = [$atta1, zom_atka2] { ai_face (); F () };
        void() zom_atka2 = [$atta2, zom_atka3] { ai_face (); F () };
        void() zom_atka3 = [$atta3, zom_atka4] { ai_face (); F () };
        void() zom_atka4 = [$atta4, zom_atka5] { ai_face (); F () };
        void() zom_atka5 = [$atta5, zom_atka6] { ai_face (); F () };
        void() zom_atka6 = [$atta6, zom_atka7] { ai_face (); F () };
        void() zom_atka7 = [$atta7, zom_atka8] { ai_face (); F () };
        void() zom_atka8 = [$atta8, zom_atka9] { ai_face (); F () };
        void() zom_atka9 = [$atta9, zom_atka10] { ai_face (); F () };
        void() zom_atka10 = [$atta10, zom_atka11] { ai_face (); F () };
        void() zom_atka11 = [$atta11, zom_atka12] { ai_face (); F () };
        void() zom_atka12 = [$atta12, zom_atka13] { ai_face (); F () };
        void() zom_atka13 = [$atta13, zom_run1]
        {
                ai_face ();
                base_monster_fire_zombiechunk ('-10 -22 30', 0);
                F ()
        };
        //--------------------------------------------------------------
        // Zombie Attack B
        //--------------------------------------------------------------
        void() zom_atkb1 = [$attb1, zom_atkb2] { ai_face (); F () };
        void() zom_atkb2 = [$attb2, zom_atkb3] { ai_face (); F () };
        void() zom_atkb3 = [$attb3, zom_atkb4] { ai_face (); F () };
        void() zom_atkb4 = [$attb4, zom_atkb5] { ai_face (); F () };
        void() zom_atkb5 = [$attb5, zom_atkb6] { ai_face (); F () };
        void() zom_atkb6 = [$attb6, zom_atkb7] { ai_face (); F () };
        void() zom_atkb7 = [$attb7, zom_atkb8] { ai_face (); F () };
        void() zom_atkb8 = [$attb8, zom_atkb9] { ai_face (); F () };
        void() zom_atkb9 = [$attb9, zom_atkb10] { ai_face (); F () };
        void() zom_atkb10 = [$attb10, zom_atkb11] { ai_face (); F () };
        void() zom_atkb11 = [$attb11, zom_atkb12] { ai_face (); F () };
        void() zom_atkb12 = [$attb12, zom_atkb13] { ai_face (); F () };
        void() zom_atkb13 = [$attb13, zom_atkb14] { ai_face (); F () };
        void() zom_atkb14 = [$attb13, zom_run1]
        {
                ai_face ();
                base_monster_fire_zombiechunk ('-10 -24 29', 0);
                F ()
        };
        //--------------------------------------------------------------
        // Zombie Attack C
        //--------------------------------------------------------------
        void() zom_atkc1 = [$attc1, zom_atkc2] { ai_face (); F () };
        void() zom_atkc2 = [$attc2, zom_atkc3] { ai_face (); F () };
        void() zom_atkc3 = [$attc3, zom_atkc4] { ai_face (); F () };
        void() zom_atkc4 = [$attc4, zom_atkc5] { ai_face (); F () };
        void() zom_atkc5 = [$attc5, zom_atkc6] { ai_face (); F () };
        void() zom_atkc6 = [$attc6, zom_atkc7] { ai_face (); F () };
        void() zom_atkc7 = [$attc7, zom_atkc8] { ai_face (); F () };
        void() zom_atkc8 = [$attc8, zom_atkc9] { ai_face (); F () };
        void() zom_atkc9 = [$attc9, zom_atkc10] { ai_face (); F () };
        void() zom_atkc10 = [$attc10, zom_atkc11] { ai_face (); F () };
        void() zom_atkc11 = [$attc11, zom_atkc12] { ai_face (); F () };
        void() zom_atkc12 = [$attc12, zom_run1]
        {
                ai_face ();
                base_monster_fire_zombiechunk ('-12 -19 29', 0);
                F ()
        };
        ///////////////////////////
        /// turret frames START ///
        ///////////////////////////
        //--------------------------------------------------------------
        // Zombie Turret Attack A
        //--------------------------------------------------------------
        void() zom_tur_atka1 = [$atta1, zom_tur_atka2]
        {
                self.health = ZOMBIE_HEALTH - 1;
                ai_face ();
                F ()
        };
        void() zom_tur_atka2 = [$atta2, zom_tur_atka3] { ai_face (); F () };
        void() zom_tur_atka3 = [$atta3, zom_tur_atka4] { ai_face (); F () };
        void() zom_tur_atka4 = [$atta4, zom_tur_atka5] { ai_face (); F () };
        void() zom_tur_atka5 = [$atta5, zom_tur_atka6] { ai_face (); F () };
        void() zom_tur_atka6 = [$atta6, zom_tur_atka7] { ai_face (); F () };
        void() zom_tur_atka7 = [$atta7, zom_tur_atka8] { ai_face (); F () };
        void() zom_tur_atka8 = [$atta8, zom_tur_atka9] { ai_face (); F () };
        void() zom_tur_atka9 = [$atta9, zom_tur_atka10] { ai_face (); F () };
        void() zom_tur_atka10 = [$atta10, zom_tur_atka11]
        {
                ai_face ();
                // was .attack_elevation -- CEV
                self.t_height = preach_iterate_elevation (
                        OGRE_DEFAULT_ELEVATION, ZCHUNK_SPEED,
                        self.origin, self.enemy.origin);
                F ()
        };
        void() zom_tur_atka11 = [$atta11, zom_tur_atka12]
        {
                ai_face ();
                self.t_height = preach_iterate_elevation (
                        self.t_height, ZCHUNK_SPEED,
                        self.origin, self.enemy.origin);
                F ()
        };
        void() zom_tur_atka12 = [$atta12, zom_tur_atka13]
        {
                ai_face ();
                self.t_height = preach_iterate_elevation (
                        self.t_height, ZCHUNK_SPEED,
                        self.origin, self.enemy.origin);
                F ()
        };
        void() zom_tur_atka13 = [$atta13, zom_alt_seek1]
        {
                ai_run (0);
                base_monster_fire_zombiechunk ('0 0 0', self.t_height);
                F ()
        };
        //--------------------------------------------------------------
        // Zombie Turret Attack B
        //--------------------------------------------------------------
        void() zom_tur_atkb1 = [$attb1, zom_tur_atkb2]
        {
                self.health = ZOMBIE_HEALTH - 1;
                ai_face ();
                F ()
        };
        void() zom_tur_atkb2 = [$attb2, zom_tur_atkb3] { ai_face (); F () };
        void() zom_tur_atkb3 = [$attb3, zom_tur_atkb4] { ai_face (); F () };
        void() zom_tur_atkb4 = [$attb4, zom_tur_atkb5] { ai_face (); F () };
        void() zom_tur_atkb5 = [$attb5, zom_tur_atkb6] { ai_face (); F () };
        void() zom_tur_atkb6 = [$attb6, zom_tur_atkb7] { ai_face (); F () };
        void() zom_tur_atkb7 = [$attb7, zom_tur_atkb8] { ai_face (); F () };
        void() zom_tur_atkb8 = [$attb8, zom_tur_atkb9] { ai_face (); F () };
        void() zom_tur_atkb9 = [$attb9, zom_tur_atkb10] { ai_face (); F () };
        void() zom_tur_atkb10 = [$attb10, zom_tur_atkb11] {ai_face (); F () };
        void() zom_tur_atkb11 = [$attb11, zom_tur_atkb12]
        {
                ai_face ();
                self.t_height = preach_iterate_elevation (
                        OGRE_DEFAULT_ELEVATION, ZCHUNK_SPEED,
                        self.origin, self.enemy.origin);
                F ()
        };
        void() zom_tur_atkb12 = [$attb12, zom_tur_atkb13]
        {
                ai_face ();
                self.t_height = preach_iterate_elevation (
                        self.t_height, ZCHUNK_SPEED,
                        self.origin, self.enemy.origin);
                F ()
        };
        void() zom_tur_atkb13 = [$attb13, zom_tur_atkb14]
        {
                ai_face ();
                self.t_height = preach_iterate_elevation (
                        self.t_height, ZCHUNK_SPEED,
                        self.origin, self.enemy.origin);
                F ()
        };
        void() zom_tur_atkb14 = [$attb13, zom_alt_seek1]
        {
                ai_run (0);
                base_monster_fire_zombiechunk ('0 0 0', self.t_height);
                F ()
        };
        //--------------------------------------------------------------
        // Zombie Turret Attack C
        //--------------------------------------------------------------
        void() zom_tur_atkc1 = [$attc1, zom_tur_atkc2]
        {
                self.health = ZOMBIE_HEALTH - 1;
                ai_face ();
                F ()
        };
        void() zom_tur_atkc2 = [$attc2, zom_tur_atkc3] { ai_face (); F () };
        void() zom_tur_atkc3 = [$attc3, zom_tur_atkc4] { ai_face (); F () };
        void() zom_tur_atkc4 = [$attc4, zom_tur_atkc5] { ai_face (); F () };
        void() zom_tur_atkc5 = [$attc5, zom_tur_atkc6] { ai_face (); F () };
        void() zom_tur_atkc6 = [$attc6, zom_tur_atkc7] { ai_face (); F () };
        void() zom_tur_atkc7 = [$attc7, zom_tur_atkc8] { ai_face (); F () };
        void() zom_tur_atkc8 = [$attc8, zom_tur_atkc9] { ai_face (); F () };
        void() zom_tur_atkc9 = [$attc9, zom_tur_atkc10]
        {
                ai_face ();
                self.t_height = preach_iterate_elevation (
                        OGRE_DEFAULT_ELEVATION, ZCHUNK_SPEED,
                        self.origin, self.enemy.origin);
                F ()
        };
        void() zom_tur_atkc10 = [$attc10, zom_tur_atkc11]
        {
                ai_face ();
                self.t_height = preach_iterate_elevation (
                        self.t_height, ZCHUNK_SPEED,
                        self.origin, self.enemy.origin);
                F ()
        };
        void() zom_tur_atkc11 = [$attc11, zom_tur_atkc12]
        {
                ai_face ();
                self.t_height = preach_iterate_elevation (
                        self.t_height, ZCHUNK_SPEED,
                        self.origin, self.enemy.origin);
                F ()
        };
        void() zom_tur_atkc12 = [$attc12, zom_alt_seek1]
        {
                ai_run (0);
                base_monster_fire_zombiechunk ('0 0 0', self.t_height);
                F ()
        };
        //--------------------------------------------------------------
        // Zombie Turret Seek Stand
        //--------------------------------------------------------------
        void() zom_alt_seek1 = [$stand1, zom_alt_seek2]
        {
                self.health = ZOMBIE_HEALTH - 1;
                ai_run (0);
                F ()
        };
        void() zom_alt_seek2 = [$stand2, zom_seek3] { ai_run (0); F () };
        void() zom_seek3 = [$stand3, zom_seek4] { ai_run (0); F () };
        void() zom_seek4 = [$stand4, zom_seek5] { ai_run (0); F () };
        void() zom_seek5 = [$stand5, zom_seek6] { ai_run (0); F () };
        void() zom_seek6 = [$stand6, zom_seek7] { ai_run (0); F () };
        void() zom_seek7 = [$stand7, zom_seek8] { ai_run (0); F () };
        void() zom_seek8 = [$stand8, zom_seek9] { ai_run (0); F () };
        void() zom_seek9 = [$stand9, zom_seek10] { ai_run (0); F () };
        void() zom_seek10 = [$stand10, zom_seek11] { ai_run (0); F () };
        void() zom_seek11 = [$stand11, zom_seek12] { ai_run (0); F () };
        void() zom_seek12 = [$stand12, zom_seek13] { ai_run (0); F () };
        void() zom_seek13 = [$stand13, zom_seek14] { ai_run (0); F () };
        void() zom_seek14 = [$stand14, zom_seek15] { ai_run (0); F () };
        void() zom_seek15 = [$stand15, zom_alt_seek1] { ai_run (0); F () };
        ///////////////////////////
        /// turret frames END   ///
        ///////////////////////////
        //--------------------------------------------------------------
        // Zombie Pain State A
        //--------------------------------------------------------------
        void() zom_paina1 = [$paina1, zom_paina2]
        {
                SOUND (self, snd_zombie_pain_01)
                F ()
        };
        void() zom_paina2 = [$paina2, zom_paina3] { ai_painforward (3); F () };
        void() zom_paina3 = [$paina3, zom_paina4] { ai_painforward (1); F () };
        void() zom_paina4 = [$paina4, zom_paina5] { ai_pain (1); F () };
        void() zom_paina5 = [$paina5, zom_paina6] { ai_pain (3); F () };
        void() zom_paina6 = [$paina6, zom_paina7] { ai_pain (1); F () };
        void() zom_paina7 = [$paina7, zom_paina8] { F () };
        void() zom_paina8 = [$paina8, zom_paina9] { F () };
        void() zom_paina9 = [$paina9, zom_paina10] { F () };
        void() zom_paina10 = [$paina10, zom_paina11] { F () };
        void() zom_paina11 = [$paina11, zom_paina12] { F () };
        void() zom_paina12 = [$paina12, zom_run1] { F () };
        //--------------------------------------------------------------
        // Zombie Pain State B
        //--------------------------------------------------------------
        void() zom_painb1 = [$painb1, zom_painb2]
        {
                SOUND (self, snd_zombie_pain_02)
                F ()
        };
        void() zom_painb2 = [$painb2, zom_painb3] { ai_pain (2); F () };
        void() zom_painb3 = [$painb3, zom_painb4] { ai_pain (8); F () };
        void() zom_painb4 = [$painb4, zom_painb5] { ai_pain (6); F () };
        void() zom_painb5 = [$painb5, zom_painb6] { ai_pain (2); F () };
        void() zom_painb6 = [$painb6, zom_painb7] { F () };
        void() zom_painb7 = [$painb7, zom_painb8] { F () };
        void() zom_painb8 = [$painb8, zom_painb9] { F () };
        void() zom_painb9 = [$painb9, zom_painb10]
        {
                SOUND (self, snd_zombie_fall)
                F ()
        };
        void() zom_painb10 = [$painb10, zom_painb11] { F () };
        void() zom_painb11 = [$painb11, zom_painb12] { F () };
        void() zom_painb12 = [$painb12, zom_painb13] { F () };
        void() zom_painb13 = [$painb13, zom_painb14] { F () };
        void() zom_painb14 = [$painb14, zom_painb15] { F () };
        void() zom_painb15 = [$painb15, zom_painb16] { F () };
        void() zom_painb16 = [$painb16, zom_painb17] { F () };
        void() zom_painb17 = [$painb17, zom_painb18] { F () };
        void() zom_painb18 = [$painb18, zom_painb19] { F () };
        void() zom_painb19 = [$painb19, zom_painb20] { F () };
        void() zom_painb20 = [$painb20, zom_painb21] { F () };
        void() zom_painb21 = [$painb21, zom_painb22] { F () };
        void() zom_painb22 = [$painb22, zom_painb23] { F () };
        void() zom_painb23 = [$painb23, zom_painb24] { F () };
        void() zom_painb24 = [$painb24, zom_painb25] { F () };
        void() zom_painb25 = [$painb25, zom_painb26]
        {
                ai_painforward (1);
                F ()
        };
        void() zom_painb26 = [$painb26, zom_painb27] { F () };
        void() zom_painb27 = [$painb27, zom_painb28] { F () };
        void() zom_painb28 = [$painb28, zom_run1] { F () };
        //--------------------------------------------------------------
        // Zombie Pain State C
        //--------------------------------------------------------------
        void() zom_painc1 = [$painc1, zom_painc2]
        {
                SOUND (self, snd_zombie_pain_02)
                F ()
        };
        void() zom_painc2 = [$painc2, zom_painc3] { F () };
        void() zom_painc3 = [$painc3, zom_painc4] { ai_pain (3); F () };
        void() zom_painc4 = [$painc4, zom_painc5] { ai_pain (1); F () };
        void() zom_painc5 = [$painc5, zom_painc6] { F () };
        void() zom_painc6 = [$painc6, zom_painc7] { F () };
        void() zom_painc7 = [$painc7, zom_painc8] { F () };
        void() zom_painc8 = [$painc8, zom_painc9] { F () };
        void() zom_painc9 = [$painc9, zom_painc10] { F () };
        void() zom_painc10 = [$painc10, zom_painc11] { F () };
        void() zom_painc11 = [$painc11, zom_painc12]
        {
                ai_painforward (1);
                F ()
        };
        void() zom_painc12 = [$painc12, zom_painc13]
        {
                ai_painforward (1);
                F ()
        };
        void() zom_painc13 = [$painc13, zom_painc14] { F () };
        void() zom_painc14 = [$painc14, zom_painc15] { F () };
        void() zom_painc15 = [$painc15, zom_painc16] { F () };
        void() zom_painc16 = [$painc16, zom_painc17] { F () };
        void() zom_painc17 = [$painc17, zom_painc18] { F () };
        void() zom_painc18 = [$painc18, zom_run1] { F () };
        //--------------------------------------------------------------
        // Zombie Pain State D
        //--------------------------------------------------------------
        void() zom_paind1 = [$paind1, zom_paind2]
        {
                SOUND (self, snd_zombie_pain_01)
                F ()
        };
        void() zom_paind2 = [$paind2, zom_paind3] { F () };
        void() zom_paind3 = [$paind3, zom_paind4] { F () };
        void() zom_paind4 = [$paind4, zom_paind5] { F () };
        void() zom_paind5 = [$paind5, zom_paind6] { F () };
        void() zom_paind6 = [$paind6, zom_paind7] { F () };
        void() zom_paind7 = [$paind7, zom_paind8] { F () };
        void() zom_paind8 = [$paind8, zom_paind9] { F () };
        void() zom_paind9 = [$paind9, zom_paind10] { ai_pain (1); F () };
        void() zom_paind10 = [$paind10, zom_paind11] { F () };
        void() zom_paind11 = [$paind11, zom_paind12] { F () };
        void() zom_paind12 = [$paind12, zom_paind13] { F () };
        void() zom_paind13 = [$paind13, zom_run1] { F () };
        //--------------------------------------------------------------
        // Zombie Pain State E
        //--------------------------------------------------------------
        void() zom_paine1 = [$paine1, zom_paine2]
        {
                SOUND (self, snd_zombie_pain_01)
                self.health = ZOMBIE_HEALTH - 1;
                F ()
        };
        void() zom_paine2 = [$paine2, zom_paine3] { ai_pain (8); F () };
        void() zom_paine3 = [$paine3, zom_paine4] { ai_pain (5); F () };
        void() zom_paine4 = [$paine4, zom_paine5] { ai_pain (3); F () };
        void() zom_paine5 = [$paine5, zom_paine6] { ai_pain (1); F () };
        void() zom_paine6 = [$paine6, zom_paine7] { ai_pain (2); F () };
        void() zom_paine7 = [$paine7, zom_paine8] { ai_pain (1); F () };
        void() zom_paine8 = [$paine8, zom_paine9] { ai_pain (1); F () };
        void() zom_paine9 = [$paine9, zom_paine10] { ai_pain (2); F () };
        void() zom_paine10 = [$paine10, zom_paine11]
        {
                SOUND (self, snd_zombie_fall)
                self.solid = SOLID_NOT;
                self.SendFlags |= NETFLAG_BASE_ENTITY_FRAME |
                        NETFLAG_BASE_ENTITY_SOLID;
        };
        void() zom_paine11 = [$paine11, zom_paine12]
        {
                self.nextthink = self.nextthink + 5;
                self.health = ZOMBIE_HEALTH - 1;
                F ()
        };
        void() zom_paine12 = [$paine12, zom_paine13]
        {
                // see if ok to stand up
                self.health = ZOMBIE_HEALTH - 1;
                SOUND (self, snd_zombie_idle_01)
                if (!walkmove(0, 0))
                {
                        self.think = zom_paine11;
                        self.solid = SOLID_NOT;
                }
                else
                {
                        self.solid = SOLID_SLIDEBOX;
                }
                self.SendFlags |= NETFLAG_BASE_ENTITY_FRAME |
                        NETFLAG_BASE_ENTITY_SOLID;
        };
        void() zom_paine13 = [$paine13, zom_paine14] { F () };
        void() zom_paine14 = [$paine14, zom_paine15] { F () };
        void() zom_paine15 = [$paine15, zom_paine16] { F () };
        void() zom_paine16 = [$paine16, zom_paine17] { F () };
        void() zom_paine17 = [$paine17, zom_paine18] { F () };
        void() zom_paine18 = [$paine18, zom_paine19] { F () };
        void() zom_paine19 = [$paine19, zom_paine20] { F () };
        void() zom_paine20 = [$paine20, zom_paine21] { F () };
        void() zom_paine21 = [$paine21, zom_paine22] { F () };
        void() zom_paine22 = [$paine22, zom_paine23] { F () };
        void() zom_paine23 = [$paine23, zom_paine24] { F () };
        void() zom_paine24 = [$paine24, zom_paine25] { F () };
        void() zom_paine25 = [$paine25, zom_paine26]
        {
                ai_painforward (5);
                F ()
        };
        void() zom_paine26 = [$paine26, zom_paine27]
        {
                ai_painforward (3);
                F ()
        };
        void() zom_paine27 = [$paine27, zom_paine28]
        {
                ai_painforward (1);
                F ()
        };
        void() zom_paine28 = [$paine28, zom_paine29] { ai_pain (1); F () };
        void() zom_paine29 = [$paine29, zom_paine30] { F () };
        void() zom_paine30 = [$paine30, zom_run1] { F () };
        #undef F
        //==============================================================
        // Interaction
        //==============================================================
        //--------------------------------------------------------------
        // zombie_pain
        //
        // Zombies can only be killed (gibbed) by doing 60 hit points of
        // damage in a single frame (rockets, grenades, quad shotgun,
        // quad nailgun).
        //
        // A hit of 25 points or more (super shotgun, quad nailgun) will
        // always put it down to the ground.
        //
        // A hit of from 10 to 40 points in one frame will cause it to
        // go down if it has been twice in two seconds, otherwise it
        // goes into one of the four fast pain frames.
        //
        // A hit of less than 10 points of damage (winged by a shotgun)
        // will be ignored.
        //
        // FIXME: don't use pain_finished because of nightmare hack
        //--------------------------------------------------------------
        void(entity attacker, float take) monster_zombie_pain =
        {
                if (self.spawnflags & SPAWNFLAG_MONSTER_TURRET)
                {
                        // always reset health
                        self.health = ZOMBIE_HEALTH - 1;
                        if (take >= ZOMBIE_HEALTH - 1)
                        {
                                // work out knockback direction -- CEV
                                vector dir;     
                                dir = self.origin - (attacker.absmin +
                                        attacker.absmax) * 0.5;
                                dir = normalize (dir);
                                monster_zombie_destroy (dir);
                        }
                        else
                        {
                                return;
                        }
                }
                local float r;
                // always reset health
                self.health = ZOMBIE_HEALTH - 1;
                if (take < 9)
                        // totally ignore
                        return;
                // if (self.inpain == 2)
                if (self.speed2 == 2)
                        // down on ground, so don't reset any counters
                        return;
                // go down immediately if a big enough hit
                if (take >= 25)
                {
                        // self.inpain = 2;
                        self.speed2 = 2;
                        zom_paine1 ();
                        return;
                }
                // if (self.inpain)
                if (self.speed2)
                {
                        // if hit again in next gre seconds while
                        // not in pain frames, definately drop
                        self.pain_finished = time + 3;
                        // currently going through an animation, don't change
                        return;
                }
                if (self.pain_finished > time)
                {
                        // hit again, so drop down
                        // self.inpain = 2;
                        self.speed2 = 2;
                        zom_paine1 ();
                        return;
                }
                // gp into one of the fast pain animations
                // self.inpain = 1;
                self.speed2 = 1;
                r = random ();
                if (r < 0.25)
                        zom_paina1 ();
                else if (r <  0.5)
                        zom_painb1 ();
                else if (r <  0.75)
                        zom_painc1 ();
                else
                        zom_paind1 ();
        };
        //--------------------------------------------------------------
        // zombie_die
        //--------------------------------------------------------------
        void(vector dir) monster_zombie_destroy =
        {
                self.deadflag |= DF_DEAD;
                self.deadflag |= DF_GIBBED;
                SOUND (self, snd_zombie_gib)
                base_monster_item_dropitems (dir);
                base_entity_remove (self);
        };
        //--------------------------------------------------------------
        // dumptruck_ds -- makes self.count = 0 so zombie_stand1 is called
        //--------------------------------------------------------------
        void() monster_zombie_use =
        {
                // wake up a sleeping zombie!
                self.count = 0;
                // attacker = other;
                // monster_use
                base_monster_use_angry ();
        };
        //==============================================================
        // Initialization
        //==============================================================
        //--------------------------------------------------------------
        entity(vector org, vector ang, float sflags, float yaw)
                spawn_monster_zombie =
        {
                return spawn_base_monster (org, ang, sflags, yaw,
                        monster_zombie_init);
        };
        //--------------------------------------------------------------
        // stand up if orig. lying down, else just start running
        //--------------------------------------------------------------
        void() monster_zombie_decide =
        {
                if (self.health == ZOMBIE_HEALTH)
                        zom_paine12 ();
                else
                        zom_run1 ();
                self.th_run = zom_run1;
        };
        //--------------------------------------------------------------
        // determine if zombie is to be lying down, or standing
        // shims th_stand -- CEV
        //--------------------------------------------------------------
        void() monster_zombie_start =
        {
                // dumptruck_ds -- Don't start zombie_stand1 yet!
                self.count = 1;
                if (self.spawnflags & SPAWNFLAG_MONSTER_ZOMBIE_SLEEPING)
                {
                        if (!sub_istargeted())
                        {
                                dprint (sprintf("monster_zombie_start: "
                                        "WARNING removed untargeted sleeping "
                                        "zombie at %v\n", self.origin));
                                monster_update_total (-1);
                                remove (self);
                                return;
                        }
                        // self.inpain = 2;
                        self.speed2 = 2;
                        zom_stand1 ();
                }
                else
                {
                        zom_alt_stand1 ();
                }
                self.th_stand = zom_alt_stand1;
        };
#endif
#if defined(CSQC) || defined(SSQC)
        //--------------------------------------------------------------
        void(entity e) monster_zombie_init =
        {
                #ifdef SSQC
                if (deathmatch)
                {
                        remove (e);
                        return;
                }
                #endif
                e.classname = "monster_zombie";
                e.classtype = CT_MONSTER_ZOMBIE;
                e.pos1 = ZOMBIE_MINS;
                e.pos2 = ZOMBIE_MAXS;
                #ifdef CSQC
                if (e.modelindex)
                {
                        setmodelindex (e, e.modelindex);
                        setsize (e, ZOMBIE_MINS, ZOMBIE_MAXS);
                }
                // call walkmonster_init on the clientside -- CEV
                base_monster_init (e);
                #endif
                #ifdef SSQC
                precache_model ("progs/zombie.mdl");
                precache_model ("progs/h_zombie.mdl");
                precache_model ("progs/zom_gib.mdl");
                precache_sound (snd_zombie_idle_01.wav);
                precache_sound (snd_zombie_idle_02.wav);
                precache_sound (snd_zombie_idle_03.wav);
                precache_sound (snd_zombie_shot.wav);
                precache_sound (snd_zombie_gib.wav);
                precache_sound (snd_zombie_pain_01.wav);
                precache_sound (snd_zombie_pain_02.wav);
                precache_sound (snd_zombie_fall.wav);
                precache_sound (snd_zombie_miss.wav);
                precache_sound (snd_zombie_hit.wav);
                precache_model ("progs/gib1.mdl");
                precache_model ("progs/gib2.mdl");
                precache_model ("progs/gib3.mdl");
                // set up gibs -- CEV
                e.item[BASE_ENTITY_ITEMLEN - 4] = ITEM_SEQ_GIB1;
                e.item[BASE_ENTITY_ITEMLEN - 3] = ITEM_SEQ_GIB2;
                e.item[BASE_ENTITY_ITEMLEN - 2] = ITEM_SEQ_GIB3;
                e.item[BASE_ENTITY_ITEMLEN - 1] = ITEM_SEQ_HEAD_ZOMBIE;
                e.th_destroy = monster_zombie_destroy;
                e.health = ZOMBIE_HEALTH;
                e.sightsound = monster_zombie_sightsound;
                e.th_stand = monster_zombie_start;
                e.th_walk = zom_walk1;
                if (e.spawnflags & SPAWNFLAG_MONSTER_TURRET)
                        e.th_run = zom_alt_seek1;
                else
                        e.th_run = monster_zombie_decide;
                e.th_pain = monster_zombie_pain;
                e.th_turret = monster_zombie_attack_turretmissile;
                e.th_missile = monster_zombie_attack_missile;
                // set up model and size for later -- CEV
                e.mdl = "progs/zombie.mdl";
                if (e.spawnflags & SPAWNFLAG_MONSTER_ZOMBIE_CRUCIFIED)
                {
                        e.solid = SOLID_SLIDEBOX;
                        e.movetype = MOVETYPE_NONE;
                        setmodel (e, "progs/zombie.mdl");
                        setsize (e, ZOMBIE_MINS, ZOMBIE_MAXS);
                        e.SendEntity = base_entity_netsend;
                        e.SendFlags = NETFLAG_BASE_ENTITY_FULLSEND;
                        sub_runvoidas (e, zom_cruc1);
                }
                else if (e.spawnflags & SPAWNFLAG_MONSTER_ZOMBIE_DEAD_CRUCIFIED)
                {
                        e.solid = SOLID_SLIDEBOX;
                        e.movetype = MOVETYPE_NONE;
                        setmodel (e, "progs/zombie.mdl");
                        setsize (e, ZOMBIE_MINS, ZOMBIE_MAXS);
                        e.SendEntity = base_entity_netsend;
                        e.SendFlags = NETFLAG_BASE_ENTITY_FULLSEND;
                        sub_runvoidas (e, zom_dead_cruc1);
                }
                else
                {
                        // walkmonster_start
                        base_monster_init (e);
                }
                #endif
        };
#endif
#ifdef SSQC
        //--------------------------------------------------------------
        void() monster_zombie =
        {
                // remap spawnflags & fields, inhibit if necessary -- CEV
                BASE_MONSTER_PREINIT (base_monster_init_field)
                monster_zombie_init (self);
        };
#endif
// };
#if defined(CSQC) || defined(SSQC)
$flush
#endif
Return to the top of this page or return to the overview of this repo.
Log zombie.qc
| Date | Commit Message | Author | + | - | 
|---|---|---|---|---|
| 2025-08-13 | Another big commit. Item changes, field rework, etc. | cev | +85 | -101 | 
| 2025-03-30 | Big commit. Entity networking, etc. | cev | +455 | -355 | 
| 2024-06-26 | pmove fixes, GL now a faux tribolt, wall climbing | cev | +18 | -9 | 
| 2024-06-15 | Major update, committing as-is, will have bugs | cev | +34 | -24 | 
| 2024-04-12 | Moveable gibs, heads, some bugfixes | cev | +87 | -30 | 
| 2024-04-05 | Player footsteps, shareware monsters, misc? | cev | +549 | -457 | 
| 2024-02-18 | Client/player, projectiles, entrypoints refactor | cev | +58 | -172 | 
| 2024-01-31 | Class based monster refactor & start projectiles | cev | +995 | -723 | 
| 2024-01-13 | Refactored items into classes, fix teleporttrain | cev | +1 | -1 | 
| 2024-01-09 | Continue OO / Class-based refactor | cev | +2 | -2 | 
| 2023-12-09 | Start OO / class-based refactor, work on items | cev | -28 | |
| 2023-10-13 | New movement code based on SV_RunClientCommand | cev | +865 | -865 | 
| 2023-10-13 | Rename "qc-server" dir to "qc" | cev | +865 | 
Return to the top of this page or return to the overview of this repo.