Skip to content

Commit

Permalink
feat: gain animus mastery experience and exp message update
Browse files Browse the repository at this point in the history
  • Loading branch information
phacUFPE committed Dec 7, 2024
1 parent 02fff0a commit 71e5a78
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 19 deletions.
6 changes: 5 additions & 1 deletion data-otservbr-global/migrations/47.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
function onUpdateDatabase()
return false -- true = There are others migrations file | false = this is the last migration file
logger.info("Updating database to version 48 (feat: animus mastery (soulpit))")

db.query("ALTER TABLE `players` ADD `animus_mastery` mediumblob NOT NULL;")

return true
end
3 changes: 3 additions & 0 deletions data-otservbr-global/migrations/48.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function onUpdateDatabase()
return false -- true = There are others migrations file | false = this is the last migration file
end
47 changes: 34 additions & 13 deletions src/creatures/players/animus_mastery/animus_mastery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,36 +12,57 @@
#include "config/configmanager.hpp"

AnimusMastery::AnimusMastery(Player &player) :
m_player(player),
maxMonsterXpMultiplier(g_configManager().getFloat(ANIMUS_MASTERY_MAX_MONSTER_XP_MULTIPLIER)),
monsterXpMultiplier(g_configManager().getFloat(ANIMUS_MASTERY_MONSTER_XP_MULTIPLIER)),
monstersXpMultiplier(g_configManager().getFloat(ANIMUS_MASTERY_MONSTERS_XP_MULTIPLIER)),
monstersAmountToMultiply(g_configManager().getFloat(ANIMUS_MASTERY_MONSTERS_TO_INCREASE_XP_MULTIPLIER)) { }
m_player(player) {
maxMonsterXpMultiplier = g_configManager().getFloat(ANIMUS_MASTERY_MAX_MONSTER_XP_MULTIPLIER);
monsterXpMultiplier = g_configManager().getFloat(ANIMUS_MASTERY_MONSTER_XP_MULTIPLIER);
monstersXpMultiplier = g_configManager().getFloat(ANIMUS_MASTERY_MONSTERS_XP_MULTIPLIER);
monstersAmountToMultiply = std::clamp<uint16_t>(g_configManager().getNumber(ANIMUS_MASTERY_MONSTERS_TO_INCREASE_XP_MULTIPLIER), 1, std::numeric_limits<uint16_t>::max());
}

void AnimusMastery::add(std::string_view addMonsterType) {
void AnimusMastery::add(const std::string &addMonsterType) {
if (!has(addMonsterType)) {
animusMasteries.emplace_back(addMonsterType);
const std::string &lowerMonsterName = asLowerCaseString(addMonsterType);
animusMasteries.emplace_back(lowerMonsterName);
}
}

void AnimusMastery::remove(std::string_view removeMonsterType) {
std::erase_if(animusMasteries, [removeMonsterType](const std::string &monsterType) {
return monsterType == removeMonsterType;
void AnimusMastery::remove(const std::string &removeMonsterType) {
const std::string &lowerMonsterName = asLowerCaseString(removeMonsterType);
std::erase_if(animusMasteries, [lowerMonsterName](const std::string &monsterType) {
return asLowerCaseString(monsterType) == lowerMonsterName;
});
}

bool AnimusMastery::has(std::string_view searchMonsterType) const {
auto it = std::ranges::find(animusMasteries, searchMonsterType);
bool AnimusMastery::has(const std::string &searchMonsterType) const {
const std::string &lowerMonsterName = asLowerCaseString(searchMonsterType);
auto it = std::ranges::find(animusMasteries, lowerMonsterName);

return it != animusMasteries.end();
}

float AnimusMastery::getExperienceMultiplier() const {
uint16_t monsterAmountMultiplier = animusMasteries.size() / monstersAmountToMultiply;

return std::min(maxMonsterXpMultiplier, 1 + (monsterAmountMultiplier * monstersXpMultiplier));
return std::min(maxMonsterXpMultiplier, 1 + (monsterXpMultiplier + (monsterAmountMultiplier * monstersXpMultiplier)) / 100);
}

uint16_t AnimusMastery::getPoints() const {
return animusMasteries.size();
}

const std::vector<std::string> &AnimusMastery::getAnimusMasteries() const {
return animusMasteries;
}

void AnimusMastery::serialize(PropWriteStream &propWriteStream) const {
std::ranges::for_each(animusMasteries, [&propWriteStream](const std::string &monsterName) {
propWriteStream.writeString(monsterName);
});
}

bool AnimusMastery::unserialize(PropStream &propStream) {
std::string monsterName;
while (propStream.readString(monsterName)) {
animusMasteries.emplace_back(monsterName);
}
}
13 changes: 10 additions & 3 deletions src/creatures/players/animus_mastery/animus_mastery.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,27 @@
#pragma once

class Player;
class PropStream;
class PropWriteStream;

class AnimusMastery {
public:
explicit AnimusMastery(Player &player);

void add(std::string_view addMonsterType);
void remove(std::string_view removeMonsterType);
void add(const std::string &addMonsterType);
void remove(const std::string &removeMonsterType);

bool has(std::string_view searchMonsterType) const;
bool has(const std::string &searchMonsterType) const;

float getExperienceMultiplier() const;

uint16_t getPoints() const;

const std::vector<std::string> &getAnimusMasteries() const;

void serialize(PropWriteStream &propWriteStream) const;
bool unserialize(PropStream &propStream);

private:
Player &m_player;

Expand Down
12 changes: 12 additions & 0 deletions src/creatures/players/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3078,6 +3078,14 @@ void Player::addExperience(const std::shared_ptr<Creature> &target, uint64_t exp
exp += (exp * (1.75 * getHazardSystemPoints() * g_configManager().getFloat(HAZARD_EXP_BONUS_MULTIPLIER))) / 100.;
}

const bool handleAnimusMastery = monster && animusMastery()->has(monster->getMonsterType()->name);
float animusMasteryMultiplier = 0;

if (handleAnimusMastery) {
animusMasteryMultiplier = animusMastery()->getExperienceMultiplier();
exp *= animusMasteryMultiplier;
}

experience += exp;

if (sendText) {
Expand All @@ -3089,6 +3097,10 @@ void Player::addExperience(const std::shared_ptr<Creature> &target, uint64_t exp
}
}

if (handleAnimusMastery) {
expString = fmt::format("{} (animus mastery bonus {:.1f}%)", expString, (animusMasteryMultiplier - 1) * 100);
}

TextMessage message(MESSAGE_EXPERIENCE, "You gained " + expString + (handleHazardExperience ? " (Hazard)" : ""));
message.position = position;
message.primary.value = exp;
Expand Down
15 changes: 15 additions & 0 deletions src/io/functions/iologindata_load_player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "creatures/combat/condition.hpp"
#include "database/database.hpp"
#include "creatures/monsters/monsters.hpp"
#include "creatures/players/animus_mastery/animus_mastery.hpp"
#include "creatures/players/achievement/player_achievement.hpp"
#include "creatures/players/cyclopedia/player_badge.hpp"
#include "creatures/players/cyclopedia/player_cyclopedia.hpp"
Expand Down Expand Up @@ -275,6 +276,20 @@ void IOLoginDataLoad::loadPlayerConditions(const std::shared_ptr<Player> &player
}
}

void IOLoginDataLoad::loadPlayerAnimusMastery(const std::shared_ptr<Player> &player, const DBResult_ptr &result) {
if (!result || !player) {
g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__);
return;
}

unsigned long attrSize;
const char* attr = result->getStream("animus_mastery", attrSize);
PropStream propStream;
propStream.init(attr, attrSize);

player->animusMastery()->unserialize(propStream);
}

void IOLoginDataLoad::loadPlayerDefaultOutfit(const std::shared_ptr<Player> &player, const DBResult_ptr &result) {
if (!result || !player) {
g_logger().warn("[{}] - Player or Result nullptr", __FUNCTION__);
Expand Down
1 change: 1 addition & 0 deletions src/io/functions/iologindata_load_player.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class IOLoginDataLoad : public IOLoginData {
static void loadPlayerExperience(const std::shared_ptr<Player> &player, const DBResult_ptr &result);
static void loadPlayerBlessings(const std::shared_ptr<Player> &player, const DBResult_ptr &result);
static void loadPlayerConditions(const std::shared_ptr<Player> &player, const DBResult_ptr &result);
static void loadPlayerAnimusMastery(const std::shared_ptr<Player> &player, const DBResult_ptr &result);
static void loadPlayerDefaultOutfit(const std::shared_ptr<Player> &player, const DBResult_ptr &result);
static void loadPlayerSkullSystem(const std::shared_ptr<Player> &player, const DBResult_ptr &result);
static void loadPlayerSkill(const std::shared_ptr<Player> &player, const DBResult_ptr &result);
Expand Down
9 changes: 9 additions & 0 deletions src/io/functions/iologindata_save_player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "io/functions/iologindata_save_player.hpp"

#include "config/configmanager.hpp"
#include "creatures/players/animus_mastery/animus_mastery.hpp"
#include "creatures/combat/condition.hpp"
#include "creatures/monsters/monsters.hpp"
#include "game/game.hpp"
Expand Down Expand Up @@ -246,6 +247,14 @@ bool IOLoginDataSave::savePlayerFirst(const std::shared_ptr<Player> &player) {

query << "`conditions` = " << db.escapeBlob(attributes, static_cast<uint32_t>(attributesSize)) << ",";

// serialize animus mastery
PropWriteStream propAnimusMasteryStream;
player->animusMastery()->serialize(propAnimusMasteryStream);
size_t animusMasterySize;
const char* animusMastery = propAnimusMasteryStream.getStream(animusMasterySize);

query << "`animus_mastery` = " << db.escapeBlob(animusMastery, static_cast<uint32_t>(animusMasterySize)) << ",";

if (g_game().getWorldType() != WORLD_TYPE_PVP_ENFORCED) {
int64_t skullTime = 0;

Expand Down
3 changes: 3 additions & 0 deletions src/io/iologindata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ bool IOLoginData::loadPlayer(const std::shared_ptr<Player> &player, const DBResu
// load conditions
IOLoginDataLoad::loadPlayerConditions(player, result);

// load animus mastery
IOLoginDataLoad::loadPlayerAnimusMastery(player, result);

// load default outfit
IOLoginDataLoad::loadPlayerDefaultOutfit(player, result);

Expand Down
5 changes: 3 additions & 2 deletions src/server/network/protocol/protocolgame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "creatures/monsters/monster.hpp"
#include "creatures/monsters/monsters.hpp"
#include "creatures/npcs/npc.hpp"
#include "creatures/players/animus_mastery/animus_mastery.hpp"
#include "creatures/players/achievement/player_achievement.hpp"
#include "creatures/players/cyclopedia/player_badge.hpp"
#include "creatures/players/cyclopedia/player_cyclopedia.hpp"
Expand Down Expand Up @@ -2379,8 +2380,8 @@ void ProtocolGame::parseBestiarysendMonsterData(NetworkMessage &msg) {

newmsg.addByte(currentLevel);

newmsg.add<uint16_t>(0); // Animus Mastery Bonus
newmsg.add<uint16_t>(0); // Animus Mastery Points
newmsg.add<uint16_t>(static_cast<uint16_t>((player->animusMastery()->getExperienceMultiplier() - 1) * 1000)); // Animus Mastery Bonus
newmsg.add<uint16_t>(player->animusMastery()->getPoints()); // Animus Mastery Points

newmsg.add<uint32_t>(killCounter);

Expand Down

0 comments on commit 71e5a78

Please sign in to comment.