Game Development Community

Weapon fire change

by Nick "Steve" DeChiara · in Torque 3D Professional · 05/02/2009 (11:27 am) · 13 replies

I was doing some work to add a shotgun to the FPS kit, and modified the onfire function a bit

(game/scripts/server/weapon.cs)
function WeaponImage::onFire(%this, %obj, %slot)
{
    //echo("\c4WeaponImage::onFire( "@%this.getName()@", "@%obj.client.nameBase@", "@%slot@" )");

    // Decrement inventory ammo. The image's ammo state is updated
    // automatically by the ammo inventory hooks.
    %obj.decInventory(%this.ammo, 1);
	%iscc = %this.projectileCount;
	if(!%iscc){
		%iscc=1;
	}
    //echo(%iscc);
    for(%isc=0; %isc < %iscc; %isc++){
    	%matrix="";
    	if (%this.projectileSpread)
    	{
    	    // We'll need to "skew" this projectile a little bit.  We start by
    	    // getting the straight ahead aiming point of the gun
    	    %vec = %obj.getMuzzleVector(%slot);

    	    // Then we'll create a spread matrix by randomly generating x, y, and z
    	    // points in a circle
	    %spreadadd=%this.projectileSpread;
	    %playervel=getword(%obj.client.player.getvelocity(),0) + getword(%obj.client.player.getvelocity(),1);
	    if(%playervel > 3 || %playervel < -3){
		%spreadadd+=%this.movingSpread;
	    }
	    %playerjump = getword(%obj.client.player.getvelocity(),2);
	    if(%playerjump>1 || %playerjump<-1){
		%spreadadd+=%this.jumpSpread;
	    }
    	    for(%i = 0; %i < 3; %i++)
    	        %matrix = %matrix @ (getRandom() - 0.5) * 2 * 3.1415926 * %spreadadd @ " ";
    	        %mat = MatrixCreateFromEuler(%matrix);

    	    // Which we'll use to alter the projectile's initial vector with
    	    %muzzleVector = MatrixMulVector(%mat, %vec);
    	}
    	else
    	{
    	    // Weapon doesn't have a spread factor so we fire it using the
    	    // straight ahead aiming point of the gun
    	    %muzzleVector = %obj.getMuzzleVector(%slot);
    	}

    	// Get the player's velocity, we'll then add it to that of the projectile
    	%objectVelocity = %obj.getVelocity();
    	%muzzleVelocity = VectorAdd(
            VectorScale(%muzzleVector, %this.projectile.muzzleVelocity + getrandom(%this.projectile.velocityVariance * -1, %this.projectile.velocityVariance)),
            VectorScale(%objectVelocity, %this.projectile.velInheritFactor));

    	// Create the projectile object
    	%p = new (%this.projectileType)()
    	{
    	    dataBlock = %this.projectile;
    	    initialVelocity = %muzzleVelocity;
    	    initialPosition = %obj.getMuzzlePoint(%slot);
    	    sourceObject = %obj;
    	    sourceSlot = %slot;
    	    client = %obj.client;
    	};
    	MissionCleanup.add(%p);
    }
    // Do some recoil if this weapon has the required field:  recoilType
    if (%this.recoilType !$= "")
        CommandToClient(%obj.client, 'DoRecoil', %this.recoilType);

    return %p;
}

What this does:
-a weapon can shoot multiple projectiles at once
-weapons that have no "projectileCount" set will have it default to 1
-a weapon can be less accurate when the player is moving
-a weapon can be less accurate when the player is jumping(although this is a very basic system which should be expanded upon)
-adds velocityVariance for projectiles

(from the shotgun I added)
//scripted spread system
    projectileSpread = 0.003;
    movingSpread = 0.005;
    jumpSpread = 0.002;

    //projectile count
    projectileCount = 10;

I'd love to see some of these changes in the final release, or at least reproduced by a better scripter than I. But, for the moment, this is mainly a resource for anyone who wants to mess around with the weapons.

Things you can help me with:
-is there anything wrong with the script?
-anyone know how I could improve the jump spread check?

Also: I know there are some indentation issues, I script in a font called terminal so they only show up as wrong here. Just my luck.

Update: cleaned up the movement detection code and thus fixed an issue where standing on a slope would count as moving.
I also added velocityVariance to projectiles, and cleaned up the jump detection code which hopefully should work better now.

#1
05/02/2009 (11:41 am)
We've done shotguns in the past in Torque using raycasts which performs much better than networking 10 projectiles.

In reality what we would want is a SpreadProjectile that can be networked as a single object but internally manages collision for multiple shots.

If i had time i would write this C++ class derived from Projectile... but so far i've not had a chance.

Someone feel like taking on this project?
#2
05/02/2009 (12:07 pm)
I actually removed the shotgun stuff the week before beta. Tom's suggestion is one I've been wanting to try, along with other projectile types.
#3
05/02/2009 (12:33 pm)
Well, I work with what I'm given.

I would like to see more projectile types, however, or at least a built-in hitscan projectile type.

In the meantime, I'm adding some more values to this, and still trying to fix the jump-spread check.
#4
05/02/2009 (12:56 pm)
We had a machinegun also but it had gotten cut, I was thinking about linking the bullet skew with the lame recoil effect that annoys me. I like your idea of run-spread and jump-spread. If you want to see it incorporated in the FPS kit (basic) I'll be more than happy to drop it in.

One problem that I had noticed with multiple projectiles at once was the network traffic when 20 bots had shotguns. The same 20 bots with the rocketlauncher had a much smaller footprint.
#5
05/02/2009 (3:14 pm)
I'd love to see it incorporated, but you'd probably need a better jump-spread check as mine is unreliable.

If a raycast-projectile type or the aforementioned spreadProjectile was added, shotguns would be much more efficient.

If you don't mind me asking, why does the recoil effect annoy you?
#6
05/02/2009 (3:23 pm)
Quote:If you don't mind me asking, why does the recoil effect annoy you?
I thought it was a pretty neat effect, until I started experimenting with AI -- trying to shoot something became ridiculously hard if you missed that first shot with anything other than the Steam Pistol. It's also one of those things that could be better incorporated in source code rather than the $mvPitch/$mvYaw trick I used -- case in point was the machine gun which could literally spin you completely around.
#7
05/02/2009 (4:07 pm)
Hm, I'm working with the recoil now.

Here's what I have so far
function clientCmdDoRecoil(%type)
{
   switch$ (%type)
   {
      case "Light":
         $mvPitch += getrandom(-4,-6)/1000;//getrandom(-4,-6)/1000;
	 %yaw=getrandom(-4,4);
	 %yaw /= 1000;
	 $mvYaw += %yaw;
         //$mvYaw += getRandom() ? 0.004 : -0.004;
      case "Moderate":
         $mvPitch += getrandom(-1,-2)/100;
	 %yaw=getrandom(-8,8);
	 %yaw /= 1000;
	 $mvYaw += %yaw;
         //$mvYaw += getRandom() ? 0.008 : -0.008;
      case "High":
         $mvPitch += getrandom(-3,-5)/100;//high is moderate, but more forceful push upwards.
	 %yaw=getrandom(-8,8);
	 %yaw /= 1000;
	 $mvYaw += %yaw;
         //$mvYaw += getRandom() ? 0.008 : -0.008;
      case "Heavy":
         $mvPitch += getrandom(-4,-6)/100;
	 %yaw=getrandom(-2,2);
	 %yaw /= 100;
	 $mvYaw += %yaw;
         //$mvYaw += getRandom() ? 0.02 : -0.02;
      case "Extreme":
         $mvPitch += getrandom(-1,-2)/10;
	 %yaw=getrandom(-4,4);
	 %yaw /= 100;
	 $mvYaw += %yaw;
         //$mvYaw += getRandom() ? 0.1 : -0.1;
      case "Hit":
         $mvPitch += getrandom(4,-4)/100;
	 %yaw=getrandom(-8,8);
	 %yaw /= 1000;
	 $mvYaw += %yaw;
         //$mvYaw += getRandom() ? 0.008 : -0.008;
   }
}

Result is a much more controlled recoil that arcs off to either side much smoother. I'm going to keep working with it, but first I need to make a fast firing gun to test it out a bit more.

Update: added a SMG-type weapon, and it works great. It pushes up against you but its still accurate once you get used to it.
Also updated the code above, making the pitch randomized as well and adding a "High" recoil type.
#8
05/02/2009 (5:09 pm)
Hey! That works pretty well. What I had seemed to only yaw to the left about 1 out 5 times. It bounces back and forth better now. I originally had half a dozen or so different settings for recoil, and thought about moving the random amount fields into the datablock so that each weapon could have it's own unique settings. In the end though... simplicity won out.

I'll definitely add your changes in to the FPS(basic) kit when I get home where my svn accessible computer is at.
#9
05/02/2009 (6:00 pm)
If the functionality you have there in that script is fairly flexible we should just move it into C++... putting the random ranges for pitch and yaw into the ImageData and calling a function to move the input within Player::updateMove().

This would make it a completely client side and driven directly by the weapon state machine logic taking up zero network bandwidth.
#10
05/02/2009 (7:40 pm)
If you move it into C++, add a script-sided way to add new recoil types.
#11
05/04/2009 (9:57 am)
There's a handful of script methods that I would like to move into C++, but for the purposes of a basic FPS kit it's been indicated to me that I/we should keep using script -- trying to maintain as much as possible a non-genre specific C++ codebase I guess. However, it is something that should definitely be done for the advanced FPS kit.
#12
05/04/2009 (7:08 pm)
Update:

I made it so that when a player takes damage, they also take a minor recoil effect.

in games/scripts/server/player.cs

%obj.applyDamage(%damage);//line 184
    CommandToClient(%obj.client, 'DoRecoil', "Hit");//add this

I also updated my recoil code above to reflect this. The recoil values on it may need some tweaking, though.
#13
05/04/2009 (9:52 pm)
You've taken that and ran with it. Which is just awesome! I'm glad to see someone inspired to add a little extra code to what I had.

I'm planning on a concussion grenade effect that will be tied into the DoRecoil function also -- that thing ended up being more versatile than I thought it would.