[phpBB Debug] PHP Warning: in file [ROOT]/includes/functions.php on line 5150: file_get_contents(https://freedomsponsors.org/api/project/294): failed to open stream: HTTP request failed! HTTP/1.1 502 Bad Gateway
energyWeapon Resource - Forums | Torque 3D

energyWeapon Resource

Scripts and code that enhance the gameplay functionality of the engine.
9 posts Page 1 of 1
Steve_Yorkshire
Posts: 191
Joined: Tue Feb 03, 2015 10:30 pm
 
  by Steve_Yorkshire » Wed Feb 11, 2015 6:10 pm


How to make a weapon which uses energy and not ammunition. To keep things simple we will inherit a lot things from Lurker weapon like shapes, animations and audio.

Step 1:
Create a new energyRifle.cs file in art/datablocks/weapons.
The important bits are that the ImageDatablock does NOT have "ammo" listed, or there will be a conflict with "usesEnergy".
"minEnergy" is the minimum amount of energy the player must have for it to fire.
"infiniteAmmo" should be set to "true" to prevent console spam from weaponImage::onFire attempting to decrease ammo which does not exist. Alternatively the onFIre script could be changed to "if ( !%this.infiniteAmmo || %this.usesEnergy )" but we will stick to using "infiniteAmmo" in the imageDatablock for this resource.
"stateEnergyDrain" in the onFire state drains %n energy per full second so divide by the timeOut state if you want exact amounts.

//audio, particles and projectile all comes from Lurker.cs

//--------------------------------------------------------------------------
// 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 SoldierWeaponImage is used.
//-----------------------------------------------------------------------------
datablock ItemData(energyRifle)
{
// 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 = "art/shapes/weapons/Lurker/TP_Lurker.DAE";
mass = 1;
elasticity = 0.2;
friction = 0.6;
emap = true;
PreviewImage = 'lurker.png';

// Dynamic properties defined by the scripts
pickUpName = "energyRifle";
description = "energyRifle";
image = energyRifleWeaponImage;
reticle = "crossHair";
};

datablock ShapeBaseImageData(energyRifleWeaponImage)
{
// Basic Item properties
shapeFile = "art/shapes/weapons/Lurker/TP_Lurker.DAE";
shapeFileFP = "art/shapes/weapons/Lurker/FP_Lurker.DAE";
emap = true;

imageAnimPrefix = "Rifle";
imageAnimPrefixFP = "Rifle";

// Specify mount point & offset for 3rd person, and eye offset
// for first person rendering.
mountPoint = 0;
firstPerson = true;
useEyeNode = true;
animateOnServer = true;

// 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 = true;

// Add the WeaponImage namespace as a parent, WeaponImage namespace
// provides some hooks into the inventory system.
class = "WeaponImage";
className = "WeaponImage";

// Projectiles and Ammo.
item = energyRifle;

usesEnergy = true;
minEnergy = 10;
infiniteAmmo = true;//need this to prevent console spam from weaponImage::onFire due to no ammo

projectile = BulletProjectile;
projectileType = Projectile;
projectileSpread = "0.0";

altProjectile = GrenadeLauncherProjectile;
altProjectileSpread = "0.02";

casing = BulletShell;
shellExitDir = "1.0 0.3 1.0";
shellExitOffset = "0.15 -0.56 -0.1";
shellExitVariance = 15.0;
shellVelocity = 3.0;

// Weapon lights up while firing
lightType = "WeaponFireLight";
lightColor = "0.992126 0.968504 0.700787 1";
lightRadius = "4";
lightDuration = "100";
lightBrightness = 2;

// Shake camera while firing.
shakeCamera = false;
camShakeFreq = "0 0 0";
camShakeAmp = "0 0 0";

// 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.

useRemainderDT = true;

// 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";
stateTransitionGeneric0In[1] = "SprintEnter";
stateTransitionOnTimeout[1] = "Ready";
stateTimeoutValue[1] = 0.5;
stateSequence[1] = "switch_in";
stateSound[1] = LurkerSwitchinSound;

// Ready to fire, just waiting for the trigger
stateName[2] = "Ready";
stateTransitionGeneric0In[2] = "SprintEnter";
stateTransitionOnMotion[2] = "ReadyMotion";
stateTransitionOnTimeout[2] = "ReadyFidget";
stateTimeoutValue[2] = 10;
stateWaitForTimeout[2] = false;
stateScaleAnimation[2] = false;
stateScaleAnimationFP[2] = false;
stateTransitionOnNoAmmo[2] = "NoAmmo";
stateTransitionOnTriggerDown[2] = "Fire";
stateSequence[2] = "idle";

// Same as Ready state but plays a fidget sequence
stateName[3] = "ReadyFidget";//yorks - this is the devil, really.
stateTransitionGeneric0In[3] = "SprintEnter";
stateTransitionOnMotion[3] = "ReadyMotion";
stateTransitionOnTimeout[3] = "Ready";
stateTimeoutValue[3] = 6;
stateWaitForTimeout[3] = false;
stateTransitionOnNoAmmo[3] = "NoAmmo";
stateTransitionOnTriggerDown[3] = "Fire";
stateSequence[3] = "idle_fidget1";
stateSound[3] = LurkerIdleSound;

// Ready to fire with player moving
stateName[4] = "ReadyMotion";
stateTransitionGeneric0In[4] = "SprintEnter";
stateTransitionOnNoMotion[4] = "Ready";
stateWaitForTimeout[4] = false;
stateScaleAnimation[4] = false;
stateScaleAnimationFP[4] = false;
stateSequenceTransitionIn[4] = true;
stateSequenceTransitionOut[4] = true;
stateTransitionOnNoAmmo[4] = "NoAmmo";
stateTransitionOnTriggerDown[4] = "Fire";
stateSequence[4] = "run";

// Fire the weapon. Calls the fire script which does
// the actual work.
stateName[5] = "Fire";
stateTransitionGeneric0In[5] = "SprintEnter";
stateTransitionOnTimeout[5] = "NewRound";
stateTimeoutValue[5] = 0.15;
stateEnergyDrain[5] = 50.0;//yorks drain per full second
stateFire[5] = true;
stateRecoil[5] = "";
stateAllowImageChange[5] = false;
stateSequence[5] = "fire";
stateScaleAnimation[5] = false;
stateSequenceNeverTransition[5] = true;
stateSequenceRandomFlash[5] = true; // use muzzle flash sequence
stateScript[5] = "onFire";
stateSound[5] = LurkerFireSoundList;
stateEmitter[5] = GunFireSmokeEmitter;
stateEmitterTime[5] = 0.025;

// Put another round into the chamber if one is available
stateName[6] = "NewRound";
stateTransitionGeneric0In[6] = "SprintEnter";
stateTransitionOnNoAmmo[6] = "NoAmmo";
stateTransitionOnTimeout[6] = "Ready";
stateWaitForTimeout[6] = "0";
stateTimeoutValue[6] = 0.05;
stateAllowImageChange[6] = false;
stateEjectShell[6] = true;

// No ammo in the weapon, just idle until something
// shows up. Play the dry fire sound if the trigger is
// pulled.
stateName[7] = "NoAmmo";
stateTransitionGeneric0In[7] = "SprintEnter";
stateTransitionOnMotion[7] = "NoAmmoMotion";
stateTransitionOnAmmo[7] = "Ready";
stateTimeoutValue[7] = 0.1; // Slight pause to allow script to run when trigger is still held down from Fire state
stateSequence[7] = "idle";
stateScaleAnimation[7] = false;
stateScaleAnimationFP[7] = false;
stateTransitionOnTriggerDown[7] = "DryFire";

stateName[8] = "NoAmmoMotion";
stateTransitionGeneric0In[8] = "SprintEnter";
stateTransitionOnNoMotion[8] = "NoAmmo";
stateWaitForTimeout[8] = false;
stateScaleAnimation[8] = false;
stateScaleAnimationFP[8] = false;
stateSequenceTransitionIn[8] = true;
stateSequenceTransitionOut[8] = true;
stateTransitionOnTriggerDown[8] = "DryFire";
stateTransitionOnAmmo[8] = "Ready";
stateSequence[8] = "run";

// No ammo dry fire
stateName[9] = "DryFire";
stateTransitionGeneric0In[9] = "SprintEnter";
stateTransitionOnAmmo[9] = "Ready";
stateWaitForTimeout[9] = "0";
stateTimeoutValue[9] = 0.7;
stateTransitionOnTimeout[9] = "NoAmmo";
stateScript[9] = "onDryFire";
stateSound[9] = MachineGunDryFire;

// Start Sprinting
stateName[10] = "SprintEnter";
stateTransitionGeneric0Out[10] = "SprintExit";
stateTransitionOnTimeout[10] = "Sprinting";
stateWaitForTimeout[10] = false;
stateTimeoutValue[10] = 0.5;
stateWaitForTimeout[10] = false;
stateScaleAnimation[10] = false;
stateScaleAnimationFP[10] = false;
stateSequenceTransitionIn[10] = true;
stateSequenceTransitionOut[10] = true;
stateAllowImageChange[10] = false;
stateSequence[10] = "sprint";

// Sprinting
stateName[11] = "Sprinting";
stateTransitionGeneric0Out[11] = "SprintExit";
stateWaitForTimeout[11] = false;
stateScaleAnimation[11] = false;
stateScaleAnimationFP[11] = false;
stateSequenceTransitionIn[11] = true;
stateSequenceTransitionOut[11] = true;
stateAllowImageChange[11] = false;
stateSequence[11] = "sprint";

// Stop Sprinting
stateName[12] = "SprintExit";
stateTransitionGeneric0In[12] = "SprintEnter";
stateTransitionOnTimeout[12] = "Ready";
stateWaitForTimeout[12] = false;
stateTimeoutValue[12] = 0.5;
stateSequenceTransitionIn[12] = true;
stateSequenceTransitionOut[12] = true;
stateAllowImageChange[12] = false;
stateSequence[12] = "sprint";
};


Part 2:
Remember to exec the file in art/datablockExec.cs.
//...
// Load the weapon datablocks
exec("./weapons/Lurker.cs");
exec("./weapons/Ryder.cs");
exec("./weapons/ProxMine.cs");
exec("./weapons/Turret.cs");
exec("./weapons/energyRifle.cs");//yorks - our new energyRifle after Lurker which we inherit from

exec("./teleporter.cs");
//...


Step 3
Stock Torque3D is set not to show the weapon icon on the player's HUD if there is no ammo, so we need to change that.
In scripts/server/weapon.cs edit the "WeaponImage::onMount" function, go right to the bottom and set a new condition if there is no ammo.
function WeaponImage::onMount(%this, %obj, %slot)
{
//...
if (%obj.client !$= "" && !%obj.isAiControlled)
%obj.client.RefreshWeaponHud( 1, %this.item.previewImage, %this.item.reticle, %this.item.zoomReticle, %currentAmmo );
}
else//yorks in start
{
//make sure weapon icon appears on the player HUD for energy weapons and non-ammo weapons
if (%obj.client !$= "" && !%obj.isAiControlled)
%obj.client.RefreshWeaponHud( 0, %this.item.previewImage, %this.item.reticle, %this.item.zoomReticle, 0 );
}//yorks in end
}

Now the energyRifle's weapon icon will show on the HUD (we're using the lurker.png image) and there will be no ammo count.

Part 4
Give the player datablock the ability to have the weapon in it's inventory and set it to be the default weapon.
art/datablocks/player.cs edit the datablock for "PlayerData(DefaultPlayerData)"

//...
cameraMinDist = "0";
DecalData = "PlayerFootprint";

// Allowable Inventory Items
mainWeapon = energyRifle;//yorks was - Ryder;

maxInv[energyRifle] = 1;//yorks new

maxInv[Lurker] = 1;
maxInv[LurkerClip] = 20;

maxInv[LurkerGrenadeLauncher] = 1;
maxInv[LurkerGrenadeAmmo] = 20;
//...


Part 5
Let's equip the player with the energyRifle when they spawn.
scripts/server/gamecore.cs edit gameCore::loadout function.

function GameCore::loadOut(%game, %player)
{
//echo (%game @"\c4 -> "@ %game.class @" -> GameCore::loadOut");

%player.clearWeaponCycle();

%player.setInventory(energyRifle, 1);//yorks new
%player.addToWeaponCycle(energyRifle);//yorks new

%player.setInventory(Ryder, 1);
%player.setInventory(RyderClip, %player.maxInventory(RyderClip));
//...


Part 6
Finally we need to set the player's energy to the HUD so they can see what is going on. Open the GUI Editor and add a "GuiHealthBarHud" and a "GuiHealthTextHud". Remember to set both of these to display Energy or else they will show health. As the "minEnergy" for shooting is 10 in the imageDatablock, set the bar's "pulseThreshold" to 0.1 (10%) and the text's "warnThreshold" to 10.
Here is what my art/gui/playGui.gui looks like:
new GuiHealthBarHud() {
fillColor = "0 0 0 0.65";
frameColor = "0 0 1 1";
damageFillColor = "0 1 1 1";
pulseRate = "2";
pulseThreshold = "0.1";
showFill = "1";
showFrame = "1";
displayEnergy = "1";
position = "202 697";
extent = "32 64";
minExtent = "8 2";
horizSizing = "right";
vertSizing = "top";
profile = "GuiDefaultProfile";
visible = "1";
active = "1";
tooltipProfile = "GuiToolTipProfile";
hovertime = "1000";
isContainer = "0";
canSave = "1";
canSaveDynamicFields = "0";
};
new GuiHealthTextHud() {
fillColor = "0 0 0 0.65";
frameColor = "0 0 0 1";
textColor = "0 1 1 1";
warningColor = "1 0 0 1";
showFill = "1";
showFrame = "1";
showTrueValue = "0";
showEnergy = "1";
warnThreshold = "10";
pulseThreshold = "5";
pulseRate = "2";
position = "239 693";
extent = "72 72";
minExtent = "8 2";
horizSizing = "right";
vertSizing = "top";
profile = "GuiBigTextProfile";
visible = "1";
active = "1";
tooltipProfile = "GuiToolTipProfile";
hovertime = "1000";
isContainer = "0";
canSave = "1";
canSaveDynamicFields = "0";
};


And hopefully that's that and it all works fine.

EDIT
Turns out there is a crash if a non-ammo using weapon is the default weapon loaded at runtime and then changes to another weapon. Crash does not occur if the starting weapon uses ammo ... :? FFS Torque ...

Fix is simple. scripts/client/client.cs client command "RefreshWeaponHUD" function needs changing

function clientCmdRefreshWeaponHUD(%amount, %preview, %ret, %zoomRet, %amountInClips)
{
if (!%amount)
{
//AmmoAmount.setVisible(false);//yorks bad!
//causes a crash if this weapon is the default and you change to an other weapon
AmmoAmount.setText("");
}
else
{
AmmoAmount.setVisible(true);
AmmoAmount.setText("Ammo: " @ %amount @ "/" @ %amountInClips);
}
//...


And now no crash.
Last edited by Steve_Yorkshire on Thu Feb 12, 2015 6:00 pm, edited 1 time in total.
buckmaster
Steering Committee
Steering Committee
Posts: 321
Joined: Thu Feb 05, 2015 1:02 am
by buckmaster » Wed Feb 11, 2015 11:06 pm
Yay! Great resource :). Show-off forum though? :P
LukasPJ
Site Admin
Posts: 318
Joined: Tue Feb 03, 2015 7:25 pm
 
by LukasPJ » Wed Feb 11, 2015 11:12 pm
It's fine, I'll move it when I actually get a resource section up ;)
Gibby
Posts: 72
Joined: Wed Feb 11, 2015 2:40 pm
by Gibby » Thu Feb 12, 2015 5:39 pm
@Steve: Thanks for this! Care to add a riibbon to the projectile? I'm still struggling to make mine work...
Steve_Yorkshire
Posts: 191
Joined: Tue Feb 03, 2015 10:30 pm
 
by Steve_Yorkshire » Thu Feb 12, 2015 6:01 pm
Found a crash caused by RefreshWeaponHUD not displaying the ammoAmount if a non-ammo weapon is the first one loaded at startup and then the player switches to an ammo-using weapon. No crash if first weapon loaded is an ammo-user. Makes no sense but hey, we're all used to that. :P
Fix posted in resource, also suggest fix goes into main repo.

function clientCmdRefreshWeaponHUD(%amount, %preview, %ret, %zoomRet, %amountInClips)
{
if (!%amount)
{
//AmmoAmount.setVisible(false);//yorks bad!
//causes a crash if this weapon is the default and you change to an other weapon
AmmoAmount.setText("");
}
else
{
AmmoAmount.setVisible(true);
AmmoAmount.setText("Ammo: " @ %amount @ "/" @ %amountInClips);
}
Steve_Yorkshire
Posts: 191
Joined: Tue Feb 03, 2015 10:30 pm
 
by Steve_Yorkshire » Thu Feb 12, 2015 7:40 pm
buckmaster
Steering Committee
Steering Committee
Posts: 321
Joined: Thu Feb 05, 2015 1:02 am
by buckmaster » Fri Feb 13, 2015 4:30 am
A crash? I think we should try to make the script API as crash-resistant as possible. Any chance you could see what's happening in the engine to allow it to crash? A minimal example script would also be appreciated :).
Steve_Yorkshire
Posts: 191
Joined: Tue Feb 03, 2015 10:30 pm
 
by Steve_Yorkshire » Sat Feb 14, 2015 1:35 am
@
User avatar
buckmaster

Seems to crash looking for a valid character in gfx/gFont.h. Only happens if there is no ammoAmount to show and thus ammoAmount in scripts/client/client.cs is hidden. And it only crashes if the first weapon on startup is non-ammo. Loading an ammo-wpn first and then switching back and forth between ammo and non-ammo weapons is fine.
// Update the Ammo Counter with current ammo, if not any then hide the counter. 
function clientCmdSetAmmoAmountHud(%amount, %amountInClips)
{
if (!%amount)
AmmoAmount.setVisible(false);
else
{
AmmoAmount.setVisible(true);
AmmoAmount.setText("Ammo: " @ %amount @ "/" @ %amountInClips);
}
}


gfx/gFont.h
inline bool GFont::isValidChar(const UTF16 in_charIndex) const
{
if(mRemapTable[in_charIndex] != -1)//dies here
return true;

if(mPlatformFont)
return mPlatformFont->isValidChar(in_charIndex);

return false;
}


I'll post the full stack - but if I'm honest I just like make gaemz and don't understand what makes them go. ;)

>	energyWeapon_DEBUG DLL.dll!GFont::isValidChar(const unsigned short in_charIndex) Line 185	C++
energyWeapon_DEBUG DLL.dll!GFont::getStrNWidthPrecise(const unsigned short * str, unsigned int n) Line 486 C++
energyWeapon_DEBUG DLL.dll!GFont::getStrNWidthPrecise(const char * str, unsigned int n) Line 466 C++
energyWeapon_DEBUG DLL.dll!GFont::getStrWidthPrecise(const char * in_pString) Line 419 C++
energyWeapon_DEBUG DLL.dll!GuiControl::renderJustifiedText(Point2I offset, Point2I extent, const char * text) Line 605 C++
energyWeapon_DEBUG DLL.dll!GuiTextCtrl::onRender(Point2I offset, const RectI & updateRect) Line 235 C++
energyWeapon_DEBUG DLL.dll!GuiControl::renderChildControls(Point2I offset, const RectI & updateRect) Line 574 C++
energyWeapon_DEBUG DLL.dll!GuiBitmapBorderCtrl::onRender(Point2I offset, const RectI & updateRect) Line 135 C++
energyWeapon_DEBUG DLL.dll!GuiControl::renderChildControls(Point2I offset, const RectI & updateRect) Line 574 C++
energyWeapon_DEBUG DLL.dll!GuiTSCtrl::onRender(Point2I offset, const RectI & updateRect) Line 471 C++
energyWeapon_DEBUG DLL.dll!GameTSCtrl::onRender(Point2I offset, const RectI & updateRect) Line 179 C++
energyWeapon_DEBUG DLL.dll!GuiCanvas::renderFrame(bool preRenderOnly, bool bufferSwap) Line 1760 C++
energyWeapon_DEBUG DLL.dll!GuiCanvas::handlePaintEvent(unsigned int did) Line 342 C++
energyWeapon_DEBUG DLL.dll!fastdelegate::FastDelegate1<unsigned int,void>::operator()(unsigned int p1) Line 990 C++
energyWeapon_DEBUG DLL.dll!Signal<void __cdecl(unsigned int)>::trigger(unsigned int a) Line 669 C++
energyWeapon_DEBUG DLL.dll!Journal::Call<Signal<void __cdecl(unsigned int)>,unsigned int>(Signal<void __cdecl(unsigned int)> * obj, void (unsigned int) * method, unsigned int a) Line 634 C++
energyWeapon_DEBUG DLL.dll!JournaledSignal<void __cdecl(unsigned int)>::trigger(unsigned int a) Line 81 C++
energyWeapon_DEBUG DLL.dll!GuiCanvas::paint() Line 1522 C++
energyWeapon_DEBUG DLL.dll!fastdelegate::FastDelegate0<void>::operator()() Line 905 C++
energyWeapon_DEBUG DLL.dll!Signal<void __cdecl(void)>::trigger() Line 651 C++
energyWeapon_DEBUG DLL.dll!Process::processEvents() Line 95 C++
energyWeapon_DEBUG DLL.dll!StandardMainLoop::doMainLoop() Line 610 C++
energyWeapon_DEBUG DLL.dll!torque_enginetick() Line 120 C++
energyWeapon_DEBUG DLL.dll!TorqueMain(int argc, const char * * argv) Line 377 C++
energyWeapon_DEBUG DLL.dll!torque_winmain(HINSTANCE__ * hInstance, HINSTANCE__ * __formal, char * lpszCmdLine, int __formal) Line 452 C++
energyWeapon_DEBUG.exe!WinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, char * lpszCmdLine, int nCommandShow) Line 95 C++
[External Code]
[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]
rlranft
Posts: 298
Joined: Thu Feb 05, 2015 3:11 pm
 
by rlranft » Wed Feb 18, 2015 7:31 am
So, isValidChar() doesn't like null?
9 posts Page 1 of 1

Who is online

Users browsing this forum: No registered users and 1 guest