set g_monster_dog_speed_walk 60 "Rottweiler walk speed"
set g_monster_dog_speed_run 120 "Rottweiler run speed"
-// Spawn
-set g_monster_tarbaby 1 "Enable Spawns"
-set g_monster_tarbaby_health 80 "Spawn health"
-set g_monster_tarbaby_drop ammo "Spawn drops this item when it explodes"
-set g_monster_tarbaby_drop_size rockets "Size of the item Spawns drop. Possible values are: small, medium, large"
-set g_monster_tarbaby_speed_walk 20 "Spawn walk speed"
-set g_monster_tarbaby_speed_run 30 "Spawn run speed"
+// Slime
+set g_monster_slime 1 "Enable Slime"
+set g_monster_slime_health 80 "Slime health"
+set g_monster_slime_drop ammo "Slime drops this item when it explodes"
+set g_monster_slime_drop_size rockets "Size of the item Slime drops. Possible values are: small, medium, large"
+set g_monster_slime_speed_walk 20 "Slime walk speed"
+set g_monster_slime_speed_run 30 "Slime run speed"
// Hell-Knight
set g_monster_hellknight 1 "Enable Hell-Knights"
precache_model(DOG_MODEL);
break;
}
- case MONSTER_TARBABY:
+ case MONSTER_SLIME:
{
- precache_model(TARBABY_MODEL);
+ precache_model(SLIME_MODEL);
precache_sound("weapons/rocket_impact.wav");
break;
}
mid2info_max = DOG_MAX;
break;
}
- case MONSTER_TARBABY:
+ case MONSTER_SLIME:
{
- mid2info_model = TARBABY_MODEL;
- mid2info_name = "Spawn";
- mid2info_min = TARBABY_MIN;
- mid2info_max = TARBABY_MAX;
+ mid2info_model = SLIME_MODEL;
+ mid2info_name = "Slime";
+ mid2info_min = SLIME_MIN;
+ mid2info_max = SLIME_MAX;
break;
}
case MONSTER_HELLKNIGHT:
DEATHTYPE(DEATH_MONSTER_MARINE_SLAP, DEATH_SELF_MON_MARINE_SLAP, NO_MSG, NORMAL_POS) \
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_TARBABY, DEATH_SELF_MON_TARBABY, 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_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) \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_MARINE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was gunned down by a Marine%s%s\n"), "") \
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_TARBABY, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 came too close to an exploding Pumpkin%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_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_MULTI_NOTIF(1, DEATH_SELF_MON_MARINE, NO_MSG, INFO_DEATH_SELF_MON_MARINE, CENTER_DEATH_SELF_MONSTER) \
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_TARBABY, NO_MSG, INFO_DEATH_SELF_MON_TARBABY, 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_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) \
-.void() attack_melee;
+.float() attack_melee;
.float() attack_ranged;
.float() checkattack;
float MONSTER_MARINE = 7;
float MONSTER_SCRAG = 8;
float MONSTER_DOG = 9;
-float MONSTER_TARBABY = 10;
+float MONSTER_SLIME = 10;
float MONSTER_HELLKNIGHT = 11;
float MONSTER_FISH = 12;
float MONSTER_MAGE = 13;
monster_move(autocvar_g_monster_demon_speed_run, autocvar_g_monster_demon_speed_walk, 100, demon_anim_run, demon_anim_walk, demon_anim_stand);
}
-void demon_attack_melee ()
+float demon_attack_melee ()
{
monsters_setframe(demon_anim_attack);
self.attack_finished_single = time + 1;
monster_melee(self.enemy, autocvar_g_monster_demon_damage, 0.3, DEATH_MONSTER_FIEND, TRUE);
+
+ return TRUE;
}
void Demon_JumpTouch ()
monster_move(autocvar_g_monster_dog_speed_run, autocvar_g_monster_dog_speed_walk, 50, dog_anim_run, dog_anim_walk, dog_anim_idle);
}
-void dog_attack ()
+float dog_attack ()
{
monsters_setframe(dog_anim_attack);
self.attack_finished_single = time + 0.7;
monster_melee(self.enemy, autocvar_g_monster_dog_bite_damage, 0.2, DEATH_MONSTER_DOG_BITE, TRUE);
+
+ return TRUE;
}
float dog_jump ()
monster_move(autocvar_g_monster_fish_speed_run, autocvar_g_monster_fish_speed_walk, 10, fish_anim_swim, fish_anim_swim, fish_anim_swim);
}
-void fish_attack ()
+float fish_attack ()
{
monsters_setframe(fish_anim_attack);
self.attack_finished_single = time + 0.5;
monster_melee(self.enemy, autocvar_g_monster_fish_damage, 0.1, DEATH_MONSTER_FISH, FALSE);
+
+ return TRUE;
}
void fish_die ()
}
float hknight_type;
-void hknight_melee ()
+float hknight_melee ()
{
hknight_type += 1;
hellknight_weapon_attack();
hknight_type = 0;
}
+
+ return TRUE;
}
float hknight_magic ()
monster_move(autocvar_g_monster_knight_speed_run, autocvar_g_monster_knight_speed_walk, 50, knight_anim_run, knight_anim_walk, knight_anim_stand);
}
-void knight_attack ()
+float knight_attack ()
{
float len = vlen(self.velocity);
self.attack_finished_single = time + 1.25;
monster_melee(self.enemy, autocvar_g_monster_knight_melee_damage, 0.3, DEATH_MONSTER_KNIGHT, FALSE);
+
+ return TRUE;
}
void knight_die ()
}
}
-void ogre_melee()
+float ogre_melee()
{
self.ogre_cycles = 0;
ogre_swing();
+ return TRUE;
}
void ogre_die()
self.monster_delayedattack = func_null;
}
-void shalrath_attack_melee()
+float shalrath_attack_melee()
{
self.monster_delayedattack = shalrathattack_melee;
self.delay = time + 0.2;
monsters_setframe(shalrath_anim_attack);
self.attack_finished_single = time + autocvar_g_monster_shalrath_attack_melee_delay;
+
+ return TRUE;
}
void shalrath_grenade_explode()
}
}
-void sham_melee ()
+float sham_melee ()
{
local float chance = random();
shambler_swing_right ();
else
shambler_swing_left ();
+
+ return TRUE;
}
void CastLightning ()
--- /dev/null
+// size
+const vector SLIME_MIN = '-16 -16 -24';
+const vector SLIME_MAX = '16 16 16';
+
+// model
+string SLIME_MODEL = "models/monsters/slime.dpm";
+
+#ifdef SVQC
+// cvars
+float autocvar_g_monster_slime;
+float autocvar_g_monster_slime_health;
+float autocvar_g_monster_slime_speed_walk;
+float autocvar_g_monster_slime_speed_run;
+
+// animations
+const float slime_anim_walk = 0;
+const float slime_anim_idle = 1;
+const float slime_anim_jump = 2;
+const float slime_anim_fly = 3;
+const float slime_anim_die = 4;
+const float slime_anim_pain = 5;
+
+void() slime_dead;
+
+void slime_think()
+{
+ self.think = slime_think;
+ self.nextthink = time + self.ticrate;
+
+ monster_move(autocvar_g_monster_slime_speed_run, autocvar_g_monster_slime_speed_walk, 20, slime_anim_walk, slime_anim_walk, slime_anim_idle);
+}
+
+void slime_touch_jump()
+{
+ if(self.health > 0)
+ if(other.health > 0)
+ if(other.takedamage)
+ if(vlen(self.velocity) > 200)
+ {
+ slime_dead();
+
+ return;
+ }
+
+ if (trace_dphitcontents)
+ {
+ self.touch = MonsterTouch;
+ self.movetype = MOVETYPE_WALK;
+ }
+}
+
+float slime_attack()
+{
+ makevectors(self.angles);
+ if(monster_leap(slime_anim_jump, slime_touch_jump, v_forward * 600 + '0 0 200', 0.5))
+ return TRUE;
+
+ return FALSE;
+}
+
+void slime_explode()
+{
+ RadiusDamage(self, self, 250 * monster_skill, 15, 250 * (monster_skill * 0.7), world, 250, DEATH_MONSTER_SLIME, world);
+ pointparticles(particleeffectnum("explosion_medium"), self.origin, '0 0 0', 1);
+ sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
+
+ Monster_CheckDropCvars ("slime"); // drop items after exploding to prevent player picking up item before dying
+
+ setmodel(self, "");
+}
+
+void slime_dead()
+{
+ self.health = -100; // gibbed
+ slime_explode();
+
+ self.think = Monster_Fade;
+ self.nextthink = time;
+
+ monster_hook_death();
+
+ self.event_damage = func_null; // reset by monster_hook_death
+ self.takedamage = DAMAGE_NO;
+}
+
+void slime_die()
+{
+ self.think = slime_dead;
+ self.nextthink = time;
+ self.event_damage = func_null;
+ self.movetype = MOVETYPE_NONE;
+ self.enemy = world;
+ self.health = 0;
+
+ self.SendFlags |= MSF_MOVE | MSF_STATUS;
+}
+
+void slime_spawn()
+{
+ if not(self.health)
+ self.health = autocvar_g_monster_slime_health;
+
+ self.damageforcescale = 0.003;
+ self.classname = "monster_slime";
+ self.checkattack = GenericCheckAttack;
+ self.attack_ranged = slime_attack;
+ self.attack_melee = self.attack_ranged;
+ self.nextthink = time + random() * 0.5 + 0.1;
+ self.think = slime_think;
+
+ monsters_setframe(slime_anim_idle);
+
+ monster_setupsounds("slime");
+
+ monster_hook_spawn(); // for post-spawn mods
+}
+
+void spawnfunc_monster_slime()
+{
+ if not(autocvar_g_monster_slime) { remove(self); return; }
+
+ self.monster_spawnfunc = spawnfunc_monster_slime;
+
+ if(Monster_CheckAppearFlags(self))
+ return;
+
+ if not (monster_initialize(
+ "Slime", MONSTER_SLIME,
+ SLIME_MIN, SLIME_MAX,
+ FALSE,
+ slime_die, slime_spawn))
+ {
+ remove(self);
+ return;
+ }
+}
+
+// compatibility with old spawns
+void spawnfunc_monster_tarbaby() { spawnfunc_monster_slime(); }
+
+#endif // SVQC
}
}
-void soldier_melee ()
+float soldier_melee ()
{
monsters_setframe(soldier_anim_shoot);
self.attack_finished_single = time + 0.8;
monster_melee(self.enemy, autocvar_g_monster_soldier_melee_damage, 0.3, DEATH_MONSTER_MARINE_SLAP, TRUE);
+
+ return TRUE;
}
void soldier_die()
const float SPIDER_TYPE_ICE = 0;
const float SPIDER_TYPE_FIRE = 1;
-void spider_attack_standing()
+float spider_attack_standing()
{
monster_melee(self.enemy, autocvar_g_monster_spider_attack_stand_damage, 0.3, DEATH_MONSTER_SPIDER, TRUE);
monsters_setframe((random() > 0.5) ? spider_anim_attack : spider_anim_attack2);
self.attack_finished_single = time + autocvar_g_monster_spider_attack_stand_delay;
+
+ return TRUE;
}
void spider_web_explode ()
+++ /dev/null
-// size
-const vector TARBABY_MIN = '-16 -16 -24';
-const vector TARBABY_MAX = '16 16 16';
-
-// model
-string TARBABY_MODEL = "models/monsters/slime.dpm";
-
-#ifdef SVQC
-// cvars
-float autocvar_g_monster_tarbaby;
-float autocvar_g_monster_tarbaby_health;
-float autocvar_g_monster_tarbaby_speed_walk;
-float autocvar_g_monster_tarbaby_speed_run;
-
-// animations
-const float tarbaby_anim_walk = 0;
-const float tarbaby_anim_idle = 1;
-const float tarbaby_anim_jump = 2;
-const float tarbaby_anim_fly = 3;
-const float tarbaby_anim_die = 4;
-const float tarbaby_anim_pain = 5;
-
-void tarbaby_think ()
-{
- self.think = tarbaby_think;
- self.nextthink = time + self.ticrate;
-
- monster_move(autocvar_g_monster_tarbaby_speed_run, autocvar_g_monster_tarbaby_speed_walk, 20, tarbaby_anim_walk, tarbaby_anim_walk, tarbaby_anim_idle);
-}
-
-void Tar_JumpTouch ()
-{
- if(self.health > 0)
- if(other.health > 0)
- if(other.takedamage)
- if(vlen(self.velocity) > 200)
- {
- // make the monster die
- self.event_damage(self, self, self.health + self.max_health + 200, DEATH_MONSTER_TARBABY, self.origin, '0 0 0');
-
- return;
- }
-
- if (trace_dphitcontents)
- {
- self.touch = MonsterTouch;
- self.movetype = MOVETYPE_WALK;
- }
-}
-
-void tarbaby_jump ()
-{
- self.movetype = MOVETYPE_BOUNCE;
- makevectors(self.angles);
- monster_leap(tarbaby_anim_jump, Tar_JumpTouch, v_forward * 600 + '0 0 200', 0.5);
-}
-
-float tbaby_jump ()
-{
- tarbaby_jump();
- return TRUE;
-}
-
-void tarbaby_blowup ()
-{
- RadiusDamage(self, self, 250 * monster_skill, 15, 250 * (monster_skill * 0.7), world, 250, DEATH_MONSTER_TARBABY, world);
- pointparticles(particleeffectnum("explosion_medium"), self.origin, '0 0 0', 1);
- sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
-
- Monster_CheckDropCvars ("tarbaby"); // drop items after exploding to prevent player picking up item before dying
-
- setmodel(self, "");
-}
-
-void tarbaby_explode()
-{
- tarbaby_blowup();
-
- self.think = Monster_Fade;
- self.nextthink = time + 0.1;
-
- monster_hook_death();
-
- self.event_damage = func_null; // reset by monster_hook_death
- self.takedamage = DAMAGE_NO;
-}
-
-void tarbaby_die ()
-{
- self.think = tarbaby_explode;
- self.nextthink = time + 0.1;
- self.event_damage = func_null;
- self.movetype = MOVETYPE_NONE;
- self.enemy = world;
- self.health = 0;
-
- WaypointSprite_Kill(self.sprite);
-
- self.SendFlags |= MSF_MOVE | MSF_STATUS;
-}
-
-void tarbaby_spawn ()
-{
- if not(self.health)
- self.health = autocvar_g_monster_tarbaby_health;
-
- self.damageforcescale = 0.003;
- self.classname = "monster_tarbaby";
- self.checkattack = GenericCheckAttack;
- self.attack_ranged = tbaby_jump;
- self.attack_melee = tarbaby_jump;
- self.nextthink = time + random() * 0.5 + 0.1;
- self.think = tarbaby_think;
-
- monsters_setframe(tarbaby_anim_idle);
-
- monster_setupsounds("tarbaby");
-
- monster_hook_spawn(); // for post-spawn mods
-}
-
-void spawnfunc_monster_tarbaby ()
-{
- if not(autocvar_g_monster_tarbaby) { remove(self); return; }
-
- self.monster_spawnfunc = spawnfunc_monster_tarbaby;
-
- if(Monster_CheckAppearFlags(self))
- return;
-
- if not (monster_initialize(
- "Slime", MONSTER_TARBABY,
- TARBABY_MIN, TARBABY_MAX,
- FALSE,
- tarbaby_die, tarbaby_spawn))
- {
- remove(self);
- return;
- }
-}
-
-#endif // SVQC
const float zombie_anim_runforwardright = 29;
const float zombie_anim_spawn = 30;
-void zombie_attack_standing()
+float zombie_attack_standing()
{
float rand = random(), chosen_anim;
self.attack_finished_single = time + autocvar_g_monster_zombie_attack_stand_delay;
monster_melee(self.enemy, autocvar_g_monster_zombie_attack_stand_damage, 0.3, DEATH_MONSTER_ZOMBIE_MELEE, TRUE);
+
+ return TRUE;
}
void zombie_attack_leap_touch ()
#include "monster/soldier.qc"
#include "monster/wizard.qc"
#include "monster/dog.qc"
-#include "monster/tarbaby.qc"
+#include "monster/slime.qc"
#include "monster/hknight.qc"
#include "monster/fish.qc"
#include "monster/shalrath.qc"
case MONSTER_MARINE:
case MONSTER_ZOMBIE:
case MONSTER_SPIDER:
- case MONSTER_TARBABY:
+ case MONSTER_SLIME:
case MONSTER_DOG:
case MONSTER_SCRAG:
case MONSTER_FISH:
case MONSTER_MARINE: return "marine";
case MONSTER_SCRAG: return "scrag";
case MONSTER_DOG: return "dog";
- case MONSTER_TARBABY: return "tarbaby";
+ case MONSTER_SLIME: return "slime";
case MONSTER_HELLKNIGHT: return "hellknight";
case MONSTER_FISH: return "fish";
case MONSTER_MAGE: return "mage";
case MONSTER_MARINE:
case MONSTER_ZOMBIE:
case MONSTER_SPIDER:
- case MONSTER_TARBABY:
+ case MONSTER_SLIME:
case MONSTER_DOG:
case MONSTER_OGRE:
case MONSTER_SHAMBLER:
if(n_dogs) RandomSelection_Add(world, MONSTER_DOG, "", 1, 1);
if(n_knights) RandomSelection_Add(world, MONSTER_KNIGHT, "", 1, 1);
if(n_shamblers) RandomSelection_Add(world, MONSTER_SHAMBLER, "", 0.2, 0.2);
- if(n_tarbabies) RandomSelection_Add(world, MONSTER_TARBABY, "", 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_fish && waterspawns_count) RandomSelection_Add(world, MONSTER_FISH, "", 0.2, 0.2);
void queue_monsters(float maxmonsters)
{
- float mc = 10; // note: shambler + tarbaby = 1
+ float mc = 10; // note: shambler + slime = 1
if(waterspawns_count > 0)
mc += 1;
n_hknights = DistributeEvenly_Get(1);
n_zombies = DistributeEvenly_Get(1);
n_spiders = DistributeEvenly_Get(1);
- n_tarbabies = DistributeEvenly_Get(0.7);
+ n_slimes = DistributeEvenly_Get(0.7);
n_shamblers = DistributeEvenly_Get(0.3);
if(flyspawns_count > 0)
n_wizards = DistributeEvenly_Get(1);
case MONSTER_MARINE: n_soldiers -= 1; break;
case MONSTER_SCRAG: n_wizards -= 1; break;
case MONSTER_DOG: n_dogs -= 1; break;
- case MONSTER_TARBABY: n_tarbabies -= 1; break;
+ case MONSTER_SLIME: n_slimes -= 1; break;
case MONSTER_HELLKNIGHT: n_hknights -= 1; break;
case MONSTER_FISH: n_fish -= 1; break;
case MONSTER_MAGE: n_shalraths -= 1; break;
// Counters
float monster_count, totalmonsters;
-float n_knights, n_dogs, n_ogres, n_shamblers, n_wizards, n_shalraths, n_soldiers, n_hknights, n_demons, n_zombies, n_tarbabies, n_fish, n_spiders;
+float n_knights, 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 current_monsters;
float waterspawns_count, flyspawns_count;
float wave_count, max_waves;