public override bool Process() { if (NetworkManager.IsClient) { return(false); } // 5x5, but remove corners for (int y = TargetY - 2; y <= TargetY + 2; y++) { for (int x = TargetX - 2; x <= TargetX + 2; x++) { // check for corner tiles :) if ((x == TargetX - 2 || x == TargetX + 2) && (y == TargetY - 2 || y == TargetY + 2)) { continue; } if (x < 0 || y < 0 || x >= MapLogic.Instance.Width || y >= MapLogic.Instance.Height) { continue; } // check if there are FIRE effects on this cell, don't spawn fog bool spawnblocked = false; foreach (MapObject mo in MapLogic.Instance.Nodes[x, y].Objects) { if (!(mo is MapProjectile)) { continue; } MapProjectile mp = (MapProjectile)mo; if (mp.Class == null || mp.Class.ID != (int)AllodsProjectile.PoisonCloud) { continue; } // don't remove if on edge of fire wall if (new Vector2(mp.ProjectileX - x + 0.5f, mp.ProjectileY - y + 0.5f).magnitude > 0.8f) { continue; } spawnblocked = true; break; } if (spawnblocked) { continue; } Server.SpawnProjectileEOT(AllodsProjectile.PoisonCloud, Spell.User, x + 0.5f, y + 0.5f, 0, (int)(MapLogic.TICRATE * Spell.GetDuration()), 40, 0, 0, 16, proj => { DamageFlags spdf = SphereToDamageFlags(Spell); // get projectile cells int axFrom = Mathf.Max(0, Mathf.FloorToInt(proj.ProjectileX)); int axTo = Mathf.Min(MapLogic.Instance.Width - 1, Mathf.CeilToInt(proj.ProjectileX)); int ayFrom = Mathf.Max(0, Mathf.FloorToInt(proj.ProjectileY)); int ayTo = Mathf.Min(MapLogic.Instance.Height - 1, Mathf.CeilToInt(proj.ProjectileY)); for (int py = ayFrom; py <= ayTo; py++) { for (int px = axFrom; px <= axTo; px++) { // check how much projectile is on this cell float pdst = 1f - Mathf.Min(1f, new Vector2(px + 0.5f - proj.ProjectileX, py + 0.5f - proj.ProjectileY).magnitude); // 0..1 effect power MapNode node = MapLogic.Instance.Nodes[px, py]; for (int i = 0; i < node.Objects.Count; i++) { MapObject mo = node.Objects[i]; if (!(mo is MapUnit)) { continue; } MapUnit mov = (MapUnit)mo; int dmg = (int)(Spell.GetIndirectPower() * pdst); if (dmg <= 0) { continue; // don't add null effects } SpellEffects.Effect eff = new SpellEffects.Poison(this, dmg, MapLogic.TICRATE * 8); // originally 8 seconds mov.AddSpellEffects(eff); } } } }); } } return(false); }
public override bool Process() { if (TargetUnit == null) { return(false); } // look for 3-7 enemies nearby int maxTargets = Spell.GetIndirectPower(); List <MapUnit> targets = new List <MapUnit>(); int range = Mathf.CeilToInt(Spell.GetDistance()); int fromX = Spell.User.X - range; int fromY = Spell.User.Y - range; int toX = Spell.User.X + Spell.User.Width + range; int toY = Spell.User.Y + Spell.User.Height + range; for (int y = fromY; y <= toY; y++) { if (y < 0 || y >= MapLogic.Instance.Height) { continue; } for (int x = fromX; x <= toX; x++) { if (x < 0 || x >= MapLogic.Instance.Width) { continue; } if (targets.Count >= maxTargets - 1) { break; } MapNode node = MapLogic.Instance.Nodes[x, y]; foreach (MapObject objnode in node.Objects) { if (objnode is MapUnit) { MapUnit unit = (MapUnit)objnode; if ((Spell.User.Player.Diplomacy[unit.Player.ID] & DiplomacyFlags.Enemy) != 0) // in war with this unit, then add to list { if (!targets.Contains(unit)) { targets.Add(unit); } } } } } } // randomize units System.Random rng = new System.Random(); targets = targets.Where(a => a != TargetUnit).OrderBy(a => rng.Next()).Take(maxTargets - 1).ToList(); targets.Insert(0, TargetUnit); for (int i = 0; i < targets.Count; i++) { SpawnProjectile(targets[i], Spell.GetDamage(), i + 1, 1f / targets.Count); } return(false); }