Code questions. Renpy crash with TypeError: 'NoneType' object and strange button code behaviour

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
Alem
Regular
Posts: 38
Joined: Wed Mar 15, 2017 7:53 am
Contact:

Code questions. Renpy crash with TypeError: 'NoneType' object and strange button code behaviour

#1 Post by Alem »

Greetings! I'm tinkering around VN/Management hybrid idea with some group-based combat based on this tutorial. So far the prototype progresses nicely with few exceptions, which I hoped to clear up with community's help. I don't think posting all the code here is wise - it'll be a huge blob of text, so here's Renpy project folder for details.

1) I prepared a method for combat groups to inflict damage to their opponents, you can check it out here as a proof of concept. The function works fine in the external IDE, but if I try to use it in combat screen (start the project -> begin sortie button, then engage button) Renpy crashes with TypeError: 'NoneType' object is not callable. The full log is in the attached archive. I think Python tries to work with a blank object and fails, but which one?

2)Showing screens force them to execute methods inside the button code block even if normally this would require the player to click on a button to activate these. I noticed it after including time.sleep(5) inside the deal_damage function for the fleet. The game pauses for the marked time before shoving the combat screen yet it must fire only then the button is pressed. Is there a way to forbid such behavior and execute methods on buttons only if the button is clicked?

Thank you!
Attachments
traceback.txt
(2.81 KiB) Downloaded 79 times

Alem
Regular
Posts: 38
Joined: Wed Mar 15, 2017 7:53 am
Contact:

Re: Code questions. Renpy crash with TypeError: 'NoneType' object and strange button code behaviour

#2 Post by Alem »

I guess the code may help :/

Code: Select all

init -1 python:
    import renpy.store as store
    import renpy.exports as renpy
    import random
    import time

    targets = []
    target = None
    stopbattle = 0

    class Fleet(store.object):
        def __init__(self,speed="Fast"):
            self.items = []
            self.speed = speed
        def add(self, item): # a simple method that adds an item; we could also add conditions here (like check if there is space in the inventory)
            self.items.append(item)
            
        def deal_damage(self, enemyfleet):
            targets=[]
            time.sleep(1)
            for item in enemyfleet.items:
                if item.hp > 0:
                    targets.append(item)
            if len(targets) == 0:
                stopbattle=1
            else:
                for item in self.items:
                    if item.hp > 0:
                        damage = item.damage + renpy.random.randint(0,5)
                        target = renpy.random.choice(targets)
                        target.hp = target.hp - damage
                    else:
                        stopbattle=2
The rest is omitted. The problem I have is in the deal_damage method, which is called like this as a test:

Code: Select all

screen combat_screen:
	textbutton ("Engage") action Function(fleet.deal_damage(enemyfleet)) xpos .430 ypos .85
The sleep timer fires off at the moment I enter the screen and clicking on the engage button crashes with Renpy TypeError: 'NoneType' object is not callable. Am I using the code in wrong way, any thoughts?

User avatar
Remix
Eileen-Class Veteran
Posts: 1628
Joined: Tue May 30, 2017 6:10 am
Completed: None... yet (as I'm still looking for an artist)
Projects: An un-named anime based trainer game
Contact:

Re: Code questions. Renpy crash with TypeError: 'NoneType' object and strange button code behaviour

#3 Post by Remix »

Function() is actually an interpolated call so it needs parameters rather than a stringlike call

Function( fleet.deal_damage, enemyfleet )
Frameworks & Scriptlets:

Alem
Regular
Posts: 38
Joined: Wed Mar 15, 2017 7:53 am
Contact:

Re: Code questions. Renpy crash with TypeError: 'NoneType' object and strange button code behaviour

#4 Post by Alem »

Thanks, Remix. Worked like a charm after your fix. Strangely enough, another screen used the same incorrect input for Function() with parenthesis and gave the results regardless.

User avatar
Remix
Eileen-Class Veteran
Posts: 1628
Joined: Tue May 30, 2017 6:10 am
Completed: None... yet (as I'm still looking for an artist)
Projects: An un-named anime based trainer game
Contact:

Re: Code questions. Renpy crash with TypeError: 'NoneType' object and strange button code behaviour

#5 Post by Remix »

Your 'fleet.deal_damage' function has no return, so basically returns None...
When Ren'py does Function(fleet.deal_damage(arg)) it calls that first parameter (which is effectively the return value of the function), so effectively tries to call type(None).__call__() hence the error "TypeError: 'NoneType' object is not callable"
If a function returned something, a string, a dict, an object, the Function call would then try to call that, so could work

val = 0
def a(): val += 1
def b(): return a
Function(b()) ...
val -> 1

Something like that anyway
Frameworks & Scriptlets:

Alem
Regular
Posts: 38
Joined: Wed Mar 15, 2017 7:53 am
Contact:

Re: Code questions. Renpy crash with TypeError: 'NoneType' object and strange button code behaviour

#6 Post by Alem »

Remix wrote: Fri Aug 18, 2017 4:41 pm Your 'fleet.deal_damage' function has no return, so basically returns None...
When Ren'py does Function(fleet.deal_damage(arg)) it calls that first parameter (which is effectively the return value of the function), so effectively tries to call type(None).__call__() hence the error "TypeError: 'NoneType' object is not callable"
If a function returned something, a string, a dict, an object, the Function call would then try to call that, so could work

val = 0
def a(): val += 1
def b(): return a
Function(b()) ...
val -> 1

Something like that anyway
Oh, now I get it. Yeah, you are right, the other function used inventory slots to swap between two lists and returned the result. With damage method, I wanted to troubleshoot it step by step until I stumbled on this problem. Ironically, I needed to go ahead and finish it before any real testing.

Thanks again!

Post Reply

Who is online

Users browsing this forum: Kocker