Inside3D tutorials.
/* =============================================================================== ENEMY WEAPONS--START CODE =============================================================================== */ /* =============================================================================== ENEMY WEAPONS--END CODE =============================================================================== */You may be thinking 'wellthat was useless.' Well, you're pretty much correct. But, I findit always helps me keep my bearings to have a 'start' and 'end'to work between. So, when you do this tutorial, make sureeverything goes BETWEEN those two things. Not necessary, but muchcleaner. Anyways, Step 1 will be for making monsters fire ashotgun. You can use the same code in army_fire from soldier.qc .So paste this in:
//Enemy Shotgun void() Enemy_Fire_Shotgun = { local vector dir; local entity en; ai_face(); sound (self, CHAN_WEAPON, "soldier/sattck1.wav", 1,ATTN_NORM); en = self.enemy; dir = en.origin - en.velocity*0.2; dir = normalize (dir - self.origin); FireBullets (4, dir, '0.1 0.1 0'); };And while your there, copy and paste the same thing right below it with the changes in RED to do the super shotgun.
//Enemy Super Shotgun void() Enemy_Fire_SupShotgun = { local vector dir; local entity en; ai_face(); sound (self, CHAN_WEAPON, "soldier/sattck1.wav", 1,ATTN_NORM); en = self.enemy; dir = en.origin - en.velocity*0.2; dir = normalize (dir - self.origin); FireBullets (12, dir, '0.1 0.1 0'); };Alright, now all yourmonsters can shoot either shotgun.
//Enemy Nailgun void() Enemy_Fire_Nailgun = { local vector dir; sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1,ATTN_NORM); dir = normalize (self.enemy.origin - self.origin); launch_spike (self.origin + '0 0 16', dir); };Alright,there's the nailgun code, now super...
//Enemy SuperNailgun void() Enemy_Fire_SNailgun = { local vector dir; sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1,ATTN_NORM); dir = normalize (self.enemy.origin - self.origin); launch_spike (self.origin + '0 0 16', dir); newmis.touch = superspike_touch; setmodel (newmis, "progs/s_spike.mdl"); setsize (newmis, VEC_ORIGIN, VEC_ORIGIN); };
void() W_Precache = { precache_sound ("weapons/r_exp3.wav"); precache_sound ("weapons/rocket1i.wav"); precache_sound ("weapons/sgun1.wav"); precache_sound ("weapons/guncock.wav"); precache_sound ("weapons/ric1.wav"); precache_sound ("weapons/ric2.wav"); precache_sound ("weapons/ric3.wav"); precache_sound ("weapons/spike2.wav"); precache_sound ("weapons/tink1.wav"); precache_sound ("weapons/grenade.wav"); precache_sound ("weapons/bounce.wav"); precache_sound ("weapons/shotgn2.wav"); precache_model("progs/laser.mdl"); precache_sound("enforcer/enfire.wav"); precache_sound ("enforcer/enfstop.wav"); };Now add this:
void()Enemy_Laser_Touch = { local vector org; if (other == self.owner) return; // don't explode on owner if (pointcontents(self.origin) == CONTENT_SKY) { remove(self); return; } sound (self, CHAN_WEAPON, "enforcer/enfstop.wav", 1,ATTN_STATIC); org = self.origin - 8*normalize(self.velocity); if (other.health) { SpawnBlood (org, self.velocity*0.2, 15); T_Damage (other, self, self.owner, 15); } else { WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); WriteByte (MSG_BROADCAST, TE_GUNSHOT); WriteCoord (MSG_BROADCAST, org_x); WriteCoord (MSG_BROADCAST, org_y); WriteCoord (MSG_BROADCAST, org_z); } remove(self); }; void(vector org, vector vec) Enemy_LaunchLaser = { local vector vec; if (self.classname == "monster_enforcer") sound (self, CHAN_WEAPON, "enforcer/enfire.wav", 1,ATTN_NORM); vec = normalize(vec); newmis = spawn(); newmis.owner = self; newmis.movetype = MOVETYPE_FLY; newmis.solid = SOLID_BBOX; newmis.effects = EF_DIMLIGHT; setmodel (newmis, "progs/laser.mdl"); setsize (newmis, '0 0 0', '0 0 0'); setorigin (newmis, org); newmis.velocity = vec * 600; newmis.angles = vectoangles(newmis.velocity); newmis.nextthink = time + 5; newmis.think = SUB_Remove; newmis.touch = Enemy_Laser_Touch; }; void() Enemy_Fire_Laser = { local vector org; self.effects = self.effects | EF_MUZZLEFLASH; makevectors (self.angles); org = self.origin + v_forward * 30 + v_right * 8.5 + '0 0 16'; Enemy_LaunchLaser(org, self.enemy.origin - self.origin); };
//Enemy Grenade void() EnemyGrenadeExplode = { T_RadiusDamage (self, self.owner, 40, world); sound (self, CHAN_VOICE, "weapons/r_exp3.wav", 1,ATTN_NORM); WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); WriteByte (MSG_BROADCAST, TE_EXPLOSION); WriteCoord (MSG_BROADCAST, self.origin_x); WriteCoord (MSG_BROADCAST, self.origin_y); WriteCoord (MSG_BROADCAST, self.origin_z); self.velocity = '0 0 0'; self.touch = SUB_Null; setmodel (self, "progs/s_explod.spr"); self.solid = SOLID_NOT; s_explode1 (); }; void() EnemyGrenadeTouch = { if (other == self.owner) return; // don't explode on owner if (other.takedamage == DAMAGE_AIM) { EnemyGrenadeExplode(); return; } sound (self, CHAN_VOICE, "weapons/bounce.wav", 1,ATTN_NORM); // bounce sound if (self.velocity == '0 0 0') self.avelocity = '0 0 0'; }; void() Enemy_Fire_Grenade = { local entity missile; self.effects = self.effects | EF_MUZZLEFLASH; sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1,ATTN_NORM); missile = spawn (); missile.owner = self; missile.movetype = MOVETYPE_BOUNCE; missile.solid = SOLID_BBOX; // set missile speed makevectors (self.angles); missile.velocity = normalize(self.enemy.origin - self.origin); missile.velocity = missile.velocity * 600; missile.velocity_z = 200; missile.avelocity = '300 300 300'; missile.angles = vectoangles(missile.velocity); missile.touch = EnemyGrenadeTouch; // set missile duration missile.nextthink = time + 2.5; missile.think = EnemyGrenadeExplode; setmodel (missile, "progs/grenade.mdl"); setsize (missile, '0 0 0', '0 0 0'); setorigin (missile, self.origin); };
//Enemy Rocket void() T_EnemyMisTouch = { local float damg; if (other == self.owner) return; // don't explode on owner if (pointcontents(self.origin) == CONTENT_SKY) { remove(self); return; } damg = 10 + random()*2; if (other.health) { if (other.classname == "monster_shambler") damg = damg * 0.5; // mostly immune T_Damage (other, self, self.owner, damg ); } T_RadiusDamage (self, self.owner, 10, other); //Changed from 120to 10 self.origin = self.origin - 8*normalize(self.velocity); WriteByte (MSG_BROADCAST, SVC_TEMPENTITY); WriteByte (MSG_BROADCAST, TE_EXPLOSION); WriteCoord (MSG_BROADCAST, self.origin_x); WriteCoord (MSG_BROADCAST, self.origin_y); WriteCoord (MSG_BROADCAST, self.origin_z); BecomeExplosion (); }; void() W_EnemyRocket = { local entity missile; sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1,ATTN_NORM); missile = spawn (); missile.owner = self; missile.movetype = MOVETYPE_FLYMISSILE; missile.solid = SOLID_BBOX; missile.classname = "missile"; missile.velocity = normalize(self.enemy.origin - self.origin); missile.velocity = missile.velocity * 600; missile.angles = vectoangles(missile.velocity); missile.touch = T_EnemyMisTouch; missile.nextthink = time + 5; missile.think = SUB_Remove; setmodel (missile, "progs/missile.mdl"); setsize (missile, '0 0 0', '0 0 0'); setorigin (missile, self.origin + v_forward*8 + '0 0 16'); }; void() Enemy_Fire_Rocket = { local vector dir; local entity en; ai_face(); sound (self, CHAN_WEAPON, "soldier/sattck1.wav", 1,ATTN_NORM); en = self.enemy; dir = en.origin - en.velocity*0.2; dir = normalize (dir - self.origin); W_EnemyRocket(); };Wow....that was loooong...anyways, we're almost done. In fact, you could skipthis next step if you want, but I think it's more fun this way.
//EnemyRandomizer void() Enemy_Weapons_Random = { local float ewrandom; ewrandom = random(); if (ewrandom < 0.16 ) Enemy_Fire_Shotgun(); else if ((ewrandom > 0.15) && (ewrandom < 0.32) Enemy_Fire_SupShotgun(); else if ((ewrandom > 0.31) && (ewrandom < 0.48) Enemy_Fire_Nailgun(); else if ((ewrandom > 0.47) && (ewrandom < 0.64) Enemy_Fire_SNailgun(); else if ((ewrandom > 0.63) && (ewrandom < 0.8) Enemy_Fire_Grenade(); else if ((ewrandom > 0.79) && (ewrandom < 0.96) Enemy_Fire_Rocket(); else Enemy_Fire_Shotgun(); };
void()enf_atk6 =[ $attack6, enf_atk7 ] {enforcer_fire();}; void() enf_atk10 =[ $attack6, enf_atk11 ] {enforcer_fire();}; Change them to: void()enf_atk6 =[ $attack6, enf_atk7 ] {Enemy_Weapons_Random();}; void() enf_atk10 =[ $attack6, enf_atk11 ]{Enemy_Weapons_Random();};
void()ogre_nail4 =[ $shoot3, ogre_nail5 ]{ai_face();OgreFireGrenade();}; Change to: void()ogre_nail4 =[ $shoot3, ogre_nail5 ]{ai_face();Enemy_Weapons_Random();};
void()army_atk5 =[ $shoot5, army_atk6 ] {ai_face();army_fire(); Change to: void()army_atk5 =[ $shoot5, army_atk6 ]{ai_face();Enemy_Weapons_Random();Of course, you can apply this to more monsters, but these three are the best for it.