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 animus shambler bruiser marine wyvern dog slime hellknight fish mage zombie spider" "monsters not listed here will spawn as bruisers"
+set g_monsters_spawn_list "ogre animus shambler bruiser marine wyvern dog slime knight fish mage zombie spider" "monsters not listed here will spawn as bruisers"
// Ogre
set g_monster_ogre 1 "Enable Ogres"
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"
-set g_monster_hellknight_health 250 "Hell-Knight health"
-set g_monster_hellknight_drop armor "Hell-Knight drops this item on death"
-set g_monster_hellknight_drop_size medium "Size of the item Hell-Knights drop. Possible values are: small, medium, large"
-set g_monster_hellknight_inferno_damage 40 "Hell-Knight inferno damage"
-set g_monster_hellknight_inferno_chance 0.4 "Hell-Knight inferno attack chance"
-set g_monster_hellknight_inferno_damagetime 3 "How long the inferno should burn the player"
-set g_monster_hellknight_fireball_damage 30 "Hell-Knight fireball projectile damage"
-set g_monster_hellknight_fireball_edgedamage 10 "Hell-Knight fireball indirect hit damage"
-set g_monster_hellknight_fireball_force 50 "Hell-Knight fireball projectile push force"
-set g_monster_hellknight_fireball_radius 70 "Hell-Knight fireball projectile damage radius"
-set g_monster_hellknight_fireball_speed 600 "Hell-Knight fireball projectile speed"
-set g_monster_hellknight_fireball_spread 0 "Hell-Knight fireball projectile spread"
-set g_monster_hellknight_fireball_chance 0.3 "Chance for Hell-Knight to throw a fireball"
-set g_monster_hellknight_jump_chance 0.2 "Chance for Hell-Knight to jump at the player (always 1 if enemy is further than _dist)"
-set g_monster_hellknight_jump_damage 25 "Hell-Knight jump attack damage"
-set g_monster_hellknight_jump_dist 500 "Hell-Knight will prioritise jumping if the enemy is this far away"
-set g_monster_hellknight_melee_damage 20 "Hell-Knight melee attack damage"
-set g_monster_hellknight_spike_damage 5 "Hell-Knight spike projectile damage"
-set g_monster_hellknight_spike_edgedamage 5 "Hell-Knight spike projectile indirect hit damage"
-set g_monster_hellknight_spike_radius 20 "Hell-Knight spike projectile damage radius"
-set g_monster_hellknight_spike_force 5 "Hell-Knight spike projectile force"
-set g_monster_hellknight_spike_chance 0.5 "Hell-Knight spike attack chance"
-set g_monster_hellknight_speed_walk 75 "Hell-Knight walk speed"
-set g_monster_hellknight_speed_run 150 "Hell-Knight run speed"
+// Knight
+set g_monster_knight 1 "Enable Knights"
+set g_monster_knight_health 250 "Knight health"
+set g_monster_knight_drop armor "Knight drops this item on death"
+set g_monster_knight_drop_size medium "Size of the item Knights drop. Possible values are: small, medium, large"
+set g_monster_knight_inferno_damage 40 "Knight inferno damage"
+set g_monster_knight_inferno_chance 0.4 "Knight inferno attack chance"
+set g_monster_knight_inferno_damagetime 3 "How long the inferno should burn the player"
+set g_monster_knight_fireball_damage 30 "Knight fireball projectile damage"
+set g_monster_knight_fireball_edgedamage 10 "Knight fireball indirect hit damage"
+set g_monster_knight_fireball_force 50 "Knight fireball projectile push force"
+set g_monster_knight_fireball_radius 70 "Knight fireball projectile damage radius"
+set g_monster_knight_fireball_speed 600 "Knight fireball projectile speed"
+set g_monster_knight_fireball_spread 0 "Knight fireball projectile spread"
+set g_monster_knight_fireball_chance 0.3 "Chance for Knight to throw a fireball"
+set g_monster_knight_jump_chance 0.2 "Chance for Knight to jump at the player (always 1 if enemy is further than _dist)"
+set g_monster_knight_jump_damage 25 "Knight jump attack damage"
+set g_monster_knight_jump_dist 500 "Knight will prioritise jumping if the enemy is this far away"
+set g_monster_knight_melee_damage 20 "Knight melee attack damage"
+set g_monster_knight_spike_damage 5 "Knight spike projectile damage"
+set g_monster_knight_spike_edgedamage 5 "Knight spike projectile indirect hit damage"
+set g_monster_knight_spike_radius 20 "Knight spike projectile damage radius"
+set g_monster_knight_spike_force 5 "Knight spike projectile force"
+set g_monster_knight_spike_chance 0.5 "Knight spike attack chance"
+set g_monster_knight_speed_walk 75 "Knight walk speed"
+set g_monster_knight_speed_run 150 "Knight run speed"
// Rotfish
set g_monster_fish 1 "Enable Rotfish"
precache_sound("weapons/rocket_impact.wav");
break;
}
- case MONSTER_HELLKNIGHT:
+ case MONSTER_KNIGHT:
{
- precache_model(HELLKNIGHT_MODEL);
+ precache_model(KNIGHT_MODEL);
break;
}
case MONSTER_FISH:
mid2info_max = SLIME_MAX;
break;
}
- case MONSTER_HELLKNIGHT:
+ case MONSTER_KNIGHT:
{
- mid2info_model = HELLKNIGHT_MODEL;
- mid2info_name = "Hell-Knight";
- mid2info_min = HELLKNIGHT_MIN;
- mid2info_max = HELLKNIGHT_MAX;
+ mid2info_model = KNIGHT_MODEL;
+ mid2info_name = "Knight";
+ mid2info_min = KNIGHT_MIN;
+ mid2info_max = KNIGHT_MAX;
if(self) self.scale = 1.3;
break;
}
DEATHTYPE(DEATH_MONSTER_DOG_JUMP, DEATH_SELF_MON_DOG_JUMP, NO_MSG, NORMAL_POS) \
DEATHTYPE(DEATH_MONSTER_ANIMUS, DEATH_SELF_MON_ANIMUS, NO_MSG, NORMAL_POS) \
DEATHTYPE(DEATH_MONSTER_FISH, DEATH_SELF_MON_FISH, NO_MSG, NORMAL_POS) \
- DEATHTYPE(DEATH_MONSTER_HKNIGHT_CRUSH, DEATH_SELF_MON_HKNIGHT_CRUSH, NO_MSG, NORMAL_POS) \
- DEATHTYPE(DEATH_MONSTER_HKNIGHT_FBALL, DEATH_SELF_MON_HKNIGHT_FBALL, NO_MSG, NORMAL_POS) \
- DEATHTYPE(DEATH_MONSTER_HKNIGHT_INFERNO,DEATH_SELF_MON_HKNIGHT_INFERNO, NO_MSG, NORMAL_POS) \
- DEATHTYPE(DEATH_MONSTER_HKNIGHT_MELEE, DEATH_SELF_MON_HKNIGHT_MELEE, NO_MSG, NORMAL_POS) \
- DEATHTYPE(DEATH_MONSTER_HKNIGHT_SPIKE, DEATH_SELF_MON_HKNIGHT_SPIKE, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_MONSTER_KNIGHT_CRUSH, DEATH_SELF_MON_KNIGHT_CRUSH, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_MONSTER_KNIGHT_FBALL, DEATH_SELF_MON_KNIGHT_FBALL, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_MONSTER_KNIGHT_INFERNO, DEATH_SELF_MON_KNIGHT_INFERNO, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_MONSTER_KNIGHT_MELEE, DEATH_SELF_MON_KNIGHT_MELEE, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_MONSTER_KNIGHT_SPIKE, DEATH_SELF_MON_KNIGHT_SPIKE, NO_MSG, NORMAL_POS) \
DEATHTYPE(DEATH_MONSTER_BRUISER, DEATH_SELF_MON_BRUISER, NO_MSG, NORMAL_POS) \
DEATHTYPE(DEATH_MONSTER_OGRE_CHAINSAW, DEATH_SELF_MON_OGRE_CHAINSAW, NO_MSG, NORMAL_POS) \
DEATHTYPE(DEATH_MONSTER_OGRE_GRENADE, DEATH_SELF_MON_OGRE_GRENADE, NO_MSG, NORMAL_POS) \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_DOG_JUMP, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 didn't see the pouncing Rottweiler%s%s\n"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_ANIMUS, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was eviscerated by an Animus%s%s\n"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_FISH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was fed to the Rotfish%s%s\n"), "") \
- MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_HKNIGHT_CRUSH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was crushed by a pouncing Hell-Knight%s%s\n"), "") \
- MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_HKNIGHT_FBALL, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was turned to ash by a Hell-Knight%s%s\n"), "") \
- MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_HKNIGHT_INFERNO, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was burned to death by a Hell-Knight%s%s\n"), "") \
- MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_HKNIGHT_MELEE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was slain by a Hell-Knight%s%s\n"), "") \
- MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_HKNIGHT_SPIKE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was cursed by a Hell-Knight%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_KNIGHT_CRUSH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was crushed by a pouncing Knight%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_KNIGHT_FBALL, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was turned to ash by a Knight%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_KNIGHT_INFERNO, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was burned to death by a Knight%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_KNIGHT_MELEE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was slain by a Knight%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_KNIGHT_SPIKE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was cursed by a Knight%s%s\n"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_BRUISER, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was beaten in a fistfight by a Bruiser%s%s\n"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_OGRE_CHAINSAW, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was cut down by an Ogre%s%s\n"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_OGRE_GRENADE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 almost dodged the Ogre grenade%s%s\n"), "") \
MSG_MULTI_NOTIF(1, DEATH_SELF_MON_DOG_JUMP, NO_MSG, INFO_DEATH_SELF_MON_DOG_JUMP, CENTER_DEATH_SELF_MONSTER) \
MSG_MULTI_NOTIF(1, DEATH_SELF_MON_ANIMUS, NO_MSG, INFO_DEATH_SELF_MON_ANIMUS, CENTER_DEATH_SELF_MONSTER) \
MSG_MULTI_NOTIF(1, DEATH_SELF_MON_FISH, NO_MSG, INFO_DEATH_SELF_MON_FISH, CENTER_DEATH_SELF_MONSTER) \
- MSG_MULTI_NOTIF(1, DEATH_SELF_MON_HKNIGHT_CRUSH, NO_MSG, INFO_DEATH_SELF_MON_HKNIGHT_CRUSH, CENTER_DEATH_SELF_MONSTER) \
- MSG_MULTI_NOTIF(1, DEATH_SELF_MON_HKNIGHT_FBALL, NO_MSG, INFO_DEATH_SELF_MON_HKNIGHT_FBALL, CENTER_DEATH_SELF_MONSTER) \
- MSG_MULTI_NOTIF(1, DEATH_SELF_MON_HKNIGHT_INFERNO, NO_MSG, INFO_DEATH_SELF_MON_HKNIGHT_INFERNO, CENTER_DEATH_SELF_MONSTER) \
- MSG_MULTI_NOTIF(1, DEATH_SELF_MON_HKNIGHT_MELEE, NO_MSG, INFO_DEATH_SELF_MON_HKNIGHT_MELEE, CENTER_DEATH_SELF_MONSTER) \
- MSG_MULTI_NOTIF(1, DEATH_SELF_MON_HKNIGHT_SPIKE, NO_MSG, INFO_DEATH_SELF_MON_HKNIGHT_SPIKE, CENTER_DEATH_SELF_MONSTER) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_MON_KNIGHT_CRUSH, NO_MSG, INFO_DEATH_SELF_MON_KNIGHT_CRUSH, CENTER_DEATH_SELF_MONSTER) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_MON_KNIGHT_FBALL, NO_MSG, INFO_DEATH_SELF_MON_KNIGHT_FBALL, CENTER_DEATH_SELF_MONSTER) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_MON_KNIGHT_INFERNO, NO_MSG, INFO_DEATH_SELF_MON_KNIGHT_INFERNO, CENTER_DEATH_SELF_MONSTER) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_MON_KNIGHT_MELEE, NO_MSG, INFO_DEATH_SELF_MON_KNIGHT_MELEE, CENTER_DEATH_SELF_MONSTER) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_MON_KNIGHT_SPIKE, NO_MSG, INFO_DEATH_SELF_MON_KNIGHT_SPIKE, CENTER_DEATH_SELF_MONSTER) \
MSG_MULTI_NOTIF(1, DEATH_SELF_MON_BRUISER, NO_MSG, INFO_DEATH_SELF_MON_BRUISER, CENTER_DEATH_SELF_MONSTER) \
MSG_MULTI_NOTIF(1, DEATH_SELF_MON_OGRE_CHAINSAW, NO_MSG, INFO_DEATH_SELF_MON_OGRE_CHAINSAW, CENTER_DEATH_SELF_MONSTER) \
MSG_MULTI_NOTIF(1, DEATH_SELF_MON_OGRE_GRENADE, NO_MSG, INFO_DEATH_SELF_MON_OGRE_GRENADE, CENTER_DEATH_SELF_MONSTER) \
me.TD(me, 1, 0.4, e = makeXonoticRadioButton(2, "menu_monsters_edit_spawn", "animus", _("Animus")));
me.TD(me, 1, 0.4, e = makeXonoticRadioButton(2, "menu_monsters_edit_spawn", "spider", _("Spider")));
me.TD(me, 1, 0.4, e = makeXonoticRadioButton(2, "menu_monsters_edit_spawn", "bruiser", _("Bruiser")));
- me.TD(me, 1, 0.4, e = makeXonoticRadioButton(2, "menu_monsters_edit_spawn", "hellknight", _("Hell-Knight")));
+ me.TD(me, 1, 0.4, e = makeXonoticRadioButton(2, "menu_monsters_edit_spawn", "knight", _("Knight")));
me.TD(me, 1, 0.4, e = makeXonoticRadioButton(2, "menu_monsters_edit_spawn", "shambler", _("Shambler")));
me.TD(me, 1, 0.4, e = makeXonoticRadioButton(2, "menu_monsters_edit_spawn", "soldier", _("Marine")));
me.TR(me);
float MONSTER_WYVERN = 8;
float MONSTER_DOG = 9;
float MONSTER_SLIME = 10;
-float MONSTER_HELLKNIGHT = 11;
+float MONSTER_KNIGHT = 11;
float MONSTER_FISH = 12;
float MONSTER_MAGE = 13;
float MONSTER_SPIDER = 14;
+++ /dev/null
-// size
-const vector HELLKNIGHT_MIN = '-20 -20 -32';
-const vector HELLKNIGHT_MAX = '20 20 41';
-
-// model
-string HELLKNIGHT_MODEL = "models/monsters/hknight.mdl";
-
-#ifdef SVQC
-// cvars
-float autocvar_g_monster_hellknight;
-float autocvar_g_monster_hellknight_health;
-float autocvar_g_monster_hellknight_melee_damage;
-float autocvar_g_monster_hellknight_inferno_damage;
-float autocvar_g_monster_hellknight_inferno_damagetime;
-float autocvar_g_monster_hellknight_inferno_chance;
-float autocvar_g_monster_hellknight_speed_walk;
-float autocvar_g_monster_hellknight_speed_run;
-float autocvar_g_monster_hellknight_fireball_damage;
-float autocvar_g_monster_hellknight_fireball_force;
-float autocvar_g_monster_hellknight_fireball_radius;
-float autocvar_g_monster_hellknight_fireball_chance;
-float autocvar_g_monster_hellknight_fireball_edgedamage;
-float autocvar_g_monster_hellknight_spike_chance;
-float autocvar_g_monster_hellknight_spike_force;
-float autocvar_g_monster_hellknight_spike_radius;
-float autocvar_g_monster_hellknight_spike_edgedamage;
-float autocvar_g_monster_hellknight_spike_damage;
-float autocvar_g_monster_hellknight_jump_chance;
-float autocvar_g_monster_hellknight_jump_damage;
-float autocvar_g_monster_hellknight_jump_dist;
-
-// animations
-const float hellknight_anim_stand = 0;
-const float hellknight_anim_walk = 1;
-const float hellknight_anim_run = 2;
-const float hellknight_anim_pain = 3;
-const float hellknight_anim_death1 = 4;
-const float hellknight_anim_death2 = 5;
-const float hellknight_anim_charge1 = 6;
-const float hellknight_anim_magic1 = 7;
-const float hellknight_anim_magic2 = 8;
-const float hellknight_anim_charge2 = 9;
-const float hellknight_anim_slice = 10;
-const float hellknight_anim_smash = 11;
-const float hellknight_anim_wattack = 12;
-const float hellknight_anim_magic3 = 13;
-
-void hellknight_think()
-{
- self.think = hellknight_think;
- self.nextthink = time + self.ticrate;
-
- monster_move(autocvar_g_monster_hellknight_speed_run, autocvar_g_monster_hellknight_speed_walk, 100, hellknight_anim_run, hellknight_anim_walk, hellknight_anim_stand);
-}
-
-void hknight_spike_think()
-{
- if(self)
- {
- RadiusDamage (self, self.realowner, autocvar_g_monster_hellknight_spike_damage, autocvar_g_monster_hellknight_spike_edgedamage, autocvar_g_monster_hellknight_spike_force, world, autocvar_g_monster_hellknight_spike_radius, DEATH_MONSTER_HKNIGHT_SPIKE, other);
- remove(self);
- }
-}
-
-void hknight_spike_touch()
-{
- PROJECTILE_TOUCH;
-
- pointparticles(particleeffectnum("TE_WIZSPIKE"), self.origin, '0 0 0', 1);
-
- hknight_spike_think();
-}
-
-void() hellknight_think;
-void hknight_shoot ()
-{
- local entity missile = world;
- local vector dir = normalize((self.enemy.origin + '0 0 10') - self.origin);
- local float dist = vlen (self.enemy.origin - self.origin), flytime = 0;
-
- flytime = dist * 0.002;
- if (flytime < 0.1)
- flytime = 0.1;
-
- self.effects |= EF_MUZZLEFLASH;
-
- missile = spawn ();
- missile.owner = missile.realowner = self;
- missile.solid = SOLID_TRIGGER;
- missile.movetype = MOVETYPE_FLYMISSILE;
- setsize (missile, '0 0 0', '0 0 0');
- setorigin(missile, self.origin + '0 0 10' + v_forward * 14);
- missile.scale = self.scale;
- missile.flags = FL_PROJECTILE;
- missile.velocity = dir * 400;
- missile.avelocity = '300 300 300';
- missile.nextthink = time + 5;
- missile.think = hknight_spike_think;
- missile.enemy = self.enemy;
- missile.touch = hknight_spike_touch;
- CSQCProjectile(missile, TRUE, PROJECTILE_CRYLINK, TRUE);
-}
-
-void hknight_inferno ()
-{
- traceline((self.absmin + self.absmax) * 0.5, (self.enemy.absmin + self.enemy.absmax) * 0.5, TRUE, world);
- if (trace_fraction != 1)
- return; // not visible
- if(vlen(self.enemy.origin - self.origin) <= 2000)
- Fire_AddDamage(self.enemy, self, autocvar_g_monster_hellknight_inferno_damage * monster_skill, autocvar_g_monster_hellknight_inferno_damagetime, DEATH_MONSTER_HKNIGHT_INFERNO);
-}
-
-void hknight_infernowarning ()
-{
- self.monster_delayedattack = func_null;
- self.delay = -1;
- if(!self.enemy)
- return;
-
- traceline((self.absmin + self.absmax) * 0.5, (self.enemy.absmin + self.enemy.absmax) * 0.5, TRUE, world);
- if (trace_fraction != 1)
- return; // not visible
- self.enemy.effects |= EF_MUZZLEFLASH;
- sound(self.enemy, CHAN_AUTO, "player/lava.wav", 1, ATTN_NORM);
-
- hknight_inferno();
-}
-
-.float hknight_cycles;
-void hellknight_magic ()
-{
- self.monster_delayedattack = hknight_infernowarning;
- self.delay = time + 0.5;
- self.attack_finished_single = time + 1.2;
-}
-
-void hknight_fireball_explode(entity targ)
-{
- if(self)
- {
- RadiusDamage (self, self.realowner, autocvar_g_monster_hellknight_fireball_damage, autocvar_g_monster_hellknight_fireball_edgedamage, autocvar_g_monster_hellknight_fireball_force, world, autocvar_g_monster_hellknight_fireball_radius, self.projectiledeathtype, targ);
- if(targ)
- Fire_AddDamage(targ, self, 5 * monster_skill, autocvar_g_monster_hellknight_inferno_damagetime, self.projectiledeathtype);
- remove(self);
- }
-}
-
-void hknight_fireball_think()
-{
- hknight_fireball_explode(world);
-}
-
-void hknight_fireball_touch()
-{
- PROJECTILE_TOUCH;
-
- hknight_fireball_explode(other);
-}
-
-void hellknight_fireball ()
-{
- local entity missile = spawn();
- local vector dir = normalize((self.enemy.origin + '0 0 10') - self.origin);
- vector fmins = '-4 -4 -4', fmaxs = '4 4 4';
-
- self.effects |= EF_MUZZLEFLASH;
- sound (self, CHAN_WEAPON, "weapons/fireball2.wav", 1, ATTN_NORM);
-
- missile.owner = missile.realowner = self;
- missile.solid = SOLID_TRIGGER;
- missile.movetype = MOVETYPE_FLYMISSILE;
- missile.projectiledeathtype = DEATH_MONSTER_HKNIGHT_FBALL;
- setsize (missile, fmins, fmaxs);
- setorigin(missile, self.origin + '0 0 10' + v_forward * 14);
- missile.flags = FL_PROJECTILE;
- missile.velocity = dir * 400;
- missile.avelocity = '300 300 300';
- missile.nextthink = time + 5;
- missile.think = hknight_fireball_think;
- missile.enemy = self.enemy;
- missile.touch = hknight_fireball_touch;
- CSQCProjectile(missile, TRUE, PROJECTILE_FIREMINE, TRUE);
-
- self.delay = -1;
-}
-
-void hellknight_magic2 ()
-{
- monsters_setframe(hellknight_anim_magic2);
- self.attack_finished_single = time + 1.2;
- self.delay = time + 0.4;
- self.monster_delayedattack = hellknight_fireball;
-}
-
-void hellknight_spikes ()
-{
- self.monster_delayedattack = hellknight_spikes;
- self.delay = time + 0.1;
- self.hknight_cycles += 1;
- hknight_shoot();
- if(self.hknight_cycles >= 7)
- {
- self.monster_delayedattack = func_null;
- self.delay = -1;
- }
-}
-
-void hellknight_magic3 ()
-{
- monsters_setframe(hellknight_anim_magic3);
- self.attack_finished_single = time + 1.1;
- self.monster_delayedattack = hellknight_spikes;
- self.delay = time + 0.4;
-}
-
-float hknight_magic()
-{
- if not(self.flags & FL_ONGROUND)
- return FALSE;
-
- if not(self.enemy)
- return FALSE; // calling attack check with no enemy?!
-
- if(time < self.attack_finished_single)
- return FALSE;
-
- self.hknight_cycles = 0;
-
- if (self.enemy.monsterid == MONSTER_ZOMBIE)
- {
- // always use fireball to kill zombies
- hellknight_magic2();
- self.attack_finished_single = time + 2;
- return TRUE;
- }
- RandomSelection_Init();
- RandomSelection_Add(world, 0, "fireball", autocvar_g_monster_hellknight_fireball_chance, 1);
- RandomSelection_Add(world, 0, "inferno", autocvar_g_monster_hellknight_inferno_chance, 1);
- RandomSelection_Add(world, 0, "spikes", autocvar_g_monster_hellknight_spike_chance, 1);
- if(self.health >= 100)
- RandomSelection_Add(world, 0, "jump", ((vlen(self.enemy.origin - self.origin) > autocvar_g_monster_hellknight_jump_dist) ? 1 : autocvar_g_monster_hellknight_jump_chance), 1);
-
- switch(RandomSelection_chosen_string)
- {
- case "fireball":
- {
- hellknight_magic2();
- self.attack_finished_single = time + 2;
- return TRUE;
- }
- case "spikes":
- {
- hellknight_magic3();
- self.attack_finished_single = time + 3;
- return TRUE;
- }
- case "inferno":
- {
- hellknight_magic();
- self.attack_finished_single = time + 3;
- return TRUE;
- }
- case "jump":
- {
- if (vlen(self.enemy.origin - self.origin) >= 400)
- if (findtrajectorywithleading(self.origin, self.mins, self.maxs, self.enemy, 1000, 0, 10, 0, self))
- {
- self.velocity = findtrajectory_velocity;
- Damage(self.enemy, self, self, autocvar_g_monster_hellknight_jump_damage * monster_skill, DEATH_MONSTER_HKNIGHT_CRUSH, self.enemy.origin, normalize(self.enemy.origin - self.origin));
- self.attack_finished_single = time + 2;
- return TRUE;
- }
- return FALSE;
- }
- }
-
- return FALSE;
-}
-
-float knight_attack(float attack_type)
-{
- switch(attack_type)
- {
- case MONSTER_ATTACK_MELEE:
- {
- float anim;
- if(random() < 0.3)
- anim = hellknight_anim_slice;
- else if(random() < 0.6)
- anim = hellknight_anim_smash;
- else
- anim = hellknight_anim_wattack;
-
- monsters_setframe(anim);
- self.attack_finished_single = time + 0.7;
- monster_melee(self.enemy, autocvar_g_monster_hellknight_melee_damage, 0.3, DEATH_MONSTER_HKNIGHT_MELEE, TRUE);
-
- return TRUE;
- }
- case MONSTER_ATTACK_RANGED:
- {
- if(hknight_magic())
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-void hellknight_die ()
-{
- float chance = random();
- Monster_CheckDropCvars ("hellknight");
-
- self.think = monster_dead_think;
- self.nextthink = time + self.ticrate;
- self.ltime = time + 5;
- monsters_setframe((random() > 0.5) ? hellknight_anim_death1 : hellknight_anim_death2);
-
- if(chance < 0.10 || self.flags & MONSTERFLAG_MINIBOSS)
- if(self.candrop)
- {
- self.superweapons_finished = time + autocvar_g_balance_superweapons_time + 5; // give the player a few seconds to find the weapon
- self.weapon = WEP_FIREBALL;
- }
-
- monster_hook_death(); // for post-death mods
-}
-
-void hellknight_spawn ()
-{
- if not(self.health)
- self.health = autocvar_g_monster_hellknight_health;
-
- self.damageforcescale = 0.003;
- self.classname = "monster_hellknight";
- self.monster_attackfunc = knight_attack;
- self.nextthink = time + random() * 0.5 + 0.1;
- self.think = hellknight_think;
-
- monsters_setframe(hellknight_anim_stand);
-
- monster_setupsounds("hellknight");
-
- monster_hook_spawn(); // for post-spawn mods
-}
-
-void spawnfunc_monster_hellknight ()
-{
- if not(autocvar_g_monster_hellknight) { remove(self); return; }
-
- self.monster_spawnfunc = spawnfunc_monster_hellknight;
-
- if(Monster_CheckAppearFlags(self))
- return;
-
- self.scale = 1.3;
-
- if not (monster_initialize(
- "Hell-knight", MONSTER_HELLKNIGHT,
- HELLKNIGHT_MIN, HELLKNIGHT_MAX,
- FALSE,
- hellknight_die, hellknight_spawn))
- {
- remove(self);
- return;
- }
-}
-
-// compatibility with old spawns
-void spawnfunc_monster_hell_knight() { spawnfunc_monster_hellknight(); }
-
-#endif // SVQC
--- /dev/null
+// size
+const vector KNIGHT_MIN = '-20 -20 -32';
+const vector KNIGHT_MAX = '20 20 41';
+
+// model
+string KNIGHT_MODEL = "models/monsters/hknight.mdl";
+
+#ifdef SVQC
+// cvars
+float autocvar_g_monster_knight;
+float autocvar_g_monster_knight_health;
+float autocvar_g_monster_knight_melee_damage;
+float autocvar_g_monster_knight_inferno_damage;
+float autocvar_g_monster_knight_inferno_damagetime;
+float autocvar_g_monster_knight_inferno_chance;
+float autocvar_g_monster_knight_speed_walk;
+float autocvar_g_monster_knight_speed_run;
+float autocvar_g_monster_knight_fireball_damage;
+float autocvar_g_monster_knight_fireball_force;
+float autocvar_g_monster_knight_fireball_radius;
+float autocvar_g_monster_knight_fireball_chance;
+float autocvar_g_monster_knight_fireball_edgedamage;
+float autocvar_g_monster_knight_spike_chance;
+float autocvar_g_monster_knight_spike_force;
+float autocvar_g_monster_knight_spike_radius;
+float autocvar_g_monster_knight_spike_edgedamage;
+float autocvar_g_monster_knight_spike_damage;
+float autocvar_g_monster_knight_jump_chance;
+float autocvar_g_monster_knight_jump_damage;
+float autocvar_g_monster_knight_jump_dist;
+
+// animations
+const float knight_anim_stand = 0;
+const float knight_anim_walk = 1;
+const float knight_anim_run = 2;
+const float knight_anim_pain = 3;
+const float knight_anim_death1 = 4;
+const float knight_anim_death2 = 5;
+const float knight_anim_charge1 = 6;
+const float knight_anim_magic1 = 7;
+const float knight_anim_magic2 = 8;
+const float knight_anim_charge2 = 9;
+const float knight_anim_slice = 10;
+const float knight_anim_smash = 11;
+const float knight_anim_wattack = 12;
+const float knight_anim_magic3 = 13;
+
+.float knight_cycles;
+
+void knight_think()
+{
+ self.think = knight_think;
+ self.nextthink = time + self.ticrate;
+
+ monster_move(autocvar_g_monster_knight_speed_run, autocvar_g_monster_knight_speed_walk, 100, knight_anim_run, knight_anim_walk, knight_anim_stand);
+}
+
+void knight_inferno()
+{
+ self.monster_delayedattack = func_null;
+ self.delay = -1;
+ if not(self.enemy)
+ return;
+
+ traceline((self.absmin + self.absmax) * 0.5, (self.enemy.absmin + self.enemy.absmax) * 0.5, TRUE, world);
+ if (trace_fraction != 1)
+ return; // not visible
+
+ self.enemy.effects |= EF_MUZZLEFLASH;
+ sound(self.enemy, CHAN_AUTO, "player/lava.wav", 1, ATTN_NORM);
+
+ if(vlen(self.enemy.origin - self.origin) <= 2000)
+ Fire_AddDamage(self.enemy, self, autocvar_g_monster_knight_inferno_damage * monster_skill, autocvar_g_monster_knight_inferno_damagetime, DEATH_MONSTER_KNIGHT_INFERNO);
+}
+
+void knight_fireball_explode()
+{
+ entity e;
+ if(self)
+ {
+ pointparticles(particleeffectnum("fireball_explode"), self.origin, '0 0 0', 1);
+
+ RadiusDamage(self, self.realowner, autocvar_g_monster_knight_fireball_damage, autocvar_g_monster_knight_fireball_edgedamage, autocvar_g_monster_knight_fireball_force, world, autocvar_g_monster_knight_fireball_radius, self.projectiledeathtype, world);
+
+ for(e = world; (e = findfloat(e, takedamage, DAMAGE_AIM)); ) if(vlen(e.origin - self.origin) <= autocvar_g_monster_knight_fireball_radius)
+ Fire_AddDamage(e, self, 5 * monster_skill, autocvar_g_monster_knight_inferno_damagetime, self.projectiledeathtype);
+
+ remove(self);
+ }
+}
+
+void knight_fireball_touch()
+{
+ PROJECTILE_TOUCH;
+
+ knight_fireball_explode();
+}
+
+void knight_fireball()
+{
+ entity missile = spawn();
+ vector dir = normalize((self.enemy.origin + '0 0 10') - self.origin);
+
+ monster_makevectors(self.enemy);
+
+ self.effects |= EF_MUZZLEFLASH;
+ sound(self, CHAN_WEAPON, "weapons/fireball2.wav", 1, ATTN_NORM);
+
+ missile.owner = missile.realowner = self;
+ missile.solid = SOLID_TRIGGER;
+ missile.movetype = MOVETYPE_FLYMISSILE;
+ missile.projectiledeathtype = DEATH_MONSTER_KNIGHT_FBALL;
+ 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 * 400;
+ missile.avelocity = '300 300 300';
+ missile.nextthink = time + 5;
+ missile.think = knight_fireball_explode;
+ missile.enemy = self.enemy;
+ missile.touch = knight_fireball_touch;
+ CSQCProjectile(missile, TRUE, PROJECTILE_FIREMINE, TRUE);
+}
+
+void knight_spike_explode()
+{
+ if(self)
+ {
+ pointparticles(particleeffectnum("TE_WIZSPIKE"), self.origin, '0 0 0', 1);
+
+ RadiusDamage (self, self.realowner, autocvar_g_monster_knight_spike_damage, autocvar_g_monster_knight_spike_edgedamage, autocvar_g_monster_knight_spike_force, world, autocvar_g_monster_knight_spike_radius, DEATH_MONSTER_KNIGHT_SPIKE, other);
+ remove(self);
+ }
+}
+
+void knight_spike_touch()
+{
+ PROJECTILE_TOUCH;
+
+ knight_spike_explode();
+}
+
+void knight_spike()
+{
+ entity missile;
+ vector dir = normalize((self.enemy.origin + '0 0 10') - self.origin);
+
+ self.effects |= EF_MUZZLEFLASH;
+
+ missile = spawn ();
+ missile.owner = missile.realowner = self;
+ missile.solid = SOLID_TRIGGER;
+ missile.movetype = MOVETYPE_FLYMISSILE;
+ setsize (missile, '0 0 0', '0 0 0');
+ setorigin(missile, self.origin + '0 0 10' + v_forward * 14);
+ missile.scale = self.scale;
+ missile.flags = FL_PROJECTILE;
+ missile.velocity = dir * 400;
+ missile.avelocity = '300 300 300';
+ missile.nextthink = time + 5;
+ missile.think = knight_spike_explode;
+ missile.enemy = self.enemy;
+ missile.touch = knight_spike_touch;
+ CSQCProjectile(missile, TRUE, PROJECTILE_CRYLINK, TRUE);
+}
+
+void knight_spikes()
+{
+ self.monster_delayedattack = knight_spikes;
+ self.delay = time + 0.1;
+ self.knight_cycles += 1;
+ knight_spike();
+ if(self.knight_cycles >= 7)
+ {
+ self.monster_delayedattack = func_null;
+ self.delay = -1;
+ }
+}
+
+float knight_attack_ranged()
+{
+ if not(self.flags & FL_ONGROUND)
+ return FALSE;
+
+ self.knight_cycles = 0;
+
+ RandomSelection_Init();
+ RandomSelection_Add(world, 1, "", autocvar_g_monster_knight_fireball_chance, 1);
+ RandomSelection_Add(world, 2, "", autocvar_g_monster_knight_inferno_chance, 1);
+ RandomSelection_Add(world, 3, "", autocvar_g_monster_knight_spike_chance, 1);
+ if(self.health >= 100) RandomSelection_Add(world, 4, "", ((vlen(self.enemy.origin - self.origin) > autocvar_g_monster_knight_jump_dist) ? 1 : autocvar_g_monster_knight_jump_chance), 1);
+
+ switch(RandomSelection_chosen_float)
+ {
+ case 1:
+ {
+ monsters_setframe(knight_anim_magic2);
+ self.delay = time + 0.4;
+ self.monster_delayedattack = knight_fireball;
+ self.attack_finished_single = time + 2;
+
+ return TRUE;
+ }
+ case 2:
+ {
+ self.monster_delayedattack = knight_inferno;
+ self.delay = time + 0.5;
+ self.attack_finished_single = time + 3;
+ return TRUE;
+ }
+ case 3:
+ {
+ monsters_setframe(knight_anim_magic3);
+ self.monster_delayedattack = knight_spikes;
+ self.delay = time + 0.4;
+ self.attack_finished_single = time + 3;
+
+ return TRUE;
+ }
+ case 4:
+ {
+ float er = vlen(self.enemy.origin - self.origin);
+
+ if(er >= 400 && er < 1200)
+ if(findtrajectorywithleading(self.origin, self.mins, self.maxs, self.enemy, 1000, 0, 10, 0, self))
+ {
+ self.velocity = findtrajectory_velocity;
+ Damage(self.enemy, self, self, autocvar_g_monster_knight_jump_damage * monster_skill, DEATH_MONSTER_KNIGHT_CRUSH, self.enemy.origin, normalize(self.enemy.origin - self.origin));
+ self.attack_finished_single = time + 2;
+ return TRUE;
+ }
+ return FALSE;
+ }
+ }
+
+ return FALSE;
+}
+
+float knight_attack(float attack_type)
+{
+ switch(attack_type)
+ {
+ case MONSTER_ATTACK_MELEE:
+ {
+ float anim;
+ if(random() < 0.3)
+ anim = knight_anim_slice;
+ else if(random() < 0.6)
+ anim = knight_anim_smash;
+ else
+ anim = knight_anim_wattack;
+
+ monsters_setframe(anim);
+ self.attack_finished_single = time + 0.7;
+ monster_melee(self.enemy, autocvar_g_monster_knight_melee_damage, 0.3, DEATH_MONSTER_KNIGHT_MELEE, TRUE);
+
+ return TRUE;
+ }
+ case MONSTER_ATTACK_RANGED:
+ {
+ if(knight_attack_ranged())
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+void knight_die()
+{
+ float chance = random();
+ Monster_CheckDropCvars ("knight");
+
+ self.think = monster_dead_think;
+ self.nextthink = time + self.ticrate;
+ self.ltime = time + 5;
+ monsters_setframe((random() > 0.5) ? knight_anim_death1 : knight_anim_death2);
+
+ if(chance < 0.10 || self.flags & MONSTERFLAG_MINIBOSS)
+ if(self.candrop)
+ {
+ self.superweapons_finished = time + autocvar_g_balance_superweapons_time + 5; // give the player a few seconds to find the weapon
+ self.weapon = WEP_FIREBALL;
+ }
+
+ monster_hook_death(); // for post-death mods
+}
+
+void knight_spawn()
+{
+ if not(self.health)
+ self.health = autocvar_g_monster_knight_health;
+
+ self.damageforcescale = 0.003;
+ self.classname = "monster_knight";
+ self.monster_attackfunc = knight_attack;
+ self.nextthink = time + random() * 0.5 + 0.1;
+ self.think = knight_think;
+
+ monsters_setframe(knight_anim_stand);
+
+ monster_setupsounds("knight");
+
+ monster_hook_spawn(); // for post-spawn mods
+}
+
+void spawnfunc_monster_knight()
+{
+ if not(autocvar_g_monster_knight) { remove(self); return; }
+
+ self.monster_spawnfunc = spawnfunc_monster_knight;
+
+ if(Monster_CheckAppearFlags(self))
+ return;
+
+ self.scale = 1.3;
+
+ if not (monster_initialize(
+ "Knight", MONSTER_KNIGHT,
+ KNIGHT_MIN, KNIGHT_MAX,
+ FALSE,
+ knight_die, knight_spawn))
+ {
+ remove(self);
+ return;
+ }
+}
+
+// compatibility with old spawns
+void spawnfunc_monster_hell_knight() { spawnfunc_monster_knight(); }
+
+#endif // SVQC
missile.solid = SOLID_TRIGGER;
missile.movetype = MOVETYPE_FLYMISSILE;
missile.projectiledeathtype = DEATH_MONSTER_WYVERN;
- setsize (missile, '-6 -6 -6', '6 6 6');
+ 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;
#include "monster/wyvern.qc"
#include "monster/dog.qc"
#include "monster/slime.qc"
-#include "monster/hknight.qc"
+#include "monster/knight.qc"
#include "monster/fish.qc"
#include "monster/shalrath.qc"
#include "monster/zombie.qc"
case MONSTER_WYVERN:
case MONSTER_FISH:
return SWARM_WEAK;
- case MONSTER_HELLKNIGHT:
+ case MONSTER_KNIGHT:
case MONSTER_OGRE:
case MONSTER_SHAMBLER:
case MONSTER_MAGE:
case MONSTER_WYVERN: return "wyvern";
case MONSTER_DOG: return "dog";
case MONSTER_SLIME: return "slime";
- case MONSTER_HELLKNIGHT: return "hellknight";
+ case MONSTER_KNIGHT: return "knight";
case MONSTER_FISH: return "fish";
case MONSTER_MAGE: return "mage";
case MONSTER_SPIDER: return "spider";
case MONSTER_OGRE:
case MONSTER_SHAMBLER:
case MONSTER_MAGE:
- case MONSTER_HELLKNIGHT:
+ case MONSTER_KNIGHT:
case MONSTER_ANIMUS:
return SWARM_NORMAL;
case MONSTER_WYVERN:
if(n_animuses) RandomSelection_Add(world, MONSTER_ANIMUS, "", 1, 1);
if(n_shalraths) RandomSelection_Add(world, MONSTER_MAGE, "", 1, 1);
if(n_soldiers) RandomSelection_Add(world, MONSTER_MARINE, "", 1, 1);
- if(n_hknights) RandomSelection_Add(world, MONSTER_HELLKNIGHT, "", 1, 1);
+ if(n_knights) RandomSelection_Add(world, MONSTER_KNIGHT, "", 1, 1);
if(n_zombies) RandomSelection_Add(world, MONSTER_ZOMBIE, "", 1, 1);
if(n_spiders) RandomSelection_Add(world, MONSTER_SPIDER, "", 1, 1);
if(n_ogres) RandomSelection_Add(world, MONSTER_OGRE, "", 1, 1);
n_bruisers = DistributeEvenly_Get(1);
n_shalraths = DistributeEvenly_Get(1);
n_soldiers = DistributeEvenly_Get(1);
- n_hknights = DistributeEvenly_Get(1);
+ n_knights = DistributeEvenly_Get(1);
n_zombies = DistributeEvenly_Get(1);
n_spiders = DistributeEvenly_Get(1);
n_slimes = DistributeEvenly_Get(0.7);
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;
+ case MONSTER_KNIGHT: n_knights -= 1; break;
case MONSTER_FISH: n_fish -= 1; break;
case MONSTER_MAGE: n_shalraths -= 1; break;
case MONSTER_SPIDER: n_spiders -= 1; break;
// Counters
float monster_count, totalmonsters;
-float n_bruisers, n_dogs, n_ogres, n_shamblers, n_wyverns, n_shalraths, n_soldiers, n_hknights, n_animuses, n_zombies, n_slimes, n_fish, n_spiders;
+float n_bruisers, n_dogs, n_ogres, n_shamblers, n_wyverns, n_shalraths, n_soldiers, n_knights, n_animuses, n_zombies, n_slimes, n_fish, n_spiders;
float current_monsters;
float waterspawns_count, flyspawns_count;
float wave_count, max_waves;