Advice about collisions.

I have a sword like mesh object parented to an bone of an armature.
At the moment I have the sword set up with a property (‘attack’). All characters will die on collision with this property.

The problem is, I only want the enemies to die when the armature connected to the sword is playing a stabbing or slashing action.

Technically all the game’s characters are (currently) the same and are generated from a class, so this may require a different solution to the norm. I could have probably set up message actuators targeting the specific object if this weren’t the case.

There is probably a few ways to do this.
Is there is a way to enable or disable (delete or add?) the ‘attack’ property at a current frame of animation? This way when the collision happens without the action nothing should happen with the property disabled.

Maybe there is a way of grabbing the colliding object and getting the parent (armature) frame of the current action.

Any advice with regards to approach would be awesome, thanks.

As far as I understand the sword needs to have “attack” to do damage.

You can do this:

You know when the action starts (as you start them). -> So you can add the “attack” property at that time.
You can evaluate when the action ends (e.g. via ActuatorSensor, or property or whatever). -> So you can remove the “attack” property then this happens.

Thanks Monster.

How do I add and remove properties with python? (bge)

objectToAddPropertyTo["propertyName"] = propertyValue

del objectToDeletePropertyFrom["propertyName"]

Thanks Monster!

Unfortunatley I’m getting an error message:

KeyError: ‘gameOb[key] = value: KX_GameObject, key “attack” could not be set’

Do you know why this is?

This is strange. I never saw this error message.

Can you post your code or a blend?

The code is much bigger, but hopefully I’ve extracted the right parts.
I’ve left out stuff about keyboard keys and the usual; cont, scene, own etc

class player_character():
    def __init__(self,spawnLocation):
        own['skel'] = scenes[0].addObject("SidSkel",spawnLocation)
        self.skelly = own['skel']
        self.swordEquiped = scenes[0].addObject("SwordEquiped",self.skelly.children[16])
        self.swordCol = self.swordEquiped.children[0]
    def actionPlay(self,action_name,start_frame,end_frame,layer,priority):
        blendin = 4
        mode = 0
        layerWeight = 0.0
        ipoFlags = 1
        speed = 1.0
        self.skelly.playAction(action_name, start_frame, end_frame, layer, priority, blendin, mode, layerWeight, ipoFlags, speed)
    def attack(self):
        if self.skelly.getActionFrame(2) > 0:
            self.swordCol['attack'] = True
            del self.swordCol['attack']
        if self.attackKey:
            self.swordCol['attack'] = True
        if self.backKey and self.attackKey:

def char_update_sid():
    global sid
    #if sid.exists:

I found it. This pretty misleading error message (BGE code) means … the property could not be deleted.

I can reproduce that by deleting an property that does not exist.

There is a second error message. I think that is the one we expect to see:

"del gameOb[key]: KX_GameObject, key could not be deleted"

I guess the condition when to show what error is not correct in this situation.

Thanks Monster. In the end I was able to get this working by organising my loop in my attack() function and using the try and except clause. There is probably better ways to do this, but it’s working at the moment and I am happy. Thanks a bunch for your help!

def attack(self):
    if self.skelly.getActionFrame(2) > 0:
        self.swordCol['attack'] = True
            del self.swordCol['attack']
    if self.attackKey:
    if self.backKey and self.attackKey:

I really recommend you specify the errors you are expecting. Otherwise you hide unexpected errors. And that can result im problems you never want to investigate.

There are not that many situations, when an unspecified except is a good idea.

Beside of that, I think this solution cures the symptom, not the cause. While it temporarily works, I suggest to think about, why the property does not exist. I mean, you expect it should but it does not. So there is something incorrect in the situation.

Better investigate now and be sure the solution has no sideeffects, than to get trouble when sour code is much more later.

I updated my code removing the try and except clause.

Instead I have nested an if statement. Thanks a lot Monster!

def attack(self):
    if self.skelly.getActionFrame(2) > 0:
        self.swordCol['attack'] = True
        if self.skelly.getActionFrame(2) == 0 or self.skelly.getActionFrame(2) > 20:
            del self.swordCol['attack']
    if self.attackKey: