Announcement

Collapse
No announcement yet.

Multigrenade Mod Bug

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Multigrenade Mod Bug

    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);
    };
    Steel Sentinels remake project developer since 2012.

  • #2
    @Pringles

    If you take a look in Orge.qc you will notice at the top this:

    Code:
    void() OgreGrenadeExplode =
    {
        var float autocvar_ogre_size_influenced_attack = 0; 	  		// set cvar 'ogre_size_influenced_attack' default to 0
    	if (autocvar_ogre_size_influenced_attack == 1)				// if 'ogre_size_influenced_attack' is set via autoexec.cfg to '1' raise monster�s attack values according to its size 
    		T_RadiusDamage (self, self.owner, autocvar_ogre_grenade * self.owner.scale, world);	// default 40
    	else
    		T_RadiusDamage (self, self.owner, autocvar_ogre_grenade, world);	// default 40
    	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);
    */
    	var float autocvar_explosiondebris = 0;
    	if ( autocvar_explosiondebris == 0 )
    	{
    		[COLOR="Lime"]if (other.health)
    			pointparticles(particleeffectnum("[COLOR="Red"]multigrenade_explosion_nodebris[/COLOR]"), self.origin, '0 0 0', 1);[/COLOR]
    		else
    			pointparticles(particleeffectnum("grenade_explosion"), self.origin, '0 0 0', 1);
    	}
    	else
    		pointparticles(particleeffectnum("grenade_explosion"), self.origin, '0 0 0', 1);
    
    	self.velocity = '0 0 0';
    	self.touch = SUB_Null;
    	setmodel (self, "progs/s_explod.spr");
    	self.solid = SOLID_NOT;
    	s_explode1 ();
    };
    As you can see this is the regular ogre's attack. And it uses that same effect you changed for regular grens if other has health.

    Also Boss Orge will also use this effect because they utilize MultiGrenadeTouch and Explode from the mult_wp.qc. You can see this in OgreFireGrenade () in orge.qc.

    Code:
    	if(self.spawnflags & OGRE_BOSS)
    	{
    		missile.touch = [COLOR="lime"]MultiGrenadeTouch;[/COLOR]
    		missile.nextthink = time + 2.5;
    		missile.think = [COLOR="lime"]MultiGrenadeExplode;[/COLOR]
    		setmodel (missile, "progs/mervup.mdl");
    		setsize (missile, '0 0 0', '0 0 0');		
    		setorigin (missile, self.origin);
    		missile.classname = "MultiGrenade";
    	}
    A few ways to deal with this. A simple one for the Regular Orge Grenade problem is just take out the reference to using the multigrenade effect all together but I don't like that option.
    You can make a more default version of the effects you tweaked and rename them something else. Like multigrenade_explosion2 and multigrenade_explosion_nodebris2. Place them in your effectsinfo.txt. As long as they match the qc reference you can name them what you want.

    Example:

    Code:
    //explosion - bouble
    [COLOR="lime"]effect multigrenade_explosion_nodebris2 [/COLOR]
    underwater
    count 66
    type bubble
    tex 62 63
    size 0.2 0.8                       
    alpha 128 256 64
    gravity -0.125
    bounce 1.5
    liquidfriction 1
    originjitter 10 10 10
    Also depends on how many of these you tweaked as there are several for different conditions. Like say if underwater, vs not underwater, etc.

    Then you can change out the regular ogre one in the first part of the orge.qc with this new one that is more like the default. As for the boss orge, if you don't want him to use that effect but use the new one then you can just make an exception in the multigrenadeexplosion:

    Code:
    [COLOR="Lime"]if ((other.health) && ( self.owner.classname == "player"))[/COLOR]
          {
           pointparticles(particleeffectnum("multigrenade_explosion_nodebris"), self.origin, '0 0 0', 1);
    	else
           pointparticles(particleeffectnum("multigrenade_explosion"), self.origin, '0 0 0', 1);
          }
    [COLOR="lime"]else if ((other.health) && ( !self.owner.classname == "player"))[/COLOR]
         {
                pointparticles(particleeffectnum("[COLOR="lime"]multigrenade_explosion_nodebris2[/COLOR]"), self.origin, '0 0 0', 1);
    	else
    	    pointparticles(particleeffectnum("[COLOR="Lime"]multigrenade_explosion2[/COLOR]"), self.origin, '0 0 0', 1);
          }
    Something like that I think.

    Comment


    • #3
      It's working properly now. Thanks.
      Steel Sentinels remake project developer since 2012.

      Comment

      Working...
      X