Some refactors after installing CLion
This commit is contained in:
parent
9af9d664f5
commit
97169c715f
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
// #include "../src/api.h"
|
||||
#include "../src/Neuz.h"
|
||||
#include "../src/Mover.h"
|
||||
#include "../src/skill.h"
|
||||
|
||||
#include "../src/import.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 *>(©);
|
||||
}
|
||||
|
||||
return *reinterpret_cast<std::string*>(©);
|
||||
}
|
||||
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
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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)));
|
||||
};
|
||||
Reference in New Issue