3 const vector SOLDIER_MIN = '-16 -16 -30';
4 const vector SOLDIER_MAX = '16 16 32';
7 string SOLDIER_MODEL = "models/monsters/soldier.zym";
13 float autocvar_g_monster_soldier;
14 float autocvar_g_monster_soldier_health;
15 float autocvar_g_monster_soldier_melee_damage;
16 float autocvar_g_monster_soldier_speed_walk;
17 float autocvar_g_monster_soldier_speed_run;
18 float autocvar_g_monster_soldier_ammo;
19 float autocvar_g_monster_soldier_weapon_laser_chance;
20 float autocvar_g_monster_soldier_weapon_shotgun_chance;
21 float autocvar_g_monster_soldier_weapon_machinegun_chance;
22 float autocvar_g_monster_soldier_weapon_rocketlauncher_chance;
23 float autocvar_g_monster_soldier_attack_uzi_bullets;
24 float autocvar_g_monster_soldier_attack_uzi_damage;
25 float autocvar_g_monster_soldier_attack_uzi_force;
26 float autocvar_g_monster_soldier_attack_shotgun_damage;
27 float autocvar_g_monster_soldier_attack_shotgun_force;
28 float autocvar_g_monster_soldier_attack_shotgun_spread;
29 float autocvar_g_monster_soldier_attack_shotgun_bullets;
32 const float soldier_anim_die1 = 0;
33 const float soldier_anim_die2 = 1;
34 const float soldier_anim_draw = 2;
35 const float soldier_anim_duck = 3;
36 const float soldier_anim_duckwalk = 4;
37 const float soldier_anim_duckjump = 5;
38 const float soldier_anim_duckidle = 6;
39 const float soldier_anim_idle = 7;
40 const float soldier_anim_jump = 8;
41 const float soldier_anim_pain1 = 9;
42 const float soldier_anim_pain2 = 10;
43 const float soldier_anim_shoot = 11;
44 const float soldier_anim_taunt = 12;
45 const float soldier_anim_run = 13;
46 const float soldier_anim_runbackwards = 14;
47 const float soldier_anim_strafeleft = 15;
48 const float soldier_anim_straferight = 16;
49 const float soldier_anim_dead1 = 17;
50 const float soldier_anim_dead2 = 18;
51 const float soldier_anim_forwardright = 19;
52 const float soldier_anim_forwardleft = 20;
53 const float soldier_anim_backright = 21;
54 const float soldier_anim_backleft = 22;
58 self.think = soldier_think;
59 self.nextthink = time + self.ticrate;
62 self.nextthink = self.delay;
64 if(time < self.attack_finished_single)
65 monster_move(0, 0, 0, soldier_anim_shoot, soldier_anim_shoot, soldier_anim_shoot);
67 monster_move(autocvar_g_monster_soldier_speed_run, autocvar_g_monster_soldier_speed_walk, 50, soldier_anim_run, soldier_anim_run, soldier_anim_idle);
70 void soldier_reload ()
72 self.monster_delayedattack = func_null; // out of ammo, don't keep attacking
74 monsters_setframe(soldier_anim_draw);
75 self.attack_finished_single = time + 2;
76 self.currentammo = autocvar_g_monster_soldier_ammo;
77 sound (self, CH_SHOTS, "weapons/reload.wav", VOL_BASE, ATTN_LARGE);
81 void soldier_uzi_fire ()
83 self.currentammo -= 1;
84 if(self.currentammo <= 0)
90 self.grunt_cycles += 1;
92 if(self.grunt_cycles > autocvar_g_monster_soldier_attack_uzi_bullets)
94 self.monster_delayedattack = func_null;
99 W_SetupShot (self, autocvar_g_antilag_bullets && 18000 >= autocvar_g_antilag_bullets, 0, "weapons/uzi_fire.wav", CH_WEAPON_A, autocvar_g_monster_soldier_attack_uzi_damage);
100 fireBallisticBullet(w_shotorg, w_shotdir, 0.02, 18000, 5, autocvar_g_monster_soldier_attack_uzi_damage, autocvar_g_monster_soldier_attack_uzi_force, DEATH_MONSTER_MARINE, 0, 1, 115);
101 endFireBallisticBullet();
103 self.delay = time + 0.1;
104 self.monster_delayedattack = soldier_uzi_fire;
107 void soldier_shotgun_fire()
110 W_SetupShot (self, autocvar_g_antilag_bullets && 18000 >= autocvar_g_antilag_bullets, 5, "weapons/shotgun_fire.wav", CH_WEAPON_A, autocvar_g_monster_soldier_attack_shotgun_damage * autocvar_g_monster_soldier_attack_shotgun_bullets);
111 for (sc = 0;sc < autocvar_g_monster_soldier_attack_shotgun_bullets;sc = sc + 1)
112 fireBallisticBullet(w_shotorg, w_shotdir, autocvar_g_monster_soldier_attack_shotgun_spread, 18000, 5, autocvar_g_monster_soldier_attack_shotgun_damage, autocvar_g_monster_soldier_attack_shotgun_force, DEATH_MONSTER_MARINE, 0, 1, 115);
113 endFireBallisticBullet();
116 float soldier_attack()
118 monsters_setframe(soldier_anim_shoot);
119 makevectors(self.angles);
121 if(self.currentammo <= 0)
127 self.grunt_cycles = 0;
131 case WEP_ROCKET_LAUNCHER:
133 self.currentammo -= 1;
134 self.attack_finished_single = time + 0.8;
140 self.currentammo -= 1;
141 self.attack_finished_single = time + 0.8;
142 soldier_shotgun_fire();
147 self.attack_finished_single = time + 0.8;
148 self.delay = time + 0.1;
149 self.monster_delayedattack = soldier_uzi_fire;
154 self.attack_finished_single = time + 0.8;
159 return FALSE; // no weapon?
163 void soldier_melee ()
165 monsters_setframe(soldier_anim_shoot);
166 self.attack_finished_single = time + 0.8;
167 monster_melee(self.enemy, autocvar_g_monster_soldier_melee_damage, 0.3, DEATH_MONSTER_MARINE_SLAP, TRUE);
172 Monster_CheckDropCvars ("soldier");
174 self.think = Monster_Fade;
175 self.nextthink = time + 5;
176 monsters_setframe((random() > 0.5) ? soldier_anim_die1 : soldier_anim_die2);
178 monster_hook_death(); // for post-death mods
181 void soldier_spawn ()
184 self.health = autocvar_g_monster_soldier_health * self.scale;
186 self.damageforcescale = 0.003;
187 self.classname = "monster_soldier";
188 self.checkattack = GenericCheckAttack;
189 self.attack_melee = soldier_melee;
190 self.attack_ranged = soldier_attack;
191 self.nextthink = time + random() * 0.5 + 0.1;
192 self.think = soldier_think;
193 self.currentammo = 3;
194 self.sprite_height = 45;
195 self.items = (IT_SHELLS | IT_ROCKETS | IT_NAILS);
197 monsters_setframe(soldier_anim_draw);
199 monster_setupsounds("soldier");
201 setmodel(self, SOLDIER_MODEL);
203 RandomSelection_Init();
204 RandomSelection_Add(world, WEP_LASER, string_null, autocvar_g_monster_soldier_weapon_laser_chance, 1);
205 RandomSelection_Add(world, WEP_SHOTGUN, string_null, autocvar_g_monster_soldier_weapon_shotgun_chance, 1);
206 RandomSelection_Add(world, WEP_UZI, string_null, autocvar_g_monster_soldier_weapon_machinegun_chance, 1);
207 RandomSelection_Add(world, WEP_ROCKET_LAUNCHER, string_null, autocvar_g_monster_soldier_weapon_rocketlauncher_chance, 1);
209 self.weaponentity = spawn();
210 self.weaponentity.movetype = MOVETYPE_NOCLIP;
211 self.weaponentity.team = self.team;
212 self.weaponentity.solid = SOLID_NOT;
213 self.weaponentity.owner = self.weaponentity.realowner = self;
214 setmodel(self.weaponentity, "models/weapons/v_seeker.md3");
215 setattachment(self.weaponentity, self, "bip01 r hand");
217 self.armorvalue = bound(0.5, random(), 1);
218 self.weapon = RandomSelection_chosen_float;
220 monster_hook_spawn(); // for post-spawn mods
223 void spawnfunc_monster_soldier ()
225 if not(autocvar_g_monster_soldier) { remove(self); return; }
227 self.monster_spawnfunc = spawnfunc_monster_soldier;
229 if(Monster_CheckAppearFlags(self))
232 precache_model("models/weapons/v_seeker.md3");
233 precache_model(SOLDIER_MODEL);
235 if not (monster_initialize(
236 "Marine", MONSTER_MARINE,
237 SOLDIER_MIN, SOLDIER_MAX,
239 soldier_die, soldier_spawn))
246 // compatibility with old spawns
247 void spawnfunc_monster_army () { spawnfunc_monster_soldier(); }