What's wrong with my script?

Hi! My script isn’t working for some reason so I wanted to ask what’s wrong. Here is the script:

import bge
from bge import logic


cont = logic.getCurrentController()
own = cont.owner


sens = cont.sensors
act = cont.actuators


def cell1():
    
    9mm = sens["col9mm"]
    mo = sens["mo"]
    mlb = sens["lclick"]
    
    item = own["item"]
    count = own["count"]
    
    if count < 1:
        item = 0
        
    if 9mm.positive:
        item = 1
        count +=15
    

I made it for inventory. It tests for message sensor to be true and if it is, it adds 15 of that item to the cell aswell as sets the item type of cell to 1, but it doesn’t work for me…

You’re probably trying to run this on multiple objects, in which case the sensors and actuators will not correspond to the current object running the script, as they’re bound to the module.

It’s also important to understand how python manages data. Many primitive types (int, str, tuple, float) are immutable, meaning that once defined, they cannot be changed. This also means that any time you create a reference to these objects, it’s a reference to the value. Given that the value is immutable - i.e it cannot be changed, any later modifications to a variable for immutable types simply updates the reference in question to point to a new value.

Tl;dr - your item and count variables are being updated to hold the new values, rather than the properties on the object. You need to re-assign the values on the objects.

Oh… So I must put own[“item”] = item?
Still not resolvement. Maybe I will post .blend later?

So, here’s my .blend:
http://www.pasteall.org/blend/34618

Please, help me correcting mistakes- what it should do is:
-Make the ammo icon invisible while the slot is empty.
-Make the number 15(count of bullets) appear in the cell when player collects ammo(touches it and presses SPACE).
-Make the ammo icon visible when player collects ammo.
-Make the ammo disappear only if the ammo gets collected(only if there is a free place in the cell).

This is wrong:

Never ever cache that data at module level. Always grep it from the current context (bge.logic).

this would be better:

import bge
from bge import logic

def cell1():
    cont = logic.getCurrentController() # grep from current context
    own = cont.owner
    sens = cont.sensors
    
    9mm = sens["col9mm"]
    
    item = own["item"]
    count = own["count"]
    
    if count < 1:
        item = 0
        
    if 9mm.positive:
        item = 1
        count +=15
    

(removed unused variables)

Additionally you forgot to write the new values to the properties


    own["item"] = item
    own["count "] = count 

Still doesn’t work. Could you take a look at the .blend and see what can you change?

Monster’s amended script is not a final one - it doesn’t include the change he mentions, as I did, afterwards.

It’s quite a simple problem - you’re changing the values of item and count, but they do not apply their changes to the object properties you took them from - they’re separate (because once you change the value of the variable, it’s a new value. You need to add those lines at the end of the script.

You file is not simple enough to demonstrate what you want (if it takes > 5 minutes to find all the related objects etc. You should first try making the recommended changes, and if that doesn’t help, create a simpler blend file. But, the print function is your friend - use it to work out what the script is doing. You can solve this yourself, even if it doesn’t seem such.

I don’t have console in linux. Anyway, I changed it even adding theese 2 lines, but nothing works…

You do have console in linux, just not the button.

Start blender from a terminal using the command ‘blender’ or if it is just installed in a folder ‘/path/to/blender’

The Message actuator which is sending the ‘9mm’ message is not sending it to anybody (the To: field is blank). Who are you trying to send this message to? :wink:

I think what you’re trying to do is this:

-Get the game property and assign it to a variable:
prop = own[‘prop’]

-Do Stuff to the variable:
if x.positive: prop = 15

-Get the variable and assign it back to the game property:
own[‘prop’] = prop

Or in other words:
if x.positive: own[‘prop’] = 15

This does exactly the same thing, but cuts out the ‘middle man’ as it were. The middle man can be handy, but isn’t needed here I don’t think.

I am guessing that ‘item’ is working like a booleen deciding whether or not you have the item?
And ‘count’ equals the number of that item you have in your stack. For this script, we assume that picking up a clip sets you to x no. of items regardless of how many you had before.


from bge import logic

def pickup():
    cont = logic.getCurrentController()
    own = cont.owner

    incoming = cont.sensors['Message']

    if incoming.positive and own['item'] == 0:
        for sub in incoming.subjects:
            if sub == '9mm':
                own['item'] = 1
                own['count'] = int(sub.bodies[0])

Not tested, and probably wont work if you just copy/paste.
I change the name from ‘cell1()’ since that made no sense to me (I like my methods to say what they mean :wink: ) What this does is listen for messages with any subject, so we can pick up ‘.308’, or ‘chainsaw fuel’, or ‘cupcake’ all with the same script, just by sending it messages with the corresponding item name as the subject. The number of items aquired is found in the body of the message, to increase flexibility, and to illustrate exactly how that particular trick is done. Just leave the subject field of your message sensor blank and it will trigger to any message sent to it.

This means this message is send to anybody interested in this message.

-> Avoid to use the “to” field. It creates a strong relationship to the other object, you can’t debug the message flow, you need to know the recipient, and it must be exactly one recipient. If all this requirements are met … you can directly change a property at the other object.

You learn something new every day. I stand corrected, sir.

‘item’ shows the ID of the item in exact cell. ID 1 means so it is 9mm ammo, ID 0 means so it is empty, but ID 2 means so it is handgun(there are gone be more items too).

You cannot start a variable name with a number.

I already corrected it, but it still doesn’t help…


import bge
from bge import logic


def cell1():
    cont = logic.getCurrentController()
    own = cont.owner
    sens = cont.sensors
    act = cont.actuators
    
    ammo9 = sens["col9mm"]
        
    if own["count"] < 1:
        own["item"] = 0
        
    if ammo9.positive:
        if own["item"] == 0 or own["item"] == 1:
            own["count"] += 15
            own["item"] = 1
            act["9mmCol"].positive

This code still doesn’t work. I can also post .blend, if you need.

What is the line “act[“9mmCol”].positive” supposed to do.

For the majority of the time in Python (ignoring descriptors), statements without parenthesis at the end do not effect state changes. Do you want to activate the actuator?

Then use


act_column_9mm= cont.actuators['9mmCol']
cont.activate(act_column_9mm)

Oh, I should use .activate()?

Actually it is working, but the problem is so when I close inventory and open again it resets, but the script isn’t running while the inventory is closed. How can I resolve this?

Sure.
Please have a look at the BGE API