Added mana and fatigue point recovery (along with get_mp(), get_fp(), get_max_mp(), get_max_fp())
This commit is contained in:
parent
1c9001f582
commit
af66bfc82f
|
|
@ -84,7 +84,9 @@ namespace flyff {
|
||||||
Necklace = 501,
|
Necklace = 501,
|
||||||
Ring = 502,
|
Ring = 502,
|
||||||
|
|
||||||
|
Refresher = 1400,
|
||||||
|
VitalDrink = 1401,
|
||||||
|
Food = 1402,
|
||||||
Pill = 1404
|
Pill = 1404
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,8 @@ namespace flyff {
|
||||||
DEFINE_MEMBER(0, const flyff::String, model);
|
DEFINE_MEMBER(0, const flyff::String, model);
|
||||||
DEFINE_MEMBER(12, const uint32_t, id);
|
DEFINE_MEMBER(12, const uint32_t, id);
|
||||||
|
|
||||||
DEFINE_MEMBER(60, const uint32_t, heal_hp);
|
DEFINE_MEMBER(60, const uint32_t, recovery);
|
||||||
|
DEFINE_MEMBER(96, const uint32_t, effective_up_to);
|
||||||
|
|
||||||
// Has to be bigger that 0 to be considered for cooldown.
|
// Has to be bigger that 0 to be considered for cooldown.
|
||||||
DEFINE_MEMBER(112, const int32_t, cooldown_time);
|
DEFINE_MEMBER(112, const int32_t, cooldown_time);
|
||||||
|
|
@ -52,6 +53,32 @@ namespace flyff {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_refresher() const {
|
||||||
|
static const uint32_t RECOVERY_SUB_CATEGORY_START = 1400;
|
||||||
|
|
||||||
|
if (item_kind2 == ItemKind2::Recovery) {
|
||||||
|
const uint32_t cd = static_cast<uint32_t>(item_kind3) - RECOVERY_SUB_CATEGORY_START;
|
||||||
|
if (cd < 5) {
|
||||||
|
return RECOVERY_COOLDOWN_INDEX[cd] == COOLDOWN_REFRESHER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_vitaldrink() const {
|
||||||
|
static const uint32_t RECOVERY_SUB_CATEGORY_START = 1400;
|
||||||
|
|
||||||
|
if (item_kind2 == ItemKind2::Recovery) {
|
||||||
|
const uint32_t cd = static_cast<uint32_t>(item_kind3) - RECOVERY_SUB_CATEGORY_START;
|
||||||
|
if (cd < 5) {
|
||||||
|
return RECOVERY_COOLDOWN_INDEX[cd] == COOLDOWN_VITALDRINK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool is_quest() const { return item_kind2 == ItemKind2::Quest; }
|
bool is_quest() const { return item_kind2 == ItemKind2::Quest; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ namespace flyff {
|
||||||
|
|
||||||
DEFINE_MEMBER(144, const u32, get_max_origin_hp);
|
DEFINE_MEMBER(144, const u32, get_max_origin_hp);
|
||||||
DEFINE_MEMBER(148, const u32, get_max_origin_mp);
|
DEFINE_MEMBER(148, const u32, get_max_origin_mp);
|
||||||
|
DEFINE_MEMBER(152, const u32, get_max_origin_fp);
|
||||||
|
|
||||||
const MinimumSize<220> _size;
|
const MinimumSize<220> _size;
|
||||||
};
|
};
|
||||||
|
|
@ -154,6 +155,7 @@ namespace flyff {
|
||||||
DEFINE_MEMBER(880, const uint32_t, locked_inventory_slots);
|
DEFINE_MEMBER(880, const uint32_t, locked_inventory_slots);
|
||||||
|
|
||||||
DEFINE_MEMBER(904, uint32_t, if_not_null_needsattackitem);
|
DEFINE_MEMBER(904, uint32_t, if_not_null_needsattackitem);
|
||||||
|
DEFINE_MEMBER(908, uint32_t, fatiguepoints);
|
||||||
|
|
||||||
DEFINE_MEMBER(920, ParameterValue, adjusted_parameters[MAX_PARAM]);
|
DEFINE_MEMBER(920, ParameterValue, adjusted_parameters[MAX_PARAM]);
|
||||||
DEFINE_MEMBER(1248, ParameterValue, changed_parameters[MAX_PARAM]);
|
DEFINE_MEMBER(1248, ParameterValue, changed_parameters[MAX_PARAM]);
|
||||||
|
|
@ -183,6 +185,7 @@ namespace flyff {
|
||||||
DEFINE_MEMBER(1820, uint32_t, server_tick);
|
DEFINE_MEMBER(1820, uint32_t, server_tick);
|
||||||
|
|
||||||
DEFINE_MEMBER(1840, int, hitpoints);
|
DEFINE_MEMBER(1840, int, hitpoints);
|
||||||
|
DEFINE_MEMBER(1844, int, manapoints);
|
||||||
|
|
||||||
DEFINE_MEMBER(1848, int, is_grounded);
|
DEFINE_MEMBER(1848, int, is_grounded);
|
||||||
|
|
||||||
|
|
@ -247,9 +250,6 @@ namespace flyff {
|
||||||
|
|
||||||
ParameterValue get_change_param(ParamID index) const;
|
ParameterValue get_change_param(ParamID index) const;
|
||||||
|
|
||||||
uint32_t get_hp() const {
|
|
||||||
return raw::get_hitpoint(kMemory.to_inside(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
flyff::Pointer<flyff::ItemProperty> get_equipped_item(const flyff::Part &part) const {
|
flyff::Pointer<flyff::ItemProperty> get_equipped_item(const flyff::Part &part) const {
|
||||||
using Fn = FunctionPointer<u32, u32, u32>;
|
using Fn = FunctionPointer<u32, u32, u32>;
|
||||||
|
|
@ -273,6 +273,18 @@ namespace flyff {
|
||||||
return src_speed <= 0 ? 0 : src_speed;
|
return src_speed <= 0 ? 0 : src_speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t get_hp() const {
|
||||||
|
return hitpoints ^ adj_param;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t get_mp() const {
|
||||||
|
return manapoints ^ adj_param;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t get_fp() const {
|
||||||
|
return fatiguepoints;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t get_max_hp() const {
|
uint32_t get_max_hp() const {
|
||||||
float factor = 1.0f;
|
float factor = 1.0f;
|
||||||
auto result = get_param(ParamID::MaxHitPoint, get_max_origin_hp());
|
auto result = get_param(ParamID::MaxHitPoint, get_max_origin_hp());
|
||||||
|
|
@ -284,6 +296,28 @@ namespace flyff {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t get_max_mp() const {
|
||||||
|
float factor = 1.0f;
|
||||||
|
auto result = get_param(ParamID::MaxManaPoint, get_max_origin_mp());
|
||||||
|
auto percent = get_param(ParamID::MaxManaPointScaling, 0);
|
||||||
|
|
||||||
|
factor += static_cast<float>(percent) / 100.f;
|
||||||
|
result = static_cast<float>(result) * factor;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t get_max_fp() const {
|
||||||
|
float factor = 1.0f;
|
||||||
|
auto result = get_param(ParamID::MaxFatiguePoint, get_max_origin_fp());
|
||||||
|
auto percent = get_param(ParamID::MaxFatiguePointScaling, 0);
|
||||||
|
|
||||||
|
factor += static_cast<float>(percent) / 100.f;
|
||||||
|
result = static_cast<float>(result) * factor;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t get_hp_percent(int percent = 100) const {
|
uint32_t get_hp_percent(int percent = 100) const {
|
||||||
auto max = get_max_hp();
|
auto max = get_max_hp();
|
||||||
if (max == 0) return 0;
|
if (max == 0) return 0;
|
||||||
|
|
@ -291,6 +325,20 @@ namespace flyff {
|
||||||
return get_hp() * percent / max;
|
return get_hp() * percent / max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t get_mp_percent(int percent = 100) const {
|
||||||
|
auto max = get_max_mp();
|
||||||
|
if (max == 0) return 0;
|
||||||
|
|
||||||
|
return get_mp() * percent / max;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t get_fp_percent(int percent = 100) const {
|
||||||
|
auto max = get_max_fp();
|
||||||
|
if (max == 0) return 0;
|
||||||
|
|
||||||
|
return get_fp() * percent / max;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t get_max_origin_hp() const {
|
uint32_t get_max_origin_hp() const {
|
||||||
using Fn = FunctionPointer<u32, u32, u32, u32>;
|
using Fn = FunctionPointer<u32, u32, u32, u32>;
|
||||||
const auto &fn = fugg::function_ref<Fn>(vtable->get_max_origin_hp);
|
const auto &fn = fugg::function_ref<Fn>(vtable->get_max_origin_hp);
|
||||||
|
|
@ -298,6 +346,20 @@ namespace flyff {
|
||||||
return fn(kMemory.to_inside(this), 0, 0);
|
return fn(kMemory.to_inside(this), 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t get_max_origin_mp() const {
|
||||||
|
using Fn = FunctionPointer<u32, u32, u32, u32>;
|
||||||
|
const auto &fn = fugg::function_ref<Fn>(vtable->get_max_origin_mp);
|
||||||
|
|
||||||
|
return fn(kMemory.to_inside(this), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t get_max_origin_fp() const {
|
||||||
|
using Fn = FunctionPointer<u32, u32, u32, u32>;
|
||||||
|
const auto &fn = fugg::function_ref<Fn>(vtable->get_max_origin_fp);
|
||||||
|
|
||||||
|
return fn(kMemory.to_inside(this), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
float get_attack_range(const AttackRange& range) const {
|
float get_attack_range(const AttackRange& range) const {
|
||||||
static const float attack_ranges[] = {
|
static const float attack_ranges[] = {
|
||||||
2, 3, 4, 10, 15, 6, 18
|
2, 3, 4, 10, 15, 6, 18
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,15 @@ namespace flyff {
|
||||||
AdditionalDamage = 35,
|
AdditionalDamage = 35,
|
||||||
// DST_HP_MAX
|
// DST_HP_MAX
|
||||||
MaxHitPoint = 44,
|
MaxHitPoint = 44,
|
||||||
|
// DST_MP_MAX
|
||||||
|
MaxManaPoint,
|
||||||
|
// DST_FP_MAX
|
||||||
|
MaxFatiguePoint,
|
||||||
|
|
||||||
// DST_HP_MAX_RATE
|
// DST_HP_MAX_RATE
|
||||||
MaxHitPointScaling = 53,
|
MaxHitPointScaling = 53,
|
||||||
|
MaxManaPointScaling,
|
||||||
|
MaxFatiguePointScaling,
|
||||||
|
|
||||||
// Max = 82,
|
// Max = 82,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,13 @@
|
||||||
|
|
||||||
namespace flyff {
|
namespace flyff {
|
||||||
enum class SkillID : uint32_t {
|
enum class SkillID : uint32_t {
|
||||||
// Assist skills
|
/* Mercenary */
|
||||||
|
SwordMastery = 7,
|
||||||
|
Protect = 9,
|
||||||
|
BlazingSword = 108,
|
||||||
|
EmpowerWeapon = 111,
|
||||||
|
HeartOfFury = 404,
|
||||||
|
/* Assist */
|
||||||
Haste = 20,
|
Haste = 20,
|
||||||
Heal = 44,
|
Heal = 44,
|
||||||
Resurrection = 45,
|
Resurrection = 45,
|
||||||
|
|
@ -27,7 +32,7 @@ namespace flyff {
|
||||||
|
|
||||||
|
|
||||||
static std::ostream &operator<<(std::ostream &os, const SkillID &type) {
|
static std::ostream &operator<<(std::ostream &os, const SkillID &type) {
|
||||||
os << static_cast<uint32_t>(type);
|
os << "SkillID(" << static_cast<uint32_t>(type) << ")";
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
}; // namespace flyff
|
}; // namespace flyff
|
||||||
|
|
@ -472,6 +472,15 @@ void on_keyup_hook(int event_type, const EmscriptenKeyboardEvent *event, void *u
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::cout << "Player has the following " << client.player->skills->size() << " skills" << std::endl;
|
||||||
|
for(const auto& skill : client.player->skills) {
|
||||||
|
const auto& property = fugg::Client::get_skill_property(skill.id);
|
||||||
|
if(property) {
|
||||||
|
std::cout << client.get_text(property->name) << " ";
|
||||||
|
}
|
||||||
|
std::cout << "(" << skill.id << ") at level " << skill.level << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -642,7 +651,7 @@ void attacker_script() {
|
||||||
auto hp = client.player->get_hp();
|
auto hp = client.player->get_hp();
|
||||||
auto max_hp = client.player->get_max_hp();
|
auto max_hp = client.player->get_max_hp();
|
||||||
// How much HP is left over after healing with this item.
|
// How much HP is left over after healing with this item.
|
||||||
int32_t difference = max_hp - (hp + item_property->heal_hp);
|
int32_t difference = max_hp - (hp + item_property->recovery);
|
||||||
|
|
||||||
if (difference >= 0 && std::abs(difference) < std::abs(smallest_difference)) {
|
if (difference >= 0 && std::abs(difference) < std::abs(smallest_difference)) {
|
||||||
food_item = flyff::Pointer<flyff::InventoryItem>(&items[i]);
|
food_item = flyff::Pointer<flyff::InventoryItem>(&items[i]);
|
||||||
|
|
@ -673,7 +682,7 @@ void attacker_script() {
|
||||||
auto hp = client.player->get_hp();
|
auto hp = client.player->get_hp();
|
||||||
auto max_hp = client.player->get_max_hp();
|
auto max_hp = client.player->get_max_hp();
|
||||||
// How much HP is left over after healing with this item.
|
// How much HP is left over after healing with this item.
|
||||||
int32_t difference = max_hp - (hp + item_property->heal_hp);
|
int32_t difference = max_hp - (hp + item_property->recovery);
|
||||||
|
|
||||||
if (difference >= 0 && std::abs(difference) < std::abs(smallest_difference)) {
|
if (difference >= 0 && std::abs(difference) < std::abs(smallest_difference)) {
|
||||||
pill_item = flyff::Pointer<flyff::InventoryItem>(&items[i]);
|
pill_item = flyff::Pointer<flyff::InventoryItem>(&items[i]);
|
||||||
|
|
@ -688,12 +697,76 @@ void attacker_script() {
|
||||||
str.append(neuz.get_text(pill_item->property->name));
|
str.append(neuz.get_text(pill_item->property->name));
|
||||||
str.append(" because food item was not ready.");
|
str.append(" because food item was not ready.");
|
||||||
|
|
||||||
neuz.show_message(str);
|
neuz.show_message(str, {0x7F, 0, 0});
|
||||||
|
|
||||||
client.send_use_item_in_inventory(pill_item->index);
|
client.send_use_item_in_inventory(pill_item->index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (neuz.player->get_mp_percent() != 100) {
|
||||||
|
auto mana_item = flyff::Pointer<flyff::InventoryItem>(nullptr);
|
||||||
|
auto items = player->inventory.begin();
|
||||||
|
int32_t smallest_difference = std::numeric_limits<int32_t>::max();
|
||||||
|
for (auto i = 0; i < player->get_inventory_slots(); i++) {
|
||||||
|
const auto &item_property = items[i].property;
|
||||||
|
if (item_property &&
|
||||||
|
player->can_use_item(item_property) &&
|
||||||
|
item_property->is_refresher()) {
|
||||||
|
auto mp = client.player->get_mp();
|
||||||
|
auto max_mp = client.player->get_max_mp();
|
||||||
|
// How much HP is left over after healing with this item.
|
||||||
|
int32_t difference = max_mp - (mp + item_property->recovery);
|
||||||
|
|
||||||
|
if (difference >= 0 && std::abs(difference) < std::abs(smallest_difference)) {
|
||||||
|
mana_item = flyff::Pointer<flyff::InventoryItem>(&items[i]);
|
||||||
|
smallest_difference = difference;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mana_item) {
|
||||||
|
std::string str = "Using ";
|
||||||
|
str.append(neuz.get_text(mana_item->property->name));
|
||||||
|
|
||||||
|
neuz.show_message(str, {0, 0, 0x7F});
|
||||||
|
|
||||||
|
client.send_use_item_in_inventory(mana_item->index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Player has " << neuz.player->get_mp() << " / " << neuz.player->get_max_mp() << " MP" << std::endl;
|
||||||
|
std::cout << "Player has " << neuz.player->get_fp() << " / " << neuz.player->get_max_fp() << " FP" << std::endl;
|
||||||
|
|
||||||
|
if (neuz.player->get_fp_percent() != 100) {
|
||||||
|
auto fatigue_item = flyff::Pointer<flyff::InventoryItem>(nullptr);
|
||||||
|
auto items = player->inventory.begin();
|
||||||
|
int32_t smallest_difference = std::numeric_limits<int32_t>::max();
|
||||||
|
for (auto i = 0; i < player->get_inventory_slots(); i++) {
|
||||||
|
const auto &item_property = items[i].property;
|
||||||
|
if (item_property &&
|
||||||
|
player->can_use_item(item_property) &&
|
||||||
|
item_property->is_vitaldrink()) {
|
||||||
|
auto fp = client.player->get_fp();
|
||||||
|
auto max_fp = client.player->get_max_fp();
|
||||||
|
// How much HP is left over after healing with this item.
|
||||||
|
int32_t difference = max_fp - (fp + item_property->recovery);
|
||||||
|
|
||||||
|
if (difference >= 0 && std::abs(difference) < std::abs(smallest_difference)) {
|
||||||
|
fatigue_item = flyff::Pointer<flyff::InventoryItem>(&items[i]);
|
||||||
|
smallest_difference = difference;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fatigue_item) {
|
||||||
|
std::string str = "Drinking ";
|
||||||
|
str.append(neuz.get_text(fatigue_item->property->name));
|
||||||
|
|
||||||
|
neuz.show_message(str, {0, 0x7F, 0});
|
||||||
|
|
||||||
|
client.send_use_item_in_inventory(fatigue_item->index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Check if my current target is being attacked by another player.
|
// Check if my current target is being attacked by another player.
|
||||||
{
|
{
|
||||||
|
|
@ -701,7 +774,9 @@ void attacker_script() {
|
||||||
if (monster && !monster->enemies->empty()) {
|
if (monster && !monster->enemies->empty()) {
|
||||||
auto is_player_monster_enemy =
|
auto is_player_monster_enemy =
|
||||||
std::find_if(monster->enemies.begin(), monster->enemies.end(),
|
std::find_if(monster->enemies.begin(), monster->enemies.end(),
|
||||||
[&client](const flyff::Mover::HitInfo &x) { return x.object_id == client.player->object_id; }) !=
|
[&client](const flyff::Mover::HitInfo &x) {
|
||||||
|
return x.object_id == client.player->object_id;
|
||||||
|
}) !=
|
||||||
monster->enemies.end();
|
monster->enemies.end();
|
||||||
// If the player is not in the list of enemies, we can not attack the monster.
|
// If the player is not in the list of enemies, we can not attack the monster.
|
||||||
if (!is_player_monster_enemy) {
|
if (!is_player_monster_enemy) {
|
||||||
|
|
@ -788,7 +863,16 @@ void attacker_script() {
|
||||||
client.send_use_skill(flyff::SkillID::Asmodeus);
|
client.send_use_skill(flyff::SkillID::Asmodeus);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// }
|
} else if(neuz.player->get_job() == flyff::JobID::Knight) {
|
||||||
|
const auto &off_hand = player->get_equipped_item(flyff::Part::Shield);
|
||||||
|
|
||||||
|
if (off_hand && off_hand->item_kind3 == flyff::ItemKind3::Shield) {
|
||||||
|
// Only check for the buff if player is wearing a shield.
|
||||||
|
if (!check_rebuff(neuz.player, neuz.player, {flyff::SkillID::HeartOfFury}).empty()) {
|
||||||
|
client.send_use_skill(flyff::SkillID::HeartOfFury);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item && !item->is_despawned && neuz.player->move_toward_target == 0) {
|
if (item && !item->is_despawned && neuz.player->move_toward_target == 0) {
|
||||||
|
|
|
||||||
Reference in New Issue