static void DoDamageCharacter( const Vec2i hitVector, const int power, const int flags, const int playerUID, const int uid, TActor *actor, const special_damage_e special) { // Create events: hit, damage, score CASSERT(actor->isInUse, "Cannot damage nonexistent player"); CASSERT(CanHitCharacter(flags, uid, actor), "damaging undamageable actor"); if (ConfigGetBool(&gConfig, "Game.ShotsPushback")) { GameEvent ei = GameEventNew(GAME_EVENT_ACTOR_IMPULSE); ei.u.ActorImpulse.UID = actor->uid; ei.u.ActorImpulse.Vel = Vec2i2Net(Vec2iScaleDiv( Vec2iScale(hitVector, power), SHOT_IMPULSE_DIVISOR)); ei.u.ActorImpulse.Pos = Vec2i2Net(actor->Pos); GameEventsEnqueue(&gGameEvents, ei); } const bool canDamage = CanDamageCharacter(flags, playerUID, uid, actor, special); GameEvent e = GameEventNew(GAME_EVENT_ACTOR_HIT); e.u.ActorHit.UID = actor->uid; e.u.ActorHit.PlayerUID = actor->PlayerUID; e.u.ActorHit.HitterPlayerUID = playerUID; e.u.ActorHit.Special = special; e.u.ActorHit.Power = canDamage ? power : 0; e.u.ActorHit.Vel = Vec2i2Net(hitVector); GameEventsEnqueue(&gGameEvents, e); if (canDamage) { // Don't score for friendly or player hits const bool isFriendly = (actor->flags & FLAGS_GOOD_GUY) || (!IsPVP(gCampaign.Entry.Mode) && actor->PlayerUID >= 0); if (playerUID >= 0 && power != 0 && !isFriendly) { // Calculate score based on // if they hit a penalty character e = GameEventNew(GAME_EVENT_SCORE); e.u.Score.PlayerUID = playerUID; if (actor->flags & FLAGS_PENALTY) { e.u.Score.Score = PENALTY_MULTIPLIER * power; } else { e.u.Score.Score = power; } GameEventsEnqueue(&gGameEvents, e); } } }
static bool DoDamageCharacter( const Vec2i pos, const Vec2i hitVector, const int power, const int flags, const int player, const int uid, const TTileItem *target, const special_damage_e special, const HitSounds *hitSounds, const bool allowFriendlyHitSound) { // Create events: hit, damage, score TActor *actor = CArrayGet(&gActors, target->id); CASSERT(actor->isInUse, "Cannot damage nonexistent player"); bool canHit = CanHitCharacter(flags, uid, actor); if (canHit) { GameEvent e; e.Type = GAME_EVENT_HIT_CHARACTER; e.u.HitCharacter.TargetId = actor->tileItem.id; e.u.HitCharacter.Special = special; GameEventsEnqueue(&gGameEvents, e); if (gConfig.Sound.Hits && hitSounds != NULL && !ActorIsImmune(actor, special) && (allowFriendlyHitSound || !ActorIsInvulnerable( actor, flags, player, gCampaign.Entry.Mode))) { GameEvent es; es.Type = GAME_EVENT_SOUND_AT; es.u.SoundAt.Sound = hitSounds->Flesh; es.u.SoundAt.Pos = pos; GameEventsEnqueue(&gGameEvents, es); } if (gConfig.Game.ShotsPushback) { GameEvent ei; ei.Type = GAME_EVENT_ACTOR_IMPULSE; ei.u.ActorImpulse.Id = actor->tileItem.id; ei.u.ActorImpulse.Vel = Vec2iScaleDiv( Vec2iScale(hitVector, power), SHOT_IMPULSE_DIVISOR); GameEventsEnqueue(&gGameEvents, ei); } if (CanDamageCharacter(flags, player, uid, actor, special)) { GameEvent e1; e1.Type = GAME_EVENT_DAMAGE_CHARACTER; e1.u.DamageCharacter.Power = power; e1.u.DamageCharacter.PlayerIndex = player; e1.u.DamageCharacter.TargetId = actor->tileItem.id; e1.u.DamageCharacter.TargetPlayerIndex = -1; if (actor->pData) { e1.u.DamageCharacter.TargetPlayerIndex = actor->pData->playerIndex; } GameEventsEnqueue(&gGameEvents, e1); if (gConfig.Game.Gore != GORE_NONE) { GameEvent eb; memset(&eb, 0, sizeof eb); eb.Type = GAME_EVENT_ADD_PARTICLE; eb.u.AddParticle.FullPos = Vec2iReal2Full(pos); eb.u.AddParticle.Z = 10 * Z_FACTOR; int bloodPower = power * 2; int bloodSize = 1; while (bloodPower > 0) { switch (bloodSize) { case 1: eb.u.AddParticle.Class = StrParticleClass(&gParticleClasses, "blood1"); break; case 2: eb.u.AddParticle.Class = StrParticleClass(&gParticleClasses, "blood2"); break; default: eb.u.AddParticle.Class = StrParticleClass(&gParticleClasses, "blood3"); break; } bloodSize++; if (bloodSize > 3) { bloodSize = 1; } if (gConfig.Game.ShotsPushback) { eb.u.AddParticle.Vel = Vec2iScaleDiv( Vec2iScale(hitVector, (rand() % 8 + 8) * power), 15 * SHOT_IMPULSE_DIVISOR); } else { eb.u.AddParticle.Vel = Vec2iScaleDiv( Vec2iScale(hitVector, rand() % 8 + 8), 20); } eb.u.AddParticle.Vel.x += (rand() % 128) - 64; eb.u.AddParticle.Vel.y += (rand() % 128) - 64; eb.u.AddParticle.Angle = RAND_DOUBLE(0, PI * 2); eb.u.AddParticle.DZ = (rand() % 6) + 6; eb.u.AddParticle.Spin = RAND_DOUBLE(-0.1, 0.1); GameEventsEnqueue(&gGameEvents, eb); switch (gConfig.Game.Gore) { case GORE_LOW: bloodPower /= 8; break; case GORE_MEDIUM: bloodPower /= 2; break; default: bloodPower = bloodPower * 7 / 8; break; } } } if (player >= 0 && power != 0) { // Calculate score based on // if they hit a penalty character GameEvent e2; e2.Type = GAME_EVENT_SCORE; e2.u.Score.PlayerIndex = player; if (actor->flags & FLAGS_PENALTY) { e2.u.Score.Score = PENALTY_MULTIPLIER * power; } else { e2.u.Score.Score = power; } GameEventsEnqueue(&gGameEvents, e2); } } } return canHit; }