grenade launcher (explodes on timer not contact)
by Stephen Lujan · 04/21/2008 (9:25 am) · 3 comments
//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
// By Stephen Lujan
//-----------------------------------------------------------------------------
//
// - Grenade Launcher -
// This weapon is a test platform for grenade functionality, it borrows resources
// heavily from the crossbow weapon
//
//-----------------------------------------------------------------------------
// IMPORTANT:
// Set up the root directory for your weapons models below and uncomment
// $WeaponDir = "~/data/shapes/";
// Read how to enable better grenade functionality at the bottom.
//-----------------------------------------------------------------------------
// this explosion is not much different for now
datablock ExplosionData(GrenadeExplosion)
{
soundProfile = CrossbowExplosionSound;
lifeTimeMS = 1800;
// Volume particles
particleEmitter = CrossbowExplosionFireEmitter;
particleDensity = 75;
particleRadius = 2.5;
// Point emission
emitter[0] = CrossbowExplosionSmokeEmitter;
emitter[1] = CrossbowExplosionSparkEmitter;
// Sub explosion objects
subExplosion[0] = CrossbowSubExplosion1;
subExplosion[1] = CrossbowSubExplosion2;
// Camera Shaking
shakeCamera = true;
camShakeFreq = "10.0 11.0 10.0";
camShakeAmp = "1.0 1.0 1.0";
camShakeDuration = 0.5;
camShakeRadius = 10.0;
// Exploding debris
debris = CrossbowExplosionDebris;
debrisThetaMin = 0;
debrisThetaMax = 60;
debrisPhiMin = 0;
debrisPhiMax = 360;
debrisNum = 8;
debrisNumVariance = 2;
debrisVelocity = 6;
debrisVelocityVariance = 0.5;
// Impulse
impulseRadius = 15;
impulseForce = 15;
// Dynamic light
lightStartRadius = 12;
lightEndRadius = 6;
lightStartColor = "0.5 0.5 0.2";
lightEndColor = "0 0 0";
};
//-----------------------------------------------------------------------------
// Projectile Object
datablock ProjectileData(GrenadeLauncherProjectile)
{
projectileShapeName = $WeaponDir @ "crossbow/ammo.dts";
//$WeaponDir @ "crossbow/projectile.dts";
directDamage = 10;
radiusDamage = 30;
damageRadius = 10.0;
areaImpulse = 2000;
explosion = GrenadeExplosion;
waterExplosion = CrossbowWaterExplosion;
//particleEmitter = CrossbowBoltEmitter;
particleWaterEmitter= CrossbowBoltBubbleEmitter;
splash = CrossbowSplash;
muzzleVelocity = 20;
velInheritFactor = 0.8;
armingDelay = 2000;
lifetime = 6000;
fadeDelay = 6000;
bounceElasticity = 0.4;
// this is low so we can fake rolling/sliding
bounceFriction = 0.03;
isBallistic = true;
gravityMod = 1.00;
hasLight = false;
//lightRadius = 4;
//lightColor = "0.5 0.5 0.25";
hasWaterLight = false;
//waterLightColor = "0 0.5 0.5";
};
//-----------------------------------------------------------------------------
// NOTE: This function takes effect if the explode function engine change isn't used.
// See the bottom of the file for details.
function GrenadeLauncherProjectile::onCollision(%this,%obj,%col,%fade,%pos,%normal)
{
// Apply damage to the object all shape base objects
if (%col.getType() & $TypeMasks::ShapeBaseObjectType)
%col.damage(%obj,%pos,%this.directDamage,"Grenade");
// Radius damage is a support scripts defined in radiusDamage.cs
// Push the contact point away from the contact surface slightly
// along the contact normal to derive the explosion center. -dbs
radiusDamage(%obj, %pos, %this.damageRadius, %this.radiusDamage, "Radius", %this.areaImpulse);
}
//-----------------------------------------------------------------------------
// Ammo Item
datablock ItemData(GrenadeLauncherAmmo)
{
// Mission editor category
category = "Ammo";
// Add the Ammo namespace as a parent. The ammo namespace provides
// common ammo related functions and hooks into the inventory system.
className = "Ammo";
// Basic Item properties
shapeFile = $WeaponDir @ "crossbow/ammo.dts";
mass = 1;
elasticity = 0.2;
friction = 0.6;
// Dynamic properties defined by the scripts
pickUpName = "Grenades";
maxInventory = 20;
};
//--------------------------------------------------------------------------
// Weapon Item. This is the item that exists in the world, i.e. when it's
// been dropped, thrown or is acting as re-spawnable item. When the weapon
// is mounted onto a shape, the CrossbowImage is used.
datablock ItemData(GrenadeLauncher)
{
// Mission editor category
category = "Weapon";
// Hook into Item Weapon class hierarchy. The weapon namespace
// provides common weapon handling functions in addition to hooks
// into the inventory system.
className = "Weapon";
// Basic Item properties
shapeFile = $WeaponDir @ "crossbow/weapon.dts";
mass = 1;
elasticity = 0.2;
friction = 0.6;
emap = true;
// Dynamic properties defined by the scripts
pickUpName = "A Grenade Launcher";
image = CrossbowImage;
};
//--------------------------------------------------------------------------
// Crossbow image which does all the work. Images do not normally exist in
// the world, they can only be mounted on ShapeBase objects.
datablock ShapeBaseImageData(GrenadeLauncherImage)
{
// Basic Item properties
shapeFile = $WeaponDir @ "crossbow/weapon.dts";
emap = true;
// Specify mount point & offset for 3rd person, and eye offset
// for first person rendering.
mountPoint = 0;
eyeOffset = "0.1 0.4 -0.6";
// When firing from a point offset from the eye, muzzle correction
// will adjust the muzzle vector to point to the eye LOS point.
// Since this weapon doesn't actually fire from the muzzle point,
// we need to turn this off.
correctMuzzleVector = false;
// Add the WeaponImage namespace as a parent, WeaponImage namespace
// provides some hooks into the inventory system.
className = "WeaponImage";
// Projectile && Ammo.
item = GrenadeLauncher;
ammo = GrenadeLauncherAmmo;
projectile = GrenadeLauncherProjectile;
projectileType = Projectile;
// 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.
// 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
stateName[2] = "Ready";
stateTransitionOnNoAmmo[2] = "NoAmmo";
stateTransitionOnTriggerDown[2] = "Fire";
// Fire the weapon. Calls the fire script which does
// the actual work.
stateName[3] = "Fire";
stateTransitionOnTimeout[3] = "Reload";
stateTimeoutValue[3] = 0.2;
stateFire[3] = true;
stateRecoil[3] = LightRecoil;
stateAllowImageChange[3] = false;
stateSequence[3] = "Fire";
stateScript[3] = "onFire";
stateSound[3] = CrossbowFireSound;
// Play the relead animation, and transition into
stateName[4] = "Reload";
stateTransitionOnNoAmmo[4] = "NoAmmo";
stateTransitionOnTimeout[4] = "Ready";
stateTimeoutValue[4] = 0.8;
stateAllowImageChange[4] = false;
stateSequence[4] = "Reload";
stateEjectShell[4] = true;
stateSound[4] = CrossbowReloadSound;
// No ammo in the weapon, just idle until something
// shows up. Play the dry fire sound if the trigger is
// pulled.
stateName[5] = "NoAmmo";
stateTransitionOnAmmo[5] = "Reload";
stateSequence[5] = "NoAmmo";
stateTransitionOnTriggerDown[5] = "DryFire";
// No ammo dry fire
stateName[6] = "DryFire";
stateTimeoutValue[6] = 1.0;
stateTransitionOnTimeout[6] = "NoAmmo";
stateSound[6] = CrossbowFireEmptySound;
};
//-----------------------------------------------------------------------------
function GrenadeLauncherImage::onFire(%this, %obj, %slot)
{
%projectile = %this.projectile;
// 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;
};
MissionCleanup.add(%p);
//this requires engine changes
schedule(1900, %p,"detonate",%p);
return %p;
}
/*****************************************************************************************
* TIMED DETONATION:
*
* The bottom function is a script implementation of timed projectile detonations.
* To make use of it requires an engine change to provide an alternative to the explode
* on contact mechanism. With the engine change enabled a projectile can be detonated at
* any time with the explode function, including in the air, and before the arming period is over.
*
* Add the following code block to "engine/game/projectile.cc" at the bottom preferably.
* Then make sure you move the function projectile::explode() and projectile's
* data members mCurrPosition and mCurrVelocity from protected to public.
* Voila!
//-----------------------------------------------------------------------------------
// stephen new: had to make parameters and explode function public
ConsoleMethod( Projectile, explode, void, 2, 2, "Detonates a projectile.")
{
object->mCurrVelocity.normalize();
object->explode(object->mCurrPosition, object->mCurrVelocity, 1);
}
//-----------------------------------------------------------------------------------
*
* When you have performed the engine modifications necessary comment out or remove the
* return statement in the function below.
*****************************************************************************************/
function detonate(%obj)
{
return;
radiusDamage(0, %obj.getPosition(), %obj.getdatablock().damageRadius, %obj.getdatablock().radiusDamage, "Radius", %obj.getdatablock().areaImpulse);
//%obj.schedule(0,"delete");
%obj.explode();
}About the author
Torque Owner Dmitry Serdukov