public static MapleAttack ParseBody(CInPacket p, Character c) { return(ParseMelee(p, c)); //TODO: Confirm below one day. Delta said melee works for this // Recv [CP_UserBodyAttack] [32 00] [01] [FF FF FF FF] [FF FF FF FF] [11] [FF FF FF FF] [FF FF FF FF] [CB F9 41 01] [00] [C3 C0 24 6A] [1F 46 7E D1] [9D D4 DD D5] [9D D4 DD D5] [00 00] 80 5F CF 88 C3 02 00 F9 9E D9 1F 00 00 00 00 2F 27 00 00 07 00 01 05 A9 00 8B 01 A5 00 8B 01 00 00 0B 00 00 00 B8 8D DB 27 B9 00 8B 01 MapleAttack ret = new MapleAttack(); p.Decode1(); // field key p.Decode4(); // pDrInfo.dr0 p.Decode4(); // pDrInfo.dr1 ret.nDamagePerMob = (byte)(p.Decode1() & 0xF); // nDamagePerMob | 0x10 * nRange p.Decode4(); // pDrInfo.dr2 p.Decode4(); // pDrInfo.dr3 ret.nSkillID = p.Decode4(); ret.ValidateSkill(c); if (!ret.bValidAttack) { return(ret); } p.Decode1(); // cd->nCombatOrders p.Decode4(); // get_rand(pDrInfo.dr0, 0) p.Decode4(); // CCrc32::GetCrc32(pData, 4u, n, 0, 0) // todo lol return(null); }
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); }
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); }
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); }