public static void Handle(int nSkillID, byte nSLV, Character c, CInPacket p) { //COutPacket::COutPacket(&oPacket, 103); //v33 = 1; //v15 = get_update_time(); //COutPacket::Encode4(&oPacket, v15); //COutPacket::Encode4(&oPacket, pSkill->nSkillID); //v16 = nSLV; //COutPacket::Encode1(&oPacket, nSLV); //v17 = (unsigned __int16 *)((int(__thiscall *)(IVecCtrlOwnerVtbl * *, ZRef < CharacterData > *))v3->vfptr->GetPos)( // &v3->vfptr, // &result); //COutPacket::Encode2(&oPacket, *v17); //v18 = ((int(__thiscall *)(IVecCtrlOwnerVtbl * *, char *))v3->vfptr->GetPos)(&v3->vfptr, &v31); //COutPacket::Encode2(&oPacket, *(_WORD*)(v18 + 4)); //CClientSocket::SendPacket(TSingleton < CClientSocket >::ms_pInstance, &oPacket); // position of aura? var x = p.Decode2(); var y = p.Decode2(); var bLeft = x < c.Position.X; c.Skills.Cast(nSkillID, bLeft); }
public static void Handle(int nSkillID, byte nSLV, Character c, CInPacket p) { // Recv [CP_UserSkillUseRequest] [67 00] [D0 B3 75 10] [A6 C7 C9 01] [01] [C0 F7 8D 00] [39 FE] [DF FF] [00] //COutPacket::COutPacket(&oPacket, 103); //v50 = 3; //v36 = get_update_time(); //COutPacket::Encode4(&oPacket, v36); //COutPacket::Encode4(&oPacket, pSkill->nSkillID); //COutPacket::Encode1(&oPacket, nSLV); //COutPacket::Encode4(&oPacket, (unsigned int)cd); //COutPacket::Encode2(&oPacket, pt.x); //COutPacket::Encode2(&oPacket, pt.y); //COutPacket::Encode1(&oPacket, bLeft); //CClientSocket::SendPacket(TSingleton < CClientSocket >::ms_pInstance, &oPacket); var dwMobID = p.Decode4(); var ptX = p.Decode2(); var ptY = p.Decode2(); var bLeft = p.Decode1() > 0; if (c.Skills.Cast(nSkillID, bLeft)) { new UserEffectPacket(UserEffect.SkillUse) { nSkillID = nSkillID, nSLV = nSLV, bLeft = bLeft, ptX = ptX, ptY = ptY, }.BroadcastEffect(c, false); // TODO spawn monster lol } }
private void Handle_UserChangeSlotPositionRequest(WvsGameClient c, CInPacket p) { var tick = p.Decode4(); var type = p.Decode1(); // inventory var src = p.Decode2(); var dst = p.Decode2(); var quantity = p.Decode2(); Logger.Write(LogLevel.Debug, "UserChangeSlotPositionRequest Src {0}, Dst {1} Type {2} Qty {3}", src, dst, type, quantity); if (src < 0 && dst > 0) { CInventoryManipulator.UnEquip(c, src, dst); //check } else if (dst < 0) { CInventoryManipulator.Equip(c, src, dst); //check } else if (dst == 0) { CInventoryManipulator.Drop(c, type, src, quantity); } else { CInventoryManipulator.Move(c, type, src, dst); //check } }
private void Handle_UserSelectNpc(WvsGameClient c, CInPacket p) { var dwNpcId = p.Decode4(); var nPosX = p.Decode2(); var nPosY = p.Decode2(); if (c.NpcScript != null) { Logger.Write(LogLevel.Warning, "Npc script already in progress?"); } var field = c.GetCharField(); var npc = field.Npcs.Get(dwNpcId); if (npc != null) { //if (npc.hasShop()) //{ // chr.setConversation(1); // npc.sendShop(c); //} //else { c.NpcScript = NpcScript.GetScript(npc.Id, c); c.NpcScript.Execute(); } } else { Logger.Write(LogLevel.Warning, "Unable to find NPC {0}", dwNpcId); } }
public static TagPoint DecodePos(this CInPacket packet) { var x = packet.Decode2(); var y = packet.Decode2(); return(new TagPoint(x, y)); }
private void Handle_UserTransferFieldRequest(WvsGameClient c, CInPacket p) { if (p.Available == 0) { //Cash Shop Related return; } //TODO: Portal count checks //TODO: XY rect checks //TODO: Keep track if player spawns when entering a field var portalCount = p.Decode1(); //CField::GetFieldKey(v20); var destination = p.Decode4(); // var portalName = p.DecodeString(); var x = p.Decode2(); var y = p.Decode2(); //var extra = p.DecodeBuffer(3); idk | prem | chase var portal = c.GetCharField() .Portals .GetByName(portalName); if (portal == null) { Logger.Write(LogLevel.Warning, "Client tried to enter non existant portal {0}", portalName); } else { c.UsePortal(portal); } }
public static void Handle(int nSkillID, byte nSLV, Character c, CInPacket p) { //COutPacket::COutPacket(&oPacket, 103); //v30 = 1; //v21 = get_update_time(); //COutPacket::Encode4(&oPacket, v21); //COutPacket::Encode4(&oPacket, pSkill->nSkillID); //COutPacket::Encode1(&oPacket, v16); //v22 = (unsigned __int16 *)(*(int(__thiscall * *)(int, char *))(*(_DWORD*)v10 + 16))(v10, &v28); //COutPacket::Encode2(&oPacket, *v22); //v23 = (*(int(__thiscall * *)(int, CUserLocal * *))(*(_DWORD*)v10 + 16))(v10, &v24); //COutPacket::Encode2(&oPacket, *(_WORD*)(v23 + 4)); //CClientSocket::SendPacket(TSingleton < CClientSocket >::ms_pInstance, &oPacket); var x = p.Decode2(); var y = p.Decode2(); var bLeft = x < c.Position.X; if (c.Skills.Cast(nSkillID, bLeft, true)) // todo handle this skill { var cGate = new COpenGate(c.dwId) { Position = new CMovePath { X = x, Y = y } // TODO distance check }; var gate1 = c.Field.OpenGates1[c.dwId]; var gate2 = c.Field.OpenGates2[c.dwId]; if (gate1 is null) { c.Field.OpenGates1.Add(cGate); } else if (gate2 is null) { c.Field.OpenGates2.Add(cGate); } else if (gate1.StartTime > gate2.StartTime) { c.Field.OpenGates2.Remove(cGate.dwCharacterID); c.Field.OpenGates2.Add(cGate); } else { c.Field.OpenGates1.Remove(cGate.dwCharacterID); c.Field.OpenGates1.Add(cGate); } new UserEffectPacket(Common.Types.UserEffect.SkillUse) { nSkillID = nSkillID, nSLV = nSLV, bLeft = (c.Position.MoveAction & 1) != 0 }.BroadcastEffect(c, false); } }
public void OpenGate(CInPacket p) { var field = Parent.Field; var dwOwnerID = p.Decode4(); var nX = p.Decode2(); var nY = p.Decode2(); var bFirst = p.Decode1() != 0; (bFirst ? field.OpenGates1 : field.OpenGates2) .OnOpenGate(Parent, dwOwnerID); Enable(); }
public static void Handle(int nSkillID, byte nSLV, Character c, CInPacket p) { // COutPacket::COutPacket(&oPacket, 103); //v36 = 2; //v25 = get_update_time(); // COutPacket::Encode4(&oPacket, v25); //COutPacket::Encode4(&oPacket, pSkill->nSkillID); //COutPacket::Encode1(&oPacket, v20); //v26 = (unsigned __int16 *)(*(int (__thiscall**) (int, char*))(*(_DWORD*) v15 + 16))(v15, &v34); //COutPacket::Encode2(&oPacket, *v26); //v27 = (*(int (__thiscall**) (int, CUserLocal**))(*(_DWORD*) v15 + 16))(v15, &v30); //COutPacket::Encode2(&oPacket, *(_WORD*) (v27 + 4)); //CClientSocket::SendPacket(TSingleton<CClientSocket>::ms_pInstance, &oPacket); var x = p.Decode2(); var y = p.Decode2(); if (c.Field.Template.Town) { return; } if (c.Field.MapId / 1000000 % 100 == 9) { return; } if (c.Field.Template.HasMysticDoorLimit()) { return; } return; // TODO fix this f*****g shit if (!c.Skills.Cast(nSkillID, true, true)) { return; } c.Field.TownPortals.CreateTownPortal(c, nSkillID, x, y, Math.Min(120 * 1000, 20 * nSLV * 1000)); // TODO get time value from skill c.Party?.BroadcastLoadParty(); // TODO send the proper packet instead of this whole thing new UserEffectPacket(Common.Types.UserEffect.SkillUse) { nSkillID = nSkillID, nSLV = nSLV, bLeft = (c.Position.MoveAction & 1) != 0 }.BroadcastEffect(c, false); }
public static void Handle(int nSkillID, byte nSLV, Character character, CInPacket p) { // COutPacket::COutPacket(&oPacket, 103); // LOBYTE(v37) = 2; // v23 = get_update_time(); // COutPacket::Encode4(&oPacket, v23); // COutPacket::Encode4(&oPacket, pSkill->nSkillID); // COutPacket::Encode1(&oPacket, nSLV); // v24 = adwUserID.a; // if (adwUserID.a) // v25 = *(adwUserID.a - 1); // else // LOBYTE(v25) = 0; // COutPacket::Encode1(&oPacket, v25); // v26 = 0; // if (ZArray < unsigned long>::GetCount(&adwUserID) ) //{ // do // COutPacket::Encode4(&oPacket, v24[v26++]); // while (v26 < ZArray < unsigned long>::GetCount(&adwUserID) ); // } // COutPacket::Encode2(&oPacket, (unsigned __int16)cd); // CClientSocket::SendPacket(TSingleton < CClientSocket >::ms_pInstance, &oPacket); var v25 = p.Decode1(); var ZArray = p.DecodeIntArray(v25); var cd = p.Decode2(); }
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; } }
public static void Handle_UserShopRequest(WvsGameClient c, CInPacket p) { if (c.ActiveShop is null) { c.Character.SendMessage("Unable to find active shop. Please re-open the shop or report this to staff."); return; } switch ((ShopReq)p.Decode1()) // nOperation { case ShopReq.Buy: { var nPos = p.Decode2(); //Item index within the npc shop lol var dwTemplateID = p.Decode4(); var nCount = p.Decode2(); BuyItem(c.Character, nPos, dwTemplateID, nCount); break; } case ShopReq.Sell: { var nSlot = p.Decode2(); //Item inventory index var dwTemplateID = p.Decode4(); var nCount = p.Decode2(); SellItem(c.Character, nSlot, dwTemplateID, nCount); break; } case ShopReq.Recharge: { var nSlot = p.Decode2(); RechargeItem(c.Character, nSlot); break; } case ShopReq.Close: { Close(c.Character); break; } } }
/** * Die packet: * Recv [CP_UserTransferFieldRequest] [29 00] [01] [00 00 00 00] 00 00 00 01 00 // last bytes possibly related to death-items * Portal to other map packet: * Recv [CP_UserTransferFieldRequest] [29 00] [01] [FF FF FF FF] [06 00] [65 61 73 74 30 30] [4D 06] [C7 01] 00 00 00 */ public static void Field(WvsGameClient c, CInPacket p) { //void __thiscall CUser::OnTransferFieldRequest(CUser *this, int bLoopback, CInPacket *iPacket) //Exit Cash Shop -> Not used in WvsGame if (p.Available == 0) { return; } //TODO: Portal count checks //TODO: XY rect checks to ensure player is on portal when activating it //TODO: Keep track if player spawns when entering a field var bFieldKey = p.Decode1(); //CField::GetFieldKey(v20); var dwField = p.Decode4(); var sPortalName = p.DecodeString(); if (c.Character.Stats.nHP <= 0) { c.Character.Field.OnUserWarpDie(c.Character); } else if (sPortalName.Length > 0) // not death { var x = p.Decode2(); var y = p.Decode2(); p.Decode1(); // used to be bTownPortal var bPremium = p.Decode1(); var bChase = p.Decode1(); if (bChase > 0) { var nTargetPosition_X = p.Decode4(); var nTargetPosition_Y = p.Decode4(); } c.Character.Field.OnUserEnterPortal(c.Character, sPortalName); } else // gm warp command { // TODO admin checks // tp to desired field } }
public void HandleAddItem(CInPacket p, Character pChar) { if (dwFirstLockerId == pChar.dwId || !acceptedInvite) { return; } var nTI = (InventoryType)p.Decode1(); var nCurInvSlot = p.Decode2(); // in inventory var nCount = p.Decode2(); var nTargetSlot = p.Decode1(); // in trade window var pItem = InventoryManipulator.GetItem(pChar, nTI, nCurInvSlot); var tempInv = GetTempInv(pChar); if (pItem is null || !tempInv.CanAddToSlot(nTargetSlot)) { return; } if (ItemConstants.is_treat_singly(pItem.nItemID)) { nCount = -1; // negative amount clears the slot } else { nCount = Math.Min(pItem.nNumber, Math.Abs(nCount)); } InventoryManipulator.RemoveFrom(pChar, nTI, nCurInvSlot, nCount); if (pItem is GW_ItemSlotBundle pBundle && !pBundle.IsRechargeable) { pItem = pItem.DeepCopy(); pItem.nNumber = nCount; } var pTempItem = new TempItem(pItem, nCurInvSlot, nTargetSlot); tempInv.Add(pTempItem); Parent.SendPacket(AddItemPacket(pTempItem, !IsOwner(pChar))); Partner.SendPacket(AddItemPacket(pTempItem, IsOwner(pChar))); }
private void Handle_CheckUserLimit(WvsLoginClient c, CInPacket p) { var nWorldID = p.Decode2(); if (nWorldID == 0) //Scania { c.SendPacket(CPacket.CLogin.CheckUserLimit(0)); } }
// all movement update handlers should be calling this from now on public int UpdateMovePath(COutPacket oPacket, CInPacket iPacket) { X = iPacket.Decode2(); //ZtlSecureTear_m_x Y = iPacket.Decode2(); //ZtlSecureTear_m_y VX = iPacket.Decode2(); //ZtlSecureTear_m_vx VY = iPacket.Decode2(); //ZtlSecureTear_m_vy oPacket.Encode2(X); oPacket.Encode2(Y); oPacket.Encode2(VX); oPacket.Encode2(VY); var elems = DecodePath(iPacket); EncodePath(oPacket, elems); return(elems.Length); }
//----------------------------------------------------------------------------- private void Handle_ClientDumpLog(WvsLoginClient c, CInPacket p) { //Thank you to Mordred for this handler! var callType = p.Decode2(); var errorCode = p.Decode4(); var backupBufferSize = p.Decode2(); var rawSeq = p.Decode4(); var type = p.Decode2(); var backupBuffer = p.DecodeBuffer(backupBufferSize - 6); var callTypeName = Enum.GetName(typeof(CrashCallType), callType); var logTypeName = Enum.GetName(typeof(SendOps), type); Logger.Write(LogLevel.Trace, "RawSeq: {0} CallType: {1} ErrorCode: {2} BackupBufferSize: {3} Type: {4} - {5} Packet: {6}", rawSeq, callTypeName, errorCode, backupBufferSize, type, logTypeName, Constants.GetString(backupBuffer) ); }
public void AddItem(CInPacket p) { var nTI = (InventoryType)p.Decode1(); var nPOS = p.Decode2(); var nBundles = Math.Max((short)1, p.Decode2()); var nPricePerBundle = Math.Max((short)1, p.Decode2()); var nPrice = Math.Max(1, p.Decode4()); var pItem = InventoryManipulator.GetItem(Parent, nTI, nPOS); if (pItem is null) { Parent.SendMessage("item is null u fucc"); return; } var nQuantityRequested = -1; // negative so its removed completely from inventory if (!ItemConstants.is_treat_singly(pItem.nItemID)) { nQuantityRequested = nBundles * nPricePerBundle; if (pItem.nNumber < nQuantityRequested) { return; // f*****g retard } } InventoryManipulator.RemoveFrom(Parent, nTI, nPOS, (short)nQuantityRequested); Inventory.Add(new TempItem(pItem, nPrice, nPricePerBundle, nBundles)); Refresh(Parent); Parent.SendMessage($"Bundles: {nBundles}, PricePerBundle: {nPricePerBundle}, Price: {nPrice}"); // TODO packet editing checks }
public void Handle(TClient c, CInPacket p) { var opCode = p.Decode2(); if (m_handlers.TryGetValue(opCode, out var handler)) { if (handler.RequireLogin && !c.LoggedIn) { c.Disconnect(); } else { handler.Handler(c, p); } } }
public void Hit(Character c, CInPacket p) { // CReactorPool::FindHitReactor // CReactorPool::FindSkillReactor var bSkillReactor = p.Decode4() != 0; if (bSkillReactor) { return; // TODO handle this } var dwHitOption = p.Decode4(); // v4->dwHitOption = v13 & 1 | 2 * CUser::IsOnFoothold(v3); var tActionDelay = p.Decode2(); var nSkillID = p.Decode4(); // for skill reactors?? idk yet OnHitReactor(c, tActionDelay, 0); // TODO event idx }
private void Handle_CashShopCheckCouponRequest(WvsShopClient c, CInPacket p) { p.Decode2(); // something var code = p.DecodeString(); var coupon = new CouponCode(code, c); if (coupon.Invalid) { c.SendPacket(CPacket.CCashShop.CouponFail(CashItemFailed.InvalidCoupon)); } else if (coupon.Used) { c.SendPacket(CPacket.CCashShop.CouponFail(CashItemFailed.UsedCoupon)); } else if (coupon.IncorrectAccount) { c.SendPacket(CPacket.CCashShop.CouponFail(CashItemFailed.NotAvailableCoupon)); } else if (coupon.Expired) { c.SendPacket(CPacket.CCashShop.CouponFail(CashItemFailed.ExpiredCoupon)); } else if (coupon.Items != null && !InventoryManipulator.HasSpace(c.Character, coupon.Items)) { c.SendPacket(CPacket.CCashShop.CouponFail(CashItemFailed.NoEmptyPos)); // TODO fix this } else { if (coupon.Items != null) { foreach (var item in coupon.Items) { InventoryManipulator.InsertInto(c.Character, MasterManager.CreateItem(item, false)); CPacket.CCashShop.CouponAddItem(item); } } c.Account.AccountData.NX_Prepaid += coupon.NX; coupon.Dispose(); c.Account.Save(); } c.EnableActions(); }
// note: uses another header (0x69) than regular skill req (0x67) public static void Handle(WvsGameClient c, CInPacket p) { //COutPacket::COutPacket(&oPacket, 105); //v71 = 10; //COutPacket::Encode4(&oPacket, v5); //COutPacket::Encode1(&oPacket, nSLV); //COutPacket::Encode2(&oPacket, v4->m_nOneTimeAction & 0x7FFF | ((unsigned __int16)v4->m_nMoveAction << 15)); //COutPacket::Encode1(&oPacket, v57); //if (v5 == 33101005) // COutPacket::Encode4(&oPacket, v4->m_dwSwallowMobID); //CClientSocket::SendPacket(TSingleton < CClientSocket >::ms_pInstance, &oPacket); var nSkillID = p.Decode4(); var nSLV = p.Decode1(); var nMoveAction = p.Decode2(); var nActionSpeed = p.Decode1(); var pSkill = c.Character.Skills.Get(nSkillID, true); if (pSkill is null) { return; } if (nSkillID == (int)Skills.WILDHUNTER_SWALLOW) { var dwSwallowMobId = p.Decode4(); var pMob = c.Character.Field.Mobs[dwSwallowMobId]; if (pMob is object && !GameConstants.is_not_swallowable_mob(pMob.nMobTemplateId)) { if (!pMob.TrySwallowMob(c.Character)) { return; } } } c.Character.Field.Broadcast(UserSkillPrepare(c.Character.dwId, nSkillID, pSkill.nSLV, nMoveAction, nActionSpeed), c); }
public static void Handle(int nSkillID, byte nSLV, Character character, CInPacket p) { //COutPacket::COutPacket(&oPacket, 0x67); //v24 = 0; //v13 = get_update_time(); //COutPacket::Encode4(&oPacket, v13); //COutPacket::Encode4(&oPacket, v9->nSkillID); //v14 = nSLV; //COutPacket::Encode1(&oPacket, nSLV); //v15 = CUserLocal::FindParty(v3, v9, v14, &nCount); //COutPacket::Encode1(&oPacket, v15); //COutPacket::Encode2(&oPacket, 0); //CWvsContext::SetExclRequestSent(pCtx, 1); //CClientSocket::SendPacket(TSingleton < CClientSocket >::ms_pInstance, &oPacket); var nCount = p.Decode1(); // we arent really interested in this rn var zeroshort = p.Decode2(); // unused?? // character.Skills.Cast(nSkillID, false); // two packets are sent from cleric heal: SkillUseRequest and MagicAttack // since we cast the spell from the attack handler we dont need to process it again here }
private void Handle_MobMove(WvsGameClient c, CInPacket p) { int dwMobId = p.Decode4(); var nMobCtrlSN = p.Decode2(); var v7 = p.Decode1(); //v85 = nDistance | 4 * (v184 | 2 * ((unsigned __int8)retaddr | 2 * v72)); [ CONFIRMED ] var pOldSplit = (v7 & 0xF0) != 0; //this is a type of CFieldSplit var bMobMoveStartResult = (v7 & 0xF) != 0; var pCurSplit = p.Decode1(); var bIllegealVelocity = p.Decode4(); var v8 = p.Decode1(); var bCheatedRandom = (v8 & 0xF0) != 0; var bCheatedCtrlMove = (v8 & 0xF) != 0; p.Decode4(); //Loopy Decode 1 p.Decode4(); //Loopy Decode 2 p.DecodeBuffer(16); var movePath = p.DecodeBuffer(p.Available); //if (pMob->m_pController->pUser != pCtrl // && (!pOldSplit // || pMob->m_bNextAttackPossible // || !CLifePool::ChangeMobController(&v5->m_lifePool, pCtrl->m_dwCharacterID, pMob, 1))) //{ // CMob::SendChangeControllerPacket(v9, v10, 0); // return; //} c.SendPacket(CPacket.MobMoveAck(dwMobId, nMobCtrlSN, bMobMoveStartResult, 0, 0, 0)); var mobMove = CPacket.MobMove(dwMobId, bMobMoveStartResult, pCurSplit, bIllegealVelocity, movePath); c.GetCharField().Broadcast(mobMove, c); }
public void RemoveItem(CInPacket p) { // Recv [CP_MiniRoom] [90 00] [26] 01 00 var nShopSlot = p.Decode2(); var tItem = Inventory.GetAndRemove(nShopSlot); if (tItem is null) { // do nothing } else if (InventoryManipulator.CountFreeSlots(Parent, tItem.Item.InvType) <= 0) { Parent.SendMessage("Please make room in your inventory."); } else { InventoryManipulator.InsertInto(Parent, tItem.Item); } Refresh(Parent); }
public static void CreateCharacter(WvsLoginClient c, CInPacket p) { var newChar = Default(); // create explorer: Recv [CP_CreateNewCharacter] 16 00 06 00 70 6F 6F 70 69 65 01 00 00 00 00 00 24 4E 00 00 [4E 75 00 00] [03 00 00 00] [03 00 00 00] [86 DE 0F 00] [2F 2D 10 00] [85 5B 10 00] [8B DE 13 00] [00] // create resistance: Recv [CP_CreateNewCharacter] 16 00 06 00 64 6F 6F 64 6F 6F 00 00 00 00 00 00 84 4E 00 00 [30 75 00 00] [07 00 00 00] [01 00 00 00] [47 06 10 00] [00 00 00 00] [74 5D 10 00] [8C DE 13 00] [00] newChar.Stats.sCharacterName = p.DecodeString(); var job = (short)p.Decode4(); newChar.Stats.nJob = GameConstants.GetRealJobFromCreation(job); bool subJob = p.Decode2() > 0; //whether dual blade = 1 or adventurer = 0 newChar.Stats.nSubJob = (short)(subJob ? 1 : 0); // doing it this way to reduce potential packet editing fuckery newChar.Stats.nFace = p.Decode4(); var hairColor = p.Decode4(); newChar.Stats.nHair = p.Decode4() + hairColor; newChar.Stats.nSkin = (byte)p.Decode4(); var top = p.Decode4(); var bottom = p.Decode4(); var shoes = p.Decode4(); var weapon = p.Decode4(); newChar.Stats.nGender = p.Decode1(); if (newChar.Stats.nSubJob == 1) { newChar.Stats.nJob = 400; // thief job } newChar.Stats.dwPosMap = GameConstants.GetStartingMap(newChar.Stats.nJob, newChar.Stats.nSubJob); newChar.Look.CopyStats(newChar.Stats); // TODO validate these against wz files newChar.Look.aEquip[5] = top; newChar.Look.aEquip[6] = bottom; newChar.Look.aEquip[7] = shoes; newChar.Look.aEquip[11] = weapon; newChar.Insert(c.Account.ID); // create empty entries in mapping tables InitDefaultMappings(newChar.Stats.dwCharacterID); if (newChar.Stats.dwCharacterID < 0) { c.SendPacket(CreateCharacterPacket(false, null)); } else { // add equips // todo figure out if overalls have their own slot ID MasterManager.CreateNormalStatEquip(top) .SaveToDB(newChar.Stats.dwCharacterID, (short)(bottom > 0 ? -5 : -5)); if (bottom > 0) // will be zero if its a champ that starts with an overall { MasterManager.CreateNormalStatEquip(bottom) .SaveToDB(newChar.Stats.dwCharacterID, -6); } MasterManager.CreateNormalStatEquip(shoes) .SaveToDB(newChar.Stats.dwCharacterID, -7); MasterManager.CreateNormalStatEquip(weapon) .SaveToDB(newChar.Stats.dwCharacterID, -11); var nWhitePot = 2000002; var nManaPot = 2000006; var nPotQuantity = (short)100; var item1 = MasterManager.CreateItem(nWhitePot) as GW_ItemSlotBundle; item1.nNumber = nPotQuantity; item1.SaveToDB(newChar.Stats.dwCharacterID, 1); var item2 = MasterManager.CreateItem(nManaPot) as GW_ItemSlotBundle; item2.nNumber = nPotQuantity; item2.SaveToDB(newChar.Stats.dwCharacterID, 2); c.SendPacket(CreateCharacterPacket(true, newChar)); } }
public static void OnQuestRequest(WvsGameClient c, CInPacket p) { if (c.Character.Stats.nHP <= 0) { return; } var nType = (QuestRequestType)p.Decode1(); var nQuestId = p.Decode2(); var pQuest = MasterManager.QuestTemplates[nQuestId]; if (pQuest is null) { //c.Character.SendMessage($"Unable to find quest ID {nQuestId}."); return; } var dwNpcTemplateID = 0; if (nType != QuestRequestType.LostItem && nType != QuestRequestType.ResignQuest) { dwNpcTemplateID = p.Decode4(); var npcTemplate = MasterManager.NpcTemplates[dwNpcTemplateID]; // TODO check for if NPC should be in the same map as the player //if (!c.Character.Field.Npcs.Contains(dwNpcTemplateID)) //{ // c.Character.SendMessage($"Unable to find NPC {nQuestId} in current field."); // // return; //} if (!pQuest.AutoStart) { var ptUserPosX = p.Decode2(); var ptUserPosY = p.Decode2(); // TODO quest location check // if ( abs(v16) > 1200 || (v8 = *(v20 + 136) - pTemplate, v17 = *(v20 + 132), abs(v8) > 800) ) // tick AB } } switch (nType) { case QuestRequestType.LostItem: c.Character.Quests.OnLostQuestItem(p, nQuestId); break; case QuestRequestType.AcceptQuest: c.Character.Quests.OnAcceptQuest(p, nQuestId, dwNpcTemplateID); break; case QuestRequestType.CompleteQuest: c.Character.Quests.OnCompleteQuest(p, nQuestId, dwNpcTemplateID, false); break; case QuestRequestType.ResignQuest: c.Character.Quests.OnResignQuest(p, nQuestId); break; case QuestRequestType.OpeningScript: c.Character.Quests.OnScriptLinkedQuest(nQuestId, dwNpcTemplateID, 0); break; case QuestRequestType.CompleteScript: c.Character.Quests.OnScriptLinkedQuest(nQuestId, dwNpcTemplateID, 1); break; default: throw new ArgumentOutOfRangeException(nameof(nType)); } }
//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); }
public static void Handle_UserSkillLearnItemUseRequest(WvsGameClient c, CInPacket p) { int dwTickCount = p.Decode4(); short nPOS = p.Decode2(); int nItemID = p.Decode4(); c.Character.Action.Enable(); if (c.Character.Stats.nHP <= 0) { return; } if (InventoryManipulator.GetItem(c.Character, ItemConstants.GetInventoryType(nItemID), nPOS) is GW_ItemSlotBundle item && item.Template is ConsumeItemTemplate template) { var jobroot = Math.Floor(c.Character.Stats.nJob * 0.01); // 3500 -> 35 var bUsed = false; var bSuccess = false; var bIsMasterBook = item.nItemID / 10000 == 229; foreach (var skillId in template.SkillData) { var skillJob = (int)Math.Floor(skillId / 10000f); // 35111010 -> 3511 var skillRoot = (int)Math.Floor(skillJob / 100f); // 3511 -> 35 if (skillRoot == jobroot) // this can only be true once { if (skillJob > c.Character.Stats.nJob) { break; } var skill = c.Character.Skills.FirstOrDefault(s => s.nSkillID == skillId); if (bIsMasterBook) { if (skill is null || skill.nSLV < template.ReqSkillLevel || skill.CurMastery >= template.MasterLevel) { return; } } else { if (skill != null && skill.CurMastery > 0) { break; } } bUsed = true; if (template.SuccessRate != 100) { if (Constants.Rand.Next() % 100 > template.SuccessRate) { break; } } c.Character.Modify.Skills(mod => mod.AddEntry(skillId, s => s.CurMastery = (byte)template.MasterLevel)); bSuccess = true; break; } } if (bUsed) { InventoryManipulator.RemoveFrom(c.Character, item.InvType, nPOS); // always remove } c.Character.Field.Broadcast(CPacket.SkillLearnItemResult(c.dwCharId, bIsMasterBook, bUsed, bSuccess)); } }
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(); }