Hi. Recently I decided to come up with a fun mod for Rogue where multigrenades would explode and inflict damage before they subdivide on the ground. Also, they would explode AND subdivide when hitting a monster for ridiculous amounts of damage. I edited the MULT_WPN.QC file and added in the code. It seems to be working fine, except for one problem. I created a custom particle effect for multigrenade explosions specifically that is not to be shared with regular grenades (a tweaked version of multigrenade_explosion and multigrenade_explosion_nodebris). With this code applied, regular grenades shot by ogres use that explosion particle effect whenever the grenade touches the player or another monster. Here is my multigrenade code using SMC (all my editing really went into MultiGrenadeExplode and MultiGrenadeTouch):
Code:
// multi_weapons.qc // pmack // sept 96 //============================================================================= // Multi Grenade Code //============================================================================= void() MultiGrenadeTouch; //================================ //================================ void() MiniGrenadeExplode = { if ( self.owner.classname == "player") T_RadiusDamage (self, self.owner, 90, world); // do not make this value adjustable via cvar. As it only is for player_multi_grenade_explode, all other touch functions follow regular grenades else T_RadiusDamage (self, self.owner, autocvar_ogre_multi_grenade, world); // default 60 var float autocvar_explosiondebris = 0; if ( autocvar_explosiondebris == 0 ) { if (other.health) pointparticles(particleeffectnum("multigrenade_explosion_nodebris"), self.origin, '0 0 0', 1); else pointparticles(particleeffectnum("multigrenade_explosion"), self.origin, '0 0 0', 1); } else pointparticles(particleeffectnum("multigrenade_explosion"), self.origin, '0 0 0', 1); /* 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); */ sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM); BecomeExplosion (); }; //================================ //================================ void(float offsetAngle) MiniGrenadeLaunch = { local entity missile, mpuff; local float tempRand; missile = spawn (); missile.owner = self.owner; missile.movetype = MOVETYPE_BOUNCE; missile.solid = SOLID_BBOX; missile.classname = "MiniGrenade"; // set missile speed missile.v_angle = self.v_angle; missile.v_angle_y = missile.v_angle_y + offsetAngle; makevectors (missile.v_angle); missile.velocity = v_forward*100 + v_up*400; tempRand = (crandom()*60) - 30; missile.velocity = missile.velocity + tempRand * v_forward; tempRand = (crandom()*40) - 20; missile.velocity = missile.velocity + tempRand * v_right; tempRand = (crandom()*60) - 30; missile.velocity = missile.velocity + tempRand * v_up; missile.avelocity = '300 300 300'; missile.angles = vectoangles(missile.velocity); missile.touch = MultiGrenadeTouch; setmodel (missile, "progs/mervup.mdl"); setsize (missile, '0 0 0', '0 0 0'); setorigin (missile, self.origin); // set missile duration missile.nextthink = time + 1 + (crandom() * 0.5); missile.think = MiniGrenadeExplode; }; //================================ //================================ void() MultiGrenadeExplode = { if ( self.owner.classname == "player") T_RadiusDamage (self, self.owner, 90, world); // do not make this value adjustable via cvar. As it only is for player_multi_grenade_explode, all other touch functions follow regular grenades else T_RadiusDamage (self, self.owner, autocvar_ogre_multi_grenade, world); // default 60 var float autocvar_explosiondebris = 0; if ( autocvar_explosiondebris == 0 ) { if (other.health) pointparticles(particleeffectnum("multigrenade_explosion_nodebris"), self.origin, '0 0 0', 1); else pointparticles(particleeffectnum("multigrenade_explosion"), self.origin, '0 0 0', 1); } else pointparticles(particleeffectnum("multigrenade_explosion"), self.origin, '0 0 0', 1); /* 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); */ sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM); BecomeExplosion (); MiniGrenadeLaunch(0); MiniGrenadeLaunch(72); MiniGrenadeLaunch(144); MiniGrenadeLaunch(216); MiniGrenadeLaunch(288); }; //================================ //================================ void() MultiGrenadeTouch = { if (other == self.owner) return; // don't explode on owner if (other.inflamed == 1) { other.health = -100; other.nextthink = time; other.think = other.th_die; MultiGrenadeExplode(); return; } if (other.takedamage == DAMAGE_AIM) { if (self.classname == "MiniGrenade") MiniGrenadeExplode(); else { if (self.owner.classname == "player") MultiGrenadeExplode(); else MultiGrenadeExplode(); } return; } if (autocvar_evil_faces) { local float surfnum; local string s; local vector backwards; surfnum = getsurfacenearpoint(world, self.origin); if (surfnum >= 0) { s = getsurfacetexture(world, surfnum); if ((s == "altarb_1") || (s == "altarb_2") || (s == "dem4_1") || (s == "dem4_4") || (s == "dem5_3") || (s == "demc4_4")) // met5_3, metalt1_2, metalt1_7 and muh_bad are jesus faces { backwards = self.origin; backwards = backwards - 8*normalize(self.velocity); SpawnMeatSpray_eviltexture (backwards, '50 50 50'); SpawnMeatSpray_eviltexture (backwards, '50 50 50'); SpawnMeatSpray_eviltexture (backwards, '50 50 50'); SpawnMeatSpray_eviltexture (backwards, '50 50 50'); SpawnMeatSpray_eviltexture (backwards, '50 50 50'); SpawnMeatSpray_eviltexture (backwards, '50 50 50'); SpawnBlood (backwards, '0 0 0', 17); sound (self, CHAN_AUTO, "zombie/z_hit.wav", 1, ATTN_NORM); if (facetime < time) { facetime = time + 2; // only spawn a face every 2 seconds (not more/earlier) local vector face_spawn_pos, face_spawn_vel; face_spawn_vel = normalize (trace_plane_normal); face_spawn_vel = face_spawn_vel * 10; makevectors(self.angles); face_spawn_pos = self.origin - trace_plane_normal * 20; // face is spawned inside wall and comes out of it... spawn_face (face_spawn_pos, face_spawn_vel, 0); } remove(self); return; } } } // bounce sound sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM); if (self.velocity == '0 0 0') self.avelocity = '0 0 0'; }; //================================ //================================ void() W_FireMultiGrenade = { local entity missile, mpuff; self.currentammo = self.ammo_multi_rockets = self.ammo_multi_rockets - 1; UpdateAmmoCounts (self); sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM); self.punchangle_x = -2; ///////// pushback Multigrenadelauncher var float autocvar_pushback = 1; // set cvar 'pushback' default to 1 if (autocvar_pushback != 0) // if 'pushback' is other than '0', pushback is enabled { var float autocvar_pushbackmultigrenade = 75; // set cvar 'pushbackmultigrenade' default to 70 local vector pushback1, direc; direc = aim (self, 100); traceline (self.origin, self.origin + direc*autocvar_pushbackmultigrenade, FALSE, self); pushback1 = (trace_endpos - self.origin); // + (normalize(direc) * 80); self.velocity = self.velocity - pushback1; } missile = spawn (); missile.cansplash = TRUE; missile.owner = self; missile.movetype = MOVETYPE_BOUNCE; missile.solid = SOLID_BBOX; missile.classname = "MultiGrenade"; // set missile speed makevectors (self.v_angle); if (self.v_angle_x) missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10; else { missile.velocity = aim(self, 10000); missile.velocity = missile.velocity * 600; missile.velocity_z = 200; } missile.avelocity = '300 300 300'; missile.angles = vectoangles(missile.velocity); missile.touch = MultiGrenadeTouch; // set missile duration missile.nextthink = time + 1; missile.think = MultiGrenadeExplode; setmodel (missile, "progs/mervup.mdl"); setsize (missile, '0 0 0', '0 0 0'); setorigin (missile, self.origin); };
Comment