private bool MyPeopleNeedMe() { if (IsFaction || Crystal == null || Crystal.Deleted || !Crystal.Visible || !Crystal.Movable || Utility.RandomBool()) { return false; } Crystal.PublicOverheadMessage(MessageType.Regular, 1287, false, "I MUST GO, MY PEOPLE NEED ME."); Point3D loc = Crystal.GetWorldLocation(); // (Lee) The reason for using effects is efficiency, // since whenever the physical item's location (Z) is changed, // it sends a bunch of update packets, I know it's trivial, // but i thought you might like this example of usage of the VNc effects :) // Create a new deferred effect queue. // When the queue has finished processing, delete the crystal. var q = new EffectQueue( () => { if (Crystal != null) { Crystal.Delete(); } }); // Add 10 effects to the queue, // each with a duration of 10 (default value), // which translates to 1000 milliseconds (10 * 100). // Since they are not moving effects and each effect lasts for 1 second, // it should produce the same illusion of the original implementation design. for (int i = 0; i < 10; i++) { q.Add( new EffectInfo( loc.Clone3D(0, 0, i), Crystal.Map, Crystal.ItemID, Crystal.Hue, 10, 10, EffectRender.Normal, TimeSpan.Zero)); } // Process the effect queue after waiting 5 seconds. Timer.DelayCall( TimeSpan.FromSeconds(5.0), () => { // Anything can happen in 5 seconds, so check it all again. if (Crystal != null && !Crystal.Deleted && Crystal.Visible && Crystal.Movable && !IsFaction) { // Hiding the crystal so the effects can handle the visuals Crystal.Visible = false; // Just in case anyone wants to try to mess with it, even when it's hidden. Crystal.Movable = false; q.Process(); } // We don't need the queue, so explicitly dispose for efficiency (optional) q.Dispose(); }); return true; }
private bool MyPeopleNeedMe() { if (IsFaction || Crystal == null || Crystal.Deleted || !Crystal.Visible || !Crystal.Movable || Utility.RandomBool()) { return(false); } Crystal.PublicOverheadMessage(MessageType.Regular, 1287, false, "I MUST GO, MY PEOPLE NEED ME."); Point3D loc = Crystal.GetWorldLocation(); // (Lee) The reason for using effects is efficiency, // since whenever the physical item's location (Z) is changed, // it sends a bunch of update packets, I know it's trivial, // but i thought you might like this example of usage of the VNc effects :) // Create a new deferred effect queue. // When the queue has finished processing, delete the crystal. var q = new EffectQueue( () => { if (Crystal != null) { Crystal.Delete(); } }); // Add 10 effects to the queue, // each with a duration of 10 (default value), // which translates to 1000 milliseconds (10 * 100). // Since they are not moving effects and each effect lasts for 1 second, // it should produce the same illusion of the original implementation design. for (int i = 0; i < 10; i++) { q.Add( new EffectInfo( loc.Clone3D(0, 0, i), Crystal.Map, Crystal.ItemID, Crystal.Hue, 10, 10, EffectRender.Normal, TimeSpan.Zero)); } // Process the effect queue after waiting 5 seconds. Timer.DelayCall( TimeSpan.FromSeconds(5.0), () => { // Anything can happen in 5 seconds, so check it all again. if (Crystal != null && !Crystal.Deleted && Crystal.Visible && Crystal.Movable && !IsFaction) { // Hiding the crystal so the effects can handle the visuals Crystal.Visible = false; // Just in case anyone wants to try to mess with it, even when it's hidden. Crystal.Movable = false; q.Process(); } // We don't need the queue, so explicitly dispose for efficiency (optional) q.Dispose(); }); return(true); }
protected override void OnInvoke(BaseAspect aspect) { if (aspect == null || aspect.Deleted) { return; } var list = ListPool <EffectQueue> .AcquireObject(); var cw = Utility.RandomBool(); for (int a = (cw ? 0 : 360), h = 0; (cw ? a <= 360 : a >= 0); a += (cw ? 1 : -1)) { var x = (int)Math.Round(aspect.X + (aspect.RangePerception * Math.Sin(Geometry.DegreesToRadians(a)))); var y = (int)Math.Round(aspect.Y + (aspect.RangePerception * Math.Cos(Geometry.DegreesToRadians(a)))); if (((x * 397) ^ y) == h) { // This location was just handled, ignore it to avoid small increments continue; } h = ((x * 397) ^ y); var start = aspect.Clone3D(0, 0, 10); var end = new Point3D(x, y, aspect.Z); end.Z = end.GetTopZ(aspect.Map); var l = start.GetLine3D(end, aspect.Map, false); var q = new EffectQueue { Deferred = false, Handler = e => HandleDeathRay(aspect, e) }; for (var i = 0; i < l.Length; i++) { var p = new Block3D(l[i], 5); var blocked = i + 1 >= l.Length; if (!blocked) { var land = aspect.Map.GetLandTile(p); if (p.Intersects(land.Z, land.Height)) { var o = TileData.LandTable[land.ID]; if (o.Flags.AnyFlags(_BlockingFlags)) { blocked = true; } } } if (!blocked) { var tiles = aspect.Map.GetStaticTiles(p); var data = tiles.Where(o => p.Intersects(o.Z, o.Height)).Select(t => TileData.ItemTable[t.ID]); if (data.Any(o => o.Flags.AnyFlags(_BlockingFlags))) { blocked = true; } } if (!blocked) { var items = p.FindItemsAt(aspect.Map); var data = items.Where(p.Intersects).Select(o => TileData.ItemTable[o.ItemID]); if (data.Any(o => o.Flags.AnyFlags(_BlockingFlags))) { blocked = true; } } var effect = blocked ? 14120 : Utility.RandomMinMax(12320, 12324); var hue = blocked ? 0 : 2075; if (blocked) { p = p.Clone3D(0, 0, -8); } q.Add( new EffectInfo(p, aspect.Map, effect, hue, 10, 10, EffectRender.Darken) { QueueIndex = i }); if (blocked) { break; } } if (q.Queue.Count > 0) { list.Add(q); } } if (list.Count == 0) { ObjectPool.Free(list); return; } for (var i = 0; i < list.Count; i++) { var cur = list[i]; if (i + 1 < list.Count) { var next = list[i + 1]; cur.Callback = () => { if (aspect.Deleted || !aspect.Alive) { list.ForEach(q => q.Dispose()); ObjectPool.Free(list); return; } if (next.Queue.Count > 0) { SpellHelper.Turn(aspect, next.Queue.Last().Source); } Timer.DelayCall(TimeSpan.FromSeconds(0.05), next.Process); }; } else { cur.Callback = () => { list.ForEach(q => q.Dispose()); ObjectPool.Free(list); aspect.CantWalk = false; aspect.LockDirection = false; }; } } if (list.Count == 0) { ObjectPool.Free(list); return; } aspect.CantWalk = true; aspect.LockDirection = true; if (list[0].Queue.Count > 0) { SpellHelper.Turn(aspect, list[0].Queue.Last().Source); } Timer.DelayCall(TimeSpan.FromSeconds(0.1), list[0].Process); }
protected override void OnInvoke(BaseAspect aspect) { if (aspect == null || aspect.Deleted) { return; } var map = aspect.Map; var x = aspect.X; var y = aspect.Y; var z = aspect.Z; var count = Utility.RandomMinMax(5, 10); var sect = 360 / count; var shift = Utility.RandomMinMax(0, sect); var range = Math.Max(3, aspect.RangePerception - 3); for (var i = 0; i < count; i++) { var t = Angle.GetPoint3D(x, y, z, shift + (i * sect), range); var l = aspect.PlotLine3D(t).TakeWhile(p => map.HasLand(p) && !map.HasWater(p)); var q = new EffectQueue(range); var c = -1; foreach (var p in l) { q.Add( new EffectInfo(p, map, 14089, 0, 8, 15, EffectRender.Darken) { QueueIndex = ++c }); } if (q.Count == 0) { q.Dispose(); continue; } q.Handler = fx => { var isEnd = fx.QueueIndex >= c; if (!TryBurst(aspect, fx, ref isEnd) || isEnd) { q.Clear(); } }; q.Callback = q.Dispose; Timer.DelayCall( TimeSpan.FromSeconds(0.2 * i), () => { aspect.Direction = aspect.GetDirection(t); if (aspect.PlayAttackAnimation()) { aspect.PlayAttackSound(); } q.Process(); }); } }