inkle / ink

inkle's open source scripting language for writing interactive narrative.
http://www.inklestudios.com/ink
MIT License
4.14k stars 495 forks source link

Dynamically duplicating a knot ?? #741

Closed Alex-Sand-0 closed 2 years ago

Alex-Sand-0 commented 2 years ago

Hi, I am looking for some advice on the best way to use ink with some generated content. I have some knot describing a "templated" quest, whose parameters are instantiated from the c# game code. I would like to have several instances of the same templated quest, dynamically generated during the game. The problem: it does not work if they all use the same knot.

Here is a dummy example to better explain the issue:

EXTERNAL hasFoundItem(itemName)
EXTERNAL locateItem(itemName)
-> questSimple( "some magic choucroute" ) 

== questSimple(itemName) == 
    VAR questSimple_itemName = ""
    ~questSimple_itemName = itemName

    {itemfound:-> alreadydone}
    {running: -> running}
    -> start
    = start
        Hello, could you bring me {questSimple_itemName}
        + sure
            Great that you accept!
            ->running
        + Nope
            -> DONE

    = running
        + (itemfound) {hasFoundItem(questSimple_itemName)}  I found it
                Thanks, here is 100 gold
                -> DONE
        + Where can I find it ?
            ~ temp location = locateItem(questSimple_itemName)
            {location}
            -> running
        + bye
            ->DONE

    = alreadydone
        Thanks again for having found {questSimple_itemName}
        ->DONE

// dummy implemetation of external function for testing
=== function locateItem(itemName) ===
    ~ return "{~ somewhere to the west}"
=== function hasFoundItem(itemName) ===
    ~ return RANDOM(1,2)==1        

When the c# code instantiate a new quest, I would call _inkStory.ChoosePathString($"questSimple" , generatedItem); to start the quest. But if the player starts a second quest, the status 'itemfound' would be shared between the quests, resulting in a bug... So my question is, what is the best way to avoid this issue?

... I have been considering several workarounds so far:

It seems all those potential solutions have significant drawbacks. Is there a better way I am missing?

GreenCloversGames commented 2 years ago

Interesting. You've clearly put a lot of thought into this. Here are some I have.

I would probably experiment with the top one first, but then if that didn't work, I would use this.

There may also be a way to use flows, but I don't think visitcounts are independent of each flow.

Alex-Sand-0 commented 2 years ago

Hi, thanks for these ideas! They should indeed limit the size of the api between ink and c# compared to what I had in mind. However they still require a bit more specific logic, I still hope to be able to simply use the visitcounts from ink.

Note: I am letting the topic open for now in case someone brings more ideas.