Pre Halloween patch

This commit is contained in:
Knaapchen 2022-10-20 14:53:07 +02:00
parent ce380a92f6
commit 3b24a7e478
5 changed files with 167 additions and 47 deletions

View File

@ -12,8 +12,22 @@
#include "math.h"
#include "item.h"
namespace flyff {
namespace raw {
extern "C" {
// w2c_f410: CMover::GetHitPoint(PlayerObject* mover);
extern u32 w2c_f410(u32);
// w2c_f2454: CCooltimeMgr::CanUse(uint64_t* timers, ItemProperty* prop);
extern u32 w2c_f2454(u32, u32);
}
};
struct __attribute__((packed)) Mover {
static constexpr uint32_t MAX_PARAM = 82;
using Parameter = unsigned long;
using ObjectStateFlags = Object::StateFlags;
using ObjectState = Object::State;
@ -22,6 +36,9 @@ struct __attribute__((packed)) Mover {
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;
};
};
@ -40,9 +57,13 @@ struct __attribute__((packed)) Mover {
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);
@ -54,8 +75,11 @@ struct __attribute__((packed)) Mover {
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);
@ -74,9 +98,82 @@ struct __attribute__((packed)) Mover {
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_f2454(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>(0x00032a18);
// 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_f410(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);
factor += (float)percent / (float)100;
result = (int)(result * factor);
return result;
}
u32 get_hp_percent(int percent = 100) const {
int max = get_max_hp();
if(max == 0) return 0;
return get_hp() * percent / max;
}
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);
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;
}
@ -158,14 +255,11 @@ struct __attribute__((packed)) Mover {
return (object_state & ObjectState::TurnAll) != 0;
}
// int32_t get_level() {
// // The function itself works but I fear it returns wrong results.
// // Npc = 1
// // Players = 0
// const auto& fn = fugg::function_ref<FunctionPointer<int32_t, Pointer<Mover>>>(vtable->get_level);
u32 get_level() {
const auto& fn = fugg::function_ref<FunctionPointer<u32, u32>>(vtable->get_level);
// return fn(Pointer<Mover>(this));
// }
return fn(kMemory.to_inside(this));
}
// int32_t get_gender() {
// // The function itself works but I fear it returns wrong results.
@ -176,12 +270,6 @@ struct __attribute__((packed)) Mover {
// return fn(Pointer<Mover>(this));
// }
// bool prevents_pickup_emote() const {
// DEFINE_MEMBER(1806, uint16_t, pickup_flags);
// // Returns true if in attack animation
// return (pickup_flags & 0x8ff) != 0;
// }
};
struct MoverMap {

View File

@ -102,7 +102,7 @@ void Neuz::show_message(const std::string& message,
auto color_ = std::make_unique<flyff::Color>(color);
raw::show_message(
static_cast<uintptr_t>(messages_ui),
static_cast<u32>(messages_ui),
fugg::RuntimePointer<fugg::String>(message_.get()).as_raw(),
fugg::RuntimePointer<flyff::Color>(color_.get()).as_raw());
}
@ -116,15 +116,15 @@ void Neuz::show_announcement(const std::string& message,
auto color_ = std::make_unique<flyff::Color>(color);
raw::show_announcement(
static_cast<uintptr_t>(announcements_ui),
static_cast<u32>(announcements_ui),
fugg::RuntimePointer<fugg::String>(message_.get()).as_raw(),
fugg::RuntimePointer<flyff::Color>(color_.get()).as_raw());
}
bool Neuz::is_valid_attack(const Pointer<Mover>& attacker,
const Pointer<Mover>& defender) const {
auto result = raw::w2c_f514(static_cast<uintptr_t>(attacker),
static_cast<uintptr_t>(defender));
auto result = raw::w2c_f514(static_cast<u32>(attacker),
static_cast<u32>(defender));
return result != 0;
}

View File

@ -37,6 +37,10 @@ class Memory {
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;
@ -95,7 +99,7 @@ class __attribute__((packed)) Pointer {
return as_outside();
}
explicit operator uintptr_t() const {
explicit operator u32() const {
return offset;
}

View File

@ -651,7 +651,7 @@ static u32 w2c_f406(u32);
static u32 w2c_f407(u32);
static void w2c_f408(u32);
static u32 w2c_f409(u32);
static u32 w2c_f410(u32);
u32 w2c_f410(u32);
static void w2c_f411(u32, u32);
static u32 w2c_f412(u32);
static u32 w2c_f413(u32, u32);
@ -2695,7 +2695,7 @@ static void w2c_f2450(u32, u32, u32, u32);
static void w2c_f2451(u32, u32, u32);
static u32 w2c_f2452(u32);
static u32 w2c_f2453(u32);
static u32 w2c_f2454(u32, u32);
u32 w2c_f2454(u32, u32);
static u32 w2c_f2455(u32);
static u32 w2c_f2456(u32);
static void w2c_f2457(void);
@ -98640,7 +98640,7 @@ static u32 w2c_f409(u32 w2c_p0) {
return w2c_i0;
}
static u32 w2c_f410(u32 w2c_p0) {
u32 w2c_f410(u32 w2c_p0) {
u32 w2c_l1 = 0, w2c_l2 = 0, w2c_l3 = 0;
f32 w2c_l4 = 0;
FUNC_PROLOGUE;
@ -1095840,7 +1095840,7 @@ static u32 w2c_f2453(u32 w2c_p0) {
return w2c_i0;
}
static u32 w2c_f2454(u32 w2c_p0, u32 w2c_p1) {
u32 w2c_f2454(u32 w2c_p0, u32 w2c_p1) {
u32 w2c_l2 = 0, w2c_l3 = 0;
u64 w2c_l4 = 0;
FUNC_PROLOGUE;

View File

@ -9,10 +9,8 @@ namespace fugg
{
}
constexpr const uint32_t hash_to_id(const uint32_t hashed) {
constexpr uint32_t header_hash = 0x644ab400;
return hashed ^ header_hash;
constexpr const uint32_t hash_to_id(const uint32_t hashed) {
return hashed ^ flyff::PACKET_HEADER_HASH;
}
template<typename T>
@ -208,7 +206,7 @@ void on_keyup_hook(int event_type, const EmscriptenKeyboardEvent* event, void* u
if(mover->type == ObjectType::Mover) {
// int level = mover->get_level();
std::cout << neuz.get_text(mover->name) << ": "
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") << ", "
@ -358,10 +356,10 @@ void interact(const flyff::MoverID& id) {
if(!neuz.player)
return;
// neuz.player->selected_target = id;
neuz.player->selected_target = id;
set_target(id);
// neuz.player->move_toward_target = id;
neuz.player->move_toward_target = id;
interact_target(1);
}
@ -374,6 +372,16 @@ void bot_tick() {
if(!neuz.player)
return;
// std::cout << "Max Max HP: "
// << neuz.player->get_max_hp()
// << ", Adjust HP:"
// << neuz.player->get_adjust_param(0x2c)
// << ", Player level: "
// << neuz.player->get_level()
// << std::endl;
// printf("%#010x\n", neuz.player->get_state());
if(is_running) {
if(neuz.player->is_dead()) {
neuz.show_message("Player is dead, stopping...", {0xFF, 0x00, 0x00});
@ -389,10 +397,31 @@ void bot_tick() {
if(neuz.player->get_move_state() == 1 &&
!neuz.player->is_attacking()) {
if(current_pickup_item != nullptr && !current_pickup_item->is_despawned && neuz.player->move_toward_target == 0) {
if(neuz.player->get_hp_percent() < 75) {
neuz.show_message("Fooding because HP is under 75%");
const auto& player = neuz.player;
auto items = player->inventory.begin();
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 &&
items[i].property &&
items[i].property->is_food_item() &&
player->can_use_item(items[i].property)) {
neuz.show_message(neuz.get_text(items[i].property->name));
use_item_in_inventory(i);
break;
}
}
} else if(current_pickup_item != nullptr && !current_pickup_item->is_despawned && neuz.player->move_toward_target == 0) {
// Pickup
interact(current_pickup_item->object_id);
} else if(current_target && !current_target->is_dead() && neuz.player->attack_target == 0) {
} else if(current_target && !current_target->is_dead() && neuz.player->attack_target == 0 && neuz.player->move_toward_target == 0) {
// Attack
interact(current_target->object_id);
// neuz.player->attack_target = current_target->object_id;
@ -410,24 +439,23 @@ void bot_tick() {
interact(current_pickup_item->object_id);
neuz.show_message(str);
return;
}
current_target = attack_next_target(start_position);
if(current_target) {
std::string str = "Attacking ";
str.append(current_target->name);
std::cout << str << std::endl;
interact(current_target->object_id);
neuz.player->attack_target = current_target->object_id;
neuz.show_message(str);
} else {
neuz.show_message("Unable to find target.");
current_target = attack_next_target(start_position);
if(current_target) {
std::string str = "Attacking ";
str.append(current_target->name);
std::cout << str << std::endl;
interact(current_target->object_id);
neuz.player->attack_target = current_target->object_id;
neuz.show_message(str);
} else {
neuz.show_message("Unable to find target.");
}
}
}
}