This repository has been archived on 2024-05-15. You can view files and clone it, but cannot push or open issues or pull requests.
fugg/flyff-api/src/Mover.h

367 lines
11 KiB
C++

#pragma once
#include <fugg.h>
#include <cstddef>
#include <iterator>
#include <bitset>
#include <cmath>
#include "core.h"
#include "item/ItemProperty.h"
#include "math.h"
#include "object/Object.h"
#include "object/ObjectProperty.h"
#include "object/ObjectType.h"
#include "skill/Skill.h"
#include "item/InventoryItem.h"
#include "item/Part.h"
namespace flyff {
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;
static constexpr Parameter DST_HP_MAX = 0x2c;
static constexpr Parameter DST_HP_MAX_RATE = 0x35;
using ObjectStateFlags = Object::StateFlags;
using ObjectState = Object::State;
struct __attribute__((packed)) Vtable {
union {
DEFINE_MEMBER(52, const u32, get_level);
DEFINE_MEMBER(56, const u32, get_gender);
DEFINE_MEMBER(96, const u32, get_active_hand_item_prop);
DEFINE_MEMBER(144, const u32, get_max_origin_hp);
DEFINE_MEMBER(148, const u32, get_max_origin_mp);
const MinimumSize<220> _size;
};
};
struct __attribute__((packed)) Skill {
union {
DEFINE_MEMBER(0, const flyff::Skill, id);
DEFINE_MEMBER(4, const uintptr_t, level);
};
};
struct __attribute__((packed)) Buff {
enum class Type {
Item = 0,
Skill = 1,
};
struct __attribute__((packed)) Vtable {
union {
DEFINE_MEMBER(28, const u32, get_type);
DEFINE_MEMBER(32, const u32, get_id);
};
};
union {
DEFINE_MEMBER(0, const Pointer<Vtable>, vtable);
DEFINE_MEMBER(4, const Pointer<ObjectProperty>, property);
DEFINE_MEMBER(8, const Parameter, param_id);
DEFINE_MEMBER(16, const uint64_t, time_instantiated);
DEFINE_MEMBER(24, const uint64_t, time_total);
DEFINE_MEMBER(32, const int, level);
DEFINE_MEMBER(36, const bool, is_removed);
DEFINE_MEMBER(37, const bool, is_sfx);
};
Type get_type() const {
using Fn = FunctionPointer<Type, 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);
DEFINE_MEMBER(3324, Timestamp, last_food_time);
DEFINE_MEMBER(3348, Timestamp, last_refresher_time);
DEFINE_MEMBER(3356, Timestamp, last_vitaldrink_time);
DEFINE_MEMBER(3424, Vector<Skill>, skills);
const MinimumSize<4096> size;
};
uint32_t get_skill_level(const flyff::Skill &skill_index) const {
for (const auto &skill: skills) {
if (skill_index == skill.id)
return skill.level;
}
return 0;
}
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;
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 adjusted_parameters[index] ^ adj_param ^ 0x0554e725 + index * 0x41c64e6d;
}
Parameter get_change_param(Parameter index) const {
return changed_parameters[index] ^ adj_param ^ index * 0x41c64e6d + 0xb5a52d1a;
}
u32 get_hp() const {
return raw::w2c_f411(kMemory.to_inside(this));
}
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);
const auto &ptr = fn(kMemory.to_inside(this), static_cast<uint32_t>(part));
return flyff::Pointer<flyff::ItemProperty>(ptr);
}
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);
factor += (float) percent / (float) 100;
result = static_cast<float>(result) * factor;
return result;
}
uint32_t get_hp_percent(int percent = 100) const {
int max = get_max_hp();
if (max == 0) return 0;
return get_hp() * percent / max;
}
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(kMemory.to_inside(this), 0, 0);
}
// 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));
// }
};
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