示例#1
0
 public AlbyPvPManager()
     : base(300000)
 {
     _revivalLocations = new MabiVertex[]
     {
         new MabiVertex(1800, 4644),
         new MabiVertex(1800, 1845),
         new MabiVertex(4675, 1845),
         new MabiVertex(4675, 4644)
     };
 }
示例#2
0
 public LinePath(MabiVertex p1, MabiVertex p2)
 {
     this.P1 = new Point((int)p1.X, (int)p1.Y);
     this.P2 = new Point((int)p2.X, (int)p2.Y);
     this.Rect = new Rectangle(
         (P1.X < P2.X ? P1.X : P2.X),
         (P1.Y < P2.Y ? P1.Y : P2.Y),
         Math.Abs(P1.X - P2.X),
         Math.Abs(P1.Y - P2.Y)
     );
 }
示例#3
0
 /// <summary>
 /// "Redirect" to WorldManager.Instance.SpawnCreature.
 /// </summary>
 protected void Spawn(uint race, uint amount, uint region, MabiVertex pos, uint radius = 0, bool effect = false)
 {
     WorldManager.Instance.SpawnCreature(race, amount, region, pos, radius, effect);
 }
示例#4
0
        /// <summary>
        /// Broadcasts WalkTo. If to is null, the creature's position is used.
        /// </summary>
        /// <param name="wm"></param>
        /// <param name="creature"></param>
        public static void WalkTo(MabiCreature creature, MabiVertex to = null)
        {
            var pos = creature.GetPosition();

            var p = new MabiPacket(Op.WalkTo, creature.Id);
            p.PutInts(pos.X, pos.Y); // From
            p.PutInts(pos.X, pos.Y); // To
            p.PutBytes(1, 0);

            WorldManager.Instance.Broadcast(p, SendTargets.Range, creature);
        }
示例#5
0
 public static void OnCreatureMoves(MabiCreature creature, MabiVertex from, MabiVertex to)
 {
     if (CreatureMoves != null)
         CreatureMoves(creature, from, to);
 }
示例#6
0
        /// <summary>
        /// Starts movement towards to. Also moves Vehicle.
        /// Sends: Walking/Running
        /// </summary>
        public MabiVertex Move(MabiVertex to, bool walk = false)
        {
            var from = this.GetPosition();

            // Server calculation
            {
                _position.X = from.X;
                _position.Y = from.Y;
                _position.H = from.H;

                this.Destination.X = to.X;
                this.Destination.Y = to.Y;
                this.Destination.H = to.H;

                _moveStartTime = DateTime.Now;
                IsWalking = walk;

                var diffX = (int)to.X - (int)from.X;
                var diffY = (int)to.Y - (int)from.Y;
                _moveDuration = Math.Sqrt(diffX * diffX + diffY * diffY) / this.GetSpeed();
                _movementX = diffX / _moveDuration;
                _movementY = diffY / _moveDuration;
                _movementH = 0;

                if (this.IsFlying)
                {
                    _movementH = (from.H < to.H ? this.RaceInfo.FlightInfo.DescentSpeed : this.RaceInfo.FlightInfo.AscentSpeed);
                    _moveDuration = Math.Max(_moveDuration, Math.Abs((int)to.H - (int)from.H) / _movementH);
                }

                this.Direction = (byte)(Math.Floor(Math.Atan2(_movementY, _movementX) / 0.02454369260617026));
            }

            // Client Update
            {
                if (!this.IsFlying)
                {
                    var p = new MabiPacket(!walk ? Op.Running : Op.Walking, this.Id);
                    p.PutInt(from.X);
                    p.PutInt(from.Y);
                    p.PutInt(to.X);
                    p.PutInt(to.Y);
                    WorldManager.Instance.Broadcast(p, SendTargets.Range, this);

                    if (this.Vehicle != null)
                    {
                        this.Vehicle.Move(to, walk);
                    }
                }
            }

            // Server Updates
            {
                switch (this.ActiveSkillId)
                {
                    case SkillConst.RangedCombatMastery:
                    case SkillConst.ArrowRevolver:
                    case SkillConst.ArrowRevolver2:
                    case SkillConst.MagnumShot:
                    case SkillConst.SupportShot:
                    case SkillConst.ElvenMagicMissile:
                    case SkillConst.MirageMissile:
                    case SkillConst.CrashShot:
                        this.ResetAim();
                        break;
                }

                EventManager.CreatureEvents.OnCreatureMoves(this, from, to);
            }

            return from;
        }
示例#7
0
        protected IEnumerable Wander(bool checkForNoticeWhileIdle, bool changeStanceOnNotice)
        {
            var pos = this.Creature.GetPosition();

            MabiVertex dest;

            if (!WorldManager.InRange(pos, this.Creature.AnchorPoint, 2000))
            {
                dest = new MabiVertex(this.Creature.AnchorPoint.X, this.Creature.AnchorPoint.Y);
            }
            else
            {
                do
                {
                    var x = (uint)(pos.X + rnd.Next(-600, 600 + 1));
                    var y = (uint)(pos.Y + rnd.Next(-600, 600 + 1));
                    dest = new MabiVertex(x, y);
                } while (!WorldManager.InRange(pos, this.Creature.AnchorPoint, 2000));
            }

            foreach (var a in this.WalkTo(dest, true))
                yield return a;

            var waitTime = this.GetBeats(rnd.Next(5000, 10000));

            if (checkForNoticeWhileIdle)
            {
                var beats = 0;
                while (beats < waitTime)
                {
                    beats++;
                    yield return true;
                    foreach (var a in this.TryNotice(true, changeStanceOnNotice))
                    {
                        beats++;
                        yield return true;
                    }
                }
            }
            else
            {
                foreach (var a in this.Wait(waitTime))
                    yield return a;
            }
        }
示例#8
0
        protected IEnumerable RunTo(MabiVertex dest, bool wait)
        {
            if (!this.Creature.IsDestination(dest))
            {
                var pos = this.Creature.Move(dest, false);

                //WorldManager.Instance.CreatureMove(this.Creature, pos, dest, false);

                while (wait && this.Creature.IsMoving)
                {
                    CheckForInterrupt();
                    yield return true;
                }
            }
        }
示例#9
0
        public bool FindCollision(uint region, MabiVertex from, MabiVertex to, out MabiVertex intersection)
        {
            intersection = null;

            double x1 = from.X, y1 = from.Y;
            double x2 = to.X, y2 = to.Y;

            var intersections = new List<MabiVertex>();

            var lines = new List<LinePath>();
            this.CollisionTree[region].GetObjects(new LinePath(from, to).Rect, ref lines);

            foreach (var line in lines)
            {
                MabiVertex inter = null;
                if (FindIntersection(x1, y1, x2, y2, line.P1.X, line.P1.Y, line.P2.X, line.P2.Y, out inter))
                    intersections.Add(inter);
            }

            if (intersections.Count < 1)
                return false;

            // Select nearest intersection
            double distance = double.MaxValue;
            foreach (var inter in intersections)
            {
                var interDist = Math.Pow(x1 - x2, 2) + Math.Pow(y1 - y2, 2);
                if (interDist < distance)
                {
                    intersection = inter;
                    distance = interDist;
                }
            }

            return true;
        }
示例#10
0
        public void ActivateMobs(MabiCreature creature, MabiVertex from, MabiVertex to)
        {
            IEnumerable<MabiCreature> mobsInRange = _creatures.Where(c =>
                c.Region == creature.Region
                && c is MabiNPC
                && ((MabiNPC)c).AIScript != null);

            long leftX, rightX, topY, bottomY; //Bounding rectangle coordinates

            if (from.X < to.X) //Moving right
            {
                leftX = from.X - 2600;
                rightX = to.X + 2600;
            }
            else
            {
                leftX = to.X - 2600;
                rightX = from.X + 2600;
            }

            if (from.Y < to.Y) //Moving up
            {
                bottomY = from.Y - 2600;
                topY = to.Y + 2600;
            }
            else
            {
                bottomY = to.Y - 2600;
                topY = from.Y + 2600;
            }

            //Linear movement equation
            double slope;
            if (to.Y == from.Y)
            {
                slope = .001; //double.MinValue produces infinity in B
            }
            else
            {
                slope = ((double)to.Y - from.Y) / ((double)to.X - from.X);
            }
            double b = from.Y - slope * from.X;

            mobsInRange = mobsInRange.Where((c) =>
            {
                var pos = c.GetPosition();
                return (leftX < pos.X && pos.X < rightX && bottomY < pos.Y && pos.Y < topY && (Math.Abs(pos.Y - (long)(slope * pos.X + b)) < 2600));
            });

            double dist = Math.Sqrt(((to.X - from.X) * (to.X - from.X)) + ((to.Y - from.Y) * (to.Y - from.Y)));

            uint time = (uint)Math.Ceiling(dist / creature.GetSpeed());

            foreach (var mob in mobsInRange)
            {
                ((MabiNPC)mob).AIScript.Activate(time);
            }
        }
示例#11
0
        /// <summary>
        /// Initializes quad tree for collision detections.
        /// </summary>
        private void PlantTree()
        {
            foreach (var region in MabiData.RegionInfoDb.Entries.Values)
            {
                foreach (var area in region.Areas.Values)
                {
                    foreach (var prop in area.Props.Values)
                    {
                        foreach (var shape in prop.Shapes)
                        {
                            if (!this.CollisionTree.ContainsKey(region.Id))
                                this.CollisionTree.Add(region.Id, new Quadtree<LinePath>((int)region.X1, (int)region.Y1, (int)region.X2, (int)region.Y2));

                            var p1 = new MabiVertex(shape.X1, shape.Y1);
                            var p2 = new MabiVertex(shape.X2, shape.Y2);
                            var p3 = new MabiVertex(shape.X3, shape.Y3);
                            var p4 = new MabiVertex(shape.X4, shape.Y4);

                            this.CollisionTree[region.Id].Insert(new LinePath(p1, p2));
                            this.CollisionTree[region.Id].Insert(new LinePath(p2, p3));
                            this.CollisionTree[region.Id].Insert(new LinePath(p3, p4));
                            this.CollisionTree[region.Id].Insert(new LinePath(p4, p1));
                        }
                    }
                }
            }
        }
示例#12
0
 /// <summary>
 /// Checks distance between the two vertexes.
 /// </summary>
 public static bool InRange(MabiVertex loc1, MabiVertex loc2, uint range = 0)
 {
     return InRange(loc1.X, loc1.Y, loc2.X, loc2.Y, range);
 }
示例#13
0
        /// <summary>
        /// Returns whether the lines x1/y1-x2/y2 and x3/y3-x4/y4 intersect.
        /// The intersection point is returned in the corresponding out-variable.
        /// </summary>
        private static bool FindIntersection(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4, out MabiVertex intersection)
        {
            intersection = null;

            double denom = ((x2 - x1) * (y4 - y3)) - ((y2 - y1) * (x4 - x3));
            if (denom == 0) return false; // parallel

            double numer = ((y1 - y3) * (x4 - x3)) - ((x1 - x3) * (y4 - y3));
            double r = numer / denom;
            double numer2 = ((y1 - y3) * (x2 - x1)) - ((x1 - x3) * (y2 - y1));
            double s = numer2 / denom;
            if ((r < 0 || r > 1) || (s < 0 || s > 1)) return false; // nointersect

            double interX = x1 + (r * (x2 - x1));
            double interY = y1 + (r * (y2 - y1));

            intersection = new MabiVertex((int)interX, (int)interY);

            return true;
        }
示例#14
0
        public void SpawnCreature(uint race, uint amount, uint region, MabiVertex pos, uint radius = 0, bool effect = false)
        {
            var spawn = new SpawnInfo();
            spawn.Amount = amount;
            spawn.RaceId = race;
            spawn.Region = region;

            if (radius == 0)
            {
                spawn.SpawnType = SpawnLocationType.Point;
                spawn.SpawnPoint = new Point(pos.X, pos.Y);
            }
            else
            {
                spawn.SpawnType = SpawnLocationType.Polygon;
                spawn.SpawnPolyRegion = new SpawnRegion(new Point[]
                {
                    new Point(pos.X - radius, pos.Y - radius),
                    new Point(pos.X - radius, pos.Y + radius),
                    new Point(pos.X + radius, pos.Y + radius),
                    new Point(pos.X + radius, pos.Y - radius),
                });
                spawn.SpawnPolyBounds = spawn.SpawnPolyRegion.GetBounds();
            }

            ScriptManager.Instance.Spawn(spawn, 0, effect);
        }
示例#15
0
        public void HandleCreatureKill(MabiCreature creature, MabiCreature killer, MabiVertex position, SkillConst skillId)
        {
            if (killer != null)
            {
                // Shadow Bunshin soul counter
                if (skillId != SkillConst.ShadowBunshin)
                    killer.SoulCount++;

                // Exp
                if (killer.LevelingEnabled)
                {
                    // Give exp
                    var exp = creature.BattleExp * WorldConf.ExpRate;
                    killer.GiveExp((ulong)exp);

                    Send.CombatMessage(killer.Client, killer, "+{0} EXP", exp);

                    EventManager.CreatureEvents.OnCreatureKilled(creature, killer);
                    if (killer is MabiPC)
                        EventManager.PlayerEvents.OnKilledByPlayer(creature, killer);
                }
            }

            var npc = creature as MabiNPC;
            if (npc != null)
            {
                var rnd = RandomProvider.Get();

                // Gold
                if (rnd.NextDouble() < WorldConf.GoldDropRate)
                {
                    var amount = rnd.Next(npc.GoldMin, npc.GoldMax + 1);
                    if (amount > 0)
                    {
                        var gold = new MabiItem(2000);
                        gold.Info.Amount = (ushort)amount;
                        gold.Info.Region = npc.Region;
                        gold.Info.X = (uint)(position.X + rnd.Next(-50, 51));
                        gold.Info.Y = (uint)(position.Y + rnd.Next(-50, 51));
                        gold.DisappearTime = DateTime.Now.AddSeconds(60);

                        this.AddItem(gold);
                    }
                }

                // Drops
                foreach (var drop in npc.Drops)
                {
                    if (rnd.NextDouble() < drop.Chance * WorldConf.DropRate)
                    {
                        var item = new MabiItem(drop.ItemId);
                        item.Info.Amount = 1;
                        item.Info.Region = npc.Region;
                        item.Info.X = (uint)(position.X + rnd.Next(-50, 51));
                        item.Info.Y = (uint)(position.Y + rnd.Next(-50, 51));
                        item.DisappearTime = DateTime.Now.AddSeconds(60);

                        this.AddItem(item);
                    }
                }
            }

            // Set finisher?
            WorldManager.Instance.Broadcast(new MabiPacket(Op.CombatSetFinisher, creature.Id).PutLong(killer.Id), SendTargets.Range, creature);

            // Clear target
            Send.CombatTargetSet(killer, null);

            // Finish this finisher part?
            WorldManager.Instance.Broadcast(new MabiPacket(Op.CombatSetFinisher2, creature.Id), SendTargets.Range, creature);

            // TODO: There appears to be something missing to let it lay there for finish, if we don't kill it with the following packets.
            // TODO: Check for finishing.

            // Make it dead
            WorldManager.Instance.Broadcast(new MabiPacket(Op.IsNowDead, creature.Id), SendTargets.Range, creature);

            // Remove finisher?
            WorldManager.Instance.Broadcast(new MabiPacket(Op.CombatSetFinisher, creature.Id).PutLong(0), SendTargets.Range, creature);

            if (creature.ActiveSkillId != SkillConst.None)
                creature.CancelSkill();

            if (creature.Owner != null)
            {
                Send.DeadFeather(creature, DeadMenuOptions.Here | DeadMenuOptions.FeatherUp);
                // TODO: Unmount.
            }

            creature.CauseOfDeath = DeathCauses.None;

            if (creature.ArenaPvPManager != null && creature.ArenaPvPManager == killer.ArenaPvPManager && creature.ArenaPvPManager.IsAttackableBy(creature, killer))
            {
                creature.ArenaPvPManager.CreatureKilled(creature, killer);
                creature.CauseOfDeath = DeathCauses.Arena;
            }

            // TODO: Trans PvP

            if (creature.CauseOfDeath == DeathCauses.None && creature.EvGEnabled && killer.EvGEnabled)
                if (creature.EvGSupportRace != 0 && killer.EvGSupportRace != 0 && creature.EvGSupportRace != killer.EvGSupportRace)
                    creature.CauseOfDeath = DeathCauses.EvG;

            if (creature.CauseOfDeath == DeathCauses.None)
                creature.CauseOfDeath = DeathCauses.Mob;
        }
示例#16
0
        protected IEnumerable Circle(MabiEntity center, bool clockwise, int radius, bool wait)
        {
            var centerPos = center.GetPosition();
            var myPos = this.Creature.GetPosition();

            var deltaX = (double)myPos.X - (double)centerPos.X;
            var deltaY = (double)myPos.Y - (double)centerPos.Y;

            var angle = Math.Atan2(deltaY, deltaX);

            angle += (clockwise ? -1 : 1) * rnd.NextDouble() * (Math.PI / 6);

            var x = (int)(Math.Cos(angle) * radius);
            var y = (int)(Math.Sin(angle) * radius);

            var dest = new MabiVertex(centerPos.X + x, centerPos.Y + y);

            foreach (var a in WalkTo(dest, wait))
                yield return a;
        }
示例#17
0
        /// <summary>
        /// Calculates a position on the line between source and target.
        /// e.g. distance 0 would be the position of target, 100 would be
        /// 100 points farther away from source.
        /// </summary>
        public static MabiVertex CalculatePosOnLine(MabiVertex source, MabiVertex target, int distance)
        {
            if (source.Equals(target))
                return new MabiVertex(source.X + 1, source.Y + 1);

            var deltaX = (double)target.X - source.X;
            var deltaY = (double)target.Y - source.Y;

            var deltaXY = Math.Sqrt(Math.Pow(deltaX, 2) + Math.Pow(deltaY, 2));

            var newX = target.X + (distance / deltaXY) * (deltaX);
            var newY = target.Y + (distance / deltaXY) * (deltaY);

            return new MabiVertex((uint)newX, (uint)newY);
        }
示例#18
0
        // Built-in Behaviors --------------------------
        protected IEnumerable WalkTo(MabiVertex dest, bool wait)
        {
            var pos = this.Creature.GetPosition();

            // Check for collision, set destination 200 points before the
            // intersection, to prevent glitching through.
            MabiVertex intersection;
            if (WorldManager.Instance.FindCollision(this.Creature.Region, pos, dest, out intersection))
                dest = WorldManager.CalculatePosOnLine(pos, intersection, -200);

            this.Creature.Move(dest, true);

            //WorldManager.Instance.CreatureMove(this.Creature, pos, dest, true);

            while (wait && Creature.IsMoving)
            {
                CheckForInterrupt();
                yield return true;
            }
        }
示例#19
0
 /// <summary>
 /// Returns true if the creature is currently moving
 /// to the given position.
 /// </summary>
 /// <param name="dest"></param>
 /// <returns></returns>
 public bool IsDestination(MabiVertex dest)
 {
     return (this.Destination.Equals(dest));
 }
示例#20
0
 public static MabiPacket SpawnEffect(MabiEntity entity, SpawnEffect type, MabiVertex pos)
 {
     return
         new MabiPacket(Op.Effect, entity.Id)
         .PutInt(Effect.Spawn)
         .PutInt(entity.Region)
         .PutFloats(pos.X, pos.Y)
         .PutByte((byte)type);
 }
示例#21
0
        /// <summary>
        /// Adds one or multiple items with the given id to the creature's
        /// inventory. Tries to fill sacs first, inventory afterwards, and
        /// all remaining will be added to the temp inventory.
        /// </summary>
        /// <param name="itemClass"></param>
        /// <param name="amount"></param>
        public MabiItem GiveItem(uint itemClass, uint amount, uint color1 = 0, uint color2 = 0, uint color3 = 0, bool useDBColors = true, bool drop = false)
        {
            MabiItem result = null;

            // Fill stacks and sacs
            foreach (var item in this.Items)
            {
                if ((item.Type == ItemType.Sac && item.StackItem == itemClass) || (item.Info.Class == itemClass && item.StackType == BundleType.Stackable))
                {
                    if (item.Info.Amount >= item.StackMax)
                        continue;

                    var prev = item.Info.Amount;
                    var diff = item.StackMax - item.Info.Amount;
                    if (diff >= amount)
                    {
                        item.Info.Amount += (ushort)amount;
                        amount = 0;
                    }
                    else
                    {
                        item.Info.Amount = item.StackMax;
                        amount -= (uint)diff;
                    }

                    if (prev != item.Info.Amount)
                    {
                        this.ItemUpdate(item);
                        result = item;
                    }
                }
            }

            // Add remaining to inv or temp inv.
            while (amount > 0)
            {
                var item = new MabiItem(itemClass);
                if (!useDBColors)
                {
                    item.Info.ColorA = color1;
                    item.Info.ColorB = color2;
                    item.Info.ColorC = color3;
                }
                var max = Math.Max((ushort)1, item.StackMax); // This way, we can't drag the server into an infinate loop
                if (amount <= max)
                {
                    item.Info.Amount = (ushort)amount;
                    amount = 0;
                }
                else
                {
                    item.Info.Amount = max;
                    amount -= max;
                }

                if (drop)
                {
                    var pos = this.GetPosition();
                    var rand = RandomProvider.Get();
                    var x = (uint)(pos.X + rand.Next(-100, 101));
                    var y = (uint)(pos.Y + rand.Next(-100, 101)); WorldManager.Instance.DropItem(item, this.Region, x, y);
                    EventManager.CreatureEvents.OnCreatureDropItem(this, item);
                }
                else
                {
                    var pocket = Pocket.Inventory;
                    var space = this.GetFreeItemSpace(item, pocket);
                    if (space == null)
                    {
                        pocket = Pocket.Temporary;
                        space = new MabiVertex(0, 0);
                    }

                    item.Move(pocket, space.X, space.Y);
                    this.Items.Add(item);

                    this.ItemUpdate(item, true);
                }

                result = item;
            }

            EventManager.CreatureEvents.OnCreatureItemAction(this, itemClass);

            return result;
        }