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