diff --git a/flyff-api/CMakeLists.txt b/flyff-api/CMakeLists.txt index 17995d0..46ef47e 100644 --- a/flyff-api/CMakeLists.txt +++ b/flyff-api/CMakeLists.txt @@ -6,7 +6,7 @@ add_library( "include/flyff.h" src/core.h src/skill/SkillProperty.h - src/object/ObjectProperty.h src/item/ItemKind2.h src/item/ItemKind3.h src/item/Part.h src/item/InventoryItem.h src/object/mover/JobProperty.h src/object/mover/ParamID.h src/object/mover/MoverProperty.h src/object/mover/Rank.h src/object/mover/Element.h src/item/AttackRange.h) + src/object/ObjectProperty.h src/item/ItemKind2.h src/item/ItemKind3.h src/item/Part.h src/item/InventoryItem.h src/object/mover/JobProperty.h src/object/mover/ParamID.h src/object/mover/MoverProperty.h src/object/mover/Rank.h src/object/mover/Element.h src/item/AttackRange.h src/PacketHeader.h src/Action.h) target_include_directories(flyff-api PUBLIC "include") target_link_libraries(flyff-api PUBLIC flyff-client fugg-api) \ No newline at end of file diff --git a/flyff-api/include/flyff.h b/flyff-api/include/flyff.h index deacb35..066f102 100644 --- a/flyff-api/include/flyff.h +++ b/flyff-api/include/flyff.h @@ -12,6 +12,10 @@ #include "../src/skill/SkillID.h" #include "../src/skill/SkillProperty.h" +#include "../src/object/mover/BuffType.h" +#include "../src/PacketHeader.h" +#include "../src/Action.h" + #include "../src/import.h" #define FN_CAST(return_type, ...) return_type (*)(__VA_ARGS__) diff --git a/flyff-api/src/Action.h b/flyff-api/src/Action.h new file mode 100644 index 0000000..d11b8f3 --- /dev/null +++ b/flyff-api/src/Action.h @@ -0,0 +1,113 @@ +// +// Created by main on 18-11-22. +// + +#ifndef FUGG_ACTION_H +#define FUGG_ACTION_H + +#include + +namespace flyff { + enum class Action : uint32_t { + Move, + StopMove, + Jump, + Emote, + Target, + Skill, + MoveForward, + MoveBackward, + TurnLeft, + TurnRight, + StopTurn, + LookDown, + LookUp, + StopLook, + StopMoveFly, + FlyFreeMove, + Follow, + Interact, + ToggleWalk = 0x14, + // Charged attacks from bows and wands. + ReleaseChargedAttack, + // Send when your are being blocked from moving. + Correction = 0x18, + + }; + + static std::ostream &operator<<(std::ostream &os, const Action &action) { + switch(action) { + case Action::Move: + os << "Move"; + break; + case Action::StopMove: + os << "StopMove"; + break; + case Action::Jump: + os << "Jump"; + break; + case Action::Emote: + os << "Emote"; + break; + case Action::Target: + os << "Target"; + break; + case Action::Skill: + os << "Skill"; + break; + case Action::MoveForward: + os << "MoveForward"; + break; + case Action::MoveBackward: + os << "MoveBackward"; + break; + case Action::TurnLeft: + os << "TurnLeft"; + break; + case Action::TurnRight: + os << "TurnRight"; + break; + case Action::StopTurn: + os << "StopTurn"; + break; + case Action::LookDown: + os << "LookDown"; + break; + case Action::LookUp: + os << "LookUp"; + break; + case Action::StopLook: + os << "StopLook"; + break; + case Action::StopMoveFly: + os << "StopMoveFly"; + break; + case Action::FlyFreeMove: + os << "FlyFreeMove"; + break; + case Action::Follow: + os << "Follow"; + break; + case Action::Interact: + os << "Interact"; + break; + case Action::ToggleWalk: + os << "ToggleWalk"; + break; + case Action::ReleaseChargedAttack: + os << "ReleaseChargedAttack"; + break; + case Action::Correction: + os << "Correction"; + break; + default: + os << "Action(" << static_cast(action) << ")"; + break; + } + + return os; + } +}; + + +#endif //FUGG_ACTION_H diff --git a/flyff-api/src/Neuz.cpp b/flyff-api/src/Neuz.cpp index 0251ca1..10c1aeb 100644 --- a/flyff-api/src/Neuz.cpp +++ b/flyff-api/src/Neuz.cpp @@ -1,3 +1,11 @@ +#include +#include +#include +#include +#include +#include +#include +#include #include "Neuz.h" #include @@ -35,6 +43,8 @@ namespace flyff { extern u32 w2c_f516(u32, u32); // CProject::GetSkillProp() extern u32 w2c_f441(u32, u32); + // send_motion_packet + extern u32 w2c_f272(u32, u32, u64, u64, u64, u64); }; static const auto &get_mover_node = w2c_f207; @@ -43,6 +53,7 @@ namespace flyff { static const auto &show_announcement = w2c_f606; static const auto &can_attack_target = w2c_f516; static const auto &get_skill_prop = w2c_f441; + static const auto &send_motion_packet = w2c_f272; }; // namespace raw // Emscripten runtime: @@ -135,7 +146,7 @@ namespace flyff { } bool Neuz::is_valid_attack(const Pointer &attacker, - const Pointer &defender) const { + const Pointer &defender) { auto result = raw::can_attack_target(static_cast(attacker), static_cast(defender)); @@ -146,4 +157,11 @@ namespace flyff { Pointer Neuz::get_skill_property(const SkillID &id) { return Pointer(raw::get_skill_prop(static_cast(id), 1)); } + + uint32_t + Neuz::send_motion_packet(const Pointer &mover, Action action, unsigned long long arg0, + unsigned long long arg1, + unsigned long long arg2, unsigned long long arg3) { + return raw::send_motion_packet(static_cast(mover), static_cast(action), arg0, arg1, arg2, arg3); + } } // namespace flyff \ No newline at end of file diff --git a/flyff-api/src/Neuz.h b/flyff-api/src/Neuz.h index 4554e20..9a57120 100644 --- a/flyff-api/src/Neuz.h +++ b/flyff-api/src/Neuz.h @@ -3,12 +3,18 @@ #include #include +#include +#include +#include #include "skill/SkillID.h" #include "skill/SkillProperty.h" #include "object/mover/Mover.h" +#include "PacketHeader.h" +#include "Action.h" + namespace flyff { // Find this in send_packet. The hash that is applied to game packet headers. const uint32_t PACKET_HEADER_HASH = 0x644aac00; @@ -58,10 +64,13 @@ namespace flyff { void show_announcement(const std::string &message, const flyff::Color &color = {0xFF, 0xFF, 0xFF}) const; - bool is_valid_attack(const Pointer &attacker, const Pointer &defender) const; + static bool is_valid_attack(const Pointer &attacker, const Pointer &defender) ; - static Pointer get_skill_property(const SkillID& id) ; + static Pointer get_skill_property(const SkillID &id); + static uint32_t send_motion_packet(const Pointer &mover, Action action, unsigned long long arg0, + unsigned long long arg1, + unsigned long long arg2, unsigned long long arg3); // Easy to implement: Just send a EmscriptenKeyboardEvent* to the registered // function. void send_keydown(); void send_keyup(); void send_keypress(); }; diff --git a/flyff-api/src/PacketHeader.h b/flyff-api/src/PacketHeader.h new file mode 100644 index 0000000..63ed40c --- /dev/null +++ b/flyff-api/src/PacketHeader.h @@ -0,0 +1,26 @@ +// +// Created by main on 18-11-22. +// + +#ifndef FUGG_PACKETHEADER_H +#define FUGG_PACKETHEADER_H + +#include + +namespace flyff { + enum class PacketHeader : uint32_t { + Logout = 0x403, + Motion = 0x404, + InventoryUseItem = 0x410, + NpcOpenDialog = 0x413, + InventorySellItem = 0x419, + OpenBank = 0x437, + ChangeChannel = 0x45b, + ChatMessage = 0x2000, + InventoryMoveItem = 0x2001, + OpenGuildWarehouse = 0x201b, + }; +}; + + +#endif //FUGG_PACKETHEADER_H diff --git a/flyff-api/src/object/mover/Mover.h b/flyff-api/src/object/mover/Mover.h index 5d17f65..6cf6f80 100644 --- a/flyff-api/src/object/mover/Mover.h +++ b/flyff-api/src/object/mover/Mover.h @@ -190,9 +190,10 @@ namespace flyff { DEFINE_MEMBER(3248, const Timestamp, last_refresher_time); DEFINE_MEMBER(3256, const Timestamp, last_vitaldrink_time); - DEFINE_MEMBER(3424, Vector, skills); + DEFINE_MEMBER(3416, Vector, skills); - DEFINE_MEMBER(3548, int, pickup_pet_inventory_index); + DEFINE_MEMBER(3528, int, pickup_pet_object_id); + DEFINE_MEMBER(3540, int, pickup_pet_inventory_index); const MinimumSize<4096> size; }; @@ -259,7 +260,7 @@ namespace flyff { src_speed = src_speed + (src_speed * (static_cast(adj_value) / 100.0f)); } - return src_speed <= 0. ? 0. : src_speed; + return src_speed <= 0 ? 0 : src_speed; } uint32_t get_max_hp() const { @@ -267,7 +268,7 @@ namespace flyff { auto result = get_param(ParamID::MaxHitPoint, get_max_origin_hp()); auto percent = get_param(ParamID::MaxHitPointScaling, 0); - factor += (float) percent / (float) 100; + factor += static_cast(percent) / 100.f; result = static_cast(result) * factor; return result; diff --git a/flyff-client/src/client.c b/flyff-client/src/client.c index 87e9faf..ba47a54 100644 --- a/flyff-client/src/client.c +++ b/flyff-client/src/client.c @@ -511,7 +511,7 @@ static u32 w2c_f268(u32); static u32 w2c_f269(u32); static void w2c_f270(u32, u32); static void w2c_f271(u32, u32); -static u32 w2c_f272(u32, u32, u64, u64, u64, u64); +u32 w2c_f272(u32, u32, u64, u64, u64, u64); static u32 w2c_f273(u32); static u32 w2c_f274(u32, u32, u32); static void w2c_f275(u32); @@ -44427,7 +44427,7 @@ static void w2c_f271(u32 w2c_p0, u32 w2c_p1) { FUNC_EPILOGUE; } -static u32 w2c_f272(u32 w2c_p0, u32 w2c_p1, u64 w2c_p2, u64 w2c_p3, u64 w2c_p4, u64 w2c_p5) { +u32 w2c_f272(u32 w2c_p0, u32 w2c_p1, u64 w2c_p2, u64 w2c_p3, u64 w2c_p4, u64 w2c_p5) { u32 w2c_l6 = 0, w2c_l7 = 0, w2c_l8 = 0, w2c_l9 = 0, w2c_l10 = 0, w2c_l11 = 0, w2c_l12 = 0, w2c_l13 = 0, w2c_l14 = 0, w2c_l15 = 0, w2c_l16 = 0, w2c_l17 = 0, w2c_l18 = 0, w2c_l19 = 0, w2c_l20 = 0; u64 w2c_l24 = 0; @@ -1031848,9 +1031848,24 @@ void w2c_f2286(u32 w2c_p0) { w2c_i0 = w2c_p0; w2c_i0 = i32_load((&w2c_memory), (u64)(w2c_i0) + 4u); w2c_l4 = w2c_i0; + + const uintptr_t end = w2c_l4; + w2c_i1 = w2c_p0; w2c_i1 = i32_load((&w2c_memory), (u64)(w2c_i1)); w2c_l2 = w2c_i1; + + const uintptr_t begin = w2c_l2; + + const size_t length = end - begin; + const unsigned char* data = &(&w2c_memory)->data[begin]; + + printf("Finalizing packet of length %zd: ", length); + for(int i = 0; i < length; i++) { + printf("%02X ", data[i]); + } + printf("\n"); + w2c_i0 -= w2c_i1; w2c_l7 = w2c_i0; w2c_i0 = 9u; diff --git a/fugg-client/src/Client.cpp b/fugg-client/src/Client.cpp index a2a70ae..ef61c53 100644 --- a/fugg-client/src/Client.cpp +++ b/fugg-client/src/Client.cpp @@ -1,5 +1,4 @@ #include "Client.h" -#include "BuffType.h" #include @@ -7,6 +6,13 @@ #include #include +#include + +#include +#include + +#include + template void packet_push(std::vector &packet, const T &value, std::vector::iterator offset) { union ToBytes { @@ -36,10 +42,15 @@ namespace fugg { return instance; } - void Client::send_packet(const uint32_t &id, std::vector payload) const { - const uint32_t header = id < 0x400 ? id : id ^ flyff::PACKET_HEADER_HASH; + void Client::send_packet(const flyff::PacketHeader &header, std::vector payload) { +// constexpr auto npc_interact = flyff::PACKET_HEADER_HASH ^ 0x644a8c23; +// constexpr auto npc_dialog = flyff::PACKET_HEADER_HASH ^ 0x644aa813; +// constexpr auto open_guild_bank = flyff::PACKET_HEADER_HASH ^ 0x644a8c1b; +// constexpr auto change_channel = flyff::PACKET_HEADER_HASH ^ 0x644aa85b; +// constexpr auto open_bank = flyff::PACKET_HEADER_HASH ^ 0x644aa837; + const auto id = static_cast(header); // Add header - packet_push(payload, header, std::begin(payload)); + packet_push(payload, id < 0x400 ? id : id ^ flyff::PACKET_HEADER_HASH, std::begin(payload)); struct Vector { uintptr_t begin; @@ -66,7 +77,7 @@ namespace fugg { } void Client::send_logout() const { - send_packet(0x403, {}); + send_packet(flyff::PacketHeader::Logout, {}); } void Client::send_move_item_in_inventory(const uint32_t &from_slot, const uint32_t &to_slot) const { @@ -75,7 +86,7 @@ namespace fugg { packet_push(packet, from_slot); packet_push(packet, to_slot); - send_packet(0x2001, packet); + send_packet(flyff::PacketHeader::InventoryMoveItem, packet); } void Client::send_use_item_in_inventory(const uint32_t &slot) const { @@ -85,61 +96,63 @@ namespace fugg { // Unknown yet packet_push(packet, 0); - send_packet(0x410, packet); + send_packet(flyff::PacketHeader::InventoryUseItem, packet); } - void Client::send_motion_packet(const uint32_t &action, unsigned long long param0, unsigned long long param1, + void Client::send_motion_packet(const flyff::Action &action, unsigned long long param0, unsigned long long param1, unsigned long long param2, unsigned long long param3) const { - const int32_t motion_packet_id = 0x404; - const auto &neuz = flyff::Neuz::instance(); + const auto &client = fugg::Client::instance(); - if (!neuz.player) return; + if (!client.player) return; + auto result = flyff::Neuz::send_motion_packet(client.player, action, param0, param1, param2, param3); - std::vector packet; + std::cout << "Result from action " << action << " is " << result << std::endl; - uint8_t param_flags = 0; - if (param0 != 0) param_flags |= 1; - if (param1 != 0) param_flags |= 2; - if (param2 != 0) param_flags |= 4; - if (param3 != 0) param_flags |= 8; - - packet_push(packet, neuz.player->position); - packet_push(packet, action); - packet_push(packet, param_flags); - packet_push(packet, neuz.player->server_tick); - - if (param0 != 0) packet_push(packet, param0); - if (param1 != 0) packet_push(packet, param1); - if (param2 != 0) packet_push(packet, param2); - if (param3 != 0) packet_push(packet, param3); - - send_packet(motion_packet_id, packet); +// std::vector packet; +// +// uint8_t param_flags = 0; +// if (param0 != 0) param_flags |= 1; +// if (param1 != 0) param_flags |= 2; +// if (param2 != 0) param_flags |= 4; +// if (param3 != 0) param_flags |= 8; +// +// packet_push(packet, client.player->position); +// packet_push(packet, static_cast(action)); +// packet_push(packet, param_flags); +// packet_push(packet, client.player->server_tick); +// +// if (param0 != 0) packet_push(packet, param0); +// if (param1 != 0) packet_push(packet, param1); +// if (param2 != 0) packet_push(packet, param2); +// if (param3 != 0) packet_push(packet, param3); +// +// send_packet(flyff::PacketHeader::Motion, packet); } void Client::send_set_target(const unsigned long long &id) const { - send_motion_packet(0x04, id); + send_motion_packet(flyff::Action::Target, id); } void Client::send_clear_target() const { - send_motion_packet(0x04, {}); + send_motion_packet(flyff::Action::Target, 0); } void Client::send_interact_target(const unsigned long long &index) const { - send_motion_packet(0x11, index); + send_motion_packet(flyff::Action::Interact, index); } void Client::send_use_skill(const flyff::SkillID &id, unsigned long long unknown) const { - send_motion_packet(0x5, static_cast(id), unknown); + send_motion_packet(flyff::Action::Skill, static_cast(id), unknown); } void Client::send_follow_target(const unsigned long long &id) const { - send_motion_packet(0x10, id); + send_motion_packet(flyff::Action::Follow, id); } void Client::send_move_to(const double &x, const double &y, const double &z) const { // Mouse click send_motion_packet( - 0, + flyff::Action::Move, *reinterpret_cast(&x), *reinterpret_cast(&y), *reinterpret_cast(&z) @@ -147,10 +160,10 @@ namespace fugg { } void Client::send_correction(const double &speed) const { - send_motion_packet(0x18, *reinterpret_cast(&speed)); + send_motion_packet(flyff::Action::Correction, *reinterpret_cast(&speed)); } - void Client::send_chat_message(const std::string &message) const { + void Client::send_chat_message(const std::string &message) { std::vector packet; // Message length packet_push(packet, message.length()); @@ -163,33 +176,20 @@ namespace fugg { // Unknown 2 packet_push(packet, 0); - send_packet(0x2000, packet); + send_packet(flyff::PacketHeader::ChatMessage, packet); } } -#include -#include -#include - -#include -#include - -#include - -#include -#include - flyff::Pointer find_skill_buff(const flyff::Pointer &mover, const flyff::SkillID &skill_index) { + const auto &client = fugg::Client::instance(); for (const auto &buff: mover->buffs) { if (buff->get_type() == flyff::BuffType::Skill) { - auto skill_property = reinterpret_cast( - static_cast(buff->property) - ); + auto skill_id = static_cast(buff->get_id()); - if (!buff->is_removed && skill_property->id == skill_index) + if (!buff->is_removed && skill_id == skill_index) return buff; } } @@ -221,13 +221,17 @@ check_rebuff(const flyff::Pointer &buffer, const flyff::Pointer(buff->property) ); - std::cout << "Current skill level: " << current_skill_level << ", Player skill level: " << player_skill_level << std::endl; + std::cout << "Current skill level: " << current_skill_level << ", Player skill level: " + << player_skill_level << std::endl; if (player_skill_level > current_skill_level) { - std::cout << neuz.get_text(buff_property->name) << " has to be applied because it is lower level than what " << buffer->name << " has." << std::endl; + std::cout << neuz.get_text(buff_property->name) + << " has to be applied because it is lower level than what " << buffer->name << " has." + << std::endl; // Always apply a higher buff. result.push_back(skill_index); } else if (buff->get_time_remaining() < 30 * 1000 && player_skill_level >= current_skill_level) { - std::cout << neuz.get_text(buff_property->name) << " has to be applied because the buff is running out." << std::endl; + std::cout << neuz.get_text(buff_property->name) << " has to be applied because the buff is running out." + << std::endl; // Refresh the buff. result.push_back(skill_index); } @@ -571,10 +575,10 @@ void pickup_target(flyff::MoverID id, uint32_t action) { if (!client.player) return; - if (client.player->selected_target != id) { - client.player->selected_target = id; +// if (client.player->selected_target != id) { +// client.player->selected_target = id; client.send_set_target(id); - } +// } client.send_interact_target(action); } @@ -586,35 +590,17 @@ void attack_target(flyff::MoverID id) { const auto &target = client.get_mover(id); assert(target); - if (client.player->selected_target != id) { - client.player->selected_target = id; - client.send_set_target(id); + client.send_set_target(id); + client.send_interact_target(1); + + auto item = client.player->get_equipped_item(flyff::Part::MainHand); + assert(item); + + // Maybe Wand too... + if (item->item_kind3 == flyff::ItemKind3::Bow) { + // Release the 'charged' shot immediatly. + client.send_motion_packet(flyff::Action::ReleaseChargedAttack); } - - if (client.player->attack_target != id) { - auto item = client.player->get_equipped_item(flyff::Part::MainHand); - assert(item); - - auto range = client.player->get_attack_range(item->attack_range); - auto result = client.player->is_object_in_range(target, range); - - client.show_message("Range=" + std::to_string(range) + ", result=" + std::to_string(result)); - - if (result == 0) { - client.player->move_toward_target = id; - client.player->arrival_range = range; - } - - client.player->attack_target = id; - client.send_interact_target(1); - - // Maybe Wand too... - if (item->item_kind3 == flyff::ItemKind3::Bow) { - // Release the 'charged' shot immediatly. - client.send_motion_packet(0x15); - } - } - } flyff::MoverID current_target = 0; @@ -809,7 +795,6 @@ void attacker_script() { } else if (monster && !monster->is_dead() && neuz.player->attack_target == 0) { // Attack attack_target(monster->object_id); - // neuz.player->attack_target = monster->object_id; } else if ((!item || item->is_despawned) && (!monster || monster->is_dead())) { std::cout << "No item, no target. Searching..." << std::endl; @@ -831,7 +816,7 @@ void attacker_script() { } } // Only pickup if player has no pickup pet spawned. - if (client.player->pickup_pet_inventory_index == -1) { + if (client.player->pickup_pet_object_id == 0) { // No item target and no attack target current_pickup_item = find_next_item(); item = neuz.get_mover(current_pickup_item); diff --git a/fugg-client/src/Client.h b/fugg-client/src/Client.h index 7e5c95b..8900d76 100644 --- a/fugg-client/src/Client.h +++ b/fugg-client/src/Client.h @@ -17,7 +17,7 @@ namespace fugg { void operator=(Client const &) = delete; - void send_packet(const uint32_t &id, std::vector payload) const; + static void send_packet(const flyff::PacketHeader &header, std::__2::vector payload); void send_logout() const; @@ -25,7 +25,7 @@ namespace fugg { void send_use_item_in_inventory(const uint32_t &slot) const; - void send_motion_packet(const uint32_t &action, unsigned long long param0 = 0, unsigned long long param1 = 0, + void send_motion_packet(const flyff::Action &action, unsigned long long param0 = 0, unsigned long long param1 = 0, unsigned long long param2 = 0, unsigned long long param3 = 0) const; void send_set_target(const unsigned long long &id) const; @@ -41,7 +41,7 @@ namespace fugg { void send_correction(const double& speed) const; void send_move_to(const double &x, const double &y, const double &z) const; - void send_chat_message(const std::string &message) const; + static void send_chat_message(const std::string &message) ; }; diff --git a/fugg-client/src/main.cpp b/fugg-client/src/main.cpp index 7052245..73194a1 100644 --- a/fugg-client/src/main.cpp +++ b/fugg-client/src/main.cpp @@ -7,7 +7,7 @@ #include #include -// #include "client.h" +#include "Client.h" #define TRACE_ALLOC 0 @@ -67,13 +67,23 @@ void get_text(const std::string& text) { std::cout << text << " = \"" << result << "\"" << std::endl; } -uintptr_t to_outside(uint32_t ptr) { +uintptr_t to_outside(uintptr_t ptr) { return fugg::wasm::kMemory.address_of(ptr); } +void send_packet(uint32_t header, uintptr_t ptr, intptr_t length) { + const auto& bytes = reinterpret_cast(ptr); + + std::vector payload; + std::copy(&bytes[0], &bytes[length], std::back_inserter(payload)); + + fugg::Client::send_packet(static_cast(header), payload); +} + EMSCRIPTEN_BINDINGS(fugg) { emscripten::function("get_text", &get_text); emscripten::function("to_outside", &to_outside); + emscripten::function("send_packet", &send_packet); }; int main() {