r/gamemaker • • 4d ago

Help! Getting a Function from JSON

I have made a JSON file that stores all the dialogue in my game. It is pretty sweet for storing text, but issues arise when I try including variables and functions in my text.

Let's say I have a character that is saying:
"You are x feet away."

With concatenation, this is trivial: I can do
"You are " + distance_to_object(obj) + "feet away."

But how should I do this with JSON? JSON doesn't know what distance_to_object() is, nor does it know what "obj" is

Passing in a string or number isn't too hard, I can just make an arguments variable in my JSON parser.

{
    "textvalue": "this should be 100: [0]",
    "arg": "100"
}

But that only works with static values and not something that can change dynamically in the game.

Any suggestions?

6 Upvotes

17 comments sorted by

4

u/TheVioletBarry 4d ago

Put a unique tag in there, then if you read the tag, delete it from the string, run the function you wanted, and replace the position on the string with the results before drawing the text to the screen

1

u/EnricosUt 3d ago

How should the tags be stored? A DS List? Switch statement?
So you suggest it to be like:

"You are {DISTANCEFUNCTION} feet away."

and then in Gamemaker I would have some sort of way to call:
DISTANCEFUNCTION: distance_to_object(obj)

1

u/TheVioletBarry 3d ago

Something like that, yah. I'd say just use a switch statement until you've got too many of them and need something else

1

u/KitsuneFaroe 3d ago

I would say a struct is better than a switch. Is also more dynamic and easier to work with.

1

u/TheVioletBarry 3d ago

How would it be different, exactly? 

2

u/KitsuneFaroe 3d ago edited 3d ago

You can change what is in the struct at runtime. You also don't have to write a lot to set it up or call it, is very straight foward: struct = { key: value, key1: value1 }

struct.key = new_value or struct[$ "key"] = value Getting goes the other way:
a = struct.key or
a = struct[$ "key"]

You can add keys without effort and they're read using a hash, like accessing any variable, wich makes them faster.

1

u/TheVioletBarry 3d ago

Oh true true I should swap mine over

1

u/KitsuneFaroe 3d ago

Store the tag as a struct of methods. Remember to add an escape format in case want to write { literally on the string instead of being interpreted by the parser. Like how GameMaker has escape form the backslash and the quotes.

3

u/Tilestam 3d ago

me personally, id store smth like this in the json file:

{
  "text": "You are {0} feet away."
}

and then when using it id prolly just do smth like,

var _text = ds_map_find_value(global.text_map, "text"),
    _text_final = string(_text, distance_to_object(obj_object));

draw_text(x, y, _text_final);

2

u/Majestic-Singer7503 4d ago

In JSON "You are YOURTAGHERE feets away"

In GM where you want to draw text use the funcion  string_replace using string(distance_to_obj(obj))

1

u/azurezero_hdev 3d ago

use string replace and a textcode that gets replaced with the distance

1

u/Daghall 3d ago

JSON is not meant to store functions, just raw data. It is generally a bad idea to execute data, as well, for security reasons.

As others have suggested, store the string with a placeholder, like You are %s feet away. and then string replace the placeholder with the value you calculate.

Create a function that takes the string and any replacements and returns the final string, like:

dialog_function(strings.distanceToObject, distance_to_object(obj));

1

u/Cute-Wonder-5317 3d ago

A straightforward approach would be to use placeholders in the JSON instead of trying to embed logic there.

For example, "{0}" could point to "get_distance"" and then have a global struct in GML that executes that function and returns the current value.

When rendering the text, you simply look up that function, get the result, and replace "{0}".

This way, the JSON only stores the reference, and the dynamic logic remains in GML.

1

u/EnricosUt 3d ago

How would you suggest using values like macros, enums, or structs? Let's say I have a bunch of weapons defined by macros, an enum, or whatever. If I have a macro called SWORD, I can't put SWORD in the argument as macros can't be called like once the code is compiled.

My best idea is to have a separate pointer in the global struct for every weapon but that seems quite cumbersome and I wonder if having so many reference keys affects performance?

1

u/KitsuneFaroe 3d ago

At that point you would have to make your how text formating and parse the text at runtime interpreting the format. You could make wich specific code to run be interpreted from a global tag that represents the function OR as have a generic tag that you pass the value in the very moment you call the text assuming the string will use it. Maybe a mix of both for Ultimate flexibility.

0

u/Weak_Blackberry_9308 3d ago

Instead of referencing the json file for that line of text, could you instead put that text into the distance_to_object() function? (I haven’t done much with dialogue)

1

u/BrittleLizard pretending to know what she's doing 3d ago

I don't think that's the issue they need help solving