Alright, let me know how this works. Also, for some reason Link->Equipment will completely freak out when you use arrows (either a bug or undocumented how it works), so they don't work for now. (It seems like it's some weird bug that won't necessarily apply? I just posted a topic about it.)
////////////////////////////////////////////////////////////////
//// Constants
// The id of the item used to create an lweapon.
const int MISC_LWEAPON_ITEM = 0;
////////////////////////////////////////////////////////////////
//// Global Variables
// The item id of the last item Link has used.
int LastItemUsed = 0;
////////////////////////////////////////////////////////////////
//// Functions
////////////////
//// Updates every LWeapon on screen. Call in the active script.
void UpdateLWeapons() {
for (int i = 1; i <= Screen->NumLWeapons(); i++) {
UpdateLWeapon(Screen->LoadLWeapon(i));}}
////////////////
//// Update a given LWeapon.
void UpdateLWeapon(lweapon lw) {
// If the weapon does not have it's source item marked, mark it as
// being created by the last item that Link has used.
if (lw->Misc[MISC_LWEAPON_ITEM] == 0) {
lw->Misc[MISC_LWEAPON_ITEM] = LastItemUsed;}}
////////////////
//// Updates the LastItemUsed variable to our best guess at what was
//// most recently used. This should be called at the end of the loop,
//// right before Waitdraw or Waitframe, because the item marked in
//// LastItemUsed isn't actually used until after the Waitdraw or
//// Waitframe.
void UpdateLastItem() {
// Since we don't know which button has priority if both are pressed
// at once, cancel the B button press if A has also been pressed
// this frame.
if (Link->PressA && Link->PressB) {Link->PressB = false;}
// If Link is currently in an action where he obviously can't use
// items, then ignore his button presses.
if (Link->Action != LA_NONE &&
Link->Action != LA_WALKING) {
return;}
// Check which button is being pressed, if any. Also check for the
// appopriate Jinx.
if (Link->PressA && Link->SwordJinx == 0) {
LastItemUsed = GetEquipmentA();}
else if (Link->PressB && Link->ItemJinx == 0) {
LastItemUsed = GetEquipmentB();}}
////////////////
//// Return true if the given lweapon is from the given item.
bool IsFromItem(lweapon lw, int itemNumber) {
return lw->Misc[MISC_LWEAPON_ITEM] == itemNumber;}
////////////////
//// Return true if the given lweapon is from the given item class.
bool IsFromItemClass(lweapon lw, int itemClass) {
itemdata data = Game->LoadItemData(lw->Misc[MISC_LWEAPON_ITEM]);
return data->Family == itemClass;}
////////////////////////////////////////////////////////////////
//// Scripts
////////////////
//// When hit by an LWeapon satisfying the <trigger> condition, change
//// all combos on screen that match the <target> condition to what
//// <result> specifies.
////
//// <trigger>: This is what kind of LWeapon will trigger the combo
//// change. If positive, it specifies the item number that will
//// trigger this (e.g. I_ARROW2 will make Silver Arrows trigger
//// this). If negative or 0, it specifies the item class that will
//// trigger this (e.g. -IC_ARROW will make any arrow trigger this).
////
//// <target>: This is what combos that this trigger will change when
//// it is actually triggered. If positive, it specifies that all
//// combos on screen with the given Combo ID will be changed (e.g. a
//// 12 means change all instances of combo 12). If negative, it
//// specifies that all combos on screen with the given flag will be
//// changed (e.g. a -CF_SECRETS01 means to change all combos with the
//// Secret 1 flag on them).
////
//// <result>: This is what the target combos are changed to. If
//// positive, it specifies a combo id to change them to. If negative,
//// it instead specifies a map and screen to grab combos from. The
//// format is "-MMMYXX", where MMM is the map number, Y is the
//// screen's Y position on that map (from 0 to 7), and XX is the
//// screen's X position on that map (from 0 to 15). Every target
//// combo is changed to whatever combo is at the same coordinates on
//// that screen.
////
//// <dieOnComboChange>: If positive, this causes this ffc to cancel
//// if the combo underneath the ffc every changes its Combo ID.
////
//// <sound>: If this is non-zero, it causes the given sound to be
//// played when the trigger occurs.
////
//// <message>: If this is non-zero, it causes the given message to be
//// displayed when the trigger occurs.
ffc script WeaponTrigger {
void run(int trigger, int target, int result,
int dieOnComboChange, int sound, int message) {
// Grab the combo id underneath us so we can tell when it changes.
int loc = ComboAt(CenterX(this), CenterY(this));
int underComboId = Screen->ComboD[loc];
// Interpret <result> if it is negative.
int map;
int screen;
if (result < 0) {
map = (result * -0.001) >> 0;
screen = ((result * -0.01 % 10) >> 0) * 16 + (-result % 100);}
// Wait for something to happen.
bool waiting = true;
while (waiting) {
// If <dieOnComboChange> is set and the combo does change, terminate.
if (dieOnComboChange > 0 && Screen->ComboD[loc] != underComboId) {
return;}
// Loop through all LWeapons on screen.
for (int i = 1; i <= Screen->NumLWeapons(); i++) {
lweapon lw = Screen->LoadLWeapon(i);
// If the LWeapon is touching us.
if (lw->CollDetection && Collision(this, lw)) {
// If <trigger> is positive, test the lweapon for being the
// right item type.
if (trigger > 0) {
if (IsFromItem(lw, trigger)) {
waiting = false;}}
// If <trigger> is negative, test the lweapon for being the
// right item class.
else {
if (IsFromItemClass(lw, -trigger)) {
waiting = false;}}}}
// Advance to next frame.
Waitframe();}
// If we reach this point, it means that we've successfully been
// hit by an acceptable LWeapon.
// Now loop through every combo on screen looking for combos
// matching <target>.
for (loc = 0; loc < 176; loc++) {
bool match = false;
// If <target> is positive, test for Combo ID.
if (target > 0) {
if (Screen->ComboD[loc] == target) {
match = true;}}
// If <target> is negative, test for the flag being present.
else if (target < 0) {
if (ComboFI(loc, -target)) {
match = true;}}
// If the current combo is a match, then transform the combo
// according to <result>.
if (match) {
// If <result> is positive, just change the target to <result>.
if (result > 0) {
Screen->ComboD[loc] = result;}
// If <result> is negative, grab the combo from the given screen.
else if (result < 0) {
Screen->ComboD[loc] = Game->GetComboData(map, screen, loc);}}}
// Now play the message and sound, if appropriate.
if (sound != 0) {Game->PlaySound(sound);}
if (message != 0) {Screen->Message(message);}}}
////////////////
//// Sample Active Script.
global script Active {
void run() {
while (true) {
UpdateLWeapons();
UpdateLastItem();
Waitdraw();
Waitframe();}}}
Edited by grayswandir, 12 August 2013 - 11:07 PM.