示例#1
0
 public float GetDamageModifier(Actor attacker, WarheadInfo warhead)
 {
     return(Level > 0 ? 1 / info.ArmorModifier[Level - 1] : 1);
 }
示例#2
0
        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;
            }
        }
示例#3
0
 public float GetDamageModifier(Actor attacker, WarheadInfo warhead)
 {
     return((RemainingTicks > 0) ? 0.0f : 1.0f);
 }
示例#4
0
        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;
            }
        }
示例#5
0
 public float GetDamageModifier(Actor attacker, WarheadInfo warhead)
 {
     return(0.0f);
 }
示例#6
0
 public float GetDamageModifier(Actor attacker, WarheadInfo warhead)
 {
     return(IsProne && warhead != null ? warhead.ProneModifier / 100f : 1f);
 }
示例#7
0
        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);
        }
示例#8
0
文件: Combat.cs 项目: test71/OpenRA
        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;
            }
        }
示例#9
0
        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);
            }
        }
示例#10
0
 public float GetDamageModifier(Actor attacker, WarheadInfo warhead)
 {
     return(Invulnerable ? 0.0f : 1.0f);
 }
示例#11
0
 public float GetDamageModifier(Actor attacker, WarheadInfo warhead)
 {
     return(State == PopupState.Closed ? Info.ClosedDamageMultiplier : 1f);
 }
示例#12
0
 public float GetDamageModifier(Actor attacker, WarheadInfo warhead)
 {
     return(IsProne ? Info.ProneDamage : 1f);
 }
示例#13
0
 public float GetDamageModifier(Actor attacker, WarheadInfo warhead)
 {
     return(ArmorLevel > 0 ? (1 / (1 + ArmorLevel * info.ArmorModifier)) : 1);
 }