Jump to content

Photo

Generic FFC Trigger


  • Please log in to reply
46 replies to this topic

#31 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 12 August 2013 - 01:35 PM

Well, that certainly sounds like an intriguing idea with a TON of possibilities. (imagine the puzzles you could build!)

 

EDIT: Oh, yeah, it doesn't work with bombs. I don't think I'll ever NEED it to, but it would help for those double-wide caves, but I can use the other cave graphics, and regular bomb flags if need be. Just thought i'd mention it, because I tried it and it didn't work..


Edited by Lineas, 12 August 2013 - 01:40 PM.


#32 grayswandir

grayswandir

    semi-genius

  • Members

Posted 12 August 2013 - 10:39 PM

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.


#33 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 13 August 2013 - 06:16 AM

When entering values into attributes, I seem to understand that a positive number is the combo number to change.

Is that right?

 

However, when entering a negative value to have a flag act as a trigger, what is the correct formula?

 

(e.g. a -CF_SECRETS01): Do I enter -16 for this? I think that should be right, but I want to ensure I know what values to use.

 

I like the map function greatly, so I expect that if I want have the combos with Flag 16 change to the identically-placed combos from from Map 1, screen 7B, i enter the value 001711 and set the value for the trigger to -16, and set the item required value to the item number from the item editor that is used for that item. Correct?

 

As to arrows, i have no idea why they would not work, but would it be possible to just to incorporate a work-around that detects an LW_ARROW projectile and uses a different global command, with an argument set for the FFC that causes it to function based on arrows or LA_ARROW-based projectiles?

 

The again, I use LW_ARROW on gun projectiles, so this may be another issue, as if I want a target to require a gun or a stazer or a special item that uses LW_ARROW  as its type, it does need to affect the change. Perhaps something in the global variables that detects LW_ARROW specifically and causes the script to behave slightly differently, but still changing the combos, may solve this, while still requiring a specific item to generate the projectile.

 

e.g.

If LastItemUsed == This && lType = LW_ARROW

then this.



#34 grayswandir

grayswandir

    semi-genius

  • Members

Posted 13 August 2013 - 11:18 AM

Your examples are correct, except you want -001711 instead of 001711. So the first three arguments would be "Item Editor Item Number", -16, -1711.

 

As for the arrows, the bug doesn't happen all the time. Going to the default subscreen and changing the arrow selection to have an item override of the level 1 arrows causes it to happen, even if the level 1 arrows are what you already have. But if you don't set that, the arrows work fine. So it seems to be entirely dependent on your subscreen - it might even affect other items than arrows as well.

 

To see if it's affecting a given item, throw in these Trace lines:

////////////////
//// 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) {
    int m[] = "Item Marked:"; TraceS(m); TraceNL();
    Trace(LastItemUsed);
    Trace(GetEquipmentA());
    Trace(GetEquipmentB());
    lw->Misc[MISC_LWEAPON_ITEM] = LastItemUsed;}}

When you use a piece of equipment, this will print out to the log what LastItemUsed is as well as the current values for your equipment slots. If these values are wrong, you know it applies.

 

Edit: Saffith explained what was happening in the thread I linked. It looks like it is indeed limited to arrows, so it shouldn't be too hard to hardcode around it. Let me know if you run into the bug - I'll see if I can find a generic workaround. Otherwise, you might have to use that old EveryWeapon script on all your arrows.


Edited by grayswandir, 13 August 2013 - 02:05 PM.


#35 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 16 August 2013 - 01:47 PM

So, I'm not sure what's going on, here, but SOME of my triggers aren't working, but others are. I know they're all set up correctly, cuz i just checked, can you think of any reasons it just would decide to be temperamental?

 

EDIT: Never mind, I guess I DID have the wrong combo set, after all. (stupid identical combos)

 

EDIT AGAIN: Nope, still being temperamental even after I made DOUBLE SURE all the combos were set right


Edited by Lineas, 16 August 2013 - 02:20 PM.


#36 grayswandir

grayswandir

    semi-genius

  • Members

Posted 16 August 2013 - 03:32 PM

Is it actually triggering and not setting the combos, or is it not triggering for some reason?



#37 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 16 August 2013 - 03:37 PM

it's not triggering, as far as I can tell, but some of the triggers work (or at least they did the last time I posted in this thread, but I can't see any reason the ones that worked before would stop working, I haven't added to the global script, or anything since then.). It's really weird, I have the d0 argument set to the combo to be changed, which I double checked by selecting the combo and checking its number, the d1 to the combo it should be changed in to, and the d2 to the triggering weapon.



#38 grayswandir

grayswandir

    semi-genius

  • Members

Posted 16 August 2013 - 03:43 PM

Could you tell me exactly what the numbers you're using are, and could you set a sound or message argument to tell if it really is being triggered?



#39 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 16 August 2013 - 03:53 PM

it isn't an issue with the arguments, that much I'm certain about, I'm using various arguments on various triggers, and in SOME places it will work, while in another place it won't, even with the exact same arguments set. And as far as setting a sound... Nope, I can't. I have no idea how to. But considering it works in some places and not in others, even when I use the same arguments, I'm just going to go out on a limb and say it's not being triggered. I don't know what the problem is, but I've already eliminated those possibilities.

 

EDIT: If you'd like, I can just send you the .qst file and my script files, so you can look at them directly.


Edited by Lineas, 16 August 2013 - 04:16 PM.


#40 grayswandir

grayswandir

    semi-genius

  • Members

Posted 16 August 2013 - 04:46 PM

Are you using the latest version of the script?

ffc script WeaponTrigger {
  void run(int trigger, int target, int result,
           int dieOnComboChange, int sound, int message) {

 

 

Sure, you can send them to me.



#41 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 16 August 2013 - 05:43 PM

Yeah... I stopped updating the version I was using as soon as I got it to work. I kept breaking my global script and having to recover it from backups...



#42 grayswandir

grayswandir

    semi-genius

  • Members

Posted 16 August 2013 - 05:51 PM

Oh yeah, it might help if I knew which version you were using. :)



#43 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 16 August 2013 - 05:54 PM

oh, yeah, that would be nice. it's the version in this post. I never updated it after you pointed out I needed to set the FFC to ethereal.



#44 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 18 August 2013 - 11:44 AM

I won't pressure you into accepting it, but I did offer a bounty here, and I keep my word. I sent you a PM about it, but you didn't reply. Do you want to claim it?

 

I still haven;t gotten around to getting this set up, but that is due to being ill, and busy elsewhere. Still, it seems complete enough to justify the reward, and I hope that should I find any problems, that you can later correct them (if I cannot); I feel this is an invaluable system addition.



#45 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 25 August 2013 - 05:42 AM

I incorporated this into the latest TGC build. It does work, however there is one minor flaw at present (I have yet to do extensive testing):

If an item doesn't produce an LWeapon, using it on a trigger does nothing. For example, if I wish to use a Books Class item (e.g. Grimoire item) on the trigger to cause a change, as if intoning a spell, it does nothing.

Is there a good solution to add this ability; possibly adding argument D6 to allow for an item used on that spot in place of or in addition to argument D0 for an LWeapon that touches it? This can be combined with an item use script, now that I have the additional arguments at my disposal.

For the time being, I made the item create an LWeapon (Script1) with an invisible combo, no damage, and no speed at Link's position.

I will be testing screen and map based changing presently.

What exactly is D3 supposed to do?

Edited by ZoriaRPG, 25 August 2013 - 06:09 AM.



0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users