2 const vector SPAWNER_MIN = '-35 -35 -10';
3 const vector SPAWNER_MAX = '35 35 70';
6 float autocvar_g_monster_spawner;
7 float autocvar_g_monster_spawner_health;
8 float autocvar_g_monster_spawner_target_recheck_delay;
9 float autocvar_g_monster_spawner_target_range;
10 float autocvar_g_monster_spawner_spawn_range;
11 float autocvar_g_monster_spawner_maxmobs;
12 string autocvar_g_monster_spawner_forcespawn;
18 if(self.spawner_monstercount >= autocvar_g_monster_spawner_maxmobs || self.frozen || self.freezetag_frozen)
21 vector posi1 = '0 0 0', posi2 = '0 0 0', posi3 = '0 0 0', posi4 = '0 0 0', chosenposi = '0 0 0';
23 string type = string_null;
26 self.spawner_monstercount += 1;
28 if(self.spawnmob != "")
31 if(autocvar_g_monster_spawner_forcespawn != "0")
32 type = autocvar_g_monster_spawner_forcespawn;
34 if(type == "" || type == "spawner") // spawner spawning spawners?!
37 posi1 = self.origin - '0 70 -50' * self.scale;
38 posi2 = self.origin + '0 70 50' * self.scale;
39 posi3 = self.origin - '70 0 -50' * self.scale;
40 posi4 = self.origin + '70 0 -50' * self.scale;
51 e = spawnmonster(type, self, self, chosenposi, FALSE, MONSTER_MOVE_WANDER);
53 if(teamplay && autocvar_g_monsters_teams)
56 if(self.spawnflags & MONSTERFLAG_GIANT)
57 e.spawnflags = MONSTERFLAG_GIANT;
59 if(self.flags & MONSTERFLAG_MINIBOSS)
60 e.spawnflags = MONSTERFLAG_MINIBOSS;
66 pointparticles(particleeffectnum(((self.scale > 3) ? "explosion_big" : "explosion_medium")), self.origin, '0 0 0', 1);
67 sound (self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
69 self.solid = SOLID_NOT;
70 self.takedamage = DAMAGE_NO;
71 self.event_damage = func_null;
73 self.think = Monster_Fade;
74 self.nextthink = time + 1;
76 monster_hook_death(); // for post-death mods
79 void spawner_recount()
81 self.spawner_monstercount = 0;
82 self.think = spawner_think;
83 self.nextthink = time;
88 float finished = FALSE, enemyDistance = 0;
89 self.think = spawner_think;
91 if(self.spawner_monstercount == autocvar_g_monster_spawner_maxmobs)
93 self.think = spawner_recount;
94 self.nextthink = time + 20;
98 // remove enemy that ran away
100 if (self.delay <= time) // check if we can do the rescan now
101 if (vlen(self.origin - self.enemy.origin) > autocvar_g_monster_spawner_target_range * self.scale)
104 self.delay = time + autocvar_g_monster_spawner_target_recheck_delay;
108 self.enemy = FindTarget(self);
110 self.delay = time + autocvar_g_monster_spawner_target_recheck_delay;
115 // this spawner has an enemy
116 traceline(self.origin, self.enemy.origin, FALSE, self);
117 enemyDistance = vlen(trace_endpos - self.origin);
119 if (trace_ent == self.enemy)
120 if (self.enemy.deadflag == DEAD_NO)
121 if (self.spawner_monstercount <= autocvar_g_monster_spawner_maxmobs)
122 if (enemyDistance <= autocvar_g_monster_spawner_spawn_range * self.scale)
129 self.nextthink = time + 1;
131 if(self.spawner_monstercount <= autocvar_g_monster_spawner_maxmobs)
132 self.nextthink = time + 0.1;
137 self.nextthink = time + 0.1;
144 self.health = autocvar_g_monster_spawner_health * self.scale;
146 self.classname = "monster_spawner";
147 self.nextthink = time + 2.1;
148 self.velocity = '0 0 0';
149 self.think = spawner_think;
150 self.touch = func_null;
151 self.sprite_height = 80 * self.scale;
153 self.spawner_monstercount = 0;
156 self.movetype = MOVETYPE_NONE;
158 monster_hook_spawn(); // for post-spawn mods
161 /*QUAKED monster_spawner (1 0 0) (-18 -18 -25) (18 18 47)
162 ---------NOTES----------
163 Spawns monsters when a player is nearby
164 -------- MODEL FOR RADIANT ONLY - DO NOT SET THIS AS A KEY --------
165 modeldisabled="models/containers/crate01.md3"
167 void spawnfunc_monster_spawner()
169 if not(autocvar_g_monster_spawner)
175 self.monster_spawnfunc = spawnfunc_monster_spawner;
177 if(self.spawnflags & MONSTERFLAG_APPEAR)
179 self.think = func_null;
181 self.use = Monster_Appear;
187 if not (monster_initialize(
189 "models/containers/crate01.md3",
190 SPAWNER_MIN, SPAWNER_MAX,
192 spawner_die, spawner_spawn))
198 precache_sound("weapons/rocket_impact.wav");