Weapon Charging
by Owen "WDA" Ashcroft · 07/17/2002 (9:21 am) · 11 comments
This is pretty simple, but looks daunting when you look at all the different parts. I will not show you how to create a weapon in this tutorial, I would suggest you look at the demo application or realm war's scripts.
To do this simply requires the addition of a couple of variables a new procedure and a rewrite of the various weapon states.
The tutorial modifies the crossbow supplied in realm wars.
find crossbow.cs in rw\server\scripts
Move to the bottom until you see the code:
This is where pretty much all the modification is going to take place.
First you have to add 2 variables to keep track of information, so do below this commented area and add:
Scroll down a little further and you will see the various states the weapon can be in. States 0 and 1 remain exactly the same, the rest are slightly modified.
State 2 currently looks like:
Below this add:
There are still a couple of alterations that need to be made, Scroll down to the bottom of that data block until you see the function function CrossbowImage::onFire(%this, %obj, %slot). Just above it put this new function:
Scroll down to CrossbowImage::onFire and below %projectile = %this.projectile; add this code:
What this does is minuses the start charge time from the old time and saves the value in generalModifier, a variable that is created specifically for this projectile.
There is one last change that needs to be made, so that the eventual damage can be taken into account, go to function CrossbowProjectile::onCollision(%this,%obj,%col,%fade,%pos,%normal) on around line 140 and change:
Go on fire it up and have a try.
I am intending to write a follow up on this where the particles generated by the weapon are altered by the charge too so keep an eye out for that soon.
Owen 'WitchDr. Ash' Ashcroft
To do this simply requires the addition of a couple of variables a new procedure and a rewrite of the various weapon states.
The tutorial modifies the crossbow supplied in realm wars.
find crossbow.cs in rw\server\scripts
Move to the bottom until you see the code:
datablock ShapeBaseImageData(CrossbowImage)
{
// Images have a state system which controls how the animations
// are run, which sounds are played, script callbacks, etc. This
// state system is downloaded to the client so that clients can
// predict state changes and animate accordingly. The following
// system supports basic ready->fire->reload transitions as
// well as a no-ammo->dryfire idle state.Should be around line 380.This is where pretty much all the modification is going to take place.
First you have to add 2 variables to keep track of information, so do below this commented area and add:
startTime = 0; //Tracks the start of the charging period. maximumCharge = 5; //Maxmimum number of seconds that charging increases damage
Scroll down a little further and you will see the various states the weapon can be in. States 0 and 1 remain exactly the same, the rest are slightly modified.
State 2 currently looks like:
// Ready to fire, just waiting for the trigger stateName[2] = "Ready"; stateTransitionOnNoAmmo[2] = "NoAmmo"; stateTransitionOnTriggerDown[2] = "Fire";We are going to alter this very slightly because we don't want to fire the weapon quite yet.
// Ready to fire, just waiting for the trigger stateName[2] = "Ready"; stateTransitionOnNoAmmo[2] = "NoAmmo"; stateTransitionOnTriggerDown[2] = "ChargeUp";
Below this add:
stateName[3] = "ChargeUp"; stateTransitionOnTimeout[3] = "Holder"; stateTimeoutValue[3] = 0.1; stateScript[3] = "recordStart";This calls recordStart(%this) [more on this later] and then passes to the next state called holder.
stateName[4] = "Holder"; stateTransitionOnTriggerUp[4] = "Fire";This is the holder code, it does nothing but wait for you to release your mouse button and then changes the state to Fire.
stateName[5] = "Fire"; stateTransitionOnTimeout[5] = "Reload"; stateTimeoutValue[5] = 0.2; stateFire[5] = true; stateRecoil[5] = LightRecoil; stateAllowImageChange[5] = false; stateSequence[5] = "Fire"; stateScript[5] = "onFire"; stateSound[5] = CrossbowFireSound; stateName[6] = "Reload"; stateTransitionOnNoAmmo[6] = "NoAmmo"; stateTransitionOnTimeout[6] = "Ready"; stateTimeoutValue[6] = 1; stateAllowImageChange[6] = false; stateSequence[6] = "Reload"; stateEjectShell[6] = true; stateSound[6] = CrossbowReloadSound; // No ammo in the weapon, just idle until something // shows up. Play the dry fire sound if the trigger is // pulled. stateName[7] = "NoAmmo"; stateTransitionOnAmmo[7] = "Reload"; stateSequence[7] = "NoAmmo"; stateTransitionOnTriggerDown[7] = "DryFire"; // No ammo dry fire stateName[8] = "DryFire"; stateTimeoutValue[8] = 1.0; stateTransitionOnTimeout[8] = "NoAmmo"; stateSound[8] = CrossbowFireEmptySound;This is the same as the old code, except it is in a different place, it doesn't have to be, it just makes it easier to read once renumbered.
There are still a couple of alterations that need to be made, Scroll down to the bottom of that data block until you see the function function CrossbowImage::onFire(%this, %obj, %slot). Just above it put this new function:
function CrossbowImage::recordStart(%this)
{
%this.startTime = $Sim::Time;
}What this does is record the time when you pressed the fire button.Scroll down to CrossbowImage::onFire and below %projectile = %this.projectile; add this code:
%modifier = $Sim::Time - %this.startTime; if(%modifier > %this.maximumCharge) %modifier = %this.maximumCharge; if(%modifier < 1) %modifier = 1;
// Create the projectile object
%p = new (%this.projectileType)() {
dataBlock = %projectile;
initialVelocity = %muzzleVelocity;
initialPosition = %obj.getMuzzlePoint(%slot);
sourceObject = %obj;
sourceSlot = %slot;
client = %obj.client;
generalModifier = %modifier; //add modifier variable
};scroll to the botton and just before MissionCleanup.add(%p) putWhat this does is minuses the start charge time from the old time and saves the value in generalModifier, a variable that is created specifically for this projectile.
There is one last change that needs to be made, so that the eventual damage can be taken into account, go to function CrossbowProjectile::onCollision(%this,%obj,%col,%fade,%pos,%normal) on around line 140 and change:
%col.damage(%obj,%pos,%this.directDamage, "CrossbowBolt"); to %col.damage(%obj,%pos,%this.directDamage * %obj.generalModifier,"CrossbowBolt");What this does is alters the damage according to the modifier created at the time of firing of the projectile.
Go on fire it up and have a try.
I am intending to write a follow up on this where the particles generated by the weapon are altered by the charge too so keep an eye out for that soon.
Owen 'WitchDr. Ash' Ashcroft
About the author
#2
07/17/2002 (5:24 pm)
It would be great for a magical crossbow
#3
stateSequence[4] = "charge";
to the holder state.
Just a suggestion.
Cool resource.
07/18/2002 (6:38 am)
you could also add an animation for the charging by making a sequence called say "charge" and then adding stateSequence[4] = "charge";
to the holder state.
Just a suggestion.
Cool resource.
#4
07/18/2002 (8:13 am)
yeah it would be fine to add that, just not a modeller, so never created one :)
#5
12/12/2003 (1:47 pm)
This is actually a good resource for those of us just starting with torque with some OO background. Easy to read and understand.
#6
10/17/2004 (5:59 pm)
try this too... http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=2971
#7
10/18/2004 (4:30 pm)
You can also scale the muzzlevelocity by the modifier to reflect the change in power of the shots. Just a quick fix, probably is a better way to do it :)
#8
im not a programmer, but im leaerning.
Thanks in advance!
07/15/2005 (9:52 pm)
is there any way we can the charging of the weapon to deincrement the players energy?im not a programmer, but im leaerning.
Thanks in advance!
#9
08/21/2005 (2:11 am)
anyone read this anymore?
#10
08/05/2006 (5:53 pm)
i cant get the hang of this is it correct?// Images have a state system which controls how the animations
// are run, which sounds are played, script callbacks, etc. This
// state system is downloaded to the client so that clients can
// predict state changes and animate accordingly. The following
// system supports basic ready->fire->reload transitions as
// well as a no-ammo->dryfire idle state.
startTime = 0; //Tracks the start of the charging period.
maximumCharge = 5; //Maxmimum number of seconds that charging increases damage
// Initial start up state
stateName[0] = "Preactivate";
stateTransitionOnLoaded[0] = "Activate";
stateTransitionOnNoAmmo[0] = "NoAmmo";
// Activating the gun. Called when the weapon is first
// mounted and there is ammo.
stateName[1] = "Activate";
stateTransitionOnTimeout[1] = "Ready";
stateTimeoutValue[1] = 0.6;
stateSequence[1] = "Activate";
// Ready to fire, just waiting for the trigger
// Ready to fire, just waiting for the trigger
stateName[2] = "Ready";
stateTransitionOnNoAmmo[2] = "NoAmmo";
stateTransitionOnTriggerDown[2] = "ChargeUp";
//new reasource
stateName[3] = "ChargeUp";
stateTransitionOnTimeout[3] = "Holder";
stateTimeoutValue[3] = 0.1;
stateScript[3] = "recordStart";
// Fire the weapon. Calls the fire script which does
// the actual work.
stateName[4] = "Fire";
stateTransitionOnTimeout[4] = "Reload";
stateTimeoutValue[4] = 0.2;
stateFire[4] = true;
stateRecoil[4] = LightRecoil;
stateAllowImageChange[4] = false;
stateSequence[4] = "Fire";
stateScript[4] = "onFire";
stateSound[4] = CrossbowFireSound;
stateName[5] = "Fire";
stateTransitionOnTimeout[5] = "Reload";
stateTimeoutValue[5] = 0.2;
stateFire[5] = true;
stateRecoil[5] = LightRecoil;
stateAllowImageChange[5] = false;
stateSequence[5] = "Fire";
stateScript[5] = "onFire";
stateSound[5] = CrossbowFireSound;
stateName[6] = "Reload";
stateTransitionOnNoAmmo[6] = "NoAmmo";
stateTransitionOnTimeout[6] = "Ready";
stateTimeoutValue[6] = 1;
stateAllowImageChange[6] = false;
stateSequence[6] = "Reload";
stateEjectShell[6] = true;
stateSound[6] = CrossbowReloadSound;
// No ammo in the weapon, just idle until something
// shows up. Play the dry fire sound if the trigger is
// pulled.
stateName[7] = "NoAmmo";
stateTransitionOnAmmo[7] = "Reload";
stateSequence[7] = "NoAmmo";
stateTransitionOnTriggerDown[7] = "DryFire";
// No ammo dry fire
stateName[8] = "DryFire";
stateTimeoutValue[8] = 1.0;
stateTransitionOnTimeout[8] = "NoAmmo";
stateSound[8] = CrossbowFireEmptySound;
};
//-----------------------------------------------------------------------------
function CrossbowImage::recordStart(%this)
{
%this.startTime = $Sim::Time;
}
function CrossbowImage::onFire(%this, %obj, %slot)
{
%projectile = %this.projectile;
%modifier = $Sim::Time - %this.startTime;
if(%modifier > %this.maximumCharge)
%modifier = %this.maximumCharge;
if(%modifier < 1)
%modifier = 1;
// Decrement inventory ammo. The image's ammo state is update
// automatically by the ammo inventory hooks.
%obj.decInventory(%this.ammo,1);
// Determin initial projectile velocity based on the
// gun's muzzle point and the object's current velocity
%muzzleVector = %obj.getMuzzleVector(%slot);
%objectVelocity = %obj.getVelocity();
%muzzleVelocity = VectorAdd(
VectorScale(%muzzleVector, %projectile.muzzleVelocity),
VectorScale(%objectVelocity, %projectile.velInheritFactor));
// Create the projectile object
%p = new (%this.projectileType)() {
dataBlock = %projectile;
initialVelocity = %muzzleVelocity;
initialPosition = %obj.getMuzzlePoint(%slot);
sourceObject = %obj;
sourceSlot = %slot;
client = %obj.client;
};
// Create the projectile object
%p = new (%this.projectileType)() {
dataBlock = %projectile;
initialVelocity = %muzzleVelocity;
initialPosition = %obj.getMuzzlePoint(%slot);
sourceObject = %obj;
sourceSlot = %slot;
client = %obj.client;
generalModifier = %modifier; //add modifier variable
};
MissionCleanup.add(%p);
return %p;
}
#11
03/05/2009 (3:33 pm)
Great use of image states! 
Torque Owner Tyler Turner