python sum specific property on a list of objects


import bge




def main():


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


    sensDamage = cont.sensors['CollisionDamage']
    actuHit = cont.actuators['Hit']


    if sensDamage.positive:
        actuHit.value = sensDamage.hitObject['Damager']
        cont.activate(actuHit)
    else:
        cont.deactivate(actuHit)


main()

this is used to calculate the damage done to a character in the game.

The problem is it only counts 1 object that is hit.

How do I get the property “Damager” from the list of objects, the sum them
Also, because the property actuator uses strings the properties are strings too

I tried this but it doesn’t work:


import bge




def main():


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


    sensDamage = cont.sensors['CollisionDamage']


    if sensDamage.positive:
        total = 0
        n = 0
        for sensDamageList[n] != []:
            total = total + sensDamage.hitObjectList[n]['Damager']
            n = n + 1
        own["Health"] = own["Health"] + total


main()


Any help would be great!

Your second list is close, but you have garbled some stuff. If you check the console in game (go window-> toggle system console if on Windows, or start from terminal if on mac/linux) you should see some error messages.So let’s walk through what you’ve said:

First you import bge, define a function, get the controller and owner, get the sensor.
All well and good.

But then you try this:

 for sensDamageList[n] != []:

I can count several things wrong with that line:

  • undefined variable sensDamageList
  • Comparing an element of a list with an empty list (not illegal, but not what you want)
  • using a for loop with a boolean value (because sensDamageList[n] != [] will return False, so you are saying “for False:”

What you actually want is to create a list of objects that you’ve hit, and iterate through those.

Here’s a script that shows how it should look (because I’ve just got too lazy to type an explanation)

import bge

def main():
    cont = bge.logic.getCurrentController()
    own = cont.owner
    sensDamage = cont.sensors['CollisionDamage']

    if sensDamage.positive:
       total = 0
        sensDamageList = sensDamage.hitObjectList #Gets a list of all colliding objects
        for obj in sensDamageList: #Does the following code with each object in hitObjectList                 
           total += obj['Damager' #Sums the list
       own["Health"] = own["Health"] + total

main()

...
objectsWithPropertyDamager = findObjectsWithProperty("Damager", sensDamage.hitObjectList) # plural!
...

def findObjectsWithProperty(propertyName, objects):
   return [object for object in objects 
          if propertyName in object ]


totalDamage = sumProperty("Damager", objectsWithPropertyDamager)
...
def sumProperty(propertyName, objects):
   sum = 0
   for object in objects:
      sum += object[propertyName]
   return sum

Why are you using strings? That makes not much sense on mathematical operations, doesn’t it?
Change them to float or integers.

Indeed you can search and sum at in one step, but this is not what you asked for ;).

@Monster

A simple list comprehension can be used to extract relevant properties from the objects that have them, and Python already provides a built-in sum function.

So, this can be as simple as:


hit = sensDamage.hitObjectList

damage = sum( [o["Damager"] for o in hit if "Damager" in  o] )

Use the power that’s already there. :wink:

I was using strings because the property actuator requires them

It works properly now! thanks for the help everyone. The gameplay is pretty much done with this bug out of the way.