def explode(self, position, force, damage, damageRadius, sourceEntity = None, damagingEntity = None): """Triggers an explosion animation, which involves applying force to surrounding Entities, and damaging Entities where applicable. sourceEntity is excluded from damage and force, and damagingEntity gets the credit for any damage done. If damagingEntity is None, sourceEntity gets the credit. If both are None, no damage is done. """ particles.add(particles.SparkParticleGroup(position, numParticles = 500, speed = damageRadius * 2.5, lifeTime = 1.0, size = 6.0)) particles.add(particles.ExplosionParticleGroup(position)) for entity in (entity for entity in self.entities.values() if entity != sourceEntity and isinstance(entity, ObjectEntity)): vector = entity.getPosition() - position distance = vector.length() if distance >= damageRadius or distance == 0: continue force2 = force * max(1 - (distance / damageRadius), 0) * entity.radius * 0.5 damage2 = damage * max(1 - (distance / damageRadius), 0) pos = entity.getPosition() vector = pos - position distance = vector.length() vector.normalize() if entity.active: vector = engine.impulseToForce(vector.getX() * force2, vector.getY() * force2, vector.getZ() * force2) pos = entity.getPosition() radius = entity.radius * 0.4 pos += Vec3(uniform(-radius, radius), uniform(-radius, radius), uniform(-radius, radius)) entity.addForceAtPosition(vector, pos) if damage2 > 0: if damagingEntity != None: entity.damage(damagingEntity, damage2, False) # Grenades don't count as ranged damage. elif sourceEntity != None: entity.damage(sourceEntity, damage2, False)
def serverUpdate(self, aiWorld, entityGroup, packetUpdate): p = Weapon.serverUpdate(self, aiWorld, entityGroup, packetUpdate) if self.firing and self.active: self.addCriticalPacket(p, packetUpdate) p.add(net.Uint8(1)) # 1 = We're starting to impale an entity enemy = aiWorld.getNearestEnemy(entityGroup, self.actor.getPosition(), self.actor.getTeam(), includeCloakedUnits=True) if enemy != None: vector = self.actor.controller.targetPos - base.camera.getPos() vector2 = enemy.getPosition() - base.camera.getPos() vector3 = enemy.getPosition() - self.actor.getPosition() vector.normalize() vector2.normalize() if math.acos(vector.getX() * vector2.getX() + vector.getY() * vector2.getY() + vector.getZ() * vector2.getZ() ) < math.pi / 5 and vector3.length() < 8: p.add(net.Boolean(True)) vector3.normalize() self.actor.addForce(engine.impulseToForce(vector3 * 1000)) self.impulseVector = vector3 self.impaleTarget = enemy else: p.add(net.Boolean(False)) else: p.add(net.Boolean(False)) self.firing = False elif self.active and self.impaleStart != -1 and self.impaleTarget != None and self.impaleTarget.active and ( self.actor.getPosition() - self.impaleTarget.getPosition() ).length() < self.actor.radius + self.impaleTarget.radius + 0.5: self.addCriticalPacket(p, packetUpdate) # At this point, the blade is actually in the target. p.add(net.Uint8(2)) # 2 = We're now actually damaging the entity p.add(net.Uint8(self.impaleTarget.getId())) # Stop the player from flying past the target. if self.impaleTarget.health > self.damage: # Only add force if we don't kill the target. If the target dies, the explosion will already push us away. self.actor.addForce( engine.impulseToForce(self.impulseVector * -800)) self.impaleTarget = None else: p.add(net.Uint8(0)) # 0 = Nothing's happening return p
def serverUpdate(self, aiWorld, entityGroup, packetUpdate): p = Weapon.serverUpdate(self, aiWorld, entityGroup, packetUpdate) if self.firing and self.active: self.addCriticalPacket(p, packetUpdate) p.add(net.Uint8(1)) # 1 = We're starting to impale an entity enemy = aiWorld.getNearestEnemy(entityGroup, self.actor.getPosition(), self.actor.getTeam(), includeCloakedUnits = True) if enemy != None: vector = self.actor.controller.targetPos - base.camera.getPos() vector2 = enemy.getPosition() - base.camera.getPos() vector3 = enemy.getPosition() - self.actor.getPosition() vector.normalize() vector2.normalize() if math.acos(vector.getX() * vector2.getX() + vector.getY() * vector2.getY() + vector.getZ() * vector2.getZ()) < math.pi / 5 and vector3.length() < 8: p.add(net.Boolean(True)) vector3.normalize() self.actor.addForce(engine.impulseToForce(vector3 * 1000)) self.impulseVector = vector3 self.impaleTarget = enemy else: p.add(net.Boolean(False)) else: p.add(net.Boolean(False)) self.firing = False elif self.active and self.impaleStart != -1 and self.impaleTarget != None and self.impaleTarget.active and (self.actor.getPosition() - self.impaleTarget.getPosition()).length() < self.actor.radius + self.impaleTarget.radius + 0.5: self.addCriticalPacket(p, packetUpdate) # At this point, the blade is actually in the target. p.add(net.Uint8(2)) # 2 = We're now actually damaging the entity p.add(net.Uint8(self.impaleTarget.getId())) # Stop the player from flying past the target. if self.impaleTarget.health > self.damage: # Only add force if we don't kill the target. If the target dies, the explosion will already push us away. self.actor.addForce(engine.impulseToForce(self.impulseVector * -800)) self.impaleTarget = None else: p.add(net.Uint8(0)) # 0 = Nothing's happening return p