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 wyvern cerberus slime knight stingray mage zombie spider" "monsters not listed here will spawn as bruisers"
+set g_monsters_spawn_list "brute animus shambler bruiser wyvern cerberus slime knight stingray mage zombie spider" "monsters not listed here will spawn as bruisers"
-// Ogre
-set g_monster_ogre 1 "Enable Ogres"
-set g_monster_ogre_health 200 "Ogre health"
-set g_monster_ogre_chainsaw_damage 15 "Ogre chainsaw damage (hits multiple times)"
-set g_monster_ogre_drop ammo "Ogre drops this item on death"
-set g_monster_ogre_drop_size bullets "Size of the item Ogres drop. Possible values are: small, medium, large"
-set g_monster_ogre_speed_walk 100 "Ogre walk speed"
-set g_monster_ogre_speed_run 150 "Ogre run speed"
-set g_monster_ogre_attack_uzi_bullets 3 "Number of machine gun bullets Ogre fires"
-set g_monster_ogre_attack_uzi_chance 0.1 "Chance for Ogre to fire machine gun"
-set g_monster_ogre_attack_uzi_damage 10 "Ogre machine gun damage per bullet"
-set g_monster_ogre_attack_uzi_force 5 "Ogre machine gun knockback"
-set g_monster_ogre_attack_grenade_damage 50 "Ogre grenade damage"
-set g_monster_ogre_attack_grenade_edgedamage 25 "Ogre grenade indirect hit damage"
-set g_monster_ogre_attack_grenade_radius 200 "Ogre grenade explosion radius"
-set g_monster_ogre_attack_grenade_force 15 "Ogre grenade knockback"
+// Brute
+set g_monster_brute 1 "Enable Brutes"
+set g_monster_brute_health 200 "Brute health"
+set g_monster_brute_chainsaw_damage 15 "Brute chainsaw damage (hits multiple times)"
+set g_monster_brute_drop ammo "Brute drops this item on death"
+set g_monster_brute_drop_size bullets "Size of the item Brutes drop. Possible values are: small, medium, large"
+set g_monster_brute_speed_walk 100 "Brute walk speed"
+set g_monster_brute_speed_run 150 "Brute run speed"
+set g_monster_brute_attack_uzi_bullets 3 "Number of machine gun bullets Brute fires"
+set g_monster_brute_attack_uzi_chance 0.1 "Chance for Brute to fire machine gun"
+set g_monster_brute_attack_uzi_damage 10 "Brute machine gun damage per bullet"
+set g_monster_brute_attack_uzi_force 5 "Brute machine gun knockback"
+set g_monster_brute_attack_grenade_damage 50 "Brute grenade damage"
+set g_monster_brute_attack_grenade_edgedamage 25 "Brute grenade indirect hit damage"
+set g_monster_brute_attack_grenade_radius 200 "Brute grenade explosion radius"
+set g_monster_brute_attack_grenade_force 15 "Brute grenade knockback"
// Animus
set g_monster_animus 1 "Enable Animuses"
precache_model(ZOMBIE_MODEL);
break;
}
- case MONSTER_OGRE:
+ case MONSTER_BRUTE:
{
- precache_model(OGRE_MODEL);
+ precache_model(BRUTE_MODEL);
break;
}
case MONSTER_ANIMUS:
mid2info_max = ZOMBIE_MAX;
break;
}
- case MONSTER_OGRE:
+ case MONSTER_BRUTE:
{
- mid2info_model = OGRE_MODEL;
- mid2info_name = "Ogre";
- mid2info_min = OGRE_MIN;
- mid2info_max = OGRE_MAX;
+ mid2info_model = BRUTE_MODEL;
+ mid2info_name = "Brute";
+ mid2info_min = BRUTE_MIN;
+ mid2info_max = BRUTE_MAX;
break;
}
case MONSTER_ANIMUS:
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) \
- DEATHTYPE(DEATH_MONSTER_OGRE_UZI, DEATH_SELF_MON_OGRE_UZI, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_MONSTER_BRUTE_BLADE, DEATH_SELF_MON_BRUTE_BLADE, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_MONSTER_BRUTE_GRENADE, DEATH_SELF_MON_BRUTE_GRENADE, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_MONSTER_BRUTE_UZI, DEATH_SELF_MON_BRUTE_UZI, NO_MSG, NORMAL_POS) \
DEATHTYPE(DEATH_MONSTER_MAGE, DEATH_SELF_MON_MAGE, NO_MSG, NORMAL_POS) \
DEATHTYPE(DEATH_MONSTER_SHAMBLER_CLAW, DEATH_SELF_MON_SHAMBLER_CLAW, NO_MSG, NORMAL_POS) \
DEATHTYPE(DEATH_MONSTER_SHAMBLER_SMASH, DEATH_SELF_MON_SHAMBLER_SMASH, NO_MSG, NORMAL_POS) \
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_INFO_NOTIF(1, INFO_DEATH_SELF_MON_OGRE_UZI, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was nailed by an Ogre%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_BRUTE_BLADE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was cut down by a Brute%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_BRUTE_GRENADE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 almost dodged a Brute's grenade%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_BRUTE_UZI, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was nailed by a Brute%s%s\n"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_MAGE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was exploded by a Mage%s%s\n"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SHAMBLER_CLAW, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1's innards became outwards by a Shambler%s%s\n"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SHAMBLER_SMASH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was smashed by a Shambler%s%s\n"), "") \
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) \
- MSG_MULTI_NOTIF(1, DEATH_SELF_MON_OGRE_UZI, NO_MSG, INFO_DEATH_SELF_MON_OGRE_UZI, CENTER_DEATH_SELF_MONSTER) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_MON_BRUTE_BLADE, NO_MSG, INFO_DEATH_SELF_MON_BRUTE_BLADE, CENTER_DEATH_SELF_MONSTER) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_MON_BRUTE_GRENADE, NO_MSG, INFO_DEATH_SELF_MON_BRUTE_GRENADE, CENTER_DEATH_SELF_MONSTER) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_MON_BRUTE_UZI, NO_MSG, INFO_DEATH_SELF_MON_BRUTE_UZI, CENTER_DEATH_SELF_MONSTER) \
MSG_MULTI_NOTIF(1, DEATH_SELF_MON_MAGE, NO_MSG, INFO_DEATH_SELF_MON_MAGE, CENTER_DEATH_SELF_MONSTER) \
MSG_MULTI_NOTIF(1, DEATH_SELF_MON_SHAMBLER_CLAW, NO_MSG, INFO_DEATH_SELF_MON_SHAMBLER_CLAW, CENTER_DEATH_SELF_MONSTER) \
MSG_MULTI_NOTIF(1, DEATH_SELF_MON_SHAMBLER_SMASH, NO_MSG, INFO_DEATH_SELF_MON_SHAMBLER_SMASH, CENTER_DEATH_SELF_MONSTER) \
me.TD(me, 1, 0.25, e = makeXonoticTextLabel(0, _("Monster:")));
me.TR(me);
me.TD(me, 1, 0.4, e = makeXonoticRadioButton(2, "menu_monsters_edit_spawn", "zombie", _("Zombie")));
- me.TD(me, 1, 0.4, e = makeXonoticRadioButton(2, "menu_monsters_edit_spawn", "ogre", _("Ogre")));
+ me.TD(me, 1, 0.4, e = makeXonoticRadioButton(2, "menu_monsters_edit_spawn", "brute", _("Brute")));
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")));
// Monster IDs
float MONSTER_FIRST = 1;
float MONSTER_ZOMBIE = 2;
-float MONSTER_OGRE = 3;
+float MONSTER_BRUTE = 3;
float MONSTER_ANIMUS = 4;
float MONSTER_SHAMBLER = 5;
float MONSTER_BRUISER = 6;
--- /dev/null
+// size
+const vector BRUTE_MIN = '-36 -36 -20';
+const vector BRUTE_MAX = '36 36 50';
+
+// model
+string BRUTE_MODEL = "models/monsters/ogre.dpm";
+
+#ifdef SVQC
+// cvars
+float autocvar_g_monster_brute;
+float autocvar_g_monster_brute_health;
+float autocvar_g_monster_brute_chainsaw_damage;
+float autocvar_g_monster_brute_speed_walk;
+float autocvar_g_monster_brute_speed_run;
+float autocvar_g_monster_brute_attack_uzi_bullets;
+float autocvar_g_monster_brute_attack_uzi_damage;
+float autocvar_g_monster_brute_attack_uzi_force;
+float autocvar_g_monster_brute_attack_uzi_chance;
+float autocvar_g_monster_brute_attack_grenade_damage;
+float autocvar_g_monster_brute_attack_grenade_edgedamage;
+float autocvar_g_monster_brute_attack_grenade_force;
+float autocvar_g_monster_brute_attack_grenade_radius;
+
+// animations
+const float brute_anim_idle = 0;
+const float brute_anim_walk = 1;
+const float brute_anim_run = 2;
+const float brute_anim_pain = 3;
+const float brute_anim_swing = 4;
+const float brute_anim_die = 5;
+
+.float brute_cycles;
+
+void brute_think()
+{
+ self.think = brute_think;
+ self.nextthink = time + self.ticrate;
+
+ monster_move(autocvar_g_monster_brute_speed_run, autocvar_g_monster_brute_speed_walk, 300, brute_anim_run, brute_anim_walk, brute_anim_idle);
+}
+
+void brute_blade()
+{
+ self.brute_cycles += 1;
+ self.angles_y = self.angles_y + random()* 25;
+ self.delay = time + 0.2;
+ self.monster_delayedattack = brute_blade;
+
+ monster_melee(self.enemy, autocvar_g_monster_brute_chainsaw_damage, 0.3, DEATH_MONSTER_BRUTE_BLADE, TRUE);
+
+ if(self.brute_cycles >= 4)
+ {
+ self.monster_delayedattack = func_null;
+ self.delay = -1;
+ }
+}
+
+void brute_uzi()
+{
+ self.brute_cycles += 1;
+
+ if(self.brute_cycles > autocvar_g_monster_brute_attack_uzi_bullets)
+ {
+ self.monster_delayedattack = func_null;
+ self.delay = -1;
+ return;
+ }
+
+ monster_makevectors(self.enemy);
+
+ W_SetupShot (self, autocvar_g_antilag_bullets && 18000 >= autocvar_g_antilag_bullets, 0, "weapons/uzi_fire.wav", CH_WEAPON_A, autocvar_g_monster_brute_attack_uzi_damage);
+ fireBallisticBullet(w_shotorg, w_shotdir, 0.02, 18000, 5, autocvar_g_monster_brute_attack_uzi_damage, autocvar_g_monster_brute_attack_uzi_force, DEATH_MONSTER_BRUTE_UZI, 0, 1, 115);
+ endFireBallisticBullet();
+
+ self.delay = time + 0.1;
+ self.monster_delayedattack = brute_uzi;
+}
+
+void brute_grenade_explode()
+{
+ pointparticles(particleeffectnum("grenade_explode"), self.origin, '0 0 0', 1);
+ sound(self, CH_SHOTS, "weapons/grenade_impact.wav", VOL_BASE, ATTN_NORM);
+
+ self.event_damage = func_null;
+ self.takedamage = DAMAGE_NO;
+
+ if(self.movetype == MOVETYPE_NONE)
+ self.velocity = self.oldvelocity;
+
+ RadiusDamage (self, self.realowner, autocvar_g_monster_brute_attack_grenade_damage, autocvar_g_monster_brute_attack_grenade_edgedamage, autocvar_g_monster_brute_attack_grenade_radius, world, autocvar_g_monster_brute_attack_grenade_force, self.projectiledeathtype, other);
+
+ remove (self);
+}
+
+void brute_grenade_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+ if (self.health <= 0)
+ return;
+
+ if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
+ return; // g_projectiles_damage says to halt
+
+ self.health = self.health - damage;
+
+ if (self.health <= 0)
+ W_PrepareExplosionByDamage(attacker, self.use);
+}
+
+void brute_grenade_touch()
+{
+ PROJECTILE_TOUCH;
+
+ self.use ();
+}
+
+void brute_grenade_think()
+{
+ self.nextthink = time;
+ if (time > self.cnt)
+ {
+ other = world;
+ brute_grenade_explode();
+ return;
+ }
+}
+
+void brute_grenade()
+{
+ entity gren;
+
+ W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 4, "weapons/grenade_fire.wav", CH_WEAPON_A, autocvar_g_monster_brute_attack_grenade_damage);
+ w_shotdir = v_forward; // no TrueAim for grenades please
+
+ gren = spawn ();
+ gren.owner = gren.realowner = self;
+ gren.classname = "grenade";
+ gren.bot_dodge = TRUE;
+ gren.bot_dodgerating = autocvar_g_monster_brute_attack_grenade_damage;
+ gren.movetype = MOVETYPE_BOUNCE;
+ PROJECTILE_MAKETRIGGER(gren);
+ gren.projectiledeathtype = DEATH_MONSTER_BRUTE_GRENADE;
+ setorigin(gren, w_shotorg);
+ setsize(gren, '-3 -3 -3', '3 3 3');
+
+ gren.cnt = time + 5;
+ gren.nextthink = time;
+ gren.think = brute_grenade_think;
+ gren.use = brute_grenade_explode;
+ gren.touch = brute_grenade_touch;
+
+ gren.takedamage = DAMAGE_YES;
+ gren.health = autocvar_g_balance_grenadelauncher_primary_health;
+ gren.damageforcescale = autocvar_g_balance_grenadelauncher_primary_damageforcescale;
+ gren.event_damage = brute_grenade_damage;
+ gren.damagedbycontents = TRUE;
+ gren.missile_flags = MIF_SPLASH | MIF_ARC;
+ W_SETUPPROJECTILEVELOCITY_UP(gren, g_balance_grenadelauncher_primary);
+
+ gren.angles = vectoangles (gren.velocity);
+ gren.flags = FL_PROJECTILE;
+
+ CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE, TRUE);
+}
+
+float brute_attack(float attack_type)
+{
+ switch(attack_type)
+ {
+ case MONSTER_ATTACK_MELEE:
+ {
+ self.brute_cycles = 0;
+ monsters_setframe(brute_anim_swing);
+ self.attack_finished_single = time + 1.3;
+ brute_blade();
+
+ return TRUE;
+ }
+ case MONSTER_ATTACK_RANGED:
+ {
+ self.brute_cycles = 0;
+ if(random() <= autocvar_g_monster_brute_attack_uzi_chance)
+ {
+ monsters_setframe(brute_anim_pain);
+ self.attack_finished_single = time + 0.8;
+ self.delay = time + 0.1;
+ self.monster_delayedattack = brute_uzi;
+ }
+ else
+ {
+ monster_makevectors(self.enemy);
+ brute_grenade();
+ monsters_setframe(brute_anim_pain);
+ self.attack_finished_single = time + 1.2;
+ }
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+void brute_die()
+{
+ Monster_CheckDropCvars ("brute");
+
+ self.think = monster_dead_think;
+ self.nextthink = time + self.ticrate;
+ self.ltime = time + 5;
+ monsters_setframe(brute_anim_die);
+
+ monster_hook_death(); // for post-death mods
+}
+
+void brute_spawn()
+{
+ if not(self.health)
+ self.health = autocvar_g_monster_brute_health;
+
+ self.damageforcescale = 0.003;
+ self.classname = "monster_brute";
+ self.monster_attackfunc = brute_attack;
+ self.nextthink = time + random() * 0.5 + 0.1;
+ self.think = brute_think;
+ self.weapon = WEP_GRENADE_LAUNCHER;
+
+ monsters_setframe(brute_anim_idle);
+
+ monster_setupsounds("brute");
+
+ monster_hook_spawn(); // for post-spawn mods
+}
+
+void spawnfunc_monster_brute()
+{
+ if not(autocvar_g_monster_brute) { remove(self); return; }
+
+ self.monster_spawnfunc = spawnfunc_monster_brute;
+
+ if(Monster_CheckAppearFlags(self))
+ return;
+
+ if not (monster_initialize(
+ "Brute", MONSTER_BRUTE,
+ BRUTE_MIN, BRUTE_MAX,
+ FALSE,
+ brute_die, brute_spawn))
+ {
+ remove(self);
+ return;
+ }
+}
+
+#endif // SVQC
+++ /dev/null
-// size
-const vector OGRE_MIN = '-36 -36 -20';
-const vector OGRE_MAX = '36 36 50';
-
-// model
-string OGRE_MODEL = "models/monsters/ogre.dpm";
-
-#ifdef SVQC
-// cvars
-float autocvar_g_monster_ogre;
-float autocvar_g_monster_ogre_health;
-float autocvar_g_monster_ogre_chainsaw_damage;
-float autocvar_g_monster_ogre_speed_walk;
-float autocvar_g_monster_ogre_speed_run;
-float autocvar_g_monster_ogre_attack_uzi_bullets;
-float autocvar_g_monster_ogre_attack_uzi_damage;
-float autocvar_g_monster_ogre_attack_uzi_force;
-float autocvar_g_monster_ogre_attack_uzi_chance;
-float autocvar_g_monster_ogre_attack_grenade_damage;
-float autocvar_g_monster_ogre_attack_grenade_edgedamage;
-float autocvar_g_monster_ogre_attack_grenade_force;
-float autocvar_g_monster_ogre_attack_grenade_radius;
-
-// animations
-const float ogre_anim_idle = 0;
-const float ogre_anim_walk = 1;
-const float ogre_anim_run = 2;
-const float ogre_anim_pain = 3;
-const float ogre_anim_swing = 4;
-const float ogre_anim_die = 5;
-
-void ogre_think()
-{
- self.think = ogre_think;
- self.nextthink = time + self.ticrate;
-
- monster_move(autocvar_g_monster_ogre_speed_run, autocvar_g_monster_ogre_speed_walk, 300, ogre_anim_run, ogre_anim_walk, ogre_anim_idle);
-}
-
-.float ogre_cycles;
-void ogre_swing()
-{
- self.ogre_cycles += 1;
- self.angles_y = self.angles_y + random()* 25;
- self.delay = time + 0.2;
- self.monster_delayedattack = ogre_swing;
-
- monster_melee(self.enemy, autocvar_g_monster_ogre_chainsaw_damage, 0.3, DEATH_MONSTER_OGRE_CHAINSAW, TRUE);
-
- if(self.ogre_cycles >= 4)
- {
- self.monster_delayedattack = func_null;
- self.delay = -1;
- }
-}
-
-void ogre_uzi_fire()
-{
- self.ogre_cycles += 1;
-
- if(self.ogre_cycles > autocvar_g_monster_ogre_attack_uzi_bullets)
- {
- self.monster_delayedattack = func_null;
- self.delay = -1;
- return;
- }
-
- monster_makevectors(self.enemy);
-
- W_SetupShot (self, autocvar_g_antilag_bullets && 18000 >= autocvar_g_antilag_bullets, 0, "weapons/uzi_fire.wav", CH_WEAPON_A, autocvar_g_monster_ogre_attack_uzi_damage);
- fireBallisticBullet(w_shotorg, w_shotdir, 0.02, 18000, 5, autocvar_g_monster_ogre_attack_uzi_damage, autocvar_g_monster_ogre_attack_uzi_force, DEATH_MONSTER_OGRE_UZI, 0, 1, 115);
- endFireBallisticBullet();
-
- self.delay = time + 0.1;
- self.monster_delayedattack = ogre_uzi_fire;
-}
-
-void ogre_grenade_explode()
-{
- pointparticles(particleeffectnum("grenade_explode"), self.origin, '0 0 0', 1);
- sound(self, CH_SHOTS, "weapons/grenade_impact.wav", VOL_BASE, ATTN_NORM);
-
- self.event_damage = func_null;
- self.takedamage = DAMAGE_NO;
-
- if(self.movetype == MOVETYPE_NONE)
- self.velocity = self.oldvelocity;
-
- RadiusDamage (self, self.realowner, autocvar_g_monster_ogre_attack_grenade_damage, autocvar_g_monster_ogre_attack_grenade_edgedamage, autocvar_g_monster_ogre_attack_grenade_radius, world, autocvar_g_monster_ogre_attack_grenade_force, self.projectiledeathtype, other);
-
- remove (self);
-}
-
-void ogre_grenade_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
- if (self.health <= 0)
- return;
-
- if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
- return; // g_projectiles_damage says to halt
-
- self.health = self.health - damage;
-
- if (self.health <= 0)
- W_PrepareExplosionByDamage(attacker, self.use);
-}
-
-void ogre_grenade_touch()
-{
- PROJECTILE_TOUCH;
-
- self.use ();
-}
-
-void ogre_grenade_think()
-{
- self.nextthink = time;
- if (time > self.cnt)
- {
- other = world;
- ogre_grenade_explode();
- return;
- }
-}
-
-void ogre_gl()
-{
- entity gren;
-
- W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 4, "weapons/grenade_fire.wav", CH_WEAPON_A, autocvar_g_monster_ogre_attack_grenade_damage);
- w_shotdir = v_forward; // no TrueAim for grenades please
-
- gren = spawn ();
- gren.owner = gren.realowner = self;
- gren.classname = "grenade";
- gren.bot_dodge = TRUE;
- gren.bot_dodgerating = autocvar_g_monster_ogre_attack_grenade_damage;
- gren.movetype = MOVETYPE_BOUNCE;
- PROJECTILE_MAKETRIGGER(gren);
- gren.projectiledeathtype = DEATH_MONSTER_OGRE_GRENADE;
- setorigin(gren, w_shotorg);
- setsize(gren, '-3 -3 -3', '3 3 3');
-
- gren.cnt = time + 5;
- gren.nextthink = time;
- gren.think = ogre_grenade_think;
- gren.use = ogre_grenade_explode;
- gren.touch = ogre_grenade_touch;
-
- gren.takedamage = DAMAGE_YES;
- gren.health = autocvar_g_balance_grenadelauncher_primary_health;
- gren.damageforcescale = autocvar_g_balance_grenadelauncher_primary_damageforcescale;
- gren.event_damage = ogre_grenade_damage;
- gren.damagedbycontents = TRUE;
- gren.missile_flags = MIF_SPLASH | MIF_ARC;
- W_SETUPPROJECTILEVELOCITY_UP(gren, g_balance_grenadelauncher_primary);
-
- gren.angles = vectoangles (gren.velocity);
- gren.flags = FL_PROJECTILE;
-
- CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE, TRUE);
-}
-
-float ogre_attack(float attack_type)
-{
- switch(attack_type)
- {
- case MONSTER_ATTACK_MELEE:
- {
- self.ogre_cycles = 0;
- monsters_setframe(ogre_anim_swing);
- self.attack_finished_single = time + 1.3;
- ogre_swing();
-
- return TRUE;
- }
- case MONSTER_ATTACK_RANGED:
- {
- self.ogre_cycles = 0;
- if(random() <= autocvar_g_monster_ogre_attack_uzi_chance)
- {
- monsters_setframe(ogre_anim_pain);
- self.attack_finished_single = time + 0.8;
- self.delay = time + 0.1;
- self.monster_delayedattack = ogre_uzi_fire;
- }
- else
- {
- monster_makevectors(self.enemy);
- ogre_gl();
- monsters_setframe(ogre_anim_pain);
- self.attack_finished_single = time + 1.2;
- }
-
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-void ogre_die()
-{
- Monster_CheckDropCvars ("ogre");
-
- self.think = monster_dead_think;
- self.nextthink = time + self.ticrate;
- self.ltime = time + 5;
- monsters_setframe(ogre_anim_die);
-
- monster_hook_death(); // for post-death mods
-}
-
-void ogre_spawn()
-{
- if not(self.health)
- self.health = autocvar_g_monster_ogre_health;
-
- self.damageforcescale = 0.003;
- self.classname = "monster_ogre";
- self.monster_attackfunc = ogre_attack;
- self.nextthink = time + random() * 0.5 + 0.1;
- self.think = ogre_think;
- self.weapon = WEP_GRENADE_LAUNCHER;
-
- monsters_setframe(ogre_anim_idle);
-
- monster_setupsounds("ogre");
-
- monster_hook_spawn(); // for post-spawn mods
-}
-
-void spawnfunc_monster_ogre()
-{
- if not(autocvar_g_monster_ogre) { remove(self); return; }
-
- self.monster_spawnfunc = spawnfunc_monster_ogre;
-
- if(Monster_CheckAppearFlags(self))
- return;
-
- if not (monster_initialize(
- "Ogre", MONSTER_OGRE,
- OGRE_MIN, OGRE_MAX,
- FALSE,
- ogre_die, ogre_spawn))
- {
- remove(self);
- return;
- }
-
- weapon_action(WEP_GRENADE_LAUNCHER, WR_PRECACHE);
-}
-
-#endif // SVQC
#endif
// Monsters
-#include "monster/ogre.qc"
+#include "monster/brute.qc"
#include "monster/animus.qc"
#include "monster/shambler.qc"
#include "monster/bruiser.qc"
case MONSTER_STINGRAY:
return SWARM_WEAK;
case MONSTER_KNIGHT:
- case MONSTER_OGRE:
+ case MONSTER_BRUTE:
case MONSTER_SHAMBLER:
case MONSTER_MAGE:
case MONSTER_ANIMUS:
switch(mnster)
{
case MONSTER_ZOMBIE: return "zombie";
- case MONSTER_OGRE: return "ogre";
+ case MONSTER_BRUTE: return "brute";
case MONSTER_ANIMUS: return "animus";
case MONSTER_SHAMBLER: return "shambler";
case MONSTER_BRUISER: return "bruiser";
case MONSTER_SPIDER:
case MONSTER_SLIME:
case MONSTER_CERBERUS:
- case MONSTER_OGRE:
+ case MONSTER_BRUTE:
case MONSTER_SHAMBLER:
case MONSTER_MAGE:
case MONSTER_KNIGHT:
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);
+ if(n_brutes) RandomSelection_Add(world, MONSTER_BRUTE, "", 1, 1);
if(n_cerberuses) RandomSelection_Add(world, MONSTER_CERBERUS, "", 1, 1);
if(n_bruisers) RandomSelection_Add(world, MONSTER_BRUISER, "", 1, 1);
if(n_shamblers) RandomSelection_Add(world, MONSTER_SHAMBLER, "", 0.2, 0.2);
DistributeEvenly_Init(maxmonsters, mc);
n_animuses = DistributeEvenly_Get(1);
- n_ogres = DistributeEvenly_Get(1);
+ n_brutes = DistributeEvenly_Get(1);
n_cerberuses = DistributeEvenly_Get(1);
n_bruisers = DistributeEvenly_Get(1);
n_mages = DistributeEvenly_Get(1);
switch(self.monsterid)
{
case MONSTER_ZOMBIE: n_zombies -= 1; break;
- case MONSTER_OGRE: n_ogres -= 1; break;
+ case MONSTER_BRUTE: n_brutes -= 1; break;
case MONSTER_ANIMUS: n_animuses -= 1; break;
case MONSTER_SHAMBLER: n_shamblers -= 1; break;
case MONSTER_BRUISER: n_bruisers -= 1; break;
// Counters
float monster_count, totalmonsters;
-float n_bruisers, n_cerberuses, n_ogres, n_shamblers, n_wyverns, n_mages, n_knights, n_animuses, n_zombies, n_slimes, n_stingrays, n_spiders;
+float n_bruisers, n_cerberuses, n_brutes, n_shamblers, n_wyverns, n_mages, n_knights, n_animuses, n_zombies, n_slimes, n_stingrays, n_spiders;
float current_monsters;
float waterspawns_count, flyspawns_count;
float wave_count, max_waves;