public float GetDamageModifier(Actor attacker, WarheadInfo warhead) { return(Level > 0 ? 1 / info.ArmorModifier[Level - 1] : 1); }
public static void DoImpact(WarheadInfo warhead, ProjectileArgs args) { var world = args.firedBy.World; var targetTile = args.dest.ToCPos(); if (!world.Map.IsInMap(targetTile)) { return; } var isWater = args.destAltitude == 0 && world.GetTerrainInfo(targetTile).IsWater; var explosionType = isWater ? warhead.WaterExplosion : warhead.Explosion; if (explosionType != null) { world.AddFrameEndTask( w => w.Add(new Explosion(w, args.dest, explosionType, isWater, args.destAltitude))); } Sound.Play(GetImpactSound(warhead, isWater), args.dest); var smudgeLayers = world.WorldActor.TraitsImplementing <SmudgeLayer>().ToDictionary(x => x.Info.Type); if (warhead.Size[0] > 0) { var resLayer = world.WorldActor.Trait <ResourceLayer>(); var allCells = world.FindTilesInCircle(targetTile, warhead.Size[0]).ToList(); // `smudgeCells` might want to just be an outer shell of the cells: IEnumerable <CPos> smudgeCells = allCells; if (warhead.Size.Length == 2) { smudgeCells = smudgeCells.Except(world.FindTilesInCircle(targetTile, warhead.Size[1])); } // Draw the smudges: foreach (var sc in smudgeCells) { var smudgeType = world.GetTerrainInfo(sc).AcceptsSmudgeType.FirstOrDefault(t => warhead.SmudgeType.Contains(t)); if (smudgeType == null) { continue; } SmudgeLayer smudgeLayer; if (!smudgeLayers.TryGetValue(smudgeType, out smudgeLayer)) { throw new NotImplementedException("Unknown smudge type `{0}`".F(smudgeType)); } smudgeLayer.AddSmudge(sc); if (warhead.Ore) { resLayer.Destroy(sc); } } // Destroy all resources in range, not just the outer shell: foreach (var cell in allCells) { if (warhead.Ore) { resLayer.Destroy(cell); } } } else { var smudgeType = world.GetTerrainInfo(targetTile).AcceptsSmudgeType.FirstOrDefault(t => warhead.SmudgeType.Contains(t)); if (smudgeType != null) { SmudgeLayer smudgeLayer; if (!smudgeLayers.TryGetValue(smudgeType, out smudgeLayer)) { throw new NotImplementedException("Unknown smudge type `{0}`".F(smudgeType)); } smudgeLayer.AddSmudge(targetTile); } } if (warhead.Ore) { world.WorldActor.Trait <ResourceLayer>().Destroy(targetTile); } switch (warhead.DamageModel) { case DamageModel.Normal: { var maxSpread = warhead.Spread * (float)Math.Log(Math.Abs(warhead.Damage), 2); var hitActors = world.FindUnitsInCircle(args.dest, (int)maxSpread); foreach (var victim in hitActors) { var damage = (int)GetDamageToInflict(victim, args, warhead, args.firepowerModifier); victim.InflictDamage(args.firedBy, damage, warhead); } } break; case DamageModel.PerCell: { foreach (var t in world.FindTilesInCircle(targetTile, warhead.Size[0])) { foreach (var unit in world.FindUnits(t.ToPPos(), (t + new CVec(1, 1)).ToPPos())) { unit.InflictDamage(args.firedBy, (int)(warhead.Damage * warhead.EffectivenessAgainst(unit)), warhead); } } } break; } }
public float GetDamageModifier(Actor attacker, WarheadInfo warhead) { return((RemainingTicks > 0) ? 0.0f : 1.0f); }
public static void DoImpact(WPos pos, WarheadInfo warhead, WeaponInfo weapon, Actor firedBy, float firepowerModifier) { var world = firedBy.World; var targetTile = pos.ToCPos(); if (!world.Map.IsInMap(targetTile)) { return; } var isWater = pos.Z <= 0 && world.GetTerrainInfo(targetTile).IsWater; var explosionType = isWater ? warhead.WaterExplosion : warhead.Explosion; var explosionTypePalette = isWater ? warhead.WaterExplosionPalette : warhead.ExplosionPalette; if (explosionType != null) { world.AddFrameEndTask(w => w.Add(new Explosion(w, pos, explosionType, explosionTypePalette))); } Sound.Play(GetImpactSound(warhead, isWater), pos); var smudgeLayers = world.WorldActor.TraitsImplementing <SmudgeLayer>().ToDictionary(x => x.Info.Type); if (warhead.Size[0] > 0) { var resLayer = world.WorldActor.Trait <ResourceLayer>(); var allCells = world.FindTilesInCircle(targetTile, warhead.Size[0]).ToList(); // `smudgeCells` might want to just be an outer shell of the cells: IEnumerable <CPos> smudgeCells = allCells; if (warhead.Size.Length == 2) { smudgeCells = smudgeCells.Except(world.FindTilesInCircle(targetTile, warhead.Size[1])); } // Draw the smudges: foreach (var sc in smudgeCells) { var smudgeType = world.GetTerrainInfo(sc).AcceptsSmudgeType.FirstOrDefault(t => warhead.SmudgeType.Contains(t)); if (smudgeType == null) { continue; } SmudgeLayer smudgeLayer; if (!smudgeLayers.TryGetValue(smudgeType, out smudgeLayer)) { throw new NotImplementedException("Unknown smudge type `{0}`".F(smudgeType)); } smudgeLayer.AddSmudge(sc); if (warhead.Ore) { resLayer.Destroy(sc); } } // Destroy all resources in range, not just the outer shell: foreach (var cell in allCells) { if (warhead.Ore) { resLayer.Destroy(cell); } } } else { var smudgeType = world.GetTerrainInfo(targetTile).AcceptsSmudgeType.FirstOrDefault(t => warhead.SmudgeType.Contains(t)); if (smudgeType != null) { SmudgeLayer smudgeLayer; if (!smudgeLayers.TryGetValue(smudgeType, out smudgeLayer)) { throw new NotImplementedException("Unknown smudge type `{0}`".F(smudgeType)); } smudgeLayer.AddSmudge(targetTile); } } if (warhead.Ore) { world.WorldActor.Trait <ResourceLayer>().Destroy(targetTile); } switch (warhead.DamageModel) { case DamageModel.Normal: { var maxSpread = new WRange((int)(warhead.Spread.Range * (float)Math.Log(Math.Abs(warhead.Damage), 2))); var hitActors = world.FindActorsInCircle(pos, maxSpread); foreach (var victim in hitActors) { var damage = (int)GetDamageToInflict(pos, victim, warhead, weapon, firepowerModifier, true); victim.InflictDamage(firedBy, damage, warhead); } } break; case DamageModel.PerCell: { foreach (var t in world.FindTilesInCircle(targetTile, warhead.Size[0])) { foreach (var unit in world.ActorMap.GetUnitsAt(t)) { var damage = (int)GetDamageToInflict(pos, unit, warhead, weapon, firepowerModifier, false); unit.InflictDamage(firedBy, damage, warhead); } } } break; case DamageModel.HealthPercentage: { var range = new WRange(warhead.Size[0] * 1024); var hitActors = world.FindActorsInCircle(pos, range); foreach (var victim in hitActors) { var damage = GetDamageToInflict(pos, victim, warhead, weapon, firepowerModifier, false); if (damage != 0) // will be 0 if the target doesn't have HealthInfo { var healthInfo = victim.Info.Traits.Get <HealthInfo>(); damage = (float)(damage / 100 * healthInfo.HP); } victim.InflictDamage(firedBy, (int)damage, warhead); } } break; } }
public float GetDamageModifier(Actor attacker, WarheadInfo warhead) { return(0.0f); }
public float GetDamageModifier(Actor attacker, WarheadInfo warhead) { return(IsProne && warhead != null ? warhead.ProneModifier / 100f : 1f); }
public static void InflictDamage(this Actor self, Actor attacker, int damage, WarheadInfo warhead) { if (self.Destroyed) { return; } var health = self.TraitOrDefault <Health>(); if (health == null) { return; } health.InflictDamage(self, attacker, damage, warhead, false); }
public static void DoImpact(WarheadInfo warhead, ProjectileArgs args) { var world = args.firedBy.World; var targetTile = Util.CellContaining(args.dest); if (!world.Map.IsInMap(targetTile)) { return; } var isWater = args.destAltitude == 0 && world.GetTerrainInfo(targetTile).IsWater; var explosionType = isWater ? warhead.WaterExplosion : warhead.Explosion; if (explosionType != null) { world.AddFrameEndTask( w => w.Add(new Explosion(w, args.dest, explosionType, isWater, args.destAltitude))); } Sound.Play(GetImpactSound(warhead, isWater), args.dest); if (warhead.SmudgeType != null) { var smudgeLayer = world.WorldActor.TraitsImplementing <SmudgeLayer>() .FirstOrDefault(x => x.Info.Type == warhead.SmudgeType); if (smudgeLayer == null) { throw new NotImplementedException("Unknown smudge type `{0}`".F(warhead.SmudgeType)); } if (warhead.Size[0] > 0) { var smudgeCells = world.FindTilesInCircle(targetTile, warhead.Size[0]); if (warhead.Size.Length == 2) { smudgeCells = smudgeCells.Except(world.FindTilesInCircle(targetTile, warhead.Size[1])); } foreach (var sc in smudgeCells) { smudgeLayer.AddSmudge(sc); if (warhead.Ore) { world.WorldActor.Trait <ResourceLayer>().Destroy(sc); } } } else { smudgeLayer.AddSmudge(targetTile); } } if (warhead.Ore) { world.WorldActor.Trait <ResourceLayer>().Destroy(targetTile); } switch (warhead.DamageModel) { case DamageModel.Normal: { var maxSpread = warhead.Spread * (float)Math.Log(Math.Abs(warhead.Damage), 2); var hitActors = world.FindUnitsInCircle(args.dest, (int)maxSpread); foreach (var victim in hitActors) { var damage = (int)GetDamageToInflict(victim, args, warhead, args.firepowerModifier); victim.InflictDamage(args.firedBy, damage, warhead); } } break; case DamageModel.PerCell: { foreach (var t in world.FindTilesInCircle(targetTile, warhead.Size[0])) { foreach (var unit in world.FindUnits(Game.CellSize * t, Game.CellSize * (t + new int2(1, 1)))) { unit.InflictDamage(args.firedBy, (int)(warhead.Damage * warhead.EffectivenessAgainst(unit)), warhead); } } } break; } }
public void InflictDamage(Actor self, Actor attacker, int damage, WarheadInfo warhead, bool ignoreModifiers) { if (IsDead) { return; /* overkill! don't count extra hits as more kills! */ } var oldState = this.DamageState; /* apply the damage modifiers, if we have any. */ var modifier = self.TraitsImplementing <IDamageModifier>() .Concat(self.Owner.PlayerActor.TraitsImplementing <IDamageModifier>()) .Select(t => t.GetDamageModifier(attacker, warhead)).Product(); if (!ignoreModifiers) { damage = damage > 0 ? (int)(damage * modifier) : damage; } hp = Exts.Clamp(hp - damage, 0, MaxHP); var ai = new AttackInfo { Attacker = attacker, Damage = damage, DamageState = this.DamageState, PreviousDamageState = oldState, Warhead = warhead, }; foreach (var nd in self.TraitsImplementing <INotifyDamage>() .Concat(self.Owner.PlayerActor.TraitsImplementing <INotifyDamage>())) { nd.Damaged(self, ai); } if (DamageState != oldState) { foreach (var nd in self.TraitsImplementing <INotifyDamageStateChanged>()) { nd.DamageStateChanged(self, ai); } } if (attacker != null && attacker.IsInWorld && !attacker.IsDead()) { foreach (var nd in attacker.TraitsImplementing <INotifyAppliedDamage>() .Concat(attacker.Owner.PlayerActor.TraitsImplementing <INotifyAppliedDamage>())) { nd.AppliedDamage(attacker, self, ai); } } if (hp == 0) { attacker.Owner.Kills++; self.Owner.Deaths++; foreach (var nd in self.TraitsImplementing <INotifyKilled>() .Concat(self.Owner.PlayerActor.TraitsImplementing <INotifyKilled>())) { nd.Killed(self, ai); } if (RemoveOnDeath) { self.Destroy(); } Log.Write("debug", "{0} #{1} killed by {2} #{3}", self.Info.Name, self.ActorID, attacker.Info.Name, attacker.ActorID); } }
public float GetDamageModifier(Actor attacker, WarheadInfo warhead) { return(Invulnerable ? 0.0f : 1.0f); }
public float GetDamageModifier(Actor attacker, WarheadInfo warhead) { return(State == PopupState.Closed ? Info.ClosedDamageMultiplier : 1f); }
public float GetDamageModifier(Actor attacker, WarheadInfo warhead) { return(IsProne ? Info.ProneDamage : 1f); }
public float GetDamageModifier(Actor attacker, WarheadInfo warhead) { return(ArmorLevel > 0 ? (1 / (1 + ArmorLevel * info.ArmorModifier)) : 1); }