Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

On version 0.2.1, I have been dealing with big missbehavior of multiple features of the dungeon rooms and equipment, some of them that worked on version 0.1.6. After checking and trying to solve the annoying not-working features, I got the mayor bug that has been causing ALL these troubles.

The Bug I found is an incorrect use of hasattr to check the existance of the player's inventory. All statements condition checks with "hasattr(store, 'persistent.player_inventory')" will result into False.

The Cause of this is that "hasattr(object, 'attribute_name')" only works with direct attributes of the object, not recursively with multiple nesting levels and dot notation. See https://stackoverflow.com/questions/4342168/can-hasattr-go-multiple-children-dee...

There are at least 3 Solutions to fix it.

  • Remove all ocurrences of "hasattr(store, 'persistent.player_inventory')" (replace with empty line or the rest of the current sentence). (what i did)
  • Use "hasattr(store, 'persistent') and hasattr(store.persistent, 'player_inventory)" instead.
  • Use a custom multi-level-hasattr function to be defined in init.rpy to perform "hasattr" recursively, following dot notation for the second argument (as shown in https://stackoverflow.com/questions/4342168/can-hasattr-go-multiple-children-dee...).

 

The following list show all the places affected by the bug, and the quick fixes I applied (all code line numbers based on original v0.2.1 unaltered files):

 

1) No detection of gold coins for spins at the Gamble room ("Gamble Room Unified Action Screen"). (remove and deindent)

[code]

  File "game/dungeon_rooms.rpy", line 1889, inside gamble_unified_actions_screen.

[/code] 

2) No detection of gold coins for purchases at the Vending Machine room. (remove and deindent)

[code]

  File "game/dungeon_rooms.rpy", line 7345, inside room_vending_machine.

[/code]

3) Tight Rubber Belt equipment not breaking at Rank Up. (changed)

  File "game/init.rpy", lines 1328-1334, inside _perform_rank_up:

[code]

        belt_idx_to_remove = -1

        

        for i, item_dict in enumerate(store.persistent.player_inventory):

            if item_dict.get("id") == "equip_tight_rubber_belt":

                belt_idx_to_remove = i

                belt_snapped_this_event = True

                break

[/code]

4) Current amount of gold calculated as 0. (removed and deindent)

[code]

  File "game/init.rpy", line 1928, inside get_current_gold_amount.

[/code]

    # if the behavior of this function is to calculate the total amount of gold, then line "gold_qty = item_dict.get("quantity", 0)" has to be replaced with "gold_qty += item_dict.get("quantity", 0)". Useful for Vending Machine room, the Cubi room and any other gold-centered mechanic inside the Dungeon.

5) Check of item in Yuki's inventory always returning False. (changed)

[code]

  File "game/init.rpy", line 1940, inside yuki_has_item:

        if not isinstance(store.persistent.player_inventory, list):

[/code]

6) Passive Equipment Effects not been applied. (changed)

[code]

  File "game/init.rpy", line 2673, inside process_passive_equipment_effects:

        if not isinstance(store.persistent.player_inventory, list): return []

[/code]

7) Inventory items not been displayed/selectable in the Barter Peddler room menu (offer item to trade with the peddler) and the Hungry Idol room menu (offer item to please the idol). (changed based on the code for the select_potion_for_throw_screen screen)

[code]

  File "game/screens.rpy", lines 4016-4049, inside offer_item_generic:

            python:

                # Create a new list of indices of items to display based on the filter

                _items_to_display_indices = []

                for i, item_dict in enumerate(store.persistent.player_inventory):

                    if item_type_filter:

                        _item_id_check = item_dict.get("id")

                        _item_data_check = store.item_definitions.get(_item_id_check, {})

                        if _item_data_check.get("type") == item_type_filter:

                            _items_to_display_indices.append(i) # Store single value as the original_index

                    else:

                        _items_to_display_indices.append(i) # No filter, show all items

            

            if not _items_to_display_indices:

            ...

                        # Loop through the filtered list

                        for original_index in _items_to_display_indices: # Iterate using the filtered indices

                            python:

                                # Fetch item details using index 'original_index' from original persistent.player_inventory

                                item_dict_offer = store.persistent.player_inventory[original_index]

                                _item_id_offer = item_dict_offer.get("id")

[/code]

;)