Possible Random Unhandled Functions (Tumbleweed)

Started by Jackpumpkinhead, Fri 21/03/2025 02:18:17

Previous topic - Next topic

Jackpumpkinhead

So I have been getting back into the swing of things with AGS and my game is coming along nicely. Lots of new things learned and implementing some of my old knowledge. I'm not great with coding, but I understand enough to get what I need done.

A ln idea hit me the other day with my game. What if the Unhandled() function in the template allowed for multiple random responses? Currently the template only gives a one answer response. These are nice and help to make coding a little easier. However, I thought it would be a nice personal touch to have make the responses vary a bit.

For example: Say the room has a cup as a hotspot. The code for the room and that hotspot look like this:

Code: ags
function hcup_AnyClick()
{
    // LOOK AT
    if (Verbs.UsedAction(eGA_LookAt)) {
        player.Say("It's a blue cup.");
    }
    // USE
    else if (Verbs.UsedAction(eGA_Use)) {
        player.Say("I'd rather pick it up.");
    }
    // PICKUP
    else if (Verbs.UsedAction(eGA_PickUp)) {
        player.Say("Okay.");
        Verbs.AnyClickWalkLookPick(108, 100, eDir_Up, "You are now mine.",oCup.ID, iCup);
    }
    //USE INV
    else if (Verbs.UsedAction(eGA_UseInv)) {
        Verbs.Unhandled();
    }
    // don't forget this
    else Verbs.Unhandled();
} 

Under the "(Verbs.UsedAction(eGA_UseInv)" there is "Verbs.Unhandled()" which causes the player to say something like "I don't wanna do that." And it will say that every time the player uses an inventory item on the cup hotspot.

I was able to find the default responses in the "TemplateSettings" script. What I would like to do is modify the script so that I can add a few more lines of dialogue that will give some variety to the default Unhandled function.

For example instead of the player just saying "I don't wanna do that." They will say "These two things don't work together." or "I feel like that is a bad idea." or "probably not gonna work." And each time the player tries to use an inventory item on the cup they get a different random response from these options.

This is what I added to the "TemplateSettings" script:

Code: ags
// Function to get a random response for each verb
String GetRandomUseResponse() {
    int index = Random(7);
    if (index == 0) return "That doesn't work like that.";
    if (index == 1) return "Yeah... no. That's not gonna do anything.";
    if (index == 2) return "If this is supposed to work, I'm clearly missing something.";
    if (index == 3) return "I could try, but I'd just embarrass myself.";
    if (index == 4) return "That makes about as much sense as a screen door on a submarine.";
    if (index == 5) return "Sure, let's just combine random things and hope for the best!";
    return "I'd have better luck just staring at it until something happens.";
}

String GetRandomLookResponse() {
    int index = Random(7);
    if (index == 0) return "It looks... like a thing.";
    if (index == 1) return "Yup, that's definitely what that is.";
    if (index == 2) return "I see it, but what am I supposed to do with it?";
    if (index == 3) return "Looking at it harder isn't going to help.";
    if (index == 4) return "Cool. Now what?";
    if (index == 5) return "Great. I've observed it. Achievement unlocked.";
    return "It's there, I'm here. What a time to be alive.";
}

String GetRandomPickupResponse() {
    int index = Random(7);
    if (index == 0) return "It's not really something I need.";
    if (index == 1) return "It's probably better off where it is.";
    if (index == 2) return "I'd love to, but my pockets aren't that big.";
    if (index == 3) return "Look, I have a problem, but I'm not hoarding random junk level yet.";
    if (index == 4) return "I swear, if I pick up one more useless thing, I'm legally a pack mule.";
    if (index == 5) return "Oh sure, let me just put that in my magic bottomless pockets.";
    return "One day, I'll figure out where all this stuff actually goes.";
}

String GetRandomPushResponse() {
    int index = Random(7);
    if (index == 0) return "Why am I pushing random things?";
    if (index == 1) return "That doesn't seem like the kind of thing to push.";
    if (index == 2) return "I don't think brute force will solve this one.";
    if (index == 3) return "This would be easier if I worked out... which I don't.";
    if (index == 4) return "This is how you start unnecessary lawsuits.";
    if (index == 5) return "Because randomly pushing stuff is the mature solution.";
    return "If something explodes, I did not do it.";
}

String GetRandomPullResponse() {
    int index = Random(7);
    if (index == 0) return "I don't think that's how this works.";
    if (index == 1) return "I don't want to break anything... yet.";
    if (index == 2) return "Pulling on things randomly is not a solid strategy.";
    if (index == 3) return "If it hasn't moved by now, it probably isn't going to.";
    if (index == 4) return "Somehow, I doubt that'll make my life easier.";
    if (index == 5) return "Maybe if I pull harder it'll magically work?";
    return "I'd look pretty dumb yanking on that for no reason.";
}

String GetRandomTalkToResponse() {
    int index = Random(7);
    if (index == 0) return "It's not much of a conversationalist.";
    if (index == 1) return "I could talk, but I doubt I'd get a response.";
    if (index == 2) return "I think I'd get better conversation out of a brick wall.";
    if (index == 3) return "I'd feel weird talking to that.";
    if (index == 4) return "I talk to myself enough already. I don't need this too.";
    if (index == 5) return "I could try, but even I have limits.";
    return "Hey there, inanimate object. ...Nope, still feels weird.";
}

String GetRandomGiveToResponse() {
    int index = Random(7);
    if (index == 0) return "I don't think that's a fair trade.";
    if (index == 1) return "I doubt they'd want that.";
    if (index == 2) return "That doesn't seem like the kind of gift someone would appreciate.";
    if (index == 3) return "I'm just handing things to people now? Is that a thing I do?";
    if (index == 4) return "I'll keep it for now. Maybe I'll meet someone desperate enough to take it.";
    if (index == 5) return "Because randomly giving people stuff always works out in my favor.";
    return "I'd love to see their reaction. Just not enough to actually do it.";
}

// Function to set up random unhandled responses
function SetupUnhandledVerbResponses() {
    Verbs.VerbGuiUnhandled[eVerbGuiUnhandledUse]      = GetRandomUseResponse();
    Verbs.VerbGuiUnhandled[eVerbGuiUnhandledUseInv]   = GetRandomUseResponse();
    Verbs.VerbGuiUnhandled[eVerbGuiUnhandledLook]     = GetRandomLookResponse();
    Verbs.VerbGuiUnhandled[eVerbGuiUnhandledLookChar] = GetRandomLookResponse();
    Verbs.VerbGuiUnhandled[eVerbGuiUnhandledPickup]   = GetRandomPickupResponse();
    Verbs.VerbGuiUnhandled[eVerbGuiUnhandledPickupChar] = GetRandomPickupResponse();
    Verbs.VerbGuiUnhandled[eVerbGuiUnhandledPush]     = GetRandomPushResponse();
    Verbs.VerbGuiUnhandled[eVerbGuiUnhandledPushChar] = GetRandomPushResponse();
    Verbs.VerbGuiUnhandled[eVerbGuiUnhandledPull]     = GetRandomPullResponse();
    Verbs.VerbGuiUnhandled[eVerbGuiUnhandledPullChar] = GetRandomPullResponse();
    Verbs.VerbGuiUnhandled[eVerbGuiUnhandledTalkTo]   = GetRandomTalkToResponse();
    Verbs.VerbGuiUnhandled[eVerbGuiUnhandledTalkToChar] = GetRandomTalkToResponse();
    Verbs.VerbGuiUnhandled[eVerbGuiUnhandledGive]     = GetRandomGiveToResponse();
}

/***********************************************************************
 * game_start()
 ***********************************************************************/
function game_start()
{
    set_options(); // Keep existing Tumbleweed settings
    SetupUnhandledVerbResponses(); // Apply the new randomized responses
}

This works but when I run the game and use one of the verbs that is coded as Unhandled I only get one of the predetermined responses every time for the rest of the game. If I stop the game and start it again I will get a different predetermined response for every time that verb is used with the Unhandled function for the rest of the game.

Is there a way to properly do what I am asking?

Crimson Wizard

#1
Your mistake is that you run the randomization only once the game starts, save its result in array, and then it will be used all time after.

If you want a random reply each time, then you should get rid of "VerbGuiUnhandled" array completely, and call respective GetRandomxxxResponse instead whenever that array was read in the template code.

I don't remember the template's code. Maybe you could write a wrapper function GetRandomResponse(int unhandled_verb_type) for convenience:
Code: ags
String GetRandomResponse(int unhandled_verb_type)
{
     switch (unhandled_verb_type)
     {
     case eVerbGuiUnhandledUse: return GetRandomUseResponse();
     case eVerbGuiUnhandledLook: return GetRandomLookResponse();
     // etc
     }
     return "respond in case of unknown type";
}

Then whenever the template had something like:
Code: ags
String s = Verbs.VerbGuiUnhandled[ verb_type ];
you replace that with:
Code: ags
String s = GetRandomResponse( verb_type );



EDIT:
An alternative way would be to make a 2D array, where you can store multiple responses per unhandled verb type. Then a user would configure the array in template settings, filling it with all possible variants of reply, and Verb module would run a Random function to choose from these.
AGS 3.* does not support multidimensional arrays, but it's possible to either emulate 2D array using 1D array (although it may be complicated in case there are varied number of responses per type). Or this may be done by introducing a struct with array inside, like:

Code: ags
#define MAX_RESPONSES 8
struct UnhandledVerbResponse
{
     String Responses[MAX_RESPONSES];
     int ValidResponsesCount;
};
and change VerbGuiUnhandled to hold these structs instead of plain strings:
Code: ags
// making this up, cause I don't have a template declaration before me right now
UnhandledVerbResponse VerbGuiUnhandled[max unhandled events];

Jackpumpkinhead

Thank you for the response. I wish that I could say that I completely understand what you are saying, but as I mentioned in the beginning of the post, I'm not that great with coding. Array's are still a bit of an enigma to me. I know that I posted this in the Technical Questions forum. But I am probably more of a beginner.

Crimson Wizard

I looked at the Tumbleweed's source and, unfortunately, the change I suggested to array won't work directly, as VerbGuiUnhandled is not a real array, but a "indexed property". Regardless of the chosen approach more changes would be required for the module to make this work.

I would have to find spare time and write a answer with a proper solution, unless someone else does this first.

Khris

Open VerbGui.asc, scroll down to line 1980 and use this:

Code: ags
String GetRandomLookResponse() {
    int index = Random(7);
    if (index == 0) return "It looks... like a thing.";
    if (index == 1) return "Yup, that's definitely what that is.";
    if (index == 2) return "I see it, but what am I supposed to do with it?";
    if (index == 3) return "Looking at it harder isn't going to help.";
    if (index == 4) return "Cool. Now what?";
    if (index == 5) return "Great. I've observed it. Achievement unlocked.";
    return "It's there, I'm here. What a time to be alive.";
}

void ShuffleUnhandled() {
  verbsData.unhandled_strings[eVerbGuiUnhandledLook] = GetRandomLookResponse();
  // verbsData.unhandled_strings[eVerbGuiUnhandledUse] = GetRandomUseResponse();
  // ...
}
 
static void Verbs::Unhandled(int door_script) 
{
  ShuffleUnhandled();
  InventoryItem*ii = InventoryItem.GetAtScreenXY(mouse.x, mouse.y);
  int type=0;
  if (verbsData.location_type == eLocationHotspot)   type = 1;

(At the bottom is the top of the existing Verbs::Unhandled function, with the added ShuffleUnhandled() line.)

Danvzare

I remember this being standard in the old 9-Verb template. You could literally just copy and paste it from there.

Jackpumpkinhead

Quote from: Khris on Fri 21/03/2025 09:35:11Open VerbGui.asc, scroll down to line 1980 and use this:

Code: ags
String GetRandomLookResponse() {
    int index = Random(7);
    if (index == 0) return "It looks... like a thing.";
    if (index == 1) return "Yup, that's definitely what that is.";
    if (index == 2) return "I see it, but what am I supposed to do with it?";
    if (index == 3) return "Looking at it harder isn't going to help.";
    if (index == 4) return "Cool. Now what?";
    if (index == 5) return "Great. I've observed it. Achievement unlocked.";
    return "It's there, I'm here. What a time to be alive.";
}

void ShuffleUnhandled() {
  verbsData.unhandled_strings[eVerbGuiUnhandledLook] = GetRandomLookResponse();
  // verbsData.unhandled_strings[eVerbGuiUnhandledUse] = GetRandomUseResponse();
  // ...
}
 
static void Verbs::Unhandled(int door_script) 
{
  ShuffleUnhandled();
  InventoryItem*ii = InventoryItem.GetAtScreenXY(mouse.x, mouse.y);
  int type=0;
  if (verbsData.location_type == eLocationHotspot)   type = 1;

(At the bottom is the top of the existing Verbs::Unhandled function, with the added ShuffleUnhandled() line.)
Quote from: Khris on Fri 21/03/2025 09:35:11Open VerbGui.asc, scroll down to line 1980 and use this:

Code: ags
String GetRandomLookResponse() {
    int index = Random(7);
    if (index == 0) return "It looks... like a thing.";
    if (index == 1) return "Yup, that's definitely what that is.";
    if (index == 2) return "I see it, but what am I supposed to do with it?";
    if (index == 3) return "Looking at it harder isn't going to help.";
    if (index == 4) return "Cool. Now what?";
    if (index == 5) return "Great. I've observed it. Achievement unlocked.";
    return "It's there, I'm here. What a time to be alive.";
}

void ShuffleUnhandled() {
  verbsData.unhandled_strings[eVerbGuiUnhandledLook] = GetRandomLookResponse();
  // verbsData.unhandled_strings[eVerbGuiUnhandledUse] = GetRandomUseResponse();
  // ...
}
 
static void Verbs::Unhandled(int door_script) 
{
  ShuffleUnhandled();
  InventoryItem*ii = InventoryItem.GetAtScreenXY(mouse.x, mouse.y);
  int type=0;
  if (verbsData.location_type == eLocationHotspot)   type = 1;

(At the bottom is the top of the existing Verbs::Unhandled function, with the added ShuffleUnhandled() line.)

OMG! This works. Thank you so much. I still don't know why it's not built into the template. But whatever.

SMF spam blocked by CleanTalk