Class: WeaponAssaultGun - Damn Burst Fire!

A refuge for those migrating from the fallen DXEditing.com and a place for general discussion relating to Deus Ex editing (coding, mapping, etc).
Post Reply
Gestalt17
Mole Person
Posts: 4
Joined: Fri Feb 04, 2011 6:08 am

Class: WeaponAssaultGun - Damn Burst Fire!

Post by Gestalt17 »

Is there any way to modify the WeaponAssaultGun.uc file so that despite being an automatic weapon, quickly pressing the mouse button would fire only 1 round instead of several? I've looked through the code, but cannot determine where the game controls how many rounds are fired with each quick mouse-click.

It's funny, 'cos the WeaponAssaultShotgun seems to have a lot more code, and yet I can comfortably expel single shells with a quick mouse-click whenever I want to conserve ammo.

(BTW, is it true that the actual number of rounds fire in a burst varies with Rifle Skill?)

Thanks.

Code: Select all

//=============================================================================
// WeaponAssaultGun.
//=============================================================================
class WeaponAssaultGun extends DeusExWeapon;

var float	mpRecoilStrength;

simulated function PreBeginPlay()
{
	Super.PreBeginPlay();

	// If this is a netgame, then override defaults
	if ( Level.NetMode != NM_StandAlone )
	{
		HitDamage = mpHitDamage;
		BaseAccuracy = mpBaseAccuracy;
		ReloadTime = mpReloadTime;
		AccurateRange = mpAccurateRange;
		MaxRange = mpMaxRange;
		ReloadCount = mpReloadCount;

		// Tuned for advanced -> master skill system (Monte & Ricardo's number) client-side
		recoilStrength = 0.75;
	}
}

defaultproperties
{
     LowAmmoWaterMark=30
     FireAnim(1)=None
     GoverningSkill=Class'DeusEx.SkillWeaponRifle'
     EnviroEffective=ENVEFF_Air
     Concealability=CONC_Visual
     bAutomatic=True
     ShotTime=0.100000
     reloadTime=3.000000
     HitDamage=8
     BaseAccuracy=0.700000
     bCanHaveScope=True
     bCanHaveLaser=True
     bCanHaveSilencer=True
     FireSound2=Sound'DeusExSounds.Weapons.AssaultGunFire20mm'
     AmmoNames(0)=Class'DeusEx.Ammo762mm'
     AmmoNames(1)=Class'DeusEx.Ammo20mm'
     ProjectileNames(1)=Class'DeusEx.HECannister20mm'
     recoilStrength=0.500000
     MinWeaponAcc=0.200000
     mpReloadTime=0.500000
     mpHitDamage=9
     mpBaseAccuracy=1.000000
     mpAccurateRange=2400
     mpMaxRange=2400
     mpReloadCount=30
     bCanHaveModBaseAccuracy=True
     bCanHaveModReloadCount=True
     bCanHaveModAccurateRange=True
     bCanHaveModReloadTime=True
     bCanHaveModRecoilStrength=True
     bCanHaveModShotTime=True
     AmmoName=Class'DeusEx.Ammo762mm'
     ReloadCount=30
     PickupAmmoCount=30
     bInstantHit=True
     FireOffset=(X=-16.000000,Y=5.000000,Z=11.500000)
     shakemag=200.000000
     FireSound=Sound'DeusExSounds.Weapons.AssaultGunFire'
     AltFireSound=Sound'DeusExSounds.Weapons.AssaultGunReloadEnd'
     CockingSound=Sound'DeusExSounds.Weapons.AssaultGunReload'
     SelectSound=Sound'DeusExSounds.Weapons.AssaultGunSelect'
     InventoryGroup=4
     ItemName="Assault Rifle"
     ItemArticle="an"
     PlayerViewOffset=(X=16.000000,Y=-5.000000,Z=-11.500000)
     PlayerViewMesh=LodMesh'DeusExItems.AssaultGun'
     PickupViewMesh=LodMesh'DeusExItems.AssaultGunPickup'
     ThirdPersonMesh=LodMesh'DeusExItems.AssaultGun3rd'
     LandSound=Sound'DeusExSounds.Generic.DropMediumWeapon'
     Icon=Texture'DeusExUI.Icons.BeltIconAssaultGun'
     largeIcon=Texture'DeusExUI.Icons.LargeIconAssaultGun'
     largeIconWidth=94
     largeIconHeight=65
     invSlotsX=2
     invSlotsY=2
     Description="The 7.62x51mm assault rifle is designed for close-quarters combat, utilizing a shortened barrel and 'bullpup' design for increased maneuverability. An additional underhand 20mm HE launcher increases the rifle's effectiveness against a variety of targets."
     beltDescription="ASSAULT"
     Mesh=LodMesh'DeusExItems.AssaultGunPickup'
     CollisionRadius=15.000000
     CollisionHeight=1.100000
     Mass=30.000000
}

Gestalt17
Mole Person
Posts: 4
Joined: Fri Feb 04, 2011 6:08 am

Re: Class: WeaponAssaultGun - Damn Burst Fire!

Post by Gestalt17 »

Sorry for double post.

Played around with the ShotTime variable. I found that at the default 0.100000, the assault rifle expends 5 rounds with a single click (at Master Rifles skill). Putting this up to 0.500000, it only fires one round (yay!), but I noticed how the firing animation plays out for quite a while. To confirm my suspicions that the no. of rounds fired was somehow linked to the firing animation, I tried 0.200000 for ShotTime... and found that the firing animation time was still the same, only this time the rifle spat three rounds...

I want to try and somehow modify the rifle firing animation (hopefully just the code which determines which frames to play, and not the actually animation/mesh file itself) so that the animation lasts short enough to only fire one round with a single click (and of course, keep looping that short burst if I hold down the mouse button for full auto)... so where can I find the file to do that in?
Darma
UNATCO
Posts: 151
Joined: Wed Apr 15, 2009 2:20 pm

Re: Class: WeaponAssaultGun - Damn Burst Fire!

Post by Darma »

woo, long time I did not came here

well, the skill only affect
-->Accuracy
-->Grenade explose time (for grenades)
-->Lock time (gepgun)
-->Recoil
-->Damage
but I didn't find anything about the number of rounds
Source = DeusExWeapon.uc

Second about the mesh animation speed,
it is controled by "PlayAnim" a function which play an animation in a mesh. This one is somewhere in DeusExWeapon/Weapon.uc but I don't have enough time to look.
The function is as following:
PlayAnim( name Sequence, optional float Rate, optional float TweenTime );
Change the second variable called the Rate which will edit.... well the rate of the animation.

hope it helped, take a look at deusexweapon and search for playanim @ the one which show the firing animation

EDIT: it is Loopanim( name Sequence, optional float Rate, optional float TweenTime, optional float MinRate );

located in this function in deusexweapon:

Code: Select all

simulated function PlaySelectiveFiring()
{
	local Pawn aPawn;
	local float rnd;
	local Name anim;

	anim = 'Shoot';

	if (bHandToHand)
	{
		rnd = FRand();
		if (rnd < 0.33)
			anim = 'Attack';
		else if (rnd < 0.66)
			anim = 'Attack2';
		else
			anim = 'Attack3';
	}

	if (( Level.NetMode == NM_Standalone ) || ( DeusExPlayer(Owner) == DeusExPlayer(GetPlayerPawn())) )
	{
		if (bAutomatic)
			LoopAnim(anim,, 0.1);
		else
			PlayAnim(anim,,0.1);
	}
	else if ( Role == ROLE_Authority )
	{
		for ( aPawn = Level.PawnList; aPawn != None; aPawn = aPawn.nextPawn )
		{
			if ( aPawn.IsA('DeusExPlayer') && ( DeusExPlayer(Owner) != DeusExPlayer(aPawn) ) )
			{
				// If they can't see the weapon, don't bother
				if ( DeusExPlayer(aPawn).FastTrace( DeusExPlayer(aPawn).Location, Location ))
					DeusExPlayer(aPawn).ClientPlayAnimation( Self, anim, 0.1, bAutomatic );
			}
		}
	}
}
there, good luck
Gestalt17
Mole Person
Posts: 4
Joined: Fri Feb 04, 2011 6:08 am

Re: Class: WeaponAssaultGun - Damn Burst Fire!

Post by Gestalt17 »

Thanks for the reply Darma.

Yep, found the matching section in DeusExWeapon.uc... turns out that since I am using Shifter v1.8.3, Y|yukichigai had some fun modifying it to support functionality for his RoF weapon modification. Code looks pretty much the same though.

Compared to the 'vanilla' code, it looks like Yuki (mind if I call him Yuki? heh) actually used the "optional float Rate" argument of both the PlayAnim and LoopAnim functions:

Code: Select all

		//== Speed up the firing animation if we have the ROF mod
		mod = 1.000000 - ModShotTime;
		if (bAutomatic)
			LoopAnim(anim,FireRate * mod, 0.1);
		else
			PlayAnim(anim,FireRate * mod,0.1);
Given the context, I'm assuming the purpose of that change was to modify (increase) the *rate* at which the game loops the weapon's attack animation, to simulate automatic fire in a way that matches the RoF stat changes applied. (Hope that made sense)

I've thought about this for a long while, but I don't know how to modify the "optional float Rate" argument here to help decrease the actual play time of the firing animation (which should ultimately & hopefully make it short enough to fire off only one round from the magazine), without disturbing Yuki's RoF functionality. To be honest, I'm not even sure if I should be modifying the "optional float Rate" argument in the first place!

Anyone got any ideas? (Man, hope Yuki is reading this! :) )
Darma
UNATCO
Posts: 151
Joined: Wed Apr 15, 2009 2:20 pm

Re: Class: WeaponAssaultGun - Damn Burst Fire!

Post by Darma »

hum, yeah the purpose of that code is to edit the rate of the anim but I'm not really sure of how it works
for what I see you can edit the "ModShotTime" var value in the defaults which will have an effect on the anim speed somehow...
Allan
NSF
Posts: 52
Joined: Thu Apr 16, 2009 4:54 pm

Re: Class: WeaponAssaultGun - Damn Burst Fire!

Post by Allan »

Code: Select all

simulated function PlaySelectiveFiring()
{
	local Pawn aPawn;
	local float rnd;
	local Name anim;
	local float mod;

	anim = 'Shoot';

	if (bHandToHand)
	{
		rnd = FRand();
		if (rnd < 0.33)
			anim = 'Attack';
		else if (rnd < 0.66)
			anim = 'Attack2';
		else
			anim = 'Attack3';
	}

	if (( Level.NetMode == NM_Standalone ) || ( DeusExPlayer(Owner) == DeusExPlayer(GetPlayerPawn())) )
	{
		mod = 1.000000;
//		mod -= ModShotTime;
		if (bAutomatic)
			LoopAnim(anim, 1.0 * mod ,0.1);
		else
			PlayAnim(anim, 1.0 * mod ,0.1);
	}
	else if ( Role == ROLE_Authority )
	{
		for ( aPawn = Level.PawnList; aPawn != None; aPawn = aPawn.nextPawn )
		{
			if ( aPawn.IsA('DeusExPlayer') && ( DeusExPlayer(Owner) != DeusExPlayer(aPawn) ) )
			{
				// If they can't see the weapon, don't bother
				if ( DeusExPlayer(aPawn).FastTrace( DeusExPlayer(aPawn).Location, Location ))
					DeusExPlayer(aPawn).ClientPlayAnimation( Self, anim, 0.1, bAutomatic );
			}
		}
	}
}

state NormalFire
{
	function AnimEnd()
	{
		if (bAutomatic)
		{
			if ((Pawn(Owner).bFire != 0) && (AmmoType.AmmoAmount > 0))
			{
				if (PlayerPawn(Owner) != None)
					Global.Fire(0);
				else 
					GotoState('FinishFire');
			}
			else 
				GotoState('FinishFire');
		}
		else
		{
			// if we are a thrown weapon and we run out of ammo, destroy the weapon
			if (bHandToHand && (ReloadCount > 0) && (AmmoType.AmmoAmount <= 0))
				Destroy();
		}
	}

	function float GetShotTime()
	{
		local float mult, sTime;

		if (ScriptedPawn(Owner) != None)
			return ShotTime * (ScriptedPawn(Owner).BaseAccuracy*2+1);
		else
		{
			// AugCombat decreases shot time
			mult = 1.0;
			if (bHandToHand && DeusExPlayer(Owner) != None)
			{
				mult = 1.0 / DeusExPlayer(Owner).AugmentationSystem.GetAugLevelValue(class'AugCombat');
				if (mult == -1.0)
					mult = 1.0;
			}
//			else if(!bHandToHand && DeusExPlayer(Owner) != None)
//			{
//				mult = 1.0 / modShotTime;
//				if(mult <= 0)
//					mult = 1.0;
//			}
			sTime = ShotTime * mult;
			return (sTime);
		}
	}

Begin:
	if ((ClipCount >= ReloadCount) && (ReloadCount != 0))
	{
		if (!bAutomatic)
		{
			bFiring = False;
			FinishAnim();
		}

		if (Owner != None)
		{
			if (Owner.IsA('DeusExPlayer'))
			{
				bFiring = False;

				// should we autoreload?
				if (DeusExPlayer(Owner).bAutoReload)
				{
					// auto switch ammo if we're out of ammo and
					// we're not using the primary ammo
					if ((AmmoType.AmmoAmount == 0) && (AmmoName != AmmoNames[0]))
						CycleAmmo();
					ReloadAmmo();
				}
				else
				{
					if (bHasMuzzleFlash)
						EraseMuzzleFlashTexture();
					GotoState('Idle');
				}
			}
			else if (Owner.IsA('ScriptedPawn'))
			{
				bFiring = False;
				ReloadAmmo();
			}
		}
		else
		{
			if (bHasMuzzleFlash)
				EraseMuzzleFlashTexture();
			GotoState('Idle');
		}
	}
	if ( bAutomatic && (( Level.NetMode == NM_DedicatedServer ) || ((Level.NetMode == NM_ListenServer) && Owner.IsA('DeusExPlayer') && !DeusExPlayer(Owner).PlayerIsListenClient())))
		GotoState('Idle');

	Sleep(GetShotTime());
	if (bAutomatic && (Owner.IsA('ScriptedPawn') || (Owner.IsA('PlayerPawn') && Pawn(Owner).bFire != 0)))
	{
		GenerateBullet();	// In multiplayer bullets are generated by the client which will let the server know when
		Goto('Begin');
	}
	bFiring = False;
	FinishAnim();

	// if ReloadCount is 0 and we're not hand to hand, then this is a
	// single-use weapon so destroy it after firing once
	if ((ReloadCount == 0) && !bHandToHand)
	{
		if (DeusExPlayer(Owner) != None)
			DeusExPlayer(Owner).RemoveItemFromSlot(Self);   // remove it from the inventory grid
		Destroy();
	}
	ReadyToFire();
Done:
	bFiring = False;
	Finish();
}

simulated state ClientFiring
{
	simulated function AnimEnd()
	{
		bInProcess = False;

		if (bAutomatic)
		{
			if ((Pawn(Owner).bFire != 0) && (AmmoType.AmmoAmount > 0))
			{
				if (PlayerPawn(Owner) != None)
					ClientReFire(0);
				else
					GotoState('SimFinishFire');
			}
			else 
				GotoState('SimFinishFire');
		}
	}
	simulated function float GetSimShotTime()
	{
		local float mult, sTime;

		if (ScriptedPawn(Owner) != None)
			return ShotTime * (ScriptedPawn(Owner).BaseAccuracy*2+1);
		else
		{
			// AugCombat decreases shot time
			mult = 1.0;
			if (bHandToHand && DeusExPlayer(Owner) != None)
			{
				mult = 1.0 / DeusExPlayer(Owner).AugmentationSystem.GetAugLevelValue(class'AugCombat');
				if (mult == -1.0)
					mult = 1.0;
			}
//			else if(!bHandToHand && DeusExPlayer(Owner) != None)
//			{
//				mult = 1.0 / modShotTime;
//				if(mult <= 0)
//					mult = 1.0;
//			}
			sTime = ShotTime * mult;
			return (sTime);
		}
	}
Begin:
	if ((ClipCount >= ReloadCount) && (ReloadCount != 0))
	{
		if (!bAutomatic)
		{
			bFiring = False;
			FinishAnim();
		}
		if (Owner != None)
		{
			if (Owner.IsA('DeusExPlayer'))
			{
				bFiring = False;
				if (DeusExPlayer(Owner).bAutoReload)
				{
					bClientReadyToFire = False;
					bInProcess = False;
					if ((AmmoType.AmmoAmount == 0) && (AmmoName != AmmoNames[0]))
						CycleAmmo();
					ReloadAmmo();
					GotoState('SimQuickFinish');
				}
				else
				{
					if (bHasMuzzleFlash)
						EraseMuzzleFlashTexture();
					IdleFunction();
					GotoState('SimQuickFinish');
				}
			}
			else if (Owner.IsA('ScriptedPawn'))
			{
				bFiring = False;
			}
		}
		else
		{
			if (bHasMuzzleFlash)
				EraseMuzzleFlashTexture();
			IdleFunction();
			GotoState('SimQuickFinish');
		}
	}
	Sleep(GetSimShotTime());
	if (bAutomatic && (Owner.IsA('ScriptedPawn') || (Owner.IsA('PlayerPawn') && Pawn(Owner).bFire != 0)))
	{
		SimGenerateBullet();
		Goto('Begin');
	}
	bFiring = False;
	FinishAnim();
	bInProcess = False;
Done:
	bInProcess = False;
	bFiring = False;
	SimFinish();
}
Thaar ya go. Your Assault Rifle (or for that matter, any weapon you attach that to and set it to bAutomatic = True) now no longer fires in bursts.

While this seems like a lot of code, 99% of it is copy-pasted from DeusExWeapon.uc, with minor alterations.
The only part that changes this to non-burst fire is:

Code: Select all

	if (bAutomatic && (Owner.IsA('ScriptedPawn') || (Owner.IsA('PlayerPawn') && Pawn(Owner).bFire != 0)))
	{
		[Sim]GenerateBullet();
		Goto('Begin');
	}
instead of simply

Code: Select all

	if (bAutomatic)
	{
		[Sim]GenerateBullet();
		Goto('Begin');
	}
The rest of it that is commented out is code needed for the fire-rate mod you mentioned.
Image
Click, and watch with false amazement as this dragon grows up.
Gestalt17
Mole Person
Posts: 4
Joined: Fri Feb 04, 2011 6:08 am

Re: Class: WeaponAssaultGun - Damn Burst Fire!

Post by Gestalt17 »

Thanks for the reply Allan.

I decided to be greedy and simply applied that new if() statement conditional you pointed out directly into *DeusExWeapon.uc*, instead of copy-pasting the whole thing into WeaponAssaultGun.uc or whatever weapon I wanted the changes applied to... Well, at least that's what I think you meant by:
Thaar ya go. Your Assault Rifle (or for that matter, any weapon you attach that to and set it to bAutomatic = True) now no longer fires in bursts.
End result:

Despite the Assault Rifle firing animation lasting for about half a second (yep, that's the default animation), I only expend one round with a *single* mouse click! Full-auto fire (holding the button down) remains unaffected, and also matches different RoF values (from either me changing the ShotTime manually or by using Y|yukichigai's in-game RoF mod).

Hell, *all* automatic weapons in the game are now capable of false "semi-auto" fire, regardless of their default RoF! :shock: (Now the 12.5 rnd/s JackHammer can no longer chews through 5 rounds per click!)

While I admittedly don't understand how a simple change to that particular if() conditional gives that result... well, I'll have ta take time to study it. But bottom line: it works! Thanks Allan!

(and again, kudos to Darma for telling me where to look in the first place)
Allan
NSF
Posts: 52
Joined: Thu Apr 16, 2009 4:54 pm

Re: Class: WeaponAssaultGun - Damn Burst Fire!

Post by Allan »

Code: Select all

bAutomatic && (Owner.IsA('ScriptedPawn') || (Owner.IsA('PlayerPawn') && Pawn(Owner).bFire != 0))
can be broken into human readable form as:

"Are we an automatic weapon, and either:
- The person who owns us is an NPC, or
- The person who owns us is a player, who is holding down the fire button."
Image
Click, and watch with false amazement as this dragon grows up.
Post Reply