Some refactors after installing CLion

This commit is contained in:
Knaapchen 2022-10-22 01:33:40 +02:00
parent 9af9d664f5
commit 97169c715f
11 changed files with 1088 additions and 710 deletions

View File

@ -2,6 +2,7 @@ add_library (
flyff-api
"src/flyff.cpp"
"src/Neuz.cpp"
"src/Mover.cpp"
"src/import.cpp"
"src/api.cpp"
"include/flyff.h"

View File

@ -5,6 +5,7 @@
// #include "../src/api.h"
#include "../src/Neuz.h"
#include "../src/Mover.h"
#include "../src/skill.h"
#include "../src/import.h"

View File

@ -14,275 +14,346 @@
namespace flyff {
namespace raw {
extern "C" {
namespace raw {
extern "C" {
// w2c_f410: CMover::GetHitPoint(PlayerObject* mover);
extern u32 w2c_f411(u32);
// w2c_f2454: CCooltimeMgr::CanUse(uint64_t* timers, ItemProperty* prop);
extern u32 w2c_f2466(u32, u32);
}
};
struct __attribute__((packed)) Mover {
static constexpr uint32_t MAX_PARAM = 0x52;
using Parameter = unsigned long;
using ObjectStateFlags = Object::StateFlags;
using ObjectState = Object::State;
struct __attribute__((packed)) Vtable {
union {
DEFINE_MEMBER(52, u32, get_level);
DEFINE_MEMBER(56, u32, get_gender);
DEFINE_MEMBER(144, u32, get_max_origin_hp);
DEFINE_MEMBER(148, u32, get_max_origin_mp);
const MinimumSize<220> __size;
};
}
};
struct __attribute__((packed)) Mover {
static constexpr uint32_t MAX_PARAM = 0x52;
union {
DEFINE_MEMBER(0x0, const Pointer<Vtable>, vtable);
using Parameter = unsigned long;
DEFINE_MEMBER(0x18, Matrix4, world_matrix);
DEFINE_MEMBER(152, Vector3, position);
DEFINE_MEMBER(164, Vector3, rotation);
DEFINE_MEMBER(188, Pointer<ObjectProperty>, property);
DEFINE_MEMBER(216, bool, is_despawned);
DEFINE_MEMBER(352, MoverID, object_id);
DEFINE_MEMBER(920, Parameter, adjustParam[MAX_PARAM]);
DEFINE_MEMBER(1248, Parameter, changeParam[MAX_PARAM]);
DEFINE_MEMBER(2020, const String, name);
DEFINE_MEMBER(1628, Vector3, move_target);
DEFINE_MEMBER(1688, unsigned long long, last_combat);
DEFINE_MEMBER(1728, MoverID, move_toward_target);
DEFINE_MEMBER(1736, MoverID, last_attacked_target);
DEFINE_MEMBER(1744, MoverID, selected_target);
// The id of the target that it hit last.
DEFINE_MEMBER(1752, MoverID, attack_target);
DEFINE_MEMBER(1760, MoverID, follow_target);
// The id, only non-zero when the attack animation plays, of the target it is attacking.
DEFINE_MEMBER(1768, MoverID, current_attack_target);
DEFINE_MEMBER(1776, MoverID, platform_standing_on);
DEFINE_MEMBER(1816, int, adj_param);
DEFINE_MEMBER(1820, uint32_t, server_tick);
DEFINE_MEMBER(1840, int, hitpoints);
DEFINE_MEMBER(1792, int, current_animation);
DEFINE_MEMBER(204, ObjectType, type);
DEFINE_MEMBER(216, uint32_t, existence_check);
DEFINE_MEMBER(1804, uint32_t, object_state);
DEFINE_MEMBER(1808, uint32_t, object_state_flags);
DEFINE_MEMBER(904, uint32_t, if_not_null_needsattackitem);
DEFINE_MEMBER(192, uintptr_t, world);
// Only works on players.
DEFINE_MEMBER(2472, uint32_t, level);
DEFINE_MEMBER(860, Vector<InventoryItem>, inventory);
DEFINE_MEMBER(3324, uint64_t, last_food_time);
DEFINE_MEMBER(3348, uint64_t, last_refresher_time);
DEFINE_MEMBER(3356, uint64_t, last_vitaldrink_time);
const MinimumSize<4096> __size;
};
bool can_use_item(const Pointer<ItemProperty>& property) {
return raw::w2c_f2466(kMemory.to_inside(&last_food_time), static_cast<u32>(property));
}
bool is_in_combat() const {
const unsigned long long& now = fugg::module_ref<unsigned long long>(0x00032880);
// 10 seconds
return now - last_combat < 10000000;
}
Parameter get_param(uint32_t index, Parameter base) const {
Parameter changeParam = get_change_param(index);
if(changeParam != 0x7FFFFFFF)
return changeParam;
Parameter adjustParam = get_adjust_param(index);
if(adjustParam)
return base + adjustParam;
else
return base;
}
Parameter get_adjust_param(Parameter index) const {
// Find these values in CMover::Init
return adjustParam[index] ^ adj_param ^ 0x0554e725 + index * 0x41c64e6d;
}
Parameter get_change_param(Parameter index) const {
return changeParam[index] ^ adj_param ^ index * 0x41c64e6d + 0xb5a52d1a;
}
u32 get_hp() const {
return raw::w2c_f411(kMemory.to_inside(this));
}
u32 get_max_hp() const {
static constexpr Parameter DST_HP_MAX = 0x2c;
static constexpr Parameter DST_HP_MAX_RATE = 0x35;
float factor = 1.0f;
int result = get_param(DST_HP_MAX, get_max_origin_hp());
int percent = get_param(DST_HP_MAX_RATE, 0);
using ObjectStateFlags = Object::StateFlags;
using ObjectState = Object::State;
factor += (float)percent / (float)100;
result = (int)(result * factor);
struct __attribute__((packed)) Vtable {
union {
DEFINE_MEMBER(52, u32, get_level);
DEFINE_MEMBER(56, u32, get_gender);
return result;
}
DEFINE_MEMBER(96, u32, get_active_hand_item_prop);
u32 get_hp_percent(int percent = 100) const {
int max = get_max_hp();
if(max == 0) return 0;
DEFINE_MEMBER(144, u32, get_max_origin_hp);
DEFINE_MEMBER(148, u32, get_max_origin_mp);
return get_hp() * percent / max;
}
const MinimumSize<220> __size;
};
};
u32 get_max_origin_hp() const {
using Fn = FunctionPointer<u32, u32, u32, u32>;
const auto& fn = fugg::function_ref<Fn>(vtable->get_max_origin_hp);
struct __attribute__((packed)) Skill {
union {
DEFINE_MEMBER(0, uintptr_t, index);
DEFINE_MEMBER(4, uintptr_t, level);
};
};
return fn(kMemory.to_inside(this), 0, 0);
}
struct __attribute__((packed)) Buff {
static constexpr Parameter BUFF_ITEM = 0;
static constexpr Parameter BUFF_SKILL = 1;
struct __attribute__((packed)) Vtable {
union {
DEFINE_MEMBER(28, uintptr_t, get_type);
DEFINE_MEMBER(32, uintptr_t, get_id);
};
};
union {
DEFINE_MEMBER(0, Pointer<Vtable>, vtable);
DEFINE_MEMBER(4, Pointer<ObjectProperty>, property);
DEFINE_MEMBER(8, Parameter, param_id);
DEFINE_MEMBER(16, uint64_t, time_instantiated);
DEFINE_MEMBER(24, uint64_t, time_total);
DEFINE_MEMBER(32, int, level);
DEFINE_MEMBER(36, bool, is_removed);
DEFINE_MEMBER(37, bool, is_sfx);
};
int get_type() const {
using Fn = FunctionPointer<u32, u32>;
const auto &fn = fugg::function_ref<Fn>(vtable->get_type);
return fn(kMemory.to_inside(this));
}
int get_id() const {
using Fn = FunctionPointer<u32, u32>;
const auto &fn = fugg::function_ref<Fn>(vtable->get_id);
return fn(kMemory.to_inside(this));
}
uint64_t get_time_remaining() const;
};
union {
DEFINE_MEMBER(0x0, const Pointer<Vtable>, vtable);
DEFINE_MEMBER(0x18, Matrix4, world_matrix);
DEFINE_MEMBER(152, Vector3, position);
DEFINE_MEMBER(164, Vector3, rotation);
DEFINE_MEMBER(188, Pointer<ObjectProperty>, property);
DEFINE_MEMBER(212, int, property_id);
DEFINE_MEMBER(216, bool, is_despawned);
DEFINE_MEMBER(352, MoverID, object_id);
DEFINE_MEMBER(920, Parameter, adjusted_parameters[MAX_PARAM]);
DEFINE_MEMBER(1248, Parameter, changed_parameters[MAX_PARAM]);
DEFINE_MEMBER(1576, Vector<Pointer<Buff>>, buffs);
DEFINE_MEMBER(2020, const String, name);
DEFINE_MEMBER(1628, Vector3, move_target);
DEFINE_MEMBER(1688, unsigned long long, last_combat);
DEFINE_MEMBER(1728, MoverID, move_toward_target);
DEFINE_MEMBER(1736, MoverID, last_attacked_target);
DEFINE_MEMBER(1744, MoverID, selected_target);
// The id of the target that it hit last.
DEFINE_MEMBER(1752, MoverID, attack_target);
DEFINE_MEMBER(1760, MoverID, follow_target);
// The id, only non-zero when the attack animation plays, of the target it is attacking.
DEFINE_MEMBER(1768, MoverID, current_attack_target);
DEFINE_MEMBER(1776, MoverID, platform_standing_on);
DEFINE_MEMBER(1816, int, adj_param);
DEFINE_MEMBER(1820, uint32_t, server_tick);
DEFINE_MEMBER(1840, int, hitpoints);
DEFINE_MEMBER(1848, int, is_grounded);
DEFINE_MEMBER(1792, int, current_animation);
DEFINE_MEMBER(204, ObjectType, type);
DEFINE_MEMBER(216, uint32_t, existence_check);
DEFINE_MEMBER(1804, uint32_t, object_state);
DEFINE_MEMBER(1808, uint32_t, object_state_flags);
DEFINE_MEMBER(904, uint32_t, if_not_null_needsattackitem);
DEFINE_MEMBER(192, uintptr_t, world);
DEFINE_MEMBER(860, Vector<InventoryItem>, inventory);
// int get_max_hp() const {
// return raw::w2c_f410(kMemory.to_inside(this));
// }
DEFINE_MEMBER(3324, uint64_t, last_food_time);
DEFINE_MEMBER(3348, uint64_t, last_refresher_time);
DEFINE_MEMBER(3356, uint64_t, last_vitaldrink_time);
uint32_t get_state() const {
return object_state;
}
DEFINE_MEMBER(3424, Vector<Skill>, skills);
uint32_t get_move_state() const {
return (object_state & ObjectState::MovementAll);
}
const MinimumSize<4096> size;
};
uint32_t get_turn_state() const {
return (object_state & ObjectState::TurnAll);
}
uint32_t get_skill_level(uint32_t skill_index) const {
for (const auto &skill: skills) {
if (skill_index == skill.index)
return skill.level;
}
uint32_t get_look_state() const {
return (object_state & ObjectState::LookAll);
}
return 0;
}
uint32_t get_jump_state() const {
return (object_state & ObjectState::JumpAll);
}
bool can_use_item(const Pointer<ItemProperty> &property) {
return raw::w2c_f2466(kMemory.to_inside(&last_food_time), static_cast<u32>(property));
}
uint32_t get_attack_state() const {
return (object_state & ObjectState::AtkAll);
}
bool is_in_combat() const;
uint32_t get_damage_state() const {
return (object_state & ObjectState::DmgAll);
}
Parameter get_param(uint32_t index, Parameter base) const {
Parameter changeParam = get_change_param(index);
if (changeParam != 0x7FFFFFFF)
return changeParam;
uint32_t get_action_state() const {
return (object_state & ObjectState::ActionAll);
}
Parameter adjustParam = get_adjust_param(index);
if (adjustParam)
return base + adjustParam;
else
return base;
}
bool is_fly() const {
return (object_state_flags & ObjectStateFlags::Fly) != 0;
}
Parameter get_adjust_param(Parameter index) const {
// Find these values in CMover::Init
return adjusted_parameters[index] ^ adj_param ^ 0x0554e725 + index * 0x41c64e6d;
}
bool is_dead() const {
return (object_state & ObjectState::DieAll) != 0;
}
Parameter get_change_param(Parameter index) const {
return changed_parameters[index] ^ adj_param ^ index * 0x41c64e6d + 0xb5a52d1a;
}
bool is_sit() const {
return (object_state_flags & ObjectStateFlags::Sit) != 0;
}
// Whether the movement state is running, not if the Mover
// is actually moving. See `is_moving()`
bool is_run() const {
return (object_state_flags & ObjectStateFlags::Walk) == 0;
}
// Whether the movement state is walking, not if the Mover
// is actually moving. See `is_moving()`
bool is_walk() const {
return (object_state_flags & ObjectStateFlags::Walk) != 0;
}
// Normal action - No other commands have any effect during this action.
bool is_action() const {
return (object_state & ObjectState::ActionAll) != 0;
}
u32 get_hp() const {
return raw::w2c_f411(kMemory.to_inside(this));
}
bool is_moving() const {
return (get_move_state() == ObjectState::MoveForward ||
get_move_state() == ObjectState::MoveBackward ||
get_move_state() == ObjectState::Left ||
get_move_state() == ObjectState::Right);
}
flyff::Pointer<flyff::ItemProperty> get_equipped_item(const flyff::Part &part) {
using Fn = FunctionPointer<u32, u32, u32>;
const auto &fn = fugg::function_ref<Fn>(vtable->get_active_hand_item_prop);
bool is_jumping() const {
return (object_state & ObjectState::JumpAll) != 0;
}
const auto &ptr = fn(kMemory.to_inside(this), static_cast<uint32_t>(part));
return flyff::Pointer<flyff::ItemProperty>(ptr);
}
bool is_attacking() const {
return (object_state & ObjectState::AtkAll) != 0;
}
uint32_t get_max_hp() const {
float factor = 1.0f;
int result = get_param(DST_HP_MAX, get_max_origin_hp());
int percent = get_param(DST_HP_MAX_RATE, 0);
bool is_damaged() const {
return (object_state & ObjectState::DmgAll) != 0;
}
factor += (float) percent / (float) 100;
result = static_cast<float>(result) * factor;
bool is_turning() const {
return (object_state & ObjectState::TurnAll) != 0;
}
return result;
}
u32 get_level() {
const auto& fn = fugg::function_ref<FunctionPointer<u32, u32>>(vtable->get_level);
uint32_t get_hp_percent(int percent = 100) const {
int max = get_max_hp();
if (max == 0) return 0;
return fn(kMemory.to_inside(this));
}
return get_hp() * percent / max;
}
// int32_t get_gender() {
// // The function itself works but I fear it returns wrong results.
// // Female player = 0
// // Male player = 0
// // Npc = 2
// const auto& fn = fugg::function_ref<FunctionPointer<int32_t, Pointer<Mover>>>(vtable->get_gender);
uint32_t get_max_origin_hp() const {
using Fn = FunctionPointer<u32, u32, u32, u32>;
const auto &fn = fugg::function_ref<Fn>(vtable->get_max_origin_hp);
// return fn(Pointer<Mover>(this));
// }
};
return fn(kMemory.to_inside(this), 0, 0);
}
struct MoverMap {
struct __attribute__((packed)) Node {
const Pointer<const Node> next;
unsigned int list_index;
unsigned long long hash;
Pointer<Mover> mover;
// int get_max_hp() const {
// return raw::w2c_f410(kMemory.to_inside(this));
// }
uint32_t get_state() const {
return object_state;
}
uint32_t get_move_state() const {
return (object_state & ObjectState::MovementAll);
}
uint32_t get_turn_state() const {
return (object_state & ObjectState::TurnAll);
}
uint32_t get_look_state() const {
return (object_state & ObjectState::LookAll);
}
uint32_t get_jump_state() const {
return (object_state & ObjectState::JumpAll);
}
uint32_t get_attack_state() const {
return (object_state & ObjectState::AtkAll);
}
uint32_t get_damage_state() const {
return (object_state & ObjectState::DmgAll);
}
uint32_t get_action_state() const {
return (object_state & ObjectState::ActionAll);
}
bool is_fly() const {
return (object_state_flags & ObjectStateFlags::Fly) != 0;
}
bool is_dead() const {
return (object_state & ObjectState::DieAll) != 0;
}
bool is_sit() const {
return (object_state_flags & ObjectStateFlags::Sit) != 0;
}
// Whether the movement state is running, not if the Mover
// is actually moving. See `is_moving()`
bool is_run() const {
return (object_state_flags & ObjectStateFlags::Walk) == 0;
}
// Whether the movement state is walking, not if the Mover
// is actually moving. See `is_moving()`
bool is_walk() const {
return (object_state_flags & ObjectStateFlags::Walk) != 0;
}
// Normal action - No other commands have any effect during this action.
bool is_action() const {
return (object_state & ObjectState::ActionAll) != 0;
}
bool is_moving() const {
return (get_move_state() == ObjectState::MoveForward ||
get_move_state() == ObjectState::MoveBackward ||
get_move_state() == ObjectState::Left ||
get_move_state() == ObjectState::Right);
}
bool is_jumping() const {
return (object_state & ObjectState::JumpAll) != 0;
}
bool is_attacking() const {
return (object_state & ObjectState::AtkAll) != 0;
}
bool is_damaged() const {
return (object_state & ObjectState::DmgAll) != 0;
}
bool is_turning() const {
return (object_state & ObjectState::TurnAll) != 0;
}
u32 get_level() {
const auto &fn = fugg::function_ref<FunctionPointer<u32, u32>>(vtable->get_level);
return fn(kMemory.to_inside(this));
}
// int32_t get_gender() {
// // The function itself works but I fear it returns wrong results.
// // Female player = 0
// // Male player = 0
// // Npc = 2
// const auto& fn = fugg::function_ref<FunctionPointer<int32_t, Pointer<Mover>>>(vtable->get_gender);
// return fn(Pointer<Mover>(this));
// }
};
const Pointer<const uintptr_t> buckets;
size_t capacity;
const Pointer<const Node> first;
};
struct MoverMap {
struct __attribute__((packed)) Node {
const Pointer<const Node> next;
unsigned int list_index;
unsigned long long hash;
Pointer<Mover> mover;
};
const Pointer<const uintptr_t> buckets;
size_t capacity;
const Pointer<const Node> first;
};
}; // namespace flyff

View File

@ -6,17 +6,20 @@
// static_assert(offsetof(TestMover, name) == 0x7f4, "Mover.name needs to be at
// 2020");
namespace flyff {
namespace raw {
static const uintptr_t& WORLD = 0x00035eb8;
static const uintptr_t& PLAYER = WORLD + 4;
static constexpr uintptr_t WORLD = 0x00035eb8;
static constexpr uintptr_t PLAYER = WORLD + 4;
static const uintptr_t& PLAYER_OBJECT_ID = 0x00034ef8;
static constexpr uintptr_t PLAYER_OBJECT_ID = 0x00034ef8;
// The messages that are limited to 5 that are show temporarily.
static const uintptr_t& MESSAGES_UI = 0x00035ec8;
static const uintptr_t& ANNOUNCEMENTS_UI = 0x00034c94;
static const uintptr_t& MOVER_MAP = 0x000332c8;
static constexpr uintptr_t MESSAGES_UI = 0x00035ec8;
static constexpr uintptr_t ANNOUNCEMENTS_UI = 0x00034c94;
static constexpr uintptr_t MOVER_MAP = 0x000332c8;
static constexpr uintptr_t CURRENT_TIME = 0x00032880;
static constexpr uintptr_t START_TIME = 0x000328c0;
static constexpr uintptr_t MAYBE_LOGIN_TIME = START_TIME + 8;
extern "C" {
// get_mover
@ -29,6 +32,8 @@ extern void w2c_f341(u32, u32, u32);
extern void w2c_f607(u32, u32, u32);
// can_attack_target
extern u32 w2c_f515(u32, u32);
// CProject::GetSkillProp()
extern u32 w2c_f440(u32, u32);
};
static const auto& get_mover = w2c_f208;
@ -36,6 +41,7 @@ static const auto& get_text = w2c_f167;
static const auto& show_message = w2c_f341;
static const auto& show_announcement = w2c_f607;
static const auto& can_attack_target = w2c_f515;
static const auto& get_skill_prop = w2c_f440;
}; // namespace raw
// Emscripten runtime:
@ -50,7 +56,10 @@ Neuz::Neuz()
player(make_ref<Pointer<Mover>>(raw::PLAYER)),
messages_ui(make_ref<Pointer<uintptr_t>>(raw::MESSAGES_UI)),
announcements_ui(make_ref<Pointer<uintptr_t>>(raw::ANNOUNCEMENTS_UI)),
player_object_id(make_ref<MoverID>(raw::PLAYER_OBJECT_ID)) {}
player_object_id(make_ref<MoverID>(raw::PLAYER_OBJECT_ID)),
current_time(make_ref<uint64_t>(raw::CURRENT_TIME)),
start_time(make_ref<uint64_t>(raw::START_TIME)),
maybe_login_time(make_ref<uint64_t>(raw::MAYBE_LOGIN_TIME)) {}
Neuz& Neuz::instance() {
static bool initialised = false;
@ -126,9 +135,14 @@ void Neuz::show_announcement(const std::string& message,
bool Neuz::is_valid_attack(const Pointer<Mover>& attacker,
const Pointer<Mover>& defender) const {
auto result =
raw::can_attack_target(static_cast<u32>(attacker), static_cast<u32>(defender));
auto result = raw::can_attack_target(static_cast<u32>(attacker),
static_cast<u32>(defender));
return result != 0;
}
Pointer<SkillProperty> Neuz::get_skill_property(int id) const {
return Pointer<SkillProperty>(raw::get_skill_prop(id, 1));
}
} // namespace flyff

View File

@ -4,6 +4,7 @@
#include <cstdint>
#include "skill.h"
#include "Mover.h"
namespace flyff {
@ -38,6 +39,10 @@ class Neuz {
const Pointer<Mover>& player;
const MoverID& player_object_id;
const uint64_t& current_time;
const uint64_t& start_time;
const uint64_t& maybe_login_time;
// Execute the `main` function of the flyff-client.
int main() const;
@ -53,6 +58,8 @@ class Neuz {
bool is_valid_attack(const Pointer<Mover>& attacker, const Pointer<Mover>& defender) const;
Pointer<SkillProperty> get_skill_property(int id) const;
// Easy to implement: Just send a EmscriptenKeyboardEvent* to the registered
// function. void send_keydown(); void send_keyup(); void send_keypress();
};

View File

@ -10,7 +10,7 @@
template<typename ReturnType, typename... Args>
using FunctionPointer = ReturnType(*)(Args...);
template <const size_t kSize>
template<const size_t kSize>
class MinimumSize {
unsigned char __padding[kSize];
};
@ -26,95 +26,98 @@ class MinimumSize {
namespace flyff {
class Memory {
wasm_rt_memory_t** memory;
public:
explicit Memory(wasm_rt_memory_t** mem) : memory(mem) {}
uintptr_t start() const {
return reinterpret_cast<uintptr_t>((*memory)->data);
}
uintptr_t to_inside(const uintptr_t offset) {
return offset != NULL ? offset - start() : NULL;
}
intptr_t to_inside(const void* offset) {
return to_inside(reinterpret_cast<uintptr_t>(offset));
}
uintptr_t to_outside(const uintptr_t offset) {
return offset != NULL ? reinterpret_cast<uintptr_t>(&(*memory)->data[offset]) : NULL;
}
template <typename T>
T* to_outside(const T* offset) {
return reinterpret_cast<T*>(
to_outside(reinterpret_cast<uintptr_t>(offset)));
}
};
static auto kMemory = Memory(&Z_clientZ_memory);
class Table {};
static const auto& kTable = &Z_clientZ_table;
template<typename T>
T& make_ref(uintptr_t address) {
return *reinterpret_cast<T*>(kMemory.to_outside(address));
}
template <typename T>
class __attribute__((packed)) Pointer {
// Always located INSIDE the flyff module.
uintptr_t offset;
T* as_outside() const {
return reinterpret_cast<T*>(kMemory.to_outside(offset));
}
Pointer() : offset(0) { }
class Memory {
wasm_rt_memory_t **memory;
public:
explicit Pointer(void* ptr) : offset(ptr == nullptr ? 0 : kMemory.to_inside(reinterpret_cast<uintptr_t>(ptr))) { }
explicit Pointer(uintptr_t ptr) : offset(ptr) { }
explicit Memory(wasm_rt_memory_t **mem) : memory(mem) {}
Pointer(const Pointer<T>& other) : offset(other.offset) { }
Pointer<T>& operator=(Pointer<T> other) {
offset = other.offset;
return *this;
uintptr_t start() const {
return reinterpret_cast<uintptr_t>((*memory)->data);
}
uintptr_t to_inside(const uintptr_t offset) const {
return offset != NULL ? offset - start() : NULL;
}
uintptr_t to_inside(const void *offset) const {
return to_inside(reinterpret_cast<uintptr_t>(offset));
}
uintptr_t to_outside(const uintptr_t offset) {
return offset != NULL ? reinterpret_cast<uintptr_t>(&(*memory)->data[offset]) : NULL;
}
template<typename T>
T *to_outside(const T *offset) {
return reinterpret_cast<T *>(
to_outside(reinterpret_cast<uintptr_t>(offset)));
}
};
static auto kMemory = Memory(&Z_clientZ_memory);
class Table {
};
static const auto &kTable = &Z_clientZ_table;
template<typename T>
T &make_ref(uintptr_t address) {
return *reinterpret_cast<T *>(kMemory.to_outside(address));
}
T* operator->() const {
return as_outside();
}
template<typename T>
class __attribute__((packed)) Pointer;
T& operator*() const {
return *as_outside();
}
template<typename T>
class __attribute__((packed)) Pointer {
// Always located INSIDE the flyff module.
uintptr_t offset;
explicit operator T*() const {
return as_outside();
}
T *as_outside() const {
return reinterpret_cast<T *>(kMemory.to_outside(offset));
}
explicit operator u32() const {
return offset;
}
Pointer() : offset(0) {}
explicit operator bool() const {
return offset != 0 ? as_outside() != nullptr : false;
}
public:
explicit Pointer(void const *ptr) : offset(
ptr == nullptr ? 0 : kMemory.to_inside(reinterpret_cast<uintptr_t>(ptr))) {}
bool operator==(Pointer<T> const& rhs) const { return offset == rhs.offset; }
explicit Pointer(uintptr_t ptr) : offset(ptr) {}
friend std::ostream& operator<<(std::ostream& os, const Pointer<T>& ptr) {
os << reinterpret_cast<void*>(ptr.offset);
return os;
}
};
Pointer(const Pointer<T> &other) : offset(other.offset) {}
Pointer<T> &operator=(Pointer<T> other) {
offset = other.offset;
return *this;
}
T *operator->() const {
return as_outside();
}
explicit operator T *() const {
return as_outside();
}
explicit operator u32() const {
return offset;
}
explicit operator bool() const {
return offset != 0 && as_outside() != nullptr;
}
bool operator==(Pointer<T> const &rhs) const { return offset == rhs.offset; }
friend std::ostream &operator<<(std::ostream &os, const Pointer<T> &ptr) {
os << reinterpret_cast<void *>(ptr.offset);
return os;
}
};
// Allocates an unmanaged pointer inside the flyff module.
// template <class T, class... Args>
@ -122,81 +125,81 @@ class __attribute__((packed)) Pointer {
// return Pointer<T>(new T(std::forward<Args>(args)...));
// }
class __attribute__((packed)) String {
union {
DEFINE_MEMBER(0x0, char*, text);
DEFINE_MEMBER(0x4, size_t, length);
DEFINE_MEMBER(0x8, void*, capacity);
class __attribute__((packed)) String {
union {
DEFINE_MEMBER(0x0, char*, text);
DEFINE_MEMBER(0x4, size_t, length);
DEFINE_MEMBER(0x8, void*, capacity);
DEFINE_MEMBER(0x0, char, data[1]);
DEFINE_MEMBER(0xb, char, short_length);
DEFINE_MEMBER(0x0, char, data[1]);
DEFINE_MEMBER(0xb, char, short_length);
const MinimumSize<12> __size;
};
const MinimumSize<12> __size;
};
public:
// This has to be const until strings can allocate...
operator const std::string() const {
auto copy = *this;
public:
// This has to be const until strings can allocate...
operator const std::string() const {
auto copy = *this;
auto is_short = -1 < copy.short_length;
if (!is_short) {
copy.text = kMemory.to_outside(text);
// TODO: Probably offset capacity too.
auto is_short = -1 < copy.short_length;
if (!is_short) {
copy.text = kMemory.to_outside(text);
// TODO: Probably offset capacity too.
}
return *reinterpret_cast<std::string *>(&copy);
}
return *reinterpret_cast<std::string*>(&copy);
}
friend std::ostream &operator<<(std::ostream &os, const String &str) {
const std::string conv = str;
os << conv;
return os;
}
};
friend std::ostream& operator<<(std::ostream& os, const String& str) {
const std::string conv = str;
os << conv;
return os;
}
};
typedef unsigned long long MoverID;
typedef unsigned long long MoverID;
static_assert(sizeof(String) == sizeof(std::string),
"String needs to be the same size as std::string");
static_assert(sizeof(String) == sizeof(std::string),
"String needs to be the same size as std::string");
template<typename T>
class __attribute__((packed)) Vector {
// const Pointer<T>& begin_;
// const Pointer<T>& end_;
// const Pointer<T>& capacity_;
Pointer<T> begin_;
Pointer<T> end_;
Pointer<T> capacity_;
template<typename T>
class __attribute__((packed)) Vector {
// const Pointer<T>& begin_;
// const Pointer<T>& end_;
// const Pointer<T>& capacity_;
Pointer<T> begin_;
Pointer<T> end_;
Pointer<T> capacity_;
Vector() : begin_(nullptr), end_(nullptr), capacity_(nullptr) {}
Vector() : begin_(nullptr), end_(nullptr), capacity_(nullptr) { }
public:
typedef T *iterator;
typedef const T *const_iterator;
public:
typedef T* iterator;
typedef const T* const_iterator;
// This has to be const until strings can allocate...
T *begin() const {
return static_cast<T *>(begin_);
}
// This has to be const until strings can allocate...
T* begin() const {
return static_cast<T*>(begin_);
}
T *end() const {
return static_cast<T *>(end_);
}
T* end() const {
return static_cast<T*>(end_);
}
// friend std::ostream& operator<<(std::ostream& os, const String& str) {
// const std::string conv = str;
// os << conv;
// return os;
// }
};
// friend std::ostream& operator<<(std::ostream& os, const String& str) {
// const std::string conv = str;
// os << conv;
// return os;
// }
};
static_assert(sizeof(Vector<char>) == sizeof(std::vector<char>),
"Vector needs to be the same size as std::vector");
static_assert(sizeof(Vector<char>) == sizeof(std::vector<char>),
"Vector needs to be the same size as std::vector");
class HashMap {
};
class HashMap {
};
}; // namespace flyff

View File

@ -1,66 +1,135 @@
#pragma once
#include "core.h"
#include <iostream>
#include "core.h"
namespace flyff {
struct __attribute__((packed)) ItemProperty {
static constexpr uint32_t IK2_FOOD = 14;
static constexpr uint32_t IK3_QUEST = 43;
static constexpr uint32_t COOLDOWN_FOOD = 0x00;
static constexpr uint32_t COOLDOWN_REFRESHER = 0x03;
static constexpr uint32_t COOLDOWN_VITALDRINK = 0x04;
enum class Part : uint32_t {
// Excluded from equipment
Head = 0,
// Excluded from equipment
Hair = 1,
UpperBody = 2,
LowerBody = 3,
Hand = 4,
Foot = 5,
Helmet = 6,
Robe = 7,
Cloak = 8,
OffHand = 9,
MainHand = 10,
Shield = 11,
Mask = 12,
// Exclude from equipment - This is to go after #16, but it has to
// be converted, so I solved it this way.
RIDE = 13,
// Simultaneous output parts up to here
// If you want to increase the number above 16, you must tell xuzhu.
// Otherwise, it's an error.
static constexpr uint32_t RECOVERY_COOLDOWN_INDEX[] = {
0x03, 0x04, 0x00, 0x00, 0x01
CAP2 = 14, // Exclude from equipment
UPPER2 = 15, // Exclude from equipment
// For parts that are not rendered on the actual screen, use 16 or more.
// earrings, rings, etc.
LOWER2 = 16,
HAND2 = 17,
FOOT2 = 18,
// Installed up to here, but by installing this, other parts are invisible.
// (It's different from Exclusive.)
// Necklace
NECKLACE1 = 19,
// Ring
RING1 = 20,
RING2 = 21,
// Earrings
EARRING1 = 22,
EARRING2 = 23,
// A space to wear props except necklaces, rings, and earrings
PROPERTY = 24,
// various bullet slots
BULLET = 25,
// Fashion item hat
HAT = 26,
// Fashion Outfits
CLOTH = 27,
// Fashion Gloves
GLOVE = 28,
// Fashion Boots
BOOTS = 29,
// Fashion Cloak
CLOAK2 = 30,
};
union {
DEFINE_MEMBER(0, const flyff::String, model);
DEFINE_MEMBER(12, const uint32_t, id);
DEFINE_MEMBER(156, const flyff::String, name);
DEFINE_MEMBER(168, const flyff::String, icon);
DEFINE_MEMBER(180, const flyff::String, description);
// Has to be bigger that 0 to be considered for cooldown.
DEFINE_MEMBER(112, const int32_t, cooldown_time);
DEFINE_MEMBER(348, const uint32_t, item_kind2);
DEFINE_MEMBER(352, const uint32_t, item_kind3);
const MinimumSize<456> __size;
enum class ItemKind2 : uint32_t {
Food = 14,
Quest = 25,
};
bool is_food() {
static const uint32_t RECOVERY_SUB_CATEGORY_START = 1400;
enum class ItemKind3 : uint32_t {
CheerStick = 202,
KnuckleHammer = 203,
if(item_kind2 == IK2_FOOD) {
const uint32_t cd = item_kind3 - RECOVERY_SUB_CATEGORY_START;
if(cd < 5) {
return RECOVERY_COOLDOWN_INDEX[cd] == COOLDOWN_FOOD;
Shield = 300,
};
struct __attribute__((packed)) ItemProperty {
static constexpr uint32_t COOLDOWN_FOOD = 0x00;
static constexpr uint32_t COOLDOWN_REFRESHER = 0x03;
static constexpr uint32_t COOLDOWN_VITALDRINK = 0x04;
static constexpr uint32_t RECOVERY_COOLDOWN_INDEX[] = {0x03, 0x04, 0x00,
0x00, 0x01};
union {
DEFINE_MEMBER(0, const flyff::String, model);
DEFINE_MEMBER(12, const uint32_t, id);
DEFINE_MEMBER(244, const uint32_t, required_level);
DEFINE_MEMBER(156, const flyff::String, name);
DEFINE_MEMBER(168, const flyff::String, icon);
DEFINE_MEMBER(180, const flyff::String, description);
// Has to be bigger that 0 to be considered for cooldown.
DEFINE_MEMBER(112, const int32_t, cooldown_time);
DEFINE_MEMBER(348, const ItemKind2, item_kind2);
DEFINE_MEMBER(352, const ItemKind3, item_kind3);
const MinimumSize<456> size;
};
bool is_food() const {
static const uint32_t RECOVERY_SUB_CATEGORY_START = 1400;
if (item_kind2 == ItemKind2::Food) {
const uint32_t cd = static_cast<uint32_t>(item_kind3) - RECOVERY_SUB_CATEGORY_START;
if (cd < 5) {
return RECOVERY_COOLDOWN_INDEX[cd] == COOLDOWN_FOOD;
}
}
return false;
}
return false;
}
bool is_quest() {
return item_kind3 == IK3_QUEST;
}
};
struct __attribute__((packed)) InventoryItem {
union {
DEFINE_MEMBER(36, Pointer<ItemProperty>, property);
DEFINE_MEMBER(60, int32_t, index);
DEFINE_MEMBER(64, uint32_t, quantity);
const MinimumSize<96> __size;
bool is_quest() const { return item_kind2 == ItemKind2::Quest; }
};
struct __attribute__((packed)) InventoryItem {
union {
DEFINE_MEMBER(36, Pointer<ItemProperty>, property);
DEFINE_MEMBER(60, int32_t, index);
DEFINE_MEMBER(64, uint32_t, quantity);
const MinimumSize<96> size;
};
};
};
} // namespace flyff

View File

@ -681,7 +681,7 @@ static void w2c_f436(u32, u32, u32);
static u32 w2c_f437(u32);
static void w2c_f438(u32);
static void w2c_f439(u32, u32);
static u32 w2c_f440(u32, u32);
u32 w2c_f440(u32, u32);
static void w2c_f441(u32, u64, u64, u64, u64);
static void w2c_f442(u32, u32, u32, u32);
static u32 w2c_f443(u32, u32, u32, u32, u32);
@ -122491,7 +122491,7 @@ static void w2c_f439(u32 w2c_p0, u32 w2c_p1) {
FUNC_EPILOGUE;
}
static u32 w2c_f440(u32 w2c_p0, u32 w2c_p1) {
u32 w2c_f440(u32 w2c_p0, u32 w2c_p1) {
u32 w2c_l2 = 0, w2c_l3 = 0, w2c_l4 = 0, w2c_l5 = 0, w2c_l6 = 0, w2c_l7 = 0, w2c_l8 = 0;
FUNC_PROLOGUE;
u32 w2c_i0, w2c_i1, w2c_i2, w2c_i3;

View File

@ -9,7 +9,7 @@ add_executable(
"src/export/embind.cpp"
"src/export/env.cpp"
"src/export/platform.cpp"
)
src/Bot.cpp src/Bot.h src/Action.h)
# Flyff is based on c++14
add_definitions(-std=c++14 -Os)

View File

@ -5,32 +5,31 @@
#include <iostream>
#include <sstream>
namespace fugg
{
namespace fugg {
}
constexpr const uint32_t hash_to_id(const uint32_t hashed) {
constexpr const uint32_t hash_to_id(const uint32_t hashed) {
return hashed ^ flyff::PACKET_HEADER_HASH;
}
template<typename T>
void packet_push(std::vector<uint8_t>& packet, const T& value, std::vector<uint8_t>::iterator offset) {
void packet_push(std::vector<uint8_t> &packet, const T &value, std::vector<uint8_t>::iterator offset) {
union ToBytes {
T value;
uint8_t bytes[sizeof(T)];
uint8_t bytes[sizeof(T)];
};
ToBytes ref = { value };
ToBytes ref = {value};
packet.insert(offset, std::begin(ref.bytes), std::end(ref.bytes));
}
template<typename T>
void packet_push(std::vector<uint8_t>& packet, const T& value) {
void packet_push(std::vector<uint8_t> &packet, const T &value) {
return packet_push(packet, value, std::end(packet));
}
void send_packet(const uint32_t& id, std::vector<uint8_t> payload) {
void send_packet(const uint32_t &id, std::vector<uint8_t> payload) {
const uint32_t header = id < 0x400 ? id : id ^ flyff::PACKET_HEADER_HASH;
// Add header
packet_push(payload, header, std::begin(payload));
@ -40,22 +39,22 @@ void send_packet(const uint32_t& id, std::vector<uint8_t> payload) {
uintptr_t end;
uintptr_t capacity;
};
auto raw_payload = reinterpret_cast<const Vector*>(&payload);
auto raw_payload = reinterpret_cast<const Vector *>(&payload);
// Copy the message into a new ptr
auto payload_ = std::unique_ptr<Vector>(new Vector {
.begin = fugg::RuntimePointer<uintptr_t>(raw_payload->begin).as_raw(),
.end = fugg::RuntimePointer<uintptr_t>(raw_payload->end).as_raw(),
.capacity = fugg::RuntimePointer<uintptr_t>(raw_payload->capacity).as_raw()
auto payload_ = std::unique_ptr<Vector>(new Vector{
.begin = fugg::RuntimePointer<uintptr_t>(raw_payload->begin).as_raw(),
.end = fugg::RuntimePointer<uintptr_t>(raw_payload->end).as_raw(),
.capacity = fugg::RuntimePointer<uintptr_t>(raw_payload->capacity).as_raw()
});
flyff::api::finalize_packet(
fugg::RuntimePointer<Vector>(payload_.get()).as_raw()
fugg::RuntimePointer<Vector>(payload_.get()).as_raw()
);
flyff::api::websocket_send(
payload_->begin,
payload_->end - payload_->begin
payload_->begin,
payload_->end - payload_->begin
);
}
@ -74,7 +73,7 @@ void send_logout() {
#include <cstddef>
void move_item_in_inventory(const uint32_t& from_slot, const uint32_t& to_slot) {
void move_item_in_inventory(const uint32_t &from_slot, const uint32_t &to_slot) {
std::vector<uint8_t> packet;
packet_push<uint32_t>(packet, from_slot);
@ -83,7 +82,7 @@ void move_item_in_inventory(const uint32_t& from_slot, const uint32_t& to_slot)
send_packet(0x2001, packet);
}
void use_item_in_inventory(const uint32_t& slot) {
void use_item_in_inventory(const uint32_t &slot) {
std::vector<uint8_t> packet;
packet_push<uint32_t>(packet, slot);
@ -93,51 +92,60 @@ void use_item_in_inventory(const uint32_t& slot) {
send_packet(0x410, packet);
}
using MotionParam = unsigned long long;
struct MotionPacketParams {
unsigned long long param0 = 0;
unsigned long long param1 = 0;
unsigned long long param2 = 0;
unsigned long long param3 = 0;
};
void send_motion_packet(
const uint32_t& action,
MotionParam param0 = 0,
MotionParam param1 = 0,
MotionParam param2 = 0,
MotionParam param3 = 0
const uint32_t &action,
MotionPacketParams params,
uint32_t server_tick_delta = 0
) {
const int32_t motion_packet_id = 0x404;
const auto& neuz = flyff::Neuz::instance();
const auto &neuz = flyff::Neuz::instance();
if(!neuz.player) return;
if (!neuz.player) return;
std::vector<uint8_t> 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;
if (params.param0 != 0) param_flags |= 1;
if (params.param1 != 0) param_flags |= 2;
if (params.param2 != 0) param_flags |= 4;
if (params.param3 != 0) param_flags |= 8;
packet_push<flyff::Vector3>(packet, neuz.player->position);
packet_push<uint8_t>(packet, action);
packet_push<uint8_t>(packet, param_flags);
packet_push(packet, neuz.player->server_tick);
packet_push(packet, neuz.player->server_tick + server_tick_delta);
if(param0 != 0) packet_push<unsigned long long>(packet, param0);
if(param1 != 0) packet_push<unsigned long long>(packet, param1);
if(param2 != 0) packet_push<unsigned long long>(packet, param2);
if(param3 != 0) packet_push<unsigned long long>(packet, param3);
if (params.param0 != 0) packet_push<unsigned long long>(packet, params.param0);
if (params.param1 != 0) packet_push<unsigned long long>(packet, params.param1);
if (params.param2 != 0) packet_push<unsigned long long>(packet, params.param2);
if (params.param3 != 0) packet_push<unsigned long long>(packet, params.param3);
send_packet(motion_packet_id, packet);
}
void set_target(const unsigned long long& id) {
send_motion_packet(0x04, id);
void set_target(const unsigned long long &id) {
send_motion_packet(0x04, {id});
}
void clear_target() {
send_motion_packet(0x04);
send_motion_packet(0x04, {});
}
void interact_target(const unsigned long long& index) {
send_motion_packet(0x11, index);
void interact_target(const unsigned long long &index) {
send_motion_packet(0x11, {index});
}
void use_skill(unsigned long long id, uint32_t server_tick_delta = 0) {
static constexpr unsigned long long param1 = -1;
send_motion_packet(0x5, {id, param1}, server_tick_delta);
}
// void move_to(const float& x, const float& y, const float& z) {
@ -151,14 +159,14 @@ void interact_target(const unsigned long long& index) {
// );
// }
void write_chat_message(const std::string& message) {
void write_chat_message(const std::string &message) {
// 00 94 4A 64 [0B 00 00 00] [48 65 6C 6C 6F 20 77 6F 72 6C 64] 00 00 00 00 00 00 00 00
std::vector<uint8_t> packet;
// Message length
packet_push<uint32_t>(packet, message.length());
// Write message
for(const auto& character : message) {
for (const auto &character: message) {
packet_push<uint8_t>(packet, character);
}
// Unknown 1
@ -169,53 +177,223 @@ void write_chat_message(const std::string& message) {
send_packet(0x2000, packet);
}
flyff::Pointer<flyff::Mover::Buff> find_skill_buff(const flyff::Pointer<flyff::Mover> &mover, uint32_t skill_index) {
for (const auto &buff: mover->buffs) {
if (buff->get_type() == flyff::Mover::Buff::BUFF_SKILL) {
auto skill_property = reinterpret_cast<flyff::SkillProperty *>(
static_cast<flyff::ObjectProperty *>(buff->property)
);
if (!buff->is_removed && skill_property->id == skill_index)
return buff;
}
}
return flyff::Pointer<flyff::Mover::Buff>(nullptr);
}
template<size_t size>
std::vector<uint32_t> check_rebuff(const flyff::Pointer<flyff::Mover> &player, const uint32_t (&buffs_to_check)[size]) {
const auto &neuz = flyff::Neuz::instance();
auto result = std::vector<uint32_t>();
for (const auto &skill_index: buffs_to_check) {
const auto &buff = find_skill_buff(player, skill_index);
const auto &skill_property = neuz.get_skill_property(skill_index);
// If a buff is active
if (buff) {
auto player_skill_level = player->get_skill_level(skill_index);
// For some reason it's one off...
auto current_skill_level = buff->level + 1;
auto buff_property = reinterpret_cast<flyff::SkillProperty *>(
static_cast<flyff::ObjectProperty *>(buff->property)
);
if (player_skill_level > current_skill_level) {
// Always apply a higher buff.
result.push_back(skill_index);
} else if (buff->get_time_remaining() < 30 * 1000 && player_skill_level >= current_skill_level) {
// Refresh the buff.
result.push_back(skill_index);
}
} else {
// Apply the buff.
result.push_back(skill_index);
}
}
return result;
}
flyff::Pointer<flyff::InventoryItem> find_first_equippable_item(const flyff::ItemKind3& item_kind) {
const auto &neuz = flyff::Neuz::instance();
const auto &player = neuz.player;
uint32_t highest_level = 0;
flyff::InventoryItem const *highest = nullptr;
for (const auto &item: player->inventory) {
const auto &prop = item.property;
if (item.index < 168 && prop && prop->item_kind3 == item_kind && prop->required_level <= player->get_level() &&
prop->required_level > highest_level) {
highest = &item;
highest_level = prop->required_level;
}
}
return flyff::Pointer<flyff::InventoryItem>(highest);
}
bool is_running = false;
flyff::Vector3 start_position = { 0 };
void on_keyup_hook(int event_type, const EmscriptenKeyboardEvent* event, void* user_data) {
const auto& neuz = flyff::Neuz::instance();
flyff::Vector3 start_position = {0};
// The object property index of the monster to grind.
int object_property_index = 0;
void on_keyup_hook(int event_type, const EmscriptenKeyboardEvent *event, void *user_data) {
const auto &neuz = flyff::Neuz::instance();
if (event->keyCode == 220) {
// if (!main_hand || main_hand->item_kind3 != flyff::ItemProperty::CheerStick) {
// const auto &stick = find_first_equippable_item(flyff::ItemProperty::CheerStick);
//
// if (stick) {
// std::string str = "Found valid cheerstick: ";
// str.append(neuz.get_text(stick->property->name));
// neuz.show_message(str, {0, 0xFF, 0});
//
// use_item_in_inventory(stick->index);
// }
// }
// std::cout << reinterpret_cast<void*>(static_cast<u32>(main_hand)) << " Weapon is required level: " << main_hand->required_level << std::endl;
// auto length = ((uintptr_t)player->buffs.end() - (uintptr_t)player->buffs.begin()) / 4;
// std::cout << length << " buffs!" << std::endl;;
// for(const auto& test : player->buffs) {
// std::cout << "Buff with type " << test->get_type() << " and id " << reinterpret_cast<void*>(test->get_id()) << std::endl;
// if(test->get_type() == flyff::Mover::Buff::BUFF_SKILL) {
// auto skill_property = reinterpret_cast<flyff::SkillProperty*>(
// static_cast<flyff::ObjectProperty*>(test->property)
// );
// std::cout << "BuffSkill "
// << neuz.get_text(skill_property->name)
// << " ReqLv. " << skill_property->required_level
// << " Lv." << skill_property->level
// << " Id: " << reinterpret_cast<void*>(skill_property->id)
// << " Remaining: " << (test->get_time_remaining() / 1000)
// << std::endl;
// }
// }
//
// clear_target();
// auto items = player->inventory.begin();
// auto length = ((uintptr_t)player->inventory.end() - (uintptr_t)player->inventory.begin()) / 0x60;
// static constexpr int max_inventory_size = 168;
// static constexpr int slot_weapon = max_inventory_size + 10;
// int stick_index = -1;
// if(items[slot_weapon].index != -1 &&
// items[slot_weapon].property &&
// items[slot_weapon].property->item_kind3 == flyff::ItemProperty::CheerStick) {
// stick_index = slot_weapon;
// } else {
// for(auto i = 0; i < length; i++) {
// if(items[i].index != -1 && items[i].property) {
// // if(items[i].index < 168) InventoryItem
// // else Equipped
// // std::cout << items[i].index << std::endl;
// std::cout << neuz.get_text(items[i].property->name) << " at " << items[i].index << ": "
// << "IK2=" << items[i].property->item_kind2 << ", "
// << "IK3=" << items[i].property->item_kind3
// << std::endl;
// if(items[i].property->item_kind3 == flyff::ItemProperty::CheerStick) {
// stick_index = i;
// break;
// }
// }
// }
// if(stick_index != -1) {
// // Switch main_hand
// use_item_in_inventory(stick_index);
// }
// }
// if(stick_index != -1) {
// // Use skill Heal
// use_skill(0x2c, 10);
// } else {
// neuz.show_message("Could not find a stick to heal myself.", { 0xFF, 0, 0 });
// }
}
// BracketLeft
if(event->keyCode == 219 && is_running == false) {
if(!neuz.player)
if (event->keyCode == 219 && !is_running) {
if (!neuz.player)
return;
start_position = { neuz.player->position.x, neuz.player->position.y, neuz.player->position.z };
if (neuz.player->selected_target == 0) {
neuz.show_message("No monster selected, unable to start bot.", {0xFF, 0, 0});
return;
}
auto target = neuz.get_mover(neuz.player->selected_target);
if (!target) {
neuz.show_message("No monster selected, unable to start bot.", {0xFF, 0xFF, 0});
return;
}
std::string str = "I'm only going to kill ";
str.append(neuz.get_text(target->name));
str.append("<Lv. ");
str.append(std::to_string(target->get_level()));
str.append(">");
neuz.show_message(str);
object_property_index = target->property_id;
start_position = {neuz.player->position.x, neuz.player->position.y, neuz.player->position.z};
std::cout << "Start botting at " << start_position << std::endl;
is_running = true;
is_running = true;
neuz.show_message("Bot started");
}
neuz.show_message("Bot started");
}
if(event->keyCode == 221) {
if(is_running == true) {
is_running = false;
if (event->keyCode == 221) {
if (is_running) {
is_running = false;
neuz.show_message("Bot stopped");
} else {
if(!neuz.player) return;
if (!neuz.player) return;
const auto& player = *neuz.player;
neuz.show_announcement("Hello world!", { 0xFF, 0, 0 });
neuz.show_announcement("Hello world!", {0xFF, 0, 0});
auto current = neuz.movers.first;
do {
const auto& mover = current->mover;
const auto &mover = current->mover;
if(mover->type == ObjectType::Mover) {
if (mover->type == ObjectType::Mover) {
// int level = mover->get_level();
std::cout << neuz.get_text(mover->name) << " <Lv. " << mover->get_level() << ">): "
std::cout << neuz.get_text(mover->name) << " <Lv. " << mover->get_level() << ">): "
<< (mover->is_dead() ? "Dead" : "Not dead") << ", "
<< (mover->is_fly() ? "Flying" : "Not flying") << ", "
<< (mover->is_jumping() ? "Jumping" : "Not jumping") << ", "
<< (mover->is_moving() ? "Moving" : "Not moving")
<< (mover->is_moving() ? "Moving" : "Not moving")
<< (mover->is_grounded ? "On ground" : "Flying")
<< std::endl;
}
current = current->next;
} while(current);
} while (current);
// auto items = player.inventory.begin();
// auto length = ((uintptr_t)player.inventory.end() - (uintptr_t)player.inventory.begin()) / 0x60;
@ -238,11 +416,11 @@ void on_keyup_hook(int event_type, const EmscriptenKeyboardEvent* event, void* u
}
}
flyff::MoverID attack_next_target(flyff::Vector3 const& start_position) {
auto& neuz = flyff::Neuz::instance();
flyff::MoverID attack_next_target(flyff::Vector3 const &start_position) {
auto &neuz = flyff::Neuz::instance();
if (!neuz.player) return 0;
if(!neuz.player) return 0;
// Found in the code somewhere.
static constexpr float max_distance = 144.;
@ -251,35 +429,34 @@ flyff::MoverID attack_next_target(flyff::Vector3 const& start_position) {
auto current = neuz.movers.first;
do {
const auto& mover = current->mover;
const auto &mover = current->mover;
auto dx = std::abs(mover->position.x - start_position.x);
auto dy = std::abs(mover->position.y - start_position.y);
auto dz = std::abs(mover->position.z - start_position.z);
auto dx = std::abs(mover->position.x - neuz.player->position.x);
auto dy = std::abs(mover->position.y - neuz.player->position.y);
auto dz = std::abs(mover->position.z - neuz.player->position.z);
auto squared = (dx * dx) + (dy * dy) + (dz * dz);
auto d = std::sqrt(squared);
if(mover->type == ObjectType::Mover &&
current->hash != neuz.player_object_id &&
if (mover->type == ObjectType::Mover &&
current->hash != neuz.player_object_id &&
!mover->is_dead() &&
// Only attack ground mobs.
mover->is_grounded &&
// Only attack same mobs.
mover->property_id == object_property_index &&
d <= max_distance) {
// If it's a monster that has me targetted
if(mover->last_attacked_target == neuz.player_object_id) {
closest = mover;
std::cout << mover->name << " has attacked me, so I'm attacking" << std::endl;
break;
} else if(d < lowest_distance) {
if (d < lowest_distance) {
closest = mover;
lowest_distance = d;
}
}
current = current->next;
} while(current);
} while (current);
if(closest) {
if (closest) {
neuz.player->selected_target = closest->object_id;
set_target(closest->object_id);
@ -287,70 +464,57 @@ flyff::MoverID attack_next_target(flyff::Vector3 const& start_position) {
interact_target(1);
return closest->object_id;
}
}
return 0;
}
flyff::MoverID find_next_item() {
const auto& neuz = flyff::Neuz::instance();
const auto &neuz = flyff::Neuz::instance();
if(!neuz.player) return 0;
auto& player = *neuz.player;
if (!neuz.player) return 0;
float lowest_distance = 32.f;
auto closest = flyff::Pointer<flyff::Mover>(nullptr);
auto current = neuz.movers.first;
do {
const auto& mover = current->mover;
const auto &mover = current->mover;
auto dx = std::abs(mover->position.x - player.position.x);
auto dz = std::abs(mover->position.z - player.position.z);
auto dx = std::abs(mover->position.x - neuz.player->position.x);
auto dz = std::abs(mover->position.z - neuz.player->position.z);
auto squared = (dx * dx) + (dz * dz);
auto d = std::sqrt(squared);
if(mover->world != 0 &&
if (mover->world != 0 &&
!mover->is_despawned &&
mover->type == ObjectType::Item &&
d <= lowest_distance) {
flyff::ItemProperty* prop = reinterpret_cast<flyff::ItemProperty*>(
static_cast<flyff::ObjectProperty*>(mover->property)
auto *prop = reinterpret_cast<flyff::ItemProperty *>(
static_cast<flyff::ObjectProperty *>(mover->property)
);
if(prop->is_quest()) {
std::string str = "Skipping ";
str.append(neuz.get_text(prop->name));
str.append(" because is quest item.");
neuz.show_message(str);
} else {
if (!prop->is_quest()) {
closest = mover;
lowest_distance = d;
std::string str = "";
str.append(neuz.get_text(prop->name));
str.append(" is close.");
neuz.show_message(str);
}
}
current = current->next;
} while(current);
} while (current);
if(closest)
if (closest)
return closest->object_id;
else
return 0;
}
void interact(flyff::MoverID id) {
const auto& neuz = flyff::Neuz::instance();
const auto &neuz = flyff::Neuz::instance();
if(!neuz.player)
if (!neuz.player)
return;
neuz.player->selected_target = id;
@ -364,9 +528,9 @@ flyff::MoverID current_target = 0;
flyff::MoverID current_pickup_item = 0;
void bot_tick() {
const auto& neuz = flyff::Neuz::instance();
const auto &neuz = flyff::Neuz::instance();
if(!neuz.player)
if (!neuz.player)
return;
// std::cout << "Max Max HP: "
@ -379,78 +543,167 @@ void bot_tick() {
// printf("%#010x\n", neuz.player->get_state());
if(is_running) {
if(neuz.player->is_dead()) {
if (is_running) {
if (neuz.player->is_dead()) {
neuz.show_message("Player is dead, stopping...", {0xFF, 0x00, 0x00});
is_running = false;
return;
}
const auto &player = neuz.player;
// if is_idle:
// if item_target:
// pickup_item()
// elif attacK_target:
// attack_target()
if(neuz.player->get_hp_percent() < 75) {
if (neuz.player->get_hp_percent() < 75) {
// neuz.show_message("Fooding because HP is under 75%");
const auto& player = neuz.player;
const auto &player = neuz.player;
auto items = player->inventory.begin();
auto length = ((uintptr_t)player->inventory.end() - (uintptr_t)player->inventory.begin()) / 0x60;
auto length = ((uintptr_t) player->inventory.end() - (uintptr_t) player->inventory.begin()) / 0x60;
for(auto i = 0; i < length; i++) {
if(items[i].index != -1 &&
for (auto i = 0; i < length; i++) {
if (items[i].index != -1 &&
items[i].property &&
items[i].property->is_food() &&
items[i].property->is_food() &&
player->can_use_item(items[i].property)) {
std::string str = "Eating ";
str.append(neuz.get_text(items[i].property->name));
str.append(" because HP is below 75%");
neuz.show_message(str);
use_item_in_inventory(i);
break;
}
}
}
}
}
if(neuz.player->get_move_state() == 1 &&
if (neuz.player->get_move_state() == 1 &&
!neuz.player->is_attacking()) {
// Check buffs.
static constexpr uint32_t buffs_to_check[] = {
flyff::SkillIndex::HeapUp,
flyff::SkillIndex::Haste,
flyff::SkillIndex::Patience
};
auto item = neuz.get_mover(current_pickup_item);
auto monster = neuz.get_mover(current_target);
if(item && !item->is_despawned && neuz.player->move_toward_target == 0) {
const auto &main_hand = player->get_equipped_item(flyff::Part::MainHand);
const auto &off_hand = player->get_equipped_item(flyff::Part::Shield);
auto buffs = check_rebuff(neuz.player, buffs_to_check);
if (!buffs.empty() && (!item || item->is_despawned) && (!monster || monster->is_dead())) {
const auto next_buff = buffs.back();
if (!main_hand || main_hand->item_kind3 != flyff::ItemKind3::CheerStick) {
const auto &stick = find_first_equippable_item(flyff::ItemKind3::CheerStick);
if (stick) {
buffs.pop_back();
use_item_in_inventory(stick->index);
use_skill(next_buff);
return;
} else {
neuz.show_message("Unable to find a stick", {0xFF, 0, 0});
}
} else {
buffs.pop_back();
use_skill(next_buff);
return;
}
}
if (buffs.empty()) {
if (!main_hand || main_hand->item_kind3 != flyff::ItemKind3::KnuckleHammer) {
const auto &knuckle = find_first_equippable_item(flyff::ItemKind3::KnuckleHammer);
if (knuckle) {
use_item_in_inventory(knuckle->index);
} else {
neuz.show_message("Unable to find a knuckle", {0xFF, 0, 0});
}
}
if (!off_hand || off_hand->item_kind3 != flyff::ItemKind3::Shield) {
const auto &shield = find_first_equippable_item(flyff::ItemKind3::Shield);
if (shield) {
use_item_in_inventory(shield->index);
} else {
neuz.show_message("Unable to find a shield", {0xFF, 0, 0});
}
}
}
if (item && !item->is_despawned && neuz.player->move_toward_target == 0) {
// Pickup
interact(item->object_id);
} else if(monster && !monster->is_dead() && neuz.player->move_toward_target == 0) {
} else if (monster && !monster->is_dead() && neuz.player->move_toward_target == 0) {
// Attack
interact(monster->object_id);
// neuz.player->attack_target = monster->object_id;
} else if((!item || item->is_despawned) &&
(!monster || monster->is_dead())) {
} else if ((!item || item->is_despawned) &&
(!monster || monster->is_dead())) {
std::cout << "No item, no target. Searching..." << std::endl;
// First check all mobs if they attacked me (aggro ones).
auto current = neuz.movers.first;
do {
const auto &mover = current->mover;
if (mover->type == ObjectType::Mover &&
current->hash != neuz.player_object_id &&
!mover->is_dead() &&
// If it's a monster that has me targetted...
mover->last_attacked_target == neuz.player_object_id &&
// ...and is tracking me
mover->follow_target == neuz.player_object_id) {
current_target = attack_next_target(start_position);
monster = neuz.get_mover(current_target);
std::string str = "Attacking ";
str.append(monster->name);
str.append(" because it attacked me.");
interact(monster->object_id);
neuz.show_message(str);
return;
}
current = current->next;
} while (current);
// No item target and no attack target
current_pickup_item = find_next_item();
item = neuz.get_mover(current_pickup_item);
if(item) {
// flyff::ItemProperty* prop = (flyff::ItemProperty*)static_cast<uintptr_t*>(current_pickup_item->property);
if (item) {
flyff::ItemProperty *prop = reinterpret_cast<flyff::ItemProperty *>(
static_cast<flyff::ObjectProperty *>(item->property)
);
std::string str = "Picking up ";
std::cout << str << std::endl;
// str.append(prop->name);
str.append(neuz.get_text(prop->name));
interact(item->object_id);
neuz.show_message(str);
} else {
current_target = attack_next_target(start_position);
monster = neuz.get_mover(current_target);
if(monster) {
if (monster) {
std::string str = "Attacking ";
str.append(monster->name);
@ -458,7 +711,7 @@ void bot_tick() {
interact(monster->object_id);
// neuz.player->attack_target = monster->object_id;
neuz.show_message(str);
} else {
neuz.show_message("Unable to find target.");
@ -466,39 +719,6 @@ void bot_tick() {
}
}
}
// static constexpr uint32_t PICKUP = flyff::Object::State::AtkAll | flyff::Object::State::Dead;
// if((current_pickup_item != nullptr &&
// !current_pickup_item->is_despawned) ||
// (neuz.player->object_state & PICKUP) != 0) {
// // Wait
// std::cout << "ObjectSTate & Pickup = " << reinterpret_cast<void*>(neuz.player->object_state & PICKUP) << std::endl;
// } else if(current_target == nullptr) {
// current_pickup_item = pickup_next_item();
// if(current_pickup_item != nullptr) {
// neuz.show_message("Picking up");
// return;
// }
// current_target = attack_next_target(start_position);
// if(current_target) {
// std::string str = "Attacking ";
// str.append(current_target->name);
// neuz.show_message(str);
// } else {
// neuz.show_message("Unable to find target.");
// }
// } else if(current_target->is_dead()) {
// current_target = nullptr;
// current_pickup_item = pickup_next_item();
// if(current_pickup_item != nullptr) {
// neuz.show_message("Picking up");
// }
// }
} else {
// Reset current target is not running.
current_target = 0;
@ -515,7 +735,7 @@ void after_main_loop() {
// auto& music_properties = fugg::module_ref<fugg::Vector<flyff::MusicProperty>>(0x00034f7c);
// auto& item_properties = fugg::module_ref<fugg::Vector<flyff::ItemProperty>>(0x00035194);
// for(auto& item : item_properties) {
// std::cout << item.some_string->c_str() << std::endl;
// }
@ -579,10 +799,10 @@ void after_main_loop() {
// }
// auto test = reinterpret_cast<Pointer<int>*>(0x00035194);
// std::cout << "Test is at " << reinterpret_cast<void*>(test->to_intptr_t()) << std::endl;

View File

@ -7,175 +7,177 @@
#include <AL/alc.h>
#include <fugg.h>
#include <flyff.h>
#define TRACE_AL_CALLS 0
/* import: 'a' 'u' */
// "u": "_alSourcef",
WASM_IMPORT_IMPL(env, _alSourcef) = [](u32 a, u32 b, f32 c) {
WASM_IMPORT_IMPL(env, _alSourcef) = [](u32 source, u32 param, f32 value) {
#if TRACE_AL_CALLS
std::cout << "_alSourcef("
<< a << ", "
<< b << ", "
<< c
<< ")" << std::endl;
#endif
alSourcef(a, b, c);
};
// "w": "_alSourcei",
WASM_IMPORT_IMPL(env, _alSourcei) = [](u32 a, u32 b, u32 c) {
#if TRACE_AL_CALLS
std::cout << "_alSourcei("
<< a << ", "
<< b << ", "
<< c
<< ")" << std::endl;
#endif
alSourcei(a, b, c);
};
/* import: 'a' 'F' */
/* _alSourceStop*/
WASM_IMPORT_IMPL(env, _alSourceStop) = [](u32 a) {
#if TRACE_AL_CALLS
std::cout << "_alSourceStop("
<< a
<< ")" << std::endl;
#endif
alSourceStop(a);
};
// "L": "_alGetSourcei",
WASM_IMPORT_IMPL(env, _alGetSourcei) = [](u32 a, u32 b, u32 c) {
const auto& value = fugg::ModulePointer<ALint> { c };
#if TRACE_AL_CALLS
std::cout << "_alGetSourcei("
<< a << ", "
<< b << ", "
<< source << ", "
<< param << ", "
<< value
<< ")" << std::endl;
#endif
alGetSourcei(a, b, value);
alSourcef(source, static_cast<ALenum>(param), value);
};
// "w": "_alSourcei",
WASM_IMPORT_IMPL(env, _alSourcei) = [](u32 source, u32 param, u32 value) {
#if TRACE_AL_CALLS
std::cout << "_alSourcei("
<< source << ", "
<< param << ", "
<< value
<< ")" << std::endl;
#endif
alSourcei(source, static_cast<ALenum>(param), static_cast<ALenum>(value));
};
/* import: 'a' 'F' */
/* _alSourceStop*/
WASM_IMPORT_IMPL(env, _alSourceStop) = [](u32 source) {
#if TRACE_AL_CALLS
std::cout << "_alSourceStop("
<< source
<< ")" << std::endl;
#endif
alSourceStop(source);
};
// "L": "_alGetSourcei",
WASM_IMPORT_IMPL(env, _alGetSourcei) = [](u32 source, u32 param, u32 c) {
const auto &value = flyff::Pointer<ALint>{c};
#if TRACE_AL_CALLS
std::cout << "_alGetSourcei("
<< source << ", "
<< param << ", "
<< value
<< ")" << std::endl;
#endif
alGetSourcei(source, static_cast<ALenum>(param), static_cast<ALint *>(value));
};
/* import: 'a' 'Q' */
// "Q": "_alDeleteSources"
WASM_IMPORT_IMPL(env, _alDeleteSources) = [](u32 a, u32 b) {
const auto& sources = fugg::ModulePointer<const ALuint> { b };
WASM_IMPORT_IMPL(env, _alDeleteSources) = [](u32 n, u32 b) {
const auto &sources = flyff::Pointer<const ALuint>{b};
#if TRACE_AL_CALLS
std::cout << "_alDeleteSources("
<< a << ", "
<< n << ", "
<< sources
<< ")" << std::endl;
#endif
alDeleteSources(a, sources);
alDeleteSources(static_cast<ALsizei>(n), static_cast<const ALuint *>(sources));
};
/* _alSource3f */
WASM_IMPORT_IMPL(env, _alSource3f) = [](u32 a, u32 b, f32 c, f32 d, f32 e) {
WASM_IMPORT_IMPL(env, _alSource3f) = [](u32 source, u32 param, f32 value1, f32 value2, f32 value3) {
#if TRACE_AL_CALLS
std::cout << "_alSource3f("
<< a << ", "
<< b << ", "
<< c << ", "
<< d << ", "
<< e
<< source << ", "
<< param << ", "
<< value1 << ", "
<< value2 << ", "
<< value3
<< ")" << std::endl;
#endif
alSource3f(a, b, c, d, e);
alSource3f(source, static_cast<ALenum>(param), value1, value2, value3);
};
/* import: 'a' 'bb' */
// "bb": "_alSourcePlay",
WASM_IMPORT_IMPL(env, _alSourcePlay) = [](u32 a) {
WASM_IMPORT_IMPL(env, _alSourcePlay) = [](u32 source) {
#if TRACE_AL_CALLS
std::cout << "_alSourcePlay("
<< a
<< source
<< ")" << std::endl;
#endif
alSourcePlay(a);
alSourcePlay(source);
};
/* import: 'a' 'cb' */
// "cb": "_alListenerfv",
WASM_IMPORT_IMPL(env, _alListenerfv) = [](u32 a, u32 b) {
const auto& values = fugg::ModulePointer<const ALfloat> { b };
WASM_IMPORT_IMPL(env, _alListenerfv) = [](u32 param, u32 b) {
const auto &values = flyff::Pointer<const ALfloat>{b};
#if TRACE_AL_CALLS
std::cout << "_alListenerfv("
<< a << ", "
<< param << ", "
<< values
<< ")" << std::endl;
#endif
alListenerfv(a, values);
alListenerfv(static_cast<ALenum>(param), static_cast<const ALfloat *>(values));
};
/* import: 'a' 'db' */
// "db": "_alListener3f",
WASM_IMPORT_IMPL(env, _alListener3f) = [](u32 a, f32 b, f32 c, f32 d) {
WASM_IMPORT_IMPL(env, _alListener3f) = [](u32 param, f32 value1, f32 value2, f32 value3) {
#if TRACE_AL_CALLS
std::cout << "_alListener3f("
<< a << ", "
<< b << ", "
<< c << ", "
<< d
<< param << ", "
<< value1 << ", "
<< value2 << ", "
<< value3
<< ")" << std::endl;
#endif
alListener3f(a, b, c, d);
alListener3f(static_cast<ALenum>(param), value1, value2, value3);
};
/* import: 'a' 'Sb' */
/* _alDeleteBuffers */
WASM_IMPORT_IMPL(env, _alDeleteBuffers) = [](u32 a, u32 b) {
const auto& buffers = fugg::ModulePointer<const ALuint> { b };
WASM_IMPORT_IMPL(env, _alDeleteBuffers) = [](u32 n, u32 b) {
const auto &buffers = flyff::Pointer<const ALuint>{b};
#if TRACE_AL_CALLS
std::cout << "_alDeleteBuffers("
<< a << ", "
<< n << ", "
<< buffers
<< ")" << std::endl;
#endif
alDeleteBuffers(a, buffers);
alDeleteBuffers(static_cast<ALsizei>(n), static_cast<const ALuint *>(buffers));
};
/* import: 'a' 'Tb' */
/* _alBufferData */
WASM_IMPORT_IMPL(env, _alBufferData) = [](u32 a, u32 b, u32 c, u32 d, u32 e) {
const auto& data = fugg::ModulePointer<const ALvoid> { c };
WASM_IMPORT_IMPL(env, _alBufferData) = [](u32 buffer, u32 format, u32 c, u32 size, u32 freq) {
const auto &data = flyff::Pointer<const ALvoid>{c};
#if TRACE_AL_CALLS
std::cout << "_alBufferData("
<< a << ", "
<< b << ", "
<< buffer << ", "
<< format << ", "
<< data << ", "
<< d << ", "
<< e
<< size << ", "
<< freq
<< ")" << std::endl;
#endif
alBufferData(a, b, data, d, e);
alBufferData(buffer, static_cast<ALenum>(format), static_cast<const void *>(data), static_cast<ALsizei>(size),
static_cast<ALsizei>(freq));
};
/* import: 'a' 'Ub' */
// "Ub": "_alGenBuffers",
WASM_IMPORT_IMPL(env, _alGenBuffers) = [](u32 a, u32 b) {
const auto& buffers = fugg::ModulePointer<ALuint> { b };
WASM_IMPORT_IMPL(env, _alGenBuffers) = [](u32 n, u32 b) {
const auto &buffers = flyff::Pointer<ALuint>{b};
#if TRACE_AL_CALLS
std::cout << "_alGenBuffers("
<< a << ", "
<< n << ", "
<< buffers
<< ")" << std::endl;
#endif
alGenBuffers(a, buffers);
alGenBuffers(static_cast<ALsizei>(n), static_cast<ALuint *>(buffers));
};
/* import: 'a' 'Vb' */
// "Vb": "_alGetEnumValue",
WASM_IMPORT_IMPL(env, _alGetEnumValue) = [](u32 a) {
const auto& ename = fugg::ModulePointer<const ALchar> { a };
const auto &ename = flyff::Pointer<const ALchar>{a};
#if TRACE_AL_CALLS
std::cout << "_alGetEnumValue("
@ -183,15 +185,13 @@ WASM_IMPORT_IMPL(env, _alGetEnumValue) = [](u32 a) {
<< ")" << std::endl;
#endif
return static_cast<u32>(
alGetEnumValue(ename)
);
return static_cast<u32>(alGetEnumValue(static_cast<const ALchar *>(ename)));
};
/* import: 'a' 'Wb' */
// "Wb": "_alcCloseDevice",
WASM_IMPORT_IMPL(env, _alcCloseDevice) = [](u32 a) {
// ALCdevice is not data, but an index.
const auto& device = reinterpret_cast<ALCdevice*>(a);
const auto &device = reinterpret_cast<ALCdevice *>(a);
#if TRACE_AL_CALLS
std::cout << "_alcCloseDevice("
@ -199,41 +199,39 @@ WASM_IMPORT_IMPL(env, _alcCloseDevice) = [](u32 a) {
<< ")" << std::endl;
#endif
return static_cast<u32>(
alcCloseDevice(device)
);
return static_cast<u32>(alcCloseDevice(device));
};
/* import: 'a' 'Yb' */
// "Yb": "_alGenSources",
WASM_IMPORT_IMPL(env, _alGenSources) = [](u32 a, u32 b) {
const auto& sources = fugg::ModulePointer<ALuint> { b };
WASM_IMPORT_IMPL(env, _alGenSources) = [](u32 n, u32 b) {
const auto &sources = flyff::Pointer<ALuint>{b};
#if TRACE_AL_CALLS
std::cout << "_alGenSources("
<< a << ", "
<< n << ", "
<< sources
<< ")" << std::endl;
#endif
alGenSources(a, sources);
alGenSources(static_cast<ALsizei>(n), static_cast<ALuint *>(sources));
};
/* import: 'a' 'Zb' */
// "Zb": "_alListenerf",
WASM_IMPORT_IMPL(env, _alListenerf) = [](u32 a, f32 b) {
WASM_IMPORT_IMPL(env, _alListenerf) = [](u32 param, f32 value) {
#if TRACE_AL_CALLS
std::cout << "_alListenerf("
<< a << ", "
<< b
<< param << ", "
<< value
<< ")" << std::endl;
#endif
alListenerf(a, b);
alListenerf(static_cast<ALenum>(param), value);
};
/* import: 'a' '_b' */
// "_b": "_alcMakeContextCurrent",
WASM_IMPORT_IMPL(env, _alcMakeContextCurrent) = [](u32 a) {
// ALCcontext is not data, but an index.
const auto& context = reinterpret_cast<ALCcontext*>(a);
const auto &context = reinterpret_cast<ALCcontext *>(a);
#if TRACE_AL_CALLS
std::cout << "_alcMakeContextCurrent("
@ -241,16 +239,14 @@ WASM_IMPORT_IMPL(env, _alcMakeContextCurrent) = [](u32 a) {
<< ")" << std::endl;
#endif
return static_cast<u32>(
alcMakeContextCurrent(context)
);
return static_cast<u32>(alcMakeContextCurrent(context));
};
/* import: 'a' '$b' */
/* _alcCreateContext */
WASM_IMPORT_IMPL(env, _alcCreateContext) = [](u32 a, u32 b) {
// ALCdevice is not data, but an index.
const auto& device = reinterpret_cast<ALCdevice*>(a);
const auto& attr_list = fugg::ModulePointer<const ALCint> { b };
const auto &device = reinterpret_cast<ALCdevice *>(a);
const auto &attr_list = fugg::ModulePointer<const ALCint>{b};
#if TRACE_AL_CALLS
std::cout << "_alcCreateContext("
@ -259,15 +255,13 @@ WASM_IMPORT_IMPL(env, _alcCreateContext) = [](u32 a, u32 b) {
<< ")" << std::endl;
#endif
return reinterpret_cast<u32>(
alcCreateContext(device, attr_list)
);
return reinterpret_cast<u32>(alcCreateContext(device, attr_list));
};
/* import: 'a' 'Xb' */
// "Xb": "_alcDestroyContext",
WASM_IMPORT_IMPL(env, _alcDestroyContext) = [](u32 a) {
// ALCcontext is not data, but an index.
const auto& context = reinterpret_cast<ALCcontext*>(a);
const auto &context = reinterpret_cast<ALCcontext *>(a);
#if TRACE_AL_CALLS
std::cout << "_alcDestroyContext("
@ -280,7 +274,7 @@ WASM_IMPORT_IMPL(env, _alcDestroyContext) = [](u32 a) {
/* import: 'a' 'ac' */
// "ac": "_alcOpenDevice",
WASM_IMPORT_IMPL(env, _alcOpenDevice) = [](u32 a) {
const auto& devicename = fugg::ModulePointer<const ALchar> { a };
const auto &devicename = flyff::Pointer<const ALchar>{a};
#if TRACE_AL_CALLS
std::cout << "_alcOpenDevice("
@ -288,7 +282,5 @@ WASM_IMPORT_IMPL(env, _alcOpenDevice) = [](u32 a) {
<< ")" << std::endl;
#endif
return reinterpret_cast<u32>(
alcOpenDevice(devicename)
);
return reinterpret_cast<u32>(alcOpenDevice(static_cast<const ALchar *>(devicename)));
};