Please help with appending Ren'Py inventory via hotspot click

SammyW

New Member
Jan 7, 2020
3
0
Thanks for looking :)

I am trying to learn Ren'Py and have spent the past few nights going around in circles trying to figure out how to use an image map or hotspot to create a click-able area on-screen that will add an item to the inventory.

My code at the moment is purely in the main script.rpy file whilst I'm just practising.

I was able to use ($ append.items) through the menu options method without any trouble but all the guides for creating a hotspot or image map / button seem to be focused on navigation if not years out of date.

What I'm trying to do is give the player the ability to "pick up" an item if they click on it but allow the conversation to continue if they don't.

Any help with this would be greatly appreciated.

Regards,
Sammy
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,583
2,223
When writing an interactive , the main goal is to do something.
That something, as you're finding out, is often some form of in-game navigation using .

One solution you could use is to just to jump to a label: and code your inventory append as part of that label.

However, "Jump()" is not the only action available for clickable area like .

The main list is here:


If I had to guess, I think you'll be needing , then using the inventory functions like append.items() or whatever functions are defined.

The two other things probably worth mentioning are and that fact you can code multiple actions by coding them as part of a set (square brackets). Something like action [ SetVariable("quest_found_apple", True), Jump("back_to_village") ].

For examples of imagemap: / imagebutton:, maybe looks at these two previous posts of mine.
https://f95zone.to/threads/finding-...point-click-game-on-renpy.25325/#post-1565577
https://f95zone.to/threads/help-with-imagemaps.50306/post-3336719
There are lots of other good advice for interactive buttons here on the dev sub forums too.
 

SammyW

New Member
Jan 7, 2020
3
0
Thank you 79flavors for the reply and links, have spent most of this night just reading.

It seems my biggest problem is getting the imagemap to be recognised in the first place. Whenever my fumbling attempts at code look the most right I get the error "imagemap expected statement" but once again I have tried so many variables I don't know where I'm going wrong, I've included the gist of my code in the hopes to end this madness :).

-----------------------------------------------

label meeting:

scene chat1
with dissolve

m "I hope you enjoyed the tour"
m "There is a big blue cup on the table [mc] if you would like a drink"

show chat2
with dissolve

###############################################
here is where I am trying to insert the imagemap or button and where I believe I'm getting it wrong. The code is just one of many i tried and saved in frustration - so please don't judge it too harshly.

imagemap:
(688, 588, 173, 131)
action function ($ items.append"bluecup")

###############################################

m "Thank you for attending"
m "Lets go over your results [mc]"

label results:

scene office
with dissolve
show maggie
with moveinright

if "bluecup" in items:
m "So [mc] did you ever finish that game either?"
m "Tomorrow you need to learn blender"

else:
m "Go to bed [mc]"

-----------------------------------------------

Once again, my sincere thanks for any assistance provided,
Sammy
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,583
2,223
Okay. So the only thing that you've missed is that should be part of a definition.

You define what makes up a screen using what RenPy calls . Something you set up separately and then use in your code. You invoke a screen using either show screen or call screen.

Screens can be defined anywhere. Some people will code them within their main script, some will add their screens to the screens.rpy file and others will create their own .rpy file and put their custom screens in there. Honestly, anywhere is fine.

[...]
displays a pre-written screen on top of the existing UI and waits for the screen to trigger an action.​
[...]
displays a pre-written screen on top of the existing UI and just carries on.​
Actions are still processed, but if the player never clicks on the right place - nothing will ever be triggered.​

"show" is generally used for things like navigation/room buttons or status windows. Things the player may or may not use.
"call" is generally used for things that require the player to do something before continuing.

99%* of the time, "called" screens will have the show modal which causes all other UI elements to be disabled while the current screen is being shown. It basically forces the player to use the screen and nothing else.
* 84.7% of statistics on the internet are randomly made up on the spot and do not reflect real life.

70%* of the time, "shown" screens will have a matching statement too.

Something else I think is worth mentioning is that python and RenPy are case sensitive. "a" is not the name as "A", "True is not the same as "true"... or in the case of your code... "Function" is not the same as "function". It's a pain in the arse, but it's something you'll have to get used to.

Finally, $ is used by RenPy as shorthand for "do python command". Some people confuse it with "set variable" because that is how it is used most of the time. I don't think you would need the $ as part of your action.

Edit: As Anne points out in the post below, Function () should be coded differently than I had it. I've updated it to be what I *THINK* it should be like. You may need to tweak it a bit. I'm guessing that like Jump(), everything needs to be wrapped by double quotes too. Again, a guess on my part. My original wrong answer was action Function (items.append("bluecup").

Your final code might looks something like this:

Python:
screen name_of_screen():

    modal True
    imagemap:
        hotspot (688, 588, 173, 131) action Function ("items.append", "bluecup")


label start:

    jump meeting


label meeting:

    scene chat1 with dissolve

    m "I hope you enjoyed the tour"
    m "There is a big blue cup on the table [mc] if you would like a drink"

    show chat2 with dissolve

    call screen name_of_screen

    m "Thank you for attending"
    m "Lets go over your results [mc]"


label results:

    scene office with dissolve
    show maggie with moveinright

    if "bluecup" in items:
        m "So [mc] did you ever finish that game either?"
        m "Tomorrow you need to learn blender"

    else:
        m "Go to bed [mc]"

    # blah, blah, more code.

I've called the screen "name_of_screen". Obviously it can be anything. Like images and labels, it helps to name them in a way that makes sense to you.

Obviously, I haven't tested this code. You may run into some syntax or runtime errors. The core is basically correct, but some of the small details may be wrong.
 
Last edited:
  • Like
Reactions: trylater

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,382
15,290
So the only thing that you've missed is that should be part of a definition.
You missed that he also forgot the , but you used it in your own example.


This said :
Code:
        hotspot (688, 588, 173, 131) action Function ($ items.append"bluecup")
The $ have nothing to do here, and the function and argument(s) should be separated by a coma. So, it should be Function( items.append, "bluecup" ).
Plus, hmm, isn't there a screen action for list manipulation ? I can't find it, but it feel odd that there isn't one.
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,583
2,223
The $ have nothing to do here, and the function and argument(s) should be separated by a coma. So, it should be Function( items.append, "bluecup" ).
Yeah. I'd just spotted that and edited my post while you were replying.
I didn't know about the function / arguments - so I'll correct that too for future people who don't read ahead in threads.

Plus, hmm, isn't there a screen action for list manipulation ? I can't find it, but it feel odd that there isn't one.
Yeah. There is , and plus some toggling commands too.

I figured that the inventory function he was using might be doing something else other than adding/removing from the list array. I dunno, quantity counts or item validation of some sort. Seemed safer to use the existing function rather than working around it.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,382
15,290
Yeah. There is , and plus some toggling commands too.
But none for a list. While set are their near cousin, the two methods to add/remove items don't have the same name, so I assume the their dedicated screen actions wouldn't works.


I figured that the inventory function he was using might be doing something else other than adding/removing from the list array. I dunno, quantity counts or item validation of some sort. Seemed safer to use the existing function rather than working around it.
There's the screen action for that, but if there's more than a single test it's probably better to directly use a dedicated function. It would produce a better understandable code and be a little faster.
 

SammyW

New Member
Jan 7, 2020
3
0
Firstly, a massive thanks to 79flavors and anne O'nymous for picking up my question and pointing me in the right direction. It turns out the hardest part of Ren'Py coding for beginners is understanding the problem in the first place.

Should anyone in future check this thread with a similar question as I began with here are my updated results.

Firstly, make absolutely sure your testing the code your updating and not one of sixteen previously renamed files.

Secondly, check and recheck your spelling and capitalisation. I get that attempting to write a visual novel when language skills were not my strongest subject in school seems odd - but we only improve by trying.

Thirdly, check the line indents - I know that Atom gives a visual clue to parent and child but so many times is it easier to copy and paste and just not notice.

So, as anne pointed out, my initial mistake was assuming that [$ "******"] was just how recording worked. There are perhaps better options for data logging. It's also possible that the other 3 points may have been why I managed to get the error code "Just go to sleep and try again when you can at least count your own feet".

Here is a sample of simplified working code, I haven't yet implemented a way of continuing the story without clicking the hotspot but I'll take seeing my code run for the first time in a week as a win and fight that battle another day.

##############################

Python:
define m = Character("maggie")

label start:

    $ trackstat = []

screen office():

    imagemap:
        idle "chat.webp"
        hover "chat2.webp"
        hotspot (688, 588, 173, 131) action [ AddToSet(trackstat,"cup"), Jump("office2") ]

label office:

    call screen office

label office2:
    show bg office

    m "hello"

    if "cup" in trackstat:
        m "Did you want that cup in blue?"
        m "how did that game turn out?"

    else:
        m "Go to bed"

    return
##############################

With best regards,
Sammy