//import "std.zh"
const int ANIMATION_STAB_DURATION = 7; //The duration of the weapon's Stab animation
const int ANIMATION_SLASH_DURATION = 15; //The duration of the weapon's Slash animation.
const int ANIMATION_POUND_DURATION = 15; //The time between using the Hammer and when it slams into the ground. Exactly the same time as ANIMATION_SLASH_DURATION
const int ITEMDATA_AUGMENT_ID = 0; //The index of the array used to address the ID of the item used. This uses the D0 variable.
const int ITEMDATA_AUGMENT_FAMILY = 1; //The index of the array used to address the item's Class entry in the item editor.
const int ITEMDATA_AUGMENT_LEVEL = 2; //The index of the array used to address the item's Level entry in the item editor.
const int ITEMDATA_AUGMENT_POWER = 3; //The index of the array used to address the item's Power entry in the item editor.
const int ITEMDATA_AUGMENT_COUNTER = 4; //The index of the array used to address the item's counter reference in the item editor, primarily intended for giving the item a cost in the script. This is used here to free up a D-Variable that could be used for something else.
const int ITEMDATA_AUGMENT_USESOUND = 5; //The index of the array used to address the item's Sound entry in the item editor.
const int ITEMDATA_AUGMENT_D1 = 6; //The index of the array used to address the item's D1 variable in the item editor.
const int ITEMDATA_AUGMENT_D2 = 7; //The index of the array used to address the item's D2 variable in the item editor.
const int ITEMDATA_AUGMENT_D3 = 8; //The index of the array used to address the item's D3 variable in the item editor.
const int ITEMDATA_AUGMENT_D4 = 9; //The index of the array used to address the item's D4 variable in the item editor.
const int ITEMDATA_AUGMENT_D5 = 10; //The index of the array used to address the item's D5 variable in the item editor.
const int ITEMDATA_AUGMENT_D6 = 11; //The index of the array used to address the item's D6 variable in the item editor.
const int ITEMDATA_AUGMENT_D7 = 12; //The index of the array used to address the item's D7 variable in the item editor.
const int ITEMDATA_AUGMENT_DELAYCOUNTER = 13; //The index of the array used to store the delay variable of the item, which is initialized in the script.
const int ITEMDATA_AUGMENT_EXTRA = 14; //The index of the array reserved for extra functions
int ScriptWandAugments[15]; //The array used for communicating with scripts, stored as an array to cut down on global variable usage.
global script Slot_2{
void run(){
while(true){
ScriptWand(); //Place the call for your Wand script in the main global loop.
Waitframe();
}
}
}
global script Slot_3{ //Example Global OnExit script
void run(){
ClearItemdataScriptWand(); //Place the call to clear the array associated with the wand in your OnExit Global script.
}
}
void ScriptWand(){
if(ScriptWandAugments[ITEMDATA_AUGMENT_DELAYCOUNTER] > 0){ //Check for if the wand is being used
ScriptWandAugments[ITEMDATA_AUGMENT_DELAYCOUNTER] ++; //Increment the delay counter by 1
if(ScriptWandAugments[ITEMDATA_AUGMENT_DELAYCOUNTER] == ANIMATION_SLASH_DURATION && Game->Counter[ScriptWandAugments[ITEMDATA_AUGMENT_COUNTER]] >= ScriptWandAugments[ITEMDATA_AUGMENT_D1]){ //Change ANIMATION_STAB_DURATION to ANIMATION_SLASH_DURATION if your Wand/Sword/Candle/etc slashes. Also handles any cost required. You can set the cost to any D# variable you like except 0.
//Stuff goes here.
Game->Counter[ScriptWandAugments[ITEMDATA_AUGMENT_COUNTER]] -= ScriptWandAugments[ITEMDATA_AUGMENT_D1]; //Apply the cost
ClearItemdataScriptWand(); //Clear the array at the end of the function
}
else if(ScriptWandAugments[ITEMDATA_AUGMENT_DELAYCOUNTER] == ANIMATION_SLASH_DURATION && Game->Counter[ScriptWandAugments[ITEMDATA_AUGMENT_COUNTER]] < ScriptWandAugments[ITEMDATA_AUGMENT_D1]){ //Change ANIMATION_STAB_DURATION to ANIMATION_SLASH_DURATION if your Wand/Sword/Candle/etc slashes. Animation times up and Link doesn't have enough of counter, clear array. You can set the cost to any D# variable you like except 0.
ClearItemdataScriptWand(); //Just clear the array
}
// if(Link->Action == LA_GOTHURTLAND){ //Uncomment this code block to allow for getting hit during the slash/stab animation to cancel the projectile.
// ClearItemdataScriptWand(); //Clear the array
// }
}
}
void LoadItemdataScriptWand(int id, int d1, int d2, int d3, int d4, int d5, int d6, int d7){ //Load up the array.
itemdata data = Game->LoadItemData(id);
ScriptWandAugments[ITEMDATA_AUGMENT_ID] = id; //Item's ID. Uses D0
ScriptWandAugments[ITEMDATA_AUGMENT_FAMILY] = data->Family; //Item Class
ScriptWandAugments[ITEMDATA_AUGMENT_LEVEL] = data->Level; //Item Level
ScriptWandAugments[ITEMDATA_AUGMENT_POWER] = data->Power; //Item's Power
ScriptWandAugments[ITEMDATA_AUGMENT_COUNTER] = data->Counter; //Item's Counter
ScriptWandAugments[ITEMDATA_AUGMENT_USESOUND] = data->UseSound; //Item's Sound
ScriptWandAugments[ITEMDATA_AUGMENT_D1] = d1; //Item's D# variables
ScriptWandAugments[ITEMDATA_AUGMENT_D2] = d2;
ScriptWandAugments[ITEMDATA_AUGMENT_D3] = d3;
ScriptWandAugments[ITEMDATA_AUGMENT_D4] = d4;
ScriptWandAugments[ITEMDATA_AUGMENT_D5] = d5;
ScriptWandAugments[ITEMDATA_AUGMENT_D6] = d6;
ScriptWandAugments[ITEMDATA_AUGMENT_D7] = d7;
}
void ClearItemdataScriptWand(){ //Clear the array.
for(int i = 0; i < SizeOfArray(ScriptWandAugments); i ++){
ScriptWandAugments[i] = 0; //Clear augments
}
}
item script ScriptWand{
void run(int id, int d1, int d2, int d3, int d4, int d5, int d6, int d7){
LoadItemdataScriptWand(id, d1, d2, d3, d4, d5, d6, d7); //Loads the itemdata into a script array. Note that the D-variables are also loaded through here, because the is no itemdata entry for them.
ScriptWandAugments[ITEMDATA_AUGMENT_DELAYCOUNTER] = 1; //Start the script.
}
}
Update: 8:31 PM 12/08/2015 AEST - Addition of the option to enable getting hit while stabbing or slashing to cancel the projectile, and minor rewrite to the script to match how the built-in Wand consumes Magic/counter.
As it says on the tin, this script will allow you to hijack wands (and other things that have a stab/slash animation, like Candles and Swords) to delay the onset of the effect until the slash/stab animation has ended instead on the frame the item is used on. This replicates the delay of projectiles fired by Swords, Wands and Candles and is useful for having them fire custom LWeapons. This is currently in beta and needs testing.
Setup
Simply copy-paste the script into your script files, import std.zh if you already haven't, and place the ScriptWand(); function call in the main global loop of Global Script Slot 2. If you want the Wand to slash, change "ANIMATION_STAB_DURATION" in the ScriptWand(); call to "ANIMATION_SLASH_DURATION". Compile it and then set up your Wand (or Sword) in the item editor:
Under the Data page of the Wand item, make sure the checkbox "Allow Magic w/o Book" is unchecked. This is to prevent the wand from firing its default Magic LWeapon alongside your scripted effect. (For Swords, make sure "B.H. is percent" is unchecked and Beam Hearts is set to a really high amount (eg. 100) to prevent the sword beam from firing off alongside your scripted effect).
(Skip this if you don't require the effect to have a cost) Go over to the Pickup tab and set "Counter Reference" to the counter that the weapon uses to check against costs is set to the counter you require (eg. Set it to "Arrows" if you require the effect to cost Arrows). Next, pop over to Augments and set D1 to how much of the counter specified before it takes to activate the Wand's special effect.
While still under Augments, attach the ScriptWand script to the Wand's active slot and set D0 to the item's ID. Setting it to the correct ID is vital to the script's function, Don't miss it.
Change the item's Level, Power, UseSound and the other D-Variables to your heart's content and you are ready
However, the script by itself doesn't actually do anything - This is merely the skeleton of such a script. You, the scripter, will have to write the effect yourself. Here are a few guidelines on how to write the effect:
All 8 D# variables must be declared in the void run() of the item script or else the script will not compile.
LoadItemdataScriptWand must be called at the start of the item script.
ClearItemdataScriptWand must be called whenever the script might end. This includes in the global script after the scripted effect ends and in the item script if there is any chance that the script might end before it reaches the trigger that activates the Global portion of it (eg. If you don't meet the item's cost.). It also must be called in Global script Slot_3 (OnExit) to prevent possible issues for if you die or F6 during the wands' animation.
You put your code into the area which says "//Stuff goes here"
List of Weapon types supported by this script:
Wand
Sword
Candle
Cane of Bryna
Hammer (Use the ANIMATION_SLASH_DURATION with Hammers)
Caveats
If you are using this with Wands, do not give the player the Book unless you want it to fire the default Wand magic alongside your intended effect if the player acquires it. For the same reason, it is not a good idea to give the player the Peril Beam scroll if you give this to swords unless you like the idea of Link randomly shooting Sword Beams alongside the script's effect when at 1 Heart or whatnot.
If you charge using the sword while the script is attached to said sword, the effect occurs while you are charging; much like the standard sword beam.
If you wish to give the item a counter increase alongside this script and you wish to give it a cost, the counter the counter increase on pickup refers to is the same one as the weapon uses to read its counter cost.
Future plans
Full support for Hammers. They may or may not be supported by this script, but I will need to test that.
Support for delaying effects for swords until Link has finished charging his sword and after he has finished a Spin Attack/Hurricane spin.
A basic example script.
Full documentation. This documentation is rough and fails to explain everything I wish to explain.
I've some scripted wand, sword, and other weapons that could fill in the blanks. I even have most of the stock items set up as global functions, to make it easier to map an item to Ex buttons, or use them any way that I please.
I'm not however, sold on why this is useful: Why would you want to delay the damage of a sword, or other weapon, like this?
i.e. What is the intended application?
I should not again, for added emphasis, that if you script an item to use magic, you need to tie its cost into Game->Generic[GEN_MAGICDRAINRATE] so that if a user wants to utilise 'half-magic' in a game, it is consistent for values set both via the Item Editor, and direct script checks/instructions.
The script's intended application is to time the activation of the script's effect with the animation of the built-in Stab or Slash animation the Wand it is attached to has (which is shared with other weapon types like Sword, Candle and Cane of Bryna), instead of activating on the frame after the button is pressed like what an item script by itself would, to produce a projectile that is fired by the Wand in much the same way as how the built-in Magic weapon is fired. This can be adapted to Swords, Candles and Canes of Bryna (though the latter two are not optimal, as they have effects of their own that are harder to stop and are rendered obsolete by the versatility of the Wand unless you wish to have the weapon's swing to not cause damage and the rule that prevents the Wand from being used as a Melee weapon is not checked).
Say for instance you have a special projectile that you want a custom wand to fire. If you use just an item script, the projectile is fired on the frame you use the weapon; which does not match up with the timing at which the Wand fires its default projectile. This is acceptable when the wand has no slash/stab animation (at which point you should be using a different item class altogether instead of a wand item) or somewhat acceptable when it uses the stab animation because it instead of yourself still appears to fire the projectile.
However, when you wish to have the Wand use the slashing animation, the projectile is fired well before the Wand is held in front of Link (and before the animation ends); which looks bad as it appears to fire from Link and not the Wand itself. This combined Global/Item script approach solves this issue, as the Wand with the slashing animation now correctly appears to fire the projectile from the wand as opposed to Link appearing to fire it. It also makes the stabbing variant look more authentic and in line with how the wand fires projectiles.
Edit: I also forgot one important feature that I need to include - Getting hit while slashing or stabbing with the built-in Wand before the projectile is fired cancels the projectile. This script will need to be updated to reflect that... And done!
Edit again: Scratch that, that wasn't a feature present on the Wand. Modifying post accordingly.
Ah, that's much clearer, and something I could do in three, or four ways. I'll try to make some code for you next week, so that you have a more well-rounded project. I may even consider making a function DelayItem() as a general thing, or DelayProjectile().
It's actually probably possible to copy, kill, and recreate a projectile too.
It does sound like a very good plan indeed, and the way that I hadled this in the past was a bit different.
I may even make something like AutoGhost for weapons at some point. They're one of my specialisations (engine dynamics, and visual effects are my other prime foci), after all. That would allow a user to set up routines for eweapons, and lweapons in general.