Page 1 of 1

[Solved] Song is not always unlocked after seeing persistent

Posted: Tue Sep 25, 2018 12:53 pm
by kostek00

Code: Select all

    playerList = [
        ("bgm/M01.ogg", "images/bgm/M01.png"),
        ("bgm/M02.ogg", "images/bgm/M02.png"),
        ("bgm/M03.ogg", "images/bgm/M03.png"),
        ("bgm/M04.ogg", "images/bgm/M04.png"),
    ]

    if persistent.credits_seen:
        playerList += [
            ("bgm/ED.ogg", "images/bgm/ED.png")
        ]

    mr = MusicRoom(fadeout=0.0, shuffle=False)

    for (track, image) in playerList:
        mr.add(track, always_unlocked=True, action=SetVariable("my_image", image))

    playerList = dict(playerList)

init:
    default my_image = "images/bgm/M01.png"

screen extra:
    tag menu
    add "images/gui/menu_ground.png"

    modal True

    on "replaced" action Play("music", "bgm/M01.ogg")

    imagemap:
        auto "images/gui/extra_%s.png"

        alpha False

        hotspot(302,53,31,27) action mr.Previous()
        hotspot(346,53,25,27) action mr.Play() selected renpy.music.is_playing()
        hotspot(379,53,27,27) action mr.Stop()
        hotspot(415,53,27,27) action mr.ToggleSingleTrack()
        hotspot(454,53,32,27) action mr.Next()
        hotspot(25,534,149,40) action Return()

    add my_image pos(509,43)
This is part of my "extra" menu that contains music player. For unknown to me reason game not always unlocks song "ED.ogg". Sometimes it does sometimes it doesn't, totally random. Also while playing you can't miss "persistent.credits_seen". Any ideas?

Code: Select all

$ persistent.credits_seen = True
This persistent is right before "return" when completing game. I also checked different persistent but result was the same.

Re: Song is not always unlocked after seeing persistent

Posted: Thu Sep 27, 2018 4:15 pm
by kostek00
It seems like song is never unlocked the way I coded it which is strange because any change in game's code unlocks it immidately. Even not related to this code.

Re: Song is not always unlocked after seeing persistent

Posted: Thu Sep 27, 2018 9:49 pm
by Remix
The important code would be the lines just before what you showed, something to show what context the "if persistent.credits_seen:" is ran in... Is it a label, a screen, a python init?

The most likely explanation is that that line only runs once, so is only evaluated once

Re: Song is not always unlocked after seeing persistent

Posted: Fri Sep 28, 2018 3:24 am
by kostek00
It's in init python block.

Re: Song is not always unlocked after seeing persistent

Posted: Fri Sep 28, 2018 4:51 am
by Remix
... which runs Once, at init time... so the persistent variable check only runs when you launch the game...

Move it to a context that is re-evaluated each time it is accessed, like a label or screen.
Alternatively, recode the concept so the playerList is persistent (using default, not init) and just append to it once game completed once.

Re: Song is not always unlocked after seeing persistent

Posted: Fri Sep 28, 2018 9:45 am
by kostek00
Unfortunately when I move this code to label at the and of game i got this error:

Code: Select all

While running game code:
  File "game/S015.rpy", line 779, in script
    python:
  File "game/S015.rpy", line 782, in <module>
    ("bgm/ED.ogg", "images/bgm/ED.png")
TypeError: unsupported operand type(s) for +=: 'RevertableDict' and 'RevertableList'

-- Full Traceback ------------------------------------------------------------

Full traceback:
  File "game/S015.rpy", line 779, in script
    python:
  File "C:\Programy\Ren'Py\renpy\ast.py", line 882, in execute
    renpy.python.py_exec_bytecode(self.code.bytecode, self.hide, store=self.store)
  File "C:\Programy\Ren'Py\renpy\python.py", line 1913, in py_exec_bytecode
    exec bytecode in globals, locals
  File "game/S015.rpy", line 782, in <module>
    ("bgm/ED.ogg", "images/bgm/ED.png")
TypeError: unsupported operand type(s) for +=: 'RevertableDict' and 'RevertableList'
I searched for method that would allow me to add this song to RevertableDict but it's too complicated for me.

Re: Song is not always unlocked after seeing persistent

Posted: Fri Sep 28, 2018 4:02 pm
by Remix
Show the code, both setting up the persistent and the adding to it

Re: Song is not always unlocked after seeing persistent

Posted: Fri Sep 28, 2018 8:21 pm
by kostek00
Code is the same as in first post except the piece that is adding that one song as I moved it into python block inside label in script.

Code: Select all

label add_song:
    $ persistent.credits_seen = True
    python:
        if persistent.credits_seen:
            playerList += [
                ("bgm/ED.ogg", "images/bgm/ED.png")
            ]
I didn't changed playerList to persistent. I don't have idea how could I change this whole code like that.

Meanwhile I also tried playerList.update(dict(playerList)) but it wasn't doing anything (yea, I'm running around like headless chicken trying random stuff that most likely won't work.)

To be honest it doesn't even need to check for persistent if it could add when it's at the end of script:

Code: Select all

label add_song:
    python:
        playerList += [
            ("bgm/ED.ogg", "images/bgm/ED.png")
        ]

Re: Song is not always unlocked after seeing persistent

Posted: Fri Sep 28, 2018 8:44 pm
by philat
Why not just use append?

Re: Song is not always unlocked after seeing persistent

Posted: Fri Sep 28, 2018 9:23 pm
by Remix
unsupported operand type(s) for +=: 'RevertableDict' and 'RevertableList'
means you are trying to add a list to a dict, which (IF it references the line you posted earlier, just didn't post alongside the traceback) means playerList has been defaulted or changed to a dict somewhere and then you're trying to add a list to that

Each (every, not just the first) time you start a new game, non persistent variables will be set to their defaults...
So, each (every, not just the first) time you start or restart, playerList is set to your 4 items
In your code, it Only changes to 5 if label add_song is accessed, so you would need to jump/call that both at the start and end of the game, to check if persistent.credits_seen was good... realistically, you'd even want to call/jump it before main_menu... which is why I part suggested just persisting the list instead...

Something like:

Code: Select all

# at start
default persistent.playerList = [
        ("bgm/M01.ogg", "images/bgm/M01.png"),
        ("bgm/M02.ogg", "images/bgm/M02.png"),
        ("bgm/M03.ogg", "images/bgm/M03.png"),
        ("bgm/M04.ogg", "images/bgm/M04.png"),
    ]

# game stuff

label end_of_game_credits:

    e "Well done"

    $ persistent.playerList.append(
            ("bgm/ED.ogg", "images/bgm/ED.png") )

    return
Sub-note: If the pretext comes across as miffed it is because the code you've posted simply cannot produce the error you posted, so either you changed the code and didn't mention or re-post it or you omitted to show other relevant parts

Re: Song is not always unlocked after seeing persistent

Posted: Fri Sep 28, 2018 10:11 pm
by kostek00
@philat
Ren'Py throws error that RevertableDict has no attribute append.

@Remix
It looks like I'm not capable to understand that. I changed playerList to default persistent.playerList but that throwed error that playerList is not defined (in for loop). So I changed all playerList to persistent.playerList but that didn't worked. It throws that it have too many values to unpack.

Re: Song is not always unlocked after seeing persistent

Posted: Sat Sep 29, 2018 5:52 am
by Randomiser
This is why you're getting the RevertableDict error:

Code: Select all

    playerList = [
        ("bgm/M01.ogg", "images/bgm/M01.png"),
        ("bgm/M02.ogg", "images/bgm/M02.png"),
        ("bgm/M03.ogg", "images/bgm/M03.png"),
        ("bgm/M04.ogg", "images/bgm/M04.png"),
    ]

	... (trimmed) ...
	
    playerList = dict(playerList)
You're changing playerList to a dictionary after declaring it, but treating it like it's still a list when you go to add to it later. In the code you've shown I don't see a reason for it to be a dict at all, so unless you're using it for something else I would bet removing that line fixes your issue.

However...
Ren'py's Music Room should be able to handle detecting which music tracks you've unlocked automatically. You could probably simplify this if you add the track to the music room at startup with the others, but leave always_unlocked as False for this track. The track will only unlock when it's encountered in the game, in your case at the end, which will achieve the same thing as a persistent variable.

Re: Song is not always unlocked after seeing persistent

Posted: Sat Sep 29, 2018 7:37 am
by Remix
Randomiser wrote: Sat Sep 29, 2018 5:52 am

Code: Select all

    playerList = dict(playerList)
You're changing playerList to a dictionary after declaring it
Just saw that myself.
If you do need to continue using that list as a dict, renaming it as player_dict would make great sense.

Just looking at MusicRoom, the unlocked state tests renpy.game.persistent._seen_audio so just playing the track unlocks it. So maybe set locks based on persistence at the beginning and let the engine do the rest...

Code: Select all

    playerList = [
        ("bgm/M01.ogg", "images/bgm/M01.png", True),
        ("bgm/M02.ogg", "images/bgm/M02.png", True),
        ("bgm/M03.ogg", "images/bgm/M03.png", True),
        ("bgm/M04.ogg", "images/bgm/M04.png", True),
        ("bgm/ED.ogg", "images/bgm/ED.png", persistent.credits_seen)
        ]

    mr = MusicRoom(fadeout=0.0, shuffle=False)

    for (track, image, unlocked) in playerList:
        mr.add(track, always_unlocked=unlocked, action=SetVariable("my_image", image))

    ### ??? player_dict = dict([ (k[0],k[1]) for k in playerList]) ### if you are going to use this, at least call it a "dict" in the name
    
label end_credits:
     "..."
     python:
         persistent.credits_seen = True
         # renpy.game.persistent._seen_audio.append("bgm/ED.ogg") # maybe add()
         # If the track has not actually played   

Re: Song is not always unlocked after seeing persistent

Posted: Sat Sep 29, 2018 8:38 am
by kostek00
Remix wrote: Sat Sep 29, 2018 7:37 am

Code: Select all

    playerList = [
        ("bgm/M01.ogg", "images/bgm/M01.png", True),
        ("bgm/M02.ogg", "images/bgm/M02.png", True),
        ("bgm/M03.ogg", "images/bgm/M03.png", True),
        ("bgm/M04.ogg", "images/bgm/M04.png", True),
        ("bgm/ED.ogg", "images/bgm/ED.png", persistent.credits_seen)
        ]

    mr = MusicRoom(fadeout=0.0, shuffle=False)

    for (track, image, unlocked) in playerList:
        mr.add(track, always_unlocked=unlocked, action=SetVariable("my_image", image))
God dammit. Yesterday I was doing something simillar and yet I derped so much to not realize I could just do that. Ech...

Remix wrote: Sat Sep 29, 2018 7:37 am
Randomiser wrote: Sat Sep 29, 2018 5:52 am

Code: Select all

    playerList = dict(playerList)
You're changing playerList to a dictionary after declaring it
Just saw that myself.
If you do need to continue using that list as a dict, renaming it as player_dict would make great sense.
Removeing "playerList = dict(playerList)" isn't crashing game and player works the same so it seems it doesn't needs to be dictionary.


Thank you all for keeping up with such a noob. I really appreciate your help. :D