Lots of refactoring
This commit is contained in:
parent
cca6f82dcb
commit
4a5b4790d4
|
|
@ -8,7 +8,7 @@ add_library(
|
|||
"include/flyff.h"
|
||||
src/core.h
|
||||
src/skill/SkillProperty.h
|
||||
src/object/ObjectProperty.h src/item/ItemKind2.h src/item/ItemKind3.h src/item/Part.h src/item/InventoryItem.h src/object/mover/JobProperty.h)
|
||||
src/object/ObjectProperty.h src/item/ItemKind2.h src/item/ItemKind3.h src/item/Part.h src/item/InventoryItem.h src/object/mover/JobProperty.h src/object/mover/ParamID.h)
|
||||
|
||||
target_include_directories(flyff-api PUBLIC "include")
|
||||
target_link_libraries(flyff-api PUBLIC flyff-client fugg-api)
|
||||
|
|
@ -188,6 +188,10 @@ namespace flyff {
|
|||
T *end() const {
|
||||
return static_cast<T *>(end_);
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return static_cast<size_t>(end_ - begin_);
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(Vector<char>) == sizeof(std::vector<char>),
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@ namespace flyff {
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool Mover::is_in_combat() const {
|
||||
bool Mover::is_in_combat(uint32_t millis) const {
|
||||
const auto &neuz = flyff::Neuz::instance();
|
||||
// 10 seconds
|
||||
return neuz.current_time - last_combat < 10000000;
|
||||
return neuz.current_time - last_combat < (millis * 1000);
|
||||
}
|
||||
}; // namespace flyff
|
||||
|
|
@ -20,6 +20,7 @@
|
|||
#include "../../item/InventoryItem.h"
|
||||
#include "../../item/Part.h"
|
||||
#include "JobProperty.h"
|
||||
#include "ParamID.h"
|
||||
|
||||
namespace flyff {
|
||||
namespace raw {
|
||||
|
|
@ -36,9 +37,6 @@ namespace flyff {
|
|||
|
||||
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;
|
||||
|
||||
|
|
@ -98,7 +96,7 @@ namespace flyff {
|
|||
return fn(kMemory.to_inside(this));
|
||||
}
|
||||
|
||||
int get_id() const {
|
||||
uint32_t get_id() const {
|
||||
using Fn = FunctionPointer<u32, u32>;
|
||||
const auto &fn = fugg::function_ref<Fn>(vtable->get_id);
|
||||
|
||||
|
|
@ -113,14 +111,15 @@ namespace flyff {
|
|||
|
||||
DEFINE_MEMBER(0x18, Matrix4, world_matrix);
|
||||
|
||||
DEFINE_MEMBER(152, Vector3, position);
|
||||
DEFINE_MEMBER(164, Vector3, rotation);
|
||||
DEFINE_MEMBER(152, const Vector3, position);
|
||||
DEFINE_MEMBER(164, const Vector3, rotation);
|
||||
|
||||
DEFINE_MEMBER(188, const Pointer<const ObjectProperty>, property);
|
||||
|
||||
DEFINE_MEMBER(212, int, property_id);
|
||||
DEFINE_MEMBER(216, bool, is_despawned);
|
||||
DEFINE_MEMBER(352, MoverID, object_id);
|
||||
DEFINE_MEMBER(212, const int, property_id);
|
||||
DEFINE_MEMBER(216, const bool, is_despawned);
|
||||
|
||||
DEFINE_MEMBER(352, const MoverID, object_id);
|
||||
|
||||
DEFINE_MEMBER(920, Parameter, adjusted_parameters[MAX_PARAM]);
|
||||
DEFINE_MEMBER(1248, Parameter, changed_parameters[MAX_PARAM]);
|
||||
|
|
@ -129,11 +128,15 @@ namespace flyff {
|
|||
|
||||
DEFINE_MEMBER(2020, const String, name);
|
||||
|
||||
DEFINE_MEMBER(1616, const Vector<flyff::MoverID>, enemies);
|
||||
DEFINE_MEMBER(1628, Vector3, move_target);
|
||||
|
||||
DEFINE_MEMBER(1652, Vector3, delta_velocity);
|
||||
|
||||
DEFINE_MEMBER(1688, unsigned long long, last_combat);
|
||||
|
||||
DEFINE_MEMBER(1728, MoverID, move_toward_target);
|
||||
DEFINE_MEMBER(1736, MoverID, last_attacked_target);
|
||||
DEFINE_MEMBER(1736, MoverID, last_hit_mover);
|
||||
DEFINE_MEMBER(1744, MoverID, selected_target);
|
||||
// The id of the target that it hit last.
|
||||
DEFINE_MEMBER(1752, MoverID, attack_target);
|
||||
|
|
@ -153,8 +156,6 @@ namespace flyff {
|
|||
|
||||
DEFINE_MEMBER(204, const ObjectType, type);
|
||||
|
||||
DEFINE_MEMBER(216, uint32_t, existence_check);
|
||||
|
||||
DEFINE_MEMBER(1804, uint32_t, object_state);
|
||||
DEFINE_MEMBER(1808, uint32_t, object_state_flags);
|
||||
|
||||
|
|
@ -169,9 +170,9 @@ namespace flyff {
|
|||
|
||||
DEFINE_MEMBER(2432, const flyff::Pointer<const JobProperty>, job_property);
|
||||
|
||||
DEFINE_MEMBER(3224, Timestamp, last_food_time);
|
||||
DEFINE_MEMBER(3248, Timestamp, last_refresher_time);
|
||||
DEFINE_MEMBER(3256, Timestamp, last_vitaldrink_time);
|
||||
DEFINE_MEMBER(3224, const Timestamp, last_food_time);
|
||||
DEFINE_MEMBER(3248, const Timestamp, last_refresher_time);
|
||||
DEFINE_MEMBER(3256, const Timestamp, last_vitaldrink_time);
|
||||
|
||||
DEFINE_MEMBER(3424, Vector<Skill>, skills);
|
||||
|
||||
|
|
@ -199,9 +200,9 @@ namespace flyff {
|
|||
return max_inventory_slots - locked_inventory_slots;
|
||||
}
|
||||
|
||||
bool is_in_combat() const;
|
||||
bool is_in_combat(uint32_t millis = 10000) const;
|
||||
|
||||
Parameter get_param(uint32_t index, Parameter base) const {
|
||||
uint32_t get_param(ParamID index, uint32_t base) const {
|
||||
Parameter changeParam = get_change_param(index);
|
||||
if (changeParam != 0x7FFFFFFF)
|
||||
return changeParam;
|
||||
|
|
@ -213,13 +214,16 @@ namespace flyff {
|
|||
return base;
|
||||
}
|
||||
|
||||
Parameter get_adjust_param(Parameter index) const {
|
||||
Parameter get_adjust_param(ParamID index) const {
|
||||
auto id = static_cast<uint32_t>(index);
|
||||
// Find these values in CMover::Init
|
||||
return adjusted_parameters[index] ^ adj_param ^ 0x0554e725 + index * 0x41c64e6d;
|
||||
return adjusted_parameters[id] ^ adj_param ^ 0x0554e725 + id * 0x41c64e6d;
|
||||
}
|
||||
|
||||
Parameter get_change_param(Parameter index) const {
|
||||
return changed_parameters[index] ^ adj_param ^ index * 0x41c64e6d + 0xb5a52d1a;
|
||||
Parameter get_change_param(ParamID index) const {
|
||||
auto id = static_cast<uint32_t>(index);
|
||||
|
||||
return changed_parameters[id] ^ adj_param ^ id * 0x41c64e6d + 0xb5a52d1a;
|
||||
}
|
||||
|
||||
u32 get_hp() const {
|
||||
|
|
@ -236,8 +240,8 @@ namespace flyff {
|
|||
|
||||
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);
|
||||
auto result = get_param(ParamID::MaxHitPoint, get_max_origin_hp());
|
||||
auto percent = get_param(ParamID::MaxHitPointScaling, 0);
|
||||
|
||||
factor += (float) percent / (float) 100;
|
||||
result = static_cast<float>(result) * factor;
|
||||
|
|
@ -246,7 +250,7 @@ namespace flyff {
|
|||
}
|
||||
|
||||
uint32_t get_hp_percent(int percent = 100) const {
|
||||
int max = get_max_hp();
|
||||
auto max = get_max_hp();
|
||||
if (max == 0) return 0;
|
||||
|
||||
return get_hp() * percent / max;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
//
|
||||
// Created by main on 25-10-22.
|
||||
//
|
||||
|
||||
#ifndef FUGG_PARAMID_H
|
||||
#define FUGG_PARAMID_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace flyff {
|
||||
enum class ParamID : uint32_t {
|
||||
// DST_HP_MAX
|
||||
MaxHitPoint = 44,
|
||||
// DST_HP_MAX_RATE
|
||||
MaxHitPointScaling = 53,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif //FUGG_PARAMID_H
|
||||
|
|
@ -1051403,9 +1051403,24 @@ void w2c_f2316(u32 w2c_p0) {
|
|||
w2c_i0 = w2c_p0;
|
||||
w2c_i0 = i32_load((&w2c_memory), (u64)(w2c_i0) + 4u);
|
||||
w2c_l4 = w2c_i0;
|
||||
|
||||
const uintptr_t end = w2c_l4;
|
||||
|
||||
w2c_i1 = w2c_p0;
|
||||
w2c_i1 = i32_load((&w2c_memory), (u64)(w2c_i1));
|
||||
w2c_l2 = w2c_i1;
|
||||
|
||||
const uintptr_t begin = w2c_l2;
|
||||
|
||||
const size_t length = end - begin;
|
||||
const unsigned char* data = &(&w2c_memory)->data[begin];
|
||||
|
||||
printf("Finalizing packet of length %zd: ", length);
|
||||
for(int i = 0; i < length; i++) {
|
||||
printf("%02X ", data[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
w2c_i0 -= w2c_i1;
|
||||
w2c_l7 = w2c_i0;
|
||||
w2c_i0 = 9u;
|
||||
|
|
|
|||
|
|
@ -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 src/Packet.h)
|
||||
src/behaviour/Action.h src/Packet.h src/behaviour/Script.h)
|
||||
|
||||
# Flyff is based on c++14
|
||||
add_definitions(-std=c++14 -Os)
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
//
|
||||
// Created by main on 21-10-22.
|
||||
//
|
||||
|
||||
#ifndef FUGG_ACTION_H
|
||||
#define FUGG_ACTION_H
|
||||
|
||||
#include "Bot.h"
|
||||
|
||||
namespace fugg {
|
||||
class Action {
|
||||
|
||||
public:
|
||||
enum class State : unsigned char {
|
||||
Running,
|
||||
Failed,
|
||||
Succeeded
|
||||
};
|
||||
|
||||
virtual State evaluate(Bot &bot) = 0;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif //FUGG_ACTION_H
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
//
|
||||
// Created by main on 21-10-22.
|
||||
//
|
||||
|
||||
#include "Bot.h"
|
||||
|
||||
namespace fugg {
|
||||
Bot &Bot::instance() {
|
||||
// Constructor will be called.
|
||||
static Bot instance;
|
||||
// Whole module is initialised now.
|
||||
return instance;
|
||||
}
|
||||
|
||||
void Bot::tick() {
|
||||
|
||||
}
|
||||
};
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
//
|
||||
// Created by main on 21-10-22.
|
||||
//
|
||||
|
||||
#ifndef FUGG_BOT_H
|
||||
#define FUGG_BOT_H
|
||||
|
||||
#include <flyff.h>
|
||||
|
||||
namespace fugg {
|
||||
class Bot {
|
||||
Bot();
|
||||
|
||||
flyff::Neuz &neuz;
|
||||
|
||||
public:
|
||||
static Bot &instance();
|
||||
|
||||
Bot(Bot const &) = delete;
|
||||
|
||||
void operator=(Bot const &) = delete;
|
||||
|
||||
void tick();
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif //FUGG_BOT_H
|
||||
|
|
@ -115,20 +115,24 @@ namespace fugg {
|
|||
send_packet(motion_packet_id, packet);
|
||||
}
|
||||
|
||||
void Client::set_target(const unsigned long long &id) const {
|
||||
void Client::send_set_target(const unsigned long long &id) const {
|
||||
send_motion_packet(0x04, id);
|
||||
}
|
||||
|
||||
void Client::clear_target() const {
|
||||
void Client::send_clear_target() const {
|
||||
send_motion_packet(0x04, {});
|
||||
}
|
||||
|
||||
void Client::interact_target(const unsigned long long &index) const {
|
||||
void Client::send_interact_target(const unsigned long long &index) const {
|
||||
send_motion_packet(0x11, index);
|
||||
}
|
||||
|
||||
void Client::use_skill(const flyff::SkillID &id, unsigned long long target) const {
|
||||
send_motion_packet(0x5, static_cast<unsigned long long>(id), target);
|
||||
void Client::send_use_skill(const flyff::SkillID &id, unsigned long long unknown) const {
|
||||
send_motion_packet(0x5, static_cast<unsigned long long>(id), unknown);
|
||||
}
|
||||
|
||||
void Client::send_follow_target(const unsigned long long &id) const {
|
||||
send_motion_packet(0x10, id);
|
||||
}
|
||||
|
||||
void Client::send_move_to(const double &x, const double &y, const double &z) const {
|
||||
|
|
@ -188,16 +192,22 @@ find_skill_buff(const flyff::Pointer<flyff::Mover> &mover, const flyff::SkillID
|
|||
|
||||
template<size_t size>
|
||||
std::vector<flyff::SkillID>
|
||||
check_rebuff(const flyff::Pointer<flyff::Mover> &player, const flyff::SkillID (&buffs_to_check)[size]) {
|
||||
check_rebuff(const flyff::Pointer<flyff::Mover>& buffer, const flyff::Pointer<flyff::Mover> &target,
|
||||
const flyff::SkillID (&buffs_to_check)[size]) {
|
||||
const auto &neuz = flyff::Neuz::instance();
|
||||
|
||||
auto result = std::vector<flyff::SkillID>();
|
||||
for (const auto &skill_index: buffs_to_check) {
|
||||
const auto &buff = find_skill_buff(player, skill_index);
|
||||
const auto &buff = find_skill_buff(target, skill_index);
|
||||
const auto &skill_property = flyff::Neuz::get_skill_property(skill_index);
|
||||
const auto player_skill_level = buffer->get_skill_level(skill_index);
|
||||
// Only check for the buff if the buffer actually has the skill.
|
||||
if(player_skill_level <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 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<const flyff::SkillProperty *>(
|
||||
|
|
@ -239,47 +249,52 @@ flyff::Pointer<const flyff::InventoryItem> find_first_equippable_item(const flyf
|
|||
return flyff::Pointer<const flyff::InventoryItem>(highest);
|
||||
}
|
||||
|
||||
|
||||
bool is_running = false;
|
||||
flyff::Vector3 start_position = {0};
|
||||
// The object property id of the monster to grind.
|
||||
int object_property_index = 0;
|
||||
|
||||
flyff::MoverID current_heal_target = 0;
|
||||
|
||||
enum class ScriptType {
|
||||
Off,
|
||||
Attacker,
|
||||
Healer
|
||||
};
|
||||
|
||||
ScriptType script = ScriptType::Off;
|
||||
|
||||
void on_keyup_hook(int event_type, const EmscriptenKeyboardEvent *event, void *user_data) {
|
||||
const auto &client = fugg::Client::instance();
|
||||
|
||||
if (event->keyCode == 220) {
|
||||
const auto &player = client.player;
|
||||
if (event->keyCode == 220 && script == ScriptType::Off) {
|
||||
if (!client.player)
|
||||
return;
|
||||
|
||||
auto items = player->inventory.begin();
|
||||
|
||||
std::cout << "Player has " << player->get_inventory_slots() << " slots" << std::endl;
|
||||
std::cout << "Player has " << player->get_hp_percent() << "% HP" << std::endl;
|
||||
|
||||
for (auto i = 0; i < player->get_inventory_slots(); i++) {
|
||||
|
||||
if (items[i].property && items[i].property->is_food()) {
|
||||
std::cout << client.get_text(items[i].property->name) << ": "
|
||||
<< "Is food? " << (items[i].property->is_food() ? "Yes" : "No") << ", "
|
||||
<< "Can use? " << (player->can_use_item(items[i].property) ? "Yes" : "No")
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
// if (items[i].property &&
|
||||
// items[i].property->is_food() &&
|
||||
// player->can_use_item(items[i].property)) {
|
||||
// std::string str = "Eating ";
|
||||
// str.append(client.get_text(items[i].property->name));
|
||||
// str.append(" because HP is below 75%");
|
||||
//
|
||||
// client.show_message(str);
|
||||
//
|
||||
// client.send_use_item_in_inventory(i);
|
||||
//
|
||||
// break;
|
||||
// }
|
||||
if (client.player->selected_target == 0) {
|
||||
client.show_message("No heal target selected.", {0xFF, 0, 0});
|
||||
return;
|
||||
}
|
||||
|
||||
auto target = client.get_mover(client.player->selected_target);
|
||||
if (!target) {
|
||||
client.show_message("No heal target selected.", {0xFF, 0xFF, 0});
|
||||
return;
|
||||
}
|
||||
|
||||
std::string str = "I'm going to heal ";
|
||||
str.append(client.get_text(target->name));
|
||||
str.append("<Lv. ");
|
||||
str.append(std::to_string(target->get_level()));
|
||||
str.append(">");
|
||||
client.show_message(str);
|
||||
|
||||
current_heal_target = client.player->selected_target;
|
||||
script = ScriptType::Healer;
|
||||
|
||||
client.show_message("Bot started");
|
||||
// std::cout << "Velocity: " << client.player->delta_velocity << std::endl;
|
||||
|
||||
|
||||
// if (!main_hand || main_hand->item_kind3 != flyff::ItemProperty::CheerStick) {
|
||||
// const auto &stick = find_first_equippable_item(flyff::ItemProperty::CheerStick);
|
||||
//
|
||||
|
|
@ -303,9 +318,9 @@ void on_keyup_hook(int event_type, const EmscriptenKeyboardEvent *event, void *u
|
|||
// static_cast<flyff::ObjectProperty*>(test->property)
|
||||
// );
|
||||
|
||||
// std::cout << "BuffSkill "
|
||||
// std::cout << "BuffSkill "
|
||||
// << client.get_text(skill_property->name)
|
||||
// << " ReqLv. " << skill_property->required_level
|
||||
// << " ReqLv. " << skill_property->required_level
|
||||
// << " Lv." << skill_property->level
|
||||
// << " Id: " << reinterpret_cast<void*>(skill_property->id)
|
||||
// << " Remaining: " << (test->get_time_remaining() / 1000)
|
||||
|
|
@ -314,7 +329,7 @@ void on_keyup_hook(int event_type, const EmscriptenKeyboardEvent *event, void *u
|
|||
// }
|
||||
|
||||
//
|
||||
// clear_target();
|
||||
// send_clear_target();
|
||||
// auto items = player->inventory.begin();
|
||||
// auto length = ((uintptr_t)player->inventory.end() - (uintptr_t)player->inventory.begin()) / 0x60;
|
||||
|
||||
|
|
@ -353,14 +368,14 @@ void on_keyup_hook(int event_type, const EmscriptenKeyboardEvent *event, void *u
|
|||
|
||||
// if(stick_index != -1) {
|
||||
// // Use skill Heal
|
||||
// use_skill(0x2c, 10);
|
||||
// send_use_skill(0x2c, 10);
|
||||
// } else {
|
||||
// client.show_message("Could not find a stick to heal myself.", { 0xFF, 0, 0 });
|
||||
// }
|
||||
}
|
||||
|
||||
// BracketLeft
|
||||
if (event->keyCode == 219 && !is_running) {
|
||||
if (event->keyCode == 219 && script == ScriptType::Off) {
|
||||
if (!client.player)
|
||||
return;
|
||||
|
||||
|
|
@ -386,14 +401,14 @@ void on_keyup_hook(int event_type, const EmscriptenKeyboardEvent *event, void *u
|
|||
start_position = {client.player->position.x, client.player->position.y, client.player->position.z};
|
||||
std::cout << "Start botting at " << start_position << std::endl;
|
||||
|
||||
is_running = true;
|
||||
script = ScriptType::Attacker;
|
||||
|
||||
client.show_message("Bot started");
|
||||
}
|
||||
|
||||
if (event->keyCode == 221) {
|
||||
if (is_running) {
|
||||
is_running = false;
|
||||
if (script != ScriptType::Off) {
|
||||
script = ScriptType::Off;
|
||||
|
||||
client.show_message("Bot stopped");
|
||||
} else {
|
||||
|
|
@ -438,12 +453,12 @@ void on_keyup_hook(int event_type, const EmscriptenKeyboardEvent *event, void *u
|
|||
// << "Is this food ? " << (items[i].property->is_food_item() ? "Yes" : "No")
|
||||
// << std::endl;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
flyff::MoverID attack_next_target(flyff::Vector3 const &start_position) {
|
||||
flyff::MoverID find_closest_target() {
|
||||
auto &neuz = flyff::Neuz::instance();
|
||||
auto &client = fugg::Client::instance();
|
||||
|
||||
|
|
@ -485,12 +500,6 @@ flyff::MoverID attack_next_target(flyff::Vector3 const &start_position) {
|
|||
} while (current);
|
||||
|
||||
if (closest) {
|
||||
neuz.player->selected_target = closest->object_id;
|
||||
client.set_target(closest->object_id);
|
||||
|
||||
neuz.player->move_toward_target = closest->object_id;
|
||||
client.interact_target(1);
|
||||
|
||||
return closest->object_id;
|
||||
}
|
||||
|
||||
|
|
@ -539,223 +548,312 @@ flyff::MoverID find_next_item() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void interact(flyff::MoverID id) {
|
||||
const auto &neuz = flyff::Neuz::instance();
|
||||
void interact(flyff::MoverID id, uint32_t action) {
|
||||
const auto &client = fugg::Client::instance();
|
||||
|
||||
if (!neuz.player)
|
||||
if (!client.player)
|
||||
return;
|
||||
|
||||
neuz.player->selected_target = id;
|
||||
client.set_target(id);
|
||||
client.player->selected_target = id;
|
||||
client.send_set_target(id);
|
||||
|
||||
neuz.player->move_toward_target = id;
|
||||
client.interact_target(1);
|
||||
client.player->move_toward_target = id;
|
||||
client.send_interact_target(action);
|
||||
}
|
||||
|
||||
flyff::MoverID current_target = 0;
|
||||
flyff::MoverID current_pickup_item = 0;
|
||||
|
||||
void bot_tick() {
|
||||
void attacker_script() {
|
||||
const auto &neuz = flyff::Neuz::instance();
|
||||
const auto &client = fugg::Client::instance();
|
||||
|
||||
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;
|
||||
if (neuz.player->is_dead()) {
|
||||
neuz.show_message("Player is dead, stopping...", {0xFF, 0x00, 0x00});
|
||||
script = ScriptType::Off;
|
||||
return;
|
||||
}
|
||||
|
||||
// printf("%#010x\n", neuz.player->get_state());
|
||||
const auto &player = neuz.player;
|
||||
|
||||
if (is_running) {
|
||||
if (neuz.player->is_dead()) {
|
||||
neuz.show_message("Player is dead, stopping...", {0xFF, 0x00, 0x00});
|
||||
is_running = false;
|
||||
return;
|
||||
// if is_idle:
|
||||
// if item_target:
|
||||
// pickup_item()
|
||||
// elif attacK_target:
|
||||
// attack_target()
|
||||
|
||||
if (neuz.player->get_hp_percent() < 50) {
|
||||
// neuz.show_message("Fooding because HP is under 75%");W
|
||||
auto items = player->inventory.begin();
|
||||
std::cout << "Player has " << player->get_inventory_slots() << " slots" << std::endl;
|
||||
for (auto i = 0; i < player->get_inventory_slots(); i++) {
|
||||
if (items[i].property &&
|
||||
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);
|
||||
|
||||
client.send_use_item_in_inventory(i);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (neuz.player->get_move_state() == 1 &&
|
||||
!neuz.player->is_attacking()) {
|
||||
|
||||
|
||||
// Check buffs.
|
||||
static constexpr flyff::SkillID buffs_to_check[] = {
|
||||
flyff::SkillID::HeapUp,
|
||||
flyff::SkillID::Haste,
|
||||
flyff::SkillID::Patience,
|
||||
flyff::SkillID::BeefUp,
|
||||
};
|
||||
|
||||
auto item = neuz.get_mover(current_pickup_item);
|
||||
auto monster = neuz.get_mover(current_target);
|
||||
|
||||
if (neuz.player->get_job() == flyff::JobID::Assist) {
|
||||
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, neuz.player, buffs_to_check);
|
||||
if (!buffs.empty() && (!item || item->is_despawned) && (!monster || monster->is_dead())) {
|
||||
const auto skill_index = 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();
|
||||
|
||||
client.send_use_item_in_inventory(stick->index);
|
||||
client.send_use_skill(skill_index);
|
||||
return;
|
||||
} else {
|
||||
neuz.show_message("Unable to find a stick", {0xFF, 0, 0});
|
||||
}
|
||||
} else {
|
||||
buffs.pop_back();
|
||||
client.send_use_skill(skill_index);
|
||||
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) {
|
||||
client.send_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) {
|
||||
client.send_use_item_in_inventory(shield->index);
|
||||
} else {
|
||||
neuz.show_message("Unable to find a shield", {0xFF, 0, 0});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const auto &player = neuz.player;
|
||||
if (item && !item->is_despawned && neuz.player->move_toward_target == 0) {
|
||||
// Pickup
|
||||
interact(item->object_id, 1);
|
||||
} else if (monster && !monster->is_dead() && neuz.player->move_toward_target == 0) {
|
||||
// Attack
|
||||
interact(monster->object_id, 1);
|
||||
// neuz.player->attack_target = monster->object_id;
|
||||
} else if ((!item || item->is_despawned) &&
|
||||
(!monster || monster->is_dead())) {
|
||||
std::cout << "No item, no target. Searching..." << std::endl;
|
||||
|
||||
// if is_idle:
|
||||
// if item_target:
|
||||
// pickup_item()
|
||||
// elif attacK_target:
|
||||
// attack_target()
|
||||
// First check all mobs if they attacked me (aggro ones).
|
||||
for (const auto &id: client.player->enemies) {
|
||||
const auto &mover = client.get_mover(id);
|
||||
|
||||
if (neuz.player->get_hp_percent() < 75) {
|
||||
// neuz.show_message("Fooding because HP is under 75%");W
|
||||
auto items = player->inventory.begin();
|
||||
std::cout << "Player has " << player->get_inventory_slots() << " slots" << std::endl;
|
||||
for (auto i = 0; i < player->get_inventory_slots(); i++) {
|
||||
if (items[i].property &&
|
||||
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%");
|
||||
if (mover) {
|
||||
std::string str = "Attacking ";
|
||||
str.append(mover->name);
|
||||
str.append(" because it is my enemy.");
|
||||
|
||||
current_target = id;
|
||||
interact(id, 1);
|
||||
|
||||
neuz.show_message(str);
|
||||
|
||||
client.send_use_item_in_inventory(i);
|
||||
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
// No item target and no attack target
|
||||
current_pickup_item = find_next_item();
|
||||
item = neuz.get_mover(current_pickup_item);
|
||||
if (item) {
|
||||
auto *prop = reinterpret_cast<const flyff::ItemProperty *>(
|
||||
static_cast<const flyff::ObjectProperty *>(item->property)
|
||||
);
|
||||
|
||||
if (neuz.player->get_move_state() == 1 &&
|
||||
!neuz.player->is_attacking()) {
|
||||
std::string str = "Picking up ";
|
||||
str.append(neuz.get_text(prop->name));
|
||||
|
||||
interact(item->object_id, 1);
|
||||
|
||||
// Check buffs.
|
||||
static constexpr flyff::SkillID buffs_to_check[] = {
|
||||
flyff::SkillID::HeapUp,
|
||||
flyff::SkillID::Haste,
|
||||
flyff::SkillID::Patience,
|
||||
flyff::SkillID::BeefUp,
|
||||
};
|
||||
neuz.show_message(str);
|
||||
return;
|
||||
} else {
|
||||
current_target = find_closest_target();
|
||||
|
||||
auto item = neuz.get_mover(current_pickup_item);
|
||||
auto monster = neuz.get_mover(current_target);
|
||||
monster = neuz.get_mover(current_target);
|
||||
if (monster) {
|
||||
std::string str = "Attacking ";
|
||||
str.append(monster->name);
|
||||
|
||||
if (neuz.player->get_job() == flyff::JobID::Assist) {
|
||||
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 skill_index = 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();
|
||||
|
||||
client.send_use_item_in_inventory(stick->index);
|
||||
client.use_skill(skill_index);
|
||||
return;
|
||||
} else {
|
||||
neuz.show_message("Unable to find a stick", {0xFF, 0, 0});
|
||||
}
|
||||
} else {
|
||||
buffs.pop_back();
|
||||
client.use_skill(skill_index);
|
||||
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) {
|
||||
client.send_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) {
|
||||
client.send_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) {
|
||||
// Attack
|
||||
interact(monster->object_id);
|
||||
// neuz.player->attack_target = monster->object_id;
|
||||
} else if ((!item || item->is_despawned) &&
|
||||
(!monster || monster->is_dead())) {
|
||||
std::cout << "No item, no target. Searching..." << std::endl;
|
||||
|
||||
// First check all mobs if they attacked me (aggro ones).
|
||||
auto current = neuz.movers.first;
|
||||
do {
|
||||
const auto &mover = current->mover;
|
||||
|
||||
if (mover->type == flyff::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) {
|
||||
auto *prop = reinterpret_cast<const flyff::ItemProperty *>(
|
||||
static_cast<const flyff::ObjectProperty *>(item->property)
|
||||
);
|
||||
|
||||
std::string str = "Picking up ";
|
||||
str.append(neuz.get_text(prop->name));
|
||||
|
||||
interact(item->object_id);
|
||||
interact(current_target, 1);
|
||||
|
||||
neuz.show_message(str);
|
||||
} else {
|
||||
current_target = attack_next_target(start_position);
|
||||
|
||||
monster = neuz.get_mover(current_target);
|
||||
if (monster) {
|
||||
std::string str = "Attacking ";
|
||||
str.append(monster->name);
|
||||
|
||||
std::cout << str << std::endl;
|
||||
|
||||
interact(monster->object_id);
|
||||
// neuz.player->attack_target = monster->object_id;
|
||||
|
||||
neuz.show_message(str);
|
||||
} else {
|
||||
neuz.show_message("Unable to find target.");
|
||||
}
|
||||
neuz.show_message("Unable to find target.");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Reset current target is not running.
|
||||
current_target = 0;
|
||||
current_pickup_item = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void healer_script() {
|
||||
const auto &client = fugg::Client::instance();
|
||||
|
||||
if (!client.player)
|
||||
return;
|
||||
|
||||
if (client.player->is_dead()) {
|
||||
client.show_message("Player is dead, stopping...", {0xFF, 0x00, 0x00});
|
||||
script = ScriptType::Off;
|
||||
return;
|
||||
}
|
||||
|
||||
if (client.player->get_move_state() == 1 &&
|
||||
!client.player->is_attacking()) {
|
||||
|
||||
if (client.player->selected_target != current_heal_target) {
|
||||
client.send_set_target(current_heal_target);
|
||||
client.player->selected_target = current_heal_target;
|
||||
|
||||
client.show_message("Selected target");
|
||||
}
|
||||
|
||||
if (client.player->follow_target != current_heal_target) {
|
||||
client.send_follow_target(current_heal_target);
|
||||
client.player->follow_target = current_heal_target;
|
||||
|
||||
client.show_message("Following target");
|
||||
}
|
||||
|
||||
const auto &target = client.get_mover(current_heal_target);
|
||||
if (target) {
|
||||
// If the target has been hit, heal him.
|
||||
if (target->get_hp_percent() < 100) {
|
||||
client.show_message("Healing target");
|
||||
|
||||
client.send_use_skill(flyff::SkillID::Heal);
|
||||
return;
|
||||
}
|
||||
// If I'm hit, heal myself.
|
||||
if(client.player->get_hp_percent() < 75) {
|
||||
client.send_clear_target();
|
||||
client.player->selected_target = 0;
|
||||
|
||||
client.send_use_skill(flyff::SkillID::Heal);
|
||||
return;
|
||||
}
|
||||
// Check for rebuff on the target
|
||||
{
|
||||
// For target, check all buffs.
|
||||
static constexpr flyff::SkillID buffs_to_check[] = {
|
||||
flyff::SkillID::MentalSign,
|
||||
flyff::SkillID::Patience,
|
||||
flyff::SkillID::QuickStep,
|
||||
flyff::SkillID::HeapUp,
|
||||
flyff::SkillID::Haste,
|
||||
flyff::SkillID::BeefUp,
|
||||
flyff::SkillID::Accuracy,
|
||||
flyff::SkillID::CatsReflex,
|
||||
flyff::SkillID::CannonBall
|
||||
};
|
||||
|
||||
auto buffs = check_rebuff(client.player, target, buffs_to_check);
|
||||
if (!buffs.empty()) {
|
||||
auto skill_index = buffs.back();
|
||||
buffs.pop_back();
|
||||
|
||||
const auto& skill = fugg::Client::get_skill_property(skill_index);
|
||||
std::string str = "Buffing target with";
|
||||
str.append(client.get_text(skill->name));
|
||||
client.show_message(str);
|
||||
|
||||
client.send_use_skill(skill_index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Check for rebuff on yourself
|
||||
if(!target->is_in_combat(1500)){
|
||||
// For FS itself, only these selected buffs.
|
||||
static constexpr flyff::SkillID buffs_to_check[] = {
|
||||
flyff::SkillID::MentalSign,
|
||||
flyff::SkillID::QuickStep,
|
||||
flyff::SkillID::Patience,
|
||||
flyff::SkillID::HeapUp,
|
||||
flyff::SkillID::Haste,
|
||||
flyff::SkillID::Prevention
|
||||
};
|
||||
|
||||
auto buffs = check_rebuff(client.player, client.player, buffs_to_check);
|
||||
if (!buffs.empty()) {
|
||||
auto skill_index = buffs.back();
|
||||
buffs.pop_back();
|
||||
|
||||
client.send_clear_target();
|
||||
client.player->selected_target = 0;
|
||||
|
||||
client.send_use_skill(skill_index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
client.show_message("Can't find target!", {0xFF, 0, 0});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void before_main_loop() {
|
||||
bot_tick();
|
||||
switch (script) {
|
||||
case ScriptType::Attacker:
|
||||
attacker_script();
|
||||
break;
|
||||
|
||||
case ScriptType::Healer:
|
||||
healer_script();
|
||||
break;
|
||||
|
||||
default:
|
||||
// Reset current target is not running.
|
||||
current_target = 0;
|
||||
current_pickup_item = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void after_main_loop() {
|
||||
|
|
|
|||
|
|
@ -28,13 +28,15 @@ namespace fugg {
|
|||
void send_motion_packet(const uint32_t &action, unsigned long long param0 = 0, unsigned long long param1 = 0,
|
||||
unsigned long long param2 = 0, unsigned long long param3 = 0) const;
|
||||
|
||||
void set_target(const unsigned long long &id) const;
|
||||
void send_set_target(const unsigned long long &id) const;
|
||||
|
||||
void clear_target() const;
|
||||
void send_clear_target() const;
|
||||
|
||||
void interact_target(const unsigned long long &index) const;
|
||||
|
||||
void use_skill(const flyff::SkillID &id, unsigned long long target = -1) const;
|
||||
void send_interact_target(const unsigned long long &index) const;
|
||||
|
||||
void send_use_skill(const flyff::SkillID &id, unsigned long long unknown = -1) const;
|
||||
void send_follow_target(const unsigned long long &id) const;
|
||||
|
||||
void send_move_to(const double &x, const double &y, const double &z) const;
|
||||
void send_chat_message(const std::string &message) const;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
//
|
||||
// Created by main on 21-10-22.
|
||||
//
|
||||
|
||||
#ifndef FUGG_ACTION_H
|
||||
#define FUGG_ACTION_H
|
||||
|
||||
#include "../Client.h"
|
||||
|
||||
namespace fugg {
|
||||
class Action {
|
||||
|
||||
public:
|
||||
enum class State : unsigned char {
|
||||
Running,
|
||||
Failed,
|
||||
Succeeded
|
||||
};
|
||||
|
||||
virtual State evaluate(Client &client) = 0;
|
||||
};
|
||||
|
||||
class StatefulAction : Action {
|
||||
virtual State start() = 0;
|
||||
virtual State run() = 0;
|
||||
virtual State stop() = 0;
|
||||
};
|
||||
|
||||
|
||||
class ActionAttack : Action {
|
||||
const flyff::MoverID target_id;
|
||||
|
||||
public:
|
||||
explicit ActionAttack(flyff::MoverID id) : target_id(id) { }
|
||||
|
||||
State evaluate(Client &client) override {
|
||||
const auto& target = client.get_mover(target_id);
|
||||
|
||||
if(!target) return State::Failed;
|
||||
|
||||
if(client.player->selected_target != target_id) {
|
||||
client.player->selected_target = target_id;
|
||||
client.send_set_target(target_id);
|
||||
}
|
||||
|
||||
if(client.player->move_toward_target != target_id) {
|
||||
client.player->move_toward_target = target_id;
|
||||
client.send_interact_target(1);
|
||||
}
|
||||
|
||||
return State::Succeeded;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#endif //FUGG_ACTION_H
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
//
|
||||
// Created by main on 25-10-22.
|
||||
//
|
||||
|
||||
#ifndef FUGG_SCRIPT_H
|
||||
#define FUGG_SCRIPT_H
|
||||
|
||||
#include "Action.h"
|
||||
|
||||
namespace fugg {
|
||||
class Script {
|
||||
|
||||
public:
|
||||
virtual Action evaluate(const Client& client) = 0;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif //FUGG_SCRIPT_H
|
||||
Reference in New Issue