Exemple #1
0
        private void DecodeAttackInfo(CInPacket p)
        {
            for (int i = 0; i < nMobCount; i++)
            {
                var info = new AttackEntry();

                info.dwMobID = p.Decode4();

                info.nHitAction  = p.Decode1();
                info.nForeAction = p.Decode1();                //  COutPacket::Encode1(&v468, v376->nForeAction & 0x7F | (v181 << 7));
                info.nFrameIdx   = p.Decode1();

                // v218 = CMob::GetCurTemplate(v378->pMob)
                //    && (v166 = CMob::GetTemplate(v378->pMob), v166 != CMob::GetCurTemplate(v378->pMob));
                // v167 = (_BYTE)v218 << 7;

                info.CalcDamageStatIndex = p.Decode1(); // COutPacket::Encode1(&v460, v168 & 0x7F | v167);

                p.Skip(8);                              // position info

                info.tDelay = p.Decode2();

                for (int j = 0; j < nDamagePerMob; j++)
                {
                    info.aDamage[j] = Math.Max(0, p.Decode4());

                    //Log.Debug($"[Damaging Mob] dwMobID: {info.dwMobID} aDamage: {info.aDamage[j]}");
                }

                p.Skip(4);                 // CMob::GetCrc

                aAttackInfo[i] = info;
            }
        }
Exemple #2
0
        /// <summary>
        /// Not yet working
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public static AttackInfo ParseMelee(CInPacket p)
        {
            AttackInfo ret = new AttackInfo();

            ret.portals = p.Decode1();

            bool unkk = p.Decode1() == 0xFF;

            p.Skip(unkk ? 7 : 8);

            ret.tbyte   = p.Decode1();
            ret.targets = (byte)((ret.tbyte >> 4) & 0xF);
            ret.hits    = (byte)(ret.tbyte & 0xF);

            p.Skip(8); //-1

            ret.skill = p.Decode4();
            p.Skip(1); // 0.94
            p.Skip(4); // 0.74
            p.Skip(4); // 0.74
            p.Skip(8); // 0.88 (0)

            switch (ret.skill)
            {
            case 5101004:     // Corkscrew
            case 15101003:    // Cygnus corkscrew
            case 5201002:     // Grenade
            case 14111006:    // Poison bomb
            case 4341002:     // Final Cut
            case 4341003:     // Monster Bomb
                ret.charge = p.Decode4();
                break;

            default:
                ret.charge = 0;
                break;
            }

            ret.display   = p.Decode1(); // Always zero?
            ret.direction = p.Decode1();
            ret.stance    = p.Decode1();
            p.Skip(4);
            p.Skip(1);                             // Weapon class
            ret.speed = p.Decode1();               // Confirmed
            ret.lastAttackTickCount = p.Decode4(); // Ticks
            p.Skip(4);                             //0

            ret.allDamage = new List <AttackPair>();

            //if (ret.skill == 4211006)
            //{ // Meso Explosion
            //    return parseMesoExplosion(lea, ret);
            //}

            for (int i = 0; i < ret.targets; i++)
            {
                var mobId   = p.Decode4();
                var atkPair = new AttackPair(mobId);

                p.Skip(14);

                for (int j = 0; j < ret.hits; j++)
                {
                    var damage = p.Decode4();
                    atkPair.Attack.Add(new Tuple <int, bool>(damage, false));

                    Logger.Write(LogLevel.Debug, "Attack Mob {0} Dmg {1}", mobId, damage);
                }

                p.Skip(4); // CRC of monster [Wz Editing]
                ret.allDamage.Add(atkPair);
            }

            ret.position = p.DecodePos();

            return(ret);
        }
Exemple #3
0
        //nType:
        //
        public static MapleAttackNew Parse(CInPacket p, int nType)
        {
            MapleAttackNew ret = new MapleAttackNew();

            p.Skip(8); // -1

            ret.tByte1        = p.Decode1();
            ret.nDamagePerMob = (byte)(ret.tByte1 & 0xF);
            ret.nMobCount     = (byte)((ret.tByte1 >> 4) & 0xF);

            p.Skip(8); //-1

            var v11 = p.Decode4();

            ret.nSkillID = v11;
            p.Skip(1); // 0.94
            p.Skip(4); // 0.74
            p.Skip(4); // 0.74
            p.Skip(8); // 0.88 (0)

            //is_keydown_skill
            if (v11 == 2121001 || v11 == 2221001 || v11 == 2321001 || v11 == 3221001 || v11 == 3121004)
            {
                ret.tKeyDown = p.Decode4();
            }
            else
            {
                ret.tKeyDown = -1;
            }

            /*
             * switch (ret.skill)
             * {
             *  case 5101004: // Corkscrew
             *  case 15101003: // Cygnus corkscrew
             *  case 5201002: // Grenade
             *  case 14111006: // Poison bomb
             *  case 4341002: // Final Cut
             *  case 4341003: // Monster Bomb
             *      ret.charge = p.Decode4();
             *      break;
             *  default:
             *      ret.charge = 0;
             *      break;
             * }
             */

            p.Decode1(); //  bFinalAfterSlashBlast | 8 * bShadowPartner | 16 * v674 | 32 * (nSerialAttackSkillID != 0) | ((_BYTE)v683 << 7));

            ret.tByte2  = p.Decode2();
            ret.bLeft   = (ret.tByte2 >> 15) & 1;
            ret.nAction = ret.tByte2 & 0x7FFF;
            p.Skip(4); //CRC i think
            ret.nAttackActionType = p.Decode1();
            ret.nAttackSpeed      = p.Decode1();

            ret.tAttackTime = p.Decode4();
            p.Skip(4); //bmage?

            //More decode for bullets here

            //if (ret.skill == 4211006)
            //{ // Meso Explosion
            //    return parseMesoExplosion(lea, ret);
            //}

            for (int i = 0; i < ret.nMobCount; i++)
            {
                var info = new AttackInfo();

                info.dwMobID = p.Decode4();

                //COutPacket::Encode1(&oPacket, v567->nHitAction);
                //todo fill the reste in
                p.Skip(14);

                for (int j = 0; j < ret.nDamagePerMob; j++)
                {
                    info.aDamage[j] = p.Decode4();

                    Logger.Write(LogLevel.Debug, "Attack Mob {0} Dmg {1}", info.dwMobID, info.aDamage[j]);
                }

                p.Skip(4); // CRC of monster [Wz Editing]

                ret.aAttackInfo[i] = info;
            }

            //ret.position = p.DecodePos();

            //if greneade read pos

            return(ret);
        }
Exemple #4
0
        public static void Handle_SkillUseRequest(WvsGameClient c, CInPacket p)
        {
            // Recv [CP_UserSkillUseRequest] [67 00] [86 1E 31 2F] [9B BA 3E 00] [14] 02 12 27 00 00 23 27 00 00 C2 01
            var dwTickCount = p.Decode4();
            var nSkillID    = p.Decode4();
            var nSLV        = p.Decode1();

            var pSkill = c.Character.Skills.Get(nSkillID, true);

            // do validation here so we dont need to validate in called functions
            if (pSkill is null || nSLV > pSkill.nSLV)
            {
                return;
            }

            if (SkillLogic.IsMobCaptureSkill(nSkillID))
            {
                ActiveSkill_MobCapture.Handle(nSkillID, nSLV, c.Character, p);
            }
            else if (SkillLogic.IsSummonCapturedMobSkill(nSkillID))
            {
                ActiveSkill_SummonMonster.Handle(nSkillID, nSLV, c.Character, p);
            }
            else if (SkillLogic.IsHookAndHitSkill(nSkillID))
            {
                ActiveSkill_HookAndHit.Handle(nSkillID, nSLV, c.Character, p);
            }
            else if (SkillLogic.IsSmokeShellSkill(nSkillID))
            {
                ActiveSkill_SmokeShell.Handle(nSkillID, nSLV, c.Character, p);
            }
            else if (SkillLogic.IsDamageMeterSkill(nSkillID, c.Character.Stats.nJob))
            {
                ActiveSkill_DamageMeter.Handle(nSkillID, nSLV, c.Character, p);
            }
            else if (SkillLogic.IsFlyingSkill(nSkillID, c.Character.Stats.nJob))
            {
                ActiveSkill_Flying.Handle(nSkillID, nSLV, c.Character, p);
            }
            else if (SkillLogic.IsClericHealSkill(nSkillID))
            {
                ActiveSkill_Heal.Handle(nSkillID, nSLV, c.Character, p);
            }
            else if (SkillLogic.IsOpenGateSkill(nSkillID))
            {
                ActiveSkill_OpenGate.Handle(nSkillID, nSLV, c.Character, p);
            }
            else if (SkillLogic.IsRecoveryAura(nSkillID))
            {
                ActiveSkill_RecoveryAura.Handle(nSkillID, nSLV, c.Character, p);
            }
            else if (SkillLogic.IsMysticDoorSkill(nSkillID, c.Character.Stats.nJob) || nSkillID == (int)Skills.PRIEST_MYSTIC_DOOR)
            {
                ActiveSkill_TownPortal.Handle(nSkillID, nSLV, c.Character, p);
            }
            else if (SkillLogic.IsStatChangeAdminSkill(nSkillID, c.Character.Stats.nJob))
            {
                ActiveSkill_StatChangeAdmin.Handle(nSkillID, nSLV, c.Character, p);
            }
            else if (pSkill.Template.IsSummonSkill && nSkillID != (int)Skills.BMAGE_REVIVE)
            {
                ActiveSkill_Summon.Handle(nSkillID, nSLV, c.Character, p);
            }
            else
            {
                var bLeft = false;

                if (pSkill.Template.is_antirepeat_buff_skill)
                {
                    var x = p.Decode2();
                    var y = p.Decode2();

                    bLeft = x < c.Character.Position.X;
                }

                //  Recv [CP_UserSkillUseRequest] [67 00] [4B 5E 91 0B] [CD 14 F9 01] 14

                var nSpiritJavelinItemID = 0;
                if (nSkillID == (int)Skills.NIGHTLORD_SPIRIT_JAVELIN)       //Spirit Claw
                {
                    nSpiritJavelinItemID = p.Decode4();                     //nSpiritJavelinItemID
                }
                if (pSkill.Template.is_event_vehicle_skill)
                {
                    p.Skip(1);                     // dwAffectedMemberBitmap

                    if (nSkillID == 2311001)
                    {
                        p.Skip(2);                         // tDelay
                    }
                }

                var nRemaining = p.Available - 2;

                if (nRemaining > 0)
                {
                    p.Skip(nRemaining);
                }

                //if (nRemaining > 0)
                //{
                //    var nMobCount = p.Decode1(); // nMobCount
                //    for (int i = 0; i < nMobCount; i++)
                //    {
                //        p.Decode4(); // adwMobID
                //    }
                //}

                var tDelay = p.Available >= 2 ? p.Decode2() : (short)0;                 // tDelay

                if (nSkillID == 0 || c.Character.Skills.Cast(nSkillID, bLeft, false, nSpiritJavelinItemID))
                {
                    new UserEffectPacket(UserEffect.SkillUse)
                    {
                        nSkillID = nSkillID,
                        nSLV     = nSLV
                    }.BroadcastEffect(c.Character, false);
                }
            }

            c.Character.Action.Enable();
        }
Exemple #5
0
        public void CreateMiniRoom(Character c, MR_Type nType, CInPacket p)
        {
            switch (nType)
            {
            case MR_Type.Omok:
                // todo
                break;

            case MR_Type.MemoryGame:
                // todo
                break;

            case MR_Type.TradingRoom:
                if (c.CurMiniRoom != null)
                {
                    c.SendPacket(CPacket.SystemMessage("You are already in a trade."));
                }
                else
                {
                    Log.Debug($"Adding trade mini room to field minirooms.");
                    Add(new CTradingRoom(c));
                }
                break;

            // Recv [CP_MiniRoom] 90 00 00 05 07 00 70 65 65 66 61 63 65 00 01 00 76 C0 4C 00
            case MR_Type.PersonalShop:
                c.SendMessage("no");
                break;

            case MR_Type.EntrustedShop:
            {
                // TODO check closeness to other shops
                var sTitle = p.DecodeString();
                p.Skip(3);         // TODO what is this
                var nShopTemplateId = p.Decode4();

                var(nItemSlot, pItem) = InventoryManipulator.GetAnyItem(c, InventoryType.Cash, nShopTemplateId);

                Log.Info($"Player [{c.Stats.sCharacterName}] attempting to create a shop with ItemID [{nShopTemplateId}] and Title [{sTitle}]");

                if (pItem == null || nItemSlot == 0)
                {
                    c.SendPacket(CPacket.SystemMessage("Invalid item or item slot."));         // packet editing?
                }
                else if (!c.Field.MapId.InRange(910000000, 910000023))
                {
                    c.SendPacket(CPacket.SystemMessage("Item does not work in this map."));
                }
                else if (!ItemConstants.is_entrusted_shop_item(pItem.nItemID))
                {
                    c.SendPacket(CPacket.SystemMessage("Invalid shop item."));         // packet editing??
                }
                else
                {
                    var pMiniRoom = new CEntrustedShop(c, nShopTemplateId, sTitle);

                    if (pMiniRoom.HasItems())
                    {
                        c.SendMessage("Please retrieve items from fredrick before opening a shop.");
                    }
                    else
                    {
                        //Add(pMiniRoom); // packet is sent in here
                    }
                }
                break;
            }

            case MR_Type.CashTradingRoom:
                // todo
                break;

            default:
                break;
            }
        }
Exemple #6
0
        public static void OnPacket(WvsGameClient c, CInPacket p)
        {
            var pChar     = c.Character;
            var pMiniRoom = pChar.CurMiniRoom;

            Log.Debug($"Begin Handle_MiniRoom");

            var opcode = p.Decode1();

            Log.Debug($"Operation: {opcode}");

            switch ((MR_Action)opcode)
            {
            case MR_Action.MRP_Create:
            {
                var type = p.Decode1();
                Log.Debug($"Create Type: {type}");
                c.Character.Field.MiniRooms.CreateMiniRoom(c.Character, (MR_Type)type, p);
                break;
            }

            case MR_Action.MRP_Invite:     // occurs in some but not all rooms (games, messenger, trade, not shops)
            {
                var dwTargetCharId = p.Decode4();
                Log.Debug($"Processing trade invite request to char ID {dwTargetCharId}");

                if (pMiniRoom is CTradingRoom room)
                {
                    room.HandleSendInvite(dwTargetCharId);
                }

                break;
            }

            case MR_Action.MRP_InviteResult:
            {
                if (pMiniRoom is CTradingRoom ctr)
                {
                    ctr.HandleDecline();
                }

                break;
            }

            case MR_Action.MRP_Enter:
            {
                var targetRoomId = p.Decode4();         // theres two more bytes after this which im curious to know what they do...
                // the extra bytes might be fm room?? for remote merchants??

                Log.Info($"DWID: {targetRoomId}");
                var room = pChar.Field.MiniRooms.FirstOrDefault(r => r.dwId == targetRoomId);
                // if remote merchant operations use this same packet process then it will not work because we're searching by field.. we'd need to search by a range of fields in the channel instead
                if (room is null)
                {
                    c.SendPacket(FailedEnterPacket());
                }
                else
                {
                    room?.HandleVisit(p, c);
                }

                break;
            }

            case MR_Action.MRP_Chat:
            {
                p.Skip(4);         // timestamp

                pChar.CurMiniRoom?.HandleChat(pChar, p.DecodeString());
                break;
            }

            case MR_Action.MRP_Leave:
            {
                pChar.CurMiniRoom?.HandlePlayerExit(pChar, MR_LeaveResult.UserRequest);
                break;
            }

            case MR_Action.ESP_WithdrawAll:     // owner close
            {
                if (pChar.CurMiniRoom is CEntrustedShop ces && ces.OwnerID == pChar.dwId)
                {
                    ces.WithdrawAll();
                    ces.HandlePlayerExit(pChar, MR_LeaveResult.UserRequest);
                    ces.Destroy();
                }
                break;
            }

            case MR_Action.MRP_Balloon:     // ?? these names lmao
            {
                if (pChar.CurMiniRoom is CEntrustedShop ces && pChar.CurMiniRoom.OwnerID == pChar.dwId)
                {
                    // pChar.Field.Broadcast(r.MakeEnterFieldPacket()); // gms spawns the shop after owner fills it with items

                    ces.ShopOpen      = true;
                    pChar.CurMiniRoom = null;
                }
                break;
            }

            case MR_Action.TRP_PutItem:
            {
                if (pChar.CurMiniRoom is CTradingRoom ctr)
                {
                    ctr.HandleAddItem(p, pChar);
                }
                break;
            }

            case MR_Action.TRP_PutMoney:
            {
                if (pChar.CurMiniRoom is CTradingRoom ctr)
                {
                    ctr.HandleSetMeso(pChar, p.Decode4());
                }
                break;
            }

            case MR_Action.TRP_Trade:
            {
                if (pChar.CurMiniRoom is CTradingRoom ctr)
                {
                    ctr.HandleConfirmTrade(pChar);
                }
                break;
            }

            case MR_Action.PSP_PutItem:
            case MR_Action.ESP_PutItem:
            {
                if (pChar.CurMiniRoom is CEntrustedShop ces && pChar.CurMiniRoom.OwnerID == pChar.dwId)
                {
                    ces.AddItem(p);
                }
                break;
            }

            case MR_Action.ESP_BuyItem:
            case MR_Action.PSP_BuyItem:
            {
                if (pChar.CurMiniRoom is CEntrustedShop ces)
                {
                    ces.SellItem(c.Character, p);
                }
                break;
            }

            case MR_Action.ESP_Refresh:
            case MR_Action.PSP_Refresh:
            {
                if (pChar.CurMiniRoom is CEntrustedShop ces)
                {
                    ces.Refresh(pChar);
                }
                break;
            }

            case MR_Action.ESP_MoveItemToInventory:
            case MR_Action.PSP_MoveItemToInventory:
            {
                if (pChar.CurMiniRoom is CEntrustedShop ces)
                {
                    ces.RemoveItem(p);
                }
                break;
            }

            case MR_Action.PSP_Ban:
            case MR_Action.MGRP_Ban:
            {
                if (pChar.CurMiniRoom is CEntrustedShop ces && pChar.CurMiniRoom.OwnerID == pChar.dwId)
                {
                    //ces.BanPlayer(p.DecodeString());
                }
                break;
            }

            case MR_Action.ESP_ArrangeItem:
            {
                if (pChar.CurMiniRoom is CEntrustedShop ces && pChar.CurMiniRoom.OwnerID == pChar.dwId)
                {
                    ces.ArrangeItems();
                }
                break;
            }

            case MR_Action.ESP_DeliverVisitList:
            {
                if (pChar.CurMiniRoom is CEntrustedShop ces && pChar.CurMiniRoom.OwnerID == pChar.dwId)
                {
                    ces.DeliverVisitList();
                }
                break;
            }

            case MR_Action.ESP_DeliverBlackList:
            case MR_Action.PSP_DeliverBlackList:
            {
                if (pChar.CurMiniRoom is CEntrustedShop ces && pChar.CurMiniRoom.OwnerID == pChar.dwId)
                {
                    ces.DeliverBlackList();
                }
                break;
            }

            case MR_Action.ESP_AddBlackList:
            case MR_Action.PSP_AddBlackList:
            {
                if (pChar.CurMiniRoom is CEntrustedShop ces && pChar.CurMiniRoom.OwnerID == pChar.dwId)
                {
                    ces.AddBlackList(p);
                }
                break;
            }

            case MR_Action.PSP_DeleteBlackList:
            case MR_Action.ESP_DeleteBlackList:
            {
                if (pChar.CurMiniRoom is CEntrustedShop ces && pChar.CurMiniRoom.OwnerID == pChar.dwId)
                {
                    ces.DeleteBlackList(p);
                }
                break;
            }

            default:
                Log.Info($"Unhandled MiniRoom packet. OpCode: {opcode}.");
                Log.Info($"Full packet: {BitConverter.ToString(p.ToArray()).Replace("-", " ")}");
                break;
            }
            pChar.Action.Enable();
        }
Exemple #7
0
        public static MapleAttack ParseShoot(CInPacket p, Character c)
        {
            MapleAttack ret = new MapleAttack();

            p.Skip(8);             // -1

            var tByte1 = p.Decode1();

            ret.nDamagePerMob = (byte)(tByte1 & 0xF);
            ret.nMobCount     = (byte)((tByte1 >> 4) & 0xF);

            //c.SendMessage("Damage per mob " + ret.nDamagePerMob);
            //c.SendMessage("Mob count " + ret.nMobCount);

            p.Skip(8);                  //-1

            ret.nSkillID = p.Decode4(); //2017

            ret.ValidateSkill(c);

            if (!ret.bValidAttack)
            {
                return(ret);
            }

            var skillTemplate = MasterManager.SkillTemplates[ret.nSkillID];

            var nCombatOrders = p.Decode1(); // nCombatOrders

            p.Skip(4);                       // get_rand(pDrInfo.dr0, 0);
            p.Skip(4);                       // CCrc32::GetCrc32(pData, 4u, n, 0, 0);
            p.Skip(8);

            ret.tKeyDown = skillTemplate?.is_keydown_skill ?? false?p.Decode4() : -1;

            ret.nOption = p.Decode1();             //COutPacket::Encode1(&v498, (bSpark << 7) | (bSpiritJavelin << 6) | 8 * bShadowPartner | 4 * bMortalBlow | 2 * bSoulArrow);

            var bSpark         = (ret.nOption & 0x80) != 0;
            var bSpiritJavelin = (ret.nOption & 0x40) != 0;
            var bSerial        = (ret.nOption & 0x20) != 0;
            var bShadowPartner = (ret.nOption & 0x8) != 0;
            var bMortalBlow    = (ret.nOption & 0x4) != 0;
            var bSoulArrow     = (ret.nOption & 0x2) != 0;

            ret.bNextShootExJablin = p.Decode1() > 0;             //v339->m_bNextShootExJablin && CUserLocal::CheckApplyExJablin(v339, pSkill, nAttackAction);

            ret.nActionAndDir = p.Decode2();
            ret.bLeft         = (ret.nActionAndDir >> 15) & 1;
            ret.nAction       = ret.nActionAndDir & 0x7FFF; //nAttackAction
            p.Skip(4);                                      //CRC i think
            ret.nAttackActionType = p.Decode1();            //nAttackSpeed | 16 * nReduceCount
            ret.nAttackSpeed      = p.Decode1();

            ret.tAttackTime = p.Decode4();
            p.Skip(4);             //nPhase

            ret.nBulletItemPos     = p.Decode2();
            ret.nBulletCashItemPos = p.Decode2();
            var nShootRange0a = p.Decode1();             // nSLV (BMS)

            ret.bNoItemConsume = skillTemplate?.is_shoot_skill_not_consuming_bullet ?? false;

            if (!ret.bNoItemConsume)
            {
                if (JobLogic.is_mechanic_job(c.Stats.nJob))
                {
                    ret.bNoItemConsume = true;
                }
                else if (bSoulArrow)
                {
                    ret.bNoItemConsume = c.Buffs[(int)Skills.HUNTER_SOUL_ARROW_BOW] != null ||
                                         c.Buffs[(int)Skills.CROSSBOWMAN_SOUL_ARROW_CROSSBOW] != null ||
                                         c.Buffs[(int)Skills.WINDBREAKER_SOUL_ARROW_BOW] != null ||
                                         c.Buffs[(int)Skills.WILDHUNTER_SOUL_ARROW_CROSSBOW] != null;
                }
                else if (bSpiritJavelin)
                {
                    if (ret.bNextShootExJablin)
                    {
                        ret.bNextShootExJablin = false;
                    }
                    else
                    {
                        ret.nSpiritJavelinItemID = p.Decode4();

                        var nBulletType = (ret.nSpiritJavelinItemID % 10000) + 1;

                        c.Buffs.TryGetValue((int)Skills.NIGHTLORD_SPIRIT_JAVELIN, out AbstractBuff secondaryStat_nSpiritJavelin);

                        if (c.InventoryConsume.Get(ret.nBulletItemPos)?.nItemID != ret.nSpiritJavelinItemID)
                        {
                            c.Buffs.Remove((int)Skills.NIGHTLORD_SPIRIT_JAVELIN);                             // they have to use the same item as they
                        }
                        else
                        {
                            if (secondaryStat_nSpiritJavelin != null && nBulletType != secondaryStat_nSpiritJavelin.Stat[SecondaryStatFlag.SpiritJavelin].nValue)
                            {
                                ret.bValidAttack = false;                                 // PE
                                return(ret);
                            }

                            ret.bNoItemConsume = true;
                        }
                    }
                }
                else if (ret.bNextShootExJablin)
                {
                    ret.bNoItemConsume = true;
                }
            }

            ret.DecodeAttackInfo(p);

            p.Skip(4);             // char pos

            if (JobLogic.IsWildhunterJob(c.Stats.nJob))
            {
                var m_ptBodyRelMove = p.Decode2();                 // unsure what this is used for
            }

            p.Skip(4);             // another pos.. unsure for what

            if (ret.nSkillID == (int)Skills.STRIKER_SPARK)
            {
                ret.tReserveSpark = p.Decode4();
            }

            return(ret);
        }
Exemple #8
0
        public static MapleAttack ParseMagic(CInPacket p, Character c)
        {
            MapleAttack ret = new MapleAttack();

            p.Skip(8);             // -1

            var tByte1 = p.Decode1();

            ret.nDamagePerMob = (byte)(tByte1 & 0xF);
            ret.nMobCount     = (byte)((tByte1 >> 4) & 0xF);

            p.Skip(8);             //-1

            var v11 = p.Decode4(); //2017

            ret.nSkillID = v11;
            p.Skip(1);             // nCombatOrders
            p.Skip(4);             // get_rand(pDrInfo.dr0, 0);
            p.Skip(4);             // CCrc32::GetCrc32(pData, 4u, n, 0, 0);
            p.Skip(8);
            p.Skip(8);

            p.Skip(4);             //dwInit
            p.Skip(4);             //COutPacket::Encode4(&v468, dwInit);

            p.Skip(4);             //SKILLLEVELDATA Crc ?
            p.Skip(4);             //SKILLLEVELDATA Crc ?

            ret.ValidateSkill(c);

            if (!ret.bValidAttack)
            {
                return(ret);
            }

            ret.bNoItemConsume = true;

            if (v11 == 2121001 || v11 == 2221001 || v11 == 2321001 || v11 == 22121000 || v11 == 22151001)
            {
                ret.tKeyDown = p.Decode4();
            }
            else
            {
                ret.tKeyDown = -1;
            }

            ret.nOption = p.Decode1();             // p.Skip(1); // Zero !

            ret.nActionAndDir = p.Decode2();
            ret.bLeft         = (ret.nActionAndDir >> 15) & 1;
            ret.nAction       = ret.nActionAndDir & 0x7FFF; //nAttackAction
            p.Skip(4);                                      //CRC i think
            ret.nAttackActionType = p.Decode1();            //nAttackSpeed | 16 * nReduceCount
            ret.nAttackSpeed      = p.Decode1();

            ret.tAttackTime = p.Decode4();
            p.Skip(4);             //nPhase

            ret.DecodeAttackInfo(p);

            //ret.position = p.DecodePos(); //Confirm this

            return(ret);
        }
Exemple #9
0
        public static MapleAttack ParseMelee(CInPacket p, Character c)
        {
            MapleAttack ret = new MapleAttack();

            var nFirstByte = p.Decode1();

            if (nFirstByte == 1 || nFirstByte == 2)             // CUserLocal::TryDoingNormalAttack
            {
                p.Skip(8);
            }
            else             // CUserLocal::TryDoingMeleeAttack
            {
                p.Skip(7);
            }

            var tByte1 = p.Decode1();

            ret.nDamagePerMob = (byte)(tByte1 & 0xF);
            ret.nMobCount     = (byte)((tByte1 >> 4) & 0xF);

            p.Skip(8);             //-1

            var v11 = p.Decode4();

            ret.nSkillID = v11;

            ret.ValidateSkill(c);
            if (!ret.bValidAttack)
            {
                return(ret);
            }

            ret.bNoItemConsume = true;

            var template = MasterManager.SkillTemplates[ret.nSkillID];

            p.Skip(1);
            p.Skip(8);             // 0.74
            p.Skip(8);             // 0.88

            ret.tKeyDown = template?.is_keydown_skill ?? false?p.Decode4() : -1;

            var bSomeFlag = p.Decode1();             // bFinalAfterSlashBlast | 8 * bShadowPartner | 16 * v685 | 32 * (nSerialAttackSkillID != 0) | ((_BYTE)v694 << 7));

            var bSpark                = ((bSomeFlag >> 7) & 1) > 0;
            var bSerialAttackSkill    = ((bSomeFlag >> 5) & 1) > 0;
            var bShadowPartner        = ((bSomeFlag >> 3) & 1) > 0;
            var bFinalAfterSlashBlast = (bSomeFlag & 1) > 0;

            ret.nActionAndDir = p.Decode2();
            ret.bLeft         = (ret.nActionAndDir >> 15) & 1;
            ret.nAction       = ret.nActionAndDir & 0x7FFF;
            p.Skip(4);             //CRC i think
            ret.nAttackActionType = p.Decode1();
            ret.nAttackSpeed      = p.Decode1();

            ret.tAttackTime = p.Decode4();
            p.Skip(4);             //bmage?

            //More decode for bullets here

            //if (ret.skill == 4211006)
            //{ // Meso Explosion
            //    return parseMesoExplosion(lea, ret);
            //}

            ret.DecodeAttackInfo(p);

            p.Skip(4);             // position

            if (ret.nSkillID == (int)Skills.NIGHTWALKER_POISON_BOMB)
            {
                ret.nGrenadePtX = p.Decode2();
                ret.nGrenadePtY = p.Decode2();
            }

            return(ret);
        }
Exemple #10
0
        public static void Handle_SummonedAttack(WvsGameClient c, CInPacket p)
        {
            var dwSummonedID = p.Decode4();
            var item         = c.Character.Field.Summons[dwSummonedID];

            if (item is null)
            {
                return;
            }

            var nSkillID = item.nSkillID;

            p.Skip(8);             // crc
            p.Decode4();           // get_update_time()
            p.Skip(8);             // crc

            var nActionAndDir = p.Decode1();

            var nAction = nActionAndDir & 0x7F;

            var bLeft = ((nAction >> 7) & 1) > 0;

            p.Skip(8);             // crc

            var nMobCount = p.Decode1();

            if (nSkillID == (int)Skills.MECHANIC_TESLA_COIL && nAction != 0x10)
            {
                var adwTeslaFamily = p.DecodeIntArray(3);
            }

            p.Skip(8);             // mob pos, summon pos
            p.Skip(4);

            var deadMobs = new List <int>();
            var aSAI     = new List <SummonAttackInfo>();

            for (var i = 0; i < nMobCount; i++)
            {
                var dwMobID = p.Decode4();

                var pMob = item.Field.Mobs[dwMobID];

                var dwTemplateID         = p.Decode4();
                var nHitAction           = p.Decode1();
                var nForeAction          = p.Decode1();
                var nFrameIdx            = p.Decode1();
                var nCalcDamageStatIndex = p.Decode1();

                p.Skip(8);                 // position

                var tDelay = p.Decode2();

                var nDamage = p.Decode4();



                if (nDamage <= 0)
                {
                    continue;
                }

                if (pMob is null || pMob.Dead || pMob.Template.Invincible)
                {
                    continue;                                                                        // this happens naturally when two summons attack the same mob at the same time
                }
                aSAI.Add(new SummonAttackInfo
                {
                    dwMobID    = dwMobID,
                    nHitAction = nHitAction,
                    nDamage    = nDamage
                });

                if (pMob.Damage(c.Character, nDamage, tDelay))
                {
                    deadMobs.Add(dwMobID);
                }
            }

            item.Field.Broadcast(CPacket.CSummonedPool.SummonedAttack(item, item.dwId, nActionAndDir, aSAI), c.Character);

            deadMobs.ForEach(mob => c.Character.Field.Mobs.Remove(mob));

            if (nAction == 0x10)
            {
                item.nLeaveType = SummonLeaveType.LEAVE_TYPE_SELF_DESTRUCT;
                item.Field.Summons.Remove(item);
            }
            else if (nSkillID == (int)Skills.VALKYRIE_GABIOTA)
            {
                item.nLeaveType = SummonLeaveType.LEAVE_TYPE_GABIOTA;
                item.Field.Summons.Remove(item);
            }
        }