Author Topic: Weapon State Question [Solved]  (Read 2076 times)

How could I make it so this calls onPreFire before onFire? I don't know much about weapon states.
Code: [Select]
stateName[0]                       = "Activate";
stateTransitionOnTriggerDown[0]    = "Fire";
stateAllowImageChange[0]   = true;
stateSound[0]   = NONE;
stateTransitionOnTimeout[0]   = "Ready";
stateTimeoutValue[0]   = 0.3;

stateName[1]                       = "Ready";
stateTransitionOnTriggerDown[1]    = "Fire";
stateAllowImageChange[1]   = true;

stateName[2]                       = "Fire";
stateTransitionOnTriggerUp[2]   = "StopFire";
stateTransitionOnTimeout[2]   = "Fire";
stateTimeoutValue[2]   = 0.01;
stateWaitForTimeout[2]   = true;
stateFire[2]   = true;
stateAllowImageChange[2]   = true;
stateSound[2]   = NONE;
stateScript[2]   = "onFire";
stateEmitter[2]   = FlashlightEmitter;
stateEmitterTime[2]   = 0.07;
stateSequence[2]   = "fire";

stateName[3]   = "StopFire";
stateTransitionOnTimeout[3]   = "Ready";
stateWaitForTimeout[3]   = true;
stateAllowImageChange[3]   = true;
stateSequence[3]   = "stopFire";
« Last Edit: February 12, 2013, 12:43:52 PM by jes00 »

Explain what you're trying to make. Do you want to add a pre-fire state, or just run a script before the weapon fires?

Explain what you're trying to make. Do you want to add a pre-fire state, or just run a script before the weapon fires?
I'm making it so you need energy to fire this weapon. I just want to run a script before the weapon fires that can prevent the firing of the weapon.

I'm making it so you need energy to fire this weapon. I just want to run a script before the weapon fires that can prevent the firing of the weapon.
Well, you don't have many options for affecting the state system through script. If you simply avoid firing the projectile, the image will still play emitters and sounds and animations and such. You'll want to create at least one new state, using the fields "stateTransitionOnAmmo" and "stateTransitionOnNoAmmo," which work like the trigger down/up and timeout ones. Then you can use %player.setImageAmmo(%slot, 0 or 1) to control what will happen when you get to that state.

you could do special functions for the states
Like
for a ChargeState that calls "onCharge"
you could do onTriggerDown would call "ChargeTick" which would go back to  Charge and onTriggerUp would go back to the ready state
function WeaponImage::onChargeTick(%this,%obj,%slot)
{
    %obj.chargeWeapon++;
    if(%obj.chargeWeapon >= 100)
        %this.onFire();
}
or something of that sort

you could do special functions for the states
Like
for a ChargeState that calls "onCharge"
you could do onTriggerDown would call "ChargeTick" which would go back to  Charge and onTriggerUp would go back to the ready state
function WeaponImage::onChargeTick(%this,%obj,%slot)
{
    %obj.chargeWeapon++;
    if(%obj.chargeWeapon >= 100)
        %this.onFire();
}
or something of that sort
Manually calling onFire is a bad idea, because you don't get any of the effects imposed by the state system that I mentioned above - emitters, sounds, and animations.

You'll want to create at least one new state, using the fields "stateTransitionOnAmmo" and "stateTransitionOnNoAmmo," which work like the trigger down/up and timeout ones. Then you can use %player.setImageAmmo(%slot, 0 or 1) to control what will happen when you get to that state.
Like this?
Code: [Select]
stateName[0]   = "PreFire";
stateTransitionOnAmmo[0]   = "Activate";
stateTransitionOnNoAmmo[0]   = "StopFire";
stateAllowImageChange[0]   = "true";
stateSound[0]   = NONE;

stateName[1]                       = "Activate";
stateTransitionOnTriggerDown[1]    = "Fire";
stateAllowImageChange[1]   = true;
stateSound[1]   = NONE;
stateTransitionOnTimeout[1]   = "Ready";
stateTimeoutValue[1]   = 0.3;

stateName[2]                       = "Ready";
stateTransitionOnTriggerDown[2]    = "Fire";
stateAllowImageChange[2]   = true;

stateName[3]                       = "Fire";
stateTransitionOnTriggerUp[3]   = "StopFire";
stateTransitionOnTimeout[3]   = "Fire";
stateTimeoutValue[3]   = 0.01;
stateWaitForTimeout[3]   = true;
stateFire[3]   = true;
stateAllowImageChange[3]   = true;
stateSound[3]   = NONE;
stateScript[3]   = "onFire";
stateEmitter[3]   = FlashlightEmitter;
stateEmitterTime[3]   = 0.07;
stateSequence[3]   = "fire";

stateName[4]   = "StopFire";
stateTransitionOnTimeout[4]   = "Ready";
stateWaitForTimeout[4]   = true;
stateAllowImageChange[4]   = true;
stateSequence[4]   = "stopFire";

Like this?
Activate should be your first state - it's the one that happens as you're getting the gun out, plays the weaponSwitchSound, all that.

Bleh.
Code: [Select]
stateName[0]                       = "Activate";
stateTransitionOnTriggerDown[0]    = "PreFire";
stateAllowImageChange[0]    = true;
stateTransitionOnTimeout[0]    = "Ready";
stateTimeoutValue[0]    = 0.3;

stateName[1]                       = "Ready";
stateTransitionOnTriggerDown[1]    = "PreFire";
stateAllowImageChange[1]    = true;

stateName[2]    = "PreFire";
stateTransitionOnAmmo[2]    = "Fire";
stateTransitionOnNoAmmo[2]    = "StopFire";
stateAllowImageChange[2]    = "true";

stateName[3]                       = "Fire";
stateTransitionOnTriggerUp[3]    = "StopFire";
stateTransitionOnTimeout[3]    = "Fire";
stateTimeoutValue[3]    = 0.01;
stateWaitForTimeout[3]    = true;
stateFire[3]    = true;
stateAllowImageChange[3]    = true;
stateScript[3]    = "onFire";
stateEmitter[3]    = FlashlightEmitter;
stateEmitterTime[3]    = 0.07;
stateSequence[3]    = "fire";

stateName[4]    = "StopFire";
stateTransitionOnTimeout[4]    = "Ready";
stateWaitForTimeout[4]    = true;
stateAllowImageChange[4]    = true;
stateSequence[4]    = "StopFire";

package Flashlight
{
function flashlightImage::onFire(%this, %player, %slot)
{
if(%player.getDatablock().getID() == playerSurvivor.getID())
{
%player.setEnergyLevel(%player.getEnergyLevel() - 1);

if(!%player.getEnergyLevel())
{
%player.setImageAmmo(%slot, 0);
}

else
{
%player.setImageAmmo(%slot, 1);
}
}

else
{
%player.setImageAmmo(%slot, 1);
}

return parent::onFire(%this, %player, %slot);
}
};
activatePackage(Flashlight);
It does not stop when you run out of energy and after you run out of energy and fire it, it crashes Blockland (console says nothing).


First, it's crashing because you're cyclically transitioning through three states when out of ammo - Ready to PreFire to StopFire, repeat. Second, put a stateTransitionOnNoAmmo in fire, too, so it goes to stopFire when you run out. Third, consider adding onStopFire and onPreFire scripts that check if the energy is less or greater than an arbitrary value, like 10 percent, and if so, toggles the ammo accordingly. This will make it so if your energy runs below it, you can keep firing until you let go of the trigger (Because fire only loops through itself, not through stop/preFire) or run out of energy, at which point you'll have to recharge back up to that value before you can use it again.

First, it's crashing because you're cyclically transitioning through three states when out of ammo - Ready to PreFire to StopFire, repeat.
So how should I fix this?

So how should I fix this?
You should plan your states out before you set them all up. Think over exactly what route the game will take through them depending on circumstances. In this case, you need a delay somewhere in the process.

You should plan your states out before you set them all up. Think over exactly what route the game will take through them depending on circumstances. In this case, you need a delay somewhere in the process.
How about this?
Code: [Select]
stateName[0]                       = "Activate";
stateTransitionOnTriggerDown[0]    = "PreFire";
stateAllowImageChange[0]   = true;
stateTransitionOnTimeout[0]   = "Ready";
stateTimeoutValue[0]   = 0.2;

stateName[1]                       = "Ready";
stateTransitionOnTriggerDown[1]    = "PreFire";
stateTimeoutValue[1]   = 0.1;
stateAllowImageChange[1]   = true;

stateName[2]   = "PreFire";
stateTransitionOnAmmo[2]   = "Fire";
stateTransitionOnNoAmmo[2]   = "StopFire";
stateAllowImageChange[2]   = "true";

stateName[3]                       = "Fire";
stateTransitionOnTriggerUp[3]   = "StopFire";
stateTransitionOnNoAmmo[3]   = "StopFire";
stateTransitionOnTimeout[3]   = "Fire";
stateTimeoutValue[3]   = 0.01;
stateWaitForTimeout[3]   = true;
stateFire[3]   = true;
stateAllowImageChange[3]   = true;
stateScript[3]   = "onFire";
stateEmitter[3]   = FlashlightEmitter;
stateEmitterTime[3]   = 0.07;
stateSequence[3]   = "fire";

stateName[4]   = "StopFire";
stateTransitionOnTimeout[4]   = "Ready";
stateWaitForTimeout[4]   = true;
stateAllowImageChange[4]   = true;
stateSequence[4]   = "StopFire";

EDIT: Nope it crashes when you run out of energy >:|
« Last Edit: February 12, 2013, 11:36:58 AM by jes00 »

Put the timeout in StopFire instead of Ready - it's the one that transitions on timeout anyway.