Exemple #1
0
        /// <summary>
        /// Sets up shop, spawning the prop.
        /// </summary>
        /// <param name="title"></param>
        /// <param name="description"></param>
        public bool SetUp(string title, string description)
        {
            if (!this.IsReadyForBusiness)
            {
                return(false);
            }

            this.Title       = title;
            this.Description = description;

            var rnd       = RandomProvider.Get();
            var pos       = this.Owner.GetPosition();
            var location  = new Location(this.Owner.RegionId, GetPlacementPosition(pos, this.Owner.Direction));
            var direction = MabiMath.ByteToRadian(this.Owner.Direction);

            // Spawn prop
            var propId = GetShopPropId(this.Bag);

            this.Prop             = new Prop(propId, location.RegionId, location.X, location.Y, (float)direction);
            this.Prop.Info.Color1 = this.Bag.Info.Color1;
            this.Prop.Info.Color2 = this.Bag.Info.Color2;
            this.Prop.Info.Color3 = this.Bag.Info.Color3;
            this.Prop.Extensions.AddSilent(new ConfirmationPropExtension("default", "이 개인상점을 여시겠습니까?", "개인상점 열기"));
            this.Region.AddProp(this.Prop);

            // Move that body
            Send.UseMotion(this.Owner, 11, 4);

            // Update prop with owner and title
            this.Prop.Xml.SetAttributeValue("PSPID", this.Owner.EntityId);
            this.Prop.Xml.SetAttributeValue("PSTTL", title);
            Send.PropUpdate(this.Prop);

            return(true);
        }
Exemple #2
0
    private void PrepareTrainers(Creature challenger, Creature player)
    {
        var pos          = challenger.GetPosition();
        var playerNewPos = pos.GetRelative(MabiMath.ByteToRadian(challenger.Direction), BattleDistance);

        _challengerMonsterPos = playerNewPos.GetRelative(pos, -MonsterDistance);
        _playerMonsterPos     = pos.GetRelative(playerNewPos, -MonsterDistance);

        //challenger.Region.AddProp(new Prop(10, challenger.RegionId, _challengerMonsterPos.X, _challengerMonsterPos.Y, 0));
        //challenger.Region.AddProp(new Prop(10, challenger.RegionId, _playerMonsterPos.X, _playerMonsterPos.Y, 0));

        // Camera
        var packet = new Packet(Op.SetCamera, player.EntityId);

        packet.PutFloat(1000);                                                                                              // distance
        packet.PutFloat(0);
        packet.PutFloat(5);                                                                                                 // pitch
        packet.PutFloat(MabiMath.DirectionToRadian(pos.X - playerNewPos.X, pos.Y - playerNewPos.Y) * (180 / Math.PI) + 25); // yaw
        packet.PutFloat(0);
        player.Client.Send(packet);

        // Move and turn
        player.Jump(playerNewPos);
        player.TurnTo(pos);
        challenger.TurnTo(playerNewPos);
    }
Exemple #3
0
    protected override IEnumerable Idle()
    {
        var challenger = Creature;

        if (challenger.Vars.Temp["inTrainerBattleWith"] != null)
        {
            Return();
        }

        var dir = MabiMath.ByteToRadian(challenger.Direction) - Math.PI;         // opposite direction...?
        var pos = challenger.GetPosition();

        var players = challenger.Region.GetCreatures(a => a.IsPlayer && a.GetPosition().InCone(pos, dir, 1000, 45));

        if (players.Count != 1)
        {
            Return();
        }

        var opponent = players.First();

        if (_fought.Contains(opponent.EntityId))
        {
            Return();
        }

        _fought.Add(opponent.EntityId);

        TrainerBaseScript.StartBattle(challenger, opponent);
    }
Exemple #4
0
        /// <summary>
        /// Returns position for the shop, based on given position and direction.
        /// </summary>
        /// <param name="pos"></param>
        /// <param name="direction"></param>
        /// <returns></returns>
        private static Position GetPlacementPosition(Position pos, byte direction)
        {
            var radians = MabiMath.ByteToRadian(direction);
            var x       = pos.X + 50 * Math.Cos(radians);
            var y       = pos.Y + 50 * Math.Sin(radians);

            return(new Position((int)x, (int)y));
        }
Exemple #5
0
        /// <summary>
        /// Completes skill, placing the campfire.
        /// </summary>
        /// <param name="creature"></param>
        /// <param name="skill"></param>
        /// <param name="packet"></param>
        public void Complete(Creature creature, Skill skill, Packet packet)
        {
            var positionId = packet.GetLong();
            var unkInt1    = packet.GetInt();
            var unkInt2    = packet.GetInt();

            // Handle items
            if (skill.Info.Id == SkillId.Campfire)
            {
                // Check Firewood, the client should stop the player long before Complete.
                if (creature.Inventory.Count(creature.Temp.FirewoodItemId) < FirewoodCost)
                {
                    throw new ModerateViolation("Used Campfire without Firewood.");
                }

                // Remove Firewood
                creature.Inventory.Remove(creature.Temp.FirewoodItemId, FirewoodCost);
            }
            else
            {
                // Check kit
                var item = creature.Inventory.GetItem(creature.Temp.CampfireKitItemEntityId);
                if (item == null)
                {
                    throw new ModerateViolation("Used CampfireKit with invalid kit.");
                }

                // Reduce kit
                creature.Inventory.Decrement(item);
            }

            // Set up Campfire
            var pos    = new Position(positionId);
            var effect = (skill.Info.Rank < SkillRank.RB ? "campfire_01" : "campfire_02");
            var prop   = new Prop(PropId, creature.RegionId, pos.X, pos.Y, MabiMath.ByteToRadian(creature.Direction), 1);           // Logs

            prop.State = "single";
            prop.Xml.SetAttributeValue("EFFECT", effect);                                                       // Fire effect
            prop.DisappearTime = DateTime.Now.AddMinutes(this.GetDuration(skill.Info.Rank, creature.RegionId)); // Disappear after x minutes

            // Temp data for Rest
            prop.Temp.CampfireSkillRank = skill.RankData;
            if (skill.Info.Id == SkillId.Campfire)
            {
                prop.Temp.CampfireFirewood = AuraData.ItemDb.Find(creature.Temp.FirewoodItemId);
            }

            creature.Region.AddProp(prop);

            // Complete
            Send.SkillComplete(creature, skill.Info.Id, positionId, unkInt1, unkInt2);
        }
Exemple #6
0
        /// <summary>
        /// Creates sitting prop, fails silently if item or chair
        /// data doesn't exist.
        /// </summary>
        /// <param name="creature"></param>
        /// <param name="chairItemEntityId"></param>
        private void SetUpChair(Creature creature, long chairItemEntityId)
        {
            if (chairItemEntityId == 0)
            {
                return;
            }

            // Check item
            var item = creature.Inventory.GetItem(chairItemEntityId);

            if (item == null || item.Data.Type != ItemType.Misc)
            {
                return;
            }

            // Get chair data
            var chairData = AuraData.ChairDb.Find(item.Info.Id);

            if (chairData == null)
            {
                return;
            }

            var pos = creature.GetPosition();

            // Effect
            if (chairData.Effect != 0)
            {
                Send.Effect(creature, chairData.Effect, true);
            }

            // Chair prop
            var sittingProp = new Prop((!creature.IsGiant ? chairData.PropId : chairData.GiantPropId), creature.RegionId, pos.X, pos.Y, MabiMath.ByteToRadian(creature.Direction));

            sittingProp.Info.Color1 = item.Info.Color1;
            sittingProp.Info.Color2 = item.Info.Color2;
            sittingProp.Info.Color3 = item.Info.Color3;
            sittingProp.State       = "stand";
            creature.Region.AddProp(sittingProp);

            // Move char
            Send.AssignSittingProp(creature, sittingProp.EntityId, 1);

            // Update chair
            sittingProp.Xml.SetAttributeValue("OWNER", creature.EntityId);
            sittingProp.Xml.SetAttributeValue("SITCHAR", creature.EntityId);

            Send.PropUpdate(sittingProp);

            creature.Temp.CurrentChairData = chairData;
            creature.Temp.SittingProp      = sittingProp;
        }
Exemple #7
0
        /// <summary>
        /// Creates sitting prop, fails silently if item or chair
        /// data doesn't exist.
        /// </summary>
        /// <param name="creature"></param>
        /// <param name="chairItemEntityId"></param>
        private void SetUpChair(Creature creature, long chairItemEntityId)
        {
            if (chairItemEntityId == 0)
            {
                return;
            }

            // Check item
            var item = creature.Inventory.GetItem(chairItemEntityId);

            if (item == null || item.Data.Type != ItemType.Misc)
            {
                return;
            }

            // Get chair data
            var chairData = AuraData.ChairDb.Find(item.Info.Id);

            if (chairData == null)
            {
                return;
            }

            var pos = creature.GetPosition();

            // Effect
            if (chairData.Effect != 0)
            {
                Send.Effect(creature, chairData.Effect, true);
            }

            // Chair prop
            var sittingProp = new Prop((!creature.IsGiant ? chairData.PropId : chairData.GiantPropId), creature.RegionId, pos.X, pos.Y, MabiMath.ByteToRadian(creature.Direction));

            sittingProp.Info.Color1 = item.Info.Color1;
            sittingProp.Info.Color2 = item.Info.Color2;
            sittingProp.Info.Color3 = item.Info.Color3;
            sittingProp.State       = chairData.State;

            if (chairData.Stand != -1)
            {
                sittingProp.Xml.SetAttributeValue("PMPG", chairData.Stand);
                sittingProp.Xml.SetAttributeValue("PMPS", true);
            }

            sittingProp.Xml.SetAttributeValue("OWNER", creature.EntityId);
            sittingProp.Xml.SetAttributeValue("PMUIID", chairData.ItemId);

            creature.Region.AddProp(sittingProp);

            // State transition
            if (chairData.NextState != null)
            {
                Task.Delay(chairData.StateChangeDelay).ContinueWith(_ =>
                {
                    sittingProp.State = chairData.NextState;
                    Send.PropUpdate(sittingProp);
                });
            }

            this.SitOnProp(creature, sittingProp, chairData);
        }
Exemple #8
0
        /// <summary>
        /// Uses LightningRod
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="skill"></param>
        /// <param name="packet"></param>
        public void Use(Creature attacker, Skill skill, Packet packet)
        {
            // Set full charge variable
            attacker.Temp.LightningRodFullCharge = (DateTime.Now >= attacker.Temp.LightningRodPrepareTime.AddMilliseconds(skill.RankData.Var3));

            // Get direction for target Area
            var direction = Mabi.MabiMath.ByteToRadian(attacker.Direction);

            var attackerPos = attacker.GetPosition();

            // Calculate polygon points
            var r     = MabiMath.ByteToRadian(attacker.Direction);
            var poe   = attackerPos.GetRelative(r, 800);
            var pivot = new Point(poe.X, poe.Y);
            var p1    = new Point(pivot.X - SkillLength / 2, pivot.Y - SkillWidth / 2);
            var p2    = new Point(pivot.X - SkillLength / 2, pivot.Y + SkillWidth / 2);
            var p3    = new Point(pivot.X + SkillLength / 2, pivot.Y + SkillWidth / 2);
            var p4    = new Point(pivot.X + SkillLength / 2, pivot.Y - SkillWidth / 2);

            p1 = this.RotatePoint(p1, pivot, r);
            p2 = this.RotatePoint(p2, pivot, r);
            p3 = this.RotatePoint(p3, pivot, r);
            p4 = this.RotatePoint(p4, pivot, r);

            // TargetProp
            var lProp = new Prop(280, attacker.RegionId, poe.X, poe.Y, MabiMath.ByteToRadian(attacker.Direction), 1f, 0f, "single");

            attacker.Region.AddProp(lProp);

            // Prepare Combat Actions
            var cap = new CombatActionPack(attacker, skill.Info.Id);

            var targetAreaId = new Location(attacker.RegionId, poe).ToLocationId();

            var aAction = new AttackerAction(CombatActionType.SpecialHit, attacker, targetAreaId);

            aAction.Set(AttackerOptions.KnockBackHit1 | AttackerOptions.UseEffect);
            aAction.PropId = lProp.EntityId;
            cap.Add(aAction);

            // Get targets in Polygon - includes collission check
            var targets = attacker.Region.GetCreaturesInPolygon(p1, p2, p3, p4).Where(x => attacker.CanTarget(x) && !attacker.Region.Collisions.Any(attacker.GetPosition(), x.GetPosition())).ToList();

            var rnd = RandomProvider.Get();

            // Check crit
            var crit      = false;
            var critSkill = attacker.Skills.Get(SkillId.CriticalHit);

            if (critSkill != null && critSkill.Info.Rank > SkillRank.Novice)
            {
                var critChance = Math2.Clamp(0, 30, attacker.GetTotalCritChance(0));
                if (rnd.NextDouble() * 100 < critChance)
                {
                    crit = true;
                }
            }

            foreach (var target in targets)
            {
                var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, SkillId.CombatMastery);
                tAction.Set(TargetOptions.None);
                tAction.AttackerSkillId = skill.Info.Id;
                cap.Add(tAction);

                var damage = attacker.GetRndMagicDamage(skill, skill.RankData.Var1, skill.RankData.Var2);

                // Add damage if the skill is fully charged
                var dmgMultiplier = skill.RankData.Var4 / 100f;
                if (attacker.Temp.LightningRodFullCharge)
                {
                    damage += (damage * dmgMultiplier);
                }

                // Critical Hit
                if (crit)
                {
                    var bonus = critSkill.RankData.Var1 / 100f;
                    damage = damage + (damage * bonus);

                    tAction.Set(TargetOptions.Critical);
                }

                // MDef and MProt
                SkillHelper.HandleMagicDefenseProtection(target, ref damage);

                // Mana Deflector
                var delayReduction = ManaDeflector.Handle(attacker, target, ref damage, tAction);

                // Mana Shield
                ManaShield.Handle(target, ref damage, tAction);

                // Apply Damage
                target.TakeDamage(tAction.Damage = damage, attacker);

                // Stun Time
                tAction.Stun = TargetStun;

                // Death or Knockback
                if (target.IsDead)
                {
                    tAction.Set(TargetOptions.FinishingKnockDown);
                    attacker.Shove(target, KnockbackDistance);
                }
                else
                {
                    // Always knock down
                    if (target.Is(RaceStands.KnockDownable))
                    {
                        tAction.Set(TargetOptions.KnockDown);
                        attacker.Shove(target, KnockbackDistance);
                    }
                }
            }
            cap.Handle();

            Send.Effect(attacker, Effect.LightningRod, (int)LightningRodEffect.Attack, poe.X, poe.Y);

            Send.SkillUse(attacker, skill.Info.Id, targetAreaId, 0, 1);
            skill.Train(1);             // Use the Skill

            attacker.Region.RemoveProp(lProp);
        }
Exemple #9
0
        /// <summary>
        /// Uses LightningRod
        /// </summary>
        /// <param name="attacker"></param>
        /// <param name="skill"></param>
        /// <param name="packet"></param>
        public void Use(Creature attacker, Skill skill, Packet packet)
        {
            // Set full charge variable
            attacker.Temp.LightningRodFullCharge = (DateTime.Now >= attacker.Temp.LightningRodPrepareTime.AddMilliseconds(skill.RankData.Var3));

            // Get targets in skill area
            Position targetPropPos;
            var      targets = SkillHelper.GetTargetableCreaturesInSkillArea(attacker, SkillLength, SkillWidth, out targetPropPos);

            // TargetProp
            var lProp = new Prop(280, attacker.RegionId, targetPropPos.X, targetPropPos.Y, MabiMath.ByteToRadian(attacker.Direction), 1f, 0f, "single");

            attacker.Region.AddProp(lProp);

            // Prepare Combat Actions
            var cap = new CombatActionPack(attacker, skill.Info.Id);

            var targetAreaId = new Location(attacker.RegionId, targetPropPos).ToLocationId();

            var aAction = new AttackerAction(CombatActionType.SpecialHit, attacker, targetAreaId);

            aAction.Set(AttackerOptions.KnockBackHit1 | AttackerOptions.UseEffect);
            aAction.PropId = lProp.EntityId;
            cap.Add(aAction);

            var rnd = RandomProvider.Get();

            // Check crit
            var crit      = false;
            var critSkill = attacker.Skills.Get(SkillId.CriticalHit);

            if (critSkill != null && critSkill.Info.Rank > SkillRank.Novice)
            {
                var critChance = Math2.Clamp(0, 30, attacker.GetTotalCritChance(0));
                if (rnd.NextDouble() * 100 < critChance)
                {
                    crit = true;
                }
            }

            foreach (var target in targets)
            {
                var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, SkillId.CombatMastery);
                tAction.Set(TargetOptions.None);
                tAction.AttackerSkillId = skill.Info.Id;
                cap.Add(tAction);

                var damage = attacker.GetRndMagicDamage(skill, skill.RankData.Var1, skill.RankData.Var2);

                // Add damage if the skill is fully charged
                var dmgMultiplier = skill.RankData.Var4 / 100f;
                if (attacker.Temp.LightningRodFullCharge)
                {
                    damage += (damage * dmgMultiplier);
                }

                // Critical Hit
                if (crit)
                {
                    CriticalHit.Handle(attacker, 100, ref damage, tAction);
                }

                // Handle skills and reductions
                SkillHelper.HandleMagicDefenseProtection(target, ref damage);
                SkillHelper.HandleConditions(attacker, target, ref damage);
                var delayReduction = ManaDeflector.Handle(attacker, target, ref damage, tAction);
                ManaShield.Handle(target, ref damage, tAction);

                // Apply Damage
                target.TakeDamage(tAction.Damage = damage, attacker);

                // Stun Time
                tAction.Stun = TargetStun;

                // Death or Knockback
                if (target.IsDead)
                {
                    tAction.Set(TargetOptions.FinishingKnockDown);
                    attacker.Shove(target, KnockbackDistance);
                }
                else
                {
                    // Always knock down
                    if (target.Is(RaceStands.KnockDownable))
                    {
                        tAction.Set(TargetOptions.KnockDown);
                        attacker.Shove(target, KnockbackDistance);
                    }
                }
            }

            // Update current weapon
            SkillHelper.UpdateWeapon(attacker, targets.FirstOrDefault(), ProficiencyGainType.Melee, attacker.RightHand);

            cap.Handle();

            Send.Effect(attacker, Effect.LightningRod, LightningRodEffect.Attack, targetPropPos.X, targetPropPos.Y);

            Send.SkillUse(attacker, skill.Info.Id, targetAreaId, 0, 1);
            skill.Train(1);             // Use the Skill

            attacker.Region.RemoveProp(lProp);
        }
        /// <summary>
        /// Uses skill, attempting to place the stone.
        /// </summary>
        /// <param name="creature"></param>
        /// <param name="skill"></param>
        /// <param name="packet"></param>
        public void Use(Creature creature, Skill skill, Packet packet)
        {
            var locationId = packet.GetLong();
            var unkInt1    = packet.GetInt();
            var unkInt2    = packet.GetInt();

            var guild       = creature.Guild;
            var region      = creature.Region;
            var pos         = new Position(locationId);
            var creaturePos = creature.GetPosition();

            // Check range
            if (!creaturePos.InRange(pos, MaxStoneDistance))
            {
                creature.Unlock(Locks.Walk | Locks.Run);

                Send.Notice(creature, Localization.Get("You're too far away."));
                Send.SkillUseSilentCancel(creature);
                return;
            }

            // Check distance to other stones
            var otherStones = region.GetProps(a => a.HasTag("/guildstone/") && a.GetPosition().InRange(pos, MinStoneDistance));

            if (otherStones.Count != 0)
            {
                creature.Unlock(Locks.Walk | Locks.Run);

                Send.Notice(creature, Localization.Get("You're too close to another Guild Stone to put yours up."));
                Send.SkillUseSilentCancel(creature);
                return;
            }

            // Check street
            if (creature.Region.IsOnStreet(pos))
            {
                Send.Notice(creature, Localization.Get("You can't place a Guild Stone on the street."));
                Send.SkillUseSilentCancel(creature);
                return;
            }

            // Place stone (from complete)
            creature.Skills.Callback(skill.Info.Id, () =>
            {
                guild.Stone.PropId    = GuildStonePropId.Normal;
                guild.Stone.RegionId  = region.Id;
                guild.Stone.X         = pos.X;
                guild.Stone.Y         = pos.Y;
                guild.Stone.Direction = MabiMath.ByteToRadian(creature.Direction);

                ChannelServer.Instance.GuildManager.SetStone(guild);

                Send.Notice(NoticeType.Top, 20000, Localization.Get("{0} Guild has been formed. Guild Leader : {1}"), guild.Name, guild.LeaderName);

                creature.Inventory.Remove(63041);                 // Guild Stone Installation Permit
            });

            // TODO: Skills that don't necessarily end in Use need a way to get
            //   back to Ready, we currently don't properly support that.
            //   Use will probably require a return value, like Prepare.
            //   Temporary solution: working with stacks.
            skill.Stacks = 0;

            Send.Echo(creature, Op.SkillUse, packet);
        }