From b73d91118d23d870e4f17bcb2e46bfce8250cbbe Mon Sep 17 00:00:00 2001 From: Mario Date: Sun, 14 Apr 2013 13:04:49 +1000 Subject: [PATCH] Fix all soldier attacks --- monsters.cfg | 12 ++ qcsrc/server/monsters/monster/soldier.qc | 134 ++++++++++++++++++++++- 2 files changed, 144 insertions(+), 2 deletions(-) diff --git a/monsters.cfg b/monsters.cfg index 04a2231bb..815cfabd8 100644 --- a/monsters.cfg +++ b/monsters.cfg @@ -104,6 +104,18 @@ set g_monster_soldier_attack_shotgun_damage 4 "Grunt shotgun per bullet damage" set g_monster_soldier_attack_shotgun_spread 0.2 "Grunt shotgun bullet spread" set g_monster_soldier_attack_shotgun_bullets 12 "Grunt shotgun bullets per shot" set g_monster_soldier_attack_shotgun_force 5 "Grunt shotgun knockback" +set g_monster_soldier_attack_rocket_damage 50 "Grunt rocket direct hit damage" +set g_monster_soldier_attack_rocket_edgedamage 25 "Grunt rocket indirect hit damage" +set g_monster_soldier_attack_rocket_radius 110 "Grunt rocket explosion radius" +set g_monster_soldier_attack_rocket_force 25 "Grunt rocket knockback" +set g_monster_soldier_attack_rocket_lifetime 5 "Grunt rocket lifetime" +set g_monster_soldier_attack_rocket_speed 2000 "Grunt rocket fly speed" +set g_monster_soldier_attack_laser_damage 15 "Grunt laser damage" +set g_monster_soldier_attack_laser_edgedamage 7 "Grunt laser indirect hit damage" +set g_monster_soldier_attack_laser_radius 50 "Grunt laser damage radius" +set g_monster_soldier_attack_laser_force 300 "Grunt laser knockback" +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" diff --git a/qcsrc/server/monsters/monster/soldier.qc b/qcsrc/server/monsters/monster/soldier.qc index ac5f31612..3d5819be5 100644 --- a/qcsrc/server/monsters/monster/soldier.qc +++ b/qcsrc/server/monsters/monster/soldier.qc @@ -27,6 +27,16 @@ float autocvar_g_monster_soldier_attack_shotgun_damage; float autocvar_g_monster_soldier_attack_shotgun_force; float autocvar_g_monster_soldier_attack_shotgun_spread; float autocvar_g_monster_soldier_attack_shotgun_bullets; +float autocvar_g_monster_soldier_attack_rocket_damage; +float autocvar_g_monster_soldier_attack_rocket_edgedamage; +float autocvar_g_monster_soldier_attack_rocket_radius; +float autocvar_g_monster_soldier_attack_rocket_force; +float autocvar_g_monster_soldier_attack_rocket_lifetime; +float autocvar_g_monster_soldier_attack_rocket_speed; +float autocvar_g_monster_soldier_attack_laser_damage; +float autocvar_g_monster_soldier_attack_laser_edgedamage; +float autocvar_g_monster_soldier_attack_laser_radius; +float autocvar_g_monster_soldier_attack_laser_force; // animations const float soldier_anim_die1 = 0; @@ -104,6 +114,87 @@ void soldier_uzi_fire () self.monster_delayedattack = soldier_uzi_fire; } +void soldier_rocket_explode() +{ + self.event_damage = func_null; + self.takedamage = DAMAGE_NO; + + pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1); + sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); + + RadiusDamage (self, self.realowner, autocvar_g_monster_soldier_attack_rocket_damage, autocvar_g_monster_soldier_attack_rocket_edgedamage, autocvar_g_monster_soldier_attack_rocket_radius, world, autocvar_g_monster_soldier_attack_rocket_force, self.projectiledeathtype, other); + + remove (self); +} + +void soldier_rocket_touch() +{ + PROJECTILE_TOUCH; + + soldier_rocket_explode(); +} + +void soldier_rocket_think() +{ + self.nextthink = time; + if (time > self.cnt) + { + soldier_rocket_explode(); + return; + } +} + +void soldier_rocket_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 -= damage; + self.angles = vectoangles(self.velocity); + + if (self.health <= 0) + W_PrepareExplosionByDamage(attacker, soldier_rocket_explode); +} + +void soldier_rocket_fire() +{ + entity missile; + + W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 5, "weapons/rocket_fire.wav", CH_WEAPON_A, autocvar_g_monster_soldier_attack_rocket_damage); + + missile = spawn(); + missile.owner = missile.realowner = self; + missile.classname = "rocket"; + missile.bot_dodge = TRUE; + missile.bot_dodgerating = autocvar_g_monster_soldier_attack_rocket_damage * 2; // * 2 because it can be detonated inflight which makes it even more dangerous + + missile.takedamage = DAMAGE_YES; + missile.health = 50; + missile.event_damage = soldier_rocket_damage; + missile.damagedbycontents = TRUE; + + missile.movetype = MOVETYPE_FLY; + PROJECTILE_MAKETRIGGER(missile); + missile.projectiledeathtype = DEATH_MONSTER_MARINE; + setsize (missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot + + setorigin (missile, w_shotorg - v_forward * 3); // move it back so it hits the wall at the right point + W_SetupProjectileVelocity(missile, autocvar_g_monster_soldier_attack_rocket_speed, 0); + missile.angles = vectoangles (missile.velocity); + + missile.touch = soldier_rocket_touch; + missile.think = soldier_rocket_think; + missile.nextthink = time; + missile.cnt = time + autocvar_g_monster_soldier_attack_rocket_lifetime; + missile.flags = FL_PROJECTILE; + missile.missile_flags = MIF_SPLASH; + + CSQCProjectile(missile, TRUE, PROJECTILE_ROCKET, FALSE); +} + void soldier_shotgun_fire() { float sc; @@ -113,6 +204,45 @@ void soldier_shotgun_fire() endFireBallisticBullet(); } +void soldier_laser_touch() +{ + PROJECTILE_TOUCH; + + self.event_damage = func_null; + RadiusDamage (self, self.realowner, autocvar_g_monster_soldier_attack_laser_damage, autocvar_g_monster_soldier_attack_laser_edgedamage, autocvar_g_monster_soldier_attack_laser_radius, world, autocvar_g_monster_soldier_attack_laser_force, self.projectiledeathtype, other); + + remove (self); +} + +void soldier_laser_fire() +{ + entity missile; + + W_SetupShot_Dir(self, v_forward, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_B, autocvar_g_monster_soldier_attack_laser_damage); + + missile = spawn (); + missile.owner = missile.realowner = self; + missile.classname = "laserbolt"; + PROJECTILE_MAKETRIGGER(missile); + missile.projectiledeathtype = DEATH_MONSTER_MARINE; + + setorigin (missile, w_shotorg); + setsize(missile, '0 0 0', '0 0 0'); + + W_SETUPPROJECTILEVELOCITY(missile, g_monster_soldier_attack_laser); + missile.angles = vectoangles(missile.velocity); + missile.touch = soldier_laser_touch; + + missile.flags = FL_PROJECTILE; + missile.missile_flags = MIF_SPLASH; + missile.movetype = MOVETYPE_FLY; + + missile.think = SUB_Remove; + missile.nextthink = time + 5; + + CSQCProjectile(missile, TRUE, PROJECTILE_LASER, TRUE); +} + float soldier_attack() { monsters_setframe(soldier_anim_shoot); @@ -132,7 +262,7 @@ float soldier_attack() { self.currentammo -= 1; self.attack_finished_single = time + 0.8; - W_Rocket_Attack(); + soldier_rocket_fire(); return TRUE; } case WEP_SHOTGUN: @@ -152,7 +282,7 @@ float soldier_attack() case WEP_LASER: { self.attack_finished_single = time + 0.8; - W_Laser_Attack(0); + soldier_laser_fire(); return TRUE; } default: -- 2.39.2