[SOLVED] Display inventory screen - modal overrided by screen "say" when interacted with

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
User avatar
Arphedia
Newbie
Posts: 6
Joined: Sat Jul 11, 2020 5:36 am
Contact:

[SOLVED] Display inventory screen - modal overrided by screen "say" when interacted with

#1 Post by Arphedia » Sat Jul 11, 2020 12:06 pm

Hello everyone !
I do hope you're having a great day :)

I know you've read this a lot, but I'm a newbie whith Renpy :lol:
I started to make a RPG-like Visual Novel a month ago and even if I have resolved a lot of my issues thanks to your posts, there's still one problem I can not seem to be able to bypass ^^'

So I created some classes : Player, Item and Inventory to start my Inventory system, and I coded a screen (highly inspired by Leon's one ! Thanks a lot Leon !!) to display the inventory.

First of all, let me show you how I built my classes, so you'd be able to understand the following code !
Here's the declaration of my Player class:

Code: Select all

class Player(renpy.store.object):
        def __init__(self, name, gender="m", level=1, max_hp=10, max_mp=5):
            self.name = name
            self.gender = gender
            self.level = level
            self.max_hp = max_hp
            self.hp = max_hp
            self.max_mp = max_mp
            self.mp = max_mp
            self.inventory = Inventory(25) #25 represents the amount of gold the player posses at the label start


Now, here's the declaration of my Item class:

Code: Select all

class Item(store.object):
    def __init__(self, name, hp=0, mp=0, image="", cost=0, type="divers", consommable=True, essential=False):
        self.name = name
        self.hp = hp # How much hp gain ?
        self.mp = mp # cHow much mp gain ?
        self.image=image # path to the image without the extension "idle"/"hover"/"insensitive"
        self.cost=cost # How much does it cost ?
        self.type=type # How it will be sorted ?
        self.consommable = consommable # Can the player use the item on himself ?
        self.essential=essential #Can the player drop it ?

And finally, here's I made my Inventory class:

Code: Select all

class InventoryObject(object):
    def __init__(self, item, amount):
        self.item = item
        self.amount = amount


class Inventory(store.object):
    def __init__(self, gold=15):
        self.gold = gold
        self.items = []

    def finditem(self, item):  #return the element searched in the inventory
        return(self.items[[i.item for i in self.items].index(item)])

    def add(self, item, amount=1): # add a contener with the item et its amount in the inventory
        if item in [i.item for i in self.items]:
            self.finditem(item).amount += amount
        else:
            self.items.append(ObjetdInventaire(item, amount))
            return('success')

There, you can see that my Inventory is not only made of a list of items.
It uses an instance of InventoryObject which is an object that contain the item but also contain the amount of it in the inventory.
So, in one way, it's a container.

To make it clearer, you can see it like this. "->"means that it contains the following:

Player -> Inventory -> items -> InventoryObject -> Item
-> amount


I created the screen to display my player.inventory that I call with a button in a side menu.
From now on, I will simplify my code to the strict essential so it does't have a frightening size (more than it has :lol: )
Here's the side menu button :

Code: Select all

imagebutton idle "gui/Inventaire_idle.png" action ToggleScreen("inventaire", dissolve) tooltip "Inventaire"

And then, here is the declaration of the screen that display my inventory:

Code: Select all

screen inventory:
    modal True

    #The whole inventory screen (Big thanks to Leon :D )
    frame:
    	background "gui/Inventaire/inventaire_menu.png"
        hbox:
        	frame:
                style "frame_inventaire_items"
                xalign 0.4 yalign 0.2
                $ x = 0 # coordinates of the top left item position
                $ y = 6
                $ i = 0
                $ next_inv_page = inv_page + 1
                if next_inv_page > int(len(player.inventory.items)/25):
                	$ next_inv_page = 0
                for it in player.inventory.items:
                    $ path = "{0}".format(it.item.image)
                    $ itidle = "{0}_idle.png".format(path)
                    if i+1 <= (inv_page+1)*25 and i+1>inv_page*25 and(it.item.type == tri_inventaire or tri_inventaire=="all"):
                    	$ x += 80
                        if i%5==0:
                        	if i%25!=0:
                        		$ y += 75
    			    	$ x = 0
			frame:
				background "gui/Inventaire_petit/fond_icone_inventaire2.png"
                           	xpos x ypos y
                            	vbox:
					xalign 0.5 yalign 0.5
					imagebutton idle itidle action ToggleScreen("interaction_object", None, it.item, renpy.get_mouse_pos())
					text "[it.amount]" xalign 1.0 yalign 0.0 size 10
		$ i += 1
                if len(player.inventory.items)>25:
                	textbutton _("Page précédente") action [SetVariable('inv_page', next_inv_page), Show("inventory")]


            ### Player stats box ( simplfied)
            frame:
                style "frame_inventaire_statistiques"
                vbox:
                    vbox:
                        text "[player.name]"
                        text "Niveau [player.level]"
                    vbox:
                        hbox :
                            text "Hp"
                            text "[player.hp]/[player.max_hp]"
                        bar value AnimatedValue(player.hp, player.max_hp) style "greenbar"
                    vbox:
                        hbox :
                            text "Mp"
                            text "[player.mp]/[player.max_mp]"
                        bar value AnimatedValue(player.mp, player.max_mp) style "bluebar"

You can also take a look at my interaction_object screen that display the item menu:

Code: Select all

screen interaction_object( objet, position):
    zorder 100
    $ mouseposx = position[0]
    $ mouseposy = position[1]

    frame:
        xpos mouseposx ypos mouseposy
        xsize 400 ysize 250
        vbox:
            hbox:
                textbutton "x" xalign 1.0 yalign 0.0 action ToggleScreen("interaction_object")
                text "What do you want to do of [objet.name] ?" xalign 0.0
            vbox:
                xalign 0.5
                hbox:
                    textbutton "use it on yourself" action [SensitiveIf(objet.consommable == True),Hide("interaction_object"), Function(player.inventory.remove_item, objet, 1)]
                    # textbutton "l'utiliser" tooltip "L'utiliser sur quelqu'un ou quelque chose" ###
                #hbox:                                                                            ###
                    # textbutton "le jeter"                                                       ### Havn't coded these three yet
                    # textbutton "Observer"                                                       ###


Now that you have the code that is concerned by my issue, I'm finally going to explain what's happening ^^'

So, when I do start the game and I show the inventory screen with the button, I have all my items in my inventory as shown on screen n1 with their amount.

Image Screen n1


Then, I click on an item. On screen n2 I clicked the strawberries, and the interaction_object screen showed up !

ImageScreen n2

When I clicked the button to use the object on the player, the interaction_object screen disappeared, but instead of showing me only the inventory screen, the "say" screen showed on top, with the next say statement.
We can also see that one item of strawberries has been used, so I do know that my function has been executed correctly.

I'd like to understand what I may have done the wrong way to have the "say" statement rollforward...

I suspected that when the interaction of the second screen had finished (the interaction_object one, on an item), then the first screen (the inventory modal) sees its task as finished too and automatically execute a Return(). So it is supposed to close the modal, and rollforward the say statement.
As to know why the inventory screen do not disappear, I think it may be because of the way I had called it...

Does anyone know if I am right ?

I was wondering if someone here had had the same issue, or knows how to prevent the modal to use Return() while we do not ask for it.
I tried a lot of code to bypass this : I put the screen with the loop that display each item in another screen, I tried to rewrite the keymap to prevent the rollforward with any key, I attempted to use ui.interact() but with no success...
Maybe I have not used it well, so if you do know a way to solve my problem, I'd be more than happy!

I was looking forward to post this question here, because I've been working on this issue for some days now and I do know that many of you are a lot more experienced than I am !

Even if you don't have an answer to my question, you can answer the topic if you see any mistakes in my code ! I will also gladly take any advice you have to give :D

I'm sorry for any mistakes I may have made in english ^^' I hope it was still understandable.
Last edited by Arphedia on Sat Jul 11, 2020 6:00 pm, edited 1 time in total.

User avatar
Alex
Lemma-Class Veteran
Posts: 2727
Joined: Fri Dec 11, 2009 5:25 pm
Contact:

Re: Display inventory screen - modal overrided by screen "say" when interacted with

#2 Post by Alex » Sat Jul 11, 2020 2:58 pm

Arphedia wrote:
Sat Jul 11, 2020 12:06 pm
...I was wondering if someone here had had the same issue, or knows how to prevent the modal to use Return() while we do not ask for it. ...
Just a thought...
Your 'use' button on 'interaction_object' screen does the function 'player.inventory.remove_item' - check the code for this function.

In your Inventory class you have a function 'add' that actually has a 'return' statement, so if you have it in 'player.inventory.remove_item' function as well this might be the issue.

User avatar
Arphedia
Newbie
Posts: 6
Joined: Sat Jul 11, 2020 5:36 am
Contact:

Re: Display inventory screen - modal overrided by screen "say" when interacted with

#3 Post by Arphedia » Sat Jul 11, 2020 5:14 pm

Hello Alex !

Thank you so much for your quick answer :D

I feel really dumb right now because I think it was one of the only thing I haven't thought about ^^' And honestly I wouldn't have thought of it alone !
So really, thank you.

Alright, in my inventory function remove_item I had :

Code: Select all

def remove_item(self, item, amount=1):
            if self.has_item(item):
                self.finditem(item).amount -= amount
                if self.finditem(item).amount <= 0:
                    self.items.pop(self.items.index(self.finditem(item)))
                    return('gone')
                else:
                    return('more left')
            else:
                return('not found')
Where each return were indeed a problem here, because i returned a value...

Just one last question before I set this topic as Solved... If I do wanted to know if the object(s) has been deleted, should I use a global variable such as "global state" in which I update the status of the inventory action ? Or would there be a "cleaner" way to do so ?

User avatar
Alex
Lemma-Class Veteran
Posts: 2727
Joined: Fri Dec 11, 2009 5:25 pm
Contact:

Re: Display inventory screen - modal overrided by screen "say" when interacted with

#4 Post by Alex » Sat Jul 11, 2020 5:44 pm

Arphedia wrote:
Sat Jul 11, 2020 5:14 pm
... If I do wanted to know if the object(s) has been deleted, should I use a global variable such as "global state" in which I update the status of the inventory action ? Or would there be a "cleaner" way to do so ?
Uh, I don't know why do you want some additional info about inventory changes (if you showing inventory screen changes should be visible), but you could try to show a message via renpy.notify instead of returning a value.
https://www.renpy.org/doc/html/other.html#renpy.notify

User avatar
Arphedia
Newbie
Posts: 6
Joined: Sat Jul 11, 2020 5:36 am
Contact:

Re: Display inventory screen - modal overrided by screen "say" when interacted with

#5 Post by Arphedia » Sat Jul 11, 2020 6:01 pm

Yeah that's exactly what I wanted to do :) To Notify the player !

Again,thank you for your quick and insightful answers !

Have a nice day :D

User avatar
renardjap
Regular
Posts: 75
Joined: Sun Aug 05, 2018 1:08 pm
Location: France ! Cocorico
Contact:

Re: [SOLVED] Display inventory screen - modal overrided by screen "say" when interacted with

#6 Post by renardjap » Sat Jul 11, 2020 6:28 pm

Hi
I have a question: do you have written all the code by yourself or you found it somewhere ? I would like to make an inventory too.

P.s. ça fait plaisir de voir un peu de français sur le forum :lol:

User avatar
Arphedia
Newbie
Posts: 6
Joined: Sat Jul 11, 2020 5:36 am
Contact:

Re: [SOLVED] Display inventory screen - modal overrided by screen "say" when interacted with

#7 Post by Arphedia » Mon Jul 13, 2020 2:25 am

Hey, hello Renardjap, sorry for my delayed answer, I'd been working on that same inventory yersteday :lol:

For my inventory, I found the post of Leon, who shared one ! I based my code a lot on his, so you can find it here.

I also found a little tutorial on youtube made by Elaine that you'll be able to find here :wink: !

I mixed up both code a little and made what I needed for my game on my own, but these two really helped me for the declaration of my classes !
Hope it had helped you...

PS : Hey ! Effectivement, ce n'est pas souvent sur ce forum :lol: ravie de trouver d'autres français ici ! Désolée d'avoir mis toute ma réponse en anglais, mais c'est pour que tout le monde puisse comprendre. Bonne chance pour ton inventaire, et si jamais je peux répondre à quelques unes de tes questions tu peux me mp, j'essayerai de regarder !

User avatar
renardjap
Regular
Posts: 75
Joined: Sun Aug 05, 2018 1:08 pm
Location: France ! Cocorico
Contact:

Re: [SOLVED] Display inventory screen - modal overrided by screen "say" when interacted with

#8 Post by renardjap » Mon Jul 13, 2020 12:41 pm

Thank you for your answer.
Yes I know the both tutorial, but I'm better at art than code XD
I will try :)

P.s. ça fait quand même bizarre de communiquer en anglais entre français XD. En tout cas ton inventaire est vraiment super !

User avatar
Arphedia
Newbie
Posts: 6
Joined: Sat Jul 11, 2020 5:36 am
Contact:

Re: [SOLVED] Display inventory screen - modal overrided by screen "say" when interacted with

#9 Post by Arphedia » Tue Jul 14, 2020 1:38 pm

Yeah I know it can be difficult to understand a code when it's long !
Ahah I can relate :lol:

PS : C'est vrai ! mais on a toujours les PSs :D Merci beaucoup !

Post Reply

Who is online

Users browsing this forum: Majestic-12 [Bot]