Changes in Verb Coin Code

Started by DBoyWheeler, Wed 13/09/2023 11:55:27

Previous topic - Next topic

DBoyWheeler

Okay, I made the changes for the hotspot flag, but even then, no action verb is appearing before the target hotspot or object.

Khris

Did you fix the cursor hotspots? You could also consider using a sprite that isn't a massive X and completely obscuring the thing you want to click?

Also check your code and make sure that it always puts new text on the label, regardless of which path the execution takes.

DBoyWheeler

I shrank down the pointer (hopefully it won't be TOO small).

Um, would the code that I need to check be in the main (global) script, or somewhere in the verbcoin script?  I'm a little lost here.

Khris

Was referring to the code that changes the action line, the one you added.

DBoyWheeler

I'm assuming it's this code in the verb coin script
Code: ags
function repeatedly_execute()
{
  if (interface == null || !enabled)
  {
    // don't do anything if GUI isn't set or is disabled
  }
  else if (player.ActiveInventory == null)
  {
    if (interface.Visible)
    {
      // update text label for verb coin actions
      GUIControl* control = GUIControl.GetAtScreenXY(mouse.x, mouse.y);

      if (action_label == null)
      {
        // pass
      }
      else if (control != null && control.AsButton != null && control.Enabled && context_text != null)
      {
        if(control == btnUse)
        {if(ThingToPickUp == true){action_label.Text = String.Format("Pick up %s", context_text);}
        else if (DoorToOpen == true){action_label.Text = String.Format("Open %s", context_text);}
        else if (PlaceToInspect == true){action_label.Text = String.Format("Check %s", context_text);}}
        else action_label.Text = String.Format("%s %s", actionmap[control.ID], context_text);
      }
      else if (context_text != null)
      {
        action_label.Text = context_text;
      }
    }
    else if ((interface_inv != null && !interface_inv.Visible) || GetLocationType(mouse.x, mouse.y) == eLocationNothing)
    {
      // update regular text label
      context_text = Game.GetLocationName(mouse.x, mouse.y);

      if (action_label != null)
      {
        action_label.Text = context_text;
      }
    }
  }
  else
  {
    if (interface_inv != null && interface_inv.Visible && GUI.GetAtScreenXY(mouse.x, mouse.y) != interface_inv)
    {
      // close inventory window once the cursor leaves
      interface_inv.Visible = false;
    }

    // update text label for 'combining' items
    String location = Game.GetLocationName(mouse.x, mouse.y);
    InventoryItem *i = InventoryItem.GetAtScreenXY(mouse.x, mouse.y);

    if ((i != null && i.ID == player.ActiveInventory.ID) || location == "")
    {
      location = "...";
    }

    if (action_label != null)
    {
      action_label.Text = String.Format("Use %s with %s", player.ActiveInventory.Name, location);
    }
  }
}

Is there something that might be out of order that is messing things up?

Khris

#25
The problem seems to be this part:

Code: ags
        if (control == btnUse) {
          if (ThingToPickUp == true) {
            action_label.Text = String.Format("Pick up %s", context_text);
          } else if (DoorToOpen == true) {
            action_label.Text = String.Format("Open %s", context_text);
          } else if (PlaceToInspect == true) {
            action_label.Text = String.Format("Check %s", context_text);
          }
        } else action_label.Text = String.Format("%s %s", actionmap[control.ID], context_text);

Using proper indentation you can now see that if the execution enters the control == btnUse block but then neither of the three variables are true, the code simply does nothing.
You need to change the code so that some label text is always assigned. The easiest way to do this is to simply execute the default line first, then let the special handling overwrite the label:

Code: ags
        action_label.Text = String.Format("%s %s", actionmap[control.ID], context_text);
        if (control == btnUse) {
          if (ThingToPickUp == true) {
            action_label.Text = String.Format("Pick up %s", context_text);
          } else if (DoorToOpen == true) {
            action_label.Text = String.Format("Open %s", context_text);
          } else if (PlaceToInspect == true) {
            action_label.Text = String.Format("Check %s", context_text);
          }
        }

Also note that this can be refactored into:

Code: ags
        String action = actionmap[control.ID]; // default verb
        if (control == btnUse) {
          if (ThingToPickUp) action = "Pick up";
          else if (DoorToOpen) action = "Open";
          else if (PlaceToInspect) action = "Check";
        }
        action_label.Text = String.Format("%s %s", action, context_text);

DBoyWheeler

Okay, something is REALLY screwed up.

The verbs are working again, but when I got to the opened door (a HotSpot), the interact command is still "Use Opened Door" (instead of "Check Opened Door").  When the Dark Star appears after getting the inventory bag, when I click on the revealed Dark Star, it ends up saying "Check Dark Star" (instead of "Pick up Dark Star", which is what it is supposed to read; again the "Check" verb is for certain hotspots, not objects).  Do I need to change the Booleans into some other variables to make them work properly?

Khris

You also need to reset your variables to false.

At the point where you do
Code: ags
  if (some_condition) ThingToPickUp = true;

do this instead:
Code: ags
  ThingToPickUp = some_condition;

Otherwise ThingToPickUp will remain true and unexpected results will occur.

DBoyWheeler

Would I put that resetting the values in this section of the repeatedly_execute code?

Code: ags
if (interface == null || !enabled)
  {
    // don't do anything if GUI isn't set or is disabled
  }

Khris

I don't think that's going to work.

But like I said, just change the code you yourself added to the script, the part where you set the three flags to true.
If you simply also set them to false if the condition isn't true, that should do it.
The code should be in the module's on_mouse_click function, in the block that ends with
Code: ags
        interface.Visible = true;

DBoyWheeler

It's gone back to "Use" [object] (regardless of what the spot or object is).

Khris

I'm going to go out on a limb and say it's your code that's causing this.
Could you post the relevant lines...?

DBoyWheeler

Yeah, I don't know what the heck I'm doing wrong with the code.

Here's the mouse click one (well, the portion of the mouse click that's important here):
Code: ags
function on_mouse_click(MouseButton button)
{
  if (interface == null || !enabled)
  {
    // don't do anything if GUI isn't set or is disabled
  }
  else if (button == eMouseLeft)
  {
    if (GetLocationType(mouse.x, mouse.y) != eLocationNothing)
    {
      if (player.ActiveInventory != null)
      {
        Room.ProcessClick(mouse.x, mouse.y, eModeUseinv);
      }
      else if (interface.Visible)
      {
        interface.Visible = false;
      }
      else if (interface_inv != null && interface_inv.Visible)
      {
        interface_inv.Visible = false;
      }
      else if (Character.GetAtScreenXY(mouse.x, mouse.y) != player)
      {
        if(GetLocationType(context_x, context_y) == eLocationObject)
        {
          Object* o = Object.GetAtScreenXY(context_x, context_y);
          ThingToPickUp = o.GetProperty("CanObjectBePickedUp");
          DoorToOpen = o.GetProperty("ADoorToOpen");
        }
        if(GetLocationType(context_x, context_y) == eLocationHotspot)
        {
          Hotspot* h = Hotspot.GetAtScreenXY(context_x, context_y);
          PlaceToInspect = h.GetProperty("PlaceToInspect");
        }
        context_x = mouse.x;
        context_y = mouse.y;
        interface.X = Maths.Clamp(context_x - interface.Width / 2, 0, SCREEN_WIDTH - interface.Width);
        interface.Y = Maths.Clamp(context_y - interface.Height / 2, 0, SCREEN_HEIGHT - interface.Height);

        if (button_auto_disable)
        {
          for (int i; i < interface.ControlCount; i ++)
          {
            if (interface.Controls[i].AsButton != null)
            {
              interface.Controls[i].Enabled = IsInteractionAvailable(context_x, context_y, modemap[interface.Controls[i].ID]);
            }
          }
        }

        interface.Visible = true;
        ThingToPickUp = false;
        DoorToOpen = false;
        PlaceToInspect = false;
      }
    }
    // close windows or unset the active inventory item
    else if (interface.Visible)
    {
      interface.Visible = false;
    }
    else if (interface_inv != null && interface_inv.Visible)
    {
      interface_inv.Visible = false;
    }
    else if (player.ActiveInventory != null)
    {
      player.ActiveInventory = null;
    }
    else
    {
      // ...except when there is no nothing to deselect or close,
      // so just walk to this position
      Room.ProcessClick(mouse.x, mouse.y, eModeWalkto);
    }
  }

And here's the repeatedly execute code (again, the portion that's important here)
Code: ags
if (interface.Visible)
    {
      // update text label for verb coin actions
      GUIControl* control = GUIControl.GetAtScreenXY(mouse.x, mouse.y);

      if (action_label == null)
      {
        // pass
      }
      else if (control != null && control.AsButton != null && control.Enabled && context_text != null)
      {
        String action = actionmap[control.ID];
        if (control == btnUse)
        {
          if (ThingToPickUp) action = "Pick up";
          else if (DoorToOpen) action = "Open";
          else if (PlaceToInspect) action = "Check";
        }
        action_label.Text = String.Format("%s %s", action, context_text);
      }
      else if (context_text != null)
      {
        action_label.Text = context_text;
      }
    }
    else if ((interface_inv != null && !interface_inv.Visible) || GetLocationType(mouse.x, mouse.y) == eLocationNothing)
    {
      // update regular text label
      context_text = Game.GetLocationName(mouse.x, mouse.y);

      if (action_label != null)
      {
        action_label.Text = context_text;
      }
    }
  }

What am I screwing up?

Khris

#33
The code that sets your flags based on the properties uses old coordinates.
You need to do
Code: ags
        context_x = mouse.x;
        context_y = mouse.y;

first. Move these two lines up, above the two blocks that check the properties.

Also, resetting the flags needs to happen right before they are potentially set.
Move up the three lines below interface.Visible = true;, also above the mentioned two blocks.

Referring to the first snippet, cut lines 36, 37, 53, 54 and 55 and paste them between lines 24 and 25.

DBoyWheeler

#34
I think it's working now.  I'll test it on doors next time I do testing.  Thanks.  I'll let you know if I run into any more trouble.

[Update]
Now I have a new issue.

There's a part in my "intro tutorial" where I show the player how to use the "Spirit Falcon".
Code: ags
function cLara_AnyClick()
{if(mouse.Mode == eModeSpFalcon)
  {if((cLara.Room == 2)&&(LaraAwakened == false))
  {
    player.FaceCharacter(cLara, eBlock);
    player.Say("Spirit Falcon, this dear child needs help!");
    cLara.Animate(1, 5, eOnce, eBlock, eForwards);
    Wait(20);
    cLara.Animate(2, 5, eOnce, eBlock, eForwards);
    cLara.UnlockView();
    cLara.FaceDirection(eDirectionDown, eBlock);
    LaraAwakened = true;
    cLara.Name = "Lara Blaapeppe";
    cLara.Say("Where am I?");
    player.Say("I'm curious to that myself, but I got you out of that bag.");
    player.Say("My name is Sarimento.");
    cLara.Say("Thank you, Mr. Sarimento.  My name is Lara.  Lara Blaapeppe.");
    cLara.FaceDirection(eDirectionRight, eBlock);
    cLara.Say("My home town is not too far away.  Follow me.");
    Display("This is where we would transport to the Blaapeppe neighborhood.  For now, we'll end here.");
    QuitGame(0);
    }
  else
  {
    player.Say("She's already awoken from my Spirit Falcon's powers.");
  }}
}

But when I test it in game, nothing happens.  No error messages, no animations... nothing.  What could I be doing wrong?

Crimson Wizard

It's worth mentioning, referring to the conversation on Discord, that mouse.Mode turned out to be 0 in this function. This means that the problem is not in cLara_AnyClick, but in how mouse.Mode is set elsewhere.

DBoyWheeler

The new idea from CrimsonWizard (on Discord) helped.  Thanks.  I'll let you know if I run into any more problems.

SMF spam blocked by CleanTalk