Esempio n. 1
0
 public EventEngine(MapleCharacter starter, string script, int recreateMap = -1, bool skipSpawn = false)
 {
     Starter   = starter;
     ChannelId = Starter.Client.Channel;
     if (!(DataBuffer.EventScripts.TryGetValue(script, out EventType) && EventType != null))
     {
         return;
     }
     EventInstance = ScriptActivator.CreateScriptInstance(EventType, script, starter) as EventScript;
     if (EventInstance == null)
     {
         string error = string.Format("Error loading {0} {1}", "EventScript", script);
         ServerConsole.Error(error);
         FileLogging.Log("Event scripts", error);
         return;
     }
     RecreatedMap                     = recreateMap != -1;
     EventInstance.OnFinish          += new Action(FinishEvent);
     EventInstance.OnSpawnMobs       += new Action <int, int, int, int>(SpawnMobs);
     EventInstance.OnRandomSpawnMobs += new Action <int, int, Point, Point>(RandomSpawnMobs);
     if (RecreatedMap)
     {
         EventMap = new MapleEvent(recreateMap, DataBuffer.GetMapById(recreateMap), skipSpawn);
         EventId  = Program.RegisterEvent(EventMap);
         if (Starter != null)
         {
             AddCharacter(Starter);
         }
     }
 }
Esempio n. 2
0
 public bool ExecuteScriptForNpc()
 {
     if (ScriptInstance == null)
     {
         return(false);
     }
     try
     {
         if (IsShop)
         {
             Client.SendPacket(Packets.ShowShop((ShopScript)ScriptInstance, NpcId));
         }
         ScriptInstance.Execute();
         return(true);
     }
     catch (Exception ex)
     {
         string errorString = string.Format("NpcId: {0}\r\nState: {1}\r\n Selection: {2}\r\nException: {3}", NpcId, ScriptInstance.State, ScriptInstance.Selection, ex);
         ServerConsole.Debug("Npc script execution error: " + errorString);
         FileLogging.Log("Npc scripts", errorString);
         SendOk("An error occured, please report this on the forums\r\nNpcId: " + NpcId);
         Dispose();
         return(false);
     }
 }
Esempio n. 3
0
 internal void RecvPacket(PacketReader packet)
 {
     try
     {
         RecvPacketHandler.Handle(packet, this);
     }
     catch (Exception e)
     {
         ServerConsole.Error(e.ToString());
         FileLogging.Log("PacketExceptions.txt", e.ToString());
     }
 }
Esempio n. 4
0
        public static void HandleReturnScroll(MapleClient c, PacketReader pr)
        {
            MapleCharacter chr = c.Account.Character;

            if (!chr.DisableActions())
            {
                return;
            }
            int tickCount = pr.ReadInt();

            pr.Skip(2); //Unk
            int itemId = pr.ReadInt();

            if (!chr.Inventory.HasItem(itemId))
            {
                return;
            }
            WzConsume item = DataBuffer.GetItemById(itemId) as WzConsume;

            if (item == null)
            {
                return;
            }

            if (item.MoveTo > 0)
            {
                int toMap = 0;
                toMap = item.MoveTo == 999999999 ? chr.Map.ReturnMap : item.MoveTo;
                if (toMap != 0)
                {
                    MapleMap map = Program.GetChannelServer(c.Channel).GetMap(toMap);
                    if (map == null || map.PortalScrollLimit)
                    {
                        return;
                    }
                    if (chr.Inventory.RemoveItemsById(itemId, 1))
                    {
                        chr.ChangeMap(toMap);
                    }
                }
            }
            else
            {
                string msg = "Unhandled return scroll: " + itemId;
                ServerConsole.Warning(msg);
                FileLogging.Log("Unhandled items", msg);
                chr.EnableActions();
            }
        }
Esempio n. 5
0
        public static void Handle(MapleClient c, PacketReader pr)
        {
            try
            {
                if (c.Account == null)
                {
                    c.Disconnect("Client is not logged in to an account");
                    return;
                }

                string pic         = pr.ReadMapleString();
                int    characterId = pr.ReadInt();
                pr.Skip(1);
                string macs     = pr.ReadMapleString();
                string clientid = pr.ReadMapleString();
                if (c.Account.CheckPic(pic) && c.Account.HasCharacter(characterId) && Program.ChannelServers.ContainsKey(c.Channel))
                {
                    ushort port = Program.ChannelServers[c.Channel].Port;
                    c.Account.MigrationData.CharacterId      = characterId;
                    c.Account.MigrationData.Character        = MapleCharacter.LoadFromDatabase(characterId, false);
                    c.Account.MigrationData.Character.Hidden = c.Account.IsGM;

                    Program.EnqueueMigration(characterId, c.Account.MigrationData);

                    c.SendPacket(ChannelIpPacket(port, characterId));
                }
                else
                {
                    //Incorrect Pic
                    PacketWriter pw = new PacketWriter();
                    pw.WriteHeader(SendHeader.PICResponse);
                    pw.WriteByte(0x14);
                    c.SendPacket(pw);
                }
            }
            catch (Exception ex)
            {
                ServerConsole.Error(ex.ToString());
                FileLogging.Log("Character loading", ex.ToString());
                c.SendPacket(MapleCharacter.ServerNotice("Error loading character", 1));

                /*PacketWriter pw = new PacketWriter();
                 * pw.WriteHeader(SendHeaders.PICResponse);
                 * pw.WriteByte(0x15);
                 * c.SendPacket(pw);*/
            }
        }
Esempio n. 6
0
        public static void Handle(MapleClient c, PacketReader pr)
        {
            if (pr.Available > 8)
            {
                short  type       = pr.ReadShort();
                string typeString = "Unknown";
                if (type == 0x01)
                {
                    typeString = "SendBackupPacket";
                }
                else if (type == 0x02)
                {
                    typeString = "Crash Report";
                }
                else if (type == 0x03)
                {
                    typeString = "Exception";
                }

                int errorType = pr.ReadInt();
                //if (errorType == 0) //Usually some bounceback to login
                //return;

                short dataLength = pr.ReadShort();
                pr.Skip(4);
                int header = pr.ReadShort();

                string headerName  = Enum.GetName(typeof(SendHeader), header) + String.Format(" : {0}", header.ToString("X"));
                string accountName = c.Account.Name;
                string playerName  = "N/A (not logged in yet)";
                if (c.Account.Character != null)
                {
                    playerName = c.Account.Character.Name;
                    //TODO: map id
                }
                string remainingBytes = pr.ToString(true);
                string errorString    = String.Format("Error Type: {0}\r\nData Length: {1}\r\nError for player:{2} - account: {3}\r\nHeader: {4}\r\nData: {5}", typeString, dataLength, playerName, accountName, headerName, remainingBytes);

                FileLogging.Log("ErrorCodes.txt", errorString);
                ServerConsole.Warning("Error 38 caused by: " + headerName);
            }
        }
Esempio n. 7
0
        public NpcEngine(MapleClient c, int id)
        {
            Client = c;
            NpcId  = id;
            Type npcT;

            if (DataBuffer.NpcScripts.TryGetValue(NpcId, out npcT) && npcT != null)
            {
                ScriptInstance = ScriptActivator.CreateScriptInstance(npcT, npcT.ToString(), c.Account.Character) as NpcScript;
                if (ScriptInstance == null)
                {
                    string error = string.Format("Error loading {0} {1}", "NpcScript", npcT.ToString());
                    ServerConsole.Error(error);
                    FileLogging.Log("Npc scripts", error);
                    return;
                }
                if (ScriptInstance.IsShop)
                {
                    IsShop = true;
                }
                else
                {
                    ScriptInstance.SendOk       = new Action <string>(SendOk);
                    ScriptInstance.SendNext     = new Action <string>(SendNext);
                    ScriptInstance.SendPrev     = new Action <string>(SendPrev);
                    ScriptInstance.SendNextPrev = new Action <string>(SendNextPrev);
                    ScriptInstance.SendSimple   = new Action <string>(SendSimple);
                    ScriptInstance.EndChat      = new Action(Dispose);
                    ScriptInstance.SendYesNo    = new Action <string>(SendYesNo);
                    ScriptInstance.SendAskText  = new Action <string, int, int, string>(SendAskText);
                }
            }
            else
            {
                SendOk(string.Format(@"An error has occured in my script. Please report this as a bug\r\nNpcId: {0}", NpcId));
                ServerConsole.Debug(string.Format(@"Missing script for NPC: {0}", NpcId));
                ScriptInstance = null;
                c.Account.Character.EnableActions();
            }
        }
Esempio n. 8
0
 public static void EnterScriptedPortal(WzMap.Portal portal, MapleCharacter character)
 {
     if (!string.IsNullOrEmpty(portal.Script))
     {
         Type portalScriptType;
         if (DataBuffer.PortalScripts.TryGetValue(portal.Script, out portalScriptType) && portalScriptType != null)
         {
             PortalScript scriptInstance = Activator.CreateInstance(portalScriptType) as PortalScript;
             if (scriptInstance == null)
             {
                 string error = string.Format("Error loading {0} {1}", "PortalScript", portal.Script);
                 ServerConsole.Error(error);
                 FileLogging.Log("Portal scripts", error);
                 return;
             }
             scriptInstance.Character = new ScriptCharacter(character, portal.Script);
             try
             {
                 scriptInstance.Execute();
             }
             catch (Exception e)
             {
                 string error = string.Format("Script: {0} error: {1}", portal.Script, e);
                 FileLogging.Log("Portal scripts", error);
                 ServerConsole.Debug("Portal script execution error: " + error);
                 character.EnableActions();
             }
         }
         else
         {
             character.SendBlueMessage(string.Format("This portal is not coded yet (mapId: {0}, portalId: {1}, script name: {2})", character.MapId, portal.Id, portal.Script));
             character.EnableActions();
         }
     }
     else
     {
         character.EnableActions();
     }
 }
Esempio n. 9
0
        public static List <MapleMovementFragment> Parse(PacketReader pr)
        {
            List <MapleMovementFragment> movementList = new List <MapleMovementFragment>();
            byte movements = pr.ReadByte();

            for (int i = 0; i < movements; i++)
            {
                byte type = pr.ReadByte();
                switch (type)//completely changed by alonevampire
                {
                case 0x00:
                case 0x08:
                case 0x0F:
                case 0x12:
                case 0x17:
                case 0x3A:
                case 0x3B:
                case 0x3C:
                {
                    Point position    = pr.ReadPoint();
                    Point wobble      = pr.ReadPoint();
                    short fh          = pr.ReadShort();
                    short fhFallStart = 0;
                    Point offset      = new Point();
                    if (type == 0xF)
                    {
                        fhFallStart = pr.ReadShort();
                    }
                    if (type != 0x3A)
                    {
                        offset = pr.ReadPoint();
                    }
                    byte  state    = pr.ReadByte();
                    short duration = pr.ReadShort();

                    AbsoluteLifeMovement alm = new AbsoluteLifeMovement(type, position, state, duration, wobble, offset, fh, fhFallStart);
                    movementList.Add(alm);
                    break;
                }

                case 0x01:
                case 0x02:
                case 0x10:
                case 0x13:
                case 0x14:
                case 0x16:
                case 0x36:
                case 0x37:
                case 0x38:
                case 0x39:
                {
                    Point position    = pr.ReadPoint();
                    short fhFallStart = 0;
                    if (type == 19 || type == 20)
                    {
                        fhFallStart = pr.ReadShort();
                    }

                    byte  state    = pr.ReadByte();
                    short duration = pr.ReadShort();

                    RelativeLifeMovement rlm = new RelativeLifeMovement(type, position, state, duration, fhFallStart);
                    movementList.Add(rlm);
                    break;
                }

                case 0x03:
                case 0x04:
                case 0x05:
                case 0x06:
                case 0x07:
                case 0x09:
                case 0x0A:
                case 0x0B:
                case 0x0D:
                case 0x18:
                case 0x19:
                case 0x31:
                case 0x32:
                case 0x33:
                case 0x35:
                {
                    Point position = pr.ReadPoint();
                    short fh       = pr.ReadShort();
                    byte  state    = pr.ReadByte();
                    short duration = pr.ReadShort();

                    TeleportMovement tm = new TeleportMovement(type, position, state, duration, fh);
                    movementList.Add(tm);
                    break;
                }

                case 0x1B:
                case 0x1C:
                case 0x1D:
                case 0x1E:
                case 0x1F:
                case 0x20:
                case 0x21:
                case 0x22:
                case 0x23:
                case 0x24:
                case 0x25:
                case 0x26:
                case 0x27:
                case 0x28:
                case 0x29:
                case 0x2A:
                case 0x2B:
                case 0x2C:
                case 0x2D:
                case 0x2E:
                case 0x2F:
                case 0x30:
                case 0x34:
                {
                    byte  state    = pr.ReadByte();
                    short duration = pr.ReadShort();

                    GroundMovement gm = new GroundMovement(type, new Point(), state, duration);
                    movementList.Add(gm);
                    break;
                }

                case 0x0E:
                {
                    Point          wobble      = pr.ReadPoint();
                    short          fhFallStart = pr.ReadShort();
                    byte           state       = pr.ReadByte();
                    short          duration    = pr.ReadShort();
                    WobbleMovement m           = new WobbleMovement(type, wobble, fhFallStart, state, duration);
                    movementList.Add(m);
                }
                break;

                case 0x0C:
                {
                    byte wui = pr.ReadByte();
                    ChangeEquipMovement cem = new ChangeEquipMovement(type, wui);
                    movementList.Add(cem);
                    break;
                }

                default:
                    ServerConsole.Warning("Unknown movement type: {0} - Data:\r\n{1}", type, pr.ToString(true));
                    FileLogging.Log("MovementLog.txt", String.Format("Unknown movement type: {0} - Position: {1} - Data:\r\n{2}", type, pr.Position, pr.ToString()));
                    return(null);
                }
            }

            if (movements != movementList.Count) //probably hack
            {
                string packet = pr.ToString();
                FileLogging.Log("MovementLog.txt", String.Format("Movement count mismatch in packet {0} Data:\r\n{1}", packet.Substring(0, 5), packet));
                return(null);
            }

            return(movementList);
        }
        public static void Handle(MapleClient c, PacketReader pr)
        {
            MapleCharacter chr = c.Account.Character;

            try
            {
                if (c.NpcEngine == null || c.NpcEngine.ScriptInstance == null)
                {
                    if (chr.ActionState == ActionState.NpcTalking)
                    {
                        chr.EnableActions();
                    }
                    return;
                }
                int objectId = c.NpcEngine.ScriptInstance.ObjectId;
                if (objectId != -1) //objectId == -1 when npc conversation was started by the server, so players can talk to NPCs that are not on their map (with commands etc)
                {
                    WzMap.Npc npc = chr.Map.GetNpc(objectId);
                    if (npc == null)
                    {
                        c.NpcEngine.ScriptInstance = null;
                        return;
                    }
                }
                byte type = pr.ReadByte();
                byte next = pr.ReadByte();
                if (next == 0xFF) //End Chat
                {
                    c.NpcEngine.Dispose();
                    return;
                }
                if (next == 0 && (type != 2))
                {
                    c.NpcEngine.ScriptInstance.State -= 1;
                }
                else
                {
                    c.NpcEngine.ScriptInstance.State += 1;
                }
                bool execute = false;
                switch (type)
                {
                case 0:     //SendOk, SendPrev, SendNext
                    execute = true;
                    break;

                case 2:     //SendYesNo
                    execute = true;
                    c.NpcEngine.ScriptInstance.Selection = next == 0 ? 0 : 1;
                    break;

                case 3:    //SendAskText
                    if (next == 0)
                    {
                        execute = false;
                    }
                    else
                    {
                        execute = true;
                        string text = pr.ReadMapleString();
                        c.NpcEngine.ScriptInstance.InText = text;
                    }
                    break;

                case 4:     //SendGetNumber
                    //Player.GetNpcStatus().Num = pr.ReadInt();
                    execute = true;
                    break;

                case 5:     //SendSimple
                    if (next == 0)
                    {
                        execute = false;
                    }
                    else
                    {
                        if (pr.Available >= 4)
                        {
                            c.NpcEngine.ScriptInstance.Selection = pr.ReadInt();     //This can be int as well, decided by the client
                        }
                        else if (pr.Available >= 1)
                        {
                            c.NpcEngine.ScriptInstance.Selection = pr.ReadSByte();
                        }
                        execute = true;
                    }
                    break;

                case 23:     //Choose Job
                    int choice = pr.ReadInt();

                    break;

                default:
                    string msg = "Unknown Npc chat type: " + pr.ToString();
                    ServerConsole.Error(msg);
                    FileLogging.Log("NPC chat type", msg);
                    c.NpcEngine.ScriptInstance = null;
                    break;
                }
                if (execute)
                {
                    NpcEngine engine = c.NpcEngine;
                    if (engine == null)
                    {
                        if (c.Account.Character.ActionState == ActionState.NpcTalking)
                        {
                            c.Account.Character.EnableActions();
                        }
                        return;
                    }
                    engine.ExecuteScriptForNpc();
                }
                else
                {
                    c.NpcEngine.ScriptInstance = null;
                    if (chr.ActionState == ActionState.NpcTalking)
                    {
                        chr.EnableActions();
                    }
                }
            }
            catch (Exception ex)
            {
                ServerConsole.Error("NpcChatMoreHandler.Handle : " + ex.ToString());
                if (c.NpcEngine != null)
                {
                    c.NpcEngine.ScriptInstance = null;
                }
                if (chr.ActionState == ActionState.NpcTalking)
                {
                    chr.EnableActions();
                }
            }
        }
Esempio n. 11
0
        public static bool CheckAndApplySkillEffect(MapleCharacter chr, int skillId, WzCharacterSkill wzCharacterSkill, int skillLevel = -1, int numTargets = 0, int numAttacks = 0)
        {
            if (skillLevel == -1)
            {
                skillLevel = chr.GetSkillLevel(skillId);
            }

            if (wzCharacterSkill == null)
            {
                wzCharacterSkill = DataBuffer.GetCharacterSkillById(skillId);
                if (wzCharacterSkill == null)
                {
                    return(false);
                }
            }

            if (wzCharacterSkill.HasFixedLevel && JobConstants.JobCanLearnSkill(skillId, chr.Job))
            {
                skillLevel = 1;
            }

            if (chr.IsPhantom) //check stolen skill level
            {
                PhantomSystem resource         = (PhantomSystem)chr.Resource;
                int           chosenSkillIndex = resource.GetChosenSkillIndex(skillId);
                if (chosenSkillIndex > -1)
                {
                    int impeccableMemory = PhantomSystem.GetStealSkill(chosenSkillIndex + 1);
                    skillLevel = Math.Min(chr.GetSkillLevel(impeccableMemory), chr.GetSkillLevel(skillId));
                }
            }


            if (skillLevel == 0 || (chr.HasSkillOnCooldown(skillId)))
            {
                string text = "Player tried using skill " + skillId + " while level 0 or on cooldown.";
                ServerConsole.Warning(text);
                FileLogging.Log("./LinkedSkills.txt", text);
                return(false);
            }

            SkillEffect effect = wzCharacterSkill.GetEffect((byte)skillLevel);

            if (effect == null)
            {
                return(false);
            }

            bool shadowPartner = false;

            if (numTargets > 0)
            {
                int attackCount = effect.AttackCount;
                if (chr.IsLuminous ||
                    (chr.IsBandit && chr.HasBuff(ChiefBandit.SHADOW_PARTNER)) ||
                    (chr.IsAssassin && chr.HasBuff(Hermit.SHADOW_PARTNER)) ||
                    (chr.IsNightWalker && chr.HasBuff(NightWalker3.SHADOW_PARTNER)))
                {
                    attackCount  *= 2;
                    shadowPartner = true;
                }
                if (effect.MobCount < numTargets || attackCount < numAttacks)
                {
                    return(false);
                }
            }

            int bulletConsume;

            if (effect.Info.TryGetValue(CharacterSkillStat.bulletConsume, out bulletConsume))
            {
                if (shadowPartner)
                {
                    bulletConsume *= 2;
                }
                if (!DealDamageHandler.HandleRangedAttackAmmoUsage(chr, bulletConsume))
                {
                    ServerConsole.Warning("Character with job: " + chr.Job + " tried using a skill with bulletCount: " + bulletConsume + " but doesn't have the bullets!");
                    return(false);
                }
            }

            if (chr.Mp < effect.MpCon)
            {
                return(false);
            }
            else
            {
                chr.AddMP(-effect.MpCon);
            }

            int hpCon;

            if (effect.Info.TryGetValue(CharacterSkillStat.hpCon, out hpCon))
            {
                if (chr.Hp < hpCon)
                {
                    return(false);
                }
                chr.AddHP(-hpCon);
            }

            #region Manual skill handlers and checks
            if (chr.IsAran && effect.Info.ContainsKey(CharacterSkillStat.aranComboCon))
            {
                if (!AranSystem.HandleComboUsage(chr, effect.Info[CharacterSkillStat.aranComboCon]))
                {
                    return(false);
                }
            }
            else if (chr.IsLuminous && chr.Job >= JobConstants.LUMINOUS2 && effect.Info.ContainsKey(CharacterSkillStat.gauge))
            {
                LuminousSystem.HandleGaugeGain(chr, skillId, effect.Info[CharacterSkillStat.gauge]);
            }

            switch (skillId)
            {
            case Berserker.EVIL_EYE_OF_DOMINATION:
            {
                Buff        evilEyeBuff = chr.GetBuff(Spearman.EVIL_EYE);
                MapleSummon evilEye     = chr.GetSummon(Spearman.EVIL_EYE);
                if (evilEyeBuff == null || evilEye == null)
                {
                    return(false);
                }
                uint timeUsed        = (uint)((DateTime.UtcNow.Subtract(evilEyeBuff.StartTime)).TotalMilliseconds);
                uint timeRemainingMS = (uint)evilEyeBuff.Duration - timeUsed;
                Buff newBuff         = new Buff(Spearman.EVIL_EYE, effect, timeRemainingMS, chr);
                if (evilEyeBuff.Stacks == Berserker.EVIL_EYE_OF_DOMINATION)
                {
                    newBuff.Stacks       = Spearman.EVIL_EYE;
                    evilEye.MovementType = SummonMovementType.Follow;
                }
                else
                {
                    newBuff.Stacks       = Berserker.EVIL_EYE_OF_DOMINATION;
                    evilEye.MovementType = SummonMovementType.CircleFollow;
                }
                chr.GiveBuff(newBuff);
                return(true);    //no other actions needed
            }

            case Berserker.EVIL_EYE_SHOCK:
            {
                MapleSummon evilEye = chr.GetSummon(Spearman.EVIL_EYE);
                if (evilEye == null)
                {
                    return(false);
                }
                List <MapleMonster> mobs = chr.Map.GetMobsInRange(new BoundingBox(evilEye.Position, wzCharacterSkill.TopLeft, wzCharacterSkill.BottomRight));
                if (mobs.Count > 0)
                {
                    int damage     = (int)((effect.Info[CharacterSkillStat.damage] / 100.0) * chr.Stats.GetDamage());
                    int stunProp   = effect.Info[CharacterSkillStat.prop];
                    int stunTime   = effect.Info[CharacterSkillStat.time] * 1000;
                    int mobCounter = 0;
                    foreach (MapleMonster mob in mobs)
                    {
                        mob.Damage(chr, damage);
                        if (mob.Alive)
                        {
                            if (Functions.MakeChance(stunProp))
                            {
                                mob.ApplyStatusEffect(skillId, MonsterBuffStat.STUN, 1, stunTime, chr);
                            }
                        }
                        mobCounter++;
                        if (mobCounter == 10)
                        {
                            break;
                        }
                    }
                }
                break;
            }

            case DarkKnight.SACRIFICE:
                if (!chr.RemoveSummon(Spearman.EVIL_EYE))
                {
                    return(false);
                }
                chr.CancelBuff(Spearman.EVIL_EYE);
                int healHpR = effect.Info[CharacterSkillStat.y];
                int heal    = (int)((healHpR / 100.0) * chr.Stats.MaxHp);
                chr.AddHP(heal);
                break;

            case LuminousBasics.SUNFIRE:
            case LuminousBasics.ECLIPSE:
            case LuminousBasics.EQUILIBRIUM2:
                LuminousSystem.HandleChangeDarkLight(chr, skillId);
                break;
            }
            #endregion

            #region Apply Cooldown

            bool skipCooldown = skillId == DarkKnight.GUNGNIRS_DESCENT && (chr.HasBuff(DarkKnight.SACRIFICE) || chr.HasBuff(DarkKnight.FINAL_PACT2));

            if (!skipCooldown)
            {
                int coolTime;
                if (effect.Info.TryGetValue(CharacterSkillStat.cooltime, out coolTime) && coolTime > 0)
                {
                    chr.AddCooldown(skillId, (uint)coolTime * 1000); //time in the wz is in seconds
                }
            }
            #endregion

            effect.ApplyEffect(chr, chr);

            if (wzCharacterSkill.IsBuff)
            {
                effect.ApplyBuffEffect(chr);
                chr.Map.BroadcastPacket(SkillEffect.Packets.ShowForeignSkillEffect(chr.Id, chr.Level, skillId, effect.Level), chr);
            }

            if (wzCharacterSkill.IsPartySkill)
            {
                if (chr.Party != null)
                {
                    List <MapleCharacter> partyMembersOnSameMap = chr.Party.GetCharactersOnMap(chr.Map, chr.Id);
                    if (partyMembersOnSameMap.Count > 0)
                    {
                        List <MapleCharacter> partyMembersInRange = chr.Map.GetCharactersInRange(effect.CalculateBoundingBox(chr.Position, chr.IsFacingLeft), partyMembersOnSameMap);
                        foreach (MapleCharacter partyMember in partyMembersInRange)
                        {
                            effect.ApplyEffect(chr, partyMember);
                            if (wzCharacterSkill.IsBuff)
                            {
                                effect.ApplyBuffEffect(partyMember);
                            }
                        }
                    }
                }
                else if (wzCharacterSkill.IsGmSkill && chr.IsStaff)
                {
                    var targets = chr.Map.GetCharactersInRange(effect.CalculateBoundingBox(chr.Position, chr.IsFacingLeft));
                    foreach (MapleCharacter target in targets.Where(x => x.Id != chr.Id))
                    {
                        effect.ApplyEffect(chr, target);
                        if (wzCharacterSkill.IsBuff)
                        {
                            effect.ApplyBuffEffect(target);
                        }
                    }
                }
            }
            return(true);
        }