set g_monsters_skill_hard 5 "Monster hard skill level (used for skill based functions)"
set g_monsters_skill_insane 7 "Monster insane skill level (used for skill based functions)"
set g_monsters_skill_nightmare 10 "Monster nightmare skill level (used for skill based functions)"
-set g_monsters_spawn_list "ogre demon shambler bruiser marine scrag dog slime hellknight fish mage zombie spider" "monsters not listed here will spawn as bruisers"
+set g_monsters_spawn_list "ogre demon shambler bruiser marine wyvern dog slime hellknight fish mage zombie spider" "monsters not listed here will spawn as bruisers"
// Ogre
set g_monster_ogre 1 "Enable Ogres"
set g_monster_soldier_attack_laser_speed 2000 "Grunt laser projectile speed"
set g_monster_soldier_attack_laser_spread 0 "Grunt laser projectile spread"
-// Scrag
-set g_monster_wizard 1 "Enable Scrags"
-set g_monster_wizard_health 80 "Scrag health"
-set g_monster_wizard_drop ammo "Scrag drops this item on death"
-set g_monster_wizard_drop_size cells "Size of the item Scrags drop. Possible values are: small, medium, large"
-set g_monster_wizard_speed_walk 40 "Scrag walk speed"
-set g_monster_wizard_speed_run 70 "Scrag run speed"
-set g_monster_wizard_spike_damage 15 "Scrag spike damage"
-set g_monster_wizard_spike_damage 7 "Scrag spike edge damage"
-set g_monster_wizard_spike_radius 20 "Scrag spike damage radius"
-set g_monster_wizard_spike_speed 400 "Scrag spike speed"
+// Wyvern
+set g_monster_wyvern 1 "Enable Wyverns"
+set g_monster_wyvern_health 80 "Wyvern health"
+set g_monster_wyvern_drop ammo "Wyvern drops this item on death"
+set g_monster_wyvern_drop_size cells "Size of the item Wyverns drop. Possible values are: small, medium, large"
+set g_monster_wyvern_speed_walk 40 "Wyvern walk speed"
+set g_monster_wyvern_speed_run 70 "Wyvern run speed"
+set g_monster_wyvern_fireball_damagetime 3 "How long the enemy will burn if it's within fireball radius"
+set g_monster_wyvern_fireball_damage 30 "Wyvern fireball projectile damage"
+set g_monster_wyvern_fireball_edgedamage 20 "Wyvern fireball indirect hit damage"
+set g_monster_wyvern_fireball_force 50 "Wyvern fireball projectile push force"
+set g_monster_wyvern_fireball_radius 70 "Wyvern fireball projectile damage radius"
+set g_monster_wyvern_fireball_speed 400 "Wyvern fireball projectile speed"
// Rottweiler
set g_monster_dog 1 "Enable Rottweilers"
precache_model("models/weapons/v_seeker.md3");
break;
}
- case MONSTER_SCRAG:
+ case MONSTER_WYVERN:
{
- precache_model(WIZARD_MODEL);
+ precache_model(WYVERN_MODEL);
break;
}
case MONSTER_DOG:
mid2info_max = SOLDIER_MAX;
break;
}
- case MONSTER_SCRAG:
+ case MONSTER_WYVERN:
{
- mid2info_model = WIZARD_MODEL;
- mid2info_name = "Scrag";
- mid2info_min = WIZARD_MIN;
- mid2info_max = WIZARD_MAX;
+ mid2info_model = WYVERN_MODEL;
+ mid2info_name = "Wyvern";
+ mid2info_min = WYVERN_MIN;
+ mid2info_max = WYVERN_MAX;
if(self) self.scale = 1.3;
break;
}
DEATHTYPE(DEATH_MONSTER_SPIDER, DEATH_SELF_MON_SPIDER, NO_MSG, NORMAL_POS) \
DEATHTYPE(DEATH_MONSTER_SPIDER_FIRE, DEATH_SELF_MON_SPIDER_FIRE, NO_MSG, NORMAL_POS) \
DEATHTYPE(DEATH_MONSTER_SLIME, DEATH_SELF_MON_SLIME, NO_MSG, NORMAL_POS) \
- DEATHTYPE(DEATH_MONSTER_SCRAG, DEATH_SELF_MON_SCRAG, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_MONSTER_WYVERN, DEATH_SELF_MON_WYVERN, NO_MSG, NORMAL_POS) \
DEATHTYPE(DEATH_MONSTER_ZOMBIE_JUMP, DEATH_SELF_MON_ZOMBIE_JUMP, NO_MSG, NORMAL_POS) \
DEATHTYPE(DEATH_MONSTER_ZOMBIE_MELEE, DEATH_SELF_MON_ZOMBIE_MELEE, NO_MSG, DEATH_MONSTER_LAST) \
DEATHTYPE(DEATH_NOAMMO, DEATH_SELF_NOAMMO, NO_MSG, NORMAL_POS) \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SPIDER, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was bitten by a Spider%s%s\n"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SPIDER_FIRE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was incinerated by a Spider%s%s\n"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SLIME, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was blown up by a Slime%s%s\n"), "") \
- MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SCRAG, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was cursed by a Scrag%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_WYVERN, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was fireballed by a Wyvern%s%s\n"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_ZOMBIE_JUMP, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 joins the Zombies%s%s\n"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_ZOMBIE_MELEE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was given kung fu lessons by a Zombie%s%s\n"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NOAMMO, 2, 1, "s1 s2loc spree_lost", "s1", "notify_outofammo", _("^BG%s^K1 died%s%s. What's the point of living without ammo?\n"), _("^BG%s^K1 ran out of ammo%s%s\n")) \
MSG_MULTI_NOTIF(1, DEATH_SELF_MON_SPIDER, NO_MSG, INFO_DEATH_SELF_MON_SPIDER, CENTER_DEATH_SELF_MONSTER) \
MSG_MULTI_NOTIF(1, DEATH_SELF_MON_SPIDER_FIRE, NO_MSG, INFO_DEATH_SELF_MON_SPIDER_FIRE, CENTER_DEATH_SELF_MONSTER) \
MSG_MULTI_NOTIF(1, DEATH_SELF_MON_SLIME, NO_MSG, INFO_DEATH_SELF_MON_SLIME, CENTER_DEATH_SELF_MONSTER) \
- MSG_MULTI_NOTIF(1, DEATH_SELF_MON_SCRAG, NO_MSG, INFO_DEATH_SELF_MON_SCRAG, CENTER_DEATH_SELF_MONSTER) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_MON_WYVERN, NO_MSG, INFO_DEATH_SELF_MON_WYVERN, CENTER_DEATH_SELF_MONSTER) \
MSG_MULTI_NOTIF(1, DEATH_SELF_MON_ZOMBIE_JUMP, NO_MSG, INFO_DEATH_SELF_MON_ZOMBIE_JUMP, CENTER_DEATH_SELF_MONSTER) \
MSG_MULTI_NOTIF(1, DEATH_SELF_MON_ZOMBIE_MELEE, NO_MSG, INFO_DEATH_SELF_MON_ZOMBIE_MELEE, CENTER_DEATH_SELF_MONSTER) \
MSG_MULTI_NOTIF(1, DEATH_SELF_NOAMMO, NO_MSG, INFO_DEATH_SELF_NOAMMO, CENTER_DEATH_SELF_NOAMMO) \
me.TD(me, 1, 0.4, e = makeXonoticRadioButton(2, "menu_monsters_edit_spawn", "slime", _("Slime")));
me.TD(me, 1, 0.4, e = makeXonoticRadioButton(2, "menu_monsters_edit_spawn", "fish", _("Rotfish")));
me.TD(me, 1, 0.4, e = makeXonoticRadioButton(2, "menu_monsters_edit_spawn", "mage", _("Mage")));
- me.TD(me, 1, 0.4, e = makeXonoticRadioButton(2, "menu_monsters_edit_spawn", "scrag", _("Scrag")));
+ me.TD(me, 1, 0.4, e = makeXonoticRadioButton(2, "menu_monsters_edit_spawn", "wyvern", _("Wyvern")));
me.TR(me);
me.TD(me, 1, 0.25, e = makeXonoticTextLabel(0, _("Name:")));
me.TD(me, 1, 1.5, box = makeXonoticInputBox(1, "menu_monsters_edit_name"));
float MONSTER_SHAMBLER = 5;
float MONSTER_BRUISER = 6;
float MONSTER_MARINE = 7;
-float MONSTER_SCRAG = 8;
+float MONSTER_WYVERN = 8;
float MONSTER_DOG = 9;
float MONSTER_SLIME = 10;
float MONSTER_HELLKNIGHT = 11;
missile.owner = missile.realowner = self;
missile.solid = SOLID_TRIGGER;
missile.movetype = MOVETYPE_FLYMISSILE;
- self.projectiledeathtype = DEATH_MONSTER_HKNIGHT_FBALL;
+ missile.projectiledeathtype = DEATH_MONSTER_HKNIGHT_FBALL;
setsize (missile, fmins, fmaxs);
setorigin(missile, self.origin + '0 0 10' + v_forward * 14);
missile.flags = FL_PROJECTILE;
+++ /dev/null
-// size
-const vector WIZARD_MIN = '-20 -20 -58';
-const vector WIZARD_MAX = '20 20 20';
-
-// model
-string WIZARD_MODEL = "models/monsters/wizard.mdl";
-
-#ifdef SVQC
-// cvars
-float autocvar_g_monster_wizard;
-float autocvar_g_monster_wizard_health;
-float autocvar_g_monster_wizard_speed_walk;
-float autocvar_g_monster_wizard_speed_run;
-float autocvar_g_monster_wizard_spike_damage;
-float autocvar_g_monster_wizard_spike_edgedamage;
-float autocvar_g_monster_wizard_spike_radius;
-float autocvar_g_monster_wizard_spike_speed;
-
-// animations
-const float wizard_anim_hover = 0;
-const float wizard_anim_fly = 1;
-const float wizard_anim_magic = 2;
-const float wizard_anim_pain = 3;
-const float wizard_anim_death = 4;
-
-void wizard_think ()
-{
- self.think = wizard_think;
- self.nextthink = time + self.ticrate;
-
- monster_move(autocvar_g_monster_wizard_speed_run, autocvar_g_monster_wizard_speed_walk, 300, wizard_anim_fly, wizard_anim_hover, wizard_anim_hover);
-}
-
-void Wiz_FastExplode()
-{
- self.event_damage = func_null;
- self.takedamage = DAMAGE_NO;
- RadiusDamage (self, self.realowner, autocvar_g_monster_wizard_spike_damage, autocvar_g_monster_wizard_spike_edgedamage, autocvar_g_monster_wizard_spike_radius, world, 0, self.projectiledeathtype, other);
-
- remove (self);
-}
-
-void Wiz_FastTouch ()
-{
- if(other == self.owner)
- return;
-
- PROJECTILE_TOUCH;
-
- pointparticles(particleeffectnum("TE_WIZSPIKE"), self.origin, '0 0 0', 1);
-
- Wiz_FastExplode();
-}
-
-void Wiz_StartFast ()
-{
- entity missile;
- vector dir = normalize((self.enemy.origin + '0 0 10') - self.origin);
-
- self.attack_finished_single = time + 0.2;
-
- monster_makevectors(self.enemy);
-
- missile = spawn ();
- missile.owner = missile.realowner = self;
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.origin + v_forward * 14 + '0 0 30' + v_right * 14);
- missile.enemy = self.enemy;
- missile.nextthink = time + 3;
- missile.think = Wiz_FastExplode;
- missile.velocity = dir * autocvar_g_monster_wizard_spike_speed;
- missile.avelocity = '300 300 300';
- missile.solid = SOLID_BBOX;
- missile.movetype = MOVETYPE_FLYMISSILE;
- missile.touch = Wiz_FastTouch;
- missile.projectiledeathtype = DEATH_MONSTER_SCRAG;
- CSQCProjectile(missile, TRUE, PROJECTILE_CRYLINK, TRUE);
-
- missile = spawn ();
- missile.owner = missile.realowner = self;
- setsize (missile, '0 0 0', '0 0 0');
- setorigin (missile, self.origin + v_forward * 14 + '0 0 30' + v_right * -14);
- missile.enemy = self.enemy;
- missile.nextthink = time + 3;
- missile.touch = Wiz_FastTouch;
- missile.solid = SOLID_BBOX;
- missile.movetype = MOVETYPE_FLYMISSILE;
- missile.think = Wiz_FastExplode;
- missile.velocity = dir * autocvar_g_monster_wizard_spike_speed;
- missile.avelocity = '300 300 300';
- missile.projectiledeathtype = DEATH_MONSTER_SCRAG;
- CSQCProjectile(missile, TRUE, PROJECTILE_CRYLINK, TRUE);
-}
-
-float wyvern_attack(float attack_type)
-{
- switch(attack_type)
- {
- case MONSTER_ATTACK_MELEE:
- case MONSTER_ATTACK_RANGED:
- {
- Wiz_StartFast();
-
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-void wizard_die ()
-{
- Monster_CheckDropCvars ("wizard");
-
- self.think = monster_dead_think;
- self.nextthink = time + self.ticrate;
- self.ltime = time + 5;
- self.velocity_x = -200 + 400 * random();
- self.velocity_y = -200 + 400 * random();
- self.velocity_z = 100 + 100 * random();
-
- monsters_setframe(wizard_anim_death);
-
- monster_hook_death(); // for post-death mods
-}
-
-void wizard_spawn ()
-{
- if not(self.health)
- self.health = autocvar_g_monster_wizard_health;
-
- self.classname = "monster_wizard";
- self.monster_attackfunc = wyvern_attack;
- self.nextthink = time + random() * 0.5 + 0.1;
- self.movetype = MOVETYPE_FLY; // TODO: make it fly up/down
- self.flags |= FL_FLY;
- self.think = wizard_think;
-
- monster_setupsounds("wizard");
-
- monster_hook_spawn(); // for post-spawn mods
-}
-
-void spawnfunc_monster_scrag ()
-{
- if not(autocvar_g_monster_wizard) { remove(self); return; }
-
- self.monster_spawnfunc = spawnfunc_monster_scrag;
-
- if(Monster_CheckAppearFlags(self))
- return;
-
- self.scale = 1.3;
-
- if not (monster_initialize(
- "Scrag", MONSTER_SCRAG,
- WIZARD_MIN, WIZARD_MAX,
- TRUE,
- wizard_die, wizard_spawn))
- {
- remove(self);
- return;
- }
-}
-
-// compatibility with old spawns
-void spawnfunc_monster_wizard() { spawnfunc_monster_scrag(); }
-
-#endif // SVQC
--- /dev/null
+// size
+const vector WYVERN_MIN = '-20 -20 -58';
+const vector WYVERN_MAX = '20 20 20';
+
+// model
+string WYVERN_MODEL = "models/monsters/wizard.mdl";
+
+#ifdef SVQC
+// cvars
+float autocvar_g_monster_wyvern;
+float autocvar_g_monster_wyvern_health;
+float autocvar_g_monster_wyvern_speed_walk;
+float autocvar_g_monster_wyvern_speed_run;
+float autocvar_g_monster_wyvern_fireball_damage;
+float autocvar_g_monster_wyvern_fireball_force;
+float autocvar_g_monster_wyvern_fireball_radius;
+float autocvar_g_monster_wyvern_fireball_edgedamage;
+float autocvar_g_monster_wyvern_fireball_damagetime;
+float autocvar_g_monster_wyvern_fireball_speed;
+
+// animations
+const float wyvern_anim_hover = 0;
+const float wyvern_anim_fly = 1;
+const float wyvern_anim_magic = 2;
+const float wyvern_anim_pain = 3;
+const float wyvern_anim_death = 4;
+
+void wyvern_think ()
+{
+ self.think = wyvern_think;
+ self.nextthink = time + self.ticrate;
+
+ monster_move(autocvar_g_monster_wyvern_speed_run, autocvar_g_monster_wyvern_speed_walk, 300, wyvern_anim_fly, wyvern_anim_hover, wyvern_anim_hover);
+}
+
+void wyvern_fireball_explode()
+{
+ entity e;
+ if(self)
+ {
+ pointparticles(particleeffectnum("fireball_explode"), self.origin, '0 0 0', 1);
+
+ RadiusDamage(self, self.realowner, autocvar_g_monster_wyvern_fireball_damage, autocvar_g_monster_wyvern_fireball_edgedamage, autocvar_g_monster_wyvern_fireball_force, world, autocvar_g_monster_wyvern_fireball_radius, self.projectiledeathtype, world);
+
+ for(e = world; (e = findfloat(e, takedamage, DAMAGE_AIM)); ) if(vlen(e.origin - self.origin) <= autocvar_g_monster_wyvern_fireball_radius)
+ Fire_AddDamage(e, self, 5 * monster_skill, autocvar_g_monster_wyvern_fireball_damagetime, self.projectiledeathtype);
+
+ remove(self);
+ }
+}
+
+void wyvern_fireball_touch()
+{
+ PROJECTILE_TOUCH;
+
+ wyvern_fireball_explode();
+}
+
+void wyvern_fireball()
+{
+ entity missile = spawn();
+ vector dir = normalize((self.enemy.origin + '0 0 10') - self.origin);
+
+ monster_makevectors(self.enemy);
+
+ missile.owner = missile.realowner = self;
+ missile.solid = SOLID_TRIGGER;
+ missile.movetype = MOVETYPE_FLYMISSILE;
+ missile.projectiledeathtype = DEATH_MONSTER_WYVERN;
+ setsize (missile, '-6 -6 -6', '6 6 6');
+ setorigin(missile, self.origin + self.view_ofs + v_forward * 14);
+ missile.flags = FL_PROJECTILE;
+ missile.velocity = dir * autocvar_g_monster_wyvern_fireball_speed;
+ missile.avelocity = '300 300 300';
+ missile.nextthink = time + 5;
+ missile.think = wyvern_fireball_explode;
+ missile.enemy = self.enemy;
+ missile.touch = wyvern_fireball_touch;
+ CSQCProjectile(missile, TRUE, PROJECTILE_FIREMINE, TRUE);
+}
+
+float wyvern_attack(float attack_type)
+{
+ switch(attack_type)
+ {
+ case MONSTER_ATTACK_MELEE:
+ case MONSTER_ATTACK_RANGED:
+ {
+ self.attack_finished_single = time + 1.2;
+
+ wyvern_fireball();
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+void wyvern_die()
+{
+ Monster_CheckDropCvars ("wyvern");
+
+ self.think = monster_dead_think;
+ self.nextthink = time + self.ticrate;
+ self.ltime = time + 5;
+ self.velocity_x = -200 + 400 * random();
+ self.velocity_y = -200 + 400 * random();
+ self.velocity_z = 100 + 100 * random();
+
+ monsters_setframe(wyvern_anim_death);
+
+ monster_hook_death(); // for post-death mods
+}
+
+void wyvern_spawn()
+{
+ if not(self.health)
+ self.health = autocvar_g_monster_wyvern_health;
+
+ self.classname = "monster_wyvern";
+ self.monster_attackfunc = wyvern_attack;
+ self.nextthink = time + random() * 0.5 + 0.1;
+ self.movetype = MOVETYPE_FLY;
+ self.flags |= FL_FLY;
+ self.think = wyvern_think;
+
+ monster_setupsounds("wyvern");
+
+ monster_hook_spawn(); // for post-spawn mods
+}
+
+void spawnfunc_monster_wyvern()
+{
+ if not(autocvar_g_monster_wyvern) { remove(self); return; }
+
+ self.monster_spawnfunc = spawnfunc_monster_wyvern;
+
+ if(Monster_CheckAppearFlags(self))
+ return;
+
+ self.scale = 1.3;
+
+ if not (monster_initialize(
+ "Wyvern", MONSTER_WYVERN,
+ WYVERN_MIN, WYVERN_MAX,
+ TRUE,
+ wyvern_die, wyvern_spawn))
+ {
+ remove(self);
+ return;
+ }
+}
+
+// compatibility with old spawns
+void spawnfunc_monster_wizard() { spawnfunc_monster_wyvern(); }
+
+#endif // SVQC
#include "monster/shambler.qc"
#include "monster/bruiser.qc"
#include "monster/soldier.qc"
-#include "monster/wizard.qc"
+#include "monster/wyvern.qc"
#include "monster/dog.qc"
#include "monster/slime.qc"
#include "monster/hknight.qc"
case MONSTER_SPIDER:
case MONSTER_SLIME:
case MONSTER_DOG:
- case MONSTER_SCRAG:
+ case MONSTER_WYVERN:
case MONSTER_FISH:
return SWARM_WEAK;
case MONSTER_HELLKNIGHT:
case MONSTER_SHAMBLER: return "shambler";
case MONSTER_BRUISER: return "bruiser";
case MONSTER_MARINE: return "marine";
- case MONSTER_SCRAG: return "scrag";
+ case MONSTER_WYVERN: return "wyvern";
case MONSTER_DOG: return "dog";
case MONSTER_SLIME: return "slime";
case MONSTER_HELLKNIGHT: return "hellknight";
case MONSTER_HELLKNIGHT:
case MONSTER_DEMON:
return SWARM_NORMAL;
- case MONSTER_SCRAG:
+ case MONSTER_WYVERN:
return SWARM_FLY;
case MONSTER_FISH:
return SWARM_SWIM;
if(n_bruisers) RandomSelection_Add(world, MONSTER_BRUISER, "", 1, 1);
if(n_shamblers) RandomSelection_Add(world, MONSTER_SHAMBLER, "", 0.2, 0.2);
if(n_slimes) RandomSelection_Add(world, MONSTER_SLIME, "", 0.2, 0.2);
- if(n_wizards && flyspawns_count) RandomSelection_Add(world, MONSTER_SCRAG, "", 1, 1);
+ if(n_wyverns && flyspawns_count) RandomSelection_Add(world, MONSTER_WYVERN, "", 1, 1);
if(n_fish && waterspawns_count) RandomSelection_Add(world, MONSTER_FISH, "", 0.2, 0.2);
return RandomSelection_chosen_float;
n_slimes = DistributeEvenly_Get(0.7);
n_shamblers = DistributeEvenly_Get(0.3);
if(flyspawns_count > 0)
- n_wizards = DistributeEvenly_Get(1);
+ n_wyverns = DistributeEvenly_Get(1);
if(waterspawns_count > 0)
n_fish = DistributeEvenly_Get(1);
}
case MONSTER_SHAMBLER: n_shamblers -= 1; break;
case MONSTER_BRUISER: n_bruisers -= 1; break;
case MONSTER_MARINE: n_soldiers -= 1; break;
- case MONSTER_SCRAG: n_wizards -= 1; break;
+ case MONSTER_WYVERN: n_wyverns -= 1; break;
case MONSTER_DOG: n_dogs -= 1; break;
case MONSTER_SLIME: n_slimes -= 1; break;
case MONSTER_HELLKNIGHT: n_hknights -= 1; break;
// Counters
float monster_count, totalmonsters;
-float n_bruisers, n_dogs, n_ogres, n_shamblers, n_wizards, n_shalraths, n_soldiers, n_hknights, n_demons, n_zombies, n_slimes, n_fish, n_spiders;
+float n_bruisers, n_dogs, n_ogres, n_shamblers, n_wyverns, n_shalraths, n_soldiers, n_hknights, n_demons, n_zombies, n_slimes, n_fish, n_spiders;
float current_monsters;
float waterspawns_count, flyspawns_count;
float wave_count, max_waves;