-#ifdef REGISTER_MONSTER
-REGISTER_MONSTER(
-/* MON_##id */ KNIGHT,
-/* function */ m_knight,
-/* spawnflags */ MONSTER_SIZE_BROKEN | MON_FLAG_MELEE | MON_FLAG_RANGED | MON_FLAG_MUTATORBLOCKED,
-/* mins,maxs */ '-20 -20 -32', '20 20 41',
-/* model */ "hknight.mdl",
-/* netname */ "knight",
-/* fullname */ _("Knight")
-);
-
-#define KNIGHT_SETTINGS(monster) \
- MON_ADD_CVAR(monster, health) \
- MON_ADD_CVAR(monster, attack_melee_damage) \
- MON_ADD_CVAR(monster, attack_inferno_damage) \
- MON_ADD_CVAR(monster, attack_inferno_damagetime) \
- MON_ADD_CVAR(monster, attack_inferno_chance) \
- MON_ADD_CVAR(monster, attack_fireball_damage) \
- MON_ADD_CVAR(monster, attack_fireball_edgedamage) \
- MON_ADD_CVAR(monster, attack_fireball_damagetime) \
- MON_ADD_CVAR(monster, attack_fireball_force) \
- MON_ADD_CVAR(monster, attack_fireball_radius) \
- MON_ADD_CVAR(monster, attack_fireball_chance) \
- MON_ADD_CVAR(monster, attack_spike_damage) \
- MON_ADD_CVAR(monster, attack_spike_edgedamage) \
- MON_ADD_CVAR(monster, attack_spike_force) \
- MON_ADD_CVAR(monster, attack_spike_radius) \
- MON_ADD_CVAR(monster, attack_spike_chance) \
- MON_ADD_CVAR(monster, attack_jump_damage) \
- MON_ADD_CVAR(monster, attack_jump_distance) \
- MON_ADD_CVAR(monster, attack_jump_chance) \
- MON_ADD_CVAR(monster, speed_stop) \
- MON_ADD_CVAR(monster, speed_run) \
- MON_ADD_CVAR(monster, speed_walk)
-
-#ifdef SVQC
-KNIGHT_SETTINGS(knight)
-#endif // SVQC
-#else
-#ifdef SVQC
-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_inferno()
-{
- 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, ATTEN_NORM);
-
- if(vlen(self.enemy.origin - self.origin) <= 2000)
- Fire_AddDamage(self.enemy, self, MON_CVAR(knight, attack_inferno_damage) * monster_skill, MON_CVAR(knight, attack_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, MON_CVAR(knight, attack_fireball_damage), MON_CVAR(knight, attack_fireball_edgedamage), MON_CVAR(knight, attack_fireball_force), world, MON_CVAR(knight, attack_fireball_radius), self.projectiledeathtype, world);
-
- for(e = world; (e = findfloat(e, takedamage, DAMAGE_AIM)); ) if(vlen(e.origin - self.origin) <= MON_CVAR(knight, attack_inferno_damage))
- Fire_AddDamage(e, self, 5 * monster_skill, MON_CVAR(knight, attack_fireball_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, ATTEN_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, MON_CVAR(knight, attack_spike_damage), MON_CVAR(knight, attack_spike_edgedamage), MON_CVAR(knight, attack_spike_force), world, MON_CVAR(knight, attack_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.knight_cycles += 1;
- knight_spike();
-
- if(self.knight_cycles <= 7)
- defer(0.1, knight_spikes);
-}
-
-float knight_attack_ranged()
-{
- if not(self.flags & FL_ONGROUND)
- return FALSE;
-
- self.knight_cycles = 0;
-
- RandomSelection_Init();
- RandomSelection_Add(world, 1, "", MON_CVAR(knight, attack_fireball_chance), 1);
- RandomSelection_Add(world, 2, "", MON_CVAR(knight, attack_inferno_chance), 1);
- RandomSelection_Add(world, 3, "", MON_CVAR(knight, attack_spike_chance), 1);
- if(self.health >= 100) RandomSelection_Add(world, 4, "", ((vlen(self.enemy.origin - self.origin) > MON_CVAR(knight, attack_jump_distance)) ? 1 : MON_CVAR(knight, attack_jump_chance)), 1);
-
- switch(RandomSelection_chosen_float)
- {
- case 1:
- {
- self.frame = knight_anim_magic2;
- self.attack_finished_single = time + 2;
- defer(0.4, knight_fireball);
-
- return TRUE;
- }
- case 2:
- {
- self.attack_finished_single = time + 3;
- defer(0.5, knight_inferno);
- return TRUE;
- }
- case 3:
- {
- self.frame = knight_anim_magic3;
- self.attack_finished_single = time + 3;
- defer(0.4, knight_spikes);
-
- 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, MON_CVAR(knight, attack_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;
-
- return monster_melee(self.enemy, MON_CVAR(knight, attack_melee_damage), anim, self.attack_range, 0.7, DEATH_MONSTER_KNIGHT_MELEE, TRUE);
- }
- case MONSTER_ATTACK_RANGED:
- {
- return knight_attack_ranged();
- }
- }
-
- return FALSE;
-}
-
-void spawnfunc_monster_knight()
-{
- self.classname = "monster_knight";
-
- self.monster_spawnfunc = spawnfunc_monster_knight;
-
- if(Monster_CheckAppearFlags(self))
- return;
-
- if not(monster_initialize(MON_KNIGHT, FALSE)) { remove(self); return; }
-}
-
-// compatibility with old spawns
-void spawnfunc_monster_hell_knight() { spawnfunc_monster_knight(); }
-
-float m_knight(float req)
-{
- switch(req)
- {
- case MR_THINK:
- {
- monster_move(MON_CVAR(knight, speed_run), MON_CVAR(knight, speed_walk), MON_CVAR(knight, speed_stop), knight_anim_run, knight_anim_walk, knight_anim_stand);
- return TRUE;
- }
- case MR_DEATH:
- {
- float chance = random();
- self.frame = ((random() > 0.5) ? knight_anim_death1 : knight_anim_death2);
- if(chance < 0.10 || self.spawnflags & 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;
- }
- return TRUE;
- }
- case MR_SETUP:
- {
- if not(self.health) self.health = MON_CVAR(knight, health);
-
- self.monster_loot = spawnfunc_item_armor_big;
- self.monster_attackfunc = knight_attack;
- self.frame = knight_anim_stand;
-
- return TRUE;
- }
- case MR_PRECACHE:
- {
- precache_model ("models/monsters/hknight.mdl");
- precache_sound ("player/lava.wav");
- precache_sound ("weapons/fireball2.wav");
- return TRUE;
- }
- case MR_CONFIG:
- {
- MON_CONFIG_SETTINGS(KNIGHT_SETTINGS(knight))
- return TRUE;
- }
- }
-
- return TRUE;
-}
-
-#endif // SVQC
-#ifdef CSQC
-float m_knight(float req)
-{
- switch(req)
- {
- case MR_PRECACHE:
- {
- precache_model ("models/monsters/hknight.mdl");
- return TRUE;
- }
- }
-
- return TRUE;
-}
-
-#endif // CSQC
-#endif // REGISTER_MONSTER